Foundations

Typography and fonts

Three families and a Bangla fallback, eight sizes, five type classes. Load the fonts once; every component picks them up from the font slots.

The families#

Inter

Body and interface

Vehicles inside 128 · Gate 2 opened at 14:32

Everything by default: labels, tables, buttons, forms.

--font-inter

Plus Jakarta Sans

Display

Every car park, one screen

Page titles, headings and the big numbers on stat cards (the .disp class).

--font-jakarta

JetBrains Mono

Code and identifiers

SES-2026-10-02-0412 · DHA-GA 12-3456

Code, keys, receipt and session IDs (the .mono class).

--font-jetbrains

Noto Sans Bengali

Bangla and ৳

আজকের আয় ৳৪৮,২৫০ · গাড়ি ভিতরে ১২৮

The fallback in every slot, so Bangla text and the Taka sign render in the system's style.

after each family

Loading them#

The package names the families but does not ship font files, so the app loads them its own way. The setup guides do this in step 5: Next.js with next/font (self-hosted, no layout shift), and Vite with Google Fonts links or @fontsource packages. Weights used: 400, 500, 600, 700 for Inter and Bangla; 500, 600, 700 for Plus Jakarta Sans; 400 and 500 for JetBrains Mono.

The scale#

Interfaces are dense, so most text is 13px. Larger sizes are for reading and for the one number a card is about.

38/700Revenue this month
28/600৳48,250
22/600Live occupancy
16/600Close the cash shift
14/400Cars pay ৳30 for the first hour.
13/400Vehicles inside · Approvals · Review
12/400vs last Thursday
11/600Live

Type classes#

.dispThe display family, tight tracking, the text colour. Titles and lead numbers.
.numTabular, lining figures with a slashed zero. Mandatory on every number in a column, so digits line up.
.monoThe code family at 13px. IDs, keys, code.
.ovThe overline: 11px, semibold, uppercase, spaced, muted. Group labels in menus and tables.
.curThe currency symbol at the weight the figures around it need.

Figures that line up

Put num on every number in a column, a total or a timer. Proportional figures make 1,111 narrower than 8,888, and a column of amounts stops lining up.

Without .num

৳1,111.10

৳8,888.80

৳40,000.00

With .num

৳1,111.10

৳8,888.80

৳40,000.00

Using other fonts#

Load the families, then put them in the slots. Keep Noto Sans Bengali after them if the product shows Bangla or Taka.

globals.css
/* After @import "@waveinno/ui/styles.css": your families in the package's slots. */
:root {
  --font-inter: "Manrope", "Noto Sans Bengali";       /* body and interface */
  --font-jakarta: "Space Grotesk", "Noto Sans Bengali"; /* display */
  --font-jetbrains: "IBM Plex Mono";                  /* code */
}

Or let createTheme() write the slots with the rest of a theme (the theme builder has a font picker):

theme.ts
import { createTheme } from "@waveinno/ui";

const { css } = createTheme({ primary: "#0f9d7a", fontSans: "Manrope", fontDisplay: "Space Grotesk" });

Bangla#

  • Inter has no Bangla glyphs and no ৳, so Noto Sans Bengali sits after every family; the browser takes those characters from it.
  • Dates and numbers follow the locale you pass (locale="bn-BD" on the date pickers, Intl in the formatters), not the font.
  • Bangla lines need a little more height; components use 1.25 or more, so mixed text does not clip.