Skip to content

Design Tokens

The shared vocabulary between design (Figma), web (Next.js/CSS variables), and mobile (Flutter ThemeExtension). Tokens are the single source of truth: no raw hex values, pixel sizes, or durations in component code.

Status: proposal

All values below — especially color — are starting proposals pending the brand identity project. The structure and names are stable; the values may change. Build against the tokens, not the values.

Naming convention

--{category}-{concept}-{variant} in kebab-case. The same names map 1:1 to Flutter (YamTokens.colorPrimary500) and to the Tailwind theme config. Semantic tokens (e.g. --color-text-primary) reference primitive tokens (e.g. --color-neutral-900) — components consume semantic tokens wherever one exists, so dark mode is a semantic remap, not a component rewrite.

1. Color

Primitive palette

Primary — Yam3at Deep Purple (brand family; celebration-royal, distinct from delivery-app teal/orange clutter in the Kuwaiti market):

Token Hex Notes
--color-primary-50 #F5F2FB Tint backgrounds, selected-state washes
--color-primary-100 #E9E1F7 Hover washes, chips
--color-primary-200 #D3C3EF Borders of selected items
--color-primary-300 #B49BE3 Decorative, illustrations
--color-primary-400 #9370D4 Secondary emphasis
--color-primary-500 #7A4FC6 Brand mid — icons, accents
--color-primary-600 #6639B0 Primary action color (AA on white: 6.3:1)
--color-primary-700 #552E93 Hover/pressed of primary actions
--color-primary-800 #452676 Headers on light surfaces
--color-primary-900 #331C57 Deep brand, hero backgrounds

Accent — Celebration Gold (used sparingly: milestones, featured/premium markers):

Token Hex
--color-accent-100 #FBF0D9
--color-accent-400 #E3B04B
--color-accent-500 #D49A2E
--color-accent-700 #9C6F1C

Neutrals (slightly warm gray so photography-heavy screens don't feel clinical):

Token Hex Typical semantic use
--color-neutral-0 #FFFFFF Surfaces
--color-neutral-50 #FAF9FB App background
--color-neutral-100 #F2F0F4 Cards on background, input fills
--color-neutral-200 #E4E1E8 Dividers, borders
--color-neutral-400 #A9A3B2 Placeholders, disabled text
--color-neutral-600 #6E6879 Secondary text (AA on white)
--color-neutral-800 #3A3542 Primary text alt
--color-neutral-900 #231F29 Primary text

Semantic status (each with a -bg tint for badges/banners):

Token Hex -bg tint Used for
--color-success-600 / --color-success-bg #1E8E4E #E6F5EC Confirmed, Accepted, Completed, payment success
--color-warning-600 / --color-warning-bg #B4690E #FCF1E3 Pending, Negotiating, expiring soon
--color-error-600 / --color-error-bg #C6303E #FBE9EB Rejected, Cancelled, failed payment, validation errors
--color-info-600 / --color-info-bg #22679E #E7F1F9 Draft, informational banners, Quoted

Semantic tokens (light / dark)

Token Light Dark
--color-bg-page neutral-50 #171420
--color-bg-surface neutral-0 #211D2B
--color-bg-surface-raised neutral-0 #2A2537
--color-text-primary neutral-900 #F0EDF4
--color-text-secondary neutral-600 #A79FB3
--color-text-on-primary #FFFFFF #FFFFFF
--color-action-primary primary-600 primary-400 (#9370D4 — AA on dark surface)
--color-action-primary-hover primary-700 primary-300
--color-border neutral-200 #3B3448
--color-focus-ring primary-500 primary-300

Dark mode ships for the Customer and Vendor mobile apps at MVP (follows OS setting); web dark mode is Scale. Status colors get dark variants by raising lightness ~15% (e.g. success #3FAE6E on dark).

2. Typography

Families (see Arabic-First & RTL for pairing rationale):

--font-family-arabic: "IBM Plex Sans Arabic";
--font-family-latin:  "IBM Plex Sans";
--font-family-display-arabic: "Noto Kufi Arabic";   /* marketing/hero only */

Type scale (rem, base 16 px). lh-ar applies when lang="ar":

Token Size Weight lh (en) lh (ar) Use
--text-display 2.25rem / 36px 700 1.2 1.4 Hero, marketing
--text-h1 1.75rem / 28px 700 1.25 1.45 Screen titles
--text-h2 1.375rem / 22px 600 1.3 1.5 Section headers
--text-h3 1.125rem / 18px 600 1.4 1.6 Card titles
--text-body-lg 1rem / 16px 400 1.5 1.75 Primary body
--text-body 0.9375rem / 15px 400 1.5 1.75 Default body (15px floor protects Arabic legibility)
--text-caption 0.8125rem / 13px 400 1.4 1.6 Timestamps, helper text
--text-overline 0.75rem / 12px 600 1.3 1.5 Eyebrows (EN: +0.06em tracking; AR: tracking 0, weight only)

Weights: --font-weight-regular: 400, --font-weight-medium: 500, --font-weight-semibold: 600, --font-weight-bold: 700. No italics token — Arabic has none; emphasis is weight/color.

3. Spacing (4pt scale)

Token Value Typical use
--space-1 4px Icon-to-label gaps
--space-2 8px Inside chips, tight stacks
--space-3 12px Card internal padding (compact)
--space-4 16px Default screen gutter (mobile), card padding
--space-5 20px Between form fields
--space-6 24px Section spacing
--space-8 32px Between major blocks
--space-10 40px Page-level separation (web)
--space-12 48px Hero padding
--space-16 64px Marketing sections

Rule: only these steps. Always applied via logical properties (padding-inline-*) so RTL is automatic.

4. Radii

Token Value Use
--radius-sm 6px Inputs, chips, tags
--radius-md 10px Buttons, small cards
--radius-lg 16px Cards, sheets, modals
--radius-xl 24px Bottom sheets, hero cards
--radius-full 9999px Avatars, pills, badges

5. Elevation

Soft, purple-tinted shadows (never pure black) — imagery stays hero, chrome stays quiet:

Token Value Use
--elevation-0 none Flat lists, admin tables
--elevation-1 0 1px 3px rgba(35,28,60,.08) Cards at rest
--elevation-2 0 4px 12px rgba(35,28,60,.10) Raised cards, dropdowns, sticky CTA bars
--elevation-3 0 8px 24px rgba(35,28,60,.14) Modals, bottom sheets
--elevation-4 0 16px 48px rgba(35,28,60,.18) Dialogs above modals (rare)

Dark mode replaces shadows with surface-lightening (bg-surfacebg-surface-raised) plus a 20%-opacity shadow.

6. Motion

Token Value Use
--duration-instant 80ms Hover/pressed feedback
--duration-fast 150ms Toggles, chips, checkbox
--duration-base 240ms Sheets, dropdowns, screen transitions
--duration-slow 400ms Full-screen modals, celebration entrances
--easing-standard cubic-bezier(0.2, 0, 0, 1) Default for everything
--easing-decelerate cubic-bezier(0, 0, 0, 1) Elements entering the screen
--easing-accelerate cubic-bezier(0.3, 0, 1, 1) Elements leaving the screen

Directional motion (slides, wizard step transitions) mirrors in RTL: "forward" slides leftward in Arabic. All motion collapses to opacity-only under prefers-reduced-motion. Celebration moments (payment success, booking confirmed) may use up to 800ms one-shot animation — the only exception to --duration-slow.

7. Breakpoints & layout

Token Value Meaning
--breakpoint-sm 640px Large phones landscape / small tablet
--breakpoint-md 768px Tablet portrait — 2-column layouts begin
--breakpoint-lg 1024px Desktop — persistent side nav (vendor/admin)
--breakpoint-xl 1280px Wide desktop — max content width applies
--layout-max-width 1200px Customer web content column
--layout-max-width-admin 1440px Admin tables need width

Design baseline: 360×800 (mobile-first, per Design Principles).

8. Z-index & misc

--z-sticky: 100 (sticky CTA bars) · --z-dropdown: 400 · --z-overlay: 800 (sheet/modal scrim) · --z-modal: 900 · --z-toast: 1000.

Touch target minimum: --size-touch-target: 48px. Focus ring: --focus-ring: 2px solid var(--color-focus-ring); outline-offset: 2px — never removed, only restyled.

Platform delivery

Platform Mechanism
Source of truth tokens.json (W3C Design Tokens format) in the design-system repo; Figma variables synced from it
Web Style Dictionary → CSS custom properties on :root / [data-theme="dark"]; Tailwind theme reads the same variables
Flutter Style Dictionary → generated YamTokens ThemeExtension (light/dark)
Email templates Baked-in hex at build time from the same tokens.json

Token changes ship as versioned PRs to tokens.json reviewed by design + one dev per platform. MVP ships the light theme fully and mobile dark theme; token names are frozen at MVP even while values await branding.

Related: Design Principles · Arabic-First & RTL · Key Screens