Merge main
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Jared He 2022-09-12 20:02:01 -04:00
commit 34e05db3fc
4 changed files with 252 additions and 0 deletions

View File

@ -0,0 +1,75 @@
.wrapper {
position: relative;
}
.line {
position: absolute;
height: 100%;
border-radius: calc(10rem / 16);
background-color: var(--secondary-accent);
z-index: -1;
}
.timelineSections {
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
gap: calc(20rem / 16);
}
.timelineSection {
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
}
.time {
margin: 0;
text-align: right;
font-size: calc(30rem / 16);
font-weight: 700;
color: var(--secondary-accent);
word-wrap: break-word;
}
.circle {
background-color: var(--secondary-accent);
box-shadow: calc(0rem / 16) calc(0rem / 16) calc(30rem / 16) var(--secondary-accent);
display: flex;
justify-content: center;
align-items: center;
}
.innerCircle {
background-color: var(--label);
display: none;
}
.text {
height: fit-content;
margin: 0;
padding: calc(15rem / 16);
border-radius: calc(10rem / 16);
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;
}
.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);
}

142
components/Timeline.tsx Normal file
View File

@ -0,0 +1,142 @@
import React from "react";
import styles from "./Timeline.module.css";
interface TimelineData {
time: string;
text: string;
}
interface TimelineProps {
data: TimelineData[];
/** 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 the time label AND the text label to middle line, in pixels. */
gap?: number;
className?: string;
}
export function Timeline({
data,
isTimeUppercase = true,
lineWidth = 5,
outerCircleWidth = 30,
innerCircleWidth = 15,
timeWidth = 200,
textWidth = 300,
gap = 50,
className,
}: TimelineProps) {
const largerMiddleElement =
outerCircleWidth > lineWidth ? outerCircleWidth : lineWidth;
const width = timeWidth + gap + largerMiddleElement + gap + textWidth;
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 }}
>
<div
className={styles.line}
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}
gap={gap}
/>
))}
</div>
</div>
);
}
interface TimelineSectionProps {
datum: TimelineData;
width: number;
isTimeUppercase: boolean;
outerCircleWidth: number;
innerCircleWidth: number;
timeWidth: number;
textWidth: number;
gap: number;
}
function TimelineSection({
datum,
width,
isTimeUppercase,
outerCircleWidth,
innerCircleWidth,
timeWidth,
textWidth,
gap,
}: TimelineSectionProps) {
return (
<div className={styles.timelineSection} style={{ gap: gap }}>
<div
className={styles.time}
style={{
width: timeWidth,
marginLeft: (width - 2 * gap - outerCircleWidth) / 2 - timeWidth,
}}
>
{isTimeUppercase ? datum.time.toUpperCase() : datum.time}
</div>
<div
className={styles.circle}
style={{
width: outerCircleWidth,
height: outerCircleWidth,
borderRadius: outerCircleWidth,
}}
>
<div
className={styles.innerCircle}
style={{
width: innerCircleWidth,
height: innerCircleWidth,
borderRadius: innerCircleWidth,
}}
/>
</div>
<div
className={styles.text}
style={{
width: textWidth,
marginRight: (width - 2 * gap - outerCircleWidth) / 2 - textWidth,
}}
>
{datum.text}
</div>
</div>
);
}

View File

@ -80,6 +80,33 @@ export const moreMockCategoricalData = [
{ key: "Dart", value: 2.21 }, { key: "Dart", value: 2.21 },
]; ];
export const mockTimelineData = [
{
time: "Fall 2020",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
},
{
time: "Winter 2021",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad",
},
{
time: "Spring 2021",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor i",
},
{
time: "Fall 2021",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proid",
},
{
time: "Winter 2022",
text: "Lorem ipsum dolor sit amet, consectetur adipi",
},
{
time: "Spring 2022",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut en",
},
];
export const mockBoxPlotData = [ export const mockBoxPlotData = [
{ {
category: "1A", category: "1A",

View File

@ -7,6 +7,7 @@ import {
mockQuoteData, mockQuoteData,
mockQuoteDataLong, mockQuoteDataLong,
mockPieData, mockPieData,
mockTimelineData,
} from "data/mocks"; } from "data/mocks";
import { sectionsData } from "data/routes"; import { sectionsData } from "data/routes";
import React from "react"; import React from "react";
@ -15,6 +16,7 @@ import { About } from "@/components/About";
import { PieChart } from "@/components/PieChart"; import { PieChart } from "@/components/PieChart";
import { QuotationCarousel } from "@/components/QuotationCarousel"; import { QuotationCarousel } from "@/components/QuotationCarousel";
import { Sections } from "@/components/Sections"; import { Sections } from "@/components/Sections";
import { Timeline } from "@/components/Timeline";
import { CenterWrapper } from "../components/CenterWrapper"; import { CenterWrapper } from "../components/CenterWrapper";
import { ColorPalette } from "../components/ColorPalette"; import { ColorPalette } from "../components/ColorPalette";
@ -29,6 +31,7 @@ export default function Home() {
<p>Show off your components here!</p> <p>Show off your components here!</p>
<ColorPalette /> <ColorPalette />
<h2> <h2>
<code>Text Styles</code> <code>Text Styles</code>
</h2> </h2>
@ -92,6 +95,11 @@ export default function Home() {
}))} }))}
/> />
<h2>
<code>{"<Timeline />"}</code>
</h2>
<Timeline data={mockTimelineData} />
<h2> <h2>
<code>{"<Textbox />"}</code> <code>{"<Textbox />"}</code>
</h2> </h2>