Components
Animated List
A list whose items fade/slide in with a per-item stagger delay. Purely presentational — no Morphos equivalent.
Installation
npx kosmesis add animated-listpnpm dlx kosmesis add animated-listyarn dlx kosmesis add animated-listbunx kosmesis add animated-listCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { cn } from "@/lib/utils";export interface AnimatedListProps { class?: string; id?: string; children?: Children;}@Component()export class AnimatedList extends StatelessComponent<AnimatedListProps> { render() { const { class: cls, id, children } = this.props; return ( <div id={id} data-slot="animated-list" class={cn("flex flex-col gap-2", cls)}> {children} </div> ); }}export interface AnimatedListItemProps { index?: number; class?: string; id?: string; children?: Children;}// Stagger delay is inline (a dynamic per-item value, so it can't be a static Tailwind class).@Component()export class AnimatedListItem extends StatelessComponent<AnimatedListItemProps> { render() { const { index = 0, class: cls, id, children } = this.props; return ( <div id={id} data-slot="animated-list-item" class={cn("animate-in fade-in slide-in-from-top-2", cls)} style={{ animationDelay: `${String(index * 80)}ms`, animationDuration: "300ms", animationFillMode: "backwards" }} > {children} </div> ); }}Install the following dependencies:
npm install @praxisjs/csspnpm add @praxisjs/cssyarn add @praxisjs/cssbun add @praxisjs/cssCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { cx, keyframes, Stylesheet, Styled } from "@praxisjs/css";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";const fadeSlideIn = keyframes("kosmesis-animated-list-item", { from: { opacity: "0", transform: "translateY(-0.5rem)" }, to: { opacity: "1", transform: "translateY(0)" },});class AnimatedListStyles extends Stylesheet { $root = this.css({ display: "flex", flexDirection: "column", gap: "0.5rem" }); $item = this.css({ animation: `${fadeSlideIn} 300ms ease both` });}export interface AnimatedListProps { class?: string; id?: string; children?: Children;}@Component()export class AnimatedList extends StatelessComponent<AnimatedListProps> { @Styled(AnimatedListStyles) $s!: AnimatedListStyles; render() { const { class: cls, id, children } = this.props; return ( <div id={id} data-slot="animated-list" class={cx(this.$s.$root, cls)}> {children} </div> ); }}export interface AnimatedListItemProps { index?: number; class?: string; id?: string; children?: Children;}// Stagger delay is inline (a dynamic per-item value, so it can't be a static class).@Component()export class AnimatedListItem extends StatelessComponent<AnimatedListItemProps> { @Styled(AnimatedListStyles) $s!: AnimatedListStyles; render() { const { index = 0, class: cls, id, children } = this.props; return ( <div id={id} data-slot="animated-list-item" class={cx(this.$s.$item, cls)} style={{ animationDelay: `${String(index * 80)}ms` }} > {children} </div> ); }}Examples
About
Purely presentational — no Morphos equivalent. The Tailwind flavor reuses tw-animate-css's
animate-in/fade-in/slide-in-from-top utilities (already a Kosmesis runtime dependency, see
Dialog/Popover); the @praxisjs/css flavor defines the same fade+slide as a local keyframes().
Either way, the per-item stagger delay (index * 80ms) is a dynamic value applied via inline style.
Usage
import { AnimatedList, AnimatedListItem } from "@/components/ui/animated-list";
<AnimatedList>
{items.map((item, i) => (
<AnimatedListItem key={item.id} index={i}>{item.text}</AnimatedListItem>
))}
</AnimatedList>Props
AnimatedListItem
| Prop | Type | Default |
|---|---|---|
index | number | 0 |
class | string | — |
AnimatedList accepts class, id, and children only.