Skip to content

Price

Price display component with multi-currency support, promotional variants, and accessible formatting. Uses the usePrice composable based on Intl.NumberFormat.

Usage

Basic

Simple price

vue
<SuPrice :amount="29.99" />

Sizes

sm / md / lg

vue
<SuPrice :amount="29.99" size="sm" />
<SuPrice :amount="29.99" size="md" />
<SuPrice :amount="29.99" size="lg" />

Variants

default / highlight / muted

vue
<SuPrice :amount="29.99" variant="default" />
<SuPrice :amount="29.99" variant="highlight" />
<SuPrice :amount="29.99" variant="muted" />

Strikethrough price (promotion)

Original price crossed out + new price

vue
<SuPrice
  :amount="29.99"
  :originalAmount="49.99"
  :showOriginal="true"
  size="lg"
/>

Full promotional pricing

Prefix + strikethrough + highlight + badge

vue
<SuPrice
  :amount="29.99"
  :originalAmount="49.99"
  :showOriginal="true"
  variant="highlight"
  size="lg"
>
  <template #prefix>
    <span>From</span>
  </template>
  <template #suffix>
    <SuBadge variant="error" size="sm">-40%</SuBadge>
  </template>
</SuPrice>

Integer only

Without decimals

vue
<SuPrice :amount="1299.99" :integerOnly="true" size="lg" />

Superscript decimals

E-commerce style

vue
<SuPrice :amount="29.99" :superscriptDecimals="true" size="lg" />

Multiple currencies

EUR, USD, GBP, JPY

vue
<SuPrice :amount="1299.99" currency="EUR" locale="fr-FR" />
<SuPrice :amount="1299.99" currency="USD" locale="en-US" />
<SuPrice :amount="1299.99" currency="GBP" locale="en-GB" />
<SuPrice :amount="1299" currency="JPY" locale="ja-JP" />

With slots

Prefix and suffix

vue
<SuPrice :amount="9.99" size="lg">
  <template #prefix><span>Starting at</span></template>
</SuPrice>

<SuPrice :amount="9.99" size="lg">
  <template #suffix><span>/month</span></template>
</SuPrice>

usePrice composable

The usePrice composable can be used independently to format prices in your components:

vue
<script setup>
import { usePrice } from '@surgeui/ds-vue'

const { formatted, integerPart, decimalPart, currencySymbol } = usePrice({
  amount: 1299.99,
  currency: 'EUR',
  locale: 'fr-FR',
})
</script>

<template>
  <p>Full price: {{ formatted }}</p>
  <p>Integer: {{ integerPart }}{{ currencySymbol }}</p>
</template>

API

Props

PropTypeDefaultDescription
amountnumber— (required)Numeric amount to display
originalAmountnumberOriginal amount for strikethrough
currencystring'EUR'ISO 4217 currency code
localestring'fr-FR'BCP 47 locale
variant'default' | 'highlight' | 'muted''default'Visual variant
size'sm' | 'md' | 'lg''md'Size
integerOnlybooleanfalseHide decimal part
showOriginalbooleanfalseShow strikethrough original price
currencyDisplay'symbol' | 'narrowSymbol' | 'code' | 'name''symbol'Currency symbol format
currencyPosition'auto' | 'prefix' | 'suffix''auto'Symbol position
formatValue(amount: number) => stringCustom formatter
superscriptDecimalsbooleanfalseSuperscript decimal display
ariaLabelstringAccessible label (auto-generated if omitted)

Slots

SlotPropsDescription
prefixContent before the price (e.g. "Starting at")
original{ formatted: string, amount: number }Custom rendering of strikethrough price
suffixContent after the price (e.g. "/month", Badge)

usePrice — Options

OptionTypeDefaultDescription
amountnumber | Ref<number> | () => number— (required)Reactive amount
currencystring'EUR'ISO 4217 currency code
localestring'fr-FR'BCP 47 locale
currencyDisplayCurrencyDisplay'symbol'Symbol format
minimumFractionDigitsnumber2Minimum fraction digits
maximumFractionDigitsnumber2Maximum fraction digits
formatValue(amount, currency, locale) => stringCustom formatter

usePrice — Return

PropertyTypeDescription
formattedReadonly<Ref<string>>Full formatted price
integerPartReadonly<Ref<string>>Integer part
decimalPartReadonly<Ref<string>>Decimal part
decimalSeparatorReadonly<Ref<string>>Decimal separator
currencySymbolReadonly<Ref<string>>Currency symbol
isSymbolPrefixReadonly<Ref<boolean>>true if symbol is before amount
ariaLabelReadonly<Ref<string>>Accessible text
rawAmountReadonly<Ref<number>>Raw amount

Accessibility

  • role="text" on the root element groups visual fragments for screen readers
  • aria-label auto-generated with full currency name (e.g. "29.99 euros")
  • All visual sub-elements marked aria-hidden="true" to prevent fragmented reading
  • prefers-contrast: high support: thicker strikethrough line
  • prefers-reduced-motion: reduce support: transitions disabled
  • font-variant-numeric: tabular-nums for grid alignment

Publié sous licence MIT.