# Namespace UIKit
**Category**: docs
**URL**: https://namespace-uikit.vercel.app/docs
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/index.mdx
> Accessible React components for Namespace products and modern web applications.
Namespace UIKit is a typed React component library built on accessible React primitives and Tailwind CSS. It includes the foundational and advanced components documented on this site.
## Start here
- [Install UIKit](./getting-started)
- [Browse components](./components)
- [Read the AI index](/llms.txt)
# Accordion
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/accordion
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/accordion.mdx
> A collapsible content panel for organizing information in a compact space
## Import
```tsx
import { Accordion } from "@thenamespace/uikit";
```
### Usage
```tsx
import { Accordion } from "@thenamespace/uikit";
import {
RefreshIcon,
PackageIcon,
ArrowDown01Icon,
CreditCardIcon,
Globe02Icon,
ReceiptDollarIcon,
ShoppingBag01Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
const items = [
{
content:
"Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
icon: ,
title: "How do I place an order?",
},
{
content:
"Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
icon: ,
title: "Can I modify or cancel my order?",
},
{
content:
"We accept all major credit cards, including Visa, Mastercard, and American Express.",
icon: ,
title: "What payment methods do you accept?",
},
{
content:
"Shipping costs vary based on your location and the size of your order. We offer free shipping for orders over $50.",
icon: ,
title: "How much does shipping cost?",
},
{
content:
"Yes, we ship to most countries. Please check our shipping rates and policies for more information.",
icon: ,
title: "Do you ship internationally?",
},
{
content:
"If you're not satisfied with your purchase, you can request a refund within 30 days of purchase. Please contact our customer support team for assistance.",
icon: ,
title: "How do I request a refund?",
},
];
export function Basic() {
return (
{items.map((item, index) => (
{item.icon ? (
{item.icon}
) : null}
{item.title}
{item.content}
))}
);
}
```
### Anatomy
Import the Accordion component and access all parts using dot notation.
```tsx
import { Accordion } from "@thenamespace/uikit";
export default () => (
);
```
### Surface
```tsx
import { Accordion } from "@thenamespace/uikit";
import {
RefreshIcon,
PackageIcon,
ArrowDown01Icon,
CreditCardIcon,
Globe02Icon,
ReceiptDollarIcon,
ShoppingBag01Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
const items = [
{
content:
"Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
icon: ,
title: "How do I place an order?",
},
{
content:
"Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
icon: ,
title: "Can I modify or cancel my order?",
},
{
content:
"We accept all major credit cards, including Visa, Mastercard, and American Express.",
icon: ,
title: "What payment methods do you accept?",
},
{
content:
"Shipping costs vary based on your location and the size of your order. We offer free shipping for orders over $50.",
icon: ,
title: "How much does shipping cost?",
},
{
content:
"Yes, we ship to most countries. Please check our shipping rates and policies for more information.",
icon: ,
title: "Do you ship internationally?",
},
{
content:
"If you're not satisfied with your purchase, you can request a refund within 30 days of purchase. Please contact our customer support team for assistance.",
icon: ,
title: "How do I request a refund?",
},
];
export function Surface() {
return (
{items.map((item, index) => (
{item.icon ? (
{item.icon}
) : null}
{item.title}
{item.content}
))}
);
}
```
### Multiple Expanded
```tsx
import {Accordion} from "@thenamespace/uikit";
export function Multiple() {
return (
Getting Started
Learn the basics of Namespace UIKit and how to integrate it into your React project. This section
covers installation, setup, and your first component.
Core Concepts
Understand the fundamental concepts behind Namespace UIKit, including the compound component
pattern, styling with Tailwind CSS, and accessibility features.
Advanced Usage
Explore advanced features like custom variants, theme customization, and integration
with other libraries in your React ecosystem.
Best Practices
Follow our recommended best practices for building performant, accessible, and
maintainable applications with Namespace UIKit components.
);
}
```
### Controlled
```tsx
"use client";
import React from "react";
import {
Accordion,
Button,
useDisclosureGroupNavigation,
} from "@thenamespace/uikit";
import {
ArrowDown01Icon,
ArrowUp01Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
const items = [
{
content:
"Learn the basics of Namespace UIKit and how to integrate it into your React project. This section covers installation, setup, and your first component.",
id: "getting-started",
title: "Getting Started",
},
{
content:
"Understand the fundamental concepts behind Namespace UIKit, including the compound component pattern, styling with Tailwind CSS, and accessibility features.",
id: "core-concepts",
title: "Core Concepts",
},
{
content:
"Explore advanced features like custom variants, theme customization, and integration with other libraries in your React ecosystem.",
id: "advanced-usage",
title: "Advanced Usage",
},
];
export function Controlled() {
const [expandedKeys, setExpandedKeys] = React.useState(
new Set(["getting-started"]),
);
const itemIds = items.map((item) => item.id);
const { isNextDisabled, isPrevDisabled, onNext, onPrevious } =
useDisclosureGroupNavigation({
expandedKeys,
itemIds,
onExpandedChange: setExpandedKeys,
});
return (
);
}
```
### Custom Indicator
```tsx
"use client";
import React from "react";
import type { Key } from "@thenamespace/uikit";
import { Accordion } from "@thenamespace/uikit";
import {
Add01Icon,
ChevronsDownIcon,
CircleChevronDownIcon,
HugeiconsIcon,
Remove01Icon,
} from "@thenamespace/uikit/icons";
export function CustomIndicator() {
const [expandedKeys, setExpandedKeys] = React.useState>(new Set([""]));
return (
Using Plus/Minus Icon
{expandedKeys.has("1") ? (
) : (
)}
This accordion uses a plus icon that transforms when expanded. The icon automatically
rotates 45 degrees to form an X.
Using Caret Icon
This item uses a caret icon for the indicator. The rotation animation is applied
automatically.
Using Arrow Icon
This item uses an arrow icon. Any icon you pass will receive the rotation animation when
the item expands.
);
}
```
### Disabled State
```tsx
import {Accordion} from "@thenamespace/uikit";
export function Disabled() {
return (
Entire accordion disabled
Disabled Item 1
This content cannot be accessed when the accordion is disabled.
Disabled Item 2
This content cannot be accessed when the accordion is disabled.
Individual items disabled
Active Item
This item is active and can be toggled normally.
Disabled Item
This content cannot be accessed when the item is disabled.
Another Active Item
This item is also active and can be toggled.
);
}
```
### FAQ Layout
```tsx
import { Accordion } from "@thenamespace/uikit";
import { ArrowDown01Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function FAQ() {
const categories = [
{
items: [
{
content:
"Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
title: "How do I place an order?",
},
{
content:
"Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
title: "Can I modify or cancel my order?",
},
],
title: "General",
},
{
items: [
{
content:
"You can purchase a license directly from our website. Select the license type that fits your needs and proceed to checkout.",
title: "How do I purchase a license?",
},
{
content:
"A standard license is for personal use or small projects, while a pro license includes commercial use rights and priority support.",
title: "What is the difference between a standard and a pro license?",
},
],
title: "Licensing",
},
{
items: [
{
content:
"You can reach our support team through the contact form on our website, or email us directly at support@example.com.",
title: "How do I get support?",
},
],
title: "Support",
},
];
return (
Frequently Asked Questions
Everything you need to know about licensing and usage.
);
}
```
### Custom Styles
```tsx
import { Accordion, cn } from "@thenamespace/uikit";
import { ArrowDown01Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
const items = [
{
content: "Stay informed about your account activity with real-time notifications.",
iconUrl: "/assets/docs/3dicons/bell-small.png",
subtitle: "Receive account activity updates",
title: "Set Up Notifications",
},
{
content: "Enhance your browsing experience by installing our official browser extension",
iconUrl: "/assets/docs/3dicons/compass-small.png",
subtitle: "Connect your browser to your account",
title: "Set up Browser Extension",
},
{
content:
"Begin your journey into the world of digital collectibles by creating your first NFT. ",
iconUrl: "/assets/docs/3dicons/mint-collective-small.png",
subtitle: "Create your first collectible",
title: "Mint Collectible",
},
];
export function CustomStyles() {
return (
{items.map((item) => (
{item.iconUrl ? (
) : null}
{item.title}{item.subtitle}
{item.content}
))}
);
}
```
### Without Separator
```tsx
import { Accordion } from "@thenamespace/uikit";
import {
ArrowDown01Icon,
CreditCardIcon,
ReceiptDollarIcon,
ShoppingBag01Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
const items = [
{
content:
"Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
icon: ,
title: "How do I place an order?",
},
{
content:
"Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
icon: ,
title: "Can I modify or cancel my order?",
},
{
content:
"We accept all major credit cards, including Visa, Mastercard, and American Express.",
icon: ,
title: "What payment methods do you accept?",
},
];
export function WithoutSeparator() {
return (
{items.map((item, index) => (
{item.icon ? (
{item.icon}
) : null}
{item.title}
{item.content}
))}
);
}
```
### Custom Render Function
```tsx
"use client";
import { Accordion } from "@thenamespace/uikit";
import {
RefreshIcon,
PackageIcon,
ArrowDown01Icon,
CreditCardIcon,
Globe02Icon,
ReceiptDollarIcon,
ShoppingBag01Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
const items = [
{
content:
"Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
icon: ,
title: "How do I place an order?",
},
{
content:
"Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
icon: ,
title: "Can I modify or cancel my order?",
},
{
content:
"We accept all major credit cards, including Visa, Mastercard, and American Express.",
icon: ,
title: "What payment methods do you accept?",
},
{
content:
"Shipping costs vary based on your location and the size of your order. We offer free shipping for orders over $50.",
icon: ,
title: "How much does shipping cost?",
},
{
content:
"Yes, we ship to most countries. Please check our shipping rates and policies for more information.",
icon: ,
title: "Do you ship internationally?",
},
{
content:
"If you're not satisfied with your purchase, you can request a refund within 30 days of purchase. Please contact our customer support team for assistance.",
icon: ,
title: "How do I request a refund?",
},
];
export function CustomRenderFunction() {
return (
}
>
{items.map((item, index) => (
}
>
}
>
}
>
{item.icon ? (
{item.icon}
) : null}
{item.title}
}
>
{item.content}
))}
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
"use client";
import { Accordion, cn } from "@thenamespace/uikit";
import { ArrowDown01Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
const items = [
{
content:
"Stay informed about your account activity with real-time notifications. You'll receive instant alerts for important events like transactions, new messages, security updates, and system announcements. ",
iconUrl: "/assets/docs/3dicons/bell-small.png",
title: "Set Up Notifications",
subtitle: "Receive account activity updates",
},
{
content:
"Enhance your browsing experience by installing our official browser extension. The extension provides seamless integration with your account, allowing you to receive notifications directly in your browser, quickly access your dashboard, and interact with web3 applications securely. Compatible with Chrome, Firefox, Edge, and Brave browsers.",
iconUrl: "/assets/docs/3dicons/compass-small.png",
title: "Set up Browser Extension",
subtitle: "Connect you browser to your account",
},
{
content:
"Begin your journey into the world of digital collectibles by creating your first NFT. Our intuitive minting process guides you through uploading your artwork, setting metadata, choosing royalty percentages, and deploying to the blockchain. Whether you're an artist, creator, or collector, you'll find all the tools you need to bring your digital assets to life. Your collectibles are stored on IPFS for permanent decentralized storage.",
iconUrl:
"/assets/docs/3dicons/mint-collective-small.png",
title: "Mint Collectible",
subtitle: "Create your first collectible",
},
];
export function CustomStyles() {
return (
{items.map((item, index) => (
{item.iconUrl ? (
) : null}
{item.title}{item.subtitle}
{item.content}
))}
);
}
```
### Customizing the component classes
To customize the Accordion component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.accordion {
@apply rounded-xl bg-gray-50;
}
.accordion__trigger {
@apply font-semibold text-lg;
}
.accordion--outline {
@apply shadow-lg border-2;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Accordion component uses these CSS classes:
#### Base Classes
- `.accordion` - Base accordion container
- `.accordion__body` - Content body container
- `.accordion__heading` - Heading wrapper
- `.accordion__indicator` - Expand/collapse indicator icon
- `.accordion__item` - Individual accordion item
- `.accordion__panel` - Collapsible panel container
- `.accordion__trigger` - Clickable trigger button
#### Variant Classes
- `.accordion--outline` - Outline variant with border and background
#### State Classes
- `.accordion__trigger[aria-expanded="true"]` - Expanded state
- `.accordion__panel[aria-hidden="false"]` - Panel visible state
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Hover**: `:hover` or `[data-hovered="true"]` on trigger
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on trigger
- **Disabled**: `:disabled` or `[aria-disabled="true"]` on trigger
- **Expanded**: `[aria-expanded="true"]` on trigger
## API Reference
### Accordion Props
| Prop | Type | Default | Description |
| ------------------------ | ---------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------- |
| `allowsMultipleExpanded` | `boolean` | `false` | Whether multiple items can be expanded at once |
| `defaultExpandedKeys` | `Iterable` | - | The initial expanded keys |
| `expandedKeys` | `Iterable` | - | The controlled expanded keys |
| `onExpandedChange` | `(keys: Set) => void` | - | Handler called when expanded keys change |
| `isDisabled` | `boolean` | `false` | Whether the entire accordion is disabled |
| `variant` | `"default" \| "surface"` | `"default"` | The visual variant of the accordion |
| `hideSeparator` | `boolean` | `false` | Hide separator lines between accordion items |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The accordion items |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Accordion.Item Props
| Prop | Type | Default | Description |
| ------------------ | -------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- |
| `id` | `Key` | - | Unique identifier for the item |
| `isDisabled` | `boolean` | `false` | Whether this item is disabled |
| `defaultExpanded` | `boolean` | `false` | Whether item is initially expanded |
| `isExpanded` | `boolean` | - | Controlled expanded state |
| `onExpandedChange` | `(isExpanded: boolean) => void` | - | Handler for expanded state changes |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The item content |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Accordion.Trigger Props
| Prop | Type | Default | Description |
| ------------ | -------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Trigger content or render function |
| `onPress` | `() => void` | - | Additional press handler |
| `isDisabled` | `boolean` | - | Whether trigger is disabled |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Accordion.Panel Props
| Prop | Type | Default | Description |
| ----------- | --------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Panel content |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Accordion.Indicator Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Custom indicator icon |
### Accordion.Body Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Body content |
# Action Bar
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/action-bar
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/action-bar.mdx
> A floating toolbar for contextual actions — bulk selection, editing controls, or any set of actions that appear in response to user interaction.
## Usage
{/* DEMO action-bar-default */}
```tsx
"use client";
import { useState } from "react";
import { ActionBar } from "@thenamespace/uikit";
import { Button } from "@thenamespace/uikit/button";
import { Chip } from "@thenamespace/uikit/chip";
import { ListView } from "@thenamespace/uikit/list-view";
import { Separator } from "@thenamespace/uikit/separator";
import { Tooltip } from "@thenamespace/uikit/tooltip";
import type { Selection } from "react-aria-components";
import { Icon } from "@/demos/icon";
const files = [
"Project proposal.pdf",
"Q4 financial report.xlsx",
"Brand guidelines.fig",
"Team photo.jpg",
"Meeting notes.md",
"API documentation.pdf",
].map((label, index) => ({ id: index + 1, label }));
function Bar({ clear, count }: { clear: () => void; count: number }) {
return (
0}>
{count}
{[
["Edit", "lucide:pencil"],
["Export", "lucide:arrow-up-from-line"],
["Archive", "lucide:archive"],
].map(([label, icon]) => (
))}
Clear selection
);
}
function DefaultDemo() {
const [selected, setSelected] = useState(new Set());
const count = selected === "all" ? files.length : selected.size;
return (
);
}
export const DemoDefaultExample = () => ;
```
## Anatomy
Import the Agenda component and the `useAgenda` hook. Access all subcomponents using dot notation.
```tsx
import {Agenda, useAgenda} from "@thenamespace/uikit";
const agenda = useAgenda({
events: [...],
defaultView: "week",
});
{/* Day / Week view */}
all-day
{agenda.allDayLayout.map((item) => (
))}
{agenda.visibleDays.map((day) => (
{agenda.getEventsForDay(day).map((event) => (
))}
))}
{/* Month view */}
{agenda.visibleWeeks.map((week, i) => {
const rowLayout = agenda.getMonthRowLayout(week);
return (
{rowLayout.items.map((item) => (
))}
{week.map((day, colIdx) => (
{agenda.getPerCellEvents(day, week).map((event) => (
))}
))}
);
})}
```
## Views
The Agenda supports three views controlled via the `ViewSelector` or programmatically through `setView`:
- **Day** — single day with full time grid
- **Week** — 7-day (or custom count) view with shared time grid
- **Month** — calendar grid with spanning multi-day events
## Events
Events are defined as an array of `AgendaEvent` objects:
```tsx
interface AgendaEvent {
id: string;
title: string;
start: CalendarDateTime;
end: CalendarDateTime;
color?: string;
isAllDay?: boolean;
isReadOnly?: boolean;
status?: "confirmed" | "unconfirmed";
}
```
### Unconfirmed Events
Set `status: "unconfirmed"` to render an event with a dashed border and transparent background, indicating a tentative or pending event.
### Read-Only Events
Set `isReadOnly: true` to prevent an event from being moved or resized. The event can still be selected but drag interactions are disabled and the resize handle is hidden.
## Drag Interactions
All drag interactions work out of the box when callbacks are provided:
- **Drag to create** — click and drag on an empty time slot to create a new event
- **Drag to move** — drag an event to a different time or day
- **Drag to resize** — drag the bottom edge of an event to change its duration
- **Cross-day move** — drag an event horizontally to move it to a different day
On mobile, drag interactions (create, move, resize) are disabled by default. The consumer controls this by passing `undefined` for the drag callbacks when on a small screen.
### Event Callbacks
```tsx
const agenda = useAgenda({
events,
onEventCreate: (event) => {
/* { start, end } */
},
onEventMove: (id, start, end) => {
/* moved */
},
onEventResize: (id, start, end) => {
/* resized */
},
onEventDelete: (id) => {
/* deleted via Delete/Backspace key */
},
onEventSelect: (id) => {
/* selected */
},
});
```
## All-Day Events
All-day events appear in a collapsible section above the time grid. Multi-day all-day events span across day columns.
The section includes an expand/collapse toggle. When collapsed, event counts are shown per day (e.g. "2 events"). Customize the collapsed label with the `collapsedLabel` prop on `Agenda.AllDaySection`.
## Month View Features
### Spanning Events
Multi-day all-day events render as bars spanning across the month grid row. Use `getMonthRowLayout(week)` to compute layout positions and `getPerCellEvents(day, week)` for per-cell events.
### Event Overflow
`Agenda.MonthCell` limits visible events via the `maxEvents` prop (default: 2). Overflow shows a "N more" link that navigates to the day view. Customize the label with the `moreLabel` prop.
### Date Navigation
Clicking a date number in the month grid navigates to that date in day view. The first day of each month shows the month name (e.g. "May 1").
## Weekend Highlighting
Saturday and Sunday columns automatically receive a subtle gray background (`data-weekend` attribute) in all views.
## Current Time Indicator
A live indicator shows the current time in the time grid:
- Displays a time label badge (e.g. "10:30 AM") in the time column
- In week view, a faded line spans all columns with an active highlight on today's column
- Nearby hour labels auto-hide to avoid overlap
- Updates every minute
## CSS Classes
### Base
- `.agenda` — Root container. Sets CSS custom properties for sizing.
### CSS Variables
- `--agenda-slot-height` — Height of each hour slot (default: `60px`).
- `--agenda-time-column-width` — Width of the time labels column (default: `58px`).
- `--agenda-current-time-color` — Color of the current time indicator (default: `var(--color-danger)`).
- `--agenda-event-radius` — Border radius of event cards (default: `var(--radius-md)`).
### Header
- `.agenda__header` — Flex container for heading, view selector, and navigation.
- `.agenda__heading` — Month/year title text.
- `.agenda__navigation` — Wrapper for nav buttons and today button.
- `.agenda__nav-button` — Override hook for navigation arrow buttons (uses Namespace UIKit Button).
- `.agenda__today-button` — Override hook for the Today button (uses Namespace UIKit Button).
- `.agenda__view-selector` — Override hook for the view selector (uses Namespace UIKit Segment).
### Day/Week View
- `.agenda__week-header` — Row of day headers above the time grid.
- `.agenda__day-header` — Individual day header with name and date.
- `.agenda__time-grid` — Scrollable time grid container.
- `.agenda__time-labels` — Sticky column of hour labels.
- `.agenda__time-label` — Individual hour label.
- `.agenda__day-column` — Column for a single day's events.
- `.agenda__time-slot` — Individual hour slot row.
### Events
- `.agenda__event` — Positioned event card in the time grid.
- `.agenda__event-title` — Event title text.
- `.agenda__event-time` — Event time range text.
- `.agenda__resize-handle` — Bottom resize handle with hover indicator.
### All-Day Section
- `.agenda__all-day-section` — Grid container for all-day events.
- `.agenda__all-day-toggle` — Expand/collapse chevron button.
- `.agenda__all-day-label` — "all-day" label text.
- `.agenda__all-day-event` — All-day event bar.
- `.agenda__all-day-summary` — Collapsed event count per day.
### Month View
- `.agenda__month-grid` — Month grid container.
- `.agenda__month-weekday-header` — Sticky weekday names row.
- `.agenda__month-row` — Week row in the month grid.
- `.agenda__month-cell` — Individual day cell.
- `.agenda__month-cell-date` — Date number button (navigates to day view).
- `.agenda__month-cell-more` — "N more" overflow link.
- `.agenda__month-event` — Per-cell event in month view.
- `.agenda__month-spanning-event` — Multi-day event bar spanning across cells.
### Interactive States
- `[data-dragging]` — Applied during drag interactions.
- `[data-resizing]` — Applied during resize.
- `[data-selected="true"]` — Applied to selected events.
- `[data-status="unconfirmed"]` — Dashed border style for tentative events.
- `[data-readonly]` — Applied to read-only events.
- `[data-weekend]` — Applied to weekend columns and cells.
- `[data-today]` — Applied to today's date elements.
- `[data-drop-target]` — Applied to the target cell during drag.
### Previews
- `.agenda__create-preview` — Dashed preview rectangle during drag-to-create.
- `.agenda__drop-preview` — Outlined preview at the target position during drag-to-move.
## API Reference
### useAgenda
The main hook for managing agenda state. Returns all data and methods needed by the component.
| Option | Type | Default | Description |
| ----------------- | ------------------------------- | -------- | ------------------------------------------------------------ |
| `events` | `AgendaEvent[]` | — | Array of events to display. Required. |
| `defaultView` | `"day" \| "week" \| "month"` | `"week"` | Initial view. |
| `view` | `"day" \| "week" \| "month"` | — | Controlled view state. |
| `onViewChange` | `(view: AgendaView) => void` | — | Called when the view changes. |
| `defaultDate` | `CalendarDate` | today | Initial focused date. |
| `date` | `CalendarDate` | — | Controlled date state. |
| `onDateChange` | `(date: CalendarDate) => void` | — | Called when the date changes. |
| `startHour` | `number` | `0` | First visible hour in the time grid. |
| `endHour` | `number` | `24` | Last visible hour in the time grid. |
| `slotDuration` | `number` | `60` | Duration of each time slot in minutes. |
| `onEventCreate` | `(event: {start, end}) => void` | — | Called when dragging to create a new event. |
| `onEventDelete` | `(id: string) => void` | — | Called when Delete/Backspace is pressed on a selected event. |
| `onEventMove` | `(id, start, end) => void` | — | Called when an event is dragged to a new position. |
| `onEventResize` | `(id, start, end) => void` | — | Called when an event is resized. |
| `onEventSelect` | `(id: string \| null) => void` | — | Called when an event is selected or deselected. |
| `selectedEventId` | `string \| null` | — | Controlled selected event state. |
### Agenda
Root component. Wraps children in context and Motion providers.
Also supports all HTML `div` props.
### Agenda.Header
Container for heading, view selector, and navigation controls.
Also supports all HTML `div` props.
### Agenda.Heading
Displays the current month and year (e.g. "May 2026").
Also supports all HTML `h1` props.
### Agenda.ViewSelector
Segmented control for switching between day, week, and month views. Built on the Namespace UIKit Segment component.
| Prop | Type | Default | Description |
| ------ | ---------------------- | ------- | ---------------------------- |
| `size` | `"sm" \| "md" \| "lg"` | `"sm"` | Size of the segment control. |
### Agenda.NavButton
Navigation button for previous/next. Built on the Namespace UIKit Button component.
| Prop | Type | Default | Description |
| ------ | ---------------------- | ------- | ------------------------ |
| `slot` | `"previous" \| "next"` | — | Direction of navigation. |
### Agenda.TodayButton
Button to navigate to today's date. Built on the Namespace UIKit Button component.
### Agenda.AllDaySection
Collapsible section for all-day events with a CSS grid layout for spanning events.
| Prop | Type | Default | Description |
| ---------------- | --------------------------- | ------------ | ---------------------------------------- |
| `collapsedLabel` | `(count: number) => string` | `"N events"` | Custom label for collapsed event counts. |
### Agenda.AllDayEvent
An all-day event bar positioned in the grid.
| Prop | Type | Default | Description |
| ---------- | ------------- | ------- | ---------------------------------- |
| `event` | `AgendaEvent` | — | The event data. Required. |
| `colStart` | `number` | — | Grid column start index (0-based). |
| `colSpan` | `number` | — | Number of columns to span. |
| `row` | `number` | — | Row index for stacking. |
### Agenda.Event
A timed event card positioned absolutely in a day column. Supports drag-to-move and drag-to-resize.
| Prop | Type | Default | Description |
| ------- | ------------- | ------- | ------------------------- |
| `event` | `AgendaEvent` | — | The event data. Required. |
### Agenda.MonthCell
A day cell in the month grid. Limits visible events and shows overflow.
| Prop | Type | Default | Description |
| ------------------ | --------------------------- | ---------- | ------------------------------------------------- |
| `date` | `CalendarDate` | — | The date for this cell. Required. |
| `maxEvents` | `number` | `2` | Maximum number of events to show before overflow. |
| `moreLabel` | `(count: number) => string` | `"N more"` | Custom label for the overflow link. |
| `spanningRowCount` | `number` | `0` | Number of spanning event rows above this cell. |
### Agenda.MonthSpanningEvent
A multi-day event bar in the month grid, positioned absolutely across cells.
| Prop | Type | Default | Description |
| ---------- | ------------- | ------- | -------------------------------- |
| `event` | `AgendaEvent` | — | The event data. Required. |
| `colStart` | `number` | — | Column start index (0-based). |
| `colSpan` | `number` | — | Number of columns to span. |
| `row` | `number` | — | Row index for vertical stacking. |
### Agenda.MonthEvent
A per-cell event in the month grid. Supports drag-to-move across cells.
| Prop | Type | Default | Description |
| ------- | ------------- | ------- | ------------------------- |
| `event` | `AgendaEvent` | — | The event data. Required. |
# AlertDialog
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/alert-dialog
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/alert-dialog.mdx
> Modal dialog for critical confirmations requiring user attention and explicit action
## Import
```tsx
import { AlertDialog } from "@thenamespace/uikit";
```
### Usage
```tsx
"use client";
import {AlertDialog, Button} from "@thenamespace/uikit";
export function Default() {
return (
Delete project permanently?
This will permanently delete My Awesome Project and all of its
data. This action cannot be undone.
);
}
```
### Anatomy
Import the AlertDialog component and access all parts using dot notation.
```tsx
import { AlertDialog, Button } from "@thenamespace/uikit";
export default () => (
{/* Optional: Close button */}
{/* Optional: Status icon */}
);
```
### Statuses
```tsx
"use client";
import {AlertDialog, Button} from "@thenamespace/uikit";
export function Statuses() {
const examples = [
{
actions: {
cancel: "Stay Signed In",
confirm: "Sign Out",
},
body: "You'll need to sign in again to access your account. Any unsaved changes will be lost.",
classNames: "bg-accent-soft text-accent-soft-foreground",
header: "Sign out of your account?",
status: "accent",
trigger: "Sign Out",
},
{
actions: {
cancel: "Not Yet",
confirm: "Mark Complete",
},
body: "This will mark the task as complete and notify all team members. The task will be moved to your completed list.",
classNames: "bg-success-soft text-success-soft-foreground",
header: "Complete this task?",
status: "success",
trigger: "Complete Task",
},
{
actions: {
cancel: "Keep Editing",
confirm: "Discard",
},
body: "You have unsaved changes that will be permanently lost. Are you sure you want to discard them?",
classNames: "bg-warning-soft text-warning-soft-foreground",
header: "Discard unsaved changes?",
status: "warning",
trigger: "Discard Changes",
},
{
actions: {
cancel: "Cancel",
confirm: "Delete Account",
},
body: "This will permanently delete your account and remove all your data from our servers. This action is irreversible.",
classNames: "bg-danger-soft text-danger-soft-foreground",
header: "Delete your account?",
status: "danger",
trigger: "Delete Account",
},
] as const;
return (
{placement === "auto"
? "Automatically positions at the bottom on mobile and center on desktop for optimal user experience."
: `This dialog is positioned at the ${placement} of the viewport. Critical confirmations are typically centered for maximum attention.`}
))}
);
}
```
### Backdrop Variants
```tsx
"use client";
import {AlertDialog, Button} from "@thenamespace/uikit";
export function BackdropVariants() {
const variants = ["opaque", "blur", "transparent"] as const;
return (
{variant === "opaque"
? "An opaque dark backdrop that completely obscures the background, providing maximum focus on the dialog."
: variant === "blur"
? "A blurred backdrop that softly obscures the background while maintaining visual context."
: "A transparent backdrop that keeps the background fully visible, useful for less critical confirmations."}
))}
);
}
```
### Sizes
```tsx
"use client";
import { AlertDialog, Button } from "@thenamespace/uikit";
import { Rocket01Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function Sizes() {
const sizes = ["xs", "sm", "md", "lg", "cover"] as const;
return (
{size === "cover" ? (
<>
This alert dialog uses the cover size
variant. It spans the full screen with margins: 16px on
mobile and 40px on desktop. Maintains rounded corners
and standard padding. Perfect for critical confirmations
that need maximum width while preserving alert dialog
aesthetics.
>
) : (
<>
This alert dialog uses the {size} size
variant. On mobile devices, all sizes adapt to near
full-width for optimal viewing. On desktop, each size
provides a different maximum width to suit various
content needs.
>
)}
))}
);
}
```
### Custom Icon
```tsx
"use client";
import { AlertDialog, Button } from "@thenamespace/uikit";
import { SquareUnlock01Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function CustomIcon() {
return (
Reset your password?
We'll send a password reset link to your email address. You'll
need to create a new password to regain access to your account.
);
}
```
### Custom Backdrop
```tsx
"use client";
import { AlertDialog, Button } from "@thenamespace/uikit";
import { Alert01Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function CustomBackdrop() {
return (
Permanently delete your account?
This action cannot be undone. All your data, settings, and
content will be permanently removed from our servers. The
dramatic red backdrop emphasizes the severity and
irreversibility of this decision.
);
}
```
### Dismiss Behavior
```tsx
"use client";
import { AlertDialog, Button } from "@thenamespace/uikit";
import {
InformationCircleIcon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function DismissBehavior() {
return (
isDismissable
Controls whether the alert dialog can be dismissed by clicking the
overlay backdrop. Alert dialogs typically require explicit action, so
this defaults to false. Set to true for less
critical confirmations.
isDismissable = false
Clicking the backdrop won't close this alert dialog
Try clicking outside this alert dialog on the overlay - it
won't close. You must use the action buttons to dismiss it.
isKeyboardDismissDisabled
Controls whether the ESC key can dismiss the alert dialog. Alert
dialogs typically require explicit action, so this defaults to{" "}
true. When set to false, the ESC key will be
enabled.
isKeyboardDismissDisabled = true
ESC key is disabled
Press ESC - nothing happens. You must use the action buttons
to dismiss this alert dialog.
);
}
```
### Close Methods
```tsx
"use client";
import {AlertDialog, Button} from "@thenamespace/uikit";
export function CloseMethods() {
return (
Using slot="close"
The simplest way to close a dialog. Add slot="close" to any Button component
within the dialog. When clicked, it will automatically close the dialog.
Using slot="close"
Click either button below - both have slot="close" and will close
the dialog automatically.
Using Dialog render props
Access the close method from the Dialog's render props. This gives you full
control over when and how to close the dialog, allowing you to add custom logic before
closing.
{(renderProps) => (
<>
Using Dialog render props
The buttons below use the close method from render props. You
can add validation or other logic before calling{" "}
renderProps.close().
>
)}
);
}
```
### Controlled State
```tsx
"use client";
import {AlertDialog, Button, useOverlayState} from "@thenamespace/uikit";
import React from "react";
export function Controlled() {
const [isOpen, setIsOpen] = React.useState(false);
const state = useOverlayState();
return (
With React.useState()
Control the alert dialog using React's useState{" "}
hook for simple state management. Perfect for basic use cases.
Status:{" "}
{isOpen ? "open" : "closed"}
Controlled with useState()
This alert dialog is controlled by React's useState hook. Pass{" "}
isOpen and onOpenChange props to manage the dialog state
externally.
With useOverlayState()
Use the useOverlayState hook for a cleaner API
with convenient methods like open(), close(), and{" "}
toggle().
Status:{" "}
{state.isOpen ? "open" : "closed"}
Controlled with useOverlayState()
The useOverlayState hook provides dedicated methods for common
operations. No need to manually create callbacks—just use{" "}
state.open(), state.close(), or{" "}
state.toggle().
);
}
```
### Custom Trigger
```tsx
"use client";
import { AlertDialog, Button } from "@thenamespace/uikit";
import { Delete02Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function CustomTrigger() {
return (
Delete Item
Permanently remove this item
Delete this item?
Use AlertDialog.Trigger to create custom trigger
elements beyond standard buttons. This example shows a
card-style trigger with icons and descriptive text.
);
}
```
### Custom Animations
```tsx
"use client";
import { AlertDialog, Button } from "@thenamespace/uikit";
import {
HugeiconsIcon,
type IconSvgElement,
SparklesIcon,
Upload01Icon,
} from "@thenamespace/uikit/icons";
const iconMap: Record = {
"hugeicons:arrow-up-from-line": Upload01Icon,
"hugeicons:sparkles": SparklesIcon,
};
export function CustomAnimations() {
const animations = [
{
classNames: {
backdrop: [
"data-[entering]:duration-400",
"data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]",
].join(" "),
container: [
"data-[entering]:animate-in",
"data-[entering]:fade-in-0",
"data-[entering]:zoom-in-95",
"data-[entering]:duration-400",
"data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]",
"data-[exiting]:animate-out",
"data-[exiting]:fade-out-0",
"data-[exiting]:zoom-out-95",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]",
].join(" "),
},
description:
"Physics-based elastic scaling. Simulates a high-damping spring system with fast transient response and prolonged settling time. Ideal for Alert Dialogs and Modals.",
icon: "hugeicons:sparkles",
name: "Kinematic Scale",
},
{
classNames: {
backdrop: [
"data-[entering]:duration-500",
"data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]",
].join(" "),
container: [
"data-[entering]:animate-in",
"data-[entering]:fade-in-0",
"data-[entering]:slide-in-from-bottom-4",
"data-[entering]:duration-500",
"data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]",
"data-[exiting]:animate-out",
"data-[exiting]:fade-out-0",
"data-[exiting]:slide-out-to-bottom-2",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]",
].join(" "),
},
description:
"Simulates movement through a medium with fluid resistance. Eliminates mechanical linearity for a natural, grounded feel. Perfect for Bottom Sheets or Toasts.",
icon: "hugeicons:arrow-up-from-line",
name: "Fluid Slide",
},
];
return (
Render alert dialogs inside a custom container instead of document.body
Apply transform: translateZ(0) to the
container to create a new stacking context.
{!!portalContainer && (
Custom Portal
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
This alert dialog has custom styling applied via Tailwind
classes
);
}
```
### Customizing the component classes
To customize the AlertDialog component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.alert-dialog__backdrop {
@apply bg-gradient-to-br from-black/60 to-black/80;
}
.alert-dialog__dialog {
@apply rounded-2xl border border-red-500/20 shadow-2xl;
}
.alert-dialog__header {
@apply gap-4;
}
.alert-dialog__icon {
@apply size-16;
}
.alert-dialog__close-trigger {
@apply rounded-full bg-white/10 hover:bg-white/20;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The AlertDialog component uses these CSS classes:
#### Base Classes
- `.alert-dialog__trigger` - Trigger element that opens the alert dialog
- `.alert-dialog__backdrop` - Overlay backdrop behind the dialog
- `.alert-dialog__container` - Positioning wrapper with placement support
- `.alert-dialog__dialog` - Dialog content container
- `.alert-dialog__header` - Header section for icon and title
- `.alert-dialog__heading` - Heading text styles
- `.alert-dialog__body` - Main content area
- `.alert-dialog__footer` - Footer section for actions
- `.alert-dialog__icon` - Icon container with status colors
- `.alert-dialog__close-trigger` - Close button element
#### Backdrop Variants
- `.alert-dialog__backdrop--opaque` - Opaque colored backdrop (default)
- `.alert-dialog__backdrop--blur` - Blurred backdrop with glass effect
- `.alert-dialog__backdrop--transparent` - Transparent backdrop (no overlay)
#### Status Variants (Icon)
- `.alert-dialog__icon--default` - Default gray status
- `.alert-dialog__icon--accent` - Accent blue status
- `.alert-dialog__icon--success` - Success green status
- `.alert-dialog__icon--warning` - Warning orange status
- `.alert-dialog__icon--danger` - Danger red status
### Interactive States
The component supports these interactive states:
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` - Applied to trigger, dialog, and close button
- **Hover**: `:hover` or `[data-hovered="true"]` - Applied to close button on hover
- **Active**: `:active` or `[data-pressed="true"]` - Applied to close button when pressed
- **Entering**: `[data-entering]` - Applied during dialog opening animation
- **Exiting**: `[data-exiting]` - Applied during dialog closing animation
- **Placement**: `[data-placement="*"]` - Applied based on dialog position (auto, top, center, bottom)
## API Reference
### AlertDialog
| Prop | Type | Default | Description |
| ---------- | ----------- | ------- | ------------------------------ |
| `children` | `ReactNode` | - | Trigger and container elements |
### AlertDialog.Trigger
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `children` | `ReactNode` | - | Custom trigger content |
| `className` | `string` | - | CSS classes |
### AlertDialog.Backdrop
| Prop | Type | Default | Description |
| --------------------------- | ------------------------------------- | ---------- | ------------------------- |
| `variant` | `"opaque" \| "blur" \| "transparent"` | `"opaque"` | Backdrop overlay style |
| `isDismissable` | `boolean` | `false` | Close on backdrop click |
| `isKeyboardDismissDisabled` | `boolean` | `true` | Disable ESC key to close |
| `isOpen` | `boolean` | - | Controlled open state |
| `onOpenChange` | `(isOpen: boolean) => void` | - | Open state change handler |
| `className` | `string \| (values) => string` | - | Backdrop CSS classes |
| `UNSTABLE_portalContainer` | `HTMLElement` | - | Custom portal container |
### AlertDialog.Container
| Prop | Type | Default | Description |
| ----------- | ----------------------------------------- | -------- | ------------------------- |
| `placement` | `"auto" \| "center" \| "top" \| "bottom"` | `"auto"` | Dialog position on screen |
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "cover"` | `"md"` | Alert Dialog size variant |
| `className` | `string \| (values) => string` | - | Container CSS classes |
### AlertDialog.Dialog
| Prop | Type | Default | Description |
| ------------------ | ------------------------------------- | --------------- | -------------------------- |
| `children` | `ReactNode \| ({close}) => ReactNode` | - | Content or render function |
| `className` | `string` | - | CSS classes |
| `role` | `string` | `"alertdialog"` | ARIA role |
| `aria-label` | `string` | - | Accessibility label |
| `aria-labelledby` | `string` | - | ID of label element |
| `aria-describedby` | `string` | - | ID of description element |
### AlertDialog.Header
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ------------------------------------------- |
| `children` | `ReactNode` | - | Header content (typically Icon and Heading) |
| `className` | `string` | - | CSS classes |
### AlertDialog.Heading
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ------------ |
| `children` | `ReactNode` | - | Heading text |
| `className` | `string` | - | CSS classes |
### AlertDialog.Body
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ------------ |
| `children` | `ReactNode` | - | Body content |
| `className` | `string` | - | CSS classes |
### AlertDialog.Footer
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ----------------------------------------- |
| `children` | `ReactNode` | - | Footer content (typically action buttons) |
| `className` | `string` | - | CSS classes |
### AlertDialog.Icon
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------- | ---------- | -------------------- |
| `children` | `ReactNode` | - | Custom icon element |
| `status` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"danger"` | Status color variant |
| `className` | `string` | - | CSS classes |
### AlertDialog.CloseTrigger
| Prop | Type | Default | Description |
| ----------- | ------------------------------ | ------- | ------------------- |
| `children` | `ReactNode` | - | Custom close button |
| `className` | `string \| (values) => string` | - | CSS classes |
### useOverlayState Hook
```tsx
import { useOverlayState } from "@thenamespace/uikit";
const state = useOverlayState({
defaultOpen: false,
onOpenChange: (isOpen) => console.log(isOpen),
});
state.isOpen; // Current state
state.open(); // Open dialog
state.close(); // Close dialog
state.toggle(); // Toggle state
state.setOpen(); // Set state directly
```
## Accessibility
Implements [WAI-ARIA AlertDialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/):
- **Focus trap**: Focus locked within alert dialog
- **Keyboard**: `ESC` closes (when enabled), `Tab` cycles elements
- **Screen readers**: Proper ARIA attributes with `role="alertdialog"`
- **Scroll lock**: Body scroll disabled when open
- **Required action**: Defaults to requiring explicit user action (no backdrop/ESC dismiss)
# Alert
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/alert
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/alert.mdx
> Display important messages and notifications to users with status indicators
## Import
```tsx
import { Alert } from "@thenamespace/uikit";
```
### Usage
```tsx
import {Alert, Button, CloseButton, Spinner} from "@thenamespace/uikit";
import React from "react";
export function Basic() {
return (
{/* Default - General information */}
New features available
Check out our latest updates including dark mode support and improved accessibility
features.
{/* Accent - Important information with action */}
Update available
A new version of the application is available. Please refresh to get the latest features
and bug fixes.
{/* Danger - Error with detailed steps */}
Unable to connect to server
We're experiencing connection issues. Please try the following:
Check your internet connection
Refresh the page
Clear your browser cache
{/* Without description */}
Profile updated successfully
{/* Custom indicator - Loading state */}
Processing your request
Please wait while we sync your data. This may take a few moments.
{/* Without close button */}
Scheduled maintenance
Our services will be unavailable on Sunday, March 15th from 2:00 AM to 6:00 AM UTC for
scheduled maintenance.
);
}
```
### Anatomy
Import the Alert component and access all parts using dot notation.
```tsx
import { Alert } from "@thenamespace/uikit";
export default () => (
);
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { Alert } from "@thenamespace/uikit";
function CustomAlert() {
return (
Custom Alert
This alert has custom styling applied
);
}
```
### Customizing the component classes
To customize the Alert component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.alert {
@apply rounded-2xl shadow-lg;
}
.alert__title {
@apply font-bold text-lg;
}
.alert--danger {
@apply border-l-4 border-red-600;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Alert component uses these CSS classes:
#### Base Classes
- `.alert` - Base alert container
- `.alert__indicator` - Icon/indicator container
- `.alert__content` - Content wrapper for title and description
- `.alert__title` - Alert title text
- `.alert__description` - Alert description text
#### Status Variant Classes
- `.alert--default` - Default gray status
- `.alert--accent` - Accent blue status
- `.alert--success` - Success green status
- `.alert--warning` - Warning yellow/orange status
- `.alert--danger` - Danger red status
### Interactive States
The Alert component is primarily informational and doesn't have interactive states on the base component. However, it can contain interactive elements like buttons or close buttons.
## API Reference
### Alert Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------- | ----------- | ------------------------------ |
| `status` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | The visual status of the alert |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The alert content |
### Alert.Indicator Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ----------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Custom indicator icon (defaults to status icon) |
### Alert.Content Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ----------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Content (typically Title and Description) |
### Alert.Title Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The alert title text |
### Alert.Description Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | -------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The alert description text |
# AppLayout
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/app-layout
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/app-layout.mdx
> A scaffold layout that composes a full-height sidebar, a sticky navbar, a main content area, and an optional right-side aside panel.
## Usage
{/* DEMO app-layout-default */}
```tsx
// @ts-nocheck -- Complex demo data intentionally uses heterogeneous shapes.
"use client";
import {
AnalyticsUpIcon,
DashboardSquare01Icon,
HelpCircleIcon,
Logout01Icon,
Notification02Icon,
Search01Icon,
Settings01Icon,
Task01Icon,
UserIcon,
} from "@thenamespace/uikit/icons";
import { HugeiconsIcon } from "@thenamespace/uikit/icons";
import {
Avatar,
Breadcrumbs,
BreadcrumbsItem,
Button,
Chip,
Dropdown,
} from "@thenamespace/uikit";
import { AppLayout, Navbar, Sidebar } from "@thenamespace/uikit";
const navigation = [
{ icon: DashboardSquare01Icon, label: "Dashboard" },
{
icon: AnalyticsUpIcon,
items: ["Overview", "Reports", "Conversions"],
label: "Analytics",
},
{ badge: "New", icon: Task01Icon, label: "Tracker" },
{
icon: Settings01Icon,
items: ["General", "Team", "Notifications"],
label: "Settings",
},
] as const;
function StoryIcon({ icon }: { icon: typeof DashboardSquare01Icon }) {
return ;
}
function Brand({ mobile = false }: { mobile?: boolean }) {
return (
) : undefined
}
>
);
}
export const DemoComplexExample = () => (
);
```
A full-featured layout combining an agent-hub-style sidebar, compact spacing, multiple menu groups, chips, a user dropdown, and a navbar with breadcrumbs and actions.
## Resizable Sidebar and Aside
Opt into user-resizable panels with `sidebarResizable` / `asideResizable`. Both flags render the shell inside a [`Resizable`](/react/components/resizable) group so users can drag the handles to adjust the layout. Sizes are persisted when `resizableAutoSaveId` is set.
`sidebarResizable` requires `sidebarCollapsible="offcanvas"` or `"none"` — the icon-rail mode is not compatible with free-resize yet and falls back to the static layout.
Resizable size props accept both percentages and CSS units. Numbers keep the existing percentage behavior, while strings let you set fixed constraints such as `"220px"` or `"18rem"`. Use `sidebarResizeBehavior="preserve-pixel-size"` or `asideResizeBehavior="preserve-pixel-size"` when that panel should keep its pixel width as the browser window changes size.
```tsx
{children}
```
## Persisted State
When `AppLayout` is **uncontrolled** (no `sidebarOpen` / `asideOpen` props), it automatically writes `sidebar_state` and `aside_state` cookies on every toggle. To restore the state across page loads, read those cookies server-side and pass them as `defaultSidebarOpen` / `defaultAsideOpen`. Because the server renders with the correct state from the start, there is no flash and no hydration mismatch.
### Next.js App Router
```tsx
// app/layout.tsx
import { cookies } from "next/headers";
import { AppLayout, Navbar, Sidebar } from "@thenamespace/uikit";
export default async function Layout({
children,
}: {
children: React.ReactNode;
}) {
const store = await cookies();
const defaultSidebarOpen = store.get("sidebar_state")?.value !== "false";
const defaultAsideOpen = store.get("aside_state")?.value !== "false";
return (
}
navbar={}
>
{children}
);
}
```
### Vite / CSR
For client-only apps you can read the cookies with a library like `js-cookie`:
```tsx
import Cookies from "js-cookie";
const defaultSidebarOpen = Cookies.get("sidebar_state") !== "false";
const defaultAsideOpen = Cookies.get("aside_state") !== "false";
```
> Using `Sidebar.Provider` on its own without `AppLayout`? It writes the same `sidebar_state` cookie automatically. See [Sidebar > Persisted State](/react/components/sidebar#persisted-state).
## Aside Keyboard Shortcut
Pass `asideToggleShortcut` to bind a keyboard combo to `toggleAside()`. The shortcut parser is shared with `toggleShortcut` — same `mod+.`, `shift+?`, `ctrl+alt+k` syntax. Disabled by default to avoid swallowing `Cmd+.` on macOS.
```tsx
}>
{children}
```
## Mobile Aside Sheet
By default the aside is hidden below `1024px`. Set `asideMobile="sheet"` to render it in a full-height `Sheet` instead, toggled by the same `AppLayout.AsideTrigger`. Use the `` slot to provide different mobile content (e.g. a condensed view):
```tsx
}>
{children}
```
If no `MobileAside` slot is provided, the `aside` prop is used inside the sheet.
## Toolbar and Footer
Pass `toolbar` to render a second sticky row below the navbar, and `footer` for a pinned row at the bottom of the body column. Both are optional and tree-shake when unused.
## Mobile Behavior
On viewports below `768px` the desktop sidebar is hidden. Use `AppLayout.MenuToggle` inside the `Navbar.Header` to open a `Sidebar.Mobile` sheet:
```tsx
{/* … */}
}
sidebar={
<>
{/* desktop sidebar */}{/* mobile sheet sidebar */}
>
}
>
{children}
```
- `AppLayout.MenuToggle` is **mobile-only** via CSS — it's hidden on desktop and visible below the `md` breakpoint.
- `Sidebar.Trigger` is hidden on mobile inside an `AppLayout` so the two controls never appear together.
## Client-Side Routing
`AppLayout` forwards its `navigate` prop to both the internal `Sidebar.Provider` **and** any `Navbar` rendered inside it via the `navbar` prop. Pass your router's push function once and every `Sidebar.MenuItem`, `Navbar.Item`, and `Navbar.MenuItem` with an `href` will route through it:
> **Already using a global `RouterProvider`?** If your app is wrapped in React Aria's [`RouterProvider`](https://react-spectrum.adobe.com/react-aria/routing.html), you can omit the `navigate` prop entirely — the layout's `Sidebar.MenuItem`, `Navbar.Item`, and `Navbar.MenuItem` all defer to it automatically. Pass `navigate` only when this layout needs a different router than the global one (an explicit `navigate` always wins). See the [Navbar](/react/components/navbar#option-1--global-routerprovider-recommended) and [Sidebar](/react/components/sidebar#option-1--global-routerprovider-recommended) routing guides.
### Next.js (App Router)
```tsx
"use client";
import { useRouter } from "next/navigation";
import { AppLayout } from "@thenamespace/uikit";
export function DashboardLayout({ children }) {
const router = useRouter();
return (
{children}
);
}
```
> A `Navbar` rendered via the `navbar` prop inherits the layout's `navigate` automatically. If you set a `navigate` prop directly on the `Navbar`, that value wins — useful when the navbar needs a different router (e.g. an external shell app). See the [Navbar routing guide](/react/components/navbar#client-side-routing) for non-layout usage.
### React Router
```tsx
import { useNavigate } from "react-router";
import { AppLayout } from "@thenamespace/uikit";
export function DashboardLayout({ children }) {
const navigate = useNavigate();
return (
{children}
);
}
```
### TanStack Router
```tsx
import { useRouter } from "@tanstack/react-router";
import { AppLayout } from "@thenamespace/uikit";
export function DashboardLayout({ children }) {
const router = useRouter();
return (
router.navigate({ to: href })}
navbar={/* … */}
sidebar={/* … */}
>
{children}
);
}
```
## Controlled State
Both the sidebar and aside panel can be controlled via props on `AppLayout`:
```tsx
const [sidebarOpen, setSidebarOpen] = useState(true);
const [asideOpen, setAsideOpen] = useState(true);
}
navbar={}
sidebar={}
>
{children}
;
```
Inside children, you can reach for [`useSidebar`](/react/components/sidebar#usesidebar) to read or toggle the sidebar state, and [`useAppLayout`](#useapplayout) to read or toggle the aside state.
## Navbar Adaptation
When a `Navbar` is rendered inside `AppLayout` (via the `navbar` prop), it automatically detects the parent layout and:
- Drops its own sticky/floating/static positioning (the `AppLayout` header element owns positioning).
- Clears border, margin, radius, and shadow overrides from `position="floating"`.
- Sets `data-in-app-layout="true"` so you can style it further if needed.
This means you can reuse the same `Navbar` composition standalone or inside an `AppLayout` without changing its markup.
### Resizable Aside
{/* DEMO app-layout-resizable-aside */}
```tsx
// @ts-nocheck -- Complex demo data intentionally uses heterogeneous shapes.
"use client";
import {
AnalyticsUpIcon,
DashboardSquare01Icon,
HelpCircleIcon,
Logout01Icon,
Notification02Icon,
Search01Icon,
Settings01Icon,
Task01Icon,
UserIcon,
} from "@thenamespace/uikit/icons";
import { HugeiconsIcon } from "@thenamespace/uikit/icons";
import {
Avatar,
Breadcrumbs,
BreadcrumbsItem,
Button,
Chip,
Dropdown,
} from "@thenamespace/uikit";
import { AppLayout, Navbar, Sidebar } from "@thenamespace/uikit";
const navigation = [
{ icon: DashboardSquare01Icon, label: "Dashboard" },
{
icon: AnalyticsUpIcon,
items: ["Overview", "Reports", "Conversions"],
label: "Analytics",
},
{ badge: "New", icon: Task01Icon, label: "Tracker" },
{
icon: Settings01Icon,
items: ["General", "Team", "Notifications"],
label: "Settings",
},
] as const;
function StoryIcon({ icon }: { icon: typeof DashboardSquare01Icon }) {
return ;
}
function Brand({ mobile = false }: { mobile?: boolean }) {
return (
);
}
```
### Sizes
```tsx
import {Avatar, Badge} from "@thenamespace/uikit";
const AVATAR_URL = "/assets/avatars/green.jpg";
export function BadgeSizes() {
const sizes = ["sm", "md", "lg"] as const;
return (
{sizes.map((size) => (
JD
5
))}
);
}
```
### Variants
```tsx
import {Avatar, Badge, Separator} from "@thenamespace/uikit";
import React from "react";
const AVATAR_URL = "/assets/avatars/green.jpg";
export function BadgeVariants() {
const variants = ["primary", "secondary", "soft"] as const;
const colors = ["accent", "default", "success", "warning", "danger"] as const;
return (
{variants.map((variant, index) => (
{variant}
{colors.map((color) => (
JD
5
))}
{index < variants.length - 1 && }
))}
);
}
```
### Placements
```tsx
import {Avatar, Badge} from "@thenamespace/uikit";
const AVATAR_URL = "/assets/avatars/green.jpg";
export function BadgePlacements() {
const placements = ["top-right", "top-left", "bottom-right", "bottom-left"] as const;
return (
{placements.map((placement) => (
JD{placement}
))}
);
}
```
### With Content
Badge supports text, numbers, and icons as content. When no children are provided, it renders as a dot indicator.
```tsx
import { Avatar, Badge } from "@thenamespace/uikit";
import { Notification01Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
const AVATAR_URL = "/assets/avatars/green.jpg";
export function BadgeWithContent() {
return (
JD
5
JD
New
JD
99+
JD
);
}
```
### Dot Badge
Empty badges act as status indicators — useful for online/offline states or activity signals.
```tsx
import {Avatar, Badge} from "@thenamespace/uikit";
const AVATAR_URL = "/assets/avatars/green.jpg";
export function BadgeDot() {
const colors = ["accent", "success", "warning", "danger"] as const;
return (
{colors.map((color) => (
JD
))}
);
}
```
## Styling
### Passing Tailwind CSS classes
You can style the root container and individual slots:
```tsx
import { Badge, Avatar } from "@thenamespace/uikit";
function CustomBadge() {
return (
99+
);
}
```
### Customizing the component classes
To customize the Badge component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.badge {
@apply rounded-full text-xs;
}
.badge__label {
@apply font-semibold;
}
.badge--accent {
@apply shadow-sm;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Badge component uses these CSS classes:
#### Base Classes
- `.badge` - Base badge container styles
- `.badge__label` - Label text slot styles
- `.badge-anchor` - Positioning wrapper for the anchored element
#### Color Classes
- `.badge--accent` - Accent color variant
- `.badge--danger` - Danger color variant
- `.badge--default` - Default color variant
- `.badge--success` - Success color variant
- `.badge--warning` - Warning color variant
#### Variant Classes
- `.badge--primary` - Primary variant with filled background
- `.badge--secondary` - Secondary variant with default background
- `.badge--soft` - Soft variant with lighter background
#### Size Classes
- `.badge--sm` - Small size
- `.badge--md` - Medium size (default)
- `.badge--lg` - Large size
#### Placement Classes
- `.badge--top-right` - Position at top-right corner (default)
- `.badge--top-left` - Position at top-left corner
- `.badge--bottom-right` - Position at bottom-right corner
- `.badge--bottom-left` - Position at bottom-left corner
#### Compound Variant Classes
Badges support combining variant and color classes (e.g., `.badge--primary.badge--accent`). The following combinations have default styles defined:
**Primary Variants:**
- `.badge--primary.badge--accent` - Primary accent with filled background
- `.badge--primary.badge--default` - Primary default with filled background
- `.badge--primary.badge--success` - Primary success with filled background
- `.badge--primary.badge--warning` - Primary warning with filled background
- `.badge--primary.badge--danger` - Primary danger with filled background
**Soft Variants:**
- `.badge--soft.badge--accent` - Soft accent with lighter background
- `.badge--soft.badge--default` - Soft default with lighter background
- `.badge--soft.badge--success` - Soft success with lighter background
- `.badge--soft.badge--warning` - Soft warning with lighter background
- `.badge--soft.badge--danger` - Soft danger with lighter background
## API Reference
### Badge Props
| Prop | Type | Default | Description |
| ----------- | -------------------------------------------------------------- | ------------- | -------------------------------------------------------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to display inside the badge (text, number, or icon). When omitted, renders as a dot. |
| `className` | `string` | - | Additional CSS classes for the root element |
| `color` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | Color variant of the badge |
| `variant` | `"primary" \| "secondary" \| "soft"` | `"primary"` | Visual style variant |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the badge |
| `placement` | `"top-right" \| "top-left" \| "bottom-right" \| "bottom-left"` | `"top-right"` | Position of the badge relative to its anchor |
### Badge.Anchor Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | --------------------------------------------------------- |
| `children` | `React.ReactNode` | - | The element to anchor the badge to, plus the Badge itself |
| `className` | `string` | - | Additional CSS classes for the anchor wrapper |
### Badge.Label Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ----------------------------------------- |
| `children` | `React.ReactNode` | - | Label text content |
| `className` | `string` | - | Additional CSS classes for the label slot |
# Bar Chart
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/bar-chart
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/bar-chart.mdx
> A bar chart for comparing categorical data with grouped, stacked, and horizontal layout support.
## Usage
{/* DEMO bar-chart-default */}
```tsx
"use client";
import { BarChart } from "@thenamespace/uikit";
import { Card } from "@thenamespace/uikit/card";
import { ChartTooltip } from "@thenamespace/uikit/chart-tooltip";
import { Chip } from "@thenamespace/uikit/chip";
import { ArrowUp02Icon, Icon } from "@thenamespace/uikit/icons";
const sales = [18, 32, 28, 45, 38, 52, 42, 55, 48, 60, 53, 58].map((value, index) => ({
month:
["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][index] ??
"Unknown",
sales: value,
}));
export const DemoDefaultExample = () => (
Daily SalesUnits sold per month
12.5%
!active || !payload?.length ? null : (
{label}
{payload.map((entry) => (
{entry.name ?? "Sales"}{entry.value} units
))}
)
}
/>
);
```
## Anatomy
Import the BarChart component and access all parts using dot notation.
```tsx
import { BarChart } from "@thenamespace/uikit";
;
```
## Comparison
{/* DEMO bar-chart-comparison */}
```tsx
"use client";
import { BarChart } from "@thenamespace/uikit";
import { Card } from "@thenamespace/uikit/card";
function Legend({
items,
}: {
items: ReadonlyArray<{ color: string; label: string }>;
}) {
return (
);
}
const plans = [
{ enterprise: 12000, pro: 8000, quarter: "Q1", starter: 4000 },
{ enterprise: 15000, pro: 10000, quarter: "Q2", starter: 5000 },
{ enterprise: 18000, pro: 12000, quarter: "Q3", starter: 6000 },
{ enterprise: 22000, pro: 14000, quarter: "Q4", starter: 7000 },
];
export const DemoStackedExample = () => (
Revenue by Plan `${(value / 1000).toFixed(0)}k`}
width={40}
/>
`${Number(value).toLocaleString()}`}
/>
}
/>
);
```
## CSS Classes
### Element Classes
- `.bar-chart` — Root container wrapping `ResponsiveContainer` and the Recharts chart.
### Recharts Theming
The following CSS rules target Recharts internal class names to apply Namespace UIKit design tokens automatically:
- `.bar-chart .recharts-cartesian-axis-tick-value` — Axis tick labels. 10px muted text.
- `.bar-chart .recharts-cartesian-axis-line` — Axis lines. Hidden by default.
- `.bar-chart .recharts-cartesian-axis-tick-line` — Tick lines. Hidden by default.
- `.bar-chart .recharts-cartesian-grid line` — Cartesian grid lines. Muted stroke at 0.15 opacity.
- `.bar-chart .recharts-tooltip-cursor` — Tooltip cursor. Subtle filled rectangle behind the hovered bar.
## API Reference
### BarChart
The root wrapper. Renders a `ResponsiveContainer` + Recharts `BarChart` with Namespace UIKit CSS theming applied automatically.
| Prop | Type | Default | Description |
| ---------- | ------------------------------------------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------- |
| `data` | `Record[]` | — | Chart data — array of objects with numeric/string fields for each series. |
| `height` | `number` | `300` | Chart height in pixels. |
| `width` | ``number \| `${number}%` `` | `"100%"` | Chart width in pixels or percentage string. |
| `layout` | `"horizontal" \| "vertical"` | `"horizontal"` | Bar layout direction. Use `"vertical"` for horizontal bar charts. |
| `margin` | `{ top?: number; right?: number; bottom?: number; left?: number }` | `{ top: 8, right: 8, bottom: 0, left: 0 }` | Recharts margin around the chart area. |
| `children` | `ReactNode` | — | Recharts child components (`BarChart.Bar`, `BarChart.XAxis`, etc.). |
Also supports all native `div` HTML attributes.
### BarChart.Bar
Re-exported Recharts `Bar` component. Follows the [Recharts Bar API](https://recharts.github.io/en-US/api/Bar/).
### BarChart.XAxis
Re-exported Recharts `XAxis` component. Follows the [Recharts XAxis API](https://recharts.github.io/en-US/api/XAxis/).
### BarChart.YAxis
Re-exported Recharts `YAxis` component. Follows the [Recharts YAxis API](https://recharts.github.io/en-US/api/YAxis/).
### BarChart.Grid
Re-exported Recharts `CartesianGrid` component. Follows the [Recharts CartesianGrid API](https://recharts.github.io/en-US/api/CartesianGrid/).
### BarChart.Tooltip
Re-exported Recharts `Tooltip` component. Follows the [Recharts Tooltip API](https://recharts.github.io/en-US/api/Tooltip/). Use with `BarChart.TooltipContent` for styled tooltips.
### BarChart.TooltipContent
Pre-built tooltip renderer for Recharts. Pass as the `content` prop of `BarChart.Tooltip`. See [ChartTooltip](/react/components/chart-tooltip) for full props.
# Breadcrumbs
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/breadcrumbs
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/breadcrumbs.mdx
> Navigation breadcrumbs showing the current page's location within a hierarchy
## Import
```tsx
import { Breadcrumbs } from "@thenamespace/uikit";
```
### Usage
```tsx
"use client";
import {Breadcrumbs} from "@thenamespace/uikit";
export default function BreadcrumbsBasic() {
return (
HomeProductsElectronicsLaptop
);
}
```
### Anatomy
Import the Breadcrumbs component and access all parts using dot notation.
```tsx
import { Breadcrumbs } from "@thenamespace/uikit";
export default () => (
HomeCategoryCurrent Page
);
```
### Navigation Levels
```tsx
"use client";
import {Breadcrumbs} from "@thenamespace/uikit";
export default function BreadcrumbsLevel2() {
return (
HomeCurrent Page
);
}
```
```tsx
"use client";
import {Breadcrumbs} from "@thenamespace/uikit";
export default function BreadcrumbsLevel3() {
return (
HomeCategoryCurrent Page
);
}
```
### Custom Separator
```tsx
"use client";
import {Breadcrumbs} from "@thenamespace/uikit";
export default function BreadcrumbsCustomSeparator() {
return (
}
>
HomeProductsElectronicsLaptop
);
}
```
### Disabled State
```tsx
"use client";
import {Breadcrumbs} from "@thenamespace/uikit";
export default function BreadcrumbsDisabled() {
return (
HomeProductsElectronicsLaptop
);
}
```
### Custom Render Function
```tsx
"use client";
import {Breadcrumbs} from "@thenamespace/uikit";
export function CustomRenderFunction() {
return (
}>
}>
Home
}>
Products
}>
Electronics
}>
Laptop
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { Breadcrumbs } from "@thenamespace/uikit";
function CustomBreadcrumbs() {
return (
Home
Current
);
}
```
### Customizing the component classes
To customize the Breadcrumbs component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.breadcrumbs {
@apply gap-4 text-lg;
}
.breadcrumbs__link {
@apply font-semibold;
}
.breadcrumbs__separator {
@apply text-blue-500;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Breadcrumbs component uses these CSS classes:
#### Base Classes
- `.breadcrumbs` - Base breadcrumbs container
- `.breadcrumbs__item` - Individual breadcrumb item wrapper
- `.breadcrumbs__link` - Breadcrumb link element
- `.breadcrumbs__separator` - Separator icon between items
#### State Classes
- `.breadcrumbs__link[data-current="true"]` - Current page indicator (not a link)
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Current**: `[data-current="true"]` on link (indicates current page)
- **Hover**: Link elements support standard hover states
- **Disabled**: `isDisabled` prop disables all links
## API Reference
### Breadcrumbs Props
| Prop | Type | Default | Description |
| ------------ | ----------------------------------------------------------------- | ------------------ | --------------------------------------------------------------- |
| `separator` | `ReactNode` | chevron-right icon | Custom separator between breadcrumb items |
| `isDisabled` | `boolean` | `false` | Whether all breadcrumb links are disabled |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | The breadcrumb items |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function |
### Breadcrumbs.Item Props
| Prop | Type | Default | Description |
| ----------- | ----------------------------------------------------------------------------- | ------- | --------------------------------------------------------------- |
| `href` | `string` | - | The URL to link to (omit for current page) |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Item content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function |
## Accessibility
Breadcrumbs uses React Aria Components' Breadcrumbs primitive, which provides:
- Proper ARIA attributes for navigation landmarks
- Current page indication via `aria-current="page"`
- Keyboard navigation support
- Screen reader announcements for navigation context
The last breadcrumb item (without `href`) automatically becomes the current page indicator.
# ButtonGroup
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/button-group
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/button-group.mdx
> Group related buttons together with consistent styling and spacing
## Import
```tsx
import { ButtonGroup, Button } from "@thenamespace/uikit";
```
### Usage
```tsx
import {
Button,
ButtonGroup,
Chip,
Description,
Dropdown,
Label,
} from "@thenamespace/uikit";
import {
ArrowDown01Icon,
ArrowLeft01Icon,
ArrowRight01Icon,
GitForkIcon,
MoreHorizontalIcon,
Image01Icon,
PinIcon,
QrCodeIcon,
StarIcon,
TextAlignCenterIcon,
TextAlignJustifyCenterIcon,
TextAlignLeftIcon,
TextAlignRightIcon,
ThumbsDownIcon,
ThumbsUpIcon,
Video01Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function Basic() {
return (
{/* Single button with dropdown */}
All commits from this branch will be added to the base
branch
The 14 commits from this branch will be combined into one
commit in the base branch
The 14 commits from this branch will be rebased and added to
the base branch
{/* Individual buttons */}
{/* Previous/Next Button Group */}
{/* Content Selection Button Group */}
{/* Text Alignment Button Group */}
{/* Icon-Only Alignment Button Group */}
);
}
```
### Anatomy
Import the ButtonGroup component and access all parts using dot notation.
```tsx
import { ButtonGroup, Button } from "@thenamespace/uikit";
export default () => (
);
```
> **ButtonGroup** wraps multiple Button components together, applying consistent styling, spacing, and automatic border radius handling. It uses React Context to pass `size`, `variant`, and `isDisabled` props to all child buttons.
### Variants
```tsx
import {Button, ButtonGroup} from "@thenamespace/uikit";
export function Variants() {
return (
Primary
Secondary
Tertiary
Outline
Ghost
Danger
);
}
```
### Sizes
```tsx
import {Button, ButtonGroup} from "@thenamespace/uikit";
export function Sizes() {
return (
Small
Medium (default)
Large
);
}
```
### Orientation
Use the `orientation` prop to arrange buttons horizontally or vertically.
```tsx
import { Button, ButtonGroup } from "@thenamespace/uikit";
import {
TextAlignCenterIcon,
TextAlignJustifyCenterIcon,
TextAlignLeftIcon,
TextAlignRightIcon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function Orientation() {
return (
Horizontal
Vertical
);
}
```
### With Icons
```tsx
import { Button, ButtonGroup } from "@thenamespace/uikit";
import {
Globe02Icon,
Add01Icon,
Delete02Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function WithIcons() {
return (
With icons
Icon only buttons
);
}
```
### Full Width
```tsx
import { Button, ButtonGroup } from "@thenamespace/uikit";
import {
TextAlignCenterIcon,
TextAlignLeftIcon,
TextAlignRightIcon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function FullWidth() {
return (
);
}
```
### Disabled State
```tsx
import {Button, ButtonGroup} from "@thenamespace/uikit";
export function Disabled() {
return (
All buttons disabled
Group disabled, but one button overrides
);
}
```
### Without Separator
Simply omit the `` component from your buttons.
```tsx
import {Button, ButtonGroup} from "@thenamespace/uikit";
export function WithoutSeparator() {
return (
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { ButtonGroup, Button } from "@thenamespace/uikit";
function CustomButtonGroup() {
return (
);
}
```
### Customizing the component classes
To customize the ButtonGroup component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.button-group {
@apply gap-2 rounded-lg;
}
.button-group__separator {
@apply opacity-25;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ButtonGroup component uses these CSS classes:
#### Base Classes
- `.button-group` - Base button group container
- `.button-group--full-width` - Full width modifier
- `.button-group__separator` - Separator element between buttons
The ButtonGroup component automatically applies border radius to buttons:
- First button gets rounded left/start edge
- Last button gets rounded right/end edge
- Middle buttons have no border radius
- Single button gets full border radius on all edges
Add `` inside each Button (except the first) to show dividers between buttons.
## API Reference
### ButtonGroup Props
| Prop | Type | Default | Description |
| ------------- | --------------------------------------------------------------- | -------------- | --------------------------------------------------------------------------------------- |
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'ghost' \| 'danger'` | - | Visual style variant applied to all buttons in the group |
| `size` | `'sm' \| 'md' \| 'lg'` | - | Size applied to all buttons in the group |
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | The orientation of the button group |
| `fullWidth` | `boolean` | `false` | Whether the button group should take full width of its container |
| `isDisabled` | `boolean` | `false` | Whether all buttons in the group are disabled (can be overridden on individual buttons) |
| `className` | `string` | - | Additional CSS classes |
| `children` | `React.ReactNode` | - | Button components to group together |
### ButtonGroup.Separator Props
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
### Notes
- ButtonGroup uses React Context to pass `size`, `variant`, and `isDisabled` props to all child Button components
- **Only direct child buttons receive the ButtonGroup props** - Buttons nested inside other components (like Modal, Dropdown, etc.) will not inherit the group's props even if they are descendants of the ButtonGroup
- Individual Button components can override the group's `isDisabled` prop by setting `isDisabled={false}`
- The component automatically handles border radius between buttons
- Add `` inside each Button (except the first) to show dividers between buttons
- Buttons in a group have their active/pressed scale transform removed for a more cohesive appearance
# Button
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/button
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/button.mdx
> A clickable button component with multiple variants and states
## Import
```tsx
import { Button } from "@thenamespace/uikit";
```
### Usage
```tsx
"use client";
import {Button} from "@thenamespace/uikit";
export function Basic() {
return ;
}
```
### Variants
```tsx
import {Button} from "@thenamespace/uikit";
export function Variants() {
return (
);
}
```
### With Icons
```tsx
import { Button } from "@thenamespace/uikit";
import {
Mail01Icon,
Globe02Icon,
Add01Icon,
Delete02Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function WithIcons() {
return (
);
}
```
### Icon Only
```tsx
import { Button } from "@thenamespace/uikit";
import {
MoreHorizontalIcon,
Settings01Icon,
Delete02Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function IconOnly() {
return (
);
}
```
### Loading
```tsx
"use client";
import {Button, Spinner} from "@thenamespace/uikit";
import React from "react";
export function Loading() {
return (
);
}
```
### Loading State
```tsx
"use client";
import React, { useState } from "react";
import { Button, Spinner } from "@thenamespace/uikit";
import { Attachment01Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function LoadingState() {
const [isLoading, setLoading] = useState(false);
const handlePress = () => {
setLoading(true);
setTimeout(() => setLoading(false), 2000);
};
return (
);
}
```
### Sizes
```tsx
import {Button} from "@thenamespace/uikit";
export function Sizes() {
return (
);
}
```
### Full Width
```tsx
import { Button } from "@thenamespace/uikit";
import { Add01Icon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function FullWidth() {
return (
);
}
```
### Disabled State
```tsx
import {Button} from "@thenamespace/uikit";
export function Disabled() {
return (
);
}
```
### Social Buttons
```tsx
import { Button } from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
export function Social() {
return (
);
}
```
### Custom Render Function
```tsx
"use client";
import {Button} from "@thenamespace/uikit";
export function CustomRenderFunction() {
return (
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { Button } from "@thenamespace/uikit";
function CustomButton() {
return (
Purple Button
);
}
```
### Customizing the component classes
To customize the Button component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.button {
@apply bg-purple-500 text-white hover:bg-purple-600;
}
.button--icon-only {
@apply rounded-lg bg-blue-500;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### Adding custom variants
You can extend Namespace UIKit components by wrapping them and adding your own custom variants.
```tsx
import type {ButtonProps} from "@thenamespace/uikit";
import type {VariantProps} from "tailwind-variants";
import {Button, buttonVariants} from "@thenamespace/uikit";
import {tv} from "tailwind-variants";
const myButtonVariants = tv({
base: "text-md font-semibold shadow-md text-shadow-lg data-[pending=true]:opacity-40",
defaultVariants: {
radius: "full",
variant: "primary",
},
extend: buttonVariants,
variants: {
radius: {
full: "rounded-full",
lg: "rounded-lg",
md: "rounded-md",
sm: "rounded-sm",
},
size: {
lg: "h-12 px-8",
md: "h-11 px-6",
sm: "h-10 px-4",
xl: "h-13 px-10",
},
variant: {
primary: "text-white dark:bg-white/10 dark:text-white dark:hover:bg-white/15",
},
},
});
type MyButtonVariants = VariantProps;
export type MyButtonProps = Omit &
MyButtonVariants & {className?: string};
function CustomButton({className, radius, variant, ...props}: MyButtonProps) {
return ;
}
export function CustomVariants() {
return Custom Button;
}
```
### Adding Ripple Effect
The Button component supports ripple effects through composition, allowing you to nest ripple components as children. This example uses [m3-ripple](https://github.com/saltyaom/m3-ripple).
```tsx
"use client";
import {Button} from "@thenamespace/uikit";
import {Ripple} from "m3-ripple";
import "m3-ripple/ripple.css";
export function RippleEffect() {
return (
Click me
);
}
```
### CSS Classes
The Button component uses these CSS classes:
#### Base & Size Classes
- `.button` - Base button styles
- `.button--sm` - Small size variant
- `.button--md` - Medium size variant
- `.button--lg` - Large size variant
#### Variant Classes
- `.button--primary`
- `.button--secondary`
- `.button--tertiary`
- `.button--outline`
- `.button--ghost`
- `.button--danger`
#### Modifier Classes
- `.button--icon-only`
- `.button--icon-only.button--sm`
- `.button--icon-only.button--lg`
### Interactive States
The button supports both CSS pseudo-classes and data attributes for flexibility:
- **Hover**: `:hover` or `[data-hovered="true"]`
- **Active/Pressed**: `:active` or `[data-pressed="true"]` (includes scale transform)
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` (shows focus ring)
- **Disabled**: `:disabled` or `[aria-disabled="true"]` (reduced opacity, no pointer events)
- **Pending**: `[data-pending]` (no pointer events during loading)
## API Reference
### Button Props
| Prop | Type | Default | Description |
| ------------ | ---------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------- |
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'outline' \| 'ghost' \| 'danger'` | `'primary'` | Visual style variant |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the button |
| `fullWidth` | `boolean` | `false` | Whether the button should take full width of its container |
| `isDisabled` | `boolean` | `false` | Whether the button is disabled |
| `isPending` | `boolean` | `false` | Whether the button is in a loading state |
| `isIconOnly` | `boolean` | `false` | Whether the button contains only an icon |
| `onPress` | `(e: PressEvent) => void` | - | Handler called when the button is pressed |
| `children` | `React.ReactNode \| (values: ButtonRenderProps) => React.ReactNode` | - | Button content or render prop |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ButtonRenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ---------------- | --------- | ---------------------------------------------- |
| `isPending` | `boolean` | Whether the button is in a loading state |
| `isPressed` | `boolean` | Whether the button is currently pressed |
| `isHovered` | `boolean` | Whether the button is hovered |
| `isFocused` | `boolean` | Whether the button is focused |
| `isFocusVisible` | `boolean` | Whether the button should show focus indicator |
| `isDisabled` | `boolean` | Whether the button is disabled |
# Calendar Year Picker
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/calendar-year-picker
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/calendar-year-picker.mdx
> Year-selection parts shared by Calendar and RangeCalendar.
Import this public entry point directly when composing lower-level UIKit parts.
```tsx
import * as CalendarYearPicker from "@thenamespace/uikit/calendar-year-picker";
```
See [calendar](./calendar) for complete composition examples and API guidance.
This entry point is also re-exported from `@thenamespace/uikit`. Direct imports make the dependency explicit and provide a stable location for advanced customization.
# Calendar
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/calendar
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/calendar.mdx
> Composable date picker with month grid, navigation, and year picker support built on React Aria Calendar
## Import
```tsx
import { Calendar } from "@thenamespace/uikit";
```
### Usage
```tsx
"use client";
import {Calendar} from "@thenamespace/uikit";
export function Basic() {
return (
{(day) => {day}}
{(date) => }
);
}
```
### Anatomy
```tsx
import { Calendar } from "@thenamespace/uikit";
export default () => (
{(day) => {day}}
{(date) => }
);
```
### Year Picker
`Calendar.YearPickerTrigger`, `Calendar.YearPickerGrid`, and their body/cell subcomponents provide an integrated year navigation pattern.
```tsx
"use client";
import {Calendar} from "@thenamespace/uikit";
export function YearPicker() {
return (
{(day) => {day}}
{(date) => }
{({year}) => }
);
}
```
### Default Value
```tsx
"use client";
import {Calendar} from "@thenamespace/uikit";
import {parseDate} from "@internationalized/date";
export function DefaultValue() {
return (
{(day) => {day}}
{(date) => }
);
}
```
### Controlled
Use controlled `value` and `focusedValue` for external state coordination and custom shortcuts.
```tsx
"use client";
import type {CalendarDate} from "@internationalized/date";
import {Button, ButtonGroup, Calendar, Description} from "@thenamespace/uikit";
import {
getLocalTimeZone,
parseDate,
startOfMonth,
startOfWeek,
today,
} from "@internationalized/date";
import {useState} from "react";
import {useLocale} from "react-aria-components";
export function Controlled() {
const [value, setValue] = useState(null);
const [focusedDate, setFocusedDate] = useState(parseDate("2025-12-25"));
const {locale} = useLocale();
return (
);
}
```
### Min and Max Dates
```tsx
"use client";
import {Calendar, Description} from "@thenamespace/uikit";
import {getLocalTimeZone, today} from "@internationalized/date";
export function MinMaxDates() {
const now = today(getLocalTimeZone());
const minDate = now;
const maxDate = now.add({months: 3});
return (
{(day) => {day}}
{(date) => }
Select a date between today and {maxDate.toString()}
);
}
```
### Unavailable Dates
Use `isDateUnavailable` to block dates such as weekends, holidays, or booked slots.
```tsx
"use client";
import type {DateValue} from "@internationalized/date";
import {Calendar, Description} from "@thenamespace/uikit";
import {isWeekend} from "@internationalized/date";
import {useLocale} from "react-aria-components";
export function UnavailableDates() {
const {locale} = useLocale();
const isDateUnavailable = (date: DateValue) => isWeekend(date, locale);
return (
{(day) => {day}}
{(date) => }Weekends are unavailable
);
}
```
### Weeks in Month
Set `weeksInMonth` to a fixed value (for example, `6`) to keep the grid height stable when navigating between months. Use with care in non-Gregorian locales, similar to `firstDayOfWeek`.
```tsx
"use client";
import {Calendar, Description} from "@thenamespace/uikit";
export function WeeksInMonth() {
return (
{(day) => {day}}
{(date) => }
Always shows 6 weeks per month to avoid layout shift when navigating
);
}
```
### Week View
Set `visibleDuration={{ weeks: n }}` to show one or more weeks at a time. Navigation advances by the visible week range. Use `pageBehavior="single"` to move one week at a time when showing multiple weeks.
```tsx
"use client";
import {Calendar, Label, ListBox, Select} from "@thenamespace/uikit";
import {useState} from "react";
const weekOptions = [
{id: "1", name: "1 week"},
{id: "2", name: "2 weeks"},
{id: "3", name: "3 weeks"},
{id: "4", name: "4 weeks"},
{id: "5", name: "5 weeks"},
{id: "6", name: "6 weeks"},
{id: "8", name: "8 weeks"},
] as const;
export function WeekView() {
const [weeks, setWeeks] = useState(1);
return (
{(day) => {day}}
{(date) => }
);
}
```
### Day View
Set `visibleDuration={{ days: n }}` to show a rolling window of consecutive days. Navigation advances by the visible day range. Use `pageBehavior="single"` to move one day at a time when showing multiple days.
```tsx
"use client";
import {Calendar, Label, ListBox, Select} from "@thenamespace/uikit";
import {useState} from "react";
const dayOptions = [
{id: "1", name: "1 day"},
{id: "5", name: "5 days"},
{id: "7", name: "7 days"},
{id: "8", name: "8 days"},
{id: "10", name: "10 days"},
{id: "14", name: "14 days"},
{id: "21", name: "21 days"},
] as const;
export function DayView() {
const [days, setDays] = useState(5);
return (
{(day) => {day}}
{(date) => }
);
}
```
### Multiple Selection
Set `selectionMode="multiple"` to let users select several dates. `value`, `defaultValue`, and `onChange` use an array of dates.
```tsx
"use client";
import type {DateValue} from "@internationalized/date";
import {Calendar, Description} from "@thenamespace/uikit";
import {useState} from "react";
export function MultipleSelection() {
const [value, setValue] = useState([]);
return (
);
}
```
### Disabled
```tsx
"use client";
import {Calendar, Description} from "@thenamespace/uikit";
import {getLocalTimeZone, today} from "@internationalized/date";
export function Disabled() {
return (
{(day) => {day}}
{(date) => }Calendar is disabled
);
}
```
### Read Only
```tsx
"use client";
import {Calendar, Description} from "@thenamespace/uikit";
import {getLocalTimeZone, today} from "@internationalized/date";
export function ReadOnly() {
return (
{(day) => {day}}
{(date) => }Calendar is read-only
);
}
```
### Focused Value
Programmatically control which date is focused using `focusedValue` and `onFocusChange`.
```tsx
"use client";
import type {DateValue} from "@internationalized/date";
import {Button, Calendar, Description} from "@thenamespace/uikit";
import {parseDate} from "@internationalized/date";
import {useState} from "react";
export function FocusedValue() {
const [focusedDate, setFocusedDate] = useState(parseDate("2025-06-15"));
return (
setFocusedDate(parseDate("2025-01-01"))}
>
Go to Jan
setFocusedDate(parseDate("2025-06-15"))}
>
Go to Jun
setFocusedDate(parseDate("2025-12-25"))}
>
Go to Christmas
);
}
```
### Cell Indicators
You can customize `Calendar.Cell` children and use `Calendar.CellIndicator` to display metadata like events.
```tsx
"use client";
import {Calendar} from "@thenamespace/uikit";
import {getLocalTimeZone, isToday} from "@internationalized/date";
const datesWithEvents = [3, 7, 12, 15, 21, 28];
export function WithIndicators() {
return (
{(day) => {day}}
{(date) => (
{({formattedDate}) => (
<>
{formattedDate}
{(isToday(date, getLocalTimeZone()) || datesWithEvents.includes(date.day)) && (
)}
>
)}
)}
);
}
```
### Multiple Months
Render multiple grids with `visibleDuration` and `offset` for booking and planning experiences. Use `Calendar.Heading` with an `offset` (for example, `offset={{ months: 1 }}`) in each column header to label that month.
```tsx
"use client";
import {Calendar} from "@thenamespace/uikit";
export function MultipleMonths() {
return (
{(day) => {day}}
{(date) => }
{(day) => {day}}
{(date) => }
);
}
```
### International Calendars
By default, Calendar displays dates using the calendar system for the user's locale. You can override this by wrapping your Calendar with `I18nProvider` and setting the [Unicode calendar locale extension](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar#adding_a_calendar_in_the_locale_string).
The example below shows the Indian calendar system:
```tsx
"use client";
import {Calendar} from "@thenamespace/uikit";
import {getLocalTimeZone, today} from "@internationalized/date";
import {I18nProvider} from "react-aria-components";
export function InternationalCalendar() {
return (
{(day) => {day}}
{(date) => }
{({year}) => }
);
}
```
**Note:** The `onChange` event always returns a date in the same calendar system as the `value` or `defaultValue` (Gregorian if no value is provided), regardless of the displayed locale. This ensures your application logic works consistently with a single calendar system while still displaying dates in the user's preferred format.
### Custom Navigation Icons
Pass children to `Calendar.NavButton` to replace the default chevron icons.
```tsx
"use client";
import {Calendar} from "@thenamespace/uikit";
export function CustomIcons() {
return (
{(day) => {day}}
{(date) => }
);
}
```
### Real-World Example
```tsx
"use client";
import type {CalendarDate, DateValue} from "@internationalized/date";
import {Button, Calendar} from "@thenamespace/uikit";
import {getLocalTimeZone, isWeekend, today} from "@internationalized/date";
import {useState} from "react";
import {useLocale} from "react-aria-components";
export function BookingCalendar() {
const [selectedDate, setSelectedDate] = useState(null);
const {locale} = useLocale();
const bookedDates = [5, 6, 12, 13, 14, 20];
const isDateUnavailable = (date: DateValue) => {
return isWeekend(date, locale) || bookedDates.includes(date.day);
};
return (
{(["default", "secondary"] as const).map((variant) => (
{variant}
))}
);
```
## CSS Classes
### Base Classes
- `.cell-switch` - Root wrapper (renders as a `label` via Namespace UIKit Switch)
### Element Classes
- `.cell-switch__trigger` - The visible cell row container
- `.cell-switch__trigger--default` - Default variant trigger styling
- `.cell-switch__trigger--secondary` - Secondary variant trigger styling
- `.cell-switch__label` - Leading text label
- `.cell-switch__control` - Switch control wrapper
- `.cell-switch__control--secondary` - Secondary variant control styling
### Variant Classes
- `.cell-switch--secondary` - Secondary variant on the root
## API Reference
### CellSwitch
The root component. Wraps Namespace UIKit [Switch](https://namespace.com/docs/react/components/switch) with cell-style layout. Clicking anywhere in the cell toggles the switch.
| Prop | Type | Default | Description |
| --------- | -------------------------- | ----------- | -------------------- |
| `variant` | `'default' \| 'secondary'` | `'default'` | Visual style variant |
Also supports all [Namespace UIKit Switch](https://namespace.com/docs/react/components/switch) props except `variant`.
### CellSwitch.Trigger
The visible cell row containing the label and switch control. Renders Namespace UIKit `Switch.Content` (a `
# Chain Of Thought
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/chain-of-thought
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/chain-of-thought.mdx
> A collapsible reasoning timeline for assistant thinking, progress, and agent traces.
## Usage
{/* DEMO chain-of-thought-default */}
```tsx
"use client";
import { ChainOfThought } from "@thenamespace/uikit";
export const DemoDefaultExample = () => (
Thought for 4 seconds
Looked up Namespace UIKit chat template patterns for message layout
and composer spacing.
Mapped the template structure to SDK-agnostic compound components.
);
```
Use `ChainOfThought` to show assistant reasoning, progress, tool discovery, or agent traces without coupling to an AI SDK.
## Streaming
{/* DEMO chain-of-thought-streaming */}
```tsx
"use client";
import { ChainOfThought } from "@thenamespace/uikit";
export const DemoStreamingExample = () => (
Thinking...
Breaking the request into presentation-only UIKit components.
);
```
Set `isStreaming` to shimmer the trigger while reasoning is still in progress.
## Agent Trace
{/* DEMO chain-of-thought-agent-trace */}
```tsx
"use client";
import { useState, type ReactNode } from "react";
import { ChainOfThought } from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
function CollapsibleStep({
children,
defaultOpen = true,
icon,
title,
}: {
children: ReactNode;
defaultOpen?: boolean;
icon?: ReactNode;
title: string;
}) {
const [open, setOpen] = useState(defaultOpen);
return (
setOpen((value) => !value)}
>
{icon ? {icon} : null}
{title}
}
>
The user wants a simple login page. This is a straightforward UI
task - I should create a clean login form. Let me generate some
design inspiration first to ensure it looks good, then build the
page.
Read app/layout.tsxRead app/globals.css
Now let me check the existing UI components available:
Scanning 56 files
I have all the components I need. Let me read the button, input,
card, and label components to understand their APIs:
The user wants a simple login page. This is a straightforward UI
task - I should create a clean login form. Let me generate some
design inspiration first to ensure it looks good, then build the
page.
Read app/layout.tsxRead app/globals.css
Now let me check the existing UI components available:
Scanning 56 files
I have all the components I need. Let me read the button, input,
card, and label components to understand their APIs:
);
}
export const DemoCompactExample = () => ;
```
Use the compact variant for dense sidebars.
## Anatomy
```tsx
import { ChatListView } from "@thenamespace/uikit";
Project planningLast assistant reply preview;
```
## CSS Classes
- `.chat-list-view` - Root list
- `.chat-list-view__item` - Thread row
- `.chat-list-view__icon` - Leading icon/avatar
- `.chat-list-view__item-content` - Row text content
- `.chat-list-view__title` - Thread title
- `.chat-list-view__preview` - Thread preview
- `.chat-list-view__meta` - Optional metadata
## API Reference
### ChatListView
Root list container. Supports native `div` props.
### ChatListView\.Item
Thread row. Supports native button/link composition depending on usage.
### ChatListView\.Icon
Leading icon slot.
### ChatListView\.ItemContent
Text content wrapper.
### ChatListView\.Title
Thread title slot.
### ChatListView\.Preview
Thread description or last-message preview slot.
### ChatListView\.Meta
Optional metadata slot, such as date or unread counts.
# Chat Loader
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/chat-loader
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/chat-loader.mdx
> Loading skeletons and typing placeholders for assistant responses.
## Usage
{/* DEMO chat-loader-default */}
```tsx
"use client";
import { ChatLoader } from "@thenamespace/uikit";
export const DemoDefaultExample = () => (
Dots
Pulse
Spinner
);
```
Use `ChatLoader` while an assistant response or thread is loading.
## Anatomy
```tsx
import {ChatLoader} from "@thenamespace/uikit";
```
## CSS Classes
- `.chat-loader` - Root loading layout
- `.chat-loader__avatar` - Avatar placeholder
- `.chat-loader__content` - Loading line group
- `.chat-loader__line` - Individual loading line
## API Reference
### ChatLoader.Dots
Animated dot loader. Supports native `div` props.
### ChatLoader.Pulse
Pulse loader. Supports native `div` props.
### ChatLoader.Spinner
Spinner loader. Supports native `div` props.
### ChatLoader.Skeleton
Chat-message-shaped loading skeleton. Supports native `div` props.
### ChatLoader.SkeletonAvatar, SkeletonBlock, SkeletonLine
Composable skeleton primitives used by `ChatLoader.Skeleton`.
# Chat Message Actions
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/chat-message-actions
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/chat-message-actions.mdx
> Inline action buttons for assistant and user messages.
## Usage
{/* DEMO chat-message-actions-default */}
```tsx
"use client";
import { ChatMessage, ChatMessageActions } from "@thenamespace/uikit";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoDefaultExample = () => (
Assistant responses can expose quick actions beneath the message body.
);
```
Use `ChatMessageActions` for copy, retry, rating, share, or custom message actions.
## Minimal
{/* DEMO chat-message-actions-minimal */}
```tsx
"use client";
import { ChatMessage, ChatMessageActions } from "@thenamespace/uikit";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoMinimalExample = () => (
Minimal action set for compact layouts.
);
```
Use a smaller action set when only one or two actions are needed.
## Custom Icons
{/* DEMO chat-message-actions-custom-icons */}
```tsx
"use client";
import { ChatMessage, ChatMessageActions } from "@thenamespace/uikit";
import { Copy01Icon, HugeiconsIcon, ThumbsUpIcon } from "@thenamespace/uikit/icons";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoCustomIconsExample = () => (
Swap preset icons via the Icon subcomponents.
);
```
Actions are composable, so you can bring your own icon set.
## Anatomy
```tsx
import { ChatMessageActions } from "@thenamespace/uikit";
......;
```
## CSS Classes
- `.chat-message-actions` - Root action row
- `.chat-message-actions__action` - Individual icon button
## API Reference
### ChatMessageActions
Root action group. Supports native `div` props.
### ChatMessageActions.Action
Individual action button. Extends Namespace UIKit `Button` props.
# Chat Message
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/chat-message
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/chat-message.mdx
> Composable user and assistant message layouts for AI chat.
## Usage
{/* DEMO chat-message-default */}
```tsx
"use client";
import { ChatMessage } from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
const Wrapper = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoDefaultExample = () => (
Can you explain how compound components help AI chat UIs stay
SDK-agnostic?
Compound components let you compose message layout explicitly while
keeping state in your app layer.
);
```
Use `ChatMessage` to compose assistant and user turns with avatars, bubbles, media, markdown, actions, and attachments.
## With Markdown
{/* DEMO chat-message-with-markdown */}
```tsx
"use client";
import { ChatMessage, Markdown } from "@thenamespace/uikit";
const Wrapper = ({ children }: { children: React.ReactNode }) => (
{children}
);
const markdown =
'Here is a concise answer with **markdown** support:\n\n```ts\nexport type ChatStatus = "ready" | "streaming";\n```\n\nThe UI stays presentation-only — your SDK owns the message array.';
export const DemoWithMarkdownExample = () => (
Show me markdown inside assistant messages.
{markdown}
);
```
Render assistant responses with rich markdown content.
## Loading
{/* DEMO chat-message-loading */}
```tsx
"use client";
import { ChatLoader, ChatMessage, TextShimmer } from "@thenamespace/uikit";
const Wrapper = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoLoadingExample = () => (
What is the weather in San Francisco?
Thinking...
);
```
Use the loading demo for pending assistant turns.
## Anatomy
```tsx
import {ChatMessage, Markdown} from "@thenamespace/uikit";
{response}Hello
```
## CSS Classes
- `.chat-message--assistant` - Assistant message row
- `.chat-message--user` - User message wrapper
- `.chat-message__avatar` - Avatar slot
- `.chat-message__body` - Assistant body column
- `.chat-message__bubble` - User bubble
- `.chat-message__content` - Message content
- `.chat-message__actions` - Action row
## API Reference
### ChatMessage.Assistant
Assistant message root. Supports native `div` props.
### ChatMessage.User
User message root. Supports native `div` props.
### ChatMessage.Avatar
Avatar slot for assistant messages. Extends Namespace UIKit `Avatar` props.
### ChatMessage.Body
Assistant content column.
### ChatMessage.Bubble
User message bubble.
### ChatMessage.Content
Message text/content slot.
### ChatMessage.Actions
Container for message actions.
# Chat Source
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/chat-source
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/chat-source.mdx
> Citation chips and grouped source lists for AI responses.
## Usage
{/* DEMO chat-source-default */}
```tsx
"use client";
import { ChatMessage, ChatSource } from "@thenamespace/uikit";
const favicon = (url: string) =>
`/assets/favicons/${new URL(url).hostname.replaceAll(".", "-")}.png`;
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoDefaultExample = () => (
Here is an answer backed by a single web source.
);
```
Use `ChatSource` to cite a URL or uploaded document inline with an assistant answer.
## Document
{/* DEMO chat-source-document */}
```tsx
"use client";
import { ChatMessage, ChatSource } from "@thenamespace/uikit";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoDocumentExample = () => (
Referenced an uploaded document.
);
```
Set `sourceType="document"` for uploaded or local files.
## Grouped
{/* DEMO chat-source-grouped */}
```tsx
"use client";
import { ChatMessage, ChatSource, ChatSources } from "@thenamespace/uikit";
const favicon = (url: string) =>
`/assets/favicons/${new URL(url).hostname.replaceAll(".", "-")}.png`;
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoGroupedExample = () => (
Answer synthesized from multiple sources.
3 sources
);
```
Use `ChatSources` to group multiple citations behind a collapsible trigger.
## Stacked Favicons
{/* DEMO chat-source-stacked-favicons */}
```tsx
"use client";
import { ChatMessage, ChatSource, ChatSources } from "@thenamespace/uikit";
const favicon = (url: string) =>
`/assets/favicons/${new URL(url).hostname.replaceAll(".", "-")}.png`;
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoStackedFaviconsExample = () => {
const sources = [
{ href: "https://www.reuters.com", label: "Reuters" },
{ href: "https://nypost.com", label: "New York Post" },
{ href: "https://www.foxsports.com", label: "Fox Sports" },
];
return (
Answer synthesized from multiple sources.
{sources.map((source) => (
))}
Sources
{sources.map((source) => (
))}
);
};
```
For a compact source button, render stacked favicon avatars in the `ChatSources.Trigger`.
## Composable
{/* DEMO chat-source-composable */}
```tsx
"use client";
import { ChatMessage, ChatSource } from "@thenamespace/uikit";
const favicon = (url: string) =>
`/assets/favicons/${new URL(url).hostname.replaceAll(".", "-")}.png`;
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoComposableExample = () => (
React's documentation has a clear explanation of component
composition and state-driven rendering. The source chip below uses custom
trigger content with a fetched favicon.
React docs
react.dev
Official React documentation for learning modern React patterns.
);
```
Use compound parts when you need custom trigger content.
## Anatomy
```tsx
import {ChatSource, ChatSources} from "@thenamespace/uikit";
3 sources
```
## CSS Classes
- `.chat-source` - Source root
- `.chat-source__trigger` - Trigger wrapper
- `.chat-source__trigger-link` - Link or document pill
- `.chat-source__icon` - Favicon image or custom icon
- `.chat-source__icon-fallback` - Initial fallback for URL sources
- `.chat-source__document-icon` - Document source icon
- `.chat-source__preview` - Hover preview popover
- `.chat-sources` - Grouped source disclosure
- `.chat-sources__trigger` - Group trigger
- `.chat-sources__list` - Expanded source list
## API Reference
### ChatSource
| Prop | Type | Default | Description |
| --------------- | --------------------- | ----------------------- | -------------------------------------------------------------------------- |
| `href` | `string` | - | URL source link |
| `title` | `string` | domain | Display title |
| `description` | `string` | - | Enables and populates the hover preview |
| `enablePreview` | `boolean` | auto | Force-enable custom preview content or disable the automatic hover preview |
| `faviconUrl` | `string` | - | Favicon image shown in trigger and preview |
| `sourceType` | `'url' \| 'document'` | inferred | Source type |
| `children` | `ReactNode` | default trigger/preview | Custom source composition |
### ChatSource.Trigger
Renders the source pill trigger. Extends native anchor props for URL sources.
### ChatSource.Icon
Renders a custom icon or favicon.
| Prop | Type | Default | Description |
| ------------ | ----------- | ---------------- | ------------------- |
| `faviconUrl` | `string` | - | Favicon image URL |
| `children` | `ReactNode` | fallback initial | Custom icon element |
### ChatSource.Title
Renders the source title.
### ChatSource.Preview
Renders the hover preview content for URL sources with title or description. If you provide a
custom preview without root `title` or `description`, set `enablePreview` on `ChatSource` so the
required hover-card wrapper is mounted.
### ChatSources
Grouped source disclosure. Extends Namespace UIKit `Disclosure` props.
### ChatSources.Trigger
Renders the grouped source trigger.
### ChatSources.Content
Renders the expanded grouped source content.
### ChatSources.List
Renders the flex-wrapped source list.
# Chat Tool
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/chat-tool
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/chat-tool.mdx
> Collapsible tool-call cards for inputs, outputs, errors, approvals, and grouped tool activity.
## Usage
{/* DEMO chat-tool-default */}
```tsx
"use client";
import { ChatMessage, ChatTool } from "@thenamespace/uikit";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoDefaultExample = () => (
Completed tool call with JSON args and result.
);
```
Use `ChatTool` to show tool calls emitted by an agent or assistant.
## Streaming
{/* DEMO chat-tool-streaming */}
```tsx
"use client";
import { ChatMessage, ChatTool } from "@thenamespace/uikit";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoStreamingExample = () => (
);
```
Use streaming state while tool input is still being generated.
## Error
Use error state for failed tool calls.
## Approval
{/* DEMO chat-tool-approval */}
```tsx
"use client";
import { ChatMessage, ChatTool } from "@thenamespace/uikit";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoApprovalExample = () => (
{}}
onReject={() => {}}
/>
);
```
Use approval state when a tool requires user confirmation.
## Grouped
{/* DEMO chat-tool-grouped */}
```tsx
"use client";
import { ChatMessage, ChatTool, ChatToolGroup } from "@thenamespace/uikit";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoGroupedExample = () => (
2 tool calls
{["searchDocs", "fetchPage"].map((toolName) => (
))}
);
```
Use `ChatToolGroup` to group consecutive tool calls.
## Composable
{/* DEMO chat-tool-composable */}
```tsx
"use client";
import { ChatMessage, ChatTool } from "@thenamespace/uikit";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoComposableExample = () => (
Used tool: getWeather
);
```
Tool cards expose slots for custom trigger and content layouts.
## Anatomy
```tsx
import {ChatTool, ChatToolGroup} from "@thenamespace/uikit";
Used tool: searchDocs
```
### Error State
{/* DEMO chat-tool-error-state */}
```tsx
"use client";
import { ChatMessage, ChatTool } from "@thenamespace/uikit";
const Assistant = ({ children }: { children: React.ReactNode }) => (
{children}
);
export const DemoErrorStateExample = () => (
);
```
## CSS Classes
- `.chat-tool` - Tool card root
- `.chat-tool__trigger` - Collapsible trigger
- `.chat-tool__content` - Disclosure content panel
- `.chat-tool__args` - Tool input content
- `.chat-tool__result` - Tool output content
- `.chat-tool__error` - Tool error content
- `.chat-tool-group` - Grouped tool root
## API Reference
### ChatTool
| Prop | Type | Default | Description |
| ----------------- | ----------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------- |
| `toolName` | `string` | - | Tool display name |
| `state` | `'input-streaming' \| 'input-available' \| 'output-available' \| 'output-error' \| 'requires-action'` | - | Tool state |
| `triggerPrefix` | `ReactNode` | - | Optional label rendered before `toolName` in preset mode |
| `input` | `unknown` | - | Tool input rendered as JSON in preset mode |
| `output` | `unknown` | - | Tool output rendered as JSON in preset mode |
| `argsText` | `string` | - | Preformatted tool input text, useful while streaming partial JSON |
| `errorText` | `string` | - | Error details rendered for `output-error` state |
| `onApprove` | `() => void` | - | Called by the preset approval action in `requires-action` state |
| `onReject` | `() => void` | - | Called by the preset rejection action in `requires-action` state |
| `defaultExpanded` | `boolean` | - | Open by default |
| `isExpanded` | `boolean` | - | Controlled expanded state |
### ChatTool.Trigger
Renders the collapsible tool trigger.
### ChatTool.Content
Renders the expanded tool body.
### ChatTool.Args, Result, Error, Approval
Semantic slots for tool input, output, error details, and approval controls.
### ChatToolGroup
Groups multiple `ChatTool` items. Extends Namespace UIKit `Disclosure` props.
# Checkbox Button Group
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/checkbox-button-group
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/checkbox-button-group.mdx
> A multi-selection button group with card-style checkboxes, icons, and custom indicators.
## Usage
{/* DEMO checkbox-button-group-default */}
```tsx
"use client";
import { CheckboxButtonGroup } from "@thenamespace/uikit";
import { Description } from "@thenamespace/uikit/description";
import { Label } from "@thenamespace/uikit/label";
const features = [
{
description: "Real-time threat detection and prevention",
value: "security",
},
{
description: "Cloud-based storage with automatic backups",
value: "storage",
},
{
description: "Usage reports and performance dashboards",
value: "analytics",
},
];
function FeatureContent({
description,
value,
}: {
description: string;
value: string;
}) {
return (
{description}
);
}
export const DemoDefaultExample = () => (
Choose all that apply to your project
{features.map((feature) => (
))}
);
```
## Anatomy
Import the CheckboxButtonGroup component and access all parts using dot notation.
```tsx
import { CheckboxButtonGroup } from "@thenamespace/uikit";
;
```
## Controlled
{/* DEMO checkbox-button-group-controlled */}
```tsx
"use client";
import { useState } from "react";
import { CheckboxButtonGroup } from "@thenamespace/uikit";
import { Description } from "@thenamespace/uikit/description";
import { Label } from "@thenamespace/uikit/label";
import { NumberValue } from "@thenamespace/uikit/number-value";
const addons = [
{
description: "Automated daily backups",
price: 5,
title: "Backups",
value: "backups",
},
{
description: "24/7 monitoring and alerts",
price: 12,
title: "Monitoring",
value: "monitoring",
},
{
description: "Priority email and chat support",
price: 8,
title: "Support",
value: "support",
},
];
function AddonContent({ addon }: { addon: (typeof addons)[number] }) {
return (
);
}
```
### Controlled
```tsx
"use client";
import {Checkbox, CheckboxGroup, Label} from "@thenamespace/uikit";
import {useState} from "react";
export function Controlled() {
const [selected, setSelected] = useState(["coding", "design"]);
return (
Coding
Design
Writing
);
}
```
### Validation
```tsx
"use client";
import {Button, Checkbox, CheckboxGroup, FieldError, Form, Label} from "@thenamespace/uikit";
export function Validation() {
return (
);
}
```
### Disabled
```tsx
import {Checkbox, CheckboxGroup, Description, Label} from "@thenamespace/uikit";
export function Disabled() {
return (
Feature selection is temporarily disabled
Feature 1
This feature is coming soon
Feature 2
This feature is coming soon
);
}
```
### Features and Add-ons Example
```tsx
import {
Checkbox,
CheckboxGroup,
Description,
Label,
} from "@thenamespace/uikit";
import {
Comment01Icon,
HugeiconsIcon,
Mail01Icon,
Notification01Icon,
} from "@thenamespace/uikit/icons";
import clsx from "clsx";
export function FeaturesAndAddOns() {
const addOns = [
{
description: "Receive updates via email",
icon: Mail01Icon,
title: "Email Notifications",
value: "email",
},
{
description: "Get instant SMS notifications",
icon: Comment01Icon,
title: "SMS Alerts",
value: "sms",
},
{
description: "Browser and mobile push alerts",
icon: Notification01Icon,
title: "Push Notifications",
value: "push",
},
];
return (
Choose how you want to receive updates
{addOns.map((addon) => (
{addon.title}{addon.description}
))}
);
}
```
### Custom Render Function
```tsx
"use client";
import {Checkbox, CheckboxGroup, Description, Label} from "@thenamespace/uikit";
export function CustomRenderFunction() {
return (
}>
Choose all that apply
Coding
Love building software
Design
Enjoy creating beautiful interfaces
Writing
Passionate about content creation
);
}
```
## Styling
### Passing Tailwind CSS classes
You can customize the CheckboxGroup component:
```tsx
import { CheckboxGroup, Checkbox, Label } from "@thenamespace/uikit";
function CustomCheckboxGroup() {
return (
Option 1
);
}
```
### Customizing the component classes
To customize the CheckboxGroup component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.checkbox-group {
@apply flex flex-col gap-2;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The CheckboxGroup component uses these CSS classes:
- `.checkbox-group` - Base checkbox group container
## API Reference
### CheckboxGroup Props
Inherits from [React Aria CheckboxGroup](https://react-spectrum.adobe.com/react-aria/CheckboxGroup.html).
| Prop | Type | Default | Description |
| -------------- | -------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------- |
| `value` | `string[]` | - | The current selected values (controlled) |
| `defaultValue` | `string[]` | - | The default selected values (uncontrolled) |
| `onChange` | `(value: string[]) => void` | - | Handler called when the selected values change |
| `isDisabled` | `boolean` | `false` | Whether the checkbox group is disabled |
| `isRequired` | `boolean` | `false` | Whether the checkbox group is required |
| `isReadOnly` | `boolean` | `false` | Whether the checkbox group is read only |
| `isInvalid` | `boolean` | `false` | Whether the checkbox group is in an invalid state |
| `name` | `string` | - | The name of the checkbox group, used when submitting an HTML form |
| `children` | `React.ReactNode \| (values: CheckboxGroupRenderProps) => React.ReactNode` | - | Checkbox group content or render prop |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### CheckboxGroupRenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ------------ | ---------- | ------------------------------------------------- |
| `value` | `string[]` | The currently selected values |
| `isDisabled` | `boolean` | Whether the checkbox group is disabled |
| `isReadOnly` | `boolean` | Whether the checkbox group is read only |
| `isInvalid` | `boolean` | Whether the checkbox group is in an invalid state |
| `isRequired` | `boolean` | Whether the checkbox group is required |
# Checkbox
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/checkbox
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/checkbox.mdx
> Checkboxes allow users to select multiple items from a list of individual items, or to mark one individual item as selected.
## Import
```tsx
import { Checkbox } from "@thenamespace/uikit";
```
### Usage
```tsx
import {Checkbox} from "@thenamespace/uikit";
export function Basic() {
return (
Accept terms and conditions
);
}
```
### Anatomy
Import the Checkbox component and access all parts using dot notation.
```tsx
import { Checkbox, Description, FieldError } from "@thenamespace/uikit";
export default () => (
Label {/* plain text — the clickable label + accessible name */}
{/* Optional — field-level help text */}
{/* Optional — validation message */}
);
```
### Disabled
```tsx
import {Checkbox, Description} from "@thenamespace/uikit";
export function Disabled() {
return (
Premium Feature
This feature is coming soon
);
}
```
### Default Selected
```tsx
import {Checkbox} from "@thenamespace/uikit";
export function DefaultSelected() {
return (
Enable email notifications
);
}
```
### Controlled
```tsx
"use client";
import {Checkbox} from "@thenamespace/uikit";
import {useState} from "react";
export function Controlled() {
const [isSelected, setIsSelected] = useState(true);
return (
Email notifications
Status: {isSelected ? "Enabled" : "Disabled"}
);
}
```
### Indeterminate
```tsx
"use client";
import {Checkbox, Description} from "@thenamespace/uikit";
import {useState} from "react";
export function Indeterminate() {
const [isIndeterminate, setIsIndeterminate] = useState(true);
const [isSelected, setIsSelected] = useState(false);
return (
{
setIsSelected(selected);
setIsIndeterminate(false);
}}
>
Select all
Shows indeterminate state (dash icon)
);
}
```
### External Label
```tsx
import {Checkbox, Label} from "@thenamespace/uikit";
export function ExternalLabel() {
return (
);
}
```
### With Description
```tsx
import {Checkbox, Description} from "@thenamespace/uikit";
export function WithDescription() {
return (
Email notifications
Get notified when someone mentions you in a comment
);
}
```
### Render Props
```tsx
"use client";
import {Checkbox, Description} from "@thenamespace/uikit";
export function RenderProps() {
return (
{({isSelected}) => (
<>
{isSelected ? "Terms accepted" : "Accept terms"}
{isSelected ? "Thank you for accepting" : "Please read and accept the terms"}
>
)}
);
}
```
### Form Integration
```tsx
"use client";
import {Button, Checkbox} from "@thenamespace/uikit";
import React from "react";
export function Form() {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
alert(
`Form submitted with:\n${Array.from(formData.entries())
.map(([key, value]) => `${key}: ${value}`)
.join("\n")}`,
);
};
return (
);
}
```
### Invalid
```tsx
import {Checkbox, FieldError} from "@thenamespace/uikit";
export function Invalid() {
return (
I agree to the terms
You must accept the terms to continue
);
}
```
### Custom Indicator
```tsx
"use client";
import {Checkbox} from "@thenamespace/uikit";
export function CustomIndicator() {
return (
);
}
```
### Full Rounded
```tsx
import {Checkbox, Label} from "@thenamespace/uikit";
export function FullRounded() {
return (
Small size
Default size
Large size
Extra large size
);
}
```
### Variants
The Checkbox component supports two visual variants:
- **`primary`** (default) - Standard styling with default background, suitable for most use cases
- **`secondary`** - Lower emphasis variant, suitable for use in Surface components
```tsx
import {Checkbox, Description} from "@thenamespace/uikit";
export function Variants() {
return (
Primary variant
Primary checkbox
Standard styling with default background
Secondary variant
Secondary checkbox
Lower emphasis variant for use in surfaces
);
}
```
### Custom Render Function
```tsx
"use client";
import {Checkbox, Label} from "@thenamespace/uikit";
export function CustomRenderFunction() {
return (
}>
);
}
```
## Styling
### Passing Tailwind CSS classes
You can customize individual Checkbox components:
```tsx
import { Checkbox } from "@thenamespace/uikit";
function CustomCheckbox() {
return (
Custom Checkbox
);
}
```
### Customizing the component classes
To customize the Checkbox component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.checkbox {
@apply inline-flex gap-3 items-center;
}
.checkbox__control {
@apply size-5 border-2 border-gray-400 rounded data-[selected=true]:bg-blue-500 data-[selected=true]:border-blue-500;
/* Animated background indicator */
&::before {
@apply bg-accent pointer-events-none absolute inset-0 z-0 origin-center scale-50 rounded-md opacity-0 content-[''];
transition:
scale 200ms linear,
opacity 200ms linear,
background-color 200ms ease-out;
}
/* Show indicator when selected */
&[data-selected="true"]::before {
@apply scale-100 opacity-100;
}
}
.checkbox__indicator {
@apply text-white;
}
.checkbox__content {
@apply items-center gap-3;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Checkbox component uses these CSS classes:
- `.checkbox` - Base checkbox container (the field)
- `.checkbox__content` - Clickable label wrapping the control and label text
- `.checkbox__control` - Checkbox control box
- `.checkbox__indicator` - Checkbox checkmark indicator
### Interactive States
The checkbox supports both CSS pseudo-classes and data attributes for flexibility:
- **Selected**: `[data-selected="true"]` or `[aria-checked="true"]` (shows checkmark and background color change)
- **Indeterminate**: `[data-indeterminate="true"]` (shows indeterminate state with dash)
- **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` (shows error state with danger colors)
- **Hover**: `:hover` or `[data-hovered="true"]` on `Checkbox.Control` (button)
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on the button (shows focus ring on control)
- **Disabled**: `[data-disabled="true"]` on the field (reduced opacity, including help text)
- **Pressed**: `:active` or `[data-pressed="true"]`
## API Reference
### Checkbox Props
Inherits from [React Aria CheckboxField](https://react-spectrum.adobe.com/react-aria/Checkbox.html).
| Prop | Type | Default | Description |
| -------------------- | -------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `isSelected` | `boolean` | `false` | Whether the checkbox is checked |
| `defaultSelected` | `boolean` | `false` | Whether the checkbox is checked by default (uncontrolled) |
| `isIndeterminate` | `boolean` | `false` | Whether the checkbox is in an indeterminate state |
| `isDisabled` | `boolean` | `false` | Whether the checkbox is disabled |
| `isInvalid` | `boolean` | `false` | Whether the checkbox is invalid |
| `isReadOnly` | `boolean` | `false` | Whether the checkbox is read only |
| `isRequired` | `boolean` | `false` | Whether the checkbox must be selected |
| `validate` | `(value: boolean) => ValidationError \| true \| null \| undefined` | - | Custom validation function |
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA |
| `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the component. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. |
| `name` | `string` | - | The name of the input element, used when submitting an HTML form |
| `value` | `string` | - | The value of the input element, used when submitting an HTML form |
| `onChange` | `(isSelected: boolean) => void` | - | Handler called when the checkbox value changes |
| `children` | `React.ReactNode \| (values: CheckboxFieldRenderProps) => React.ReactNode` | - | Checkbox content or field render prop |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Checkbox.Content Props
The clickable `
# Chip
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/chip
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/chip.mdx
> Small informational badges for displaying labels, statuses, and categories
## Import
```tsx
import { Chip } from "@thenamespace/uikit";
```
## Anatomy
Import the Chip component and access all parts using dot notation.
> Plain-text children are automatically wrapped in ``.
```tsx
Label text
```
### Usage
```tsx
import {Chip} from "@thenamespace/uikit";
export function ChipBasic() {
return (
DefaultAccentSuccessWarningDanger
);
}
```
### Variants
```tsx
import React from "react";
import { Chip, Separator } from "@thenamespace/uikit";
import { CircleIcon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function ChipVariants() {
const sizes = ["lg", "md", "sm"] as const;
const variants = ["primary", "secondary", "tertiary", "soft"] as const;
const colors = ["accent", "default", "success", "warning", "danger"] as const;
return (
{sizes.map((size, index) => (
{size}
{/* Color labels header */}
{colors.map((color) => (
{color}
))}
{variants.map((variant) => (
{variant}
{colors.map((color) => (
Label
))}
))}
{index < sizes.length - 1 && }
))}
);
}
```
### With Icons
```tsx
import { Chip } from "@thenamespace/uikit";
import {
ArrowDown01Icon,
CheckmarkCircle02Icon,
CircleIcon,
Clock01Icon,
Cancel01Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function ChipWithIcon() {
return (
InformationCompletedPendingFailedLabel
);
}
```
### Statuses
```tsx
import { Chip } from "@thenamespace/uikit";
import {
UnavailableIcon,
CheckmarkSquare02Icon,
CircleIcon,
InformationCircleIcon,
Alert01Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function ChipStatuses() {
return (
DefaultActivePendingInactive
New FeatureAvailableBetaDeprecated
);
}
```
## Styling
### Passing Tailwind CSS classes
You can style the root container and individual slots:
```tsx
import { Chip } from "@thenamespace/uikit";
function CustomChip() {
return (
Custom Styled
);
}
```
### Customizing the component classes
To customize the Chip component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.chip {
@apply rounded-full text-xs;
}
.chip__label {
@apply font-medium;
}
.chip--accent {
@apply border-accent/20;
}
.chip--accent .chip__label {
@apply text-accent;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The Chip component uses these CSS classes:
#### Base Classes
- `.chip` - Base chip container styles
- `.chip__label` - Label text slot styles
#### Color Classes
- `.chip--accent` - Accent color variant
- `.chip--danger` - Danger color variant
- `.chip--default` - Default color variant
- `.chip--success` - Success color variant
- `.chip--warning` - Warning color variant
#### Variant Classes
- `.chip--primary` - Primary variant with filled background
- `.chip--secondary` - Secondary variant with border
- `.chip--tertiary` - Tertiary variant with transparent background
- `.chip--soft` - Soft variant with lighter background
#### Size Classes
- `.chip--sm` - Small size
- `.chip--md` - Medium size (default)
- `.chip--lg` - Large size
#### Compound Variant Classes
Chips support combining variant and color classes (e.g., `.chip--secondary.chip--accent`). The following combinations have default styles defined:
**Primary Variants:**
- `.chip--primary.chip--accent` - Primary accent combination with filled background
- `.chip--primary.chip--success` - Primary success combination with filled background
- `.chip--primary.chip--warning` - Primary warning combination with filled background
- `.chip--primary.chip--danger` - Primary danger combination with filled background
**Soft Variants:**
- `.chip--accent.chip--soft` - Soft accent combination with lighter background
- `.chip--success.chip--soft` - Soft success combination with lighter background
- `.chip--warning.chip--soft` - Soft warning combination with lighter background
- `.chip--danger.chip--soft` - Soft danger combination with lighter background
**Note:** You can apply custom styles to any variant-color combination (e.g., `.chip--secondary.chip--accent`, `.chip--tertiary.chip--success`) using the `@layer components` directive in your CSS.
## API Reference
### Chip Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------- | ------------- | ------------------------------------------- |
| `children` | `React.ReactNode` | - | Content to display inside the chip |
| `className` | `string` | - | Additional CSS classes for the root element |
| `color` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | Color variant of the chip |
| `variant` | `"primary" \| "secondary" \| "tertiary" \| "soft"` | `"secondary"` | Visual style variant |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the chip |
### Chip.Label Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | ------- | ----------------------------------------- |
| `children` | `React.ReactNode` | - | Label text content |
| `className` | `string` | - | Additional CSS classes for the label slot |
# CloseButton
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/close-button
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/close-button.mdx
> Button component for closing dialogs, modals, or dismissing content
## Import
```tsx
import { CloseButton } from "@thenamespace/uikit";
```
### Usage
```tsx
import {CloseButton} from "@thenamespace/uikit";
export function Default() {
return ;
}
```
### With Custom Icon
```tsx
import { CloseButton } from "@thenamespace/uikit";
import {
CancelCircleIcon,
Cancel01Icon,
HugeiconsIcon,
} from "@thenamespace/uikit/icons";
export function WithCustomIcon() {
return (
Custom Icon
Alternative Icon
);
}
```
### Interactive
```tsx
"use client";
import {CloseButton} from "@thenamespace/uikit";
import {useState} from "react";
export function Interactive() {
const [count, setCount] = useState(0);
return (
setCount(count + 1)}
/>
Clicked: {count} times
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { CloseButton } from "@thenamespace/uikit";
function CustomCloseButton() {
return (
Close
);
}
```
### Customizing the component classes
To customize the CloseButton component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.close-button {
@apply bg-red-100 text-red-800 hover:bg-red-200;
}
.close-button--custom {
@apply rounded-full border-2 border-red-300;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The CloseButton component uses these CSS classes:
#### Base Classes
- `.close-button` - Base component styles
#### Variant Classes
- `.close-button--default` - Default variant
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Hover**: `:hover` or `[data-hovered="true"]`
- **Active/Pressed**: `:active` or `[data-pressed="true"]`
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]`
- **Disabled**: `:disabled` or `[aria-disabled="true"]`
## API Reference
### CloseButton Props
| Prop | Type | Default | Description |
| ------------ | ----------------------- | --------------- | ------------------------------------------- |
| `variant` | `"default"` | `"default"` | Visual variant of the button |
| `children` | `ReactNode \| function` | `` | Content to display (defaults to close icon) |
| `onPress` | `() => void` | - | Handler called when the button is pressed |
| `isDisabled` | `boolean` | `false` | Whether the button is disabled |
### React Aria Button Props
CloseButton extends all React Aria Button props. Common props include:
| Prop | Type | Description |
| ------------------ | -------- | --------------------------------------- |
| `aria-label` | `string` | Accessible label for screen readers |
| `aria-labelledby` | `string` | ID of element that labels the button |
| `aria-describedby` | `string` | ID of element that describes the button |
### RenderProps
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
| ------------ | --------- | ------------------------------ |
| `isHovered` | `boolean` | Whether the button is hovered |
| `isPressed` | `boolean` | Whether the button is pressed |
| `isFocused` | `boolean` | Whether the button is focused |
| `isDisabled` | `boolean` | Whether the button is disabled |
# Code Block
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/code-block
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/code-block.mdx
> Syntax-highlighted code blocks with language labels and copy actions for AI markdown.
## Usage
{/* DEMO code-block-default */}
```tsx
"use client";
import { CodeBlock } from "@thenamespace/uikit";
const code = `function greet(name: string) {
return \`Hello, \${name}!\`;
}
console.log(greet("Namespace UIKit"));`;
export const DemoDefaultExample = () => (
typescript
);
```
Use `CodeBlock` for fenced code output, tool snippets, and AI-generated examples.
## Anatomy
```tsx
import { CodeBlock } from "@thenamespace/uikit";
typescript;
```
## CSS Classes
- `.code-block` - Root code block surface
- `.code-block__header` - Header row
- `.code-block__code` - Code scroll region
- `.code-block__copy-button` - Copy/check icon button
## API Reference
### CodeBlock
Root container. Also supports native `div` props.
### CodeBlock.Header
Header slot for language labels and actions. Also supports native `div` props.
### CodeBlock.Code
| Prop | Type | Default | Description |
| ---------- | -------- | ---------------- | ----------------- |
| `code` | `string` | - | Code to render |
| `language` | `string` | `'plaintext'` | Shiki language id |
| `theme` | `string` | `'github-light'` | Shiki theme |
Also supports native `div` props.
### CodeBlock.CopyButton
| Prop | Type | Default | Description |
| ------------ | -------- | ------------- | ------------------------ |
| `code` | `string` | - | Code copied to clipboard |
| `aria-label` | `string` | `'Copy code'` | Accessible label |
| `className` | `string` | - | Additional class |
# ColorArea
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/color-area
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/color-area.mdx
> A 2D color picker that allows users to select colors from a gradient area
## Import
```tsx
import { ColorArea } from "@thenamespace/uikit";
```
### Usage
```tsx
import {ColorArea} from "@thenamespace/uikit";
export function ColorAreaBasic() {
return (
);
}
```
### Anatomy
```tsx
import { ColorArea } from "@thenamespace/uikit";
export default () => (
);
```
### With Dots
```tsx
import {ColorArea} from "@thenamespace/uikit";
export function ColorAreaWithDots() {
return (
);
}
```
### Controlled
```tsx
"use client";
import type {Color} from "@thenamespace/uikit";
import {ColorArea, ColorSwatch, parseColor} from "@thenamespace/uikit";
import {useState} from "react";
export function ColorAreaControlled() {
const [color, setColor] = useState(parseColor("#9B80FF"));
return (
Current color:{" "}
{color ? color.toString("hex") : "(empty)"}
);
}
```
### Color Space & Channels
Use `colorSpace` to set the color space (RGB, HSL, HSB) and `xChannel`/`yChannel` props to customize which color channels are displayed on each axis.
```tsx
"use client";
import type {ColorSpace, Key} from "@thenamespace/uikit";
import {ColorArea, Label, ListBox, Select, parseColor} from "@thenamespace/uikit";
import {useState} from "react";
type ColorChannel = "hue" | "saturation" | "brightness" | "lightness" | "red" | "green" | "blue";
interface ChannelOption {
id: ColorChannel;
name: string;
}
const colorSpaces: Array<{id: ColorSpace; name: string}> = [
{id: "rgb", name: "RGB"},
{id: "hsl", name: "HSL"},
{id: "hsb", name: "HSB"},
];
const channelsBySpace: Record = {
hsb: [
{id: "hue", name: "Hue"},
{id: "saturation", name: "Saturation"},
{id: "brightness", name: "Brightness"},
],
hsl: [
{id: "hue", name: "Hue"},
{id: "saturation", name: "Saturation"},
{id: "lightness", name: "Lightness"},
],
rgb: [
{id: "red", name: "Red"},
{id: "green", name: "Green"},
{id: "blue", name: "Blue"},
],
};
export function ColorAreaSpaceAndChannels() {
const [colorSpace, setColorSpace] = useState("hsb");
const [color, setColor] = useState(() => parseColor("hsb(219, 58%, 93%)"));
const channels = channelsBySpace[colorSpace];
const defaultX = colorSpace === "rgb" ? "blue" : "saturation";
const defaultY =
colorSpace === "rgb" ? "green" : colorSpace === "hsl" ? "lightness" : "brightness";
const [xChannel, setXChannel] = useState(defaultX);
const [yChannel, setYChannel] = useState(defaultY);
const handleColorSpaceChange = (newSpace: Key | null) => {
if (!newSpace) return;
const space = newSpace as ColorSpace;
setColorSpace(space);
// Reset channels to appropriate defaults for the new color space
if (space === "rgb") {
setXChannel("blue");
setYChannel("green");
} else if (space === "hsl") {
setXChannel("saturation");
setYChannel("lightness");
} else {
setXChannel("saturation");
setYChannel("brightness");
}
};
// Filter out the other channel from options (can't have same channel on both axes)
const xChannelOptions = channels.filter((c) => c.id !== yChannel);
const yChannelOptions = channels.filter((c) => c.id !== xChannel);
return (
{/* Controls */}
{/* Color Space Select */}
{/* X Channel Select */}
{/* Y Channel Select */}
{/* Color Area */}
{/* Color Value Display */}
{color.toString(colorSpace)}
);
}
```
### Disabled
```tsx
import {ColorArea} from "@thenamespace/uikit";
export function ColorAreaDisabled() {
return (
);
}
```
### Custom Render Function
```tsx
"use client";
import {ColorArea} from "@thenamespace/uikit";
export function CustomRenderFunction() {
return (
}
>
} />
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { ColorArea } from "@thenamespace/uikit";
function CustomColorArea() {
return (
);
}
```
### Customizing the component classes
To customize the ColorArea component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-area {
@apply rounded-3xl;
}
.color-area__thumb {
@apply size-5 border-4;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorArea component uses these CSS classes:
#### Base Classes
- `.color-area` - Base styles with gradient background and inner shadow
- `.color-area--show-dots` - Adds dot grid overlay for precision picking
#### Element Classes
- `.color-area__thumb` - Draggable thumb indicator
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Disabled**: `[data-disabled="true"]`
- **Focus**: `[data-focus-visible="true"]`
- **Dragging**: `[data-dragging="true"]` (thumb only)
## API Reference
### ColorArea Props
Inherits from [React Aria ColorArea](https://react-spectrum.adobe.com/react-aria/ColorArea.html).
| Prop | Type | Default | Description |
| -------------- | ---------------------------------------------------------------------------- | -------------- | ---------------------------------------------------------------- |
| `value` | `string \| Color` | - | The current color value (controlled) |
| `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) |
| `onChange` | `(color: Color) => void` | - | Handler called when the color changes while dragging |
| `onChangeEnd` | `(color: Color) => void` | - | Handler called when the user stops dragging |
| `xChannel` | `ColorChannel` | `"saturation"` | Color channel for the horizontal axis |
| `yChannel` | `ColorChannel` | `"brightness"` | Color channel for the vertical axis |
| `colorSpace` | `ColorSpace` | - | The color space for the channels |
| `isDisabled` | `boolean` | `false` | Whether the color area is disabled |
| `showDots` | `boolean` | `false` | Whether to show the dot grid overlay |
| `className` | `string` | - | Additional CSS classes |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorArea.Thumb Props
| Prop | Type | Default | Description |
| ----------- | ----------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `style` | `CSSProperties \| ((renderProps) => CSSProperties)` | - | Inline styles or render props function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
# ColorField
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/color-field
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/color-field.mdx
> Color input field with labels, descriptions, and validation built on React Aria ColorField
## Import
```tsx
import { ColorField, parseColor } from "@thenamespace/uikit";
```
### Usage
```tsx
"use client";
import type {Color} from "@thenamespace/uikit";
import {ColorField, ColorSwatch, Label, parseColor} from "@thenamespace/uikit";
import {useState} from "react";
export function Basic() {
const [color, setColor] = useState(parseColor("#0485F7"));
return (
);
}
```
### Anatomy
```tsx
import {
ColorField,
Label,
ColorSwatch,
Description,
FieldError,
parseColor,
} from "@thenamespace/uikit";
export default () => (
);
```
> **ColorField** combines label, color input, description, and error into a single accessible component.
### With Description
```tsx
import {ColorField, Description, Label} from "@thenamespace/uikit";
export function WithDescription() {
return (
Enter your brand's primary colorUsed for highlights and CTAs
);
}
```
### Required Field
```tsx
import {ColorField, Description, Label} from "@thenamespace/uikit";
export function Required() {
return (
Required field
);
}
```
### Validation
Use `isInvalid` together with `FieldError` to surface validation messages.
```tsx
import {ColorField, FieldError, Label} from "@thenamespace/uikit";
export function Invalid() {
return (
Please enter a valid hex colorInvalid color format. Use hex (e.g., #FF5733)
);
}
```
### Channel Editing
ColorField supports editing individual color channels (hue, saturation, lightness, red, green, blue, alpha) by setting the `colorSpace` and `channel` props.
```tsx
"use client";
import type {Color} from "@thenamespace/uikit";
import {ColorField, ColorSwatch, Label, parseColor} from "@thenamespace/uikit";
import {useState} from "react";
export function ChannelEditing() {
const [color, setColor] = useState(parseColor("#7F007F"));
return (
);
}
```
### Controlled
Control the value to synchronize with other components or state management.
```tsx
"use client";
import type {Color} from "@thenamespace/uikit";
import {Button, ColorField, ColorSwatch, Description, Label, parseColor} from "@thenamespace/uikit";
import {useState} from "react";
export function Controlled() {
const [value, setValue] = useState(parseColor("#0485F7"));
return (
Current value: {value ? value.toString("hex") : "(empty)"}
setValue(parseColor("#EF4444"))}>
Set Red
setValue(parseColor("#10B981"))}>
Set Green
setValue(null)}>
Clear
);
}
```
### Disabled State
```tsx
"use client";
import {ColorField, Description, Label} from "@thenamespace/uikit";
export function Disabled() {
return (
This color field is disabledThis color field is disabled
);
}
```
### Full Width
```tsx
import {ColorField, Label} from "@thenamespace/uikit";
export function FullWidth() {
return (
);
}
```
### Variants
The ColorField.Group component supports two visual variants:
- **`primary`** (default) - Standard styling with shadow, suitable for most use cases
- **`secondary`** - Lower emphasis variant without shadow, suitable for use in Surface components
```tsx
import {ColorField, Label} from "@thenamespace/uikit";
export function Variants() {
return (
);
}
```
### On Surface
When used inside a [Surface](/docs/components/surface) component, use `variant="secondary"` on ColorField.Group to apply the lower emphasis variant suitable for surface backgrounds.
```tsx
import {ColorField, Description, Label, Surface} from "@thenamespace/uikit";
export function OnSurface() {
return (
Select your theme color
);
}
```
### Form Example
Complete form example with validation and submission handling.
```tsx
"use client";
import type {Color} from "@thenamespace/uikit";
import {Button, ColorField, ColorSwatch, Description, Form, Label} from "@thenamespace/uikit";
import {useState} from "react";
export function FormExample() {
const [value, setValue] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!value) {
return;
}
setIsSubmitting(true);
// Simulate API call
setTimeout(() => {
console.log("Color submitted:", {color: value.toString("hex")});
setValue(null);
setIsSubmitting(false);
}, 1500);
};
return (
);
}
```
### Custom Render Function
```tsx
"use client";
import type {Color} from "@thenamespace/uikit";
import {ColorField, ColorSwatch, Label, parseColor} from "@thenamespace/uikit";
import {useState} from "react";
export function CustomRenderFunction() {
const [color, setColor] = useState(parseColor("#0485F7"));
return (
}
value={color}
onChange={setColor}
>
}>
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import {
ColorField,
Label,
ColorSwatch,
Description,
} from "@thenamespace/uikit";
function CustomColorField() {
return (
Select your brand's primary color.
);
}
```
### Customizing the component classes
ColorField has minimal default styling. Override the `.color-field` class to customize the container styling.
```css
@layer components {
.color-field {
@apply flex flex-col gap-1;
&[data-invalid="true"],
&[aria-invalid="true"] {
[data-slot="description"] {
@apply hidden;
}
}
[data-slot="label"] {
@apply w-fit;
}
[data-slot="description"] {
@apply px-1;
}
}
}
```
### CSS Classes
- `.color-field` – Root container with minimal styling (`flex flex-col gap-1`)
> **Note:** Child components ([Label](/docs/components/label), [Description](/docs/components/description), [FieldError](/docs/components/field-error)) have their own CSS classes and styling. See their respective documentation for customization options. ColorField.Group styling is documented below in the API Reference section.
### Interactive States
ColorField automatically manages these data attributes based on its state:
- **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` - Automatically hides the description slot when invalid
- **Required**: `[data-required="true"]` - Applied when `isRequired` is true
- **Disabled**: `[data-disabled="true"]` - Applied when `isDisabled` is true
- **Focus Within**: `[data-focus-within="true"]` - Applied when any child input is focused
## API Reference
### ColorField Props
ColorField inherits all props from React Aria's [ColorField](https://react-aria.adobe.com/ColorField.md) component.
#### Base Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------- |
| `children` | `React.ReactNode \| (values: ColorFieldRenderProps) => React.ReactNode` | - | Child components (Label, ColorField.Group, etc.) or render function. |
| `className` | `string \| (values: ColorFieldRenderProps) => string` | - | CSS classes for styling, supports render props. |
| `style` | `React.CSSProperties \| (values: ColorFieldRenderProps) => React.CSSProperties` | - | Inline styles, supports render props. |
| `fullWidth` | `boolean` | `false` | Whether the color field should take full width of its container |
| `id` | `string` | - | The element's unique identifier. |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
#### Value Props
| Prop | Type | Default | Description |
| -------------- | -------------------------------- | ------- | -------------------------------------- |
| `value` | `Color \| null` | - | Current value (controlled). |
| `defaultValue` | `Color \| null` | - | Default value (uncontrolled). |
| `onChange` | `(color: Color \| null) => void` | - | Handler called when the value changes. |
#### Channel Props
| Prop | Type | Default | Description |
| ------------ | -------------- | ------- | ---------------------------------------------------------------------------- |
| `colorSpace` | `ColorSpace` | - | The color space that the color field operates in when `channel` is provided. |
| `channel` | `ColorChannel` | - | The color channel to edit. If not provided, edits hex value. |
#### Validation Props
| Prop | Type | Default | Description |
| -------------------- | ---------------------------------------------------------------- | ---------- | -------------------------------------------------------------- |
| `isRequired` | `boolean` | `false` | Whether user input is required before form submission. |
| `isInvalid` | `boolean` | - | Whether the value is invalid. |
| `validate` | `(value: Color) => ValidationError \| true \| null \| undefined` | - | Custom validation function. |
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA attributes. |
#### State Props
| Prop | Type | Default | Description |
| ----------------- | --------- | ------- | -------------------------------------------------- |
| `isDisabled` | `boolean` | - | Whether the input is disabled. |
| `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed. |
| `isWheelDisabled` | `boolean` | - | Whether to disable changing the value with scroll. |
#### Form Props
| Prop | Type | Default | Description |
| ----------- | --------- | ------- | ---------------------------------------------------- |
| `name` | `string` | - | Name of the input element, for HTML form submission. |
| `autoFocus` | `boolean` | - | Whether the element should receive focus on render. |
#### Accessibility Props
| Prop | Type | Default | Description |
| ------------------ | -------- | ------- | ----------------------------------------------------- |
| `aria-label` | `string` | - | Accessibility label when no visible label is present. |
| `aria-labelledby` | `string` | - | ID of elements that label this field. |
| `aria-describedby` | `string` | - | ID of elements that describe this field. |
| `aria-details` | `string` | - | ID of elements with additional details. |
### Composition Components
ColorField works with these separate components that should be imported and used directly:
- **Label** - Field label component from `@thenamespace/uikit`
- **ColorField.Group** - Color input group component (documented below)
- **ColorField.Input** - Input element within ColorField.Group
- **ColorField.Prefix** / **ColorField.Suffix** - Prefix and suffix slots for the input group
- **ColorSwatch** - Color preview component from `@thenamespace/uikit`
- **Description** - Helper text component from `@thenamespace/uikit`
- **FieldError** - Validation error message from `@thenamespace/uikit`
Each of these components has its own props API. Use them directly within ColorField for composition:
```tsx
import {
ColorField,
Label,
ColorSwatch,
Description,
FieldError,
parseColor,
} from "@thenamespace/uikit";
Select your brand's primary color.Please enter a valid color.;
```
### Color Types
ColorField uses `Color` objects from React Aria Components:
```tsx
import { parseColor } from "@thenamespace/uikit";
// Parse from hex string
const color = parseColor("#3B82F6");
// Get hex string from color
const hex = color.toString("hex"); // "#3b82f6"
// Get RGB values
const rgb = color.toString("rgb"); // "rgb(59, 130, 246)"
// Use in ColorField
{/* ... */}
;
```
### ColorFieldRenderProps
When using render props with `className`, `style`, or `children`, these values are available:
| Prop | Type | Description |
| ---------------- | --------- | ----------------------------------------------- |
| `isDisabled` | `boolean` | Whether the field is disabled. |
| `isInvalid` | `boolean` | Whether the field is currently invalid. |
| `isReadOnly` | `boolean` | Whether the field is read-only. |
| `isRequired` | `boolean` | Whether the field is required. |
| `isFocused` | `boolean` | Whether the field is currently focused. |
| `isFocusWithin` | `boolean` | Whether any child element is focused. |
| `isFocusVisible` | `boolean` | Whether focus is visible (keyboard navigation). |
### ColorField.Group Props
ColorField.Group accepts all props from React Aria's `Group` component plus the following:
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `fullWidth` | `boolean` | `false` | Whether the color input group should take full width of its container |
| `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the component. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorField.Input Props
ColorField.Input accepts all props from React Aria's `Input` component plus the following:
| Prop | Type | Default | Description |
| ------------- | -------- | ------- | -------------------------------------------------- |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `placeholder` | `string` | - | Placeholder text shown when empty. |
### ColorField.Prefix Props
ColorField.Prefix accepts standard HTML `div` attributes:
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | -------------------------------------------------- |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `children` | `ReactNode` | - | Content to display in the prefix slot. |
### ColorField.Suffix Props
ColorField.Suffix accepts standard HTML `div` attributes:
| Prop | Type | Default | Description |
| ----------- | ----------- | ------- | -------------------------------------------------- |
| `className` | `string` | - | Tailwind classes merged with the component styles. |
| `children` | `ReactNode` | - | Content to display in the suffix slot. |
## ColorField.Group Styling
### Customizing the component classes
The base classes power every instance. Override them once with `@layer components`.
```css
@layer components {
.color-input-group {
@apply inline-flex h-9 items-center overflow-hidden rounded-field border bg-field text-sm text-field-foreground shadow-field outline-none;
&:hover,
&[data-hovered="true"] {
@apply bg-field-hover;
}
&[data-focus-within="true"],
&:focus-within {
@apply status-focused-field;
}
&[data-invalid="true"] {
@apply status-invalid-field;
}
&[data-disabled="true"],
&[aria-disabled="true"] {
@apply status-disabled;
}
}
.color-input-group__input {
@apply flex flex-1 items-center rounded-none border-0 bg-transparent px-3 py-2 shadow-none outline-none;
}
.color-input-group__prefix,
.color-input-group__suffix {
@apply shrink-0 text-field-placeholder flex items-center;
}
}
```
### ColorField.Group CSS Classes
- `.color-input-group` – Root container styling
- `.color-input-group__input` – Input wrapper styling
- `.color-input-group__prefix` – Prefix element styling
- `.color-input-group__suffix` – Suffix element styling
### ColorField.Group Interactive States
- **Hover**: `:hover` or `[data-hovered="true"]`
- **Focus Within**: `[data-focus-within="true"]` or `:focus-within`
- **Invalid**: `[data-invalid="true"]` (also syncs with `aria-invalid`)
- **Disabled**: `[data-disabled="true"]` or `[aria-disabled="true"]`
# Color Input Group
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/color-input-group
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/color-input-group.mdx
> Input-group primitives used to compose color fields and pickers.
Import this public entry point directly when composing lower-level UIKit parts.
```tsx
import * as ColorInputGroup from "@thenamespace/uikit/color-input-group";
```
See [color-field](./color-field) for complete composition examples and API guidance.
This entry point is also re-exported from `@thenamespace/uikit`. Direct imports make the dependency explicit and provide a stable location for advanced customization.
# ColorPicker
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/color-picker
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/color-picker.mdx
> A composable color picker that synchronizes color value between multiple color components
## Import
```tsx
import {
ColorPicker,
ColorArea,
ColorSlider,
ColorSwatch,
ColorField,
ColorSwatchPicker,
} from "@thenamespace/uikit";
```
### Usage
```tsx
import {ColorArea, ColorPicker, ColorSlider, ColorSwatch, Label} from "@thenamespace/uikit";
export function Basic() {
return (
);
}
```
### Anatomy
The ColorPicker is a composable component that combines multiple color components:
```tsx
import {
ColorPicker,
ColorArea,
ColorSlider,
ColorSwatch,
Label,
} from "@thenamespace/uikit";
export default () => (
);
```
### Controlled
```tsx
"use client";
import { useState } from "react";
import {
Button,
ColorArea,
ColorField,
ColorPicker,
ColorSlider,
ColorSwatch,
ColorSwatchPicker,
Label,
parseColor,
} from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
export function Controlled() {
const [color, setColor] = useState(parseColor("#325578"));
const colorPresets = [
"#ef4444",
"#f97316",
"#eab308",
"#22c55e",
"#06b6d4",
"#3b82f6",
"#8b5cf6",
"#ec4899",
"#f43f5e",
];
const shuffleColor = () => {
const randomHue = Math.floor(Math.random() * 360);
const randomSaturation = 50 + Math.floor(Math.random() * 50); // 50-100%
const randomLightness = 40 + Math.floor(Math.random() * 30); // 40-70%
setColor(parseColor(`hsl(${randomHue}, ${randomSaturation}%, ${randomLightness}%)`));
};
return (
{colorPresets.map((preset) => (
))}
Selected: {color.toString("hex")}
);
}
```
### With Swatches
```tsx
import {
ColorArea,
ColorPicker,
ColorSlider,
ColorSwatch,
ColorSwatchPicker,
Label,
} from "@thenamespace/uikit";
export function WithSwatches() {
const presets = [
"#ef4444",
"#f97316",
"#eab308",
"#22c55e",
"#06b6d4",
"#3b82f6",
"#8b5cf6",
"#ec4899",
"#f43f5e",
];
return (
{presets.map((preset) => (
))}
);
}
```
### With Fields
Use `ColorField` to allow users to edit individual color channel values with a `Select` to switch between color spaces.
```tsx
"use client";
import type {ColorChannel, ColorSpace} from "@thenamespace/uikit";
import {
ColorArea,
ColorField,
ColorPicker,
ColorSlider,
ColorSwatch,
Label,
ListBox,
Select,
} from "@thenamespace/uikit";
import {useState} from "react";
export function WithFields() {
const [colorSpace, setColorSpace] = useState("hsl");
const colorChannelsByColorSpace: Record = {
hsb: ["hue", "saturation", "brightness"],
hsl: ["hue", "saturation", "lightness"],
rgb: ["red", "green", "blue"],
};
return (
);
}
```
### With Sliders
Use multiple `ColorSlider` components to adjust each channel of a color value.
```tsx
"use client";
import type {ColorChannel, ColorSpace} from "@thenamespace/uikit";
import {ColorPicker, ColorSlider, ColorSwatch, Label, ListBox, Select} from "@thenamespace/uikit";
import {useState} from "react";
export function WithSliders() {
const [colorSpace, setColorSpace] = useState("hsl");
const colorChannelsByColorSpace: Record = {
hsb: ["hue", "saturation", "brightness", "alpha"],
hsl: ["hue", "saturation", "lightness", "alpha"],
rgb: ["red", "green", "blue", "alpha"],
};
return (
{colorChannelsByColorSpace[colorSpace].map((channel: ColorChannel) => (
// @ts-expect-error - TypeScript can't correlate dynamic colorSpace with channel type
))}
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import {
ColorPicker,
ColorArea,
ColorSlider,
ColorSwatch,
Label,
} from "@thenamespace/uikit";
function CustomColorPicker() {
return (
);
}
```
### Customizing the component classes
To customize the ColorPicker component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-picker {
@apply inline-flex;
}
.color-picker__trigger {
@apply inline-flex items-center gap-4 rounded-lg;
}
.color-picker__popover {
@apply p-4 rounded-xl;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorPicker component uses these CSS classes:
#### Base Classes
- `.color-picker` - Base container
- `.color-picker__trigger` - Trigger button
- `.color-picker__popover` - Popover container
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]`
- **Disabled**: `:disabled` or `[data-disabled="true"]`
## API Reference
### ColorPicker Props
Inherits from [React Aria ColorPicker](https://react-spectrum.adobe.com/react-aria/ColorPicker.html).
| Prop | Type | Default | Description |
| -------------- | ------------------------ | ------- | ---------------------------------------------------- |
| `value` | `string \| Color` | - | The current color value (controlled) |
| `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) |
| `onChange` | `(color: Color) => void` | - | Handler called when the color changes |
| `children` | `React.ReactNode` | - | Content of the color picker (Trigger, Popover, etc.) |
| `className` | `string` | - | Additional CSS classes |
### ColorPicker.Trigger Props
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------- | ------- | ------------------------------ |
| `children` | `React.ReactNode \| ((renderProps) => React.ReactNode)` | - | Trigger content or render prop |
| `className` | `string` | - | Additional CSS classes |
### ColorPicker.Popover Props
| Prop | Type | Default | Description |
| ----------- | ----------------- | --------------- | ------------------------ |
| `placement` | `Placement` | `"bottom left"` | Placement of the popover |
| `children` | `React.ReactNode` | - | Popover content |
| `className` | `string` | - | Additional CSS classes |
### Related Types
#### Color
Represents a color value. See [React Aria Color](https://react-spectrum.adobe.com/react-aria/ColorPicker.html#color) for full API.
| Method | Description |
| ---------------------------------- | ---------------------------------------------------------------------------- |
| `toString(format)` | Converts the color to a string in the given format (hex, rgb, hsl, hsb, css) |
| `toFormat(format)` | Converts the color to the given format and returns a new Color object |
| `getChannelValue(channel)` | Returns the numeric value for a given channel |
| `withChannelValue(channel, value)` | Sets the numeric value for a channel and returns a new Color |
#### parseColor
```tsx
import { parseColor } from "react-aria-components";
// Parse from string
const color = parseColor("#ff0000");
const hslColor = parseColor("hsl(0, 100%, 50%)");
```
# ColorSlider
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/color-slider
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/color-slider.mdx
> A color slider allows users to adjust an individual channel of a color value
## Import
```tsx
import { ColorSlider, Label } from "@thenamespace/uikit";
```
### Usage
```tsx
import {ColorSlider, Label} from "@thenamespace/uikit";
export function Basic() {
return (
);
}
```
### Anatomy
Import the ColorSlider component and access all parts using dot notation.
```tsx
import { ColorSlider, Label } from "@thenamespace/uikit";
export default () => (
);
```
### Vertical
```tsx
import {ColorSlider} from "@thenamespace/uikit";
export function Vertical() {
return (
);
}
```
### Disabled
```tsx
import {ColorSlider, Label} from "@thenamespace/uikit";
export function Disabled() {
return (
);
}
```
### Controlled
```tsx
"use client";
import {ColorSlider, ColorSwatch, Label} from "@thenamespace/uikit";
import {useState} from "react";
import {parseColor} from "react-aria-components";
export function Controlled() {
const [color, setColor] = useState(parseColor("hsl(200, 100%, 50%)"));
return (
Current color: {color.toString("hsl")}
);
}
```
### HSL Channels
Use multiple ColorSliders to control different channels of a color value. The sliders can share the same color value to create a complete color picker.
```tsx
"use client";
import {ColorSlider, ColorSwatch, Label} from "@thenamespace/uikit";
import {useState} from "react";
import {parseColor} from "react-aria-components";
export function Channels() {
const [color, setColor] = useState(parseColor("hsl(0, 100%, 50%)"));
return (
Current color: {color.toString("hsl")}
);
}
```
### Alpha Channel
The alpha channel slider shows a transparency checkerboard pattern to help visualize the transparency level.
```tsx
import {ColorSlider, Label} from "@thenamespace/uikit";
export function AlphaChannel() {
return (
);
}
```
### RGB Channels
You can also use RGB color space with red, green, and blue channels.
```tsx
"use client";
import {ColorSlider, ColorSwatch, Label} from "@thenamespace/uikit";
import {useState} from "react";
import {parseColor} from "react-aria-components";
export function RGBChannels() {
const [color, setColor] = useState(parseColor("rgb(255, 100, 50)"));
return (
Current color: {color.toString("rgb")}
);
}
```
### Custom Render Function
```tsx
"use client";
import {ColorSlider, Label} from "@thenamespace/uikit";
export function CustomRenderFunction() {
return (
}
>
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { ColorSlider, Label } from "@thenamespace/uikit";
function CustomColorSlider() {
return (
);
}
```
### Customizing the component classes
To customize the ColorSlider component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-slider {
@apply flex flex-col gap-2;
}
.color-slider__output {
@apply text-muted text-sm;
}
.color-slider__track {
@apply relative h-5 w-full rounded-full;
}
.color-slider__thumb {
@apply size-4 rounded-full border-3 border-white shadow-overlay;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorSlider component uses these CSS classes:
#### Base Classes
- `.color-slider` - Base slider container
- `.color-slider__output` - Output element displaying current value
- `.color-slider__track` - Track element with color gradient
- `.color-slider__thumb` - Thumb element showing current color
#### State Classes
- `.color-slider[data-disabled="true"]` - Disabled slider state
- `.color-slider[data-orientation="vertical"]` - Vertical orientation
- `.color-slider__thumb[data-dragging="true"]` - Thumb being dragged
- `.color-slider__thumb[data-focus-visible="true"]` - Thumb keyboard focused
- `.color-slider__thumb[data-disabled="true"]` - Disabled thumb state
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Hover**: `:hover` or `[data-hovered="true"]` on thumb
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on thumb
- **Dragging**: `[data-dragging="true"]` on thumb
- **Disabled**: `:disabled` or `[data-disabled="true"]` on slider or thumb
## API Reference
### ColorSlider Props
Inherits from [React Aria ColorSlider](https://react-spectrum.adobe.com/react-aria/ColorSlider.html).
| Prop | Type | Default | Description |
| -------------- | ------------------------------------------------------------------------------ | -------------- | --------------------------------------------------------------------------------------------------------------- |
| `channel` | `ColorChannel` | - | The color channel that the slider manipulates (hue, saturation, lightness, brightness, alpha, red, green, blue) |
| `colorSpace` | `ColorSpace` | - | The color space (hsl, hsb, rgb). Defaults to the color space of the value |
| `value` | `string \| Color` | - | The current color value (controlled) |
| `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) |
| `onChange` | `(value: Color) => void` | - | Handler called when the value changes during dragging |
| `onChangeEnd` | `(value: Color) => void` | - | Handler called when dragging ends |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | The orientation of the slider |
| `isDisabled` | `boolean` | - | Whether the slider is disabled |
| `name` | `string` | - | The name of the input element for form submission |
| `aria-label` | `string` | - | Accessibility label for the slider |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Slider content or render function |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorSlider.Output Props
| Prop | Type | Default | Description |
| ----------- | ----------------------------- | ------- | --------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Output content or render function |
### ColorSlider.Track Props
| Prop | Type | Default | Description |
| ----------- | --------------------------------- | ------- | -------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `style` | `CSSProperties \| RenderFunction` | - | Inline styles or render function |
| `children` | `ReactNode \| RenderFunction` | - | Track content or render function |
### ColorSlider.Thumb Props
| Prop | Type | Default | Description |
| ----------- | --------------------------------- | ------- | -------------------------------- |
| `className` | `string` | - | Additional CSS classes |
| `style` | `CSSProperties \| RenderFunction` | - | Inline styles or render function |
| `children` | `ReactNode \| RenderFunction` | - | Thumb content or render function |
### RenderProps
When using render functions, these values are provided:
| Prop | Type | Description |
| ------------- | ---------------------------- | ------------------------------ |
| `state` | `ColorSliderState` | The state of the color slider |
| `color` | `Color` | The current color value |
| `orientation` | `"horizontal" \| "vertical"` | The orientation of the slider |
| `isDisabled` | `boolean` | Whether the slider is disabled |
## Accessibility
The ColorSlider component implements the ARIA slider pattern and provides:
- Full keyboard navigation support (Arrow keys, Home, End, Page Up/Down)
- Screen reader announcements for value changes
- Proper focus management
- Support for disabled states
- HTML form integration via hidden input elements
- Internationalization support with locale-aware value formatting
For more information, see the [React Aria ColorSlider documentation](https://react-spectrum.adobe.com/react-aria/ColorSlider.html).
# ColorSwatchPicker
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/color-swatch-picker
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/color-swatch-picker.mdx
> A list of color swatches that allows users to select a color from a predefined palette.
## Import
```tsx
import { ColorSwatchPicker, parseColor } from "@thenamespace/uikit";
```
### Usage
```tsx
import {ColorSwatchPicker} from "@thenamespace/uikit";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
export function Basic() {
return (
{colors.map((color) => (
))}
);
}
```
### Anatomy
Import the ColorSwatchPicker component and access all parts using dot notation.
```tsx
import { ColorSwatchPicker } from "@thenamespace/uikit";
export default () => (
);
```
### Variants
```tsx
import {ColorSwatchPicker} from "@thenamespace/uikit";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
export function Variants() {
return (
);
}
```
### Disabled
```tsx
import {ColorSwatchPicker} from "@thenamespace/uikit";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
export function Disabled() {
return (
{colors.map((color) => (
))}
);
}
```
### Custom Indicator
```tsx
import { ColorSwatchPicker } from "@thenamespace/uikit";
import { FavouriteIcon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function CustomIndicator() {
const colors = [
"#F43F5E",
"#D946EF",
"#8B5CF6",
"#3B82F6",
"#06B6D4",
"#10B981",
"#84CC16",
];
return (
{colors.map((color) => (
))}
);
}
```
### Custom Render Function
```tsx
"use client";
import {ColorSwatchPicker} from "@thenamespace/uikit";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];
export function CustomRenderFunction() {
return (
}>
{colors.map((color) => (
))}
);
}
```
## Styling
### Passing Tailwind CSS classes
You can customize the ColorSwatchPicker using className props:
```tsx
import { ColorSwatchPicker } from "@thenamespace/uikit";
function CustomColorSwatchPicker() {
return (
);
}
```
### Customizing the component classes
To customize the ColorSwatchPicker component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-swatch-picker {
@apply gap-4;
}
.color-swatch-picker__item {
@apply shadow-md;
}
.color-swatch-picker__swatch {
@apply border-2 border-white;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorSwatchPicker component uses these CSS classes:
#### Base & Structure
- `.color-swatch-picker` - Base container (flex layout)
- `.color-swatch-picker__item` - Individual swatch item wrapper
- `.color-swatch-picker__swatch` - The color swatch visual element
#### Size Classes
- `.color-swatch-picker--xs` - Extra small (16px)
- `.color-swatch-picker--sm` - Small (24px)
- `.color-swatch-picker--md` - Medium (32px, default)
- `.color-swatch-picker--lg` - Large (36px)
- `.color-swatch-picker--xl` - Extra large (40px)
#### Shape Variants
- `.color-swatch-picker--circle` - Circle shape (default)
- `.color-swatch-picker--square` - Square shape with rounded corners
#### Layout Classes
- `.color-swatch-picker--grid` - Horizontal wrapping layout (default)
- `.color-swatch-picker--stack` - Vertical stacked layout
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Hover**: `:hover` or `[data-hovered="true"]` - Scale up to 1.1 (only when not selected)
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` - Focus ring
- **Selected**: `[data-selected="true"]` - Inner border with same color as swatch
- **Disabled**: `[data-disabled="true"]` - Reduced opacity
## API Reference
### ColorSwatchPicker Props
Inherits from [React Aria ColorSwatchPicker](https://react-spectrum.adobe.com/react-aria/ColorSwatchPicker.html).
| Prop | Type | Default | Description |
| -------------- | ------------------------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------- |
| `value` | `string \| Color` | - | The current selected color (controlled) |
| `defaultValue` | `string \| Color` | - | The default selected color (uncontrolled) |
| `onChange` | `(value: Color) => void` | - | Handler called when selection changes |
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Size of the swatches |
| `variant` | `"circle" \| "square"` | `"circle"` | Shape of the swatches |
| `layout` | `"grid" \| "stack"` | `"grid"` | Layout direction |
| `className` | `string` | - | Additional CSS classes |
| `children` | `React.ReactNode` | - | ColorSwatchPicker.Item elements |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorSwatchPicker.Item Props
| Prop | Type | Default | Description |
| ------------ | ---------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------- |
| `color` | `string \| Color` | **Required** | The color of the swatch |
| `isDisabled` | `boolean` | `false` | Whether the item is disabled |
| `className` | `string` | - | Additional CSS classes |
| `children` | `React.ReactNode` | - | ColorSwatchPicker.Swatch element |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### ColorSwatchPicker.Swatch Props
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ---------------------- |
| `className` | `string` | - | Additional CSS classes |
### parseColor
The `parseColor` function is re-exported from React Aria Components for convenience:
```tsx
import { parseColor } from "@thenamespace/uikit";
// Parse hex color
const red = parseColor("#ff0000");
// Parse RGB
const green = parseColor("rgb(0, 255, 0)");
// Parse HSL
const blue = parseColor("hsl(240, 100%, 50%)");
```
# ColorSwatch
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/color-swatch
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/color-swatch.mdx
> A visual preview of a color value with accessibility support
## Import
```tsx
import { ColorSwatch } from "@thenamespace/uikit";
```
### Usage
```tsx
import {ColorSwatch} from "@thenamespace/uikit";
export function ColorSwatchBasic() {
return (
);
}
```
### Sizes
```tsx
import {ColorSwatch} from "@thenamespace/uikit";
export function ColorSwatchSizes() {
return (
);
}
```
### Shapes
```tsx
import {ColorSwatch} from "@thenamespace/uikit";
export function ColorSwatchShapes() {
return (
);
}
```
### Transparency
```tsx
import {ColorSwatch} from "@thenamespace/uikit";
export function ColorSwatchTransparency() {
return (
);
}
```
### Custom Styles with Render Props
You can use the `style` render props to access the color value and create custom visual effects.
```tsx
"use client";
import {ColorSwatch} from "@thenamespace/uikit";
export function ColorSwatchCustomStyles() {
const colors = ["#0485F7", "#EF4444", "#F59E0B", "#10B981", "#D946EF"];
return (
);
}
```
### Accessibility
Use `colorName` to provide a custom accessible name for the color, and `aria-label` to add context about how the color is used.
```tsx
import {ColorSwatch} from "@thenamespace/uikit";
export function ColorSwatchAccessibility() {
return (
);
}
```
### Custom Render Function
```tsx
"use client";
import {ColorSwatch} from "@thenamespace/uikit";
export function CustomRenderFunction() {
return (
}
/>
}
/>
}
/>
}
/>
}
/>
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { ColorSwatch } from "@thenamespace/uikit";
function CustomColorSwatch() {
return ;
}
```
### Customizing the component classes
To customize the ColorSwatch component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.color-swatch {
@apply border-2 border-white;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ColorSwatch component uses these CSS classes:
#### Base Classes
- `.color-swatch` - Base swatch styles with checkered background for transparency
#### Shape Classes
- `.color-swatch--circle` - Circular shape (default)
- `.color-swatch--square` - Square shape with rounded corners
#### Size Classes
- `.color-swatch--xs` - Extra small (16px)
- `.color-swatch--sm` - Small (24px)
- `.color-swatch--md` - Medium (32px, default)
- `.color-swatch--lg` - Large (36px)
- `.color-swatch--xl` - Extra large (40px)
## API Reference
### ColorSwatch Props
| Prop | Type | Default | Description |
| ------------ | ------------------------------------------------------------------------------ | ---------- | -------------------------------------------------------------------- |
| `color` | `string \| Color` | - | The color value to display (hex, rgb, hsl, etc.) |
| `colorName` | `string` | - | Accessible name for the color (overrides auto-generated description) |
| `className` | `string` | - | Additional CSS classes |
| `shape` | `"circle" \| "square"` | `"circle"` | Shape of the swatch |
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Size of the swatch |
| `style` | `CSSProperties \| ((renderProps) => CSSProperties)` | - | Inline styles or render props function with access to color |
| `aria-label` | `string` | - | Accessible label for the swatch |
| `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function. |
### Style Render Props
When using the `style` prop as a function, you receive render props with access to the color:
```tsx
({
boxShadow: `0 4px 14px ${color.toString("css")}80`,
})}
/>
```
The `color` object provides methods like:
- `color.toString("css")` - Returns CSS color string
- `color.toString("hex")` - Returns hex color string
- `color.getChannelValue("alpha")` - Returns alpha channel value
# ComboBox
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/combo-box
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/combo-box.mdx
> A combo box combines a text input with a listbox, allowing users to filter a list of options to items matching a query
## Import
```tsx
import { ComboBox } from "@thenamespace/uikit";
```
### Usage
```tsx
"use client";
import {ComboBox, Input, Label, ListBox} from "@thenamespace/uikit";
export function Default() {
return (
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
);
}
```
### Anatomy
Import the ComboBox component and access all parts using dot notation.
```tsx
import {
ComboBox,
Input,
Label,
Description,
Header,
ListBox,
Separator,
} from "@thenamespace/uikit";
export default () => (
);
```
### With Description
```tsx
"use client";
import {ComboBox, Description, Input, Label, ListBox} from "@thenamespace/uikit";
export function WithDescription() {
return (
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
Search and select your favorite animal
);
}
```
### With Sections
```tsx
"use client";
import {ComboBox, Header, Input, Label, ListBox, Separator} from "@thenamespace/uikit";
export function WithSections() {
return (
North America
United States
Canada
Mexico
Europe
United Kingdom
France
Germany
Spain
Italy
Asia
Japan
China
India
South Korea
);
}
```
### With Disabled Options
```tsx
"use client";
import {ComboBox, Input, Label, ListBox} from "@thenamespace/uikit";
export function WithDisabledOptions() {
return (
Dog
Cat
Bird
Kangaroo
Elephant
Tiger
);
}
```
### Custom Indicator
```tsx
"use client";
import { ComboBox, Input, Label, ListBox } from "@thenamespace/uikit";
import { UnfoldMoreIcon, HugeiconsIcon } from "@thenamespace/uikit/icons";
export function CustomIndicator() {
return (
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
);
}
```
### Required
```tsx
"use client";
import {Button, ComboBox, FieldError, Form, Input, Label, ListBox} from "@thenamespace/uikit";
export function Required() {
const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data: Record = {};
formData.forEach((value, key) => {
data[key] = value.toString();
});
alert("Form submitted successfully!");
};
return (
);
}
```
### Custom Value
```tsx
"use client";
import {
Avatar,
AvatarFallback,
AvatarImage,
ComboBox,
Description,
Input,
Label,
ListBox,
} from "@thenamespace/uikit";
export function CustomValue() {
const users = [
{
avatarUrl: "/assets/avatars/blue.jpg",
email: "bob@namespace.ninja",
fallback: "B",
id: "1",
name: "Bob",
},
{
avatarUrl: "/assets/avatars/green.jpg",
email: "fred@namespace.ninja",
fallback: "F",
id: "2",
name: "Fred",
},
{
avatarUrl: "/assets/avatars/purple.jpg",
email: "martha@namespace.ninja",
fallback: "M",
id: "3",
name: "Martha",
},
{
avatarUrl: "/assets/avatars/red.jpg",
email: "john@namespace.ninja",
fallback: "J",
id: "4",
name: "John",
},
{
avatarUrl: "/assets/avatars/orange.jpg",
email: "jane@namespace.ninja",
fallback: "J",
id: "5",
name: "Jane",
},
];
return (
{users.map((user) => (
{user.fallback}
);
}
```
### Custom Filtering
```tsx
"use client";
import {ComboBox, Input, Label, ListBox} from "@thenamespace/uikit";
export function CustomFiltering() {
const animals = [
{id: "cat", name: "Cat"},
{id: "dog", name: "Dog"},
{id: "bird", name: "Bird"},
{id: "fish", name: "Fish"},
{id: "hamster", name: "Hamster"},
];
return (
{
if (!inputValue) return true;
return text.toLowerCase().includes(inputValue.toLowerCase());
}}
>
{animals.map((animal) => (
{animal.name}
))}
);
}
```
### Allows Custom Value
```tsx
"use client";
import {ComboBox, Description, Input, Label, ListBox} from "@thenamespace/uikit";
export function AllowsCustomValue() {
return (
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
You can type any animal name, even if it's not in the list
);
}
```
### Disabled
```tsx
"use client";
import {ComboBox, Input, Label, ListBox} from "@thenamespace/uikit";
export function Disabled() {
return (
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
);
}
```
### Default Selected Key
```tsx
"use client";
import {ComboBox, Input, Label, ListBox} from "@thenamespace/uikit";
export function DefaultSelectedKey() {
return (
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
);
}
```
### Full Width
```tsx
import {ComboBox, Input, Label, ListBox} from "@thenamespace/uikit";
export function FullWidth() {
return (
Aardvark
Cat
Dog
);
}
```
### In Surface
When used inside a [Surface](/docs/components/surface) component, use `variant="secondary"` to apply the lower emphasis variant suitable for surface backgrounds.
```tsx
"use client";
import {Button, ComboBox, FieldError, Form, Input, Label, ListBox, Surface} from "@thenamespace/uikit";
export function OnSurface() {
const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data: Record = {};
formData.forEach((value, key) => {
data[key] = value.toString();
});
alert("Form submitted successfully!");
};
return (
);
}
```
### Menu Trigger
Use the `menuTrigger` prop to control when the popover opens:
- `focus` (default): popover opens when the user focuses the input
- `input`: popover opens when the user edits the input text
- `manual`: popover only opens when the user presses the trigger button or uses the arrow keys
```tsx
"use client";
import {ComboBox, Description, Input, Label, ListBox} from "@thenamespace/uikit";
export function MenuTrigger() {
return (
Focus (default)
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
Popover opens when the input is focused
Input
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
Popover opens when the user edits the input text
Manual
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
Popover only opens when the trigger button is pressed or arrow keys are used
);
}
```
### Custom Render Function
```tsx
"use client";
import {ComboBox, Input, Label, ListBox} from "@thenamespace/uikit";
export function CustomRenderFunction() {
return (
}>
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
);
}
```
## Styling
### Passing Tailwind CSS classes
```tsx
import { ComboBox, Input } from "@thenamespace/uikit";
function CustomComboBox() {
return (
Item 1
);
}
```
### Customizing the component classes
To customize the ComboBox component classes, you can use the `@layer components` directive.
[Learn
more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).
```css
@layer components {
.combo-box {
@apply flex flex-col gap-1;
}
.combo-box__input-group {
@apply relative inline-flex items-center;
}
.combo-box__trigger {
@apply absolute right-0 text-muted;
}
.combo-box__popover {
@apply rounded-lg border border-border bg-surface p-2;
}
}
```
Namespace UIKit follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.
### CSS Classes
The ComboBox component uses these CSS classes:
#### Base Classes
- `.combo-box` - Base ComboBox container
- `.combo-box__input-group` - Container for the input and trigger button
- `.combo-box__trigger` - The button that triggers the popover
- `.combo-box__popover` - The popover container
#### State Classes
- `.combo-box[data-invalid="true"]` - Invalid state
- `.combo-box[data-disabled="true"]` - Disabled ComboBox state
- `.combo-box__trigger[data-focus-visible="true"]` - Focused trigger state
- `.combo-box__trigger[data-disabled="true"]` - Disabled trigger state
- `.combo-box__trigger[data-open="true"]` - Open trigger state
### Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- **Hover**: `:hover` or `[data-hovered="true"]` on trigger
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on trigger
- **Disabled**: `:disabled` or `[data-disabled="true"]` on ComboBox
- **Open**: `[data-open="true"]` on trigger
## API Reference
### ComboBox Props
| Prop | Type | Default | Description |
| ----------------------- | ---------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `inputValue` | `string` | - | Current input value (controlled) |
| `defaultInputValue` | `string` | - | Default input value (uncontrolled) |
| `onInputChange` | `(value: string) => void` | - | Handler called when the input value changes |
| `selectedKey` | `Key \| null` | - | Current selected key (controlled) |
| `defaultSelectedKey` | `Key \| null` | - | Default selected key (uncontrolled) |
| `onSelectionChange` | `(key: Key \| null) => void` | - | Handler called when the selection changes |
| `items` | `Iterable` | - | The items to display in the listbox |
| `disabledKeys` | `Iterable` | - | Keys of disabled items |
| `defaultFilter` | `(text: string, inputValue: string) => boolean` | - | Custom filter function for filtering items |
| `isDisabled` | `boolean` | - | Whether the ComboBox is disabled |
| `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed by the user |
| `isRequired` | `boolean` | - | Whether user input is required |
| `isInvalid` | `boolean` | - | Whether the ComboBox value is invalid |
| `validate` | `(value: ComboBoxValidationValue) => ValidationError \| true \| null \| undefined` | - | A function that returns an error message if a given value is invalid. Validation errors are displayed to the user when the form is submitted if `validationBehavior="native"`. For realtime validation, use the `isInvalid` prop instead |
| `validationBehavior` | `"native" \| "aria"` | `"native"` | Whether to use native HTML form validation to prevent form submission when the value is missing or invalid, or mark the field as required or invalid via ARIA |
| `name` | `string` | - | The name of the input, used when submitting an HTML form |
| `form` | `string` | - | The id of a `
# Command
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/command
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/command.mdx
> A command palette with fuzzy search, keyboard navigation, and nested groups for quick actions.
## Usage
{/* DEMO command-default */}
```tsx
"use client";
import { useState } from "react";
import { Button, Chip, Kbd } from "@thenamespace/uikit";
import { Command } from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
const actions = [
["Create new file...", "lucide:file-plus-2"],
["Create new folder...", "lucide:folder-plus"],
["Assign to me", "lucide:user-round-pen"],
] as const;
const settings = [
["Preferences", "lucide:settings"],
["Change theme", "lucide:palette"],
["Keyboard shortcuts", "lucide:keyboard"],
] as const;
function Contents({ minimal = false }: { minimal?: boolean }) {
return (
<>
{minimal ? null : (
Home
)}
Esc <>No results found.>}>
{actions.map(([label, icon]) => (
{label}
))}
{minimal ? null : (
{settings.map(([label, icon]) => (
{label}
))}
)}
{minimal ? null : (
↑↓Navigate↵Select
)}
>
);
}
function Palette({
label = "Open Command Palette",
size = "md",
variant = "opaque",
children,
}: {
children?: React.ReactNode;
label?: string;
size?: "sm" | "md" | "lg";
variant?: "transparent" | "opaque" | "blur";
}) {
const [open, setOpen] = useState(false);
return (
<>
setOpen(true)}>
{label} ⌘ K{children ?? }
>
);
}
export const DemoDefaultExample = () => ;
```
## Anatomy
Import the Command component and access all parts using dot notation.
```tsx
import { Command } from "@thenamespace/uikit";
;
```
## Clean
{/* DEMO command-clean */}
```tsx
"use client";
import { useState } from "react";
import { Button, Chip, Kbd } from "@thenamespace/uikit";
import { Command } from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
const actions = [
["Create new file...", "lucide:file-plus-2"],
["Create new folder...", "lucide:folder-plus"],
["Assign to me", "lucide:user-round-pen"],
] as const;
const settings = [
["Preferences", "lucide:settings"],
["Change theme", "lucide:palette"],
["Keyboard shortcuts", "lucide:keyboard"],
] as const;
function Contents({ minimal = false }: { minimal?: boolean }) {
return (
<>
{minimal ? null : (
Home
)}
Esc <>No results found.>}>
{actions.map(([label, icon]) => (
{label}
))}
{minimal ? null : (
{settings.map(([label, icon]) => (
{label}
))}
)}
{minimal ? null : (
↑↓Navigate↵Select
)}
>
);
}
function Palette({
label = "Open Command Palette",
size = "md",
variant = "opaque",
children,
}: {
children?: React.ReactNode;
label?: string;
size?: "sm" | "md" | "lg";
variant?: "transparent" | "opaque" | "blur";
}) {
const [open, setOpen] = useState(false);
return (
<>
setOpen(true)}>
{label} ⌘ K{children ?? }
>
);
}
export const DemoCleanExample = () => (
home
);
```
## Dev Toolbar
{/* DEMO command-dev-toolbar */}
```tsx
"use client";
import { useState } from "react";
import { Button, Chip, Kbd } from "@thenamespace/uikit";
import { Command } from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
const actions = [
["Create new file...", "lucide:file-plus-2"],
["Create new folder...", "lucide:folder-plus"],
["Assign to me", "lucide:user-round-pen"],
] as const;
const settings = [
["Preferences", "lucide:settings"],
["Change theme", "lucide:palette"],
["Keyboard shortcuts", "lucide:keyboard"],
] as const;
function Contents({ minimal = false }: { minimal?: boolean }) {
return (
<>
{minimal ? null : (
Home
)}
Esc <>No results found.>}>
{actions.map(([label, icon]) => (
{label}
))}
{minimal ? null : (
{settings.map(([label, icon]) => (
{label}
))}
)}
{minimal ? null : (
↑↓Navigate↵Select
)}
>
);
}
function Palette({
label = "Open Command Palette",
size = "md",
variant = "opaque",
children,
}: {
children?: React.ReactNode;
label?: string;
size?: "sm" | "md" | "lg";
variant?: "transparent" | "opaque" | "blur";
}) {
const [open, setOpen] = useState(false);
return (
<>
setOpen(true)}>
{label} ⌘ K{children ?? }
>
);
}
export const DemoDevToolbarExample = () => (
{[
"Feedback",
"Notifications",
"Feature Flags",
"Share Preview",
"Switch Branch",
"View Logs",
"Tracing",
].map((x) => (
{x}
{x[0]}
))}
);
```
## Launcher
{/* DEMO command-launcher */}
```tsx
"use client";
import { useState } from "react";
import { Button, Chip, Kbd } from "@thenamespace/uikit";
import { Command } from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
const actions = [
["Create new file...", "lucide:file-plus-2"],
["Create new folder...", "lucide:folder-plus"],
["Assign to me", "lucide:user-round-pen"],
] as const;
const settings = [
["Preferences", "lucide:settings"],
["Change theme", "lucide:palette"],
["Keyboard shortcuts", "lucide:keyboard"],
] as const;
function Contents({ minimal = false }: { minimal?: boolean }) {
return (
<>
{minimal ? null : (
Home
)}
Esc <>No results found.>}>
{actions.map(([label, icon]) => (
{label}
))}
{minimal ? null : (
{settings.map(([label, icon]) => (
{label}
))}
)}
{minimal ? null : (
↑↓Navigate↵Select
)}
>
);
}
function Palette({
label = "Open Command Palette",
size = "md",
variant = "opaque",
children,
}: {
children?: React.ReactNode;
label?: string;
size?: "sm" | "md" | "lg";
variant?: "transparent" | "opaque" | "blur";
}) {
const [open, setOpen] = useState(false);
return (
<>
setOpen(true)}>
{label} ⌘ K{children ?? }
>
);
}
export const DemoLauncherExample = () => (
{[
"Design Tool",
"Project Tracker",
"Team Chat",
"Calendar",
"Settings",
].map((x, i) => (
{x}
Application
))}
);
```
## Minimal
{/* DEMO command-minimal */}
```tsx
"use client";
import { useState } from "react";
import { Button, Chip, Kbd } from "@thenamespace/uikit";
import { Command } from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
const actions = [
["Create new file...", "lucide:file-plus-2"],
["Create new folder...", "lucide:folder-plus"],
["Assign to me", "lucide:user-round-pen"],
] as const;
const settings = [
["Preferences", "lucide:settings"],
["Change theme", "lucide:palette"],
["Keyboard shortcuts", "lucide:keyboard"],
] as const;
function Contents({ minimal = false }: { minimal?: boolean }) {
return (
<>
{minimal ? null : (
Home
)}
Esc <>No results found.>}>
{actions.map(([label, icon]) => (
{label}
))}
{minimal ? null : (
{settings.map(([label, icon]) => (
{label}
))}
)}
{minimal ? null : (
↑↓Navigate↵Select
)}
>
);
}
function Palette({
label = "Open Command Palette",
size = "md",
variant = "opaque",
children,
}: {
children?: React.ReactNode;
label?: string;
size?: "sm" | "md" | "lg";
variant?: "transparent" | "opaque" | "blur";
}) {
const [open, setOpen] = useState(false);
return (
<>
setOpen(true)}>
{label} ⌘ K{children ?? }
>
);
}
export const DemoMinimalExample = () => (
);
```
## Split View
{/* DEMO command-split-view */}
```tsx
"use client";
import { useState } from "react";
import { Button, Chip, Kbd } from "@thenamespace/uikit";
import { Command } from "@thenamespace/uikit";
import { Icon } from "@/demos/icon";
const actions = [
["Create new file...", "lucide:file-plus-2"],
["Create new folder...", "lucide:folder-plus"],
["Assign to me", "lucide:user-round-pen"],
] as const;
const settings = [
["Preferences", "lucide:settings"],
["Change theme", "lucide:palette"],
["Keyboard shortcuts", "lucide:keyboard"],
] as const;
function Contents({ minimal = false }: { minimal?: boolean }) {
return (
<>
{minimal ? null : (
Home
)}
Esc <>No results found.>}>
{actions.map(([label, icon]) => (
{label}
))}
{minimal ? null : (
{settings.map(([label, icon]) => (
{label}
))}
)}
{minimal ? null : (
↑↓Navigate↵Select
)}
>
);
}
function Palette({
label = "Open Command Palette",
size = "md",
variant = "opaque",
children,
}: {
children?: React.ReactNode;
label?: string;
size?: "sm" | "md" | "lg";
variant?: "transparent" | "opaque" | "blur";
}) {
const [open, setOpen] = useState(false);
return (
<>
setOpen(true)}>
{label} ⌘ K{children ?? }
>
);
}
function Split() {
const [selected, setSelected] = useState("Button");
const items = [
"Button",
"Input",
"Radio",
"Chip",
"Slider",
"Avatar",
"Switch",
];
return (
);
}
export const DemoBackdropVariantsExample = () => ;
```
## CSS Classes
### Base & Variant Classes
- `.command__backdrop` — Fixed fullscreen overlay behind the command palette. Centered flex layout with enter/exit animations.
- `.command__backdrop--transparent` — Fully transparent backdrop.
- `.command__backdrop--opaque` — Dark semi-transparent backdrop (`bg-black/50`).
- `.command__backdrop--blur` — Dark backdrop with `backdrop-blur-md`.
### Size Modifier Classes
- `.command__dialog--sm` — Small dialog (`max-w-sm`, max-height `300px`).
- `.command__dialog--md` — Medium dialog (`max-w-lg`, max-height `356px`). Default.
- `.command__dialog--lg` — Large dialog (`max-w-xl`, max-height `440px`).
### Element Classes
- `.command__container` — Positioning wrapper centering the dialog at `15vh` from top. Has slide + zoom enter/exit animations.
- `.command__dialog` — The command palette box. Rounded with `bg-overlay`, `shadow-overlay`, and animated height transitions.
- `.command__input-group` — Search field container with bottom border. Flex row holding prefix, input, and suffix.
- `.command__input-group-prefix` — Leading content area (e.g., search icon) with muted color.
- `.command__input-group-suffix` — Trailing content area with muted color.
- `.command__input-group-clear-button` — Clear button that hides when input is empty.
- `.command__header` — Content area above the input (e.g., breadcrumbs or tabs).
- `.command__list` — Scrollable command list with `overflow-y: auto` and `overscroll-contain`.
- `.command__item` — Individual command entry. Rounded with gap for icon and keyboard shortcut.
- `.command__group` — Section grouping with top margin between groups.
- `.command__group-heading` — Section label with muted color and small font.
- `.command__separator` — Horizontal divider between groups (`bg-separator`).
- `.command__footer` — Bottom bar with border-top, muted text, and `bg-default/50` background.
- `.command__empty` — Empty state centered text shown when no results match.
### Interactive States
- **Entering**: `[data-entering="true"]` on `.command__backdrop` — `fade-in` animation (150ms). On `.command__container` — `fade-in` + `zoom-in-95` + `slide-in-from-top` (200ms).
- **Exiting**: `[data-exiting="true"]` on `.command__backdrop` — `fade-out` (100ms). On `.command__container` — `fade-out` + `zoom-out-95` (100ms).
- **Item hover**: `[data-hovered="true"]` on `.command__item` — applies `bg-default`.
- **Item focused**: `[data-focused="true"]` on `.command__item` — applies `bg-default`.
- **Item pressed**: `[data-pressed="true"]` on `.command__item` — applies `bg-default-hover`.
- **Item disabled**: `[data-disabled="true"]` on `.command__item` — reduced opacity, default cursor.
- **Clear button hidden**: `[data-empty="true"]` on `.command__input-group` — hides the clear button.
- **Reduced motion**: `motion-reduce:animate-none` on all animated elements.
## API Reference
### Command
The root provider. Sets up the component context.
| Prop | Type | Default | Description |
| ---------- | ----------- | ------- | ------------------------------- |
| `children` | `ReactNode` | — | Content of the command palette. |
### Command.Backdrop
The fullscreen overlay. Must wrap `Command.Container`.
| Prop | Type | Default | Description |
| --------------- | ------------------------------------- | ---------- | ------------------------------------------------- |
| `isDismissable` | `boolean` | `true` | Whether clicking the backdrop closes the palette. |
| `variant` | `"opaque" \| "blur" \| "transparent"` | `"opaque"` | Backdrop visual style. |
Also supports all RAC [ModalOverlay](https://react-spectrum.adobe.com/react-aria/Modal.html) props.
### Command.Container
Positioning wrapper centering the dialog. Must be placed inside `Command.Backdrop`.
| Prop | Type | Default | Description |
| ------ | ---------------------- | ------- | --------------------------- |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the command dialog. |
Also supports all RAC [Modal](https://react-spectrum.adobe.com/react-aria/Modal.html) props.
### Command.Dialog
The command palette box. Wraps an internal `Autocomplete` for filtering.
| Prop | Type | Default | Description |
| ------------------- | ---------------------------------------------------- | ------------------------- | ------------------------------------------ |
| `defaultInputValue` | `string` | — | Default search input value (uncontrolled). |
| `inputValue` | `string` | — | Controlled search input value. |
| `onInputChange` | `(value: string) => void` | — | Callback when search input changes. |
| `filter` | `(textValue: string, inputValue: string) => boolean` | Case-insensitive contains | Custom filter function. |
Also supports all RAC [Dialog](https://react-spectrum.adobe.com/react-aria/Dialog.html) props.
### Command.Header
Content area above the input (e.g., breadcrumbs or navigation tabs). Renders a plain `
`.
### Command.InputGroup
The search field container wrapping prefix, input, and suffix elements.
| Prop | Type | Default | Description |
| ----------- | --------- | ------- | ---------------------------------------------------- |
| `autoFocus` | `boolean` | `true` | Whether the input is focused when the palette opens. |
Also supports all RAC [SearchField](https://react-spectrum.adobe.com/react-aria/SearchField.html) props.
### Command.InputGroup.Prefix
Leading content inside the input group (e.g., a search icon). Renders a plain `
`.
### Command.InputGroup.Input
The text input element for searching commands.
| Prop | Type | Default | Description |
| ------------- | -------- | ---------------------- | ----------------- |
| `placeholder` | `string` | `"Search commands..."` | Placeholder text. |
Also supports all RAC [Input](https://react-spectrum.adobe.com/react-aria/TextField.html) props.
### Command.InputGroup.Suffix
Trailing content inside the input group. Renders a plain `
`.
### Command.InputGroup.ClearButton
A close button that clears the search input. Automatically hidden when the input is empty.
Also supports all [Namespace UIKit CloseButton](https://namespace.com/docs/react/components/close-button) props.
### Command.List
The scrollable list of command items. Backed by RAC `Menu`.
| Prop | Type | Default | Description |
| ------------------ | ----------------- | ------- | ----------------------------------------------- |
| `renderEmptyState` | `() => ReactNode` | — | Custom empty state content when no items match. |
Also supports all RAC [Menu](https://react-spectrum.adobe.com/react-aria/Menu.html) props.
### Command.Item
An individual command entry. Supports icons, labels, and keyboard shortcuts.
Also supports all RAC [MenuItem](https://react-spectrum.adobe.com/react-aria/Menu.html#menuitem) props.
### Command.Group
Groups related command items under a heading.
| Prop | Type | Default | Description |
| --------- | ----------- | ------- | ---------------------------- |
| `heading` | `ReactNode` | — | Heading label for the group. |
Also supports all RAC [MenuSection](https://react-spectrum.adobe.com/react-aria/Menu.html#menusection) props.
### Command.Separator
A horizontal divider between groups.
Also supports all RAC [Separator](https://react-spectrum.adobe.com/react-aria/Separator.html) props.
### Command.Footer
Content area below the list (e.g., keyboard shortcut hints). Renders a plain `
`.
# Composed Chart
**Category**: components
**URL**: https://namespace-uikit.vercel.app/docs/components/composed-chart
**Source**: https://github.com/thenamespace/uikit/blob/main/apps/docs/content/docs/components/composed-chart.mdx
> A composed chart that combines Bar, Line, and Area series in a single cartesian chart for multi-metric dashboards.
## Usage
{/* DEMO composed-chart-default */}
```tsx
"use client";
import { ComposedChart } from "@thenamespace/uikit";
import { Card } from "@thenamespace/uikit/card";
import { ChartTooltip } from "@thenamespace/uikit/chart-tooltip";
function Legend({
items,
}: {
items: ReadonlyArray<{ color: string; label: string }>;
}) {
return (