The design system behind OlyRetail's retail operations dashboard.
Logo & lockup
The mark is an abstract diagonal "O" built from converging strokes, filled with the brand gradient. It pairs with the wordmark as a horizontal lockup, or stands alone as the app icon / favicon.
Keep clearspace around the mark equal to the height of the icon glyph on all sides. Never scale the lockup below 20px icon height / 90px lockup width — the wordmark strokes start to close up below that.
Use the supplied SVGs as-is. Use the dark lockup on dark or busy photographic backgrounds.
Don't recolor the gradient, rotate the mark, add drop shadows, or stretch the lockup's aspect ratio.
Color system
Every color in the product is a CSS custom property with a light and dark value, so the whole UI re-themes by flipping data-theme. Toggle the switch in the side rail to see it in action.
Page sits behind every surface; Surface and Surface Alt stack panels and cards on top of it. The three text tones step down in emphasis — Primary for content, Secondary for labels, Tertiary for captions and metadata.
Primary carries interactive intent — active nav, primary buttons, links, focus rings, selection highlight.
Semantic colors always ship as a base/tint pair: the tint fills badge and banner backgrounds, the base colors the icon or label text on top of it.
Series A / B is reserved for two-way comparisons in analytics charts (e.g. demographic splits). It never doubles as a semantic success/danger color.
Typography
Neue Haas Grotesk Pro is the system typeface — a clean, high-legibility grotesque suited to dense, numbers-heavy dashboards. It falls back to Helvetica Neue / Arial Nova / Arial where the licensed font isn't installed.
Spacing & layout
Spacing is built on a 4px base unit, nudged by 1–2px where optical balance matters in dense table and pill layouts. Structural chrome uses a fixed set of measurements across every view.
Corner radius
Radius scales with the size and prominence of the surface — small tight controls stay crisp, primary containers get the signature 14px rounding, and anything pill-shaped goes fully round.
The widget card doesn't reference the --r token — it hardcodes 16px directly. A small real inconsistency, left as-is here rather than smoothed over.
Elevation
Shadows are soft and low-contrast at rest, growing in size and spread as a surface lifts further off the page — never darker or harder-edged.
Motion
Most interactions resolve in under 200ms. A single spring easing is reserved for a few moments of character — the active nav indicator, a badge settling into place — everything else uses a standard ease. Hover a row to preview.
Iconography
Tabler Icons — outline style, 1.5px stroke. Used at 14–16px inline with text, 18–19px in navigation, always inheriting the surrounding text color.
Buttons
One primary action per view. Secondary and ghost buttons handle everything else; danger is reserved for destructive, hard-to-reverse actions.
Badges & status pills
Status is always color + label, never color alone — every pill carries text so meaning survives for colorblind users and in monochrome exports.
Form fields
Inputs rest on the alt surface tint so they read as recessed; focus swaps to the primary surface with a border + glow ring.
The product has no custom toggle switch — native checkboxes are simply tinted with accent-color, and multi-select filters use this bordered chip that fills purple when checked.
Avatars & cards
The widget card is the workhorse container — nearly every chart and panel in the app lives inside one. KPI and stat cards lead with a number instead of a chart; avatars carry the brand gradient by default.
The primary content container used across Analytics, Reports and Home — a plain surface, 16px radius (not the default 14px card radius), with an eyebrow + title on the left and icon actions on the right.
Used in list-heavy views like User Management — an icon chip on the left, no gradient. Reach for this when a stat sits beside a table rather than leading a dashboard.
The signature Home-screen card: a colored gradient, an icon chip, a large number, a trend pill, and a one-line AI insight underneath.
| Store | Region | Status | Footfall |
|---|---|---|---|
| Indiranagar Flagship | South Zone | Active | 1,204 |
| Changi Corridor | Central Hub | Pending | 842 |
| West District | West District | Offline | — |
Tabs & segmented controls
Tabs mark the active item with a bottom border, never a filled background. Segmented controls (period switches, grid-density toggles) use a raised white chip on a tinted track instead.
Progress & status
A thin rounded track for completion state, compact status pills for at-a-glance state, and a compound pill that fuses an icon cell to a colored status — used for camera/device health.
Icon-metric chips used in the live-feed camera grid. On hover, the product shows a floating tooltip near the cursor — not an inline expanding label.
Search & notifications
Global search widens and reveals grouped results on focus, replacing its keyboard-shortcut hint with the live query. Notifications drop a full panel — tabs, a mark-all-read action, per-item unread dots — not just a badge.
Entrance camera offline
Marina Bay Sands · 2 min agoQueue exceeded projection by 12%
Changi Corridor · 1 hr agoBreadcrumb
Used when drilling into a hierarchy (region → store). The back button is fused to the trail rather than floating separately.
Empty & loading states
Empty states use a single large icon at reduced opacity — never a custom illustration — plus a bold title, muted subtext, and an optional primary CTA. Loading states shimmer generic gray blocks shaped like the content they'll become.
Dropdowns & modals
Overlays float in the "lg"/"xl" elevation tiers, sit on the primary surface regardless of page background, and dismiss on outside click or Escape.
Remove this store?
This can't be undone. Historical analytics for this location will be archived, not deleted.
Date range picker
A preset row (Today / 7d / 30d) sits above a month grid — presets cover the common cases so the grid is rarely needed for anything but a custom range.
Filter drawer
A right-side panel that slides in over a dimmed backdrop — reused across Analytics, Live Feed, Reports and User Management for advanced filtering, rather than building a bespoke filter UI per view.
The darkened area is the dimmed backdrop (25% black) that sits behind the panel while it's open — not empty space.
Usage guidelines
A few rules that keep the system coherent as new surfaces get built.
Pull colors, radius and shadow values from the tokens on this page — never hard-code a one-off hex or pixel value in a new screen.
Don't introduce a new accent color for a single feature. If none of the semantic or brand colors fit, that's a signal to raise it with design first.
Pair every status color with a text label and, where space allows, an icon.
Don't rely on color alone to communicate state, and don't use the spring easing for more than one element on screen at a time.
Audited against WCAG AA: white text on the dark-mode primary (#8A87FF) measures ~3.0:1 — below the 4.5:1 minimum for normal text. It's an existing production value, carried here as-is rather than silently corrected. Until it's revisited, keep dark-mode primary-button labels bold and ≥14px, and don't use primary-on-white for long-form text. Tertiary text and status-pill labels also sit in the ~2.9–4.4:1 range by design, intended for de-emphasized captions and badges only — never for primary body copy.