Tailwind for developers

Tokens, not hex codes

North ships Tailwind themes generated from the same token file as everything else. Install them once and use brand classes: bg-n-action, text-n-heading, rounded-lg, shadow-2, text-heading-1. Hex codes in class names (bg-[#227ED1]) are a code-review failure.

Tailwind v4

/* app.css */
@import "tailwindcss";
@import "./north-tokens.css";     /* CSS variables: primitives + light/dark semantic roles */
@import "./north-tailwind.css";   /* @theme: brand palette, type styles, radius, shadows, motion */
  • The default Tailwind palette is removed (--color-*: initial): only brand colours exist, so off-brand colours fail at build time.
  • The dark: variant follows both the OS setting and <html data-theme="dark">, like the hub. With semantic classes you rarely need it.
  • Spacing uses a 4px base (--spacing: 4px): p-4 = 16px, gap-6 = 24px, matching --n-space-*.

Tailwind v3

// tailwind.config.js
module.exports = {
  presets: [require('./tailwind.preset.cjs')],
  content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
};
/* and load north-tokens.css globally: semantic colours read its variables */

Class names are identical in v3 and v4. In v3, opacity modifiers (/20) don't work on semantic colours because they are CSS variables; use the primitive colour instead (bg-gulf-70/20).

What the theme provides

GroupClassesSource tokens
Semantic colours (switch light/dark)bg-n-canvas bg-n-subtle bg-n-panel bg-n-surface-raised text-n-heading text-n-body text-n-caption text-n-link bg-n-action hover:bg-n-action-hover text-n-on-action border-n-border border-n-border-ui outline-n-focus bg-n-skeleton-base bg-n-scrim bg-n-table-header and all n-diagram-*semantic.*
Brand palettemidnight-05…95 dune-02…95 dawn-* oasis-* gulf-* steel-* snow white black status-*color.*
Chart seriesdataviz-1…6color.dataviz.*
Fontsfont-display font-text font-arabic font-mono (font-sans = text)font.family.*
Text stylestext-display-xl text-display-lg text-heading-1…4 text-lead text-body-lg text-body text-body-sm text-caption text-microtitle text-code (size + line height + tracking + weight)typography.*
Radiusrounded-xs sm md lg xl 2xl fullradius.*
Shadowsshadow-1 shadow-2 shadow-3 shadow-4 shadow-glowshadow.*
Breakpointssm: 640 · md: 960 · lg: 1280 · xl: 1600breakpoint.*
Motionease-standard ease-enter ease-exit ease-rise duration-instant/fast/base/slow/deliberate, animate-shimmer animate-dot animate-glow animate-rise animate-indeterminate animate-skel-pulsemotion.*
Sizesh-control-sm/md/lg min-h-touch min-w-touch max-w-measure max-w-contentsize.*, grid.*
Effectsblur-scrim blur-sm blur-md blur-lg backdrop-blur-scrim backdrop-blur-sm backdrop-blur-mdfilter.*
Gradientsbg-aurora bg-horizon bg-nightgradient.*

Component recipes

Class strings that reproduce the North components. The specs and states are on the component pages (Buttons, Forms, Tables, Feedback). If your project allows plain CSS, north-components.css gives you all of them as .n-* classes.

Primary button

Secondary button

Danger button

Icon button

Text input

Label

Hint

Badge (success)

AI badge

Filter chip (selected)

Card

Interactive card

Underline tab (active)

Table header cell

Table number cell

Alert (danger)

Toast

Skeleton line

Spinner

Agent pulse

Dialog

Scrim

Floating image button

Code block

Page heading

Body

Hero section

Using @apply for repeated components

/* v4 */
@layer components {
  .btn-primary { @apply inline-flex items-center gap-2 h-control-md px-4 rounded-sm bg-n-action text-n-on-action font-medium hover:bg-n-action-hover; }
}

Prefer real components (React, Vue, web components) over @apply for anything with logic. Keep one implementation per component in each product.

Rules for code review

  • No arbitrary colour values (bg-[#…], text-[rgb(…)]). If a colour is missing, ask for a token.
  • No raw pixel spacing outside the 4px scale (p-[13px]). Arbitrary values are fine for one-off layout sizes, not for brand values.
  • Use semantic classes (bg-n-*, text-n-*) in components; primitives (bg-midnight-80) only in brand artwork.
  • Every interactive element has focus-visible: styles.
  • Respect motion preferences: pair animate-* with motion-reduce:animate-none where the animation is decorative.
  • Arabic: use logical utilities (ps-4 pe-4 ms-auto start-0 text-start) instead of left/right.

Dos and don'ts

Do

  • Import the generated theme; never copy values by hand.
  • Use semantic classes in components.
  • Use logical (start/end) utilities for RTL.
  • Regenerate when tokens change (npm run tokens).

Don't

  • Re-enable the default Tailwind palette.
  • Use arbitrary hex values.
  • Use dark: overrides where a semantic class exists.
  • Fork the theme per product.

Last updated on 14 October 2026