From 0cc460e80ab1ed19bfacc14e23be37c29711c5fe Mon Sep 17 00:00:00 2001 From: Franck Gaudin Date: Fri, 15 Dec 2023 14:01:59 -0500 Subject: [PATCH] Add doc components on storybook (#117) --- apps/docs/.storybook/global.css | 21 ++++- apps/docs/.storybook/preview.tsx | 4 +- apps/docs/app/playground/page.tsx | 3 +- .../copyButton/CopyButton.stories.tsx | 29 +++++++ .../docs/components/copyButton/CopyButton.tsx | 38 ++++++--- .../CodeBlockCopyButton.css | 18 ----- .../CodeBlockCopyButton.tsx | 33 -------- .../docs/components/copyButton/copyButton.css | 29 ++++++- .../inlineCopyButton/InlineCopyButton.css | 14 ---- .../inlineCopyButton/InlineCopyButton.tsx | 33 -------- apps/docs/components/iconTable/IconItem.tsx | 14 ++-- .../iconTable/IconTable.stories.tsx | 18 +++++ apps/docs/components/iconTable/iconItem.css | 17 ++-- .../components/preview/Preview.stories.tsx | 77 +++++++++++++++++++ .../tableSection/TableSection.stories.tsx | 36 +++++++++ apps/docs/components/tabs/Tabs.stories.tsx | 36 +++++++++ .../themeSwitch/ThemeSwitch.stories.tsx | 12 +-- .../components/themeSwitch/ThemeSwitch.tsx | 5 +- .../components/themeSwitch/themeSwitch.css | 25 +++--- apps/docs/components/ui/card/Card.stories.ts | 17 ++++ apps/docs/components/ui/code/Code.stories.ts | 18 +++++ apps/docs/components/ui/code/Code.tsx | 5 +- .../components/ui/header/Header.stories.ts | 12 ++- apps/docs/components/ui/header/Header.tsx | 2 +- .../ui/iconButton/IconButton.stories.tsx | 20 +++++ .../components/ui/image/Image.stories.tsx | 20 +++++ .../ui/mobileMenu/MobileMenu.stories.tsx | 35 +++++++++ .../components/ui/mobileMenu/mobileMenu.css | 16 ++-- apps/docs/components/ui/nav/Nav.stories.tsx | 33 ++++++++ .../components/ui/overlay/Overlay.stories.ts | 17 ++++ apps/docs/components/ui/pre/Pre.stories.tsx | 28 +++++++ apps/docs/components/ui/pre/Pre.tsx | 33 +++++--- apps/docs/components/ui/pre/pre.css | 51 ++++++++---- .../sectionPopover/SectionPopover.stories.tsx | 38 +++++++++ .../components/ui/sidebar/Sidebar.stories.tsx | 49 ++++++++++++ .../ui/subHeader/SubHeader.stories.tsx | 39 ++++++++++ .../ui/switcher/Switcher.stories.tsx | 23 ++++++ .../components/ui/table/Table.stories.tsx | 31 ++++++++ .../docs/components/ui/title/Title.stories.ts | 25 ------ .../components/ui/title/Title.stories.tsx | 39 ++++++++++ apps/docs/contentlayer.config.js | 1 - apps/docs/styles/themes/rehype.css | 19 ++--- apps/docs/styles/tokens.css | 4 +- pnpm-lock.yaml | 15 ++-- 44 files changed, 806 insertions(+), 246 deletions(-) create mode 100644 apps/docs/components/copyButton/CopyButton.stories.tsx delete mode 100644 apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.css delete mode 100644 apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.tsx delete mode 100644 apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.css delete mode 100644 apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.tsx create mode 100644 apps/docs/components/iconTable/IconTable.stories.tsx create mode 100644 apps/docs/components/preview/Preview.stories.tsx create mode 100644 apps/docs/components/tableSection/TableSection.stories.tsx create mode 100644 apps/docs/components/tabs/Tabs.stories.tsx create mode 100644 apps/docs/components/ui/card/Card.stories.ts create mode 100644 apps/docs/components/ui/code/Code.stories.ts create mode 100644 apps/docs/components/ui/iconButton/IconButton.stories.tsx create mode 100644 apps/docs/components/ui/image/Image.stories.tsx create mode 100644 apps/docs/components/ui/mobileMenu/MobileMenu.stories.tsx create mode 100644 apps/docs/components/ui/nav/Nav.stories.tsx create mode 100644 apps/docs/components/ui/overlay/Overlay.stories.ts create mode 100644 apps/docs/components/ui/pre/Pre.stories.tsx create mode 100644 apps/docs/components/ui/sectionPopover/SectionPopover.stories.tsx create mode 100644 apps/docs/components/ui/sidebar/Sidebar.stories.tsx create mode 100644 apps/docs/components/ui/subHeader/SubHeader.stories.tsx create mode 100644 apps/docs/components/ui/switcher/Switcher.stories.tsx create mode 100644 apps/docs/components/ui/table/Table.stories.tsx delete mode 100644 apps/docs/components/ui/title/Title.stories.ts create mode 100644 apps/docs/components/ui/title/Title.stories.tsx diff --git a/apps/docs/.storybook/global.css b/apps/docs/.storybook/global.css index bcf92b577..16d728453 100644 --- a/apps/docs/.storybook/global.css +++ b/apps/docs/.storybook/global.css @@ -1,7 +1,20 @@ @import url("@/styles/tokens.css"); -.hd-container { - width: 100vw; - height: 100vh; - background-color: var(--hd-color-surface-primary); +.shd-container { + --sbt-container-background: var(--hd-white); + --sbt-container-color: var(--hd-neutral-50); + + width: 100%; + min-height: 100vh; + padding: 2rem; + background: + linear-gradient(90deg,var(--sbt-container-background) 10px,transparent 1%) 50%, + linear-gradient(var(--sbt-container-background) 10px,transparent 1%) 50%, + var(--sbt-container-color); + background-size: 12px 12px; +} + +[data-theme="dark"] { + --sbt-container-background: var(--hd-neutral-900); + --sbt-container-color: var(--hd-neutral-800); } diff --git a/apps/docs/.storybook/preview.tsx b/apps/docs/.storybook/preview.tsx index 672a148e7..26e612f48 100644 --- a/apps/docs/.storybook/preview.tsx +++ b/apps/docs/.storybook/preview.tsx @@ -5,8 +5,8 @@ import "../app/globals.css"; // Storybook styles import "./global.css"; -const Container = ({ children, theme }) => ( -
{children}
+const Container = ({ children, theme }: { children: React.ReactNode, theme: "light" | "dark"}) => ( +
{children}
) const preview: Preview = { diff --git a/apps/docs/app/playground/page.tsx b/apps/docs/app/playground/page.tsx index 74b2bbe97..9095df0e8 100644 --- a/apps/docs/app/playground/page.tsx +++ b/apps/docs/app/playground/page.tsx @@ -11,7 +11,8 @@ export default function PlaygroundPage() { flexDirection: "column", gap: "0.75rem", marginBlock: "2rem" - }}> + }} + >
  • Codeblock →
  • diff --git a/apps/docs/components/copyButton/CopyButton.stories.tsx b/apps/docs/components/copyButton/CopyButton.stories.tsx new file mode 100644 index 000000000..2009d39aa --- /dev/null +++ b/apps/docs/components/copyButton/CopyButton.stories.tsx @@ -0,0 +1,29 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import CopyButton from "./CopyButton"; + +const meta = { + title: "Component/CopyButton", + component: CopyButton, + args: { + text: "storybook is awesome" + } +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const Inline: Story = { + args: { + variant: "inline" + } +}; + +export const Ghost: Story = { + args: { + variant: "ghost", + children: "this text can be copied in 1 click" + } +}; diff --git a/apps/docs/components/copyButton/CopyButton.tsx b/apps/docs/components/copyButton/CopyButton.tsx index 629a66b67..254c4bc95 100644 --- a/apps/docs/components/copyButton/CopyButton.tsx +++ b/apps/docs/components/copyButton/CopyButton.tsx @@ -1,37 +1,57 @@ "use client"; +import React from "react"; import clsx from "clsx"; -import React, { type ReactNode } from "react"; import { Button } from "react-aria-components"; import "./copyButton.css"; interface CopyButtonProps { + variant?: "default" | "inline" | "ghost"; text: string; className?: string; - children?: ReactNode; onCopy?: () => void; - isCopied: boolean; - setIsCopied: React.Dispatch>; + copyMessage?: string; } -const CopyButton = ({ text, className, children, onCopy, isCopied, setIsCopied }: CopyButtonProps) => { - const classes = clsx("hd-copy-button", className); +const CopiedSvg = ; +// eslint-disable-next-line max-len +const CopySvg = ; + +const CopyButton = ( + { text, className, children, onCopy, variant = "default", copyMessage = "Copied!", ...rest }: React.PropsWithChildren) => { + const [isCopied, setIsCopied] = React.useState(false); + + const classes = clsx("hd-copy-button", { + [`hd-copy-button--${variant}`]: variant !== "default" + }, className); const copy = async () => { await navigator.clipboard.writeText(text); setIsCopied(true); onCopy?.(); - setTimeout(() => { + const timer = setTimeout(() => { setIsCopied(false); }, 5000); + + return () => { + clearTimeout(timer); + }; }; + const status = ( + variant === "ghost" + ? {copyMessage} + : CopiedSvg + ); + + const content = children ?? CopySvg; + return ( - ); }; diff --git a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.css b/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.css deleted file mode 100644 index 6235d01d9..000000000 --- a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.css +++ /dev/null @@ -1,18 +0,0 @@ -.hd-codeblock-copy-button { - aspect-ratio: 1/1; - border-radius: var(--hd-space-05); - width: var(--hd-space-4); - color: var(--hd-neutral-20) -} - -.hd-codeblock-copy-button:not([disabled]):hover { - background-color: var(--hd-neutral-50); -} - -.hd-codeblock-copy-button__icon { - stroke: currentcolor; -} - -.hd-codeblock-copy-button:not([disabled]):hover .hd-codeblock-copy-button__icon { - stroke: var(--hd-neutral-900); -} diff --git a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.tsx b/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.tsx deleted file mode 100644 index 8f37de3bc..000000000 --- a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react"; -import CopyButton from "../CopyButton"; -import cx from "classnames"; - -import "./CodeBlockCopyButton.css"; - -interface CodeBlockCopyButtonProps { - text: string; - className?: string; -} - -const CodeBlockCopyButton = ({ text, className }: CodeBlockCopyButtonProps) => { - const [isCopied, setIsCopied] = React.useState(false); - - const classes = cx("hd-codeblock-copy-button", className); - - const CopiedSvg = ; - // eslint-disable-next-line max-len - const CopySvg = ; - - return ( - - {isCopied ? CopiedSvg : CopySvg} - - ); -}; - -export default CodeBlockCopyButton; diff --git a/apps/docs/components/copyButton/copyButton.css b/apps/docs/components/copyButton/copyButton.css index 971e55320..993404d15 100644 --- a/apps/docs/components/copyButton/copyButton.css +++ b/apps/docs/components/copyButton/copyButton.css @@ -1,13 +1,36 @@ .hd-copy-button { + cursor: pointer; display: flex; align-items: center; justify-content: center; - background-color: transparent; border: none; - border-radius: var(--hd-space-1); - cursor: pointer; + aspect-ratio: 1/1; + border-radius: var(--hd-space-05); + width: var(--hd-space-4); + background-color: transparent; +} + +.hd-copy-button:not([disabled]):hover { + background-color: var(--hd-color-neutral-surface-weak); +} + +.hd-copy-button__icon { + stroke: currentcolor; } .hd-copy-button[disabled]:hover { cursor: not-allowed; } + +.hd-copy-button--inline { + width: var(--hd-space-3); +} + +.hd-copy-button--ghost { + aspect-ratio: unset; + width: auto; +} + +.hd-copy-button--ghost:not([disabled]):hover { + background-color: transparent; +} diff --git a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.css b/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.css deleted file mode 100644 index 20f4e94cb..000000000 --- a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.css +++ /dev/null @@ -1,14 +0,0 @@ -.hd-inline-copy-button { - aspect-ratio: 1/1; - background: var(--hd-color-neutral-surface); - border-radius: var(--hd-space-05); - width: var(--hd-space-3); -} - -.hd-inline-copy-button:not([disabled]):hover { - background-color: var(--hd-color-neutral-surface-weak); -} - -.hd-inline-copy-button__icon { - stroke: var(--hd-icon-button-color); -} diff --git a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.tsx b/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.tsx deleted file mode 100644 index 5fed0fe91..000000000 --- a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react"; -import CopyButton from "../CopyButton"; -import cx from "classnames"; - -import "./InlineCopyButton.css"; - -interface InlineCopyButtonProps { - text: string; - className?: string; -} - -const InlineCopyButton = ({ text, className }: InlineCopyButtonProps) => { - const [isCopied, setIsCopied] = React.useState(false); - - const classes = cx("hd-inline-copy-button", className); - - const CopiedSvg = ; - // eslint-disable-next-line max-len - const CopySvg = ; - - return ( - - {isCopied ? CopiedSvg : CopySvg} - - ); -}; - -export default InlineCopyButton; diff --git a/apps/docs/components/iconTable/IconItem.tsx b/apps/docs/components/iconTable/IconItem.tsx index ea1e3e773..51348a2b1 100644 --- a/apps/docs/components/iconTable/IconItem.tsx +++ b/apps/docs/components/iconTable/IconItem.tsx @@ -17,8 +17,6 @@ function toKebabCase(str: string) { } const IconItem: React.FC = ({ name, type, size }) => { - const [isCopied, setIsCopied] = React.useState(false); - const getIconNumericSize = (iconSize: IconItemProps["size"]) => { switch (iconSize) { case "sm": @@ -45,13 +43,11 @@ const IconItem: React.FC = ({ name, type, size }) => { <>
    - - {isCopied ? Copied! : - - - - } - + + + + +
    {formattedName}
    diff --git a/apps/docs/components/iconTable/IconTable.stories.tsx b/apps/docs/components/iconTable/IconTable.stories.tsx new file mode 100644 index 000000000..9fbf4f8f9 --- /dev/null +++ b/apps/docs/components/iconTable/IconTable.stories.tsx @@ -0,0 +1,18 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { IconTable } from "./IconTable"; + +const meta = { + title: "Component/IconTable", + component: IconTable +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + size: "lg", + type: "react" + } +}; diff --git a/apps/docs/components/iconTable/iconItem.css b/apps/docs/components/iconTable/iconItem.css index 626419840..c879e42af 100644 --- a/apps/docs/components/iconTable/iconItem.css +++ b/apps/docs/components/iconTable/iconItem.css @@ -14,25 +14,18 @@ flex-direction: column; } -.hd-icon-item__icon { - align-items: center; - border-radius: var(--hd-space-1); - display: flex; - height: 3rem; - justify-content: center; - transition: opacity 0.2s ease-in-out; +.hd-icon-item__icon, +.hd-icon-item-copy { + aspect-ratio: 1; width: 3rem; } -.hd-icon-item__copy-status { +.hd-icon-item__icon { align-items: center; - color: var(--hd-color-accent-text); + border-radius: var(--hd-space-1); display: flex; - font-size: 0.875rem; - height: 3rem; justify-content: center; transition: opacity 0.2s ease-in-out; - width: 3rem; } .hd-icon-item-copy:not([disabled]):hover { diff --git a/apps/docs/components/preview/Preview.stories.tsx b/apps/docs/components/preview/Preview.stories.tsx new file mode 100644 index 000000000..3ee2276b9 --- /dev/null +++ b/apps/docs/components/preview/Preview.stories.tsx @@ -0,0 +1,77 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Preview from "./Preview"; + +const meta = { + title: "Component/Preview", + component: Preview +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const Color: Story = { + args: { + category: "color", + name: "sapphire-500", + value: "#5f61c5" + } +}; + +export const FontFamily: Story = { + args: { + category: "fontFamily", + name: "font-family-primary", + value: "ABC Favorit" + } +}; + +export const FontSize: Story = { + args: { + category: "fontSize", + name: "font-size-120", + value: "1rem" + } +}; + +export const FontWeight: Story = { + args: { + category: "fontWeight", + name: "font-weight-400", + value: "400" + } +}; + +export const LineHeight: Story = { + args: { + category: "lineHeight", + name: "line-height-120", + value: "1.125rem" + } +}; + +export const BorderRadius: Story = { + args: { + category: "borderRadius", + name: "border-radius-4", + value: "1.5rem" + } +}; + +export const Size: Story = { + args: { + category: "size", + name: "space-1280", + value: "8rem" + } +}; + +export const Shadow: Story = { + args: { + category: "shadow", + name: "shadow-sm", + value: "0 1px 6px 0 rgba(60, 60, 60, 0.10)" + } +}; diff --git a/apps/docs/components/tableSection/TableSection.stories.tsx b/apps/docs/components/tableSection/TableSection.stories.tsx new file mode 100644 index 000000000..208ad33bc --- /dev/null +++ b/apps/docs/components/tableSection/TableSection.stories.tsx @@ -0,0 +1,36 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import TableSection from "./TableSection"; + +const meta = { + title: "Component/TableSection", + component: TableSection +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + tokens: [ + { + name: "color-primary", + value: "#000" + }, + { + name: "color-secondary", + value: "#fff" + }, + { + name: "hop-space-0", + value: "0" + }, + { + name: "hop-space-20", + value: "0.125" + } + ], + categories: ["color", "space"], + categoryKey: "name" + } +}; diff --git a/apps/docs/components/tabs/Tabs.stories.tsx b/apps/docs/components/tabs/Tabs.stories.tsx new file mode 100644 index 000000000..6a8bba3ad --- /dev/null +++ b/apps/docs/components/tabs/Tabs.stories.tsx @@ -0,0 +1,36 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Tabs from "./Tabs"; + +const meta = { + title: "Component/Tabs", + component: Tabs +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + tabs: [ + { + category: "tab1", + title: "Tab 1" + }, + { + category: "tab2", + title: "Tab 2" + }, + { + category: "tab3", + title: "Tab 3" + } + ], + children: [ +
    Tab 1 content
    , +
    Tab 2 content
    , +
    Tab 3 content
    + ] + + } +}; diff --git a/apps/docs/components/themeSwitch/ThemeSwitch.stories.tsx b/apps/docs/components/themeSwitch/ThemeSwitch.stories.tsx index 77fb77b38..bb4ff50b6 100644 --- a/apps/docs/components/themeSwitch/ThemeSwitch.stories.tsx +++ b/apps/docs/components/themeSwitch/ThemeSwitch.stories.tsx @@ -2,14 +2,16 @@ import type { Meta, StoryObj } from "@storybook/react"; import ThemeSwitch from "./ThemeSwitch"; -const meta: Meta = { - title: "Component/Theme Switch/Button", +const meta = { + title: "Component/Theme Switch", component: ThemeSwitch -}; +} satisfies Meta; export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Default: Story = { - args: {} + args: { + text: "Toggle theme" + } }; diff --git a/apps/docs/components/themeSwitch/ThemeSwitch.tsx b/apps/docs/components/themeSwitch/ThemeSwitch.tsx index bcc71a1b6..3db7d03df 100644 --- a/apps/docs/components/themeSwitch/ThemeSwitch.tsx +++ b/apps/docs/components/themeSwitch/ThemeSwitch.tsx @@ -3,6 +3,7 @@ import { ToggleButton } from "react-aria-components"; import { type ColorScheme, ThemeContext } from "@/context/theme/ThemeProvider"; import Icon from "@/components/themeSwitch/ThemeSwitchIcons"; +import clsx from "clsx"; import "./themeSwitch.css"; @@ -25,12 +26,12 @@ const ThemeSwitch = ({ text, className }: ThemeSwitchProps) => { if (colorMode) { return ( - {text} + {text} ); } diff --git a/apps/docs/components/themeSwitch/themeSwitch.css b/apps/docs/components/themeSwitch/themeSwitch.css index 830e890aa..82e247791 100644 --- a/apps/docs/components/themeSwitch/themeSwitch.css +++ b/apps/docs/components/themeSwitch/themeSwitch.css @@ -1,22 +1,27 @@ .hd-theme-switch__button { - width: var(--hd-space-4); - aspect-ratio: 1/1; background-color: transparent; color: var(--hd-color-neutral-icon); border-width: 0; border-radius: var(--hd-space-05); display: flex; + gap: var(--hd-space-2); justify-content: center; align-items: center; + font-size: 1rem; } -.hd-theme-switch__button:hover { - background-color: var(--hd-color-surface-primary-weak-hover); - cursor: pointer; -} +@media screen and (width >= 48rem) { + .hd-theme-switch__button { + width: var(--hd-space-4); + aspect-ratio: 1/1; + } -.hd-theme-switch { - display: flex; - align-items: center; - gap: var(--hd-space-05); + .hd-theme-switch__button:hover { + background-color: var(--hd-color-neutral-surface-weak); + cursor: pointer; + } + + .hd-theme-switch__text { + display: none; + } } diff --git a/apps/docs/components/ui/card/Card.stories.ts b/apps/docs/components/ui/card/Card.stories.ts new file mode 100644 index 000000000..7b498ca80 --- /dev/null +++ b/apps/docs/components/ui/card/Card.stories.ts @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Card from "./Card"; + +const meta = { + title: "Ui/Card", + component: Card +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: "Card content" + } +}; diff --git a/apps/docs/components/ui/code/Code.stories.ts b/apps/docs/components/ui/code/Code.stories.ts new file mode 100644 index 000000000..84bf636e9 --- /dev/null +++ b/apps/docs/components/ui/code/Code.stories.ts @@ -0,0 +1,18 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Code from "./Code"; + +const meta = { + title: "Ui/Code", + component: Code +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: "const foo = 'bar';", + value: "const foo = 'bar';" + } +}; diff --git a/apps/docs/components/ui/code/Code.tsx b/apps/docs/components/ui/code/Code.tsx index 32b1e803c..02fa50cd3 100644 --- a/apps/docs/components/ui/code/Code.tsx +++ b/apps/docs/components/ui/code/Code.tsx @@ -1,5 +1,6 @@ import React from "react"; -import InlineCopyButton from "@/components/copyButton/inlineCopyButton/InlineCopyButton"; +import CopyButton from "@/components/copyButton/CopyButton"; + import "./code.css"; interface CodeProps { @@ -11,7 +12,7 @@ const Code: React.FC = ({ children, value }) => { return (
    {children} - +
    ); }; diff --git a/apps/docs/components/ui/header/Header.stories.ts b/apps/docs/components/ui/header/Header.stories.ts index 9e9a36376..1a0cc0a0d 100644 --- a/apps/docs/components/ui/header/Header.stories.ts +++ b/apps/docs/components/ui/header/Header.stories.ts @@ -2,14 +2,12 @@ import type { Meta, StoryObj } from "@storybook/react"; import Header from "./Header"; -const meta: Meta = { - title: "Component/Header", +const meta = { + title: "Ui/Header", component: Header -}; +} satisfies Meta; export default meta; -type Story = StoryObj; +type Story = StoryObj; -export const Default: Story = { - args: {} -}; +export const Default: Story = {}; diff --git a/apps/docs/components/ui/header/Header.tsx b/apps/docs/components/ui/header/Header.tsx index e560eaede..221b50a97 100644 --- a/apps/docs/components/ui/header/Header.tsx +++ b/apps/docs/components/ui/header/Header.tsx @@ -46,7 +46,7 @@ const Header = () => {
    {/**/} - + {/* eslint-disable-next-line max-len */} diff --git a/apps/docs/components/ui/iconButton/IconButton.stories.tsx b/apps/docs/components/ui/iconButton/IconButton.stories.tsx new file mode 100644 index 000000000..b4133f8f3 --- /dev/null +++ b/apps/docs/components/ui/iconButton/IconButton.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import IconButton from "./IconButton"; + +const meta = { + title: "Ui/IconButton", + component: IconButton +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +/* eslint-disable max-len */ +const copyIcon = ; + +export const Default: Story = { + args: { + children: copyIcon + } +}; diff --git a/apps/docs/components/ui/image/Image.stories.tsx b/apps/docs/components/ui/image/Image.stories.tsx new file mode 100644 index 000000000..f3b354edc --- /dev/null +++ b/apps/docs/components/ui/image/Image.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Image from "./Image"; + +const meta = { + title: "Ui/Image", + component: Image +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + src: "https://placebear.com/640/360", + alt: "Image", + width: 640, + height: 360 + } +}; diff --git a/apps/docs/components/ui/mobileMenu/MobileMenu.stories.tsx b/apps/docs/components/ui/mobileMenu/MobileMenu.stories.tsx new file mode 100644 index 000000000..e30e4dafa --- /dev/null +++ b/apps/docs/components/ui/mobileMenu/MobileMenu.stories.tsx @@ -0,0 +1,35 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import MobileMenu from "./MobileMenu"; +import MobileMenuTrigger from "./MobileMenuTrigger"; + +const meta = { + title: "Mobile/Menu", + component: MobileMenu, + parameters: { + viewport: { + defaultViewport: "mobile1" + } + } +} satisfies Meta; + +export default meta; +type Story = StoryObj; +type TriggerStory = StoryObj; + +export const Default: Story = { + args: { + isOpen: true + } +}; + +export const Trigger: TriggerStory = { + args: { + onToggle: () => {} + }, + render: args => { + return ( + + ); + } +}; diff --git a/apps/docs/components/ui/mobileMenu/mobileMenu.css b/apps/docs/components/ui/mobileMenu/mobileMenu.css index fade1dbc6..92db7a618 100644 --- a/apps/docs/components/ui/mobileMenu/mobileMenu.css +++ b/apps/docs/components/ui/mobileMenu/mobileMenu.css @@ -1,3 +1,7 @@ +:root { + --hd-mobile-header-height: var(--hd-space-8); +} + .hd-mobile-menu { background: var(--hd-color-neutral-surface); position: fixed; @@ -13,7 +17,7 @@ display: flex; align-items: center; border-bottom: var(--hd-border-size) solid var(--hd-color-neutral-border); - height: var(--hd-header-height); + height: var(--hd-mobile-header-height); } .hd-mobile-menu__close { @@ -74,16 +78,6 @@ color: var(--hd-color-neutral-text); } -.hd-mobile-menu-footer-button { - background-color: transparent; - cursor: pointer; - border: none; - display: flex; - gap: 1rem; - font-size: 1rem; - color: var(--hd-color-neutral-text); -} - .hd-header__mobile-menu-trigger-icon { stroke: var(--hd-color-neutral-text); } diff --git a/apps/docs/components/ui/nav/Nav.stories.tsx b/apps/docs/components/ui/nav/Nav.stories.tsx new file mode 100644 index 000000000..d79d32184 --- /dev/null +++ b/apps/docs/components/ui/nav/Nav.stories.tsx @@ -0,0 +1,33 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Nav from "./Nav"; + +const meta = { + title: "Ui/Nav", + component: Nav +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + items: [ + { + "label": "Tokens", + "path": "/tokens/getting-started/introduction", + "status": "ready" + }, + { + "label": "Icons", + "path": "/icons/getting-started/introduction", + "status": "ready" + }, + { + "label": "Components", + "path": "/components/installation", + "status": "not-ready" + } + ] + } +}; diff --git a/apps/docs/components/ui/overlay/Overlay.stories.ts b/apps/docs/components/ui/overlay/Overlay.stories.ts new file mode 100644 index 000000000..164b545ef --- /dev/null +++ b/apps/docs/components/ui/overlay/Overlay.stories.ts @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Overlay from "./Overlay"; + +const meta = { + title: "Ui/Overlay", + component: Overlay +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + isOpen: true + } +}; diff --git a/apps/docs/components/ui/pre/Pre.stories.tsx b/apps/docs/components/ui/pre/Pre.stories.tsx new file mode 100644 index 000000000..6d9ce05fe --- /dev/null +++ b/apps/docs/components/ui/pre/Pre.stories.tsx @@ -0,0 +1,28 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Pre from "./Pre"; + +const meta = { + title: "Ui/Pre", + component: Pre +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + raw: "const foo = 'bar';", + title: "Story.tsx", + "data-language": "tsx", + children: const foo = 'bar'; + } +}; + +export const WithoutTitle: Story = { + args: { + raw: "const foo = 'bar';", + "data-language": "tsx", + children: const foo = 'bar'; + } +}; diff --git a/apps/docs/components/ui/pre/Pre.tsx b/apps/docs/components/ui/pre/Pre.tsx index a6e9e2be8..a6ae9c244 100644 --- a/apps/docs/components/ui/pre/Pre.tsx +++ b/apps/docs/components/ui/pre/Pre.tsx @@ -4,7 +4,7 @@ import React from "react"; import type { HTMLAttributes } from "react"; import cx from "classnames"; -import CodeBlockCopyButton from "@/components/copyButton/codeblockCopyButton/CodeBlockCopyButton"; +import CopyButton from "@/components/copyButton/CopyButton.tsx"; import LangIcon from "@/components/ui/pre/langIcon/LangIcon"; import "./pre.css"; @@ -23,21 +23,30 @@ const Pre = ({ children, title, "data-language": dataLanguage, raw, ...props }: const classes = cx("hd-pre", preClasses); + const langContent = dataLanguage && ( + + + + ); + + const titleContent = {title}; + const copyButton = raw && ; + return (
    -            {raw && }
                 {title &&
    -            
    -
    - {dataLanguage && ( - - - ) - } - {title} +
    +
    + {langContent} + {titleContent} +
    + {copyButton}
    -
    } - {children} + } +
    + {children} +
    + {!title &&
    {copyButton}
    }
    ); }; diff --git a/apps/docs/components/ui/pre/pre.css b/apps/docs/components/ui/pre/pre.css index 5b5454e4e..f04b40ec9 100644 --- a/apps/docs/components/ui/pre/pre.css +++ b/apps/docs/components/ui/pre/pre.css @@ -1,48 +1,69 @@ .hd-pre { - position: relative; - padding-right: 3rem; + overflow: hidden; + border: var(--hd-border-size) solid var(--hd-color-neutral-border); + + /* the radius top is larger to eliminate a visual glitch with the header */ + border-radius: 0.6rem 0.6rem 0.5rem 0.5rem; + color: var(--hd-color-neutral-text); + background-color: var(--hd-color-white-surface); +} + +.hd-pre--no-title { + display: flex; + align-items: stretch; +} + +.hd-pre--no-title .hd-pre__code { + margin-right: auto; } .hd-pre--no-title code { align-content: center; - min-height: 3rem; +} + +.hd-pre--no-title .hd-pre__action { + padding-inline: var(--hd-space-1); + margin-block: auto; } /* pre HEADER */ .hd-pre-header { display: flex; - justify-content: space-between; - padding: var(--hd-space-1) 0 var(--hd-space-1) var(--hd-space-2); - font-size: 0.75rem; + padding-inline: var(--hd-space-2) var(--hd-space-1); + height: 3rem; + font-size: 0.875rem; + font-family: var(--hd-default-font-family); align-items: center; - border-bottom: var(--hd-border-size) solid var(--hd-color-border-primary-weak); + color: var(--hd-color-neutral-text-weakest); + background-color: var(--hd-color-neutral-surface); + border-top-left-radius: 0.5rem; + border-top-right-radius: 0.5rem; + border-bottom: var(--hd-border-size) solid var(--hd-color-neutral-border); } .hd-pre-header__info { display: flex; align-items: center; gap: var(--hd-space-1); + margin-right: auto; } .hd-pre-header__lang { - font-family: monospace; display: flex; } .hd-pre-header__lang-icon { width: var(--hd-space-2); aspect-ratio: 1/1; + filter: grayscale(100%); } .hd-pre-header__title { - font-style: italic; line-height: 1; - color: var(--hd-white); } -/* Copy Button */ -.hd-pre-copy-button { - position: absolute; - right: var(--hd-space-1); - top: var(--hd-space-1); +.hd-pre__code { + padding: var(--hd-space-2); + font-size: 0.875rem; + line-height: 1.5; } diff --git a/apps/docs/components/ui/sectionPopover/SectionPopover.stories.tsx b/apps/docs/components/ui/sectionPopover/SectionPopover.stories.tsx new file mode 100644 index 000000000..958ffe81f --- /dev/null +++ b/apps/docs/components/ui/sectionPopover/SectionPopover.stories.tsx @@ -0,0 +1,38 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import SectionPopover from "./sectionPopover"; + +const meta = { + title: "Mobile/SectionPopover", + component: SectionPopover, + parameters: { + viewport: { + defaultViewport: "mobile1" + } + } +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + links: [ + { + title: "Section 1", + url: "#section-1", + id: "section-1" + }, + { + title: "Section 2", + url: "#section-2", + id: "section-2" + }, + { + title: "Section 3", + url: "#section-3", + id: "section-3" + } + ] + } +}; diff --git a/apps/docs/components/ui/sidebar/Sidebar.stories.tsx b/apps/docs/components/ui/sidebar/Sidebar.stories.tsx new file mode 100644 index 000000000..f9f120b7f --- /dev/null +++ b/apps/docs/components/ui/sidebar/Sidebar.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Sidebar from "./Sidebar"; + +const meta = { + title: "Ui/Sidebar", + component: Sidebar, + parameters: { + viewport: { + defaultViewport: "mobile1" + } + } +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + data: [ + { + _id: "1", + title: "Getting Started", + _raw: { + flattenedPath: "/getting-started", + sourceFileDir: "/pages" + } + }, + { + _id: "2", + title: "Components", + _raw: { + flattenedPath: "/components", + sourceFileDir: "/pages" + } + }, + { + _id: "3", + title: "Icons", + _raw: { + flattenedPath: "/icons", + sourceFileDir: "/pages" + } + } + ], + isOpen: true, + onClose: () => {} + } +}; diff --git a/apps/docs/components/ui/subHeader/SubHeader.stories.tsx b/apps/docs/components/ui/subHeader/SubHeader.stories.tsx new file mode 100644 index 000000000..70ff1dc72 --- /dev/null +++ b/apps/docs/components/ui/subHeader/SubHeader.stories.tsx @@ -0,0 +1,39 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import SubHeader from "./SubHeader"; + +const meta = { + title: "Mobile/SubHeader", + component: SubHeader, + parameters: { + viewport: { + defaultViewport: "mobile1" + } + } +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + links: [ + { + title: "Section 1", + url: "#section-1", + id: "section-1" + }, + { + title: "Section 2", + url: "#section-2", + id: "section-2" + }, + { + title: "Section 3", + url: "#section-3", + id: "section-3" + } + ], + toggleOpenState: () => {} + } +}; diff --git a/apps/docs/components/ui/switcher/Switcher.stories.tsx b/apps/docs/components/ui/switcher/Switcher.stories.tsx new file mode 100644 index 000000000..5b7831453 --- /dev/null +++ b/apps/docs/components/ui/switcher/Switcher.stories.tsx @@ -0,0 +1,23 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Switcher from "./Switcher"; + +const meta = { + title: "Ui/Switcher", + component: Switcher +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const React: Story = { + args: { + type: "react" + } +}; + +export const Svg: Story = { + args: { + type: "svg" + } +}; diff --git a/apps/docs/components/ui/table/Table.stories.tsx b/apps/docs/components/ui/table/Table.stories.tsx new file mode 100644 index 000000000..1eac27d95 --- /dev/null +++ b/apps/docs/components/ui/table/Table.stories.tsx @@ -0,0 +1,31 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Table from "./Table"; + +const meta = { + title: "Ui/Table", + component: Table +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + category: "react", + data: [ + { + name: "--hop-sapphire-200", + value: "#95b1ff" + }, + { + name: "--hop-primary-surface-disabled", + value: "#95b1ff" + }, + { + name: "--hop-primary-surface-disabled", + value: "#2040c7" + } + ] + } +}; diff --git a/apps/docs/components/ui/title/Title.stories.ts b/apps/docs/components/ui/title/Title.stories.ts deleted file mode 100644 index cf243d6c0..000000000 --- a/apps/docs/components/ui/title/Title.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import Title from "./Title"; - -const meta: Meta = { - title: "Component/Title", - component: Title, - argTypes: { - as: { - control: { type: "select" } - }, - level: { - control: { type: "select" } - } - } -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - children: "Nothing is cheap" - } -}; diff --git a/apps/docs/components/ui/title/Title.stories.tsx b/apps/docs/components/ui/title/Title.stories.tsx new file mode 100644 index 000000000..1db7f7afb --- /dev/null +++ b/apps/docs/components/ui/title/Title.stories.tsx @@ -0,0 +1,39 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import Title from "./Title"; + +const meta = { + title: "Ui/Title", + component: Title, + argTypes: { + as: { + control: { type: "select" } + }, + level: { + control: { type: "select" } + } + }, + args: { + children: "Nothing is cheap" + } +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const Level: Story = { + render: args => { + return ( + <> + + <Title {...args} level={2} /> + <Title {...args} level={3} /> + <Title {...args} level={4} /> + <Title {...args} level={5} /> + </> + ) + ; + } +}; diff --git a/apps/docs/contentlayer.config.js b/apps/docs/contentlayer.config.js index 7373c5b12..c1269f0e9 100644 --- a/apps/docs/contentlayer.config.js +++ b/apps/docs/contentlayer.config.js @@ -173,7 +173,6 @@ export default makeSource({ if (codeEl.tagName !== "code") { return; } - node.raw = codeEl.children?.[0].value; } }); diff --git a/apps/docs/styles/themes/rehype.css b/apps/docs/styles/themes/rehype.css index 367186ead..0f02a8fe3 100644 --- a/apps/docs/styles/themes/rehype.css +++ b/apps/docs/styles/themes/rehype.css @@ -1,4 +1,8 @@ -/* EDITOR - THEME SPECIFIC COLORS */ +/* !* EDITOR - THEME SPECIFIC COLORS *! */ +[data-theme="light"] [data-rehype-pretty-code-fragment]{ + --hd-codeblock-background-color: var(--hd-neutral-800); +} + [data-rehype-pretty-code-fragment] { /* NORD */ --hd-codeblock-line-highlighted-border-color: #88C0D0; @@ -14,6 +18,7 @@ --hd-codeblock-word-value-text-color: rgb(239 194 198); --hd-codeblock-title-background-color: rgb(59 66 82); --hd-codeblock-title-text-color: rgb(216 222 233); + --hd-codeblock-background-color: var(--hd-neutral-800); margin-bottom: var(--hd-space-3); } @@ -23,18 +28,17 @@ } [data-rehype-pretty-code-fragment] pre { - border-radius: var(--hd-space-1); + background-color: var(--hd-codeblock-background-color) !important; } [data-rehype-pretty-code-fragment] code { /* until we create our own json theme, it's the best way to have a transparent code line */ - background-color: transparent!important; + background-color: transparent !important; } [data-rehype-pretty-code-fragment] pre code { display: grid; overflow-x: auto; - padding: var(--hd-space-1) 0 var(--hd-space-1) var(--hd-space-2); } [data-rehype-pretty-code-fragment] .line { @@ -88,13 +92,6 @@ /* Block Title */ [data-rehype-pretty-code-title] { - border-radius: var(--hd-space-1) var(--hd-space-1) 0 0; - font-weight: 500; - font-size: .875rem; - background-color: var(--hd-codeblock-title-background-color); - padding: var(--hd-space-1); - padding-inline-start: .75rem; - color: var(--hd-codeblock-title-text-color); display: none; } diff --git a/apps/docs/styles/tokens.css b/apps/docs/styles/tokens.css index 9e6409647..18a50027d 100644 --- a/apps/docs/styles/tokens.css +++ b/apps/docs/styles/tokens.css @@ -52,6 +52,7 @@ } [data-theme="light"] { + --hd-color-white-surface: var(--hd-white); --hd-color-neutral-surface: var(--hd-neutral-20); --hd-color-neutral-surface-weak: var(--hd-neutral-50); --hd-color-surface-neutral-selection: var(--hd-neutral-75); @@ -78,6 +79,7 @@ /* Dark Theme Overrides */ [data-theme="dark"] { + --hd-color-white-surface: var(--hd-neutral-800); --hd-color-neutral-surface: var(--hd-neutral-900); --hd-color-neutral-surface-weak: var(--hd-neutral-800); --hd-color-surface-neutral-selection: var(--hd-neutral-300); @@ -85,7 +87,7 @@ --hd-color-neutral-text-weak: var(--hd-neutral-300); --hd-color-neutral-text-weak-hover: var(--hd-neutral-0); --hd-color-neutral-text-weakest: var(--hd-neutral-300); - --hd-color-neutral-text-weakest-hover: var(--hd-neutral-100); + --hd-color-neutral-text-weakest-hover: var(--hd-neutral-50); --hd-color-primary-text: var(--hd-primary-600); --hd-color-primary-text-hover: var(--hd-white); --hd-color-primary-text-strong: var(--hd-primary-900); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7b6b7db0f..ad3ef572f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -124,7 +124,7 @@ importers: version: 4.1.3(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0) rehype-pretty-code: specifier: 0.10.2 - version: 0.10.2(shiki@0.14.5) + version: 0.10.2(shiki@0.14.6) unist-util-visit: specifier: 5.0.0 version: 5.0.0 @@ -4069,6 +4069,7 @@ packages: dependencies: is-glob: 4.0.3 micromatch: 4.0.5 + napi-wasm: 1.1.0 dev: true bundledDependencies: - napi-wasm @@ -15649,6 +15650,10 @@ packages: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} dev: true + /napi-wasm@1.1.0: + resolution: {integrity: sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==} + dev: true + /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true @@ -17429,7 +17434,7 @@ packages: unified: 11.0.4 dev: true - /rehype-pretty-code@0.10.2(shiki@0.14.5): + /rehype-pretty-code@0.10.2(shiki@0.14.6): resolution: {integrity: sha512-yBgk3S4yXtkAWVrkoN1DqDihjsaP0ReuN9Du4Dtkl/wsgwyqGNGuIUGi2etVHAOsi40e2KRHoOulQqnKPuscPA==} engines: {node: '>=16'} peerDependencies: @@ -17439,7 +17444,7 @@ packages: hast-util-to-string: 2.0.0 parse-numeric-range: 1.3.0 rehype-parse: 8.0.5 - shiki: 0.14.5 + shiki: 0.14.6 unified: 10.1.2 unist-util-visit: 4.1.2 dev: false @@ -17957,8 +17962,8 @@ packages: engines: {node: '>=8'} dev: true - /shiki@0.14.5: - resolution: {integrity: sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==} + /shiki@0.14.6: + resolution: {integrity: sha512-R4koBBlQP33cC8cpzX0hAoOURBHJILp4Aaduh2eYi+Vj8ZBqtK/5SWNEHBS3qwUMu8dqOtI/ftno3ESfNeVW9g==} dependencies: ansi-sequence-parser: 1.1.1 jsonc-parser: 3.2.0