Back to Blog

dirham v1.5.3: The Complete Guide to UAE Dirham in React, Web Components, and Vanilla JS

ReactTypeScriptOpen SourceUnicodeCurrencyUAEnpmFintechdirhamAEDU+20C3Web ComponentsNext.js
dirham v1.5.3 — UAE Dirham symbol in React, Web Components, and TypeScript

The UAE Dirham got its Unicode codepoint — U+20C3 — in July 2025. The symbol won't render natively on most devices until Unicode 18.0 font support ships in late 2026. In the meantime, dirham gives you the correct codepoint today, backed by a web font that you'll delete in one line when OS support arrives.

v1.5.3 is a large release. Animated counters, masked inputs, live exchange rates, Web Components for every primitive, a Tailwind plugin, a Next.js font helper, React Native support, and OG card generation. This post covers all of it.

Links: npm · GitHub · Docs


Installation

bash
pnpm add dirham # or npm install dirham # or yarn add dirham

React Components

DirhamSymbol

Renders an inline SVG. SSR-compatible, no font loading, fully tree-shakeable:

tsx
import { DirhamSymbol } from 'dirham/react'; <DirhamSymbol size={24} weight="bold" /> <DirhamSymbol size={48} weight="thin" />

Nine weight variants map directly to surrounding typography: thin, extralight, light, regular, medium, semibold, bold, extrabold, black.

DirhamIcon

Font-based glyph — lighter markup, requires dirham/css:

tsx
import 'dirham/css'; import { DirhamIcon } from 'dirham/react'; <DirhamIcon size={24} weight="regular" />

DirhamPrice

Combines the symbol with Intl.NumberFormat formatting:

tsx
import { DirhamPrice } from 'dirham/react'; <DirhamPrice amount={1250} /> <DirhamPrice amount={1500000} notation="compact" weight="bold" /> <DirhamPrice amount={100} useCode /> <DirhamPrice amount={750} locale="ar-AE" />
PropDefaultDescription
amount0Numeric value
locale"en-AE"Intl locale string
decimals2Decimal places
notation"standard""standard" or "compact"
useCodefalseShow AED instead of the symbol
weight"regular"Symbol stroke weight
classNameTailwind / CSS classes

AnimatedDirhamPrice

60fps count-up animation from zero to the target amount:

tsx
import { AnimatedDirhamPrice } from 'dirham/react'; <AnimatedDirhamPrice amount={1250} /> <AnimatedDirhamPrice amount={5000000} notation="compact" duration={2000} />

The duration prop controls animation length in milliseconds (default: 1000). All DirhamPrice props apply. Works with server-side rendering — the static value renders immediately, animation triggers on mount.

DirhamInput

Masked currency input that formats keystrokes as the user types:

tsx
import { DirhamInput } from 'dirham/react'; <DirhamInput value={amount} onChange={(val) => setAmount(val)} placeholder="0.00" locale="en-AE" />

The onChange callback receives the raw numeric value, not the formatted string. Handles decimal separators, thousands grouping, and backspace correctly across en-AE and ar-AE locales.


Web Components

dirham/web-component ships four custom elements. Import the bundle once — it registers all four:

html
<script type="module" src="https://cdn.jsdelivr.net/npm/dirham/dist/web-component/index.js"></script>

Or in a bundled project:

ts
import 'dirham/web-component';

<dirham-symbol>

html
<dirham-symbol size="24" weight="bold"></dirham-symbol>

<dirham-price>

html
<dirham-price amount="1250"></dirham-price> <dirham-price amount="5000000" notation="compact"></dirham-price> <dirham-price amount="100" use-code></dirham-price> <dirham-price amount="750" locale="ar-AE"></dirham-price>
AttributeDefaultDescription
amount0Numeric value
locale"en-AE"Intl locale
decimals2Decimal places
notation"standard""standard" or "compact"
use-codeBoolean; shows AED
symbol-size"1em"SVG width/height
weight"regular"Stroke weight

<dirham-animated-price>

html
<dirham-animated-price amount="5000" duration="1500"></dirham-animated-price>

<dirham-input>

html
<dirham-input value="1250" locale="en-AE"></dirham-input>

Vue

vue
<script setup> import 'dirham/web-component'; </script> <template> <dirham-symbol size="24" weight="bold" /> <dirham-animated-price amount="1250" /> <dirham-input value="500" /> </template>

Angular

typescript
import { CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core'; import 'dirham/web-component'; @Component({ schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <dirham-price amount="1250"></dirham-price> <dirham-animated-price amount="5000" duration="2000"></dirham-animated-price> ` }) export class AppComponent {}

Svelte

svelte
<script> import 'dirham/web-component'; </script> <dirham-symbol size="24" weight="bold"></dirham-symbol> <dirham-price amount="1250"></dirham-price>

JavaScript Utilities

typescript
import { formatDirham, parseDirham, copyDirhamSymbol, copyDirhamAmount, addVAT, removeVAT, getVAT, UAE_VAT_RATE, convertFromAED, convertToAED, fetchExchangeRates, DIRHAM_UNICODE, DIRHAM_SYMBOL_TEXT, DIRHAM_CURRENCY_CODE, } from 'dirham';

Formatting

typescript
formatDirham(1234.5) // '⃃ 1,234.50' formatDirham(1234.5, { locale: 'ar-AE' }) // '١٬٢٣٤٫٥٠ ⃃' formatDirham(100, { useCode: true }) // 'AED 100.00' formatDirham(1500000, { notation: 'compact' }) // '⃃ 1.5M' parseDirham('⃃ 1,234.50') // 1234.5

Clipboard

typescript
await copyDirhamSymbol() // copies ⃃ (U+20C3) await copyDirhamSymbol('html') // copies &#x20C3; await copyDirhamSymbol('css') // copies \20C3 await copyDirhamAmount(1250) // copies '⃃ 1,250.00'

UAE VAT

typescript
UAE_VAT_RATE // 0.05 addVAT(1000) // 1050 removeVAT(1050) // 1000 getVAT(1000) // 50 // Custom rate addVAT(1000, 0.10) // 1100

Currency Conversion

typescript
const rates = await fetchExchangeRates(); convertFromAED(1000, 'USD', rates) // ~272.00 convertToAED(272, 'USD', rates) // ~1000.00

useDirhamRate Hook

tsx
import { useDirhamRate } from 'dirham/react'; function PriceDisplay() { const { rate, loading, error } = useDirhamRate('USD'); if (loading) return <span>Loading...</span>; if (error) return <span>Rate unavailable</span>; return <span>1 AED = {rate} USD</span>; }

Next.js Integration

typescript
// app/layout.tsx import { dirhamFont } from 'dirham/next'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en" className={dirhamFont.variable}> <body>{children}</body> </html> ); }
css
/* app/globals.css */ @import 'dirham/css';

Tailwind Plugin

typescript
// tailwind.config.ts import dirhamPlugin from 'dirham/tailwind'; export default { plugins: [dirhamPlugin], };

The plugin adds font-dirham, dirham-symbol, and weight utilities that match the DirhamSymbol weight system.


Font Variants

Five font styles, nine weights each:

ImportVariantUse case
dirham/cssDefaultGeneral purpose
dirham/font/sans/woff2Sans-serifUI, fintech dashboards
dirham/font/serif/woff2SerifEditorial, long-form
dirham/font/mono/woff2MonospaceCode, terminal displays
dirham/font/arabic/woff2Arabicar-AE locale, RTL interfaces

Weights: thin (100)extralightlightregular (400)mediumsemiboldbold (700)extraboldblack (900).


React Native

tsx
import { DirhamSymbol, DirhamPrice } from 'dirham/react-native'; <DirhamPrice amount={1250} style={{ fontSize: 24, color: '#000' }} />

OG Card Generation

tsx
// app/api/og/route.tsx (Next.js Edge Runtime) import { ImageResponse } from 'next/og'; import { DirhamPriceCard } from 'dirham/og'; export const runtime = 'edge'; export function GET(request: Request) { const { searchParams } = new URL(request.url); const amount = Number(searchParams.get('amount') || 1250); return new ImageResponse( <DirhamPriceCard amount={amount} />, { width: 1200, height: 630 } ); }

For SVG output:

typescript
import { generatePriceCardSVG } from 'dirham/og'; const svg = generatePriceCardSVG({ amount: 1250, currency: 'AED' });

CLI

bash
npx dirham # Print symbol info and codepoint npx dirham copy # Copy ⃃ (U+20C3) to clipboard npx dirham copy html # Copy &#x20C3; npx dirham copy css # Copy \20C3

All Package Exports

ExportContents
dirhamCore utilities: formatDirham, parseDirham, copyDirhamSymbol, copyDirhamAmount, addVAT, removeVAT, getVAT, UAE_VAT_RATE, convertFromAED, convertToAED, fetchExchangeRates, constants
dirham/reactDirhamSymbol, DirhamIcon, DirhamPrice, AnimatedDirhamPrice, DirhamInput, useDirhamRate
dirham/react-nativeDirhamSymbol, DirhamPrice (React Native)
dirham/web-component<dirham-symbol>, <dirham-price>, <dirham-animated-price>, <dirham-input>
dirham/nextdirhamFont (Next.js font helper)
dirham/tailwindTailwind plugin
dirham/ogDirhamPriceCard, generatePriceCardSVG
dirham/cssCSS with @font-face (default variant)
dirham/scssSCSS with @font-face
dirham/font/woff2Default WOFF2 font file
dirham/font/sans/woff2Sans-serif variant
dirham/font/serif/woff2Serif variant
dirham/font/mono/woff2Monospace variant
dirham/font/arabic/woff2Arabic variant

Migration from v1.3.0

v1.5.3 is backward-compatible. Existing DirhamSymbol, DirhamIcon, DirhamPrice, formatDirham, and Web Component usage requires no changes. New components are additive.

If you were using dirham/css for font loading, keep it. The font system is unchanged — new variants are opt-in via specific import paths.


The Unicode Roadmap

dirham uses U+20C3 everywhere — in React components, Web Components, CSS classes, and JS utilities. When operating systems ship native Unicode 18.0 font support (expected late 2026 into 2027), the migration is a single line:

diff
- import 'dirham/css';

All components, all utilities, all Web Components continue working. The codepoint never changes.


Resources


GitHub · npm · Docs

X / Twitter
LinkedIn
Facebook
WhatsApp
Telegram

About Pooya Golchian

Common questions about Pooya's work, AI services, and how to start a project together.

Get practical AI and engineering playbooks

Weekly field notes on private AI, automation, and high-performance Next.js builds. Each edition is concise, implementation-ready, and tested in production work.

Open full subscription page

Get the latest insights on AI and full-stack development.