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>
  );
}
UI Lab