# @f0rbit/ui - SolidJS Component Library A minimal, composable UI component library for SolidJS. ## Installation ```bash bun add @f0rbit/ui ``` ```tsx import "@f0rbit/ui/styles"; import { Button, Card } from "@f0rbit/ui"; ``` ## Components ### Button A clickable button with multiple variants and sizes. ```tsx import { Button } from "@f0rbit/ui"; ``` Props: - `variant`: "primary" | "secondary" | "ghost" | "danger" (default: "primary") — Visual style variant - `size`: "sm" | "md" | "lg" (default: "md") — Button size - `icon`: boolean (default: false) — Render as square icon-only button - `label`: string — Accessible label for icon buttons (sets aria-label) - `loading`: boolean (default: false) — Show loading spinner - `disabled`: boolean (default: false) — Disable the button Example: ```tsx ``` Accessibility: - Always use the label prop for icon-only buttons (sets aria-label) - Loading state announces to screen readers via aria-busy - Disabled buttons are focusable but not interactive Avoid: - Forgetting label prop on icon buttons - screen readers won't announce the purpose - Using loading without disabling form submission - can cause double submits - Using ghost variant for primary actions - use primary for main CTAs ### Badge A small label for categorization or status indication. ```tsx import { Badge } from "@f0rbit/ui"; ``` Props: - `variant`: "default" | "success" | "error" | "warning" | "info" | "accent" (default: "default") — Visual style variant Example: ```tsx Default ``` Accessibility: - Badge is purely visual - not announced separately by screen readers - Content inside Badge is read as normal text Avoid: - Using Badge for interactive elements - use Button instead - Relying on color alone to convey meaning - always include text ### Card A container component for grouping related content. ```tsx import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@f0rbit/ui"; ``` Props: - `interactive`: boolean (default: false) — Enable hover effects for clickable cards Example: ```tsx Card Title Card description text Main content goes here Footer content ``` Accessibility: - Interactive cards should have role='button' or be wrapped in a link - Use CardTitle for proper heading hierarchy Avoid: - Using interactive without adding click handler or wrapping in link - Nesting interactive cards - avoid nested clickable elements - Missing CardHeader/CardContent structure - use sub-components for consistency ### Modal A dialog overlay for focused user interactions. ```tsx import { Modal, ModalHeader, ModalTitle, ModalBody, ModalFooter } from "@f0rbit/ui"; ``` Props: - `open`: boolean — Controls modal visibility - `onClose`: () => void — Callback when modal is closed Example: ```tsx const [open, setOpen] = createSignal(false); setOpen(false)}> Modal Title Modal content ``` Accessibility: - Focus is trapped inside modal when open - ESC key closes the modal - Clicking backdrop closes the modal - Uses aria-modal and role='dialog' - ModalTitle is announced as the dialog label Avoid: - Forgetting onClose handler - modal won't close on backdrop click or ESC - Not providing ModalTitle - screen readers need a label for the dialog - Putting autofocus elements without considering keyboard users ### Dropdown A floating menu triggered by a button or element. ```tsx import { Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, DropdownDivider } from "@f0rbit/ui"; ``` Props: - `children`: JSX.Element — Dropdown content (trigger and menu) Example: ```tsx console.log("Item 1")}>Item 1 console.log("Item 2")}>Item 2 console.log("Item 3")}>Item 3 ``` Accessibility: - Menu opens on click, closes on outside click or ESC - Arrow keys navigate between items - Enter/Space activates focused item Avoid: - Putting complex interactive content in DropdownItem - keep items simple - Using for navigation - consider a proper nav component instead - Forgetting DropdownTrigger wrapper around the trigger element ### Collapsible An expandable/collapsible content section. ```tsx import { Collapsible } from "@f0rbit/ui"; ``` Props: - `trigger`: JSX.Element | string — Content shown in the trigger area - `defaultOpen`: boolean (default: false) — Initial open state (uncontrolled) - `open`: boolean — Controlled open state - `onOpenChange`: (open: boolean) => void — Callback when open state changes Example: ```tsx

This content is collapsible.

``` Accessibility: - Trigger is keyboard accessible (Enter/Space to toggle) - Uses aria-expanded to announce state - Content region is properly associated with trigger Avoid: - Using both defaultOpen and open props - pick controlled or uncontrolled - Complex interactive content in trigger - keep trigger simple ### Stepper A multi-step progress indicator. ```tsx import { Stepper, Step } from "@f0rbit/ui"; ``` Props: - `orientation`: "horizontal" | "vertical" (default: "horizontal") — Layout direction of steps Example: ```tsx ``` Accessibility: - Steps announce their status via aria-current for current step - Completed steps show checkmark for visual confirmation Avoid: - Making Step indicators clickable without implementing navigation - Not updating status props when step changes ### Step Individual step within a Stepper component. ```tsx import { Step } from "@f0rbit/ui"; ``` Props: - `title`: string — Step title text - `description`: string — Optional description below the title - `icon`: JSX.Element — Custom icon for the step indicator - `status`: "completed" | "current" | "upcoming" (default: "upcoming") — Current status of the step Example: ```tsx ``` ### Input A text input field for single-line user input. ```tsx import { Input } from "@f0rbit/ui"; ``` Props: - `error`: boolean (default: false) — Show error styling - `disabled`: boolean (default: false) — Disable the input - `placeholder`: string — Placeholder text Example: ```tsx ``` Accessibility: - Always pair with FormField for proper label association - Error state is visual only - use FormField error prop for error message - Use aria-describedby for additional context if not using FormField Avoid: - Using Input without FormField - missing accessible label - Setting error={true} without showing error message - Forgetting to match id prop with FormField id ### Textarea A multi-line text input field. ```tsx import { Textarea } from "@f0rbit/ui"; ``` Props: - `error`: boolean (default: false) — Show error styling - `disabled`: boolean (default: false) — Disable the textarea - `placeholder`: string — Placeholder text Example: ```tsx