ComponentsForms & inputs

Font picker

Choose a typeface from a curated catalog of 59 Google Fonts families — searchable, grouped by category, every row previewed in its own face — or one of 16 type pairings. Ships with a deduped Google Fonts loader and a provider that applies a pairing to a page or a single section.

Radix Popover · WAI-ARIA combobox + listbox · radio group fonts/font-picker.tsx, fonts/pairing-picker.tsx, fonts/provider.tsx, fonts/pairings.ts, fonts/loader.ts, fonts/catalog.tstheme · material · accent · density · font

59 Google Fonts families, all with Turkish characters.

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { FontPicker, FontPairingPicker, FontProvider } from "@vamos-ui/react/fonts";

<Field label="Heading font">
  <FontPicker value={family} onValueChange={setFamily} />
</Field>

Privacy: loading from fonts.googleapis.com sends the visitor's IP address to Google. For GDPR / KVKK-sensitive sites, self-host the files (see /docs/fonts) and pass loadPreviews={false} / load={false}.

Every catalog family supports latin-ext, so Turkish ğ ş ı İ ç ö ü render in the chosen face.

Previews download glyph subsets (only the characters of the family names and the sample line), and only for rows that scroll into view.

Examples

Restrict categories

categories narrows the list — mono for code and invoice numbers, serif for article text. The chips only show categories that remain.

Empty, invalid and disabled

Inside a Field the trigger picks up the label, hint, error and disabled state.

Nothing chosen yet.

Choose a font that supports Greek for the Athens site.

Locked by the brand kit.

Inline list

FontPickerList is the panel without the popover, for settings pages. Type to filter; ↑/↓ and PageUp/PageDown move, Enter selects. The specimen strip shows the active row large.

59 families
Sans · Geometric
Outfitvar
Soravar
Plus Jakarta Sansvar
Manropevar
Urbanistvar
Lexendvar
Red Hat Displayvar
Sans · Humanist
Onestvar
Figtreevar
DM Sansvar
IBM Plex Sansvar
Source Sans 3var
Instrument Sansvar
Commissionervar
Sans · Grotesk
Hanken Groteskvar
Geistvar
Schibsted Groteskvar
Familjen Groteskvar
Bricolage Grotesquevar
Host Groteskvar
Archivovar
Work Sansvar
Inter Tightvar
Serif · Text
Newsreadervar
Source Serif 4var
Literatavar
Loravar
Crimson Provar
Spectral7w
EB Garamondvar
Serif · Display
Instrument Serif1w
Frauncesvar
Playfair Displayvar
DM Serif Display1w
Young Serif1w
Bodoni Modavar
Display
Synevar
Unboundedvar
Dela Gothic One1w
Funnel Displayvar
Rounded
Nunitovar
Quicksandvar
Fredokavar
Varela Round1w
Condensed
Barlow Condensed9w
Oswaldvar
Antoniovar
Archivo Narrowvar
Saira Condensed9w
Mono
JetBrains Monovar
Geist Monovar
IBM Plex Mono7w
Space Mono2w
DM Mono3w
Fira Codevar
Martian Monovar
Handwriting
Caveatvar
Kalam3w
Patrick Hand1w

Selected: Bricolage Grotesque

Pairing picker

Sixteen curated heading + body + mono pairings, each with its own display weight, tracking, <em> style and scale. A radio group: arrows move and select.

CMS brand settings

Three pickers build a custom pairing with createFontPairing; FontProvider applies it to the preview only, so the panel around it keeps the admin fonts.

Karaköy Bistro
Autumn menu · from 12 November

Slow-cooked lamb, wood-fired bread and Aegean wines

Ağaç fırında pişen ekmek, şef İlkay Şahin’in mevsim menüsü ve Bozcaada bağlarından seçilmiş şaraplar.

Tue–Sun
18:00–23:30
Tasting menu
₺2.450
Seats
48

Scoped provider

useFontPairing() reads and sets the pairing of the nearest FontProvider. scope="document" applies it to <html> instead.

Journal · 6 min read

How we cut onboarding from nine days to two

Our HR team rebuilt the first week around one checklist, three owners and a shared calendar. Here is what changed.

Set in Newsroom

API

FontPicker

PropTypeDefault
value
Selected family name (controlled). null = nothing selected.
string | null—
defaultValue
Initial family (uncontrolled).
string | null—
onValueChange
Called on selection; the popover then closes and focus returns to the trigger.
(family: string, font: GoogleFont) => void—
fonts
Families to offer. Default: the 59-family catalog.
GoogleFont[]googleFonts
categories
"sans" | "serif" | "display" | "rounded" | "condensed" | "mono" | "handwriting".
FontCategory[]—
previewText
Sample line under each family.
string"Hamburgefonstiv — Ağaç işçiliği"
loadPreviews
Load glyph-subset previews (a few KB per visible family) from Google Fonts. Turn off when you self-host.
booleantrue
specimen
Large specimen of the active row at the bottom of the panel.
booleantrue
listHeight
Max height of the scrolling list.
string"18rem"
size
Trigger height; md follows --control-h.
"sm" | "md" | "lg""md"
placeholder
Trigger text when empty.
string"Choose a font"
showCategory
Show the group ("Serif · Display") beside the family in the trigger.
booleantrue
open / defaultOpen / onOpenChange
Popover state, controlled or not.
boolean / boolean / (open) => void—
align
Popover alignment against the trigger.
"start" | "center" | "end""start"
name / required
Adds a hidden input for native form posts.
string / boolean—
disabled
Also read from the surrounding Field.
booleanfalse
contentClassName
Class for the popover panel.
string—
labels
Built-in strings (namespace fontPicker): placeholder, search, searchPlaceholder, categories, all, list, empty, results, variable, italic, weights.
Partial<FontPickerLabels>—

FontPickerList

PropTypeDefault
value / defaultValue / onValueChange
Same as FontPicker.
string | null / string | null / (family, font) => void—
fonts · categories · previewText · loadPreviews · specimen · listHeight · labels
Same as FontPicker.
——
autoFocus
Focus the search field on mount.
booleanfalse

FontPairingPicker

PropTypeDefault
value / defaultValue
Selected pairing id.
string | null—
onValueChange
Called when a pairing is chosen (click, arrows, Home/End).
(id: string, pairing: FontPairing) => void—
pairings
The 16 built-ins, or your own.
FontPairing[]fontPairings
layout
Specimen cards, or compact rows for popovers.
"grid" | "list""grid"
showDescription
Show the one-line description.
booleangrid: true · list: false
loadPreviews
Load preview glyphs from Google Fonts.
booleantrue
disabled
Disables every option.
booleanfalse
labels
Namespace fontPairingPicker: label.
Partial<FontPairingPickerLabels>—

FontProvider

PropTypeDefault
pairing / defaultPairing
Pairing object or preset id.
FontPairing | string"editorial"
onPairingChange
Called by useFontPairing().setPairing.
(pairing: FontPairing) => void—
scope
element: wraps children in a <div> carrying the tokens. document: applies to <html>, restored on unmount.
"element" | "document""element"
load
Load the families from Google Fonts.
booleantrue
pairings
Presets resolvable by id.
FontPairing[]fontPairings
className
Class of the wrapper (element scope).
string—

Helpers

PropTypeDefault
loadGoogleFonts(families, options?)
Injects one <link rel=stylesheet> (plus preconnect) for the families not loaded yet. Options: display (default "swap"), text, opticalSize, renderBlocking, document.
Promise<void>—
googleFontsUrl(families, options?)
The css2 URL — use it in a server-rendered <link>.
string—
applyFontPairing(el, pairing, options?)
Sets data-font, --font-ui / --font-heading / --font-code and the four --display-* tokens; loads the fonts.
Promise<void>—
createFontPairing({ heading, body, mono })
Custom pairing; display tokens follow the heading family.
FontPairing—
serializeFontPairing / parseFontPairing
Store a pairing (with its URL and tokens) in localStorage or a cookie.
StoredFontPairing ⇄ FontPairing—
fontBootScript(storageKey?, field?)
Inline <head> script that applies a stored pairing before first paint.
string—