UNPKG

@kiwicom/orbit-components

Version:

Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com's products.

429 lines (427 loc) 12.6 kB
"use strict"; "use client"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; exports.__esModule = true; exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _clsx = _interopRequireDefault(require("clsx")); var _consts = require("./consts"); function getCountryProps(code) { const codeNormalized = code ? code.toUpperCase().replace("-", "_") : "UNDEFINED"; const countryCodeExists = (codeNormalized in _consts.CODES); if (!countryCodeExists) console.warn(`Country code not supported: ${code}`); const countryCode = countryCodeExists ? _consts.CODES[codeNormalized] : _consts.CODES.UNDEFINED; return { code: countryCode }; } /** * @orbit-doc-start * README * ---------- * # CountryFlag * * To implement CountryFlag component into your project you'll need to add the import: * * ```jsx * import CountryFlag from "@kiwicom/orbit-components/lib/CountryFlag"; * ``` * * After adding import into your project you can use it simply like: * * ```jsx * <CountryFlag code="cz" name="Czech Republic" /> * ``` * * ## Props * * Table below contains all types of the props available in CountryFlag component. * * | Name | Type | Default | Description | * | :------- | :----------------------------------------------- | :------------ | :----------------------------------------- | * | code | [`enum`](#enum) | `"undefined"` | Code for the displayed country flag. | * | dataTest | `string` | | Optional prop for testing purposes. | * | id | `string` | | Set `id` for `CountryFlag`. | * | name | `string` | `""` | Defines the `alt` attribute for the image. | * | role | `React.HTMLAttributes<HTMLImageElement>["role"]` | | ARIA role for the flag image. | * | size | [`enum`](#enum) | `"medium"` | The size of the CountryFlag. | * * ### enum * * If code doesn't exist "undefined" will be used. * * | code | size | * | :------------ | :--------- | * | `"ad"` | `"small"` | * | `"ae"` | `"medium"` | * | `"af"` | * | `"ag"` | * | `"ai"` | * | `"al"` | * | `"am"` | * | `"an"` | * | `"anywhere"` | * | `"ao"` | * | `"aq"` | * | `"ar"` | * | `"as"` | * | `"at"` | * | `"au"` | * | `"aw"` | * | `"ax"` | * | `"az"` | * | `"ba"` | * | `"bb"` | * | `"bd"` | * | `"be"` | * | `"bf"` | * | `"bg"` | * | `"bh"` | * | `"bi"` | * | `"bj"` | * | `"bl"` | * | `"bm"` | * | `"bn"` | * | `"bo"` | * | `"bq"` | * | `"br"` | * | `"bs"` | * | `"bt"` | * | `"bv"` | * | `"bw"` | * | `"by"` | * | `"bz"` | * | `"ca-fr"` | * | `"ca"` | * | `"cc"` | * | `"cd"` | * | `"cf"` | * | `"cg"` | * | `"ch"` | * | `"ci"` | * | `"ck"` | * | `"cl"` | * | `"cm"` | * | `"cn"` | * | `"co"` | * | `"cr"` | * | `"cs"` | * | `"ct"` | * | `"cu"` | * | `"cv"` | * | `"cw"` | * | `"cx"` | * | `"cy"` | * | `"cz"` | * | `"de"` | * | `"dj"` | * | `"dk"` | * | `"dm"` | * | `"do"` | * | `"dz"` | * | `"ec"` | * | `"ee"` | * | `"eg"` | * | `"eh"` | * | `"er"` | * | `"es"` | * | `"et"` | * | `"eu"` | * | `"fi"` | * | `"fj"` | * | `"fk"` | * | `"fm"` | * | `"fo"` | * | `"fr"` | * | `"ga"` | * | `"gb"` | * | `"gd"` | * | `"ge"` | * | `"gf"` | * | `"gg"` | * | `"gh"` | * | `"gi"` | * | `"gl"` | * | `"gm"` | * | `"gn"` | * | `"gp"` | * | `"gq"` | * | `"gr"` | * | `"gs"` | * | `"gt"` | * | `"gu"` | * | `"gw"` | * | `"gy"` | * | `"hk"` | * | `"hm"` | * | `"hn"` | * | `"hr"` | * | `"ht"` | * | `"hu"` | * | `"ic"` | * | `"id"` | * | `"ie"` | * | `"il"` | * | `"im"` | * | `"in"` | * | `"io"` | * | `"iq"` | * | `"ir"` | * | `"is"` | * | `"it"` | * | `"je"` | * | `"jm"` | * | `"jo"` | * | `"jp"` | * | `"ke"` | * | `"kg"` | * | `"kh"` | * | `"ki"` | * | `"km"` | * | `"kn"` | * | `"kp"` | * | `"kr"` | * | `"kw"` | * | `"ky"` | * | `"kz"` | * | `"la"` | * | `"lb"` | * | `"lc"` | * | `"li"` | * | `"lk"` | * | `"lr"` | * | `"ls"` | * | `"lt"` | * | `"lu"` | * | `"lv"` | * | `"ly"` | * | `"ma"` | * | `"mc"` | * | `"md"` | * | `"me"` | * | `"mf"` | * | `"mg"` | * | `"mh"` | * | `"mk"` | * | `"ml"` | * | `"mm"` | * | `"mn"` | * | `"mo"` | * | `"mp"` | * | `"mq"` | * | `"mr"` | * | `"ms"` | * | `"mt"` | * | `"mu"` | * | `"mv"` | * | `"mw"` | * | `"mx"` | * | `"my"` | * | `"mz"` | * | `"na"` | * | `"nc"` | * | `"ne"` | * | `"nf"` | * | `"ng"` | * | `"ni"` | * | `"nl"` | * | `"no"` | * | `"np"` | * | `"nr"` | * | `"nu"` | * | `"nz"` | * | `"om"` | * | `"pa"` | * | `"pe"` | * | `"pf"` | * | `"pg"` | * | `"ph"` | * | `"pk"` | * | `"pl"` | * | `"pm"` | * | `"pn"` | * | `"pr"` | * | `"ps"` | * | `"pt"` | * | `"pw"` | * | `"py"` | * | `"qa"` | * | `"re"` | * | `"ro"` | * | `"rs"` | * | `"ru"` | * | `"rw"` | * | `"sa"` | * | `"sb"` | * | `"sc"` | * | `"sd"` | * | `"se"` | * | `"sg"` | * | `"sh"` | * | `"si"` | * | `"sj"` | * | `"sk"` | * | `"sl"` | * | `"sm"` | * | `"sn"` | * | `"so"` | * | `"sr"` | * | `"ss"` | * | `"st"` | * | `"sv"` | * | `"sx"` | * | `"sy"` | * | `"sz"` | * | `"tc"` | * | `"td"` | * | `"tf"` | * | `"tg"` | * | `"th"` | * | `"tj"` | * | `"tk"` | * | `"tl"` | * | `"tm"` | * | `"tn"` | * | `"to"` | * | `"tr"` | * | `"tt"` | * | `"tv"` | * | `"tw"` | * | `"tz"` | * | `"ua"` | * | `"ug"` | * | `"um"` | * | `"undefined"` | * | `"us"` | * | `"uy"` | * | `"uz"` | * | `"va"` | * | `"vc"` | * | `"ve"` | * | `"vg"` | * | `"vi"` | * | `"vn"` | * | `"vu"` | * | `"wf"` | * | `"ws"` | * | `"xk"` | * | `"ye"` | * | `"yt"` | * | `"za"` | * | `"zm"` | * | `"zw"` | * * * Accessibility * ------------- * ## Accessibility * * The CountryFlag component has been designed with accessibility in mind, providing flexible options for screen reader support depending on the context in which the flag is used. * * ### Accessibility Props * * **CountryFlag props:** * * | Name | Type | Description | * | :--- | :----------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | * | name | `string` | Defines the `alt` attribute for the flag image. Defaults to an empty string `""`, making the flag invisible to screen readers when no accessible name is needed. | * | role | `React.HTMLAttributes<HTMLImageElement>["role"]` | ARIA role for the flag image. The `name` prop should be used instead as it provides better screen reader support. | * * ### Automatic Accessibility Features * * - The component automatically applies the `name` prop value as the `alt` attribute on the flag image. * - When `name` is empty (default), the flag is treated as decorative and is not announced by screen readers. * - Focus management is not applicable as the component is not interactive. * * ### Best Practices * * - Use the `name` prop to provide an accessible name when the flag conveys important information. * - Leave `name` empty when the flag is purely decorative or when country information is provided by adjacent text. * - Avoid providing a `name` value that duplicates text content placed immediately next to the flag, as this creates redundant announcements for screen reader users. * - Prefer using the `name` prop over the `role` prop for better cross-platform screen reader support. * - When displaying multiple flags in a list or grid, ensure each flag has a meaningful and unique accessible name when necessary. * - Always localize country names in the `name` prop to match the user's language preferences for proper screen reader pronunciation and comprehension. * * ### Keyboard Navigation * * The CountryFlag component is not interactive and does not receive keyboard focus. No keyboard navigation is applicable. * * ### Examples * * _Note: Country names in examples are shown in English for demonstration purposes. In production, always use localized country names appropriate for your user's language._ * * #### Flag with accessible name * * ```jsx * <CountryFlag code="cz" name="Czech Republic" /> * ``` * * Screen reader announces: "Czech Republic, image" * * #### Decorative flag next to text label * * ```jsx * <Stack direction="row" spacing="100" align="center"> * <CountryFlag code="cz" /> * <Text>Czech Republic</Text> * </Stack> * ``` * * Screen reader announces: "Czech Republic" (only the text is announced) * * #### Flag in a list context * * ```jsx * <Stack direction="column"> * <CountryFlag code="us" name="United States" /> * <CountryFlag code="ca" name="Canada" /> * <CountryFlag code="mx" name="Mexico" /> * </Stack> * ``` * * Screen reader announces: "United States, image", "Canada, image", "Mexico, image" * * #### Flag without accessible name (decorative) * * ```jsx * <CountryFlag code="gb" /> * ``` * * Screen reader announces: (nothing - flag is treated as decorative) * * * @orbit-doc-end */ const CountryFlag = ({ dataTest, size = _consts.SIZES.MEDIUM, id, role, name = "", ...props }) => { const { code } = getCountryProps(props.code); const width = _consts.SIZE_WIDTHS[size]; const src = `${_consts.baseURL}/flags/${width}x0/flag-${code.toLowerCase()}.jpg`; const srcSet = `${_consts.baseURL}/flags/${width * 2}x0/flag-${code.toLowerCase()}.jpg 2x`; return /*#__PURE__*/_react.default.createElement("div", { className: (0, _clsx.default)("orbit-country-flag", "rounded-50 bg-country-flag-background relative shrink-0 overflow-hidden", { "h-country-flag-small w-country-flag-small": size === _consts.SIZES.SMALL, "h-country-flag-medium w-country-flag-medium": size === _consts.SIZES.MEDIUM }) }, /*#__PURE__*/_react.default.createElement("img", { className: "block size-full shrink-0", key: code, alt: name, id: id, "data-test": dataTest, src: src, srcSet: srcSet, role: role }), /*#__PURE__*/_react.default.createElement("div", { className: "rounded-50 shadow-country-flag absolute inset-0 block size-full" })); }; var _default = exports.default = CountryFlag;