Skip to content

ae9is/react-fontpicker

Repository files navigation

react-fontpicker

A Google font picker component for React.

  • No dependencies (other than React)
  • No Google API key required
  • 1600+ Google fonts, customisable
  • Fast, high quality font previews from pre-generated SVG images
  • Optionally autoloads fonts

Forked from https://github.com/Mikk3lRo/vue-fontpicker/

Animation showing the font picker

Documentation

A live demo including usage is available at: https://ae9is.github.io/react-fontpicker/

Installing

# npm
npm i react-fontpicker-ts
# yarn
yarn add react-fontpicker-ts

# much smaller package with fewer fonts
npm i react-fontpicker-ts-lite

Then, import the component and stylesheet:

import FontPicker from 'react-fontpicker-ts'
import 'react-fontpicker-ts/dist/index.css'

Styling

See css classnames in: packages/fontpicker/src/components/FontPicker.css

An example restyling the font picker

An example integrating the font picker into an actual app: ae9is/uimix

Project structure

The font picker project lives in this Turborepo monorepo at packages/fontpicker/

The live demo is a Vite app you can run yourself via npm run dev and which builds to /docs. Uses tsconfig.json.

The font picker component itself builds via tsup (i.e. esbuild) to /dist with type definitions generated via tsc according to tsconfig.types.json.

The font preview generation script downloads font files to /font-cache and builds font image previews to /font-preview.

Performance

The font picker previews work by loading font preview image files in CSS. The fonts are split across many image files for faster initial preview.

Once the dropdown select is opened, all the preview image files are retrieved enabling smooth scrolling and searching.

No requests are made to the Google fonts API unless the font picker is set to autoload, in which case the currently selected font is appended to the page header. (The previously selected font link is not removed.)

For example:

<head>
  ...
  <link
    rel="stylesheet"
    id="google-font-rock_salt-all"
    href="https://fonts.googleapis.com/css2?family=Rock Salt:ital,wght@0,400&amp;display=swap"
  />
</head>

The big trade-off of this approach is that the component's bundle is quite large due to all the font image previews: 8 MB in compressed SVG images for 1633 fonts. Make sure you serve compressed SVGs! See here for an example for Vite.

If you're looking for a lighter weight option, you can use react-fontpicker-ts-lite instead which is around 180 KB.

Or, for a different font picker following an on demand approach, check out: https://github.com/samuelmeuli/font-picker-react

font-picker-react requires a Google API key, and works best at the default font limit of 50 (fonts to choose from).

Building font previews

Note: most users shouldn't need to rebuild the font previews, but this section is included for convenience if you need to grab the latest fonts or edit the previews.

1. Google API key

Get a Google API key here https://developers.google.com/fonts/docs/developer_api#APIKey and create a new file called GOOGLE_API_KEY in react-fontpicker/packages/fontpicker/scripts, in the same directory as the scripts/buildFontPreviews.ts script.

2. Font preview script

All Google fonts

To generate font previews for all currently available Google fonts (latin font families only, minus Kumar One).

cd react-fontpicker/packages/fontpicker
npm run build-font-previews

Note: For 1600 fonts, budget 20-30 minutes and 800 MB to download all the fonts. Compiling the image previews themselves should be less than a minute. When re-running, the script only retrieves new font info if it's older than 1 week and skips downloading cached fonts.

Custom fonts

To generate font previews for custom fonts you'll need some info about the fonts and paths to the font file downloaded in TTF format.

buildFontPreviews.ts output-dir "font-name|font-category|font-variants-info|font-file" "font-name-2..."

Where font-variants-info is an array of values like 0,400 and 1,700 joined by +. The first value denotes a normal (0) or italic (1) font. The second value is the font weight (i.e. 100 = thin, 400 = normal, 700 = bold, 900 = heavy).

For example:

buildFontPreviews.ts output-dir "FontName|sans-serif|0,400+0,700+1,400+1,700|/path/to/font.ttf" "Font2|serif|0,400|/path/to/font2.ttf"

See the build-font-previews-manual run script in: packages/fontpicker/package.json

Development

Installation

This monorepo uses Turborepo.

Testing

The app uses Vitest and Cypress for testing. Make sure to setup the prerequisites for Cypress on your system.

On Ubuntu:

apt install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb