A versatile component for displaying content with media, title, description, and actions.
1<script lang="ts">
2 import { Button } from "@/components/ui/button";
3 import {
4 Item,
Installation
pnpm dlx sprawlify@latest add itemnpx sprawlify@latest add itemyarn sprawlify@latest add itembunx --bun sprawlify@latest add item
Install the following dependencies:
pnpm add @sprawlify/primitives @sprawlify/sveltenpm install @sprawlify/primitives @sprawlify/svelteyarn add @sprawlify/primitives @sprawlify/sveltebun add @sprawlify/primitives @sprawlify/svelte
Add the following files to your project:
1export { default as Item } from "./item.svelte";2export { default as ItemMedia } from "./item-media.svelte";3export { default as ItemContent } from "./item-content.svelte";4export { default as ItemActions } from "./item-actions.svelte";5export { default as ItemGroup } from "./item-group.svelte";6export { default as ItemSeparator } from "./item-separator.svelte";7export { default as ItemTitle } from "./item-title.svelte";8export { default as ItemDescription } from "./item-description.svelte";9export { default as ItemHeader } from "./item-header.svelte";10export { default as ItemFooter } from "./item-footer.svelte";111<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
4import type { HTMLAttributes } from "svelte/elements";
5
6interface Props extends HTMLAttributes<HTMLDivElement>, PolymorphicProps<"div"> {}
7
8let { class: className, children, ...rest }: Props = $props()
9</script>
10
11<Sprawlify
12 as="div"
13 data-scope="item"
14 data-part="actions"
15 data-slot="item-actions"
16 class={cn("gap-2 flex items-center", className)}
17 {...rest}
18>
19 {@render children?.()}
20</Sprawlify>1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
4import type { HTMLAttributes } from "svelte/elements";
5
6interface Props extends HTMLAttributes<HTMLDivElement>, PolymorphicProps<"div"> {}
7
8let { class: className, children, ...rest }: Props = $props()
9</script>
10
11<Sprawlify
12 as="div"
13 data-scope="item"
14 data-part="content"
15 data-slot="item-content"
16 class={cn(
17 "gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none",
18 className
19 )}
20 {...rest}
21>
22 {@render children?.()}
23</Sprawlify>1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
4import type { HTMLAttributes } from "svelte/elements";
5
6interface Props extends HTMLAttributes<HTMLParagraphElement>, PolymorphicProps<"p"> {}
7
8let { class: className, children, ...rest }: Props = $props()
9</script>
10
11<Sprawlify
12 as="p"
13 data-scope="item"
14 data-part="description"
15 data-slot="item-description"
16 class={cn(
17 "text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs [&>a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4",
18 className
19 )}
20 {...rest}
21>
22 {@render children?.()}
23</Sprawlify>1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
4import type { HTMLAttributes } from "svelte/elements";
5
6interface Props extends HTMLAttributes<HTMLDivElement>, PolymorphicProps<"div"> {}
7
8let { class: className, children, ...rest }: Props = $props()
9</script>
10
11<Sprawlify
12 as="div"
13 data-scope="item"
14 data-part="footer"
15 data-slot="item-footer"
16 class={cn(
17 "gap-2 flex basis-full items-center justify-between",
18 className
19 )}
20 {...rest}
21>
22 {@render children?.()}
23</Sprawlify>1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
4import type { HTMLAttributes } from "svelte/elements";
5
6interface Props extends HTMLAttributes<HTMLDivElement>, PolymorphicProps<"div"> {}
7
8let { class: className, children, ...rest }: Props = $props()
9</script>
10
11<Sprawlify
12 as="div"
13 role="list"
14 data-scope="item"
15 data-part="group"
16 data-slot="item-group"
17 class={cn(
18 "gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2 group/item-group flex w-full flex-col",
19 className
20 )}
21 {...rest}
22>
23 {@render children?.()}
24</Sprawlify>1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
4import type { HTMLAttributes } from "svelte/elements";
5
6interface Props extends HTMLAttributes<HTMLDivElement>, PolymorphicProps<"div"> {}
7
8let { class: className, children, ...rest }: Props = $props()
9</script>
10
11<Sprawlify
12 as="div"
13 data-scope="item"
14 data-part="header"
15 data-slot="item-header"
16 class={cn(
17 "gap-2 flex basis-full items-center justify-between",
18 className
19 )}
20 {...rest}
21>
22 {@render children?.()}
23</Sprawlify>1<script lang="ts">
2import { cva, type VariantProps } from "class-variance-authority"
3import { cn } from "@/lib/utils"
4import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
5import type { HTMLAttributes } from "svelte/elements";
6
7const itemMediaVariants = cva(
8 "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",
9 {
10 variants: {
11 variant: {
12 default: "bg-transparent",
13 icon: "[&_svg:not([class*='size-'])]:size-4",
14 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",
15 },
16 },
17 defaultVariants: {
18 variant: "default",
19 },
20 }
21)
22
23interface Props extends HTMLAttributes<HTMLDivElement>, PolymorphicProps<"div">, VariantProps<typeof itemMediaVariants> {}
24
25let { class: className, variant = "default", children, ...rest }: Props = $props()
26</script>
27
28<Sprawlify
29 as="div"
30 data-scope="item"
31 data-part="media"
32 data-slot="item-media"
33 data-variant={variant}
34 class={cn(itemMediaVariants({ variant, className }))}
35 {...rest}
36>
37 {@render children?.()}
38</Sprawlify>1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Separator } from "../separator"
4import type { ComponentProps } from "svelte";
5
6interface Props extends ComponentProps<typeof Separator> {}
7
8let { class: className, ...rest }: Props = $props()
9</script>
10
11<Separator
12 data-scope="item"
13 data-part="separator"
14 data-slot="item-separator"
15 orientation="horizontal"
16 class={cn("my-2", className)}
17 {...rest}
18/>1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
4import type { HTMLAttributes } from "svelte/elements";
5
6interface Props extends HTMLAttributes<HTMLDivElement>, PolymorphicProps<"div"> {}
7
8let { class: className, children, ...rest }: Props = $props()
9</script>
10
11<Sprawlify
12 as="div"
13 data-scope="item"
14 data-part="title"
15 data-slot="item-title"
16 class={cn(
17 "gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center",
18 className
19 )}
20 {...rest}
21>
22 {@render children?.()}
23</Sprawlify>1<script lang="ts">
2import { cva, type VariantProps } from "class-variance-authority"
3import { cn } from "@/lib/utils"
4import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
5import type { HTMLAttributes } from "svelte/elements";
6
7const itemVariants = cva(
8 "[a]:hover:bg-muted rounded-lg border text-sm w-full group/item focus-visible:border-ring focus-visible:ring-ring/50 flex items-center flex-wrap outline-none transition-colors duration-100 focus-visible:ring-[3px] [a]:transition-colors",
9 {
10 variants: {
11 variant: {
12 default: "border-transparent",
13 outline: "border-border",
14 muted: "bg-muted/50 border-transparent",
15 },
16 size: {
17 default: "gap-2.5 px-3 py-2.5",
18 sm: "gap-2.5 px-3 py-2.5",
19 xs: "gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0",
20 },
21 },
22 defaultVariants: {
23 variant: "default",
24 size: "default",
25 },
26 }
27)
28
29interface Props extends HTMLAttributes<HTMLDivElement>, PolymorphicProps<"div">, VariantProps<typeof itemVariants> {}
30
31let { class: className, variant = "default", size = "default", children, ...rest }: Props = $props()
32</script>
33
34<Sprawlify
35 as="div"
36 data-scope="item"
37 data-part="root"
38 data-slot="item"
39 data-variant={variant}
40 data-size={size}
41 class={cn(itemVariants({ variant, size, className }))}
42 {...rest}
43>
44 {@render children?.()}
45</Sprawlify>Update the import paths to match your project setup.
Usage
1import {
2 ItemGroup,
3 ItemSeparator,
4 Item,
5 ItemMedia,
6 ItemContent,
7 ItemTitle,
8 ItemDescription,
9 ItemAction
10} from "@/components/ui/item"1<Item>
2 <ItemMedia variant="icon">
3 <Icon />
4 </ItemMedia>
5 <ItemContent>
6 <ItemTitle>Title</ItemTitle>
7 <ItemDescription>Description</ItemDescription>
8 </ItemContent>
9 <ItemActions>
10 <Button>Action</Button>
11 </ItemActions>
12</Item>Examples
Avatar
You can use ItemMedia with variant="avatar" to display an avatar.
1<script lang="ts">
2 import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
3 import { Button } from "@/components/ui/button";
4 import {
Group
Use ItemGroup to group related items together.
1<script lang="ts">
2import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
3import { Button } from '@/components/ui/button'
4import {
Header
Use ItemHeader to add a header above the item content.
1<script lang="ts">
2import {
3 Item,
4 ItemContent,
Icon
Use ItemMedia with variant="icon" to display an icon.
1<script lang="ts">
2import { Button } from '@/components/ui/button'
3import {
4 Item,
Image
Use ItemMedia with variant="image" to display an image.
1<script lang="ts">
2 import {
3 Item,
4 ItemContent,
Link
Use the asChild prop to render the item as a link. The hover and focus states will be applied to the anchor element.
1<script lang="ts">
2 import {
3 Item,
4 ItemActions,