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 địnhred-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