Browse Source

useSize hook for Accordion on small screens

master
Dejvino 11 months ago
parent
commit
c881021532
4 changed files with 106 additions and 26 deletions
  1. +72
    -24
      src/app/components/JobHistory.tsx
  2. +2
    -1
      src/app/globals.css
  3. +30
    -0
      src/app/hooks/Size.tsx
  4. +2
    -1
      src/app/page.tsx

+ 72
- 24
src/app/components/JobHistory.tsx View File

@@ -5,42 +5,90 @@ import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row';
import JobCard from './JobCard';
import { partition } from '../utils';
import { Jobs } from '@/PersonalDataTypes';
import { Job, Jobs } from '@/PersonalDataTypes';
import useSize from '../hooks/Size';
import { Accordion } from 'react-bootstrap';

export type Props = {
type JobListProps = {
jobs: Jobs,
heading: string,
entriesPerRow?: number,
currentHeading?: string,
}

export type Props = {
heading: string,
} & JobListProps

const defaultProps = {
entriesPerRow: 2,
currentHeading: 'Currently',
}

function FullList(props: JobListProps) {
const {jobs} = props
const config = {...defaultProps, ...props}
return (
<Container>
{jobs.current && (
<Row>
<Col>
<JobCard heading={config.currentHeading} {...jobs.current} />
</Col>
</Row>
)}
{partition(jobs.previous, config.entriesPerRow).map((jobs, index) => (
<Row key={index}>
{(jobs.map((job, subindex) => (
<Col key={index + '_' + subindex}>
<JobCard {...job} />
</Col>
)))}
</Row>
))}
</Container>
)
}

function SmallList(props: JobListProps) {
const {jobs} = props
const config = {...defaultProps, ...props}
function jobTitle(job: Job) {
return `${job.position} at ${job.company}, ${job.timerange}`
}
return (
<Accordion defaultActiveKey={jobs.current ? 'current' : 'previous-0'} alwaysOpen>
{jobs.current && (
<Accordion.Item eventKey="current">
<Accordion.Header>{config.currentHeading}:<br />{jobTitle(jobs.current)} </Accordion.Header>
<Accordion.Body>
{jobs.current.position}
</Accordion.Body>
</Accordion.Item>
)}
{jobs.previous?.map((job, index) => (
<Accordion.Item eventKey={`previous-${index}`} key={index}>
<Accordion.Header>{jobTitle(job)}</Accordion.Header>
<Accordion.Body>
{job.description}
</Accordion.Body>
</Accordion.Item>
))}
</Accordion>
)
}

export default function JobHistory(props: Props) {
const jobs = props.jobs
const config = {...defaultProps, ...props}
return (
const {SizeWrapper, size} = useSize()
const jobs = props.jobs

const jobsList = size.width < 600 ? <SmallList {...props} /> : <FullList {...props} />

return (
<Container>
<h2>{config.heading}</h2>
{jobs.current && (
<Row>
<Col>
<JobCard heading={config.currentHeading} {...jobs.current} />
</Col>
</Row>
)}
{partition(jobs.previous, config.entriesPerRow).map((jobs, index) => (
<Row key={index}>
{(jobs.map((job, subindex) => (
<Col key={index + '_' + subindex}>
<JobCard {...job} />
</Col>
)))}
</Row>
))}
<h2>{props.heading}</h2>
<SizeWrapper>
{jobsList}
</SizeWrapper>
</Container>
)
)
}

+ 2
- 1
src/app/globals.css View File

@@ -17,7 +17,8 @@ body {
.tiny {
font-size: 75%;
}
h2, h3, h4 {

.container > h2, h3, h4 {
margin-top: 1em;
}



+ 30
- 0
src/app/hooks/Size.tsx View File

@@ -0,0 +1,30 @@
import React, { ForwardedRef, ReactNode, forwardRef, useEffect, useLayoutEffect, useRef, useState } from "react";

export default function useSize() {
const areaRef = useRef<HTMLDivElement>(null)
const [size, setSize] = useState({ width: 0, height: 0 })
function SizeWrapper(props: {children: ReactNode }) {
return (
<div ref={areaRef}>{props.children}</div>
)
}
useEffect(() => {
function updateSize() {
if (areaRef.current) {
setSize({
width: areaRef.current.offsetWidth,
height: areaRef.current.offsetHeight
})
}
}
updateSize()
addEventListener("resize", updateSize);
return () => {
removeEventListener("resize", updateSize)
};
}, [areaRef, setSize])

return {SizeWrapper, size}
}

+ 2
- 1
src/app/page.tsx View File

@@ -1,5 +1,5 @@
'use client'
import React from 'react';
import React, { ForwardedRef, ReactNode, RefObject, forwardRef } from 'react';
import Container from 'react-bootstrap/Container';
import AboutBrief from './components/AboutBrief';
import Skills from './components/Skills';
@@ -9,6 +9,7 @@ import Education from './components/Education';
import { Col, Row } from 'react-bootstrap';
import Footer from './components/Footer';
import Photo from './components/Photo';
import useSize from './hooks/Size';

export default function Home() {
return (


Loading…
Cancel
Save