Code review fixes
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Jared He 2022-08-31 22:34:46 -04:00
parent 3de0f67ccb
commit 4f6f3265fd
3 changed files with 77 additions and 49 deletions

View File

@ -1,15 +1,17 @@
.wrapper {
position: relative;
height: 100%;
}
.line {
position: absolute;
width: calc(5rem / 16);
height: 100%;
border-radius: calc(10rem / 16);
background-color: var(--secondary-accent);
z-index: -1;
}
.timelineSections {
position: absolute;
width: 100%;
height: 100%;
display: flex;
@ -20,7 +22,7 @@
.timelineSection {
width: 100%;
height: inherit;
height: 100%;
display: flex;
flex-direction: row;
justify-content: center;
@ -35,15 +37,7 @@
word-wrap: break-word;
}
.timeHover {
color: var(--secondary-accent-light);
}
.circle {
margin-left: calc(2rem / 16);
width: calc(30rem / 16);
height: calc(30rem / 16);
border-radius: calc(30rem / 16);
background-color: var(--secondary-accent);
box-shadow: calc(0rem / 16) calc(0rem / 16) calc(30rem / 16) var(--secondary-accent);
display: flex;
@ -52,10 +46,8 @@
}
.innerCircle {
width: calc(15rem / 16);
height: calc(15rem / 16);
border-radius: calc(15rem / 16);
background-color: var(--label);
display: none;
}
.text {
@ -66,12 +58,21 @@
font-size: calc(20rem / 16);
font-weight: 700;
color: var(--label);
border: calc(2rem / 16) solid var(--card-background);
background-color: var(--card-background);
word-wrap: break-word;
box-sizing: border-box;
}
.textHover {
.timelineSection:hover .time {
color: var(--secondary-accent-light);
}
.timelineSection:hover .innerCircle {
display: inline;
}
.timelineSection:hover .text {
border: calc(2rem / 16) solid var(--secondary-accent-light);
box-shadow: calc(0rem / 16) calc(0rem / 16) calc(20rem / 16) var(--secondary-accent);
}

View File

@ -11,50 +11,78 @@ interface TimelineProps {
data: TimelineData[];
/** Width of the entire timeline, in pixels. */
width: number;
/** Height of the entire timeline, in pixels. */
height: number;
/** Whether the time is transformed to uppercase */
/** Whether the time is transformed to uppercase. */
isTimeUppercase?: boolean;
/** Width of the middle timeline line, in pixels */
lineWidth?: number;
/** Width of the outer circles on the timeline, in pixels. */
outerCircleWidth?: number;
/** Width of the inner circles on the timeline, in pixels. */
innerCircleWidth?: number;
/** Width of time label, in pixels. */
timeWidth?: number;
/** Width of text label, in pixels. */
textWidth?: number;
/** Distance between labels to middle line, in pixels. */
labelsOffset?: number;
/** Distance between the time label AND the text label to middle line, in pixels. */
gap?: number;
className?: string;
}
export default function Timeline({
data,
width,
height,
isTimeUppercase = true,
lineWidth = 5,
outerCircleWidth = 30,
innerCircleWidth = 15,
timeWidth = 200,
textWidth = 300,
labelsOffset = 50,
gap = 50,
className,
}: TimelineProps) {
const largerMiddleElemeent =
outerCircleWidth > lineWidth ? outerCircleWidth : lineWidth;
const requestedWidth =
timeWidth + gap + largerMiddleElemeent + gap + textWidth;
if (requestedWidth > width) {
throw new Error(
`<Timeline /> - timeWidth + gap + ${
outerCircleWidth > lineWidth ? "outerCircleWidth" : "lineWidth"
} + gap + textWidth (${timeWidth} + ${gap} + ${largerMiddleElemeent} + ${gap} + ${textWidth} = ${requestedWidth}) is larger than width (${width})`
);
}
if (innerCircleWidth > outerCircleWidth) {
throw new Error(
`<Timeline /> - innerCircleWidth (${innerCircleWidth}) is larger than outerCircleWidth (${outerCircleWidth})`
);
}
return (
<div
className={
className ? `${className} ${styles.wrapper}` : `${styles.wrapper}`
}
style={{ width: width, height: height }}
style={{ width: width }}
>
<div
className={styles.line}
style={{ height: height, left: width / 2 }}
></div>
<div className={styles.timelineSections} style={{ width: width }}>
style={{
width: lineWidth,
left: width / 2 - lineWidth / 2,
}}
/>
<div className={styles.timelineSections}>
{data.map((datum) => (
<TimelineSection
key={datum.time}
datum={datum}
width={width}
isTimeUppercase={isTimeUppercase}
outerCircleWidth={outerCircleWidth}
innerCircleWidth={innerCircleWidth}
timeWidth={timeWidth}
textWidth={textWidth}
labelsOffset={labelsOffset}
gap={gap}
/>
))}
</div>
@ -66,74 +94,73 @@ interface TimelineSectionProps {
datum: TimelineData;
width: number;
isTimeUppercase: boolean;
outerCircleWidth: number;
innerCircleWidth: number;
timeWidth: number;
textWidth: number;
labelsOffset: number;
gap: number;
}
function TimelineSection({
datum,
width,
isTimeUppercase,
outerCircleWidth,
innerCircleWidth,
timeWidth,
textWidth,
labelsOffset,
gap,
}: TimelineSectionProps) {
const [onHover, setHover] = useState(false);
const handleMouseEnter = () => {
setHover(true);
console.log(onHover);
};
const handleMouseLeave = () => setHover(false);
// divs for customizable margins are necessary, absolute positioning loses vertical flex-box functionality
return (
<div className={styles.timelineSection}>
<div
style={{
width: (width - labelsOffset - labelsOffset - 30) / 2 - timeWidth,
}}
></div>
<div className={styles.timelineSection} style={{ gap: gap }}>
<div
className={onHover ? `${styles.time} ${styles.timeHover}` : styles.time}
style={{
width: timeWidth,
marginLeft: (width - 2 * gap - outerCircleWidth) / 2 - timeWidth,
}}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
{isTimeUppercase ? datum.time.toUpperCase() : datum.time}
</div>
<div style={{ width: labelsOffset }}></div>
<div
className={styles.circle}
style={{ width: 30 }}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
style={{
width: outerCircleWidth,
height: outerCircleWidth,
borderRadius: outerCircleWidth,
}}
>
<div
className={styles.innerCircle}
style={{ display: onHover ? "inline" : "none" }}
></div>
style={{
width: innerCircleWidth,
height: innerCircleWidth,
borderRadius: innerCircleWidth,
}}
/>
</div>
<div style={{ width: labelsOffset }}></div>
<div
className={onHover ? `${styles.text} ${styles.textHover}` : styles.text}
style={{
width: textWidth,
marginRight: (width - 2 * gap - outerCircleWidth) / 2 - textWidth,
}}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
{datum.text}
</div>
<div
style={{
width: (width - labelsOffset - labelsOffset - 30) / 2 - textWidth,
}}
></div>
</div>
);
}

View File

@ -68,7 +68,7 @@ export default function Home() {
<h2>
<code>{"<Timeline />"}</code>
</h2>
<Timeline data={mockTimelineData} width={800} height={1500} />
<Timeline data={mockTimelineData} width={800} />
</div>
);
}