navree
Documentation

Theming

@navree/theme: navree.com's dark theme as Tailwind CSS 4 tokens, shadcn/ui and shadcn-vue colors, self-hosted fonts and the tokens as data.

On this page

@navree/theme is the look of navree.com for your app: near-black ink surfaces with a faint sea-green cast, off-white text in four steps, one green accent, amber for warnings, and three self-hosted faces. It is dark only. shadcn/ui and shadcn-vue components pick it up without changes, so Next.js and Nuxt apps look the same.

Setting up

web/src/app/globals.css

Put class="dark" on <html>: the theme declares @custom-variant dark (&:where(.dark, .dark *)), so the dark: classes shadcn components use always apply. Add the framework package to Tailwind's sources, so the classes its data table uses are generated:

web/src/app/globals.css (Next.js)
web/app/assets/css/main.css (Nuxt)
FileWhat it is
@navree/theme/theme.cssThe Tailwind CSS 4 preset: @theme tokens, the shadcn semantic colors, the radius scale, base styles and utilities.
@navree/theme/fonts.css@font-face rules for the three faces from the @fontsource packages, and the --font-mona, --font-geist and --font-monaspace variables.
@navree/theme/tokens.cssThe color tokens and font stacks as plain custom properties, for pages without Tailwind.
@navree/theme/registry/navree.jsonA shadcn registry theme, for the shadcn CLI.
@navree/themeThe tokens as data (colors, semanticColors, fonts, radius, themeColor) and contrastRatio.

The tokens

TokenValueUse
ink-0#040605Page background
ink-1#0a0e0cCards, panels, the sidebar
ink-2#111714Hover surfaces, inputs
ink-3#16201bThe current item, a selected option
line#1c2420Every 1px border (the default border color)
line-2#2a3530Stronger borders: buttons, inputs
fg#e9efebHeadings, primary text
fg-1#cfd8d3Strong secondary text, table cells
fg-2#a9b5aeBody copy, descriptions
fg-3#8a968fCaptions, metadata, column headings
accent#3dff8fThe primary action, focus rings, positive data
accent-ink#03130aText on the accent
amber#ffbf5eWarnings
danger#ff6b6bErrors (shadcn's destructive)

Every text step meets WCAG AA on every ink step; the faintest pair, fg-3 on ink-3, is 5.4:1. The package's tests check it, and that the tokens match navree.com's.

The theme also has the display type scale (text-display-2xl to text-display-sm, text-title for an app's page title, text-figure for key figures, text-eyebrow), green glows (shadow-glow-sm, shadow-glow, shadow-glow-lg), shadow-float for popovers and dialogs, the easings ease-out-quint and ease-spring, and animate-shimmer for loading placeholders.

shadcn's semantic colors

shadcn nameToken
backgroundink-0
foregroundfg
card, popoverink-1
secondary, mutedink-2
muted-foregroundfg-2
primary, ringaccent
primary-foregroundaccent-ink
destructivedanger
warning, successamber, accent
border, inputline, line-2
sidebar, sidebar-accentink-1, ink-2
chart-1 to chart-5slate to pale mint, then accent

accent stays Navree green: it is not a grey hover color. After pnpm dlx shadcn@latest add <component>, replace hover:bg-accent and focus:bg-accent with hover:bg-ink-2 and bg-ink-3.

Corners

App UI has two radii: 4px for controls (buttons, inputs, menu items, badges, tabs, avatars) and 6px for surfaces (cards, popovers, dialogs, sheets). The theme pins Tailwind's scale to them, so whatever the shadcn CLI generates lands inside the rule: rounded-sm, rounded-md and rounded-lg are 4px, rounded-xl and up are 6px. Write rounded-md on a control and rounded-xl on a surface; rounded-full is for status dots only.

Utilities

UtilityWhat it does
surfaceA raised surface: ink-1, a 1px line border, 6px corners.
th-labelColumn headings: 12px, medium, fg-3.
eyebrowThe small label above a heading: 13px, medium, fg-3.
figuresTabular, lining figures for amounts, counts and dates.
scroll-thinA thin scrollbar for sidebars, boards and lists.
font-display-wideThe display face at its widest, for one oversized word at most.

Fonts

  • Mona Sans (SIL OFL), the display face: page titles and big figures, set semi-expanded (font-display, wdth 112). h1 uses it automatically.
  • Geist (SIL OFL), the UI and body sans (font-sans).
  • Monaspace Neon (SIL OFL), for code, ids and keys (font-mono).

fonts.css loads them from the @fontsource packages the theme depends on, every subset with its unicode-range, so a browser downloads only what a page uses and the app makes no requests to a font service. It works in Nuxt and any Vite or PostCSS pipeline.

In Next.js, next/font/local preloads the files and removes the layout shift. Load the same files there instead of fonts.css, and put the variables on <html>:

web/src/app/fonts.ts
web/src/app/layout.tsx

Add @fontsource-variable/mona-sans, @fontsource-variable/geist and @fontsource/monaspace-neon to the app's own dependencies for these paths. For scripts the three faces don't cover, see fonts for other scripts.

shadcn/ui and shadcn-vue

theme.css already maps every shadcn variable, so components added with the shadcn CLI or the shadcn-vue CLI use the theme as they are. For a project that keeps its colors in shadcn's own CSS variables instead, the package also ships the theme as a registry item in shadcn's registry schema (registry:theme), which the shadcn CLI installs from a path or a URL:

Shell

It has the same colors in its light and dark variables, because the theme is dark only. A shadcn-vue project can copy the same values from it into its CSS variables, or import theme.css.

The tokens in code

Canvas charts, <meta name="theme-color">, emails and PDFs can't read CSS variables. The package exports the tokens:

TypeScript

The rules

The green is for three things: the primary action, focus rings, and positive data (a won amount, a completed task, a success toast). Navigation, selection and hover use the ink steps: hover:bg-ink-2, the current item bg-ink-3. No pills, no glows on app UI except shadow-float under popovers and dialogs, and no second green element competing with the primary action. apps/website/DESIGN.md (section 9, App UI) has the full rules for shells, density and type.