diff --git a/site-new/assets/icons/ArrowLeft.tsx b/site-new/assets/icons/ArrowLeft.tsx new file mode 100644 index 000000000..8284433ff --- /dev/null +++ b/site-new/assets/icons/ArrowLeft.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import { SVGProps } from "react"; +const ArrowLeft = (props: SVGProps) => ( + + + + + +); +export default ArrowLeft; diff --git a/site-new/sidebars.ts b/site-new/sidebars.ts index add103427..13d0339ff 100644 --- a/site-new/sidebars.ts +++ b/site-new/sidebars.ts @@ -52,7 +52,7 @@ const sidebars: SidebarsConfig = { className: "glossary-icon no-caret", }, ], - web5Sidebar: [ + docsSidebarWeb5Sidebar: [ // { // type: "doc", // id: "web5/index", @@ -75,7 +75,7 @@ const sidebars: SidebarsConfig = { customProps: { sidebarHeader: "test" }, }, ], - tbdexSidebar: [ + docsSidebarTbdexSidebar: [ { id: "tbdex/index", type: "doc", diff --git a/site-new/src/components/Admonition/Admonition.tsx b/site-new/src/components/Admonition/Admonition.tsx index 858e5c027..1fe1f0a59 100644 --- a/site-new/src/components/Admonition/Admonition.tsx +++ b/site-new/src/components/Admonition/Admonition.tsx @@ -69,7 +69,7 @@ const Admonition = ({ variant, children, classes }: AdmonitionProps) => {
{typeof children === "string" ? ( -

{children}

+

{children}

) : ( children )} diff --git a/site-new/src/components/BlockBg/BlockBg.tsx b/site-new/src/components/BlockBg/BlockBg.tsx new file mode 100644 index 000000000..4a04aaf6b --- /dev/null +++ b/site-new/src/components/BlockBg/BlockBg.tsx @@ -0,0 +1,143 @@ +import { cn } from "@site/lib/utils"; +import { useMemo } from "react"; + +function getRandomNumber({ min, max }: { min: number; max: number }): number { + if (min > max) { + throw new Error("Minimum should be less than or equal to maximum."); + } + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +function populateGrid(grid: number[][], decreaseBlockLevel: number): void { + const rows = grid.length; + const cols = grid[0].length; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === 0) { + // sometimes populate the grid randomly without checking if the cell is occupied + if (Math.floor(Math.random() * 2) % 2 === 0) { + grid[i][j] = 1; + continue; + } + let isOccupied = false; + if (i > 0 && grid[i - 1][j] === 1) { + isOccupied = true; + } + if (j > 0 && grid[i][j - 1] === 1) { + isOccupied = true; + } + if (i < rows - 1 && grid[i + 1][j] === 1) { + isOccupied = true; + } + if (j < cols - 1 && grid[i][j + 1] === 1) { + isOccupied = true; + } + if (!isOccupied) { + grid[i][j] = 1; + } + } + } + } + + let randomIterations = decreaseBlockLevel; + + while (randomIterations--) { + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === 1 && Math.floor(Math.random() * 2) % 2 === 0) { + grid[i][j] = 0; + } + } + } + } +} + +const widths = { + 0: "25%", + 1: "50%", + 2: "75%", + 3: "100%", +} as const; + +const BlockBg = ({ + maxSize, + minSize, + rows = 12, + columns = 12, + className, + children, + decreaseBlockLevel = 2, +}: { + minSize: number; + maxSize: number; + rows?: number; + columns?: number; + className?: string; + children?: React.ReactNode; + decreaseBlockLevel?: number; +}) => { + const grid = useMemo(() => { + const generatedGrid = new Array(rows) + .fill(0) + .map(() => new Array(columns).fill(0)); + populateGrid(generatedGrid, decreaseBlockLevel); + return generatedGrid; + }, []); + + return ( +
+
+ {grid.map((row, i) => { + // generate a random height for the row + const height = getRandomNumber({ min: minSize, max: maxSize }); + return ( +
+ {row.map((col, j) => { + if (!col) return null; + // sometime use height as width sometime use height sometimes take full width + const randomNumber = Math.floor(Math.random() * 4) as 0 | 1 | 3; + + const width = + Math.floor(Math.random() * 2) % 2 === 0 + ? height + : Math.floor(Math.random() * 2) % 2 === 0 + ? getRandomNumber({ min: minSize, max: maxSize }) + : widths[randomNumber]; + + const randomHeight = + (Number.parseInt(widths[randomNumber].split("%")[0], 10) * + height) / + 100; + return ( +
+ ); + })} +
+ ); + })} +
+ +
{children}
+
+ ); +}; + +export default BlockBg; diff --git a/site-new/src/components/BlockBg/index.ts b/site-new/src/components/BlockBg/index.ts new file mode 100644 index 000000000..3b965a844 --- /dev/null +++ b/site-new/src/components/BlockBg/index.ts @@ -0,0 +1 @@ +export { default as BlockBg } from "./BlockBg"; diff --git a/site-new/src/components/BlogCard.tsx b/site-new/src/components/BlogCard.tsx index b47da678c..2e435a921 100644 --- a/site-new/src/components/BlogCard.tsx +++ b/site-new/src/components/BlogCard.tsx @@ -1,4 +1,5 @@ import clsx from "clsx"; +import Heading from "@theme/Heading"; type BlogCardProps = { date?: Date; @@ -6,8 +7,8 @@ type BlogCardProps = { title?: string; tags?: string[]; image?: string | null; - description?: string; size?: "large" | "small"; + description?: React.ReactNode; }; function BlogCard({ @@ -16,7 +17,7 @@ function BlogCard({ title = "Title", tags = [], image = require("/static/img/test-image16x9.png").default, - description = "Some description here", + description, size = "small", }: BlogCardProps) { const cardSizeClass = size === "large" ? "max-w-[840px]" : "max-w-[400px]"; @@ -24,24 +25,31 @@ function BlogCard({ return (
- +
-
{date.toLocaleDateString()}
-
{`@${author}`}
-

+

{date.toLocaleDateString()}

+
{`@${author}`}
+ {title} -

+ + {typeof description === "string" ? ( +

+ {description} +

+ ) : ( + description + )}
{tags.map((t) => (
- # + # {`${t}`}
))} diff --git a/site-new/src/components/ReadingProgress/ReadingProgress.tsx b/site-new/src/components/ReadingProgress/ReadingProgress.tsx index 9d3925fdb..bbf568208 100644 --- a/site-new/src/components/ReadingProgress/ReadingProgress.tsx +++ b/site-new/src/components/ReadingProgress/ReadingProgress.tsx @@ -3,7 +3,6 @@ import RocketProgress from "@site/assets/icons/RocketProgress"; const ReadingProgress = () => { const rocketRef = useRef(null); - const rocketBgRef = useRef(null); useEffect(() => { const updateProgressBar = () => { @@ -14,25 +13,17 @@ const ReadingProgress = () => { if (rocketRef.current) { rocketRef.current.style.left = `calc(${Math.max(scrollPercent)}%)`; } - - if (rocketBgRef.current) { - rocketBgRef.current.style.width = `calc(${Math.max(scrollPercent)}%)`; - } }; document.addEventListener("scroll", updateProgressBar); return () => { document.removeEventListener("scroll", updateProgressBar); }; - }, [rocketRef, rocketBgRef]); + }, [rocketRef]); return (
- diff --git a/site-new/src/components/SpotLightCard/SpotLightCard.tsx b/site-new/src/components/SpotLightCard/SpotLightCard.tsx new file mode 100644 index 000000000..97217f8ef --- /dev/null +++ b/site-new/src/components/SpotLightCard/SpotLightCard.tsx @@ -0,0 +1,49 @@ +import { cn, textClassesMap, ToneTypes } from "@site/lib/utils"; +import React from "react"; +import Heading from "@theme/Heading"; + +type SpotLightCardProps = { + src: string; + alt?: string; + className?: string; + tone?: ToneTypes; + title: string; + handle: string; + children?: React.ReactNode; +}; + +const SpotLightCard = ({ + src, + alt, + className, + tone = "yellow", + title, + handle, + children, +}: SpotLightCardProps) => { + return ( +
+ {alt} +
+

+ {title} +

+ + {handle} + + {typeof children === "string" ?

{children}

: children} +
+
+ ); +}; + +export default SpotLightCard; diff --git a/site-new/src/components/SpotLightCard/index.ts b/site-new/src/components/SpotLightCard/index.ts new file mode 100644 index 000000000..26329284b --- /dev/null +++ b/site-new/src/components/SpotLightCard/index.ts @@ -0,0 +1 @@ +export { default as SpotLightCard } from "./SpotLightCard"; diff --git a/site-new/src/css/custom.css b/site-new/src/css/custom.css index a9ba7bfbf..1f4336a18 100644 --- a/site-new/src/css/custom.css +++ b/site-new/src/css/custom.css @@ -65,6 +65,7 @@ --ifm-color-primary-light: #ffec19; --ifm-color-primary-lighter: #ffec19; --ifm-color-primary-lightest: #ffec19; + --tbd-yellow-shade-2: #F5D800; --ifm-code-font-size: 95%; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); --ifm-heading-color: "black"; @@ -73,7 +74,9 @@ --ifm-font-color-base: #fff; --ifm-menu-link-sublist-icon: url("/img/chevron.svg"); --ifm-footer-background-color: var(--ifm-color-primary); - --ifm-menu-link-padding-horizontal: var(--twist-core-spacing-12) + --ifm-menu-link-padding-horizontal: var(--twist-core-spacing-8); + --ifm-toc-padding-vertical: 45px; + --ifm-toc-padding-horizontal: 24px; } h2 { @@ -212,25 +215,25 @@ h2 { background: none !important; } + .menu__link--active { - border-left: 3px solid black; - color: black; - font-weight: 500; - font-size: 18px; + @apply relative bg-tbd-yellow-shade-1 +} + +.menu__link--active::before { + @apply content-[""] absolute inset-y-0 left-0 w-[3px] bg-black } .menu__list-item .menu__link:hover, .menu__list-item-collapsible:hover { - border-left: 3px solid black; color: black; font-weight: 600; - background-color: #f5d800; } -.menu__link--active:not(.menu__link--sublist) { +/* .menu__link--active:not(.menu__link--sublist) { background: none; border-left: none; -} +} */ .theme-doc-sidebar-item-category-level-1 { position: relative; @@ -657,6 +660,8 @@ a:has(.footer__logo) { @apply font-spaceGrotesk text-[1.375rem] leading-[1.65rem] lg:text-[2.125rem] lg:leading-[2.55rem]; } + + h4 { @apply text-lg leading-[1.463rem] lg:text-2.5xl; } @@ -678,8 +683,36 @@ a:has(.footer__logo) { .theme-doc-sidebar-item-link-level-2.menu__list-item .menu__link { padding-left: calc(calc(var(--ifm-menu-link-padding-horizontal) * 2) + 4px); + @apply text-base font-medium +} + + +.theme-doc-sidebar-item-category-level-2 .menu__link--sublist div { + @apply text-base font-medium } + .theme-doc-sidebar-item-link-level-3.menu__list-item .menu__link { padding-left: calc(calc(var(--ifm-menu-link-padding-horizontal) * 3) + 4px); + @apply text-base +} + +.theme-doc-sidebar-item-category-level-3 .menu__link--sublist div { + @apply text-base font-medium +} + +.menu__link.menu__link--sublist.menu__link--active::before { + content: none; +} + +.navbar__item.navbar__link.navbar__link--active { + @apply bg-black !text-tbd-yellow +} + +.navbar-sidebar__item.menu>* { + @apply text-black +} + +.navbar__toggle.clean-btn { + @apply text-black } \ No newline at end of file diff --git a/site-new/src/pages/component-guide/index.tsx b/site-new/src/pages/component-guide/index.tsx index e7f2869db..e3b9e9964 100644 --- a/site-new/src/pages/component-guide/index.tsx +++ b/site-new/src/pages/component-guide/index.tsx @@ -11,6 +11,7 @@ function ComponentList() { { name: "Quote", path: "/component-guide/quote" }, { name: "Marquee", path: "/component-guide/marquee" }, { name: "Accordion", path: "/component-guide/accordion" }, + { name: "SpotLightCard", path: "/component-guide/spotlight-card" }, { name: "FeedbackCard", path: "/component-guide/feedback-card" }, { name: "Admonition", path: "/component-guide/admonition" }, { name: "IconButton", path: "/component-guide/icon-button" }, diff --git a/site-new/src/pages/component-guide/spotlight-card.mdx b/site-new/src/pages/component-guide/spotlight-card.mdx new file mode 100644 index 000000000..ddf9783f1 --- /dev/null +++ b/site-new/src/pages/component-guide/spotlight-card.mdx @@ -0,0 +1,80 @@ +import { SpotLightCard } from "@site/src/components/SpotLightCard"; +import SomeImage from "../../../static/img/no-image.png"; +import docusaurusSocialCard from "@site/static/img/docusaurus-social-card.jpg"; +import NoImage from "@site/static/img/no-image.png"; + +## SpotLightCard Component + +
+

The SpotLightCard component is used to display a spotlight section, which includes an image, a title, a handle (typically a heading or name), and optional children (usually text or other elements). It can be used to highlight featured content or profiles.

+ +## Properties + +| Property | Type | Required | Default | Description | +| --------- | --------------- | -------- | -------- | --------------------------------------------------------------------------------- | +| src | string | Yes | "" | The URL of the image displayed in the card. | +| alt | string | No | "" | Alternative text for the image, used for accessibility. | +| className | string | No | "" | Additional CSS classes to apply custom styling to the card. | +| tone | ToneTypes | No | "yellow" | The tone or color for the title text, can be "teal", "purple", "yellow", etc. | +| title | string | Yes | "" | The title text displayed above the heading. | +| handle | string | Yes | "" | The heading or handle displayed in the card (usually a name or main heading). | +| children | React.ReactNode | No | "" | The content displayed below the handle, can be text or additional React elements. | + +## Usage + +```jsx + + This is the body text for the spotlight card. + +``` + +## Examples + +

SpotLightCard with Default Tone

+ + This is the body text for the spotlight card. + + +

SpotLightCard with Custom Tone

+ + This spotlight card uses a teal tone for the title. + + +

SpotLightCard with Custom Children

+ +
    +
  • Custom list item 1
  • +
  • Custom list item 2
  • +
+
+ +{" "} + + + From jumping headfirst into a todo app with Web5 to answering questions + straight away, it's thanks to members like you that our community is so + lively. Thank you for being here.:beers: + + +
diff --git a/site-new/src/theme/DocSidebar/Desktop/Content/index.tsx b/site-new/src/theme/DocSidebar/Desktop/Content/index.tsx index 9515ebfa0..76113fa1e 100644 --- a/site-new/src/theme/DocSidebar/Desktop/Content/index.tsx +++ b/site-new/src/theme/DocSidebar/Desktop/Content/index.tsx @@ -3,6 +3,7 @@ import clsx from "clsx"; import { ThemeClassNames } from "@docusaurus/theme-common"; import { useAnnouncementBar, + useLocalPathname, useScrollPosition, } from "@docusaurus/theme-common/internal"; import { translate } from "@docusaurus/Translate"; @@ -14,6 +15,9 @@ import DocBreadcrumbsWrapper from "@site/src/theme/DocBreadcrumbs"; import Heading from "@theme/Heading"; import styles from "./styles.module.css"; +import Link from "@docusaurus/Link"; +import ArrowLeft from "@site/assets/icons/ArrowLeft"; +import { BlockBg } from "@site/src/components/BlockBg"; function useShowAnnouncementBar() { const { isActive } = useAnnouncementBar(); @@ -39,6 +43,18 @@ export default function DocSidebarDesktopContent({ const sidebarHeader = sidebar[0].customProps.sidebarHeader as string; + const pathName = useLocalPathname(); + const pathArray = pathName.split("/"); + if (pathArray.length > 1) { + pathArray.pop(); + } + + let previousePage = pathArray.join("/"); + + if (`${previousePage}/` === pathName) { + previousePage = "/"; + } + return (