Chuyển tới nội dung chính
Version: 4.1

Hệ thống thiết kế

Panel người dùng (cổng 2083) và panel quản trị (cổng 2087) dùng chung một hệ thống thiết kế: một bộ token (CSS custom property) và một bộ component (class CSS) chỉ được xây dựng từ các token đó. Nó tồn tại để một nút, một bảng hay một modal trông và hoạt động giống nhau trên mọi trang của cả hai panel, ở chế độ sáng và tối và trong mọi giao diện panel.

Panel người dùngPanel quản trị
Tệphitechcloudpanel/static/css/design-system/hitechcloudadmin/static/css/design-system/
Được liên kết từinternal/web/templates/base.htmlinternal/webtemplates/_layout.html
URL/static/css/design-system/index.css/static/css/design-system/index.css

Ba tệp này giống hệt nhau từng byte ở cả hai kho. Hãy thay đổi chúng ở cả hai, trong cùng một thay đổi.

TệpNội dung
index.cssĐiểm vào: import hai tệp bên dưới. Đây là tệp duy nhất mà layout liên kết tới.
tokens.cssMọi custom property --ds-*, giá trị sáng trên :root, giá trị tối trên .dark.
components.cssMọi class ds-*, bên trong layer components của Tailwind.

Nguyên tắc​

  • Doanh nghiệp và giản dị. Màu phẳng, viền mảnh, bóng đổ trung tính nhẹ. Không pha trộn màu, không neon hay phát sáng, không làm mờ trong suốt ("glassmorphism"), không chuyển động trang trí.
  • Chỉ dùng token. Một component không bao giờ ghi trực tiếp một giá trị màu, kích thước hay thời lượng; nó đọc một token. Thay đổi một token sẽ thay đổi mọi component.
  • Tự chọn dùng, không hồi quy. Mọi class bắt đầu bằng ds-, và không gì trong các tệp khớp với phần tử hay class mà một trang đang dùng. Liên kết stylesheet không thay đổi trang hiện có nào; một trang áp dụng hệ thống bằng cách dùng các class.
  • Một component, một class. Biến thể là modifier (ds-btn--danger), các phần là con (ds-modal__footer). Đừng tạo nút, thẻ hay huy hiệu thứ hai: hãy mở rộng cái hiện có bằng một modifier.
  • Utility vẫn thắng. Các component nằm trong cascade layer components mà output.css của Tailwind khai báo (nó được tải trước), nên một utility trên cùng phần tử sẽ ghi đè chúng: class="ds-btn w-full" là một nút rộng toàn phần.
  • Sẵn sàng cho chiều phải sang trái. Component dùng logical property (inline-start/inline-end), nên trang có dir="rtl" tự lật mà không cần thêm quy tắc.
  • Dễ tiếp cận theo mặc định. Token văn bản giữ độ tương phản tối thiểu 4.5:1 trên các bề mặt mà chúng được dùng; mọi component tương tác đều có vòng :focus-visible nhìn thấy được; trạng thái được đọc từ thuộc tính ARIA nếu có.

Chế độ tối và giao diện panel​

Chế độ tối là class .dark trên <html>, công tắc mà cả hai panel đã dùng. Mọi token màu đều có giá trị tối.

Các giao diện panel (data-theme-brand trên <html>: mặc định, kiểu cPanel, kiểu DirectAdmin, kiểu Plesk, HiTechCloud 2) công bố màu của chúng dưới dạng thuộc tính --tb-* trong brand-themes.css (panel người dùng) và themes.css (panel quản trị). Các token thiết kế phụ thuộc thương hiệu đọc chúng trước và quay về diện mạo mặc định:

--ds-color-primary: var(--tb-primary, #2563eb);
--ds-surface: var(--tb-card, #ffffff);
--ds-surface-sidebar: var(--tb-sidebar, #ffffff);

Vì vậy ds-btn--primary có màu cam trong kiểu cPanel và màu xanh trong kiểu DirectAdmin mà không cần quy tắc riêng cho từng giao diện. Giao diện mới chỉ cần định nghĩa các token --tb-* của mình.

Token​

Kiểu chữ​

Bộ font là bộ font giao diện hệ thống và monospace: không tải web font nào.

TokenGiá trịDùng cho
--ds-font-sansbộ font giao diện hệ thốngMọi văn bản
--ds-font-monobộ font monospace hệ thốngĐường dẫn, khoá, mã, nhật ký
--ds-text-2xs11pxOverline, chú thích dày đặc
--ds-text-xs12pxVăn bản trợ giúp, huy hiệu, header bảng
--ds-text-sm13pxÔ bảng, văn bản phụ
--ds-text-base14pxVăn bản thân và điều khiển
--ds-text-md16pxTiêu đề thẻ, văn bản dẫn
--ds-text-lg18pxTiêu đề mục
--ds-text-xl20pxTiêu đề modal
--ds-text-2xl24pxTiêu đề trang
--ds-text-3xl30pxSố liệu trên bảng điều khiển
--ds-leading-tight / -snug / -normal1.25 / 1.375 / 1.5Tiêu đề / nhãn / thân
--ds-weight-regular … -bold400, 500, 600, 700
--ds-tracking-tight / -normal / -wide-0.01em / 0 / 0.04emTiêu đề lớn / thân / nhãn viết hoa

Class văn bản: ds-h1 … ds-h4, ds-body, ds-small, ds-caption, ds-overline, ds-mono, ds-link.

Màu sắc​

Token ngữ nghĩa; hãy dùng chúng, không dùng dải xám thô (--ds-gray-0 … --ds-gray-950), trong component.

TokenSángTốiDùng cho
--ds-color-primarymàu chính của giao diện, nếu không thì #2563ebmàu chính của giao diện, nếu không thì #2563ebNút chính, trạng thái được chọn, dấu đang hoạt động
--ds-color-primary-hover / -active#1d4ed8 / #1e40afnhư trên
--ds-color-primary-subtle (+ -border, -text)màu chính ở 8% trên bề mặtmàu chính ở 22%Hàng và tuỳ chọn được chọn, huy hiệu chính; một sắc phẳng, nên đi theo giao diện
--ds-color-on-primary#ffffff#ffffffVăn bản trên nền màu chính (5.2:1)
--ds-color-linkmàu liên kết của giao diện, nếu không thì #1d4ed8màu liên kết của giao diện, nếu không thì #93c5fdLiên kết, văn bản tab đang hoạt động
--ds-surface-pagemàu trang của giao diện, nếu không thì #f8fafc#0b1120Nền trang
--ds-surfacemàu thẻ của giao diện, nếu không thì #ffffff#111827Thẻ, ô nhập, bảng
--ds-surface-raised#ffffff#1f2937Menu, modal, toast
--ds-surface-sunken#f1f5f9#0f172aHeader bảng, chân, vùng lõm
--ds-surface-hover / -selected / -disabledNền tương tác
--ds-surface-inverse#1e293b#f1f5f9Tooltip
--ds-surface-overlayslate ở 50%gần đen ở 70%Nền phủ của modal và drawer
--ds-surface-header / -sidebarthanh trên / thanh bên của giao diệnKhung giao diện
--ds-text#0f172a (17.9:1)#f1f5f9 (16.2:1)Văn bản chính
--ds-text-secondary#475569#cbd5e1Văn bản phụ
--ds-text-muted#586579 (5.4:1 trên bề mặt lõm)#94a3b8Văn bản trợ giúp, chú thích
--ds-text-disabled#94a3b8#64748bChỉ cho điều khiển bị vô hiệu
--ds-bordermàu viền của giao diện, nếu không thì #e2e8f0#1f2937Đường kẻ thẻ và bảng
--ds-border-strong / -hover#cbd5e1 / #94a3b8#374151 / #4b5563Viền điều khiển
--ds-focus-color, --ds-focus-ringmàu chínhmàu liên kết sáng hơnVòng focus: khoảng hở 2px + vòng 2px

Mỗi màu trạng thái có bốn phần: màu đặc (biểu tượng, viền, nền), màu văn bản giữ 4.5:1 trên bề mặt nhạt tương ứng và trên nền trắng, một bề mặt nhạt và một viền nhạt.

Trạng tháiĐặcVăn bảnNhạtViền
success--ds-success--ds-success-text--ds-success-subtle--ds-success-border
warning--ds-warning--ds-warning-text--ds-warning-subtle--ds-warning-border
danger--ds-danger (+ -hover, -active)--ds-danger-text--ds-danger-subtle--ds-danger-border
info--ds-info--ds-info-text--ds-info-subtle--ds-info-border
neutral--ds-neutral--ds-neutral-text--ds-neutral-subtle--ds-neutral-border

Đừng bao giờ dùng màu làm tín hiệu duy nhất: huy hiệu trạng thái giữ chữ của nó, lỗi giữ thông báo của nó.

Biểu đồ: --ds-chart-1 … --ds-chart-8 là các chuỗi phân loại, theo thứ tự (xanh dương, xanh mòng két, hổ phách, tím, hồng, xanh lá, lục lam, slate), với giá trị sáng hơn ở chế độ tối; --ds-chart-grid và --ds-chart-axis tô màu khung biểu đồ. Biểu đồ một chuỗi dùng --ds-chart-1.

Khoảng cách​

Lưới 4px: --ds-space-0, -px, -0-5 (2px), -1 (4px), -1-5 (6px), -2 (8px), -3 (12px), -4 (16px), -5 (20px), -6 (24px), -8 (32px), -10 (40px), -12 (48px), -16 (64px).

Chiều cao điều khiển giúp mọi component dạng ô nhập thẳng hàng trên một dòng: --ds-control-sm 32px, --ds-control-md 38px (mặc định), --ds-control-lg 44px (cũng là vùng chạm tối thiểu).

Bo góc​

TokenGiá trịDùng cho
--ds-radius-none0
--ds-radius-sm4pxCheckbox, huy hiệu nhỏ
--ds-radius-md6pxNút, ô nhập, mục menu
--ds-radius-lg8pxThẻ, menu, toast, bảng
--ds-radius-xl12pxModal
--ds-radius-fullviên thuốcHuy hiệu, công tắc, spinner

Bóng đổ​

Nhẹ, trung tính và chỉ để thể hiện độ nổi: --ds-shadow-xs (điều khiển, thẻ), -sm (thẻ khi di chuột), -md (tooltip), -lg (menu, toast), -xl (modal, drawer), -none. Chế độ tối dùng bóng đậm và dày hơn.

Z-index​

TokenGiá trịLớp
--ds-z-base0
--ds-z-raised10Mục đang focus nằm trên các mục bên cạnh
--ds-z-sticky20Header bảng dính, thao tác biểu mẫu dính
--ds-z-header40Header trang
--ds-z-sidebar45Thanh bên
--ds-z-dropdown1000Menu, listbox
--ds-z-drawer1100Drawer
--ds-z-modal-backdrop / --ds-z-modal1200 / 1210Modal
--ds-z-popover1300Popover nằm trên modal
--ds-z-tooltip1400Tooltip
--ds-z-toast1500Toast, luôn nằm trên cùng

Các giá trị lớp phủ nằm trên khung giao diện hiện có (Tailwind z-50), nên một modal của hệ thống thiết kế che được thanh bên và header hiện tại.

Chuyển động​

TokenGiá trịDùng cho
--ds-duration-fast120msDi chuột, focus, màu
--ds-duration-base200msMenu, tooltip, công tắc
--ds-duration-slow300msModal, drawer
--ds-ease-standard / -enter / -exitđường cong cubic-bezierDi chuyển / xuất hiện / rời đi

Với prefers-reduced-motion: reduce, mọi thời lượng trở thành 0, skeleton ngừng nhấp nháy, và spinner vẫn quay (vì chúng mang ý nghĩa) ở nửa tốc độ.

Trạng thái​

Mọi component thể hiện trạng thái theo cùng một cách. Hãy ưu tiên thuộc tính ARIA: nó vừa tạo kiểu cho component vừa báo cho công nghệ hỗ trợ cùng lúc.

Trạng tháiSelectorGhi chú
Mặc địnhclass trần
Di chuột:hoverChỉ component tương tác
Focus:focus-visible--ds-focus-ring; không bao giờ bỏ nó
Đang hoạt động:active; lâu dài: aria-selected, aria-current, aria-pressed, aria-expanded, .is-active
Bị vô hiệu:disabled, aria-disabled="true", .is-disabledDùng --ds-text-disabled / --ds-surface-disabled; con trỏ not-allowed
Đang tảiaria-busy="true", .is-loadingMột spinner hoặc nhấp nháy; chặn tương tác
Lỗiaria-invalid="true", .is-errorViền/màu danger; đi kèm một thông báo
Thành công.is-successViền/màu success

Component​

Mỗi mục liệt kê các class và markup cần dùng. Chú thích phía trên mỗi phần của components.css lặp lại markup đó.

Nút​

<button class="ds-btn ds-btn--primary">Save</button>
<button class="ds-btn">Cancel</button>
<button class="ds-btn ds-btn--danger">Delete</button>
<button class="ds-btn ds-btn--ghost ds-btn--icon" aria-label="Refresh"><i class="bi bi-arrow-clockwise"></i></button>
<button class="ds-btn ds-btn--primary" aria-busy="true" disabled>Saving</button>

Biến thể --primary (một nút cho mỗi màn hình), --secondary (diện mạo mặc định), --ghost, --danger, --link; kích thước --sm, --lg; --icon (vuông, cần aria-label), --block (rộng toàn phần). Gom nhóm bằng ds-btn-group. Khi đang tải, nút giữ độ rộng của nhãn và vẽ spinner đè lên; kết hợp với disabled để thao tác không thể chạy hai lần.

Ô nhập và textarea​

<input class="ds-input" type="text">
<textarea class="ds-input ds-textarea"></textarea>
<div class="ds-input-group"><span class="ds-input-group__addon">https://</span><input class="ds-input"></div>
<div class="ds-input-wrap" aria-busy="true"><input class="ds-input"></div>

Kích thước --sm, --lg; --mono cho đường dẫn và khoá. Ô nhập chỉ đọc dùng bề mặt lõm. Lỗi: aria-invalid="true". Đang tải: bọc trong ds-input-wrap với aria-busy.

Select​

<div class="ds-select"><select>...</select></div>

Phần bọc vẽ mũi tên (không dùng hình ảnh), nên nó theo màu văn bản trong mọi giao diện. Trạng thái đặt trên select (disabled, aria-invalid) hoặc phần bọc (.is-error, .is-loading).

Combobox​

<div class="ds-combobox">
<input class="ds-input" role="combobox" aria-expanded="true" aria-controls="lb" aria-activedescendant="o2">
<ul class="ds-listbox" role="listbox" id="lb">
<li class="ds-option" role="option" id="o1">example.com</li>
<li class="ds-option is-active" role="option" id="o2" aria-selected="true">example.net</li>
</ul>
</div>

Listbox hiển thị khi ô nhập có aria-expanded="true". .is-active là tuỳ chọn đang được tô sáng bằng bàn phím; aria-selected là tuỳ chọn đã chọn. ds-listbox__empty / __status cho "không khớp" và "đang tìm". Listbox có thể dùng lại độc lập (cho tự động hoàn thành dưới bất kỳ trường nào).

Checkbox và radio​

<label class="ds-check"><input type="checkbox" class="ds-checkbox"> Enable backups</label>
<label class="ds-check"><input type="radio" class="ds-radio" name="php"> PHP 8.3</label>

Checkbox trạng thái không xác định được vẽ (input.indeterminate = true). Một ds-check__hint dưới nhãn thêm phần mô tả. Gom chúng trong một ds-fieldset có legend.

Công tắc​

<label class="ds-check"><input type="checkbox" role="switch" class="ds-switch"> Force HTTPS</label>

Công tắc áp dụng ngay lập tức; hãy dùng checkbox khi lựa chọn được lưu cùng một biểu mẫu. Trong lúc thay đổi đang được áp dụng, đặt aria-busy="true".

Tab​

<div class="ds-tabs" role="tablist">
<button class="ds-tab" role="tab" aria-selected="true">General</button>
<button class="ds-tab" role="tab" aria-selected="false">Logs <span class="ds-tab__count">3</span></button>
</div>

Liên kết dùng làm tab dùng aria-current="page". ds-tabs--pills cho diện mạo phân đoạn dùng cho bộ lọc.

<div class="ds-dropdown ds-dropdown--end">
<button class="ds-btn" aria-haspopup="menu" aria-expanded="false">Actions</button>
<div class="ds-menu" role="menu">
<p class="ds-menu__label">Site</p>
<button class="ds-menu__item" role="menuitem">Edit</button>
<div class="ds-menu__separator" role="separator"></div>
<button class="ds-menu__item ds-menu__item--danger" role="menuitem">Delete</button>
</div>
</div>

Menu hiển thị khi phần tử kích hoạt có aria-expanded="true" (hoặc dropdown có .is-open).

<div class="ds-modal-backdrop">
<div class="ds-modal" role="dialog" aria-modal="true" aria-labelledby="t">
<div class="ds-modal__header"><h2 class="ds-modal__title" id="t">Delete site</h2></div>
<div class="ds-modal__body">...</div>
<div class="ds-modal__footer">
<button class="ds-btn">Cancel</button>
<button class="ds-btn ds-btn--danger">Delete</button>
</div>
</div>
</div>

Ẩn bằng thuộc tính hidden trên nền phủ. Một <dialog class="ds-modal"> gốc mở bằng showModal() cũng hoạt động. Kích thước --sm, --lg, --xl; --danger cho xác nhận mang tính phá huỷ. Nút ở chân: thao tác chính đặt cuối cùng.

Drawer​

<div class="ds-modal-backdrop ds-drawer-backdrop">
<aside class="ds-drawer" role="dialog" aria-modal="true">header / body / footer as the modal</aside>
</div>

Mở từ phía inline end; ds-drawer--start mở từ phía inline start, --lg rộng hơn. Nó dùng lại các phần header, body và footer của modal.

Tooltip​

<span class="ds-tooltip-wrap">
<button class="ds-btn ds-btn--ghost ds-btn--icon" aria-label="Help" aria-describedby="tt"><i class="bi bi-question-circle"></i></button>
<span class="ds-tooltip" role="tooltip" id="tt">Shown on hover and on keyboard focus</span>
</span>

--bottom đặt nó ở bên dưới. Đừng bao giờ đặt bản duy nhất của thông tin quan trọng trong tooltip.

Toast​

<div class="ds-toast-region" aria-live="polite">
<div class="ds-toast ds-toast--success" role="status">
<div class="ds-toast__body"><p class="ds-toast__title">Saved</p><p class="ds-toast__text">The site configuration was updated.</p></div>
</div>
</div>

Biến thể --info, --success, --warning, --danger (dùng role="alert"), --loading (spinner). Toast dành cho thông báo thoáng qua; thông báo cần ở lại trên trang là một alert.

Alert​

<div class="ds-alert ds-alert--warning" role="alert">
<div class="ds-alert__body"><p class="ds-alert__title">Certificate expires in 5 days</p><p>Renew it from SSL.</p></div>
</div>

Biến thể --info, --success, --warning, --danger; ds-alert__actions cho các nút bên trong.

Huy hiệu​

<span class="ds-badge ds-badge--success ds-badge--dot">Running</span>

Biến thể --primary, --info, --success, --warning, --danger; --square, --dot. Huy hiệu là liên kết hoặc nút sẽ có trạng thái di chuột và focus.

Thẻ​

<section class="ds-card">
<header class="ds-card__header"><h3 class="ds-card__title">Disk</h3></header>
<div class="ds-card__body">...</div>
<footer class="ds-card__footer">...</footer>
</section>

a.ds-card hoặc ds-card--interactive là liên kết toàn thẻ có trạng thái di chuột, focus và active. ds-card__body--flush cho bảng chạy sát mép thẻ. ds-stat (__label, __value, __meta) bên trong thẻ là một số liệu bảng điều khiển.

Bảng​

<div class="ds-table-wrap">
<table class="ds-table">
<thead><tr><th aria-sort="ascending"><button class="ds-table__sort">Domain</button></th><th class="ds-num">Size</th></tr></thead>
<tbody><tr aria-selected="true"><td>example.com</td><td class="ds-num">1.2 GB</td></tr></tbody>
</table>
</div>

Phần bọc cuộn ngang thay vì làm rộng trang; header dính lại. --compact, --striped; ds-num căn phải số liệu, ds-actions cho các thao tác của hàng. Trống: một hàng có ô ds-table__empty chứa một ds-empty ds-empty--compact. Đang tải: aria-busy trên bảng, hoặc các hàng skeleton.

Phân trang​

<nav class="ds-pagination" aria-label="Pagination">
<span class="ds-pagination__info">1-20 of 312</span>
<a class="ds-page" href="?p=1" aria-label="Previous">&lsaquo;</a>
<a class="ds-page" aria-current="page">2</a>
<span class="ds-page ds-page--gap">&hellip;</span>
</nav>
<nav class="ds-breadcrumb" aria-label="Breadcrumb">
<ol><li><a href="/">Home</a></li><li><a href="/sites">Sites</a></li><li><a aria-current="page">example.com</a></li></ol>
</nav>

Dấu phân cách được vẽ và tự lật trên trang chiều phải sang trái.

<nav class="ds-sidebar" aria-label="Main">
<p class="ds-sidebar__section">Websites</p>
<a class="ds-nav-item" href="/sites" aria-current="page"><i class="bi bi-globe"></i><span>Sites</span></a>
</nav>
<header class="ds-header">
<div class="ds-header__start">...</div>
<div class="ds-header__end">...</div>
</header>

Cả hai đọc token thanh bên và thanh trên của giao diện (--tb-sidebar*, --tb-topbar*), nên thanh bên màu xanh navy đậm của một giao diện không cần quy tắc thêm. Hàng tiêu đề riêng của một trang là ds-page-header (__title, __text, __actions).

Biểu mẫu​

<form class="ds-form">
<div class="ds-field is-error">
<label class="ds-label" for="d">Domain <span class="ds-required" aria-hidden="true">*</span></label>
<input class="ds-input" id="d" aria-invalid="true" aria-describedby="d-help d-err">
<p class="ds-help" id="d-help">Without www.</p>
<p class="ds-field__error" id="d-err">This domain is already in use.</p>
</div>
<div class="ds-form__actions"><button class="ds-btn ds-btn--primary">Add</button></div>
</form>

ds-form__row xếp các trường cạnh nhau và xuống dòng trên màn hình hẹp; ds-form__section gom chúng dưới một ds-form__section-title; ds-form__actions--sticky giữ các thao tác luôn hiển thị trên biểu mẫu dài. Trường sở hữu trạng thái của nó: .is-error hiển thị ds-field__error và tô màu điều khiển, .is-success hiển thị ds-field__success. Biểu mẫu đang bận (aria-busy) chặn các trường của nó.

Tải tệp lên​

<label class="ds-dropzone">
<input type="file" class="ds-visually-hidden" multiple>
<span class="ds-dropzone__title">Drop files or <span class="ds-link">browse</span></span>
<span class="ds-dropzone__hint">Up to 50 MB each</span>
</label>
<ul class="ds-file-list">
<li class="ds-file"><span class="ds-file__name">backup.tar.gz</span><span class="ds-file__meta">42%</span>
<div class="ds-progress"><div class="ds-progress__bar" style="width:42%"></div></div></li>
</ul>

Script thêm .is-dragover khi một tệp được giữ trên vùng thả. Mỗi hàng tệp nhận .is-error / .is-success.

Biểu đồ​

<figure class="ds-chart">
<figcaption class="ds-chart__header">
<span class="ds-chart__title">CPU</span>
<ul class="ds-legend"><li><span class="ds-legend__swatch" style="--_c: var(--ds-chart-1)"></span>Used</li></ul>
</figcaption>
<div class="ds-chart__canvas"><canvas></canvas></div>
</figure>

Thư viện biểu đồ lấy màu từ các token lúc vẽ, ví dụ getComputedStyle(document.documentElement).getPropertyValue('--ds-chart-1'), và vẽ lại khi .dark thay đổi. Trạng thái: aria-busy (khung giữ chỗ nhấp nháy), .is-empty, .is-error. Mục chú giải bật/tắt một chuỗi là button.ds-legend__item với aria-pressed.

Đang tải​

ds-spinner (--sm, --lg, với role="status" và một aria-label); ds-progress với ds-progress__bar (role="progressbar" và aria-valuenow), .is-indeterminate khi chưa biết mức độ, .is-success / .is-error / --warning; ds-loading-overlay phủ một container đã định vị.

Skeleton​

ds-skeleton với --text, --title, --circle, --block: các hình xám chỉ nhấp nháy độ mờ, thay thế cho nội dung đang tải. Trong lúc đó, đánh dấu container bằng aria-busy="true".

Trạng thái trống​

<div class="ds-empty">
<div class="ds-empty__icon"><i class="bi bi-globe"></i></div>
<h3 class="ds-empty__title">No sites yet</h3>
<p class="ds-empty__text">Add a site to start serving it.</p>
<div class="ds-empty__actions"><a class="ds-btn ds-btn--primary" href="/sites/new">Add site</a></div>
</div>

--compact bên trong thẻ và bảng; .is-error cho "không tải được".

Áp dụng hệ thống trên một trang​

  1. Dùng các class ds-* trong template; giữ utility của Tailwind cho bố cục (grid, flex, margin).
  2. Thay điều khiển tự viết của trang bằng component, không phải bằng một bản sao của nó. Nếu component còn thiếu gì đó, hãy thêm một modifier vào components.css ở cả hai panel.
  3. Trang có đầu ra thay đổi có chủ ý thì chụp lại golden của nó (hitechcloudpanel/engine/tests/goldens/legacy, TZ=UTC, xem engine/tests/goldens.rs); hãy nói rõ trong pull request.

Thay đổi hệ thống​

  • Thêm hoặc đổi một token trong tokens.css, kèm giá trị tối của nó, và kiểm tra độ tương phản của mọi token văn bản với các bề mặt mà nó được dùng.
  • Giữ components.css không có giá trị màu trực tiếp, pha trộn màu và làm mờ.
  • Sao chép các tệp đã thay đổi sang panel kia trong cùng thay đổi; hai bản sao phải giống hệt nhau.
  • Cập nhật trang này.
Trang này có hữu ích không?