Skip to Content
Design SystemTypography

Typography

Coreola uses Inter as the primary typeface, paired with a deliberately tight type scale tuned for dense admin UI.

The settings live in src/themes/defaults/options.ts and src/app/settings.ts.


Font family

fontFamily: ['Inter', '"Helvetica Neue"', '-apple-system', 'Arial', 'sans-serif'].join(',')

Inter is self-hosted via @fontsource/inter. Bundled for Cyrillic glyph coverage (Ukrainian locale).

The fallback chain is: Inter → Helvetica Neue → system → Arial → sans-serif. This guarantees readable text even if the webfont fails to load.


Base font size

The MUI base font size is 13px, set in src/app/settings.ts:

baseFontSize: 13

This propagates through theme.typography.fontSize and the rem(px) helper in src/themes/defaults/helpers.ts:

export function rem(px: number) { if (!Number(px)) return px; return `${(1 / 16) * px}rem`; }

The rem() helper converts pixels to rem using the 16-px convention so the math is predictable, regardless of baseFontSize. Use it whenever you write inline font sizes in component overrides.


MUI typography variants

Coreola uses MUI’s default type scale with a handful of tweaks:

h1h6

The MUI defaults (in px equivalents):

VariantDefault font weightCoreola override
h1300
h2300
h3400
h4400
h5400
h6500 → 400overridden to 400 for visual density

subtitle1, subtitle2

subtitle1 is overridden to fontWeight: 400 (default is 400; this is explicit). subtitle2 is untouched.

body1, body2

Untouched. body1 is the default for most text; body2 is the smaller variant used in tables and dense surfaces.

button

button: { textTransform: 'none', }

Button labels are never uppercased. This is a deliberate departure from Material Design’s default to keep admin labels readable.

caption, overline

Untouched.


When to use which variant

VariantUse for
h1Almost never. Reserved for hero areas (auth screens).
h2Major page heading. One per page maximum.
h3Section heading inside a page.
h4Sub-section heading, card title.
h5Rare. Inline emphasis or dialog title.
h6Card sub-title, list group header.
subtitle1Lead paragraph or section intro.
subtitle2Form group label, smaller intro text.
body1Default paragraph text.
body2Table cells, list items, dense descriptions.
captionHelp text under a form field, timestamps in lists.
overlineCategory labels above a heading.
buttonApplied automatically by Button — do not use directly.

Component-specific overrides

The following components have type overrides in options.ts:

  • MuiBreadcrumbsfontSize: rem(10). Breadcrumbs are intentionally small to stay out of the way.
  • MuiChipsizeMedium uses rem(14). The sizeTiny variant (Coreola-specific) is 18px tall with borderRadius: 9.
  • MuiInputBase — default fontSize: rem(14). Inputs are slightly larger than body2 for hit-target comfort.
  • MuiButtonsizeTiny 12px, sizeSmall 13px, sizeMedium 14px, sizeLarge 16px.
  • MuiTableCell — head cells are fontWeight: 500. Body cells use the default.
  • MuiFormHelperText — small/medium/large at 12/13/14 px respectively, with the error variant prefixed by a "↑ " glyph.
  • MuiTooltipfontSize: 13, fontWeight: 400.

These are the only places where Coreola deviates from MUI defaults at the typography level. Adding more is discouraged.


Font weights in practice

Coreola uses three weights, no more:

  • 400 (Regular) — body text, most labels, button text.
  • 500 (Medium) — table head cells, alert filled labels, inline emphasis.
  • 600+ (Semi/Bold) — used rarely, only where MUI defaults reach for it (e.g., dialog title, snackbar emphasis).

Italic is reserved for direct quotes and field placeholders generated by MUI. Coreola does not use italic for emphasis — use <strong> (which renders 500/600 depending on context) instead.


Reading the type scale at runtime

To inspect the active type scale from anywhere in the running app:

import { useTheme } from '@mui/material/styles'; const theme = useTheme(); console.log(theme.typography);

The theme.typography object includes every variant (h1h6, body1/body2, etc.) with computed fontSize, lineHeight, letterSpacing, and fontFamily. Useful when debugging spacing problems in dense layouts.


Internationalization considerations

Inter supports Latin and Cyrillic out of the box. The Ukrainian locale (uk) uses the same primary font; Noto Sans is loaded as a Cyrillic-safe fallback in case a glyph is missing.

If you add a locale with a non-Latin script (e.g. Japanese, Arabic), add the corresponding @fontsource/... package and extend the fontFamily array in options.ts.


Anti-patterns

Avoid these — they cause inconsistency and survive code review only by mistake:

  • Hard-coded fontSize: '14px' in sx — use a typography variant or rem(14).
  • Hard-coded font weights — use theme.typography.fontWeightMedium/fontWeightBold.
  • Wrapping plain text in custom styled for emphasis — use <Typography variant="...">.
  • Uppercase button labels — Coreola explicitly disables them.

Next steps

  • Colors — palette and color roles
  • Spacing — the 4-px grid that pairs with the type scale
  • Components — components that already honor these rules
Last updated on