storybook github

version: "alpha" name: "1thay" description: "design system for saas dashboards & infographics — trăm nghe không bằng một thấy"

colors:

brand a: blue-reputa

blue-reputa-900: "#031f4a" blue-reputa-800: "#042e6e" blue-reputa-700: "#053c92" blue-reputa-600: "#064BAE" blue-reputa-400: "#5798e8"

brand b: red-premier

red-premier-900: "#4a0412" red-premier-800: "#6e081d" red-premier-700: "#920b28" red-premier-600: "#A10B2E" red-premier-400: "#e8576e"

neutral-gray surface palette

neutral-0: "#ffffff" neutral-50: "#f8fafc" neutral-100: "#f1f5f9" neutral-200: "#e2e8f0" neutral-300: "#cbd5e1" neutral-400: "#94a3b8" neutral-500: "#64748b" neutral-600: "#475569" neutral-700: "#334155" neutral-800: "#1e293b" neutral-900: "#0f172a" neutral-1000: "#020617"

semantic

success: "#16a34a" warning: "#d97706" error: "#dc2626" info: "#2563eb"

surface reference (alias to neutral)

surface-bg: "{colors.neutral-0}" surface-dim: "{colors.neutral-50}" surface-raised: "{colors.neutral-0}" surface-overlay: "{colors.neutral-800}"

text reference

text-primary: "{colors.neutral-900}" text-secondary: "{colors.neutral-500}" text-muted: "{colors.neutral-400}" text-inverse: "{colors.neutral-0}"

border reference

border-default: "{colors.neutral-200}" border-strong: "{colors.neutral-300}"

typography: display: fontFamily: "Hanken Grotesk" fontWeight: 700 lineHeight: 1.1 heading: fontFamily: "Hanken Grotesk" fontWeight: 600 lineHeight: 1.25 text: fontFamily: "Inter" fontWeight: 400 lineHeight: 1.6 ui: fontFamily: "Inter" fontWeight: 500 lineHeight: 1.4 content: fontFamily: "Merriweather" fontWeight: 400 lineHeight: 1.7 number: fontFamily: "Space Grotesk" fontWeight: 500 lineHeight: 1.3

rounded: none: "2px" sm: "4px" md: "8px" lg: "12px" xl: "16px" full: "9999px"

spacing: xs: 4 sm: 8 md: 16 lg: 24 xl: 32 "2xl": 48 "3xl": 64

components: button-primary: backgroundColor: "{colors.blue-reputa-600}" textColor: "{colors.neutral-0}" typography: "{typography.ui}" rounded: "{rounded.md}" padding: "{spacing.sm} {spacing.lg}" button-secondary: backgroundColor: "{colors.neutral-100}" textColor: "{colors.neutral-900}" typography: "{typography.ui}" rounded: "{rounded.md}" padding: "{spacing.sm} {spacing.lg}" card: backgroundColor: "{colors.surface-raised}" rounded: "{rounded.lg}" padding: "{spacing.lg}" input: backgroundColor: "{colors.surface-bg}" textColor: "{colors.text-primary}" typography: "{typography.ui}" rounded: "{rounded.md}" padding: "{spacing.sm} {spacing.md}"


overview

1thay là design system phục vụ saas dashboards và infographics. tên gọi bắt nguồn từ "trăm nghe không bằng một thấy" — đề cao trải nghiệm trực quan, khả năng đọc, và sự rõ ràng của thông tin.

hệ thống được thiết kế cho một người làm việc độc lập: designer kiêm developer, người cần một bộ công cụ nhất quán để nhanh chóng tạo ra giao diện chất lượng cao mà không cần đội ngũ lớn.

phạm vi: landing page, dashboard, documentation site, và prototype cho các sản phẩm saas.

colors

hệ thống màu gồm 3 tầng:

brand palettes — mỗi brand có 5 mức độ sáng/tối từ base color:

  • blue-reputa: phát triển từ #064BAE — mặc định
  • red-premier: phát triển từ #A10B2E

neutral-gray — dải màu từ trắng tới đen, dùng làm màu nền toàn bộ giao diện:

  • neutral-0 (trắng) → neutral-1000 (đen tuyệt đối)
  • kết hợp với opacity variants cho overlay, disabled states

semantic — màu theo ngữ nghĩa: success, warning, error, info

cách dùng:

  • màu nền: luôn dùng neutral palette, không dùng brand color làm nền chính
  • brand color: dùng cho điểm nhấn, nút chính, link, icon active
  • semantic color: dùng cho badge, alert, toast, form validation

typography

4 nhóm font cho 4 mục đích khác nhau:

nhóm font mục đích
display hanken grotesk hero, heading chính, số liệu lớn
text inter body text, label, input, ui element
content merriweather bài viết dài, tài liệu, mô tả
number space grotesk số liệu, bảng biểu, metric, dashboard

viết thường (lowercase) là phong cách mặc định cho toàn bộ văn bản giao diện, trừ tên riêng và nhãn hiệu.

layout

hệ thống layout dựa trên bento grid — lưới module chữ nhật với border radius đồng nhất.

  • grid: css grid 12 cột, gap dùng spacing tokens
  • container: max-width 1280px, padding 2 bên dùng spacing.lg
  • responsive breakpoints: mobile (< 768px), tablet (768-1024px), desktop (> 1024px)
  • spacing scale: 4 → 8 → 16 → 24 → 32 → 48 → 64 (dùng bội số của 4)

elevation & depth

hệ thống elevation dùng shadow và z-index để tạo chiều sâu:

mức shadow z-index dùng cho
0 none base (0) nội dung phẳng
1 sm dropdown (100) card resting
2 md sticky (200) dropdown, tooltip
3 lg overlay (300) sheet, drawer
4 xl modal (400) modal, dialog
5 toast (500) toast, notification
6 tooltip (600) tooltip

shapes

border radius scale:

token giá trị dùng cho
none 2px input, table, divider
sm 4px button nhỏ, badge, tag
md 8px button, input, card trong
lg 12px card, modal, panel
xl 16px card lớn, hero image
full 9999px pill, avatar, badge tròn

nguyên tắc: cùng một cấp độ phân cấp thị giác → cùng một radius.

components

component cốt lõi của hệ thống:

  • button: primary (brand-filled), secondary (neutral), ghost, destructive
  • card: container cơ bản cho nội dung, có variant flat / raised / bordered
  • input: text input, textarea, select, checkbox, radio, switch
  • table: data table với sort, filter, pagination
  • badge: trạng thái, tag, label
  • chart container: wrapper cho biểu đồ với title, legend, tooltip

mỗi component có ít nhất 2 size (sm | md | lg) và các state cần thiết (:hover, :focus-visible, [aria-disabled], [aria-invalid]).

do's and don'ts

màu sắc

  • nên: dùng neutral palette cho nền, brand color cho điểm nhấn
  • không nên: dùng brand color làm màu nền toàn trang
  • nên: kiểm tra contrast ratio trước khi merge
  • không nên: thêm màu mới mà không định nghĩa token

typography

  • nên: dùng đúng font family theo mục đích (display/text/content/number)
  • không nên: trộn font display cho body text
  • nên: giữ lowercase cho ui text, label, button
  • không nên: dùng uppercase như một phong cách

layout

  • nên: dùng spacing tokens, không hardcode giá trị px
  • không nên: tạo layout không theo bento grid
  • nên: test responsive trên cả 3 breakpoint trước khi merge

component

  • nên: dùng component token thay vì global token trong component
  • không nên: tạo variant mới khi chưa có trong design.md
  • nên: đảm bảo mọi interactive element có focus indicator