Back to Blog

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

AI Transformation Lead
  • React
  • TypeScript
  • Open Source
  • Unicode
  • Currency
  • UAE
  • npm
  • Fintech
  • dirham
  • AED
  • U+20C3
  • Web Components
  • Next.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
AI Engineering for B2B

Stuck between an AI pilot and a system your team can run?

I join your engineering team and build the agent layer alongside you, covering architecture, MCP integration, evals, and production deployment. When the engagement ends, your team owns the system and keeps shipping.

12+ years shipping production systems

Senior engineer turned AI specialist. React, Next.js, AWS, agent orchestration.

Dubai-based, working with B2B teams worldwide

Direct collaboration across UAE, Europe, and US time zones.

AI agent teams that ship, not demos that stall

Discovery, role design, MCP integration, evals, and production deployment.

Questions about this piece

Follow-ups readers ask most often about the argument above.

  • dirham is an open source TypeScript library by Pooya Golchian that renders the UAE Dirham currency symbol (U+20C3) across React, Web Components, React Native, Next.js, and vanilla JS. Version 1.5.3 ships animated price counters, masked currency inputs, live exchange rate hooks, a Tailwind plugin, OG card generation, and a CLI. Install with: pnpm add dirham.

  • v1.5.3 adds AnimatedDirhamPrice (60fps count-up animation), DirhamInput (masked currency input), useDirhamRate (live AED exchange rate hook), Web Components for all four UI primitives, a Tailwind plugin, a Next.js font helper, React Native components, and OG card generation. It also expands the font to 5 variants (Sans, Serif, Mono, Arabic, Default) each with 9 weights.

  • Run pnpm add dirham, then import the font helper in your layout: import { dirhamFont } from 'dirham/next'. Pass it to your layout className alongside your other Next.js fonts. For the CSS font fallback, import 'dirham/css' in your global stylesheet. No configuration beyond that is required.

  • DirhamSymbol renders an inline SVG. It is SSR-compatible, requires no font loading, and is fully tree-shakeable. DirhamIcon renders a font-based glyph — it produces lighter HTML markup but depends on the dirham/css import for the web font. Use DirhamSymbol in server-rendered contexts and DirhamIcon when font loading is already guaranteed.

  • AnimatedDirhamPrice uses requestAnimationFrame for a 60fps count-up animation from 0 to the target amount. Import it from dirham/react: import { AnimatedDirhamPrice } from 'dirham/react'. Render it as: <AnimatedDirhamPrice amount={1250} />. It accepts the same props as DirhamPrice — locale, decimals, notation, weight — plus duration in milliseconds.

  • Import the web component bundle once: import 'dirham/web-component'. Then use the custom elements anywhere in your templates: <dirham-symbol size='24' weight='bold'></dirham-symbol>, <dirham-price amount='1250'></dirham-price>, <dirham-animated-price amount='5000'></dirham-animated-price>, <dirham-input value='1250'></dirham-input>. In Angular, add CUSTOM_ELEMENTS_SCHEMA to the component decorator.

  • dirham ships addVAT(amount), removeVAT(amount), getVAT(amount), and the UAE_VAT_RATE constant (5%). All three functions accept an optional second argument for a custom rate. They integrate with formatDirham: formatDirham(addVAT(1000)) returns the formatted total including UAE VAT. Pooya Golchian built these specifically for UAE fintech and e-commerce applications.

  • Yes. v1.5.3 ships convertFromAED(amount, currency), convertToAED(amount, currency), and fetchExchangeRates(). The useDirhamRate hook wraps fetchExchangeRates in a React state hook that returns the current rate, a loading flag, and an error. Rates are fetched from a public exchange rate API. For production use, Pooya Golchian recommends proxying through your own API route to cache and control rate freshness.

  • Import from dirham/og: import { DirhamPriceCard, generatePriceCardSVG } from 'dirham/og'. DirhamPriceCard is a React component sized for OG images (1200x630). generatePriceCardSVG returns an SVG string you can pass to satori or sharp for edge-rendered OG images in Next.js API routes.

  • No. dirham uses U+20C3 as the underlying codepoint everywhere — in React components, Web Components, CSS classes, and JS utilities. When operating systems ship Unicode 18.0 font support (expected late 2026 into 2027), you remove the dirham/css import. All other code remains unchanged. The entire migration is a single line deletion.

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.