Skip to content
Cloaked Design SystemPrimitives

Flag

A country flag as a circular mark, drawn from vendored artwork so it is consistent across platforms and controllable in a flat interface.

Implementation preview
COMPLETE STORYBOOK REFERENCE

Every example. In one place.

Explore every named example, including states, compositions, and theme variants.

6 stories
SELECTED EXAMPLE

Default

Open controls
Default selectedOpen canvas
Example sourcepackages/design-system/src/components/primitives/Flag/Flag.stories.tsxExport Default

Implementation preview Local Storybook build 0.2.0-preview.1. Source specification status does not approve this runtime.

Stories + source JSON ↗

Local specification source status: preview. Implementation preview pending sign-off.

A country flag as a circular mark, drawn from vendored artwork so it is consistent across platforms and controllable in a flat interface.

Design-owned component contract ↗Version 0.2.0-preview.1 · Implementation preview pending sign-off
Implementation API 1 entry point · source-derived preview

Read the actual callable API and preserve its composition constraints. Each union branch is a complete alternative; props marked forbidden cannot be supplied.

import { Flag } from '@cloakedinc/design-system';
FlagFlagProps

packages/design-system/src/components/primitives/Flag/Flag.tsx:58

PropTypePresenceNotes
codestringRequiredISO 3166-1 alpha-2 country code, any casing. Deliberately a plain string: codes arrive from backend and bridge payloads, and an unknown one renders nothing rather than breaking a row.
sizeFlagSizeRequiredRendered scale.
labelstring | undefinedOptionalAccessible label, e.g. the country name. Without one the flag is hidden from assistive tech — correct when the country is already named in adjacent text, which is the common case.
classNamestring | undefinedOptional
testIdstring | undefinedOptionalOptional test selector.

Only explicit destructured parameter initializers are extracted. Other runtime defaults remain in implementation source.

Overview

A country flag as a circular mark, keyed by ISO 3166-1 alpha-2 code.

Why not the flag emoji

Emoji flags are drawn by the platform, so they arrive glossy and waving in an otherwise flat interface, at a size and baseline the design system cannot control. On iOS they at least render; on Windows there are no flag glyphs at all and the browser falls back to showing the two letters.

The deciding reason here is internal consistency: the iOS app has always shipped circular flag artwork, so emoji in the webview made one product look like two.

Use it for places, not languages

A flag names a country or a server location. It does not name a language — the same language spans many countries, and picking one country's flag for it is both inaccurate and easy to take badly.

Keep the place named in text beside the mark. A flag on its own is ambiguous to plenty of readers, which is also why label is optional: when the adjacent text already says "Amsterdam", the flag is decorative and should be hidden from assistive technology rather than announced twice.

The ring is load-bearing

Several flags are mostly white — Japan, Poland, Finland. Without a hairline ring they dissolve into a light card, and Japan in particular reads as a red dot floating in space.

Codes come from payloads

code is a plain string rather than a union, because country codes arrive from backend responses and native bridge payloads. An unrecognized code renders nothing, so a country we have no artwork for costs a mark instead of breaking the row. Narrow with isFlagCode when the caller wants to render a fallback instead.

Artwork

Vendored from circle-flags (MIT), covering the 89 countries the VPN catalog can return. scripts/generateFlagRegistry.ts bakes them into shape data at build time, stripping each source file's circular mask — every file uses the same mask id, so inlining two would make the second resolve against the first. Flag restores the circle with border-radius, which is also what makes room for the ring. The whole set is 89 flags in 329 shapes, about 10 KB gzipped.

Component specification

$schema../../../specs/component-spec.schema.json
Parts
Id
artwork
Label
Artwork
Description
The flag geometry, clipped to a circle.
Required
true
Id
ring
Label
Ring
Description
Hairline inset ring that keeps white-field flags from dissolving into a light surface.
Required
true
Allowed Design Choices
Variants
Base
Label
Base
Description
One treatment; the country changes the artwork, not the styling.
Sizes
Sm
Label
Small
Description
Inline with body and body-small text.
Md
Label
Medium
Description
List rows and compact headers.
Lg
Label
Large
Description
Leading mark on a row or card.
Variants
Id
base
Label
Base
Description
A circular flag mark.
Platforms
  • ios
  • android
  • web
Sizes
Id
sm
Label
Small
Description
16px.
Id
md
Label
Medium
Description
20px.
Id
lg
Label
Large
Description
24px.
Measurements
Id
size-sm
Label
Small diameter
Kind
exact
Token
--cds-size-16
Value
16
Unit
px
Applies To
  • artwork
Id
size-md
Label
Medium diameter
Kind
exact
Token
--cds-size-20
Value
20
Unit
px
Applies To
  • artwork
Id
size-lg
Label
Large diameter
Kind
exact
Token
--cds-size-24
Value
24
Unit
px
Applies To
  • artwork
Id
ring-width
Label
Ring width
Kind
exact
Token
--cds-border-width-hairline
Value
0.5
Unit
px
Applies To
  • ring
Layout
Alignment
Inline-block, nudged up slightly so it centers against adjacent text rather than sitting on the baseline.
Flow
A fixed-size circular mark; it never stretches to its container.
Notes
  • The artwork is a full square clipped to a circle in CSS. The vendored source set masks itself with an id that is identical in every file, so inlining the mask would collide across instances.
Typography And Color
Typography
None specified
Colors
Label
Ring
Description
Hairline ring around the artwork.
Token
--cds-divider
States
Id
known
Label
Known country
Description
A country with vendored artwork renders its flag.
Id
unknown
Label
Unknown country
Description
An unrecognized code renders nothing, so a missing flag costs a mark rather than breaking the row.
Behavior
Label
Case-insensitive codes
Description
Codes are matched lowercased, so bridge and backend casing both resolve.
Label
Untrusted input
Description
The code prop is a plain string because codes arrive from payloads; isFlagCode narrows it when a caller needs a fallback.
Accessibility
Label
Named country
Description
Pass a label when the flag is the only indication of the country, so it is announced as a meaningful image.
Label
Decorative flag
Description
Omit the label when adjacent text already names the country; the flag is then hidden from assistive technology.
Content Adaptation
Label
Pair with the country name
Description
A flag alone is ambiguous to many readers; keep the country or city in text beside it.
Label
Not for language
Description
Use a flag for a country or a server location, never to indicate a language.
Motion Haptics
Motion
Label
Static
Description
The mark does not animate.
Haptics
Label
No feedback
Description
The flag is a display and requests no haptic feedback.
Platform DifferencesNone specified
Implementation preview

This design-owned implementation is ready to try and review. It does not establish product approval. Imported specifications retain their original review status.

Inspect version 0.2.0-preview.1