A versatile component for displaying content with media, title, description, and actions.

Default
Title Only
Title + Button
Title + Description

This is a description that provides additional context.

Title + Description + Button

This item includes a title, description, and action button.

Media + Title
Media + Title + Button
Media + Title + Description

This item includes media, title, and description.

Media + Title + Description + Button

Complete item with all components: media, title, description, and button.

Multiple Actions

Item with multiple action buttons in the actions area.

Outline
Title Only
Title + Button
Title + Description

This is a description that provides additional context.

Title + Description + Button

This item includes a title, description, and action button.

Media + Title
Media + Title + Button
Media + Title + Description

This item includes media, title, and description.

Media + Title + Description + Button

Complete item with all components: media, title, description, and button.

Multiple Actions

Item with multiple action buttons in the actions area.

Muted
Title Only
Title + Button
Title + Description

This is a description that provides additional context.

Title + Description + Button

This item includes a title, description, and action button.

Media + Title
Media + Title + Button
Media + Title + Description

This item includes media, title, and description.

Media + Title + Description + Button

Complete item with all components: media, title, description, and button.

Multiple Actions

Item with multiple action buttons in the actions area.

Small
Title Only
Title + Button
Title + Description

This is a description that provides additional context.

Title + Description + Button

This item includes a title, description, and action button.

Media + Title
Media + Title + Button
Media + Title + Description

This item includes media, title, and description.

Media + Title + Description + Button

Complete item with all components: media, title, description, and button.

Multiple Actions

Item with multiple action buttons in the actions area.

Outline - Small
Title Only
Title + Button
Title + Description

This is a description that provides additional context.

Title + Description + Button

This item includes a title, description, and action button.

Media + Title
Media + Title + Button
Media + Title + Description

This item includes media, title, and description.

Media + Title + Description + Button

Complete item with all components: media, title, description, and button.

Multiple Actions

Item with multiple action buttons in the actions area.

Muted - Small
Title Only
Title + Button
Title + Description

This is a description that provides additional context.

Title + Description + Button

This item includes a title, description, and action button.

Media + Title
Media + Title + Button
Media + Title + Description

This item includes media, title, and description.

Media + Title + Description + Button

Complete item with all components: media, title, description, and button.

Multiple Actions

Item with multiple action buttons in the actions area.

Extra Small
Title Only
Title + Button
Title + Description

This is a description that provides additional context.

Title + Description + Button

This item includes a title, description, and action button.

Media + Title
Media + Title + Button
Media + Title + Description

This item includes media, title, and description.

Media + Title + Description + Button

Complete item with all components: media, title, description, and button.

Multiple Actions

Item with multiple action buttons in the actions area.

Outline - Extra Small
Title Only
Title + Button
Title + Description

This is a description that provides additional context.

Title + Description + Button

This item includes a title, description, and action button.

Media + Title
Media + Title + Button
Media + Title + Description

This item includes media, title, and description.

Media + Title + Description + Button

Complete item with all components: media, title, description, and button.

Multiple Actions

Item with multiple action buttons in the actions area.

Muted - Extra Small
Title Only
Title + Button
Title + Description

This is a description that provides additional context.

Title + Description + Button

This item includes a title, description, and action button.

Media + Title
Media + Title + Button
Media + Title + Description

This item includes media, title, and description.

Media + Title + Description + Button

Complete item with all components: media, title, description, and button.

Multiple Actions

Item with multiple action buttons in the actions area.

ItemGroup
Item 1

First item in the group.

Item 2

Second item in the group.

Item 3

Third item in the group.

Outline - ItemGroup
Item 1

First item with icon.

Item 2

Second item with icon.

Item 3

Third item with icon.

Muted - ItemGroup
Item 1

First item in muted group.

Item 2

Second item in muted group.

Item 3

Third item in muted group.

ItemSeparator
Inbox

View all incoming messages.

Sent

View all sent messages.

Drafts

View all draft messages.

Archive

View archived messages.

ItemHeader
Design System
Component Library

A comprehensive collection of reusable UI components for building consistent interfaces.

Marketing
Campaign Analytics

Track performance metrics and engagement rates across all marketing channels.

Engineering
API Documentation

Complete reference guide for all available endpoints and authentication methods.

ItemFooter
Quarterly Report Q4 2024

Financial overview including revenue, expenses, and growth metrics for the fourth quarter.

User Research Findings

Insights from interviews and surveys conducted with 50+ users across different demographics.

Product Roadmap

Planned features and improvements scheduled for the next three months.

ItemHeader + ItemFooter
Team Project
Website Redesign

Complete overhaul of the company website with modern design principles and improved user experience.

Client Work
Mobile App Development

Building a cross-platform mobile application for iOS and Android with React Native.

Documentation
API Integration Guide

Step-by-step instructions for integrating third-party APIs with authentication and error handling.

Default - ItemMedia image
Project
Project Dashboard

Overview of project settings and configuration.

Document
Document

A document with metadata displayed.

File
File Attachment

Complete file with image, title, description, and action button.

Outline - ItemMedia image
Project
Project Dashboard

Overview of project settings and configuration.

Document
Document

A document with metadata displayed.

File
File Attachment

Complete file with image, title, description, and action button.

Outline - ItemMedia image - Small
Project
Project Dashboard

Overview of project settings and configuration.

Document
Document

A document with metadata displayed.

File
File Attachment

Complete file with image, title, description, and action button.

Outline - ItemMedia image - Extra Small
Project
Project Dashboard
Document
Document
File
File Attachment
Muted - ItemMedia image
Project
Project Dashboard

Overview of project settings and configuration.

Document
Document

A document with metadata displayed.

File
File Attachment

Complete file with image, title, description, and action button.

Installation

Install the dependencies

pnpm add cn class-variance-authority github:sveltery/base

Copy the component

Copy the following files into src/lib/components/ui/item.

It imports the separator component, so copy its folder too.

src/lib/components/ui/item/Item.svelte
<script lang="ts">
  import type { ItemProps, ItemState } from './types.js';
  import { cn } from 'cn';
  import { itemVariants } from './variants.js';
  let { children, class: classProp, variant = 'default', size = 'default', render, ...props }: ItemProps = $props();
  const state: ItemState = $derived({ slot: 'item', variant, size });
  const hostProps = $derived({ 'data-slot': state.slot, 'data-variant': state.variant, 'data-size': state.size, ...props, class: cn(itemVariants({ variant, size, class: classProp })) });
</script>
{#if render}
  {@render render(hostProps, state, children)}
{:else}
  <div {...hostProps}>{@render children?.()}</div>
{/if}
src/lib/components/ui/item/ItemActions.svelte
<script lang="ts">
  import type { ItemActionsProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: ItemActionsProps = $props();
</script>
<div data-slot="item-actions" {...props} class={cn('gap-2 flex items-center', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/item/ItemContent.svelte
<script lang="ts">
  import type { ItemContentProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: ItemContentProps = $props();
</script>
<div data-slot="item-content" {...props} class={cn('gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/item/ItemDescription.svelte
<script lang="ts">
  import type { ItemDescriptionProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: ItemDescriptionProps = $props();
</script>
<p data-slot="item-description" {...props} class={cn('text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary', classProp)}>
  {@render children?.()}
</p>
src/lib/components/ui/item/ItemFooter.svelte
<script lang="ts">
  import type { ItemFooterProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: ItemFooterProps = $props();
</script>
<div data-slot="item-footer" {...props} class={cn('gap-2 flex basis-full items-center justify-between', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/item/ItemGroup.svelte
<script lang="ts">
  import type { ItemGroupProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: ItemGroupProps = $props();
</script>
<div role="list" data-slot="item-group" {...props} class={cn('gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2 group/item-group flex w-full flex-col', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/item/ItemHeader.svelte
<script lang="ts">
  import type { ItemHeaderProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: ItemHeaderProps = $props();
</script>
<div data-slot="item-header" {...props} class={cn('gap-2 flex basis-full items-center justify-between', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/item/ItemMedia.svelte
<script lang="ts">
  import type { ItemMediaProps } from './types.js';
  import { cn } from 'cn';
  import { itemMediaVariants } from './variants.js';
  let { children, class: classProp, variant = 'default', ...props }: ItemMediaProps = $props();
</script>
<div data-slot="item-media" data-variant={variant} {...props} class={cn(itemMediaVariants({ variant, class: classProp }))}>
  {@render children?.()}
</div>
src/lib/components/ui/item/ItemSeparator.svelte
<script lang="ts">
  import type { ItemSeparatorProps } from './types.js';
  import { cn } from 'cn';
  import { Separator } from '../separator/index.js';
  let { class: classProp, ...props }: ItemSeparatorProps = $props();
</script>
<Separator data-slot="item-separator" orientation="horizontal" class={cn('my-2', classProp)} {...props} />
src/lib/components/ui/item/ItemTitle.svelte
<script lang="ts">
  import type { ItemTitleProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: ItemTitleProps = $props();
</script>
<div data-slot="item-title" {...props} class={cn('gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/item/types.ts
import type { HTMLAttributes } from 'svelte/elements';
import type { RenderSnippet } from '../shared/render.js';
import type { SeparatorProps } from '../separator/index.js';
import type { ItemMediaVariants, ItemVariants } from './variants.js';

type NativeItemProps = HTMLAttributes<HTMLDivElement>;

export type ItemState = { slot: 'item'; variant: ItemVariants['variant']; size: ItemVariants['size'] };
export type ItemProps = NativeItemProps & ItemVariants & { render?: RenderSnippet<ItemState, HTMLDivElement> };
export type ItemGroupProps = NativeItemProps;
export type ItemSeparatorProps = SeparatorProps;
export type ItemMediaProps = NativeItemProps & ItemMediaVariants;
export type ItemContentProps = NativeItemProps;
export type ItemTitleProps = NativeItemProps;
export type ItemDescriptionProps = HTMLAttributes<HTMLParagraphElement>;
export type ItemActionsProps = NativeItemProps;
export type ItemHeaderProps = NativeItemProps;
export type ItemFooterProps = NativeItemProps;
src/lib/components/ui/item/variants.ts
// Adapted from shadcn-ui/ui d75a96ab; MIT: packages/ui/THIRD_PARTY_NOTICES.md.
import { cva } from 'class-variance-authority';
import type { VariantProps } from 'class-variance-authority';
export const itemVariants = cva('[a]:hover:bg-muted rounded-lg border text-sm group/item flex w-full flex-wrap items-center transition-colors duration-100 outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [a]:transition-colors', {
  variants: {
    variant: { default: 'border-transparent', outline: 'border-border', muted: 'bg-muted/50 border-transparent' },
    size: { default: 'gap-2.5 px-3 py-2.5', sm: 'gap-2.5 px-3 py-2.5', xs: 'gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0' },
  },
  defaultVariants: { variant: 'default', size: 'default' },
});
export const itemMediaVariants = cva('gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start flex shrink-0 items-center justify-center [&_svg]:pointer-events-none', {
  variants: {
    variant: { default: 'bg-transparent', icon: "[&_svg:not([class*='size-'])]:size-4", image: 'size-10 overflow-hidden rounded-sm group-data-[size=sm]/item:size-8 group-data-[size=xs]/item:size-6 [&_img]:size-full [&_img]:object-cover' },
  },
  defaultVariants: { variant: 'default' },
});
export type ItemVariants = VariantProps<typeof itemVariants>;
export type ItemMediaVariants = VariantProps<typeof itemMediaVariants>;
src/lib/components/ui/shared/render.ts
import type { Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';

/**
 * Replaces a part's default element, like the `render` snippets of Sveltery Base.
 * Spread `props` onto the host element and render `children` inside it.
 * `Host` is the element the part renders by default, so its typed event handlers carry over.
 */
export type RenderSnippet<State, Host extends HTMLElement = HTMLElement> = Snippet<[props: HTMLAttributes<Host>, state: State, children: Snippet | undefined]>;
src/lib/components/ui/item/index.ts
export { default as Item } from './Item.svelte';
export { default as ItemGroup } from './ItemGroup.svelte';
export { default as ItemSeparator } from './ItemSeparator.svelte';
export { default as ItemMedia } from './ItemMedia.svelte';
export { default as ItemContent } from './ItemContent.svelte';
export { default as ItemTitle } from './ItemTitle.svelte';
export { default as ItemDescription } from './ItemDescription.svelte';
export { default as ItemActions } from './ItemActions.svelte';
export { default as ItemHeader } from './ItemHeader.svelte';
export { default as ItemFooter } from './ItemFooter.svelte';
export { itemVariants, itemMediaVariants } from './variants.js';
export type { ItemVariants, ItemMediaVariants } from './variants.js';
export type {
  ItemProps, ItemState, ItemGroupProps, ItemSeparatorProps, ItemMediaProps, ItemContentProps, ItemTitleProps,
  ItemDescriptionProps, ItemActionsProps, ItemHeaderProps, ItemFooterProps,
} from './types.js';

Update the import paths

Change the imports to match your project setup.

Usage

<script lang="ts">
  import { Button } from '$lib/components/ui/button';
  import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle } from '$lib/components/ui/item';
</script>
<Item variant="outline">
  <ItemContent>
    <ItemTitle>Basic Item</ItemTitle>
    <ItemDescription>A simple item with title and description.</ItemDescription>
  </ItemContent>
  <ItemActions>
    <Button variant="outline" size="sm">Action</Button>
  </ItemActions>
</Item>

Pass a render snippet to render the item as a link. Spread props onto it and render children inside it.

<Item>
  {#snippet render(props, state, children)}
    <a href="/settings" {...props}>{@render children?.()}</a>
  {/snippet}
  <ItemContent>
    <ItemTitle>Settings</ItemTitle>
  </ItemContent>
</Item>