Price
A locale-aware price display component for e-commerce and SaaS interfaces. Supports currency formatting, strike-through compare-at prices (RRP / UVP / MSRP), unit prices (Grundpreis) for EU price-marking compliance, delta indicators, and size variants.
Basic Usage
Compare-At Price (RRP / UVP / MSRP)
Show the previous or recommended retail price as a strike-through alongside the current price. The strike-through value answers the question "what was this before?":
- RRP — Recommended Retail Price (UK)
- UVP — Unverbindliche Preisempfehlung (Germany)
- MSRP — Manufacturer's Suggested Retail Price (US)
The base prop carries this comparison value. It does not mean "base price" in the unit-price sense — see Unit Price (Grundpreis) below for that.
Unit Price (Grundpreis)
For pre-packaged goods sold by weight, volume, length, or area, EU and UK price-marking law requires the per-unit price to be displayed alongside the selling price. In Germany this is the Grundpreis per PAngV § 4; in the UK it is the unit price per the Price Marking Order 2004; the EU baseline is Directive 98/6/EC.
Pass unitPrice (numeric, same currency as amount) and unitMeasure (the reference unit label) — the component renders them as (€8.99 / L) next to the main price, in the same currency, in the same field of vision.
Reference units are jurisdiction-dependent. Germany / EU: per kg, L, m, m². For nominal quantities ≤ 250 g / 250 ml the law allows 100g / 100ml instead. The UK rules mirror this. The US has no federal unit-price law but several states (NY, MA, CA, MI) require unit pricing in retail with their own unit conventions (oz, lb, fl oz). The component does not validate the unit string — pass whatever your jurisdiction requires.
Delta Indicator
Attach a percentage or absolute change indicator:
Size Variants
Minor Units (Cents)
Pass amounts in minor units (cents) and let the component convert:
With Suffix Slot
Add recurring interval text or other context:
Full Sale Example
Props
| Prop | Type | Default | Description |
|---|---|---|---|
amount |
int|float |
null |
The price amount to display |
currency |
string |
'USD' |
ISO 4217 currency code |
locale |
string |
app()->getLocale() |
Locale for number formatting |
base |
int|float |
null |
Compare-at / RRP / UVP / MSRP price (shown as strike-through) |
unitPrice |
int|float |
null |
Per-unit price (Grundpreis) — required by EU / UK price-marking law for goods sold by weight / volume / length / area |
unitMeasure |
string |
null |
Reference unit label paired with unitPrice (e.g. L, kg, 100g, 100ml, m²) |
delta |
int|float |
null |
Change indicator value |
delta-format |
string |
'percent' |
Delta format: percent or absolute |
size |
string |
'md' |
Size variant: xs, sm, md, lg, xl |
minor-units |
bool |
false |
When true, divides amount / base / unitPrice by 100 |
Slots
| Slot | Description |
|---|---|
suffix |
Text after the price (e.g. "/ month") |
Accessibility
- Every part is read from the content itself — the root
<span>carries noaria-label. ARIA prohibitsaria-labelon an element with no role, so a name placed there is not required to reach assistive technology at all - Strike-through compare-at price uses
<del>element for semantic meaning, prefixed with a visually-hidden "Previous price" —<del>maps torole="deletion", which screen readers do not announce by default, so without the prefix the two amounts read as unrelated <bdi>wraps formatted values for correct RTL rendering- Unit price is read out like any other visible text; it is deliberately not
aria-hidden, because it is the figure EU / UK price-marking law requires the reader to get
Keyboard Interaction
This component is purely presentational and does not respond to keyboard input.
Pitfalls
- Don't pass an unformatted number to
:value. The component formats with the active locale's decimal/thousand separators — passing19.99is correct; passing"19,99"(already formatted) double-formats.
Design Tokens
| Token | Used for |
|---|---|
--font-wk-sans |
Price font family |
--font-wk-heading-weight |
Amount + currency weight |
--text-wk-xs / --text-wk-sm / --text-wk-md / --text-wk-lg / --text-wk-xl |
Font size per size prop |
--color-wk-text |
Amount + currency color |
--color-wk-text-muted |
Strike-through base price + suffix |
--color-wk-success-text |
Negative-direction delta (savings) |
--color-wk-danger-text |
Positive-direction delta (price increase) |
--color-wk-border |
Optional separator under base/strike row |