Collaboration
Project Management
Finance
Stories
A carousel of friends' stories, in video, image or avatar format.
Installation
npx love-ui@latest add storiesUsage
import { Stories, StoriesContent, Story, StoryVideo, StoryImage, StoryAuthor, StoryAuthorImage, StoryAuthorName, StoryTitle, StoryOverlay } from "@/components/stories"<Stories>
<StoriesContent>
{stories.map((story) => (
<Story key={story.id}>
<StoryImage src={story.image} alt={story.title} />
<StoryOverlay>
<StoryAuthor>
<StoryAuthorImage src={story.author.avatar} fallback={story.author.name} />
<StoryAuthorName>{story.author.name}</StoryAuthorName>
</StoryAuthor>
<StoryTitle>{story.title}</StoryTitle>
</StoryOverlay>
</Story>
))}
</StoriesContent>
</Stories>Features
- Composable Stories carousel with smooth scrolling
- Built-in video and image support with proper aspect ratios
- Author information with avatar and name display
- Overlay components for titles and interactive elements
- Multiple aspect ratio options (portrait, square, landscape)
- Hover effects and focus states for accessibility
- Touch and drag support via Embla Carousel
- Optimized for mobile and desktop experiences
Examples
Story Images
Mountain Adventure
CLConnor
Ocean Waves
MOThomas
Forest Trail
NNathan
City Lights
TYTyler
Desert Road
OWOwen
"use client";
import {
Stories,
StoriesContent,
Story,
StoryAuthor,
StoryAuthorImage,
StoryAuthorName,
StoryImage,
StoryOverlay,
StoryTitle,
} from "../../../../../packages/stories";
const stories = [
{
id: 1,
author: "Connor",
avatar:
"https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&h=40&fit=crop&crop=face",
fallback: "CL",
preview:
"https://images.unsplash.com/photo-1753731683731-1032f9457b02?w=1636&fit=crop",
title: "Mountain Adventure",
},
{
id: 2,
author: "Thomas",
avatar:
"https://images.unsplash.com/photo-1494790108755-2616b612b786?w=40&h=40&fit=crop&crop=face",
fallback: "MO",
preview:
"https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=300&h=533&fit=crop",
title: "Ocean Waves",
},
{
id: 3,
author: "Nathan",
avatar:
"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&h=40&fit=crop&crop=face",
fallback: "N",
preview:
"https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=300&h=533&fit=crop",
title: "Forest Trail",
},
{
id: 4,
author: "Tyler",
avatar:
"https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=40&h=40&fit=crop&crop=face",
fallback: "TY",
preview:
"https://images.unsplash.com/photo-1541336032412-2048a678540d?w=300&h=533&fit=crop",
title: "City Lights",
},
{
id: 5,
author: "Owen",
avatar:
"https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&h=40&fit=crop&crop=face",
fallback: "OW",
preview:
"https://images.unsplash.com/photo-1509316785289-025f5b846b35?w=300&fit=crop",
title: "Desert Road",
},
];
const Example = () => (
<Stories>
<StoriesContent>
{stories.map((story) => (
<Story className="aspect-[3/4] w-[200px]" key={story.id}>
<StoryImage alt={story.title} src={story.preview} />
<StoryOverlay side="top" />
<StoryOverlay side="bottom" />
<StoryTitle className="truncate font-medium text-sm">
{story.title}
</StoryTitle>
<StoryAuthor>
<StoryAuthorImage
fallback={story.fallback}
name={story.author}
src={story.avatar}
/>
<StoryAuthorName>{story.author}</StoryAuthorName>
</StoryAuthor>
</Story>
))}
</StoriesContent>
</Stories>
);
export default Example;
Story Avatars
CL
TR
CC
OC
"use client";
import {
Stories,
StoriesContent,
Story,
StoryAuthor,
StoryAuthorImage,
} from "../../../../../packages/stories";
const stories = [
{
id: 1,
author: "Connor Love",
avatar: "https://github.com/loveconnor.png",
fallback: "CL",
},
{
id: 2,
author: "Thomas Raklovits",
avatar: "https://avatars.githubusercontent.com/u/1234567890?v=4",
fallback: "TR",
},
{
id: 3,
author: "Charlie Cambell",
avatar: "https://github.com/loveconnor.png",
fallback: "CC",
},
{
id: 4,
author: "Owen Caudy",
avatar: "https://github.com/loveconnor.png",
fallback: "OC",
},
];
const Example = () => (
<div className="w-full max-w-4xl">
<Stories>
<StoriesContent className="justify-center">
{stories.map((story) => (
<Story className="aspect-square w-12 rounded-full p-0" key={story.id}>
<StoryAuthor className="p-0">
<span
aria-hidden="true"
className="inline-flex size-full rounded-full bg-gradient-to-tr from-[#f9ce34] via-[#ee2a7b] to-[#6228d7] p-0.5"
>
<span className="inline-flex size-full rounded-full bg-white p-0.5">
<StoryAuthorImage
className="size-full"
fallback={story.fallback}
src={story.avatar}
/>
</span>
</span>
</StoryAuthor>
</Story>
))}
</StoriesContent>
</Stories>
</div>
);
export default Example;