EMA Design System
One design language for all our projects. Framework-agnostic web components, a tight and fast UX, premium animations, four themes, full mobile responsiveness — and an advanced data grid built in.
27+ components
Inputs, selects, autocomplete, modals, toasts, tabs, datepicker and more — all as native custom elements that work in any stack.
Advanced data grid
Server & client pagination, search, filters, grouping, drill-down, inline editing, keyboard navigation, column resize/show/hide.
4 themes, token-driven
Light, Dark, Navy and Emerald. Every color, size and shadow is a CSS custom property — restyle the entire system in one place.
Installation
Copy the ema/ folder into your project and include three files. No build step, no dependencies, no framework required.
<!-- 1. Styles --> <link rel="stylesheet" href="ema/css/tokens.css"> <link rel="stylesheet" href="ema/css/components.css"> <link rel="stylesheet" href="ema/css/grid.css"> <!-- only if you use <ema-grid> --> <!-- 2. Scripts --> <script src="ema/js/ema.js" defer></script> <script src="ema/js/ema-grid.js" defer></script> <!-- only if you use <ema-grid> --> <!-- 3. Base class on body --> <body class="ema-body">
Then use components as plain HTML:
Theming
Themes are applied with a single attribute on <html>. Try the colored dots in the top bar — every component on this page re-themes instantly.
<html data-theme="dark"> <!-- light (default) | dark | navy | emerald -->
Runtime settings — EMA.configure()
Theme, brand colors, corner style and density are all configurable at runtime and persist
to localStorage automatically (restored when ema.js loads).
Try the ⚙ gear in the top bar of this site.
EMA.configure({
theme: 'navy', // light | dark | navy | emerald
primary: '#7c3aed', // any hex — hover/active/soft tones are derived
secondary: '#0d9488', // automatically and adapt to every theme
radius: 'rounded', // sharp (default) | subtle | rounded
density: 'medium', // tight (default) | compact | medium | large
headerBg: '#1a4c87', // header color: table headers, modal/drawer/card heads
formLayout:'left', // top (default) | left (labels beside) | compact
menu: 'rail', // sidebar | rail | top — app-shell menu (demo apps)
});
EMA.getSettings(); // current saved settings
EMA.resetSettings(); // back to defaults (sharp, tight, brand colors)
Corner radius
Sharp edges are the default. Soften globally with one attribute (or via EMA.configure):
<html> <!-- default: sharp, square corners --> <html data-radius="subtle"> <!-- 2–8px --> <html data-radius="rounded"> <!-- 4–16px -->
Density
Tight is the default (14px text, 34px controls). Four modes adjust control heights, text and spacing:
<html data-density="compact"> <!-- densest, for data-heavy screens --> <html> <!-- default: tight --> <html data-density="medium"> <!-- relaxed controls (40px) --> <html data-density="large"> <!-- spacious, touch-friendly (44px) -->
Custom branding (CSS only)
Prefer static config? Override tokens after importing tokens.css:
:root {
--ema-primary: #0b5fa5; /* your brand navy-blue */
--ema-secondary: #138a50; /* your brand green */
}
Color tokens
The primary palette is a navy / light-blue ramp; the secondary palette is green. Status colors cover success, warning, danger and info.
Primary — navy blue
Secondary — green
Neutrals
Semantic tokens
Components never reference raw ramp colors — they use semantic tokens that change per theme:
| Token | Purpose |
|---|---|
--ema-primary / -hover / -active | Brand actions, focus, selection |
--ema-primary-soft / -soft-2 | Tinted backgrounds (selected options, soft buttons) |
--ema-secondary… | Success-leaning accents, edit highlights |
--ema-bg / --ema-surface / --ema-surface-2/3 | Page and layered panel backgrounds |
--ema-text / --ema-text-2 / --ema-text-3 | Primary / secondary / muted text |
--ema-border / --ema-border-strong | Hairlines and control outlines |
--ema-danger / -warning / -success / -info | Status colors (each with a -soft tint) |
--ema-shadow-sm/md/lg/xl | Elevation scale |
--ema-radius-xs…xl / -full | Corner radii |
--ema-dur-fast/med/slow + --ema-ease* | Motion durations and easing curves |
Typography & spacing
The UI font stack prefers Inter / Segoe UI. The base UI size is a tight 14px, with a 4px spacing scale and 34px default control height — built for dense, professional applications.
| Token | Value | Use |
|---|---|---|
--ema-text-xs / sm | 12 / 13px | Meta text, table headers, hints |
--ema-text-md | 14px | Default UI text |
--ema-text-lg / xl / 2xl / 3xl | 16–30px | Headings |
--ema-sp-1 … --ema-sp-12 | 4–48px | Margins, paddings, gaps |
--ema-control-h-sm / md / lg | 28 / 34 / 40px | Buttons and inputs |
UX principles
| Principle | How the system enforces it |
|---|---|
| Tight by default | 14px base font, 34px controls, 4px spacing grid. data-density="compact" for even denser screens. |
| Keyboard first | Every interactive component is focusable and operable with the keyboard; the grid supports full arrow-key cell navigation and Enter-to-edit. |
| Motion with purpose | Animations run 120–320ms on spring/ease-out curves and respect prefers-reduced-motion. |
| Mobile responsive | Layout utilities collapse below 900/600px; grids scroll horizontally; modals, toasts and toolbars adapt to small screens. |
| Accessible | Visible focus rings, ARIA roles on composite widgets, color-contrast-checked palettes in all four themes. |
Next steps
Building or extending the system? Read the rendered README and DEVELOPMENT guide (architecture, conventions, how to author new components) — always in sync with the markdown files in the repository root.