Engineering standards
Enma makes screens look right. These standards make them work right. They apply to every project built with Enma, on every platform, and a screen isn't done until it meets them.
Performance
Targets (web, measured at the 75th percentile of real users): Largest Contentful Paint under 2.5s, Interaction to Next Paint under 200ms, Cumulative Layout Shift under 0.1.
- JavaScript: keep the first-load bundle of an app shell under about 150 KB gzipped. Split by route, lazy-load heavy views (charts, editors, maps), and check the bundle with an analyzer before each release.
- Fonts: only the active theme's families,
woff2,font-display: swap, Latin subset, self-hosted (next/font,@fontsourceor local files). Preload the display face only if it appears above the fold. - Images: AVIF or WebP, explicit
widthandheight(oraspect-ratio) to prevent layout shift,loading="lazy"below the fold, responsivesrcset. - Rendering: animate only
transformandopacity(all Enma motion does). Virtualize lists longer than about 100 rows (TanStack Virtual on web, FlashList on native). Don't re-render whole screens on every keystroke: keep state local and memoize expensive children; turn on the React Compiler where the stack supports it. - Data: show cached data first and revalidate in the background; never block a whole screen on one slow request.
- React Native: Hermes on, reanimated for anything that moves,
expo-imagefor images, no heavy work on the JS thread during navigation transitions. - Measure it: Lighthouse CI or the
web-vitalslibrary on web, the performance monitor and a release build on a mid-range Android phone for native. Test on a throttled connection, not just office Wi-Fi.
Accessibility (WCAG 2.2 AA)
- Contrast: Enma's tokens already pass (text 4.5:1, controls and focus 3:1) in every theme and mode. Don't override them with failing colors, and never put
ink-2on accent or hero fills. - Semantics first:
<button>for actions,<a>for navigation,<label>for every input, headings in order (oneh1per page), landmarks (header,nav,main,footer). Native roles and states on mobile. - Names: every icon button has a
label; images havealt(emptyalt=""when decorative); charts have a text summary (Bars,LineChart,SparklineandDonutbuild one). - Forms: visible labels, the right
type,inputmodeandautocomplete, errors as text tied to the field (TextFielddoesaria-invalidandaria-describedby), and focus moves to the first error on submit. - Feedback: toasts use
role="status"(errorsrole="alert"); loading states announce themselves; nothing important lives only in a toast. - Touch and pointer: 44px targets on mobile (WCAG's minimum is 24px; Enma uses 44), nothing that needs hover to work, no gesture without a button alternative.
- Zoom and reflow: usable at 200% zoom and at 320px width without horizontal scrolling; text resizes with the user's setting (Dynamic Type on iOS, font scale on Android).
- Motion: respect
prefers-reduced-motion(Enma's CSS and the native examples do). Nothing flashes, nothing autoplays with sound. - Test it:
eslint-plugin-jsx-a11yin the editor,@axe-core/playwrightin CI, plus a manual keyboard pass and a VoiceOver or TalkBack pass on each new screen.
Keyboard and shortcuts
Everything works with a keyboard.
- Tab order follows the visual order; nothing is reachable only by mouse.
- The focus ring is always visible. Enma's ring is a 2px
--e-focusring with a 2px gap; never remove it. - Escape closes the topmost dialog, sheet, menu or popover, then clears search.
- Dialogs move focus inside when they open, trap it while open, and return it to the trigger when they close (Radix and React Aria do this).
- Lists and menus support arrow keys; Enter opens; Space toggles.
- Web pages with navigation start with a "Skip to content" link.
Standard shortcut map. Use these in every app so muscle memory carries over. Show Cmd on macOS and Ctrl elsewhere.
| Shortcut | Action |
|---|---|
| Cmd/Ctrl+K | Command palette (search everything, run any action) |
| / | Focus the search field |
| ? | Show the keyboard shortcut sheet |
| Esc | Close the top overlay, then clear the current search or selection |
| J / K | Next / previous item in a list |
| Enter | Open the selected item |
| C | Create a new item (the screen's primary action) |
| G then H, G then S | Go to Home, go to Settings (two-key "go to" sequences) |
| Cmd/Ctrl+Enter | Submit the current form or send |
| Cmd/Ctrl+S | Save, only where the app has an explicit save |
Rules for shortcuts.
- Single-letter shortcuts never fire while focus is in a text field, and users can turn them off (WCAG 2.1.4).
- Never override browser and OS shortcuts (Cmd/Ctrl+W, T, L, R, Q, Tab and the like).
- Show each shortcut where the action lives: in the button's tooltip, next to menu items and in the command palette, as
<kbd>styled withe-meta. - Keep one shortcut registry per app (
tinykeysorreact-hotkeys-hook) scoped by screen, so shortcuts don't collide; the?sheet is generated from it. - Shortcuts are mainly for B2B and desktop tools (Graphite projects, extensions). Mobile apps only need the keyboard basics above for hardware keyboards.
States every screen needs
- Loading: skeletons shaped like the content, using
--e-raisedblocks with a slow shimmer (none under reduced motion). Avoid full-screen spinners. Show a skeleton only if loading takes longer than about 300ms. - Empty: an invitation, not an apology. A title that names the space ("Log your first workout"), one line of explanation and the primary action.
- Error: what happened and what to do, in one sentence, with a retry. Keep whatever data is already on screen.
- Offline (mobile and extensions): show cached content, mark it as stale, queue writes and sync later.
- Long and edge content: test very long names, zero, one and many items, large numbers ("1,284,000"), and right-to-left text if the product will ever need it.
Responsive and platform fit
- Mobile first. Breakpoints: 640, 768, 1024 and 1280px. B2B layouts get a sidebar at 1024px and up.
- Use container width, not device type, to decide layout, and keep line lengths readable (about 60 to 75 characters for body copy).
- Respect safe areas on mobile (notches, home indicator) and platform conventions: iOS back swipe, Android back button, native sheets and pickers.
- Format numbers, currency and dates with
Intland the user's locale (for Indian users,en-INgives "12,48,000"), not hand-written formatting.
Definition of done
A screen ships when every line is true:
- Built from Enma components and
--e-*tokens only, no raw colors or fonts, within the tweak budget. - One hero, one accent spark, one primary action.
- Works in the theme's home mode, and in the other mode if the app has a toggle.
- Loading, empty, error and offline states exist.
- Fully usable with keyboard only, with a visible focus ring, and shortcuts follow the standard map.
- No axe violations; screen reader names make sense; usable at 200% zoom and 320px width.
- Respects reduced motion; motion only on press, first view and change.
- Meets the performance targets on a mid-range phone and a throttled connection.
- Copy follows Enma's voice: sentence case, verbs first, no "successfully".