Kiểu chữ

Inter là kiểu chữ duy nhất trên mọi bề mặt Comitor. Gói không kèm file font nào — app tự nạp Inter qua next/font/google với các độ đậm 400–800 và bộ ký tự tiếng Việt, rồi công bố nó thành --font-inter.

Font được nối vào thế nào

Hai nửa phải khớp nhau: app khai font và đặt tên biến, gói đọc biến đó trong khối @theme của nó. Thiếu nửa phía app thì lỗi xảy ra lặng lẽ chứ không ồn ào: var(--font-inter) không có giá trị dự phòng, nên cả khai báo thành không hợp lệ lúc tính giá trị và chữ thừa hưởng font mặc định của trình duyệt — phần đuôi "Inter", system-ui, sans-serif viết sau nó không bao giờ tới lượt. Đặt biến này là bắt buộc.

app/layout.tsx
// app/layout.tsx — the APP loads Inter and publishes it as --font-inter.
// The package never bundles a font; it only consumes the variable.
import { Inter } from 'next/font/google'

const inter = Inter({
  subsets: ['latin', 'vietnamese'],
  weight: ['400', '500', '600', '700', '800'],
  display: 'swap',
  variable: '--font-inter',
})

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className={`${inter.variable} font-sans antialiased`}>{children}</body>
    </html>
  )
}
css
/* @comitor/ui/styles.css — the two lines the package actually ships */
@theme inline {
  --font-sans: var(--font-inter), "Inter", system-ui, sans-serif;
  --font-mono: var(--font-inter-mono, "Geist Mono"), ui-monospace, monospace;
}
BiếnAi đặtNếu thiếu
--font-interApp, như trên. Bắt buộc — gói mặc định là có nó.var() không có giá trị dự phòng, nên --font-sans không hợp lệ lúc tính giá trị và font-sans thừa hưởng font mặc định của trình duyệt. Danh sách sau nó không bao giờ được dùng tới.
--font-inter-monoApp, tuỳ chọn. Đổi font đơn cách mà Kbd và tooltip của biểu đồ dùng.--font-mono lùi về "Geist Mono", ui-monospace, monospace.

Giá trị dự phòng của font đơn cách được viết bên trong var(--font-inter-mono, "Geist Mono") chứ không viết sau nó trong danh sách, và đó là cố ý: một var() không có dự phòng trỏ vào một biến chưa khai báo làm cả khai báo không hợp lệ lúc tính giá trị, nên font-mono sẽ thừa hưởng font xung quanh thay vì đi tiếp xuống danh sách. Gần như không app nào đặt --font-inter-mono, nên nó có dự phòng ngay trong var; còn --font-inter thì app nào cũng phải đặt, vì vậy dòng sans không kèm dự phòng.

Thang chữ — mẫu trực tiếp

Design system · v1.0

text-xs font-bold tracking-[0.18em] uppercase

Comitor ships a single typeface — Inter — across every product surface. Generous line height ensures readability in dense admin UIs and marketing copy alike.

text-base leading-relaxed

The quick brown fox jumps over the lazy dog.

text-xl md:text-2xl font-semibold

The quick brown fox jumps over the lazy dog.

text-3xl md:text-4xl font-bold tracking-tight

The quick brown fox jumps over the lazy dog.

text-5xl md:text-6xl font-extrabold tracking-tight

Bảng thang chữ

Các bậc dưới đây là thang có sẵn của Tailwind. Gói cố ý không khai lại --text-* trong khối @theme của nó — không có thang chữ Comitor nào phải học thêm ngoài thang của Tailwind. Thứ gói nắm thay vào đó là cỡ chữ gốc, ở mục kế tiếp.

TênClass TailwindCỡChiều cao dòngDùng cho
Eyebrowtext-xs font-bold tracking-[0.18em] uppercase12px16px · 1.333Nhãn mục, thẻ chip
Bodytext-base leading-relaxed16px1.625 (leading-relaxed)Văn bản, mô tả, nhãn
H3text-xl md:text-2xl font-semibold20–24px28–32px · 1.4 / 1.333Tiêu đề thẻ, mục con
H2text-3xl md:text-4xl font-bold tracking-tight30–36px36–40px · 1.2 / 1.111Tiêu đề mục của trang
Display H1text-5xl md:text-6xl font-extrabold tracking-tight48–60px1Tiêu đề hero, trang giới thiệu

Các cỡ là giá trị ở bậc cỡ chữ mặc định. Vì cả thang viết bằng rem, mọi con số ở đây đổi theo khi người dùng đổi cỡ chữ.

Cỡ chữ là cài đặt của người dùng

Một trong năm trục hiển thị gói cung cấp. Nó co giãn cỡ chữ gốc, không phải thang chữ — nên icon và chiều cao control, vốn lấy cỡ từ thang khoảng cách bằng rem, to ra và nhỏ lại cùng nhịp với chữ, thay vì đứng yên trong khi nhãn quanh chúng đổi cỡ.

BậcSelectorKhai báoTác dụng
sm[data-font-size="sm"]font-size: 87.5%Gốc thu nhỏ; mọi giá trị rem theo sau.
md(không có thuộc tính)—Provider gỡ hẳn thuộc tính. Ở bậc này không gì trong gói chạm vào cỡ chữ gốc của trình duyệt.
lg[data-font-size="lg"]font-size: 112.5%Gốc phóng to; icon và chiều cao control to theo chữ.
trang cài đặt
'use client'

// The font-size axis is a user setting, wired once in the root layout with
// <FontSizeProvider> and exposed anywhere with <FontSizeControl>. Its group name
// and the three option labels follow ComitorLocaleProvider — Small / Medium /
// Large in English, Nhỏ / Vừa / Lớn under locale="vi". To reword, pass label
// and optionLabels (all three sizes at once).
import { FontSizeControl } from '@comitor/ui/shell'

export function DisplaySettings() {
  return <FontSizeControl />
}

Vì sao dùng phần trăm, và vì sao bậc mặc định không viết gì

Bậc nhỏ và bậc lớn viết bằng phần trăm của cỡ thừa hưởng, còn bậc vừa không sinh ra dòng CSS nào. Người đọc có thể đã tăng cỡ chữ mặc định của trình duyệt; khai một giá trị tuyệt đối font-size: 16px trên <html> sẽ xoá lựa chọn đó — vi phạm WCAG 1.4.4 ngay từ bên trong một tính năng trợ năng. Phần trăm là phần trăm của cỡ họ đã chọn, nên lựa chọn đó được giữ.

Quy tắc

Nên

  • Dùng thẳng thang của Tailwind — text-sm, text-base — và để cỡ chữ gốc lo phần tuỳ chọn của người dùng.
  • Nạp bộ ký tự vietnamese. Thiếu nó, dấu tiếng Việt rơi về font hệ thống ngay giữa chữ.
  • Dùng font-mono cho gợi ý phím tắt, mã và số liệu dạng bảng.

Không nên

  • Đừng thêm họ font thứ ba. Inter và font đơn cách tuỳ chọn đã đủ cho mọi nhu cầu.
  • Đừng để chữ nội dung nhỏ hơn 14px trên bất kỳ bề mặt sản phẩm nào.
  • Đừng đặt cỡ chữ gốc tuyệt đối — nó vô hiệu trục cỡ chữ và cả cài đặt riêng của người đọc.
  • Đừng khai lại --text-* trong app. Thang là của Tailwind và gói dựa vào đó.