Button
Clickable element that triggers an action.
import { Button } from "ui-lab-components";
export function Example() {
return <Button>Click me</Button>;
}Button Variants
All available button variants including primary, default, secondary, outline, and ghost styles.
Primary Variant
Default Variant
Secondary Variant
Outline Variant
Ghost Variant
Sizes
import React from 'react'
import { Button } from 'ui-lab-components'
export default function Example() {
return (
<div className="p-4 space-y-8">
<div>
<h3 className="text-sm font-semibold text-foreground-200 mb-3">Primary Variant</h3>
<div className="flex gap-2 flex-wrap">
<Button variant="primary">Primary Button</Button>
<Button variant="primary" disabled>Disabled</Button>
</div>
</div>
<div>
<h3 className="text-sm font-semibold text-foreground-200 mb-3">Default Variant</h3>
<div className="flex gap-2 flex-wrap">
<Button variant="default">Default Button</Button>
<Button variant="default" disabled>Disabled</Button>
</div>
</div>
<div>
<h3 className="text-sm font-semibold text-foreground-200 mb-3">Secondary Variant</h3>
<div className="flex gap-2 flex-wrap">
<Button variant="secondary">Secondary Button</Button>
<Button variant="secondary" disabled>Disabled</Button>
</div>
</div>
<div>
<h3 className="text-sm font-semibold text-foreground-200 mb-3">Outline Variant</h3>
<div className="flex gap-2 flex-wrap">
<Button variant="outline">Outline Button</Button>
<Button variant="outline" disabled>Disabled</Button>
</div>
</div>
<div>
<h3 className="text-sm font-semibold text-foreground-200 mb-3">Ghost Variant</h3>
<div className="flex gap-2 flex-wrap">
<Button variant="ghost">Ghost Button</Button>
<Button variant="ghost" disabled>Disabled</Button>
</div>
</div>
<div>
<h3 className="text-sm font-semibold text-foreground-200 mb-3">Sizes</h3>
<div className="flex gap-2 flex-wrap items-center">
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
</div>
</div>
)
}Multiple Actions
A primary action button grouped with secondary actions and an options menu.
"use client";
import React, { useState } from 'react'
import { Button, Flex } from 'ui-lab-components'
import { FaEllipsisVertical } from "react-icons/fa6";
export default function Example() {
return (
<Flex gap="xs" className="w-110 *:not-last:flex-1">
<Button size="sm" variant="primary" >Subscribe</Button>
<Button size="sm" >Message</Button>
<Button size="icon" variant="outline" icon={<FaEllipsisVertical />} />
</Flex>
);
}Joined Toggle Buttons
Multiple buttons grouped together for view/mode selection with active state indication.
"use client";
import React, { useState } from 'react'
import { Button, Group, Divider, Input, Flex } from 'ui-lab-components'
import { FaList, FaGrip, FaTable, FaPlus } from "react-icons/fa6";
import { LuSearch } from "react-icons/lu";
export default function Example() {
const [viewMode, setViewMode] = useState("list");
return (
<Flex className="w-110" gap="xs" align="center">
<Input
placeholder="Search items..."
icon={<LuSearch />}
className="w-full"
/>
<Group orientation="horizontal" value={viewMode} onChange={setViewMode}>
<Group.Button size="icon" value="list"><FaList /></Group.Button>
<Divider orientation="vertical" />
<Group.Button size="icon" value="grid"><FaGrip /></Group.Button>
<Divider orientation="vertical" />
<Group.Button size="icon" value="table"><FaTable /></Group.Button>
</Group>
<Button size="sm" icon={{ left: <FaPlus size={12} /> }} >New</Button>
</Flex>
);
}Sub Stack Actions
A collection of buttons and inputs arranged horizontally for grouped actions and filtering.
Ctrl+K
"use client";
import React, { useState } from 'react'
import { Button, Group, Input, Badge, Flex } from 'ui-lab-components'
import { FaList, FaGrip, FaPlus } from "react-icons/fa6";
import { LuSearch } from "react-icons/lu";
export default function Example() {
const [viewMode, setViewMode] = useState("list");
return (
<Flex align="center" gap="xs" className="w-110">
<Group orientation="horizontal" spacing="xs" value={viewMode} onChange={setViewMode}>
<Group.Button size="icon" value="list"><FaList /></Group.Button>
<Group.Button size="icon" value="grid"><FaGrip /></Group.Button>
</Group>
<Input
placeholder="Search..."
icon={<LuSearch />}
hint={<Badge size="sm" variant="secondary" >Ctrl+K</Badge>}
/>
<Button size="sm" icon={{ right: <FaPlus size={12} /> }} >Upload</Button>
</Flex>
);
}Split Action Button
A split button for bulk actions with dynamic icons, variants, and async feedback while keeping the primary action easy to repeat.
12 selected
"use client";
import React, { useState } from 'react'
import { Button, Divider, Select, Badge, Flex } from 'ui-lab-components'
import { FaBox, FaSpinner, FaCheck, FaEllipsisVertical, FaCopy, FaTags, FaTrash } from "react-icons/fa6";
type BulkAction = "archive" | "duplicate" | "tag" | "delete";
const selectedCount: number = 12;
const bulkActions: Record<BulkAction, {
label: string;
loadingLabel: string;
successLabel: string;
variant: "primary" | "outline" | "danger";
icon: React.ReactNode;
}> = {
archive: {
label: "Archive",
loadingLabel: "Archiving...",
successLabel: "Archived",
variant: "primary",
icon: <FaBox />,
},
duplicate: {
label: "Duplicate",
loadingLabel: "Duplicating...",
successLabel: "Duplicated",
variant: "outline",
icon: <FaCopy />,
},
tag: {
label: "Add Tags",
loadingLabel: "Applying tags...",
successLabel: "Tagged",
variant: "outline",
icon: <FaTags />,
},
delete: {
label: "Delete",
loadingLabel: "Deleting...",
successLabel: "Deleted",
variant: "danger",
icon: <FaTrash />,
},
};
export default function Example() {
const [action, setAction] = useState<BulkAction>("archive");
const [status, setStatus] = useState<"idle" | "loading" | "done">("idle");
const cfg = bulkActions[action];
const itemsLabel = `${selectedCount} ${selectedCount === 1 ? "item" : "items"}`;
const handleExecute = () => {
setStatus("loading");
setTimeout(() => {
setStatus("done");
setTimeout(() => setStatus("idle"), 2000);
}, 1500);
};
const leftIcon = status === "loading" ? <FaSpinner className="animate-spin" /> : status === "done" ? <FaCheck /> : cfg.icon;
const label = status === "loading" ? cfg.loadingLabel : status === "done" ? cfg.successLabel : `${cfg.label} ${itemsLabel}`;
return (
<Flex gap="xs" className="w-110" align="center">
<Badge variant="secondary">{selectedCount} selected</Badge>
<Select className="flex h-10" selectedKey={action} onSelectionChange={(key) => setAction(key as BulkAction)} isDisabled={status !== "idle"}>
<Button
onPress={handleExecute}
variant={cfg.variant}
size="sm"
className="w-full rounded-none justify-start"
isDisabled={status !== "idle" || selectedCount === 0}
icon={leftIcon}
>
{label}
</Button>
<Divider orientation="vertical" spacing="none" />
<Select.Trigger aria-label="Choose a bulk action" />
<Select.Content>
<Select.Item value="archive" textValue="Archive" icon={<FaBox className="h-3 w-3" />}>Archive</Select.Item>
<Select.Item value="duplicate" textValue="Duplicate" icon={<FaCopy className="h-3 w-3" />}>Duplicate</Select.Item>
<Select.Item value="tag" textValue="Add Tags" icon={<FaTags className="h-3 w-3" />}>Add Tags</Select.Item>
<Select.Item value="delete" textValue="Delete" icon={<FaTrash className="h-3 w-3" />}>Delete</Select.Item>
</Select.Content>
</Select>
<Button size="icon" variant="outline" icon={<FaEllipsisVertical />} aria-label="More bulk actions" />
</Flex>
);
}