Font Family Combobox
A searchable font-family picker for Tiptap editors. The trigger shows the active font; opening it reveals a fuzzy search field and fonts grouped by category, each previewed in its own typeface. A “Default font” option unsets any inline font.
It is a richer, searchable counterpart to the font-family-dropdown-menu, and it pairs with the FontFamily mark from @tiptap/extension-text-style. The component is catalog-agnostic: pass your own fonts, categories, and defaultFont, or rely on the bundled web-safe defaults. All editor logic lives in the useFontFamilyCombobox hook.
Installation
Add the component via the Tiptap CLI:
npx @tiptap/cli@latest add font-family-comboboxComponents
<FontFamilyCombobox />
A prebuilt searchable font picker built on Ariakit’s menu-with-combobox composite.
Usage
export default function MyEditor() {
return (
<FontFamilyCombobox
editor={editor}
hideWhenUnavailable={true}
onOpenChange={(isOpen) => console.log('Picker', isOpen ? 'opened' : 'closed')}
/>
)
}To use your own catalog, supply fonts, categories, and defaultFont. Each option’s category is matched against a category id, and an option’s optional fallbackFor lets imported system fonts (e.g. "Arial") resolve to a bundled family.
const fonts = [
{ value: 'inter', label: 'Inter', family: 'Inter', hint: 'UI sans', category: 'sans-serif', default: true },
{ value: 'georgia', label: 'Georgia', family: 'Georgia, serif', hint: 'Serif', category: 'serif' },
]
const categories = [
{ id: 'sans-serif', label: 'Sans-serif' },
{ id: 'serif', label: 'Serif' },
]
<FontFamilyCombobox editor={editor} fonts={fonts} categories={categories} defaultFont={fonts[0]} />Props
The component also forwards any extra Button props (except type) to the trigger.
| Name | Type | Default | Description |
|---|---|---|---|
editor | Editor | null | undefined | The Tiptap editor instance. |
fonts | FontFamilyOption[] | defaultFontFamilyOptions | The fonts to offer in the picker. |
defaultFont | FontFamilyOption | defaultFontFamilyOption | The font the document falls back to when no inline font is applied. |
categories | FontFamilyCategory[] | defaultFontFamilyCategories | Category groups to render, matched against each font’s category. |
hideWhenUnavailable | boolean | false | Hides the picker when font family cannot be applied. |
onOpenChange | (boolean) => void | undefined | Callback for when the picker opens or closes. |
Types
interface FontFamilyOption {
label: string // display name in the picker
value: string // stable identifier
family: string // CSS font-family applied to the document; previewed in this typeface
hint?: string // short descriptor under the label, e.g. "Calibri-like"
category: string // group id (matched against a FontFamilyCategory)
default?: boolean // marks the default option (no inline font)
fallbackFor?: string[] // system fonts this family stands in for on import
}
interface FontFamilyCategory {
id: string
label: string
}Hooks
useFontFamilyCombobox()
A headless hook exposing the selection state and actions needed to build a custom font picker.
Usage
function MyFontPicker() {
const { isVisible, triggerLabel, selectFont, selectDefault, filterFonts } = useFontFamilyCombobox(
{ editor, hideWhenUnavailable: true },
)
if (!isVisible) return null
const results = filterFonts('geo') // ranked matches for a search query
// …render your own UI using selectFont(font) / selectDefault()
}Props
| Name | Type | Default | Description |
|---|---|---|---|
editor | Editor | null | undefined | The Tiptap editor instance. |
fonts | FontFamilyOption[] | defaultFontFamilyOptions | The fonts to offer. |
defaultFont | FontFamilyOption | defaultFontFamilyOption | The document’s fallback font when nothing inline is set. |
hideWhenUnavailable | boolean | false | Hides the picker when font family is unavailable. |
Return Values
| Name | Type | Description |
|---|---|---|
isVisible | boolean | Whether the picker should be rendered. |
canToggle | boolean | Whether font family can be applied in the current state. |
isActive | boolean | Whether an explicit inline font is active (not the default). |
fonts | FontFamilyOption[] | The configured fonts. |
defaultFont | FontFamilyOption | The configured default font. |
selectionState | FontFamilySelectionState | The selection’s font state (default / font / mixed). |
activeFontFamily | string | The applied font-family for the selection (empty when default). |
activeFont | FontFamilyOption | undefined | The resolved option for the active family, if any. |
triggerLabel | string | Label for the trigger (active font, Mixed, or Default · …). |
selectFont | (font: FontFamilyOption) => void | Apply a font family to the selection. |
selectDefault | () => void | Unset any inline font (use the document default). |
filterFonts | (query: string) => FontFamilyOption[] | Rank the configured fonts against a search query. |
Utilities
Default catalog
import {
defaultFontFamilyOptions,
defaultFontFamilyCategories,
defaultFontFamilyOption,
} from '@/components/tiptap-ui/font-family-combobox'A web-safe set (Arial, Verdana, Tahoma, Times New Roman, Georgia, Courier New) grouped into Sans-serif / Serif / Monospace, so the component is usable out of the box without loading any webfont.
Helpers
import {
filterFontsByQuery,
findFontByFamily,
resolveFontFamily,
getActiveFontOption,
getFontFamilySelectionState,
getFontFamilyTriggerLabel,
} from '@/components/tiptap-ui/font-family-combobox'
filterFontsByQuery(fonts, 'geo') // ranked matches (blank query → unchanged order)
findFontByFamily(fonts, 'Georgia') // the option whose family matches, or undefined
resolveFontFamily(fonts, 'Arial') // map a system font through each option's fallbackFor
getActiveFontOption(fonts, 'Inter') // resolve an applied family to an option
getFontFamilySelectionState(editor) // { kind: 'default' | 'font' | 'mixed', fontFamily }
getFontFamilyTriggerLabel(state, defaultFont, fonts) // the trigger label stringRequirements
Dependencies
@tiptap/react— Core Tiptap React integration@tiptap/pm— ProseMirror model/state used to read the selection’s font marksmatch-sorter— Fuzzy ranking for the search field@tiptap/extension-text-style— Provides theFontFamilymark this picker applies
Referenced Components
use-tiptap-editor(hook)use-composed-ref(hook)font-family-dropdown-menu(component — shared editor helpers)button(primitive)combobox(primitive)input(primitive)menu(primitive)check-icon(icon)chevron-down-icon(icon)