A flag is an image. The emoji version of it is the thing this component exists to replace:
a flag emoji is a pair of regional-indicator code points (U+1F1EA U+1F1F8 for Spain), and
Windows has never shipped a glyph for that pair, so it renders as the two bare letters
“ES” for most desktop readers. There is no font stack that fixes it, and on the platforms
that do draw a flag, each one draws a different one.
import { Flag } from "@enigmax/primitives/react/flag";
<Flag code="es" size={24} />Usage
Installation
Adds the package and prints the import to use. This is the way to use them: the package keeps getting fixes, and a dependency is how they reach you.
enigma add flagsInstalls with your project's own package manager - npm, pnpm, yarn or bun - read from its packageManager field or its lockfile.
--copy writes the source into your project instead. Reach for it to EDIT a component, not to use one: a copy is frozen at today's version and stops receiving fixes.
1 Install the dependencies
2 Use it
Import from @enigmax/primitives/react/flag.
Nothing else to install. The images are served by enigma unless you download them.
The name is automatic
<Flag code="es" /> is announced as Spain - or España on a Spanish page - because the
name comes from Intl.DisplayNames, which is already in the runtime, already translated,
and maintained by whoever maintains the platform. No table of 250 country names ships with
the component, and none of them goes stale.
It lands on alt AND on title, because those do different jobs and only one of them is
visible: alt is what a screen reader reads and what shows when the image does not load,
while a hover tooltip comes from title and from nothing else.
| nothing | The country’s own name, in the reader’s language, read out and shown on hover |
label="Spanish" |
Yours, when the flag stands for a language or a region rather than a country |
decorative |
No name at all. Right beside a country name that is already on screen, where repeating it makes a screen reader say it twice |
A name is never invented. A subdivision such as gb-eng is England, and falling back to its
region would announce “United Kingdom” - confidently wrong - so it renders as decoration
instead. Same for a runtime with no Intl.
The code you pass
code takes what a codebase already holds, which is rarely a tidy ISO code:
es, ES |
The code |
Spain, spain, Cote d'Ivoire |
The NAME, in English or in the page’s language. Accents, apostrophes, & for and and St. for Saint are all folded |
en-GB, es_ES |
A locale tag |
gb-eng, au-nsw, es-ct |
A subdivision |
| the emoji flag | So a migration is the component and nothing else |
uk, an, su |
Alias codes, canonicalized to gb, cw, ru - uk.svg does not exist |
The name comes from the runtime’s own region data, so there is no table of 250 names here to
go stale, and <Flag code={row.country} /> works against a column that holds “Germany”.
Anything else is null, deliberately. A bare word used to be taken as a file name and
rendered as a broken image with no alt text, which is worse than no flag: banana and zz
resolve to nothing now, and only a name with a separator (easter_island) is taken on
trust, because nothing can check those without shipping the whole directory listing.
A BCP 47 tag is read by its casing, before anything is lowercased: es-ES is a locale
and means the flag es, while es-ct is Catalonia and means the file es-ct. Lowercasing
first makes those the same string, and then one of them is always wrong.
A code that resolves to nothing renders fallback (nothing, by default). Never a broken
image: a 404 with no alt text beside a country name is worse than no flag.
Where the images come from
enigma serves all three sets over a CDN, so nothing has to be installed and no request goes to anyone else:
| Shape | Ratio | |
|---|---|---|
rect (default) |
the usual rectangular artwork | 4:3 |
square |
the same flags, cropped square | 1:1 |
circle |
round, for a chip or an avatar row | 1:1 |
For a project that will not make a third-party request at runtime - an offline install, a
CSP with no img-src for a CDN, a build that must not break the day a CDN does - the same
files are downloaded into the project:
enigma add flags --flags localIt asks which sets, which countries and which formats, and writes
public/flags/<shape>/<code>.<format>. Non-interactively it takes every set and every
country. Then one line at startup moves the whole app onto those files:
import { configureFlags } from "@enigmax/primitives";
configureFlags({ source: "local", basePath: "/flags" });
source also takes a URL of your own, for a mirror with the same layout.
| Flag | |
|---|---|
--flags cdn|local |
served by enigma, or files in the project |
--flag-shapes rect,square,circle|all |
which sets to download |
--flag-formats svg,png,webp |
png and webp are rasterised locally and need sharp |
--countries es,fr,us|all |
which countries |
--flags-out <dir> |
default public/flags |
The artwork is stored as SVG, so that is what a remote source serves. Ask for webp and
you get SVG plus one warning in development; png and webp are for a local set, where
they are rasterised at download time.
| Prop | |
|---|---|
code |
es, ES, en-GB, gb-eng, or the emoji |
label |
Your own accessible name. Automatic when omitted |
decorative |
Renders with no name at all |
locale |
Language the automatic name is written in. Follows the document’s lang otherwise |
shape |
rect (default), square, circle |
size |
Rendered height in px, default 16. Width follows the shape |
format |
svg (default), png, webp |
source |
cdn (default), local, or a base URL |
basePath |
Where a local set is served from, default /flags |
fallback |
Rendered when the code resolves to nothing |
Styling hooks: [data-enigma-flag], plus [data-flag-shape] and [data-flag-code].