---
name: toast
title: Toast
url: https://ui.frontic.com/components/ui/toast.md
tier: ui
install: npx @frontic/ui add toast
files:
  - components/ui/toast/Toast.vue
  - components/ui/toast/index.ts
dependencies:
  - "@lucide/vue"
  - "@vueuse/core"
  - class-variance-authority
  - reka-ui
  - vue-sonner
---

# Toast

Short messages that confirm an action, like adding to the cart, with an optional action button; mount Toaster once and call toast() anywhere.

## Install

```sh
npx @frontic/ui add toast
```

npm packages: `@lucide/vue`, `@vueuse/core`, `class-variance-authority`, `reka-ui`, `vue-sonner`

## Examples

```vue
<script setup lang="ts">
import { ShoppingBagIcon } from '@lucide/vue'

import { defineComponent, h, markRaw } from 'vue'
import { Button } from '@/components/ui/button'
import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle } from '@/components/ui/item'
import { Price } from '@/components/ui/price'
import { Toast, toast } from '@/components/ui/toast'

const JACKET = {
  name: 'Polar Light Ski Jacket',
  variant: 'Dusty pink · M',
  price: { amount: 7900, currency: 'EUR' },
  image: 'https://static.frontic.com/cdn-cgi/image/width=160,format=auto/ui/products/polar-light-ski-jacket.jpg',
}

// What the toast shows under its title: the cart line that was added, and the way to the cart.
const CartLine = markRaw(
  defineComponent(
    () => () =>
      h('div', { class: 'flex flex-col gap-3' }, [
        h(Item, { size: 'sm', class: 'p-0' }, () => [
          h(ItemMedia, { variant: 'image' }, () => h('img', { src: JACKET.image, alt: '' })),
          h(ItemContent, null, () => [h(ItemTitle, null, () => JACKET.name), h(ItemDescription, null, () => JACKET.variant)]),
          h(ItemActions, null, () => h(Price, { price: JACKET.price, size: 'sm' })),
        ]),
        h(Button, { as: 'a', href: '#cart', variant: 'outline', color: 'neutral', size: 'sm', class: 'w-full', onClick: () => toast.dismiss() }, () => 'View cart'),
      ]),
  ),
)

function addToCart() {
  toast.success('Added to cart', { description: CartLine })
}
</script>

<template>
  <div>
    <Button color="buy" @click="addToCart">
      <ShoppingBagIcon data-icon />
      Add to cart
    </Button>
    <Toast />
  </div>
</template>
```

The example also uses `button`, `item` and `price`, which `add toast` leaves out: `npx @frontic/ui add button item price`.

## API reference

### Toast

Holds the toasts that toast() shows, short messages that confirm an action such as adding to the cart. Mount it once.

Also exported as `Toaster`.

Styling: `toast`, which extends [`notice-info`](https://ui.frontic.com/DESIGN.md#notice-info), [`notice-positive`](https://ui.frontic.com/DESIGN.md#notice-positive), [`notice-warning`](https://ui.frontic.com/DESIGN.md#notice-warning) and [`notice-destructive`](https://ui.frontic.com/DESIGN.md#notice-destructive); `toast-action`, which extends [`action`](https://ui.frontic.com/DESIGN.md#action); `toast-cancel`, which extends [`action`](https://ui.frontic.com/DESIGN.md#action); `toast-description`, which extends [`part-description`](https://ui.frontic.com/DESIGN.md#part-description); `toast-title`, which extends [`part-title`](https://ui.frontic.com/DESIGN.md#part-title). Change them there and every part that extends them follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` |  | Names the toaster, so a toast can target it when a page has several. |
| `invert` | `boolean` | `false` | Inverts the toast colours: dark toasts on a light theme, light ones on a dark theme. |
| `theme` | `Theme`: `'light' \| 'dark' \| 'system'` |  | The colour theme of the toasts; `system` follows the device. |
| `position` | `Position`: `'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' \| 'top-center' \| 'bottom-center'` |  | Where on the screen the toasts stack. |
| `closeButtonPosition` | `CloseButtonPosition`: `'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right'` |  | The corner of a toast its close button sits in. |
| `hotkey` | `string[]` |  | The keys that move focus to the toasts, e.g. `altKey` with `KeyT`. |
| `richColors` | `boolean` | `false` | Gives success, error, warning and info toasts their own colours. |
| `expand` | `boolean` | `false` | Shows every toast in full instead of a collapsed stack. |
| `duration` | `number` |  | How long a toast stays, in milliseconds. |
| `gap` | `number` |  | The space between expanded toasts, in pixels. |
| `visibleToasts` | `number` |  | How many toasts show at once; the rest wait their turn. |
| `closeButton` | `boolean` | `false` | Gives every toast a close button. |
| `toastOptions` | `ToastOptions` |  | Defaults for every toast, such as its classes, styles and duration. |
| `offset` | `Offset`: `string \| number \| { top?: string \| number \| undefined; right?: string \| number \| undefined; bottom?: string \| number \| undefined; left?: string \| number \| undefined; }` |  | The distance from the screen edges: one value, or one per side. |
| `mobileOffset` | `Offset`: `string \| number \| { top?: string \| number \| undefined; right?: string \| number \| undefined; bottom?: string \| number \| undefined; left?: string \| number \| undefined; }` |  | The distance from the screen edges on small screens: one value, or one per side. |
| `dir` | `'ltr' \| 'rtl' \| 'auto'` |  | The text direction of the toasts. |
| `swipeDirections` | `SwipeDirection[]` |  | The directions a toast can be swiped away in. |
| `icons` | `ToastIcons` |  | Replaces the icons of success, error, warning, info and loading toasts. |
| `containerAriaLabel` | `string` |  | The accessible name of the region that holds the toasts. |

## Exports

```ts
import { toast } from '@/components/ui/toast'
```

- `toast`: from `vue-sonner`

## Styling

| Part | Recipe |
| --- | --- |
| `default` | [`toast`](https://ui.frontic.com/DESIGN.md#toast) |
| `content` | [`toast-content`](https://ui.frontic.com/DESIGN.md#toast-content) |
| `action` | [`toast-action`](https://ui.frontic.com/DESIGN.md#toast-action) |
| `cancel` | [`toast-cancel`](https://ui.frontic.com/DESIGN.md#toast-cancel) |
| `title` | [`toast-title`](https://ui.frontic.com/DESIGN.md#toast-title) |
| `description` | [`toast-description`](https://ui.frontic.com/DESIGN.md#toast-description) |
| `focus-ring` | [`focus-ring`](https://ui.frontic.com/DESIGN.md#focus-ring) |

States with a look of their own: focus.

## Source

`components/ui/toast/Toast.vue`

```vue
<script lang="ts">
/** Holds the toasts that toast() shows, short messages that confirm an action such as adding to the cart. Mount it once. */
export default {}
</script>

<script lang="ts" setup>
import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon, XIcon } from '@lucide/vue'

import type { ToasterProps } from 'vue-sonner'
import { reactiveOmit } from '@vueuse/core'
import { cva } from 'class-variance-authority'
import { computed } from 'vue'
import { useDirection } from 'reka-ui'
import { Toaster as VueSonner } from 'vue-sonner'

const props = defineProps<ToasterProps>()
const delegatedProps = reactiveOmit(props, 'class', 'toastOptions')
// vue-sonner reads <html dir> on its own; the ConfigProvider's direction is the one the items follow.
const direction = useDirection()

const toast = cva('fui-toast flex items-center', {
  variants: {
    tone: {
      info: 'fui-toast-info',
      positive: 'fui-toast-positive',
      warning: 'fui-toast-warning',
      destructive: 'fui-toast-destructive',
    },
  },
  defaultVariants: {},
})

const classes = {
  toast: toast(),
  info: toast({ tone: 'info' }),
  success: toast({ tone: 'positive' }),
  warning: toast({ tone: 'warning' }),
  error: toast({ tone: 'destructive' }),
  title: cva('fui-toast-title')(),
  description: cva('fui-toast-description')(),
  content: cva('fui-toast-content flex flex-col')(),
  icon: 'flex shrink-0 items-center',
  actionButton: cva('fui-toast-action ms-auto inline-flex shrink-0 cursor-pointer items-center focus-visible:fui-focus-ring')(),
  cancelButton: cva('fui-toast-cancel ms-auto inline-flex shrink-0 cursor-pointer items-center focus-visible:fui-focus-ring')(),
}

const toastOptions = computed(() => {
  const own = props.toastOptions?.classes ?? {}
  const merged = Object.fromEntries(Object.entries(classes).map(([key, value]) => [key, [value, own[key as keyof typeof own]].filter(Boolean).join(' ')]))
  return { ...props.toastOptions, unstyled: true, classes: { ...own, ...merged } }
})
</script>

<template>
  <VueSonner :class="props.class" :toast-options="toastOptions" v-bind="delegatedProps" :dir="props.dir ?? direction">
    <template #success-icon>
      <CircleCheckIcon data-icon />
    </template>
    <template #info-icon>
      <InfoIcon data-icon />
    </template>
    <template #warning-icon>
      <TriangleAlertIcon data-icon />
    </template>
    <template #error-icon>
      <OctagonXIcon data-icon />
    </template>
    <template #loading-icon>
      <div>
        <Loader2Icon data-icon class="animate-spin" />
      </div>
    </template>
    <template #close-icon>
      <XIcon data-icon />
    </template>
  </VueSonner>
</template>

<style>
@import 'vue-sonner/style.css';
</style>
```

## API of the items the example uses

### Button

[Full docs](https://ui.frontic.com/components/ui/button.md) · `npx @frontic/ui add button`

#### Button

Lets the user trigger an action, such as adding a product to the cart. Renders a `<button>`.

`data-slot="button"` · `Button.vue`

Styling: `button`, which extends [`action`](https://ui.frontic.com/DESIGN.md#action). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'button'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `variant` | `'solid' \| 'outline' \| 'soft' \| 'ghost' \| 'link'` | `'solid'` | The visual style: a filled, outlined, tinted, background-free or text-link button. |
| `color` | `'neutral' \| 'primary' \| 'destructive' \| 'buy' \| 'checkout' \| 'inverse'` | `'primary'` | The colour role, e.g. primary for the brand colour, buy for add-to-cart, checkout for the checkout step, destructive for removing. |
| `size` | `'md' \| 'xs' \| 'sm' \| 'lg' \| 'icon-xs' \| 'icon-sm' \| 'icon-md' \| 'icon-lg'` | `'md'` | The button's height and padding; the `icon-*` sizes make a square, icon-only button. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-color` | `'neutral' \| 'primary' \| 'destructive' \| 'buy' \| 'checkout' \| 'inverse'` | Carries the `color` prop. |
| `data-size` | `'md' \| 'xs' \| 'sm' \| 'lg' \| 'icon-xs' \| 'icon-sm' \| 'icon-md' \| 'icon-lg'` | Carries the `size` prop. |
| `data-variant` | `'solid' \| 'outline' \| 'soft' \| 'ghost' \| 'link'` | Carries the `variant` prop. |

### Item

[Full docs](https://ui.frontic.com/components/ui/item.md) · `npx @frontic/ui add item`

#### Item

Groups the media, text and actions of one entry, such as a list row. Renders a `<div>`.

`data-slot="item"` · `Item.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |
| `variant` | `'default' \| 'outline' \| 'muted'` | `'default'` | The visual style: no border, an outlined border or a muted background. |
| `size` | `'md' \| 'xs' \| 'sm'` | `'md'` | The padding and gap around the item's content. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-size` | `'md' \| 'xs' \| 'sm'` | Carries the `size` prop. |
| `data-variant` | `'default' \| 'outline' \| 'muted'` | Carries the `variant` prop. |

#### ItemActions

Holds the actions of its item, such as buttons or links. Renders a `<div>`.

`data-slot="item-actions"` · `ItemActions.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### ItemContent

Groups the title and description of its item. Renders a `<div>`.

`data-slot="item-content"` · `ItemContent.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### ItemDescription

Gives more detail about its item below the title. Renders a `<p>`.

`data-slot="item-description"` · `ItemDescription.vue`

Styling: `item-description`, which extends [`part-description`](https://ui.frontic.com/DESIGN.md#part-description) and [`link-primary`](https://ui.frontic.com/DESIGN.md#link-primary). Change them there and every part that extends them follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'p'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### ItemFooter

Holds extra content below the main row of its item. Renders a `<div>`.

`data-slot="item-footer"` · `ItemFooter.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### ItemGroup

Groups several items into one list. Renders a `<div>`.

`data-slot="item-group"` · `ItemGroup.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### ItemHeader

Holds extra content above the main row of its item. Renders a `<div>`.

`data-slot="item-header"` · `ItemHeader.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### ItemMedia

Shows an icon, image or avatar at the start of its item. Renders a `<div>`.

`data-slot="item-media"` · `ItemMedia.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |
| `variant` | `ItemMediaVariant`: `'icon' \| 'default' \| 'image'` | `'default'` | How the media is framed: as is, sized as an icon, or as a square image. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-variant` | `'icon' \| 'default' \| 'image'` | Carries the `variant` prop. |

#### ItemSeparator

Separates the items of a group.

`data-slot="item-separator"` · `ItemSeparator.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `orientation` | `DataOrientation`: `'vertical' \| 'horizontal'` |  | Orientation of the component.<br><br>Either `vertical` or `horizontal`. Defaults to `horizontal`. |
| `decorative` | `boolean` | `false` | Whether or not the component is purely decorative.<br><br>When `true`, accessibility-related attributes are updated so that that the rendered element is removed from the accessibility tree. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### ItemTitle

Names its item. Renders a `<div>`.

`data-slot="item-title"` · `ItemTitle.vue`

Styling: `item-title`, which extends [`part-title`](https://ui.frontic.com/DESIGN.md#part-title). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

### Price

[Full docs](https://ui.frontic.com/components/ui/price.md) · `npx @frontic/ui add price`

#### Price

Shows a price, with the original price and discount percentage when reduced. Renders a `<span>`.

`data-slot="price"` · `Price.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |
| `size` | `PriceSize`: `'md' \| 'sm' \| 'lg'` | `'md'` | The text size of the price. |
| `align` | `PriceAlign`: `'start' \| 'end'` | `'start'` | Which side the badge, the prices and the hint line up on. |
| `price` (required) | `PriceType` |  | The price to show: `amount` and `ref` in minor units such as cents, `currency` as an ISO 4217 code. |
| `locale` | `string` |  | The locale that formats the price, e.g. `de-DE`; the ConfigProvider's when left out. |
| `showRef` | `boolean` | `true` | Shows the reference price struck through when it is higher than the amount. |
| `showDiscount` | `boolean` | `true` | Shows the saving as a percentage next to a discounted price. |
| `showHint` | `boolean` | `true` | Shows the hint below the price when the hint slot holds one. |
| `refLabel` | `string` | `'Was'` | Read out before the original price of a reduced product; hidden on screen. |
| `amountLabel` | `string` | `'Now'` | Read out before the current price of a reduced product; hidden on screen. |

| Slot | Slot props | Description |
| --- | --- | --- |
| `hint` |  | A note below the price, such as tax and shipping. |

#### PriceAmount

Shows the current price of the product. Renders a `<span>`.

`data-slot="price-amount"` · `PriceAmount.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### PriceRef

Shows the original price of a discounted product. Renders a `<span>`.

`data-slot="price-ref"` · `PriceRef.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### PriceDiscount

Shows the percentage saved against the original price. Renders a `<span>`.

`data-slot="price-discount"` · `PriceDiscount.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

| Slot | Slot props | Description |
| --- | --- | --- |
| `default` | `{ percent: number; }` | Replaces the discount badge; gets the percentage saved. |

#### PriceHint

Holds a note below the price, such as tax and shipping, which may link on. Renders a `<span>`.

`data-slot="price-hint"` · `PriceHint.vue`

Styling: `price-hint`, which extends [`link-foreground`](https://ui.frontic.com/DESIGN.md#link-foreground). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'span'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |
