storybook github

1thay — design system

trăm nghe không bằng một thấy · single source of truth in figma

reference files: 1thay.md · figma.md · astro.md · storybook.md · design-tokens.md · project-logs.md

project overview

1thay is a design system for saas dashboards & infographics. it serves 1thay.com (astro docs), design.1thay.com (storybook), and figma.

key principle: figma is the single source of truth for design tokens. code mirrors figma.

stack:
  astro: 5.x (static site)
  storybook: 8.x (component dev)
  react: 19.x (components)
  figma: OAinJNCk0DZ1p1R1xyPfvx (token source)
  deploy: cloudflare pages (auto from github)
  fonts: Hanken Grotesk, Inter, Merriweather, Space Grotesk
  icons: lucide (line stroke), @carbon/icons-react (shape fill)

core rules

  1. figma first — tokens change in figma, then sync to src/tokens/tokens.css. never hardcode values.
  2. lowercase — all ui text is lowercase. code identifiers follow js conventions (camelCase, PascalCase).
  3. bento grid — layouts use css grid with consistent --radius-lg and spacing tokens.
  4. storybook before astro — components are built and tested in storybook first, then used in astro pages.
  5. single file of sourcessrc/tokens/tokens.css is imported by both astro and storybook.
  6. no style prop on react components in astro — react components receive style objects, not strings. wrap with astro divs for layout spacing.

project structure

src/
├── tokens/           # single source of truth for tokens
│   ├── tokens.css     css custom properties (both astro + storybook import)
│   └── tokens.js      js export (storybook theme, programmatic use)
├── components/        # react components (storybook + astro)
│   ├── Button/         *.tsx, *.css, *.stories.tsx
│   ├── Card/           root + Header/Body/Footer sub-components
│   ├── Input/          forwardRef + label + helperText
│   └── Icon/           lucide (line) + carbon (fill) wrappers
├── layouts/           # astro layouts
│   ├── BaseLayout.astro   google fonts + global css
│   └── DocsLayout.astro   sidebar nav (foundations/components/patterns)
├── pages/             # astro pages
│   ├── index.astro        home hub
│   ├── foundations/       colors, typography, spacing, iconography
│   ├── components/        button, card, input (+ planned)
│   └── patterns/          signup, layout, navigation, data-viz
└── styles/
    └── global.css     base styles + token import

design tokens

all tokens live in src/tokens/tokens.css as css custom properties:

category prefix examples
colors --color- --color-brand-600, --color-neutral-500
typography --text- --text-hero, --text-body, --text-ui
spacing --space- --space-xs through --space-3xl
radius --radius- --radius-none through --radius-full
shadow --shadow- --shadow-sm through --shadow-xl
size --size- --size-icon-md, --size-btn-md, --size-input-md
opacity --opacity- --opacity-disabled, --opacity-hover
z-index --z- --z-dropdown through --z-tooltip
icon --icon- --icon-stroke
component --btn-, --card-, --input- component-level tokens

how to add a component

  1. create src/components/<Name>/ directory
  2. name.css — styles using only design tokens
  3. Name.tsx — react component with typescript
  4. Name.stories.tsx — storybook stories with autodocs + interaction test
  5. npm run build-storybook — verify
  6. src/pages/components/name.astro — astro documentation page
  7. update DocsLayout.astro sidebar
  8. npm run build — verify

how to add a token

  1. change it in figma first (the source of truth)
  2. update src/tokens/tokens.css to match
  3. update src/tokens/tokens.js to match
  4. verify: npm run build && npm run build-storybook

figma

  • file: OAinJNCk0DZ1p1R1xyPfvx
  • publish: assets panel (alt+2) → book icon → publish library → tick variables, text styles, effect styles
  • use in other files: assets → libraries → enable "1thay"
  • collections: Primitives, Color (Light/Dark), Spacing, Radius, Size, Opacity, Z-Index, Typography

commands

npm run dev              # astro dev server
npm run build            # astro production build → dist/
npm run storybook        # storybook dev server (port 6006)
npm run build-storybook  # storybook build → dist-storybook/
npm run lint             # astro type check

deploy

  • 1thay.com: cloudflare pages → github kien-day/1thay-com → framework: astro → dist/
  • design.1thay.com: cloudflare pages → github kien-day/1thay-com → npm run build-storybookdist-storybook/
  • auto-deploy on push to main

naming conventions

  • files/folders: kebab-case (button-primary.astro, brand-colors.css)
  • components: PascalCase (Button, Input, DocsLayout)
  • tokens: --category-property-variant (--color-brand-600, --space-md)
  • figma variables: category/name (blue-reputa/600, spacing/md)
  • figma pages: ◆ name for docs, ◇ name for components
  • no abbreviations unless industry standard (ui, btn, sm/md/lg)

brands

  • blue-reputa (default) — from #064BAE
  • red-premier — from #A10B2E
  • switch via data-brand="red-premier" attribute