⃁ Riyal

Guide · 4 min read · Updated 2026-05-08

How to display the Saudi Riyal symbol (U+20C1) in Vue 3

First-class Vue 3 components for the official SAMA Saudi Riyal sign. Install once, render with <RiyalPrice>, edit with <RiyalInput v-model mask>, and read live SAR exchange rates with the useRiyalRate composable. SSR-safe, Nuxt-ready.

If you’re building a Saudi e-commerce or fintech app on Vue 3 (or Nuxt), the riyal/vue entry gives you idiomatic components for the official Saudi Riyal symbol — no Web-Component wrapper required.

Install

pnpm add riyal vue
# or npm install riyal vue

vue ≥ 3.4 is an optional peer dependency. The components are render-function based (defineComponent + h()), so no Vue compiler plugin is needed in your app.

Basic usage

<script setup lang="ts">
import { ref } from "vue";
import {
  RiyalSymbol, RiyalIcon, RiyalPrice,
  AnimatedRiyalPrice, RiyalInput, useRiyalRate,
} from "riyal/vue";

const amount = ref<number | "">(2499.99);
const usd = useRiyalRate("USD");
</script>

<template>
  <RiyalSymbol :size="24" />
  <RiyalIcon :width="32" :height="32" />
  <RiyalPrice :amount="2499.99" locale="ar-SA" />
  <AnimatedRiyalPrice :amount="amount" :duration-ms="600" />
  <RiyalInput v-model="amount" mask />
  <span v-if="usd.rate.value">
    {{ (Number(amount) * usd.rate.value).toFixed(2) }} USD
  </span>
</template>

Masked input — paste anything

Pass mask to <RiyalInput> and the input becomes a format-as-you-type field that handles paste of every common SAR string format:

It also strips RTL marks, normalises Arabic decimal/grouping characters, enforces a max-decimals window, and preserves caret position via a digit-counting algorithm — so cursor placement during edits stays where the user expects.

SSR & Nuxt

Every component is SSR-safe. RiyalPrice and RiyalSymbol render the same markup on the server and client, so they don’t cause hydration mismatches inside <ClientOnly> blocks. The useRiyalRate composable defers the fetch to onMounted, so it stays server-render-safe.

Cart, VAT, conversion

import { lineItem, cartTotal } from "riyal/cart";

const items = [
  lineItem({ unit: 75, qty: 1 }),
  lineItem({ unit: 45, qty: 2 }),
];
const totals = cartTotal(items, { shipping: 20, discount: 10 });
// → { subtotal, vat, shipping, total, ... }

The cart helpers default to Saudi 15% VAT and apply discounts proportionally to net + VAT, matching how Saudi receipts present them.

Next steps


Built by Pooya Golchian · riyal on npm · live demo