Design principles

These principles guide every decision in the Inntrig interface. They exist to make the product trustworthy, clear, and accessible — qualities that matter especially for a tool used to evaluate accessibility.

Accessible by default

Every component is built to WCAG 2.2 AA as a baseline. This means correct colour contrast, keyboard navigability, focus indicators, and proper use of HTML semantics. The product audits accessibility — it must embody it.

The first rule of ARIA: don't use ARIA when native HTML does the job. Use <h1><h6> for headings, <button> for actions, <a> for navigation. Reach for aria-* attributes only when HTML falls short.

Semantic HTML over styling hacks

HTML elements carry meaning. An <a> navigates; a <button> triggers an action. These are not interchangeable. If something navigates, it must be an anchor — even if it looks like a button. If it triggers an in-page action (form submission, toggle), it must be a button.

The Button component supports an asChild prop precisely for this: it lets a Link (which renders as <a>) carry button styles without wrapping it in a <button>, which would be invalid HTML. Think of it as "apply button styling to this element, whatever element it is."

Rule: Never nest a <button> inside an <a> or vice versa. Use Button asChild when a navigation link needs button styling.

Links are always underlined

Text links must always be underlined. Underlines are the universally understood visual cue for a hyperlink. Relying on colour alone to distinguish links from surrounding text fails WCAG SC 1.4.1 (Use of Colour) for users who cannot distinguish colours.

The only exception: navigational links in discrete UI regions (top bar, breadcrumb nav, footer) where context makes the interactive nature unambiguous. These suppress the underline via the nav a rule but restore it on hover.

Primary actions

The most important action on a page gets the primary button style (white text on blue). If two actions have equal value — like "Sign in" and "Create account" on the home page — both can be primary. Avoid more than two primary buttons in a single viewport unless they genuinely compete for equal attention.

Secondary actions use an outlined style. Destructive or low-emphasis actions use ghost/text.

Colour communicates meaning, not decoration

The token system defines semantic roles: --color-pass, --color-fail, --color-na, --color-todo. These are used consistently across the results UI. New colour usage should map to a semantic token — not a raw hex value — so theming works correctly.

Layout lives in the app

Design system components handle their own internal layout (padding, alignment). Page-level layout — grids, gaps between components, hero sections — belongs in the consuming app's CSS. Don't pass layout-specific inline styles to components; add a class to the containing element instead.