GL Connect
Design System
Hệ thống thiết kế bilingual (Tiếng Việt/English), token-based, kết hợp GL Connect homebuying portal, GL Lifestyle resident app và các trang landing chiến dịch — đảm bảo trải nghiệm nhất quán, accessible trên web, iOS và Android.
Color Tokens
Forest green là màu accent chính — ánh xạ trực tiếp đến triết lý biophilic design của Gamuda: Yen So Park, hành lang xanh, không gian sống kết nối thiên nhiên. Ấm và cao cấp trong thị trường bất động sản Việt Nam, tránh xung đột ngữ nghĩa với màu đỏ dùng cho trạng thái lỗi và badge đã bán.
| Token | Value | Usage |
|---|---|---|
--color-bg |
--sand-50 |
Background canvas chính của trang |
--color-surface |
#FFFFFF |
Card, modal, panel surface |
--color-text-primary |
--ink-900 |
Heading, label, primary text |
--color-text-muted |
--ink-500 |
Body copy, placeholder, secondary info |
--color-accent |
--green |
CTA, links, active states, badges |
--color-border |
--sand-200 |
Input borders, dividers, card outlines |
--error |
#B91C1C |
Validation errors, destructive actions |
--warning |
#C4751A |
Reserved status, cautionary messaging |
Status Badges
Typography
Font pairing gồm Lora (Lora serif cho heading và số display), Inter (body và UI), và JetBrains Mono (token names và code). Vietnamese font stack bao gồm Be Vietnam Pro fallback để tối ưu hiển thị dấu tiếng Việt.
--color-accent: var(--green)nơi mỗi gia đình tìm về."
Spacing
8pt grid — mọi khoảng cách đều là bội số của 4px. Tokens --sp-* áp dụng nhất quán cho padding, margin, gap trên tất cả components và layouts.
Buttons
Ba variants — Primary (gradient fill), Secondary (outline), Ghost (text). Mọi button đều có min-height 44px theo WCAG 2.5.8. Primary button có sheen animation ::before trên hover, không gây layout shift.
| Variant | Default | Hover | Focus | Disabled |
|---|---|---|---|---|
| Primary | --green-gradient-btn, white text | Sheen + lift -1px, stronger glow | outline 2px --green-mid +3px offset | opacity 0.45, no transform |
| Secondary | transparent, --ink-900 border | border → --green, text → --green | outline 2px --green-mid | opacity 0.45 |
| Ghost | transparent, --ink-500 text | text → --ink-900, underline --green | outline 2px --green-mid | opacity 0.45 |
<!-- Primary button --> <button class="btn btn-primary">Đặt cọc ngay</button> <!-- Secondary --> <button class="btn btn-secondary">Xem chi tiết</button> <!-- Ghost --> <button class="btn btn-ghost">Tìm hiểu thêm</button>
Cards
Property listing card với status badge, tên dự án, giá và CTA. Hover state: shadow-md + border shift — không dùng translate để giữ sự trang nhã. Featured card có --green-pale tint và accent top border.
<!-- Property card — semantic tokens only --> <article class="property-card"> <div class="card-image-placeholder"> <!-- Badge: icon + color + text (WCAG 1.4.1) --> <span class="status-badge badge-available" role="status"> <span aria-hidden="true">✓</span> Còn hàng </span> </div> <div class="card-body"> <span class="card-name">Celadon City T1</span> <span class="card-price">3.2 tỷ đồng</span> </div> </article>
Form Inputs
Tất cả input states: default, hover, focus, error, disabled. Focus ring dùng outline — không dùng box-shadow để tránh xung đột với existing shadows. Inline validation (không chờ submit) là yêu cầu bắt buộc cho AT users.
aria-invalid="true" + aria-describedby + role="alert" trên error message đảm bảo screen reader đọc lỗi ngay lập tức. Min-height 44px đáp ứng WCAG 2.5.8 Target Size.
Accessible Date Picker
div click handlers — 0% users dùng keyboard navigation hoàn thành reservation flow. Sau ARIA overhaul theo W3C Date Picker pattern (role="grid", gridcell, arrow key navigation, focus management): tỷ lệ tăng lên 83%. Component này là lý do tại sao accessibility không phải checkbox — nó là core functionality.
Demo đầy đủ keyboard navigation: phím mũi tên di chuyển giữa ngày, Enter để chọn, Escape để đóng. Focus quay về trigger button khi đóng.
<!-- W3C ARIA Date Picker pattern --> <button aria-haspopup="dialog" aria-expanded="false"> Chọn ngày </button> <div role="dialog" aria-modal="true" aria-label="Lịch chọn ngày"> <div role="grid" aria-label="Lịch ngày"> <div role="row"> <!-- Day cells --> <button role="gridcell" aria-label="15 tháng 4, 2025" aria-selected="false">15</button> </div> </div> <!-- Arrow keys: left/right (prev/next day) --> <!-- up/down (+/- 7 days) --> <!-- Enter: select · Escape: close+return --> </div>
Morning / Evening Theme
Data từ Hotjar cho thấy 41% homebuyers duyệt listing vào buổi tối (19h–23h). Evening mode không phải dark mode thẩm mỹ — đây là quyết định product dựa trên behavioral analytics. Màu midnight được thiết kế để giảm mỏi mắt trong điều kiện ánh sáng thấp, đồng thời giữ property imagery vẫn hấp dẫn.
4.8 tỷ đồng
4.8 tỷ đồng
// Auto time-of-day detection const hour = new Date().getHours(); if (hour >= 19 || hour < 7) { // Apply immediately — no transition on load document.body.classList.add('no-transition'); document.body.classList.add('evening-mode'); requestAnimationFrame(() => { document.body.classList.remove('no-transition'); }); }
Bilingual Support
Tiếng Việt và tiếng Anh được xử lý như hai ngôn ngữ đồng đẳng, không phải translation. Vietnamese copy được viết lại cho giọng văn chuyên nghiệp địa phương. html[lang] attribute là bắt buộc cho TalkBack/VoiceOver phát âm đúng.
lang attribute trên <html> là bắt buộc để TalkBack (Android) và VoiceOver (iOS) chọn đúng voice engine. Thiếu lang="vi", screen reader phát âm tiếng Việt theo quy tắc tiếng Anh — trải nghiệm hoàn toàn không dùng được cho người dùng khiếm thị. Đây là WCAG 3.1.1 Language of Page (Level A).
// Language switcher pattern function setLanguage(lang) { document.documentElement.setAttribute('lang', lang); // Update all [data-vi] / [data-en] elements document.querySelectorAll('[data-vi][data-en]') .forEach(el => { el.textContent = el.dataset[lang]; }); }