--- name: button-usage description: > Use after component-usage-ux when an app needs @techsio/ui-kit Button for actions, including correct variant, theme, size, loading state, icon props, and token-first styling rules. metadata: type: "core" library: "@techsio/ui-kit" library_version: "0.3.2" component: "Button" component_version: "0.3.2" requires: "component-usage-ux app-token-overrides ux-guidelines" sources: "libs/ui/src/atoms/button.tsx libs/ui/src/tokens/components/atoms/_button.css libs/ui/stories/atoms/button.stories.tsx libs/ui/src/atoms/button.figma.ts" --- # @techsio/ui-kit Button Usage Use Button for in-place actions. Use `LinkButton` for navigation that should look like a button. ## UX/UI guidelines House rules come from the `ux-guidelines` skill (writing, formatting, states, where actions and feedback live). This section applies them to `Button`. **Use it when** - Any action that changes state on the current page: save, create, delete, open a dialog, apply filters. - Form submission and dialog/drawer footers. - Page-level commands in the page header (`New product`). **Use something else when** | Need | Use instead | | --- | --- | | Navigate to a URL, styled as a button | LinkButton | | Inline navigation in text | Link | | Compact repeated icon action | ActionIcon | | More than three related commands | Menu behind one Button | | Toggle a setting on/off | Switch | **Do** - One `variant="primary"` per surface; secondary actions use `secondary` / `outlined` / `borderless`. - Order groups `[Cancel] [Primary]` — primary last, at the end of the container (ux-guidelines/feedback-and-actions). - Use `variant="danger"` only for destructive actions and keep them away from Save. - Show progress with `isLoading` + `loadingText` (`Saving…`) on the button that started the action. - Add an `icon` only when it speeds recognition (`+` for New, trash for Delete); keep the text. **Don't** - Use `OK`, `Yes`, `Submit`, `Confirm` or `Click here` as labels. - Put two primary buttons side by side. - Disable a submit button when the user can't see why (ux-guidelines/states#disabled). - Fake a link with `onClick={() => router.push()}` — use LinkButton. - Change the label to a result (`Saved!`); confirm with a Toast instead. **Copy and states** - Verb + object in sentence case: `New product`, `Create product`, `Save changes`, `Delete product`, `Discard changes` (full table in ux-guidelines/ux-writing#button-labels). - `Cancel` leaves a form without saving; `Close` closes something with no pending changes. ## Setup ```tsx import { Button } from "@techsio/ui-kit/atoms/button" ``` Supported visual props from `src/atoms/button.tsx`: ```text variant: primary | secondary | tertiary | danger | warning theme: solid | light | borderless | outlined | unstyled size: sm | md | lg | current block: boolean uppercase: boolean isLoading: boolean loadingText: string icon: IconType iconPosition: left | right iconSize: xs | sm | md | lg | xl | 2xl | current ``` ## Core Patterns ### Choose variant from action semantics ```text primary -> main positive action in the current scope secondary -> secondary action with normal emphasis tertiary -> quiet tertiary action danger -> destructive action such as delete/remove/cancel order warning -> risky but not destructive action ``` ### Choose theme from emphasis ```text solid -> strongest emphasis light -> filled but softer emphasis outlined -> boundary/emphasis without solid fill borderless -> quiet action, similar to "ghost" unstyled -> only when composing inside another component surface ``` There is no `variant="ghost"`. Use `theme="borderless"` for that intent. ### Let Button own its visual styling ```tsx ``` Do not add background, foreground, padding, border, radius, or font classes that duplicate Button tokens. If the app needs different colors or sizing, change app token overrides first. ### Use loading props instead of custom disabling ```tsx ``` Use the component API for loading and disabled state instead of wrapping the button in a conditional spinner. ## Common Mistakes ### HIGH Native button Wrong: ```tsx ``` Correct: ```tsx ``` Source: libs/ui/src/atoms/button.tsx ### HIGH Hallucinated ghost variant Wrong: ```tsx ``` Correct: ```tsx ``` Source: libs/ui/src/atoms/button.tsx ### HIGH Duplicated component tokens in className Wrong: ```tsx ``` Correct: ```tsx ``` If Button danger should look different in the app, override `--color-button-*` or related semantic tokens in CSS. Source: libs/ui/src/tokens/components/atoms/_button.css ### MEDIUM Navigation rendered as Button Wrong: ```tsx ``` Correct: ```tsx Products ``` Use Button for actions and LinkButton for navigation. ## Validation Commands ```sh rg -n "]*className=.*(bg-|text-|px-|py-|rounded-|border-)" apps rg -n "]*onClick=.*router\\.push" apps rg -n "isLoading|loadingText" apps ```