Add OrganizedContent with basic functionality
This commit is contained in:
parent
efd9eecdca
commit
edbae617c3
|
@ -0,0 +1,6 @@
|
||||||
|
.organizedcontent {
|
||||||
|
background-color: rgb(78, 212, 178, 0.2);
|
||||||
|
color: var(--purple-2);
|
||||||
|
display:flex;
|
||||||
|
flex-direction:row;
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
import React, { ReactNode, ComponentType } from "react";
|
||||||
|
import styles from "./OrganizedContent.module.css";
|
||||||
|
|
||||||
|
export interface LinkProps {
|
||||||
|
children: string | ReactNode | (string | ReactNode)[]
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Link = ComponentType<LinkProps>
|
||||||
|
|
||||||
|
|
||||||
|
interface Heading {
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
headings: Heading[];
|
||||||
|
currentIndex: number;
|
||||||
|
link: Link
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OrganizedContent: React.FC<Props> = ({
|
||||||
|
headings,
|
||||||
|
currentIndex,
|
||||||
|
children,
|
||||||
|
link: Link,
|
||||||
|
}) => {
|
||||||
|
const prevHeading = currentIndex > 0 ? headings[currentIndex - 1] : undefined;
|
||||||
|
const nextHeading =
|
||||||
|
currentIndex < headings.length - 1 ? headings[currentIndex + 1] : undefined;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.organizedcontent}>
|
||||||
|
<div>
|
||||||
|
{headings.map((heading, index) => (
|
||||||
|
<h3>
|
||||||
|
<Link url={heading.url}>{heading.name}</Link>
|
||||||
|
</h3>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>{headings[currentIndex].name}</h3>
|
||||||
|
{children}
|
||||||
|
{prevHeading && (
|
||||||
|
<Link url={prevHeading.url}>
|
||||||
|
Previous
|
||||||
|
{prevHeading.name}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
{nextHeading && (
|
||||||
|
<Link url={nextHeading.url}>
|
||||||
|
Next
|
||||||
|
{nextHeading.name}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,5 +1,4 @@
|
||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import styles from "./playground.module.css";
|
import styles from "./playground.module.css";
|
||||||
|
|
||||||
import AfterHoursContent, {
|
import AfterHoursContent, {
|
||||||
|
@ -7,6 +6,7 @@ import AfterHoursContent, {
|
||||||
} from "../content/playground/after-hours.event.mdx";
|
} from "../content/playground/after-hours.event.mdx";
|
||||||
|
|
||||||
import { MiniEventCard } from "./MiniEventCard";
|
import { MiniEventCard } from "./MiniEventCard";
|
||||||
|
import { OrganizedContent, LinkProps } from "./OrganizedContent";
|
||||||
|
|
||||||
export function MiniEventCardDemo() {
|
export function MiniEventCardDemo() {
|
||||||
const { name, location, short, date } = afterHoursMetadata;
|
const { name, location, short, date } = afterHoursMetadata;
|
||||||
|
@ -48,5 +48,59 @@ export function MiniEventCardDemo() {
|
||||||
description={<AfterHoursContent />}
|
description={<AfterHoursContent />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function OrganizedContentDemo() {
|
||||||
|
let sections = [
|
||||||
|
{
|
||||||
|
name: "Heading1",
|
||||||
|
url: "a",
|
||||||
|
content: <div> Hello World! 1</div>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Heading2",
|
||||||
|
url: "b",
|
||||||
|
content: <div> Hello World! 2</div>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Heading3",
|
||||||
|
url: "c",
|
||||||
|
content: <div> Hello World! 3</div>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const readAllSection = {
|
||||||
|
name: "Read all",
|
||||||
|
url: "readall",
|
||||||
|
content: <>{sections.map((section => section.content))}</>
|
||||||
|
}
|
||||||
|
|
||||||
|
sections = [readAllSection, ...sections];
|
||||||
|
|
||||||
|
const [index, setIndex] = useState(0);
|
||||||
|
|
||||||
|
function FakeLink({ url, children }: LinkProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
const target = sections.findIndex((section) => section.url === url);
|
||||||
|
|
||||||
|
if (target >= 0) {
|
||||||
|
setIndex(target);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { content } = sections[index];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OrganizedContent headings={sections} currentIndex={index} link={FakeLink}>
|
||||||
|
{content}
|
||||||
|
</OrganizedContent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {MiniEventCardDemo} from '../components/playground'
|
import { MiniEventCardDemo, OrganizedContentDemo } from '../components/playground'
|
||||||
|
|
||||||
# Playground
|
# Playground
|
||||||
|
|
||||||
|
@ -7,4 +7,10 @@ import {MiniEventCardDemo} from '../components/playground'
|
||||||
The `<MiniEventCard />` component has a collapsible description, and it used on
|
The `<MiniEventCard />` component has a collapsible description, and it used on
|
||||||
the events page. It uses the `<details>` tag and works without JS!
|
the events page. It uses the `<details>` tag and works without JS!
|
||||||
|
|
||||||
<MiniEventCardDemo />
|
<MiniEventCardDemo />
|
||||||
|
|
||||||
|
## `<OrganizedContent />`
|
||||||
|
|
||||||
|
Works without JS!
|
||||||
|
|
||||||
|
<OrganizedContentDemo />
|
Loading…
Reference in New Issue