Patterns
Activity feed
Decisions waiting on a person. list (in a card) · cards (tone edge + icon tile) · compact (sidebar, phone).
Gate 2 offline
6 minNo heartbeat for 6 minutes
Cash shift unbalanced
22:10৳350 short at Banani
3 monthly parkers to approve
1 hNight pass · Gulshan
feed.tsx
"use client";
import { ActivityFeed, Button, Card, Segmented } from "@waveinno/ui";
import { Users, Banknote, WifiOff } from "lucide-react";
import * as React from "react";
export default function FeedDemo() {
const [variant, setVariant] = React.useState<"list" | "cards" | "compact">("cards");
const items = [
{ id: "1", tone: "danger" as const, icon: <WifiOff />, time: "6 min", title: "Gate 2 offline", detail: "No heartbeat for 6 minutes", action: <Button size="sm">Open</Button> },
{ id: "2", tone: "warning" as const, icon: <Banknote />, time: "22:10", title: "Cash shift unbalanced", detail: "৳350 short at Banani", action: <Button size="sm">Review</Button> },
{ id: "3", tone: "info" as const, icon: <Users />, time: "1 h", title: "3 monthly parkers to approve", detail: "Night pass · Gulshan", action: <Button size="sm">Approve</Button> },
];
return (
<div className="space-y-3">
<Segmented value={variant} onChange={setVariant} size="md" options={[{ value: "list", label: "List" }, { value: "cards", label: "Cards" }, { value: "compact", label: "Compact" }]} />
{variant === "list" ? (
<Card>
<ActivityFeed items={items} />
</Card>
) : variant === "compact" ? (
<Card className="max-w-md">
<ActivityFeed items={items} variant="compact" />
</Card>
) : (
<ActivityFeed items={items} variant="cards" className="max-w-2xl" />
)}
</div>
);
}Import#
Everything comes from the package root. The example above uses:
your-component.tsx
import { ActivityFeed, Button, Card, Segmented } from "@waveinno/ui";Props#
Read from the source of this version, so they match the code exactly.
<ActivityFeed>
src/components/patterns/activity-feed.tsx| Prop | Type | Default | Description |
|---|---|---|---|
itemsrequired | FeedItem[] | — | |
variant | "list" | "cards" | "compact" | "list" | |
className | string | — |
<Button>
src/components/ui/button.tsx| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | |
loading | boolean | — |
Also takes ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants>.
<Card>
src/components/ui/card.tsx| Prop | Type | Default | Description |
|---|---|---|---|
interactive | boolean | — |
Also takes HTMLAttributes<HTMLDivElement>.
<Segmented>
src/components/ui/segmented.tsx| Prop | Type | Default | Description |
|---|---|---|---|
valuerequired | T | — | |
onChangerequired | (v: T) => void | — | |
optionsrequired | SegmentedOption<T>[] | — | |
className | string | — | |
ariaLabel | string | — | |
variant | keyof typeof TRACK | "pill" | |
size | keyof typeof SIZES | "sm" | |
fullWidth | boolean | false | Stretch to the container, options sharing the width equally. |
Install#
If the project does not have the package yet, add it, then follow the setup for Next.js or Vite once.
$ npm install @waveinno/ui