docs(ui): expand bilingual component guides
This commit is contained in:
@@ -1,30 +1,103 @@
|
||||
---
|
||||
title: Choose components
|
||||
description: Select primitives by responsibility instead of importing a single monolithic component index.
|
||||
title: Component catalog
|
||||
description: Find component entry points by responsibility and understand the local Base UI composition model.
|
||||
order: 11
|
||||
toc:
|
||||
- id: forms
|
||||
title: Forms and input
|
||||
- id: overlays
|
||||
title: Overlays and menus
|
||||
- id: content
|
||||
- id: composition-model
|
||||
title: Composition model
|
||||
- id: actions-and-forms
|
||||
title: Actions and forms
|
||||
- id: overlays-and-navigation
|
||||
title: Overlays and navigation
|
||||
- id: content-and-feedback
|
||||
title: Content and feedback
|
||||
- id: layout-and-data
|
||||
title: Layout and data
|
||||
- id: icons
|
||||
title: Icons
|
||||
---
|
||||
|
||||
## Forms and input {#forms}
|
||||
## Composition model {#composition-model}
|
||||
|
||||
Use `Button`, `Input`, `Textarea`, `Field`, and `Label` for ordinary forms. Add `Checkbox`, `RadioGroup`, `Switch`, or `Slider` for choices, and `Select`, `Combobox`, `Command`, or `Calendar` for richer selection.
|
||||
The components follow shadcn/ui's model of composing primitives from editable source, with the Base UI implementation selected in this workspace. A component is usually split into Root, Trigger, Content, Item, and related parts. The underlying primitive owns state and accessibility, while Tailwind classes and `data-slot` expose presentation.
|
||||
|
||||
## Overlays and menus {#overlays}
|
||||
Base UI uses `render` to compose a custom element, rather than the `asChild` prop commonly seen in Radix examples:
|
||||
|
||||
`Dialog`, `AlertDialog`, `Sheet`, and `Drawer` cover modal surfaces. `Popover`, `HoverCard`, and `Tooltip` provide anchored information, while the menu modules cover context, dropdown, menubar, and navigation patterns.
|
||||
```tsx
|
||||
import { Button } from "@workspace/ui/components/button"
|
||||
import { Dialog, DialogTrigger } from "@workspace/ui/components/dialog"
|
||||
|
||||
## Content and feedback {#content}
|
||||
;<Dialog>
|
||||
<DialogTrigger render={<Button variant="outline" />}>
|
||||
Edit profile
|
||||
</DialogTrigger>
|
||||
</Dialog>
|
||||
```
|
||||
|
||||
Cards, items, tables, charts, progress, skeletons, spinners, empty states, messages, and toasts provide the common display vocabulary. Accordion, Collapsible, Tabs, Carousel, and Pagination organize larger content sets.
|
||||
Use `render` only when replacing the underlying element. Pass ordinary content as children.
|
||||
|
||||
## Actions and forms {#actions-and-forms}
|
||||
|
||||
| Goal | Component entry points |
|
||||
| --------------------------- | -------------------------------------------------- |
|
||||
| Buttons and grouped actions | `button`, `button-group`, `toggle`, `toggle-group` |
|
||||
| Text input | `input`, `textarea`, `input-group`, `input-otp` |
|
||||
| Field structure | `field`, `label` |
|
||||
| Boolean and single choice | `checkbox`, `switch`, `radio-group` |
|
||||
| Range and progress | `slider`, `progress` |
|
||||
| Options and commands | `native-select`, `select`, `combobox`, `command` |
|
||||
| Dates | `calendar` |
|
||||
|
||||
Prefer `NativeSelect` for simple, mobile-friendly choices that do not need a custom popup. Choose `Combobox`, `Select`, or `Command` when the interaction needs search, custom items, or command behavior.
|
||||
|
||||
## Overlays and navigation {#overlays-and-navigation}
|
||||
|
||||
| Goal | Component entry points |
|
||||
| ------------------------------ | -------------------------------------------------------- |
|
||||
| Modal confirmation and editing | `alert-dialog`, `dialog`, `sheet`, `drawer` |
|
||||
| Anchored content | `popover`, `hover-card`, `tooltip`, `anchored-surface` |
|
||||
| Menus | `dropdown-menu`, `context-menu`, `menubar` |
|
||||
| Page navigation | `breadcrumb`, `navigation-menu`, `pagination`, `sidebar` |
|
||||
|
||||
Dialog, Sheet, and Drawer expose controlled state and composable parts. Use `AlertDialog` for consequential destructive actions, `Tooltip` for brief descriptions, and `Popover` for an anchored panel containing interactive controls.
|
||||
|
||||
## Content and feedback {#content-and-feedback}
|
||||
|
||||
| Goal | Component entry points |
|
||||
| ------------------------- | ----------------------------------------------------- |
|
||||
| Containers and states | `card`, `item`, `empty`, `alert`, `badge`, `marker` |
|
||||
| Loading and notifications | `skeleton`, `spinner`, `toast` |
|
||||
| Messaging UI | `message`, `bubble`, `attachment`, `message-scroller` |
|
||||
| Sectioned content | `accordion`, `collapsible`, `tabs`, `carousel` |
|
||||
|
||||
`Message` owns participant layout, alignment, and metadata; `Bubble` owns the message surface; `Attachment` expresses an upload lifecycle; and `MessageScroller` handles follow mode and jump controls. They are presentation primitives and do not own conversation data.
|
||||
|
||||
## Layout and data {#layout-and-data}
|
||||
|
||||
| Goal | Component entry points |
|
||||
| -------------- | ------------------------------------------------------- |
|
||||
| Data display | `table`, `chart` |
|
||||
| Layout | `separator`, `aspect-ratio`, `resizable`, `scroll-area` |
|
||||
| Direction | `direction` |
|
||||
| Keyboard hints | `kbd` |
|
||||
| Avatars | `avatar` |
|
||||
|
||||
The chart module wraps Recharts containers, tooltips, legends, and style mappings without choosing an application data model. `DirectionProvider` re-exports Base UI's direction context; the page should still synchronize the HTML `dir` attribute.
|
||||
|
||||
## Icons {#icons}
|
||||
|
||||
Import named icons from `@workspace/ui/components/icon`. The module centralizes the `@icones/react` vocabulary so applications and packages use the same icon source.
|
||||
Import named icons from the local Icones adapter:
|
||||
|
||||
```tsx
|
||||
import { SearchIcon, SettingsIcon } from "@workspace/ui/components/icon"
|
||||
```
|
||||
|
||||
Components provide a default size to SVGs that do not have an explicit size class. Icon buttons still require an accessible name:
|
||||
|
||||
```tsx
|
||||
<Button size="icon" aria-label="Search">
|
||||
<SearchIcon aria-hidden="true" />
|
||||
</Button>
|
||||
```
|
||||
|
||||
Do not reintroduce `lucide-react` in new components. Register additional icons through `createIcon` in `components/icon.tsx` so the workspace keeps one icon path.
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
title: Feedback and messaging
|
||||
description: Configure Toast and compose messaging interfaces from Message, Bubble, Attachment, and MessageScroller.
|
||||
order: 13
|
||||
toc:
|
||||
- id: toast-provider
|
||||
title: Toast Provider
|
||||
- id: send-toast
|
||||
title: Send a toast
|
||||
- id: message-composition
|
||||
title: Message composition
|
||||
- id: attachments
|
||||
title: Attachment states
|
||||
- id: scrolling
|
||||
title: Message scrolling
|
||||
---
|
||||
|
||||
## Toast Provider {#toast-provider}
|
||||
|
||||
Mount one `Toaster` near the application root:
|
||||
|
||||
```tsx
|
||||
import { Toaster } from "@workspace/ui/components/toast"
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<>
|
||||
<Routes />
|
||||
<Toaster />
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
The default viewport is fixed to the bottom on small screens and the bottom-right on larger screens. Toasts support stacking, expansion, swipe dismissal, keyboard focus, and icons for `success`, `info`, `warning`, `error`, and `loading` types.
|
||||
|
||||
## Send a toast {#send-toast}
|
||||
|
||||
Use the manager exported by the module:
|
||||
|
||||
```tsx
|
||||
import { Button } from "@workspace/ui/components/button"
|
||||
import { toast } from "@workspace/ui/components/toast"
|
||||
|
||||
;<Button
|
||||
onClick={() =>
|
||||
toast.add({
|
||||
title: "Saved",
|
||||
description: "Your profile has been updated.",
|
||||
type: "success",
|
||||
})
|
||||
}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
```
|
||||
|
||||
When notifications need an isolated scope, create a manager with `createToastManager()` and pass it to both `Toaster` and the caller. The default accessible name of the close button comes from the UI localization context.
|
||||
|
||||
## Message composition {#message-composition}
|
||||
|
||||
```tsx
|
||||
import {
|
||||
Message,
|
||||
MessageContent,
|
||||
MessageFooter,
|
||||
MessageGroup,
|
||||
} from "@workspace/ui/components/message"
|
||||
import { Bubble, BubbleContent } from "@workspace/ui/components/bubble"
|
||||
|
||||
;<MessageGroup>
|
||||
<Message align="end">
|
||||
<MessageContent>
|
||||
<Bubble align="end" variant="tinted">
|
||||
<BubbleContent>Tomorrow at three works for me.</BubbleContent>
|
||||
</Bubble>
|
||||
<MessageFooter>Read · 14:32</MessageFooter>
|
||||
</MessageContent>
|
||||
</Message>
|
||||
</MessageGroup>
|
||||
```
|
||||
|
||||
Keep message IDs, authors, delivery state, and actions in the product layer. The UI primitives derive layout only from props and `data-*` state.
|
||||
|
||||
## Attachment states {#attachments}
|
||||
|
||||
`Attachment` supports `idle`, `uploading`, `processing`, `error`, and `done`. `AttachmentMedia`, `AttachmentTitle`, `AttachmentDescription`, and `AttachmentActions` adapt their presentation to the state; the application still owns progress and retry behavior.
|
||||
|
||||
Use the default `orientation="horizontal"` for rows and `orientation="vertical"` for thumbnail grids. `AttachmentGroup` adds horizontal scrolling and snap behavior for a collection.
|
||||
|
||||
## Message scrolling {#scrolling}
|
||||
|
||||
Keep `MessageScrollerProvider`, `MessageScroller`, `MessageScrollerViewport`, and `MessageScrollerContent` in that hierarchy. Wrap each message in `MessageScrollerItem`, adding `scrollAnchor` to the item that should anchor follow mode. `MessageScrollerButton direction="end"` reveals and hides itself from the current scroll state.
|
||||
|
||||
Do not assign `scrollTop` directly when appending messages. Use the follow and visibility state exposed by these primitives so a user reading older messages is not forced back to the bottom.
|
||||
@@ -0,0 +1,113 @@
|
||||
---
|
||||
title: Overlays and positioning
|
||||
description: Compose Dialog and Popover with Base UI render semantics and the local AnchoredSurface.
|
||||
order: 12
|
||||
toc:
|
||||
- id: dialog
|
||||
title: Dialog
|
||||
- id: popover
|
||||
title: Popover
|
||||
- id: anchored-surface
|
||||
title: Continuous tail
|
||||
- id: positioning
|
||||
title: Custom positioning
|
||||
- id: choosing-an-overlay
|
||||
title: Choose an overlay
|
||||
---
|
||||
|
||||
## Dialog {#dialog}
|
||||
|
||||
```tsx
|
||||
import { Button } from "@workspace/ui/components/button"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@workspace/ui/components/dialog"
|
||||
|
||||
export function ProfileDialog() {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger render={<Button variant="outline" />}>
|
||||
Edit profile
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Edit profile</DialogTitle>
|
||||
<DialogDescription>Update your public information.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div>Form content</div>
|
||||
<DialogFooter>
|
||||
<Button type="submit">Save</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
`DialogContent` already includes the portal, overlay, and default close button. The title and description connect to the underlying accessibility attributes, so do not replace them with unstructured `div` elements.
|
||||
|
||||
## Popover {#popover}
|
||||
|
||||
```tsx
|
||||
import { Button } from "@workspace/ui/components/button"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverDescription,
|
||||
PopoverTitle,
|
||||
PopoverTrigger,
|
||||
} from "@workspace/ui/components/popover"
|
||||
|
||||
;<Popover>
|
||||
<PopoverTrigger render={<Button variant="outline" />}>
|
||||
Open settings
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end">
|
||||
<PopoverTitle>Display settings</PopoverTitle>
|
||||
<PopoverDescription>Choose the list density.</PopoverDescription>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
```
|
||||
|
||||
The local API continues to forward Base UI Popup and Positioner props. Pass `open` and `onOpenChange` to `Popover` when controlled state is required.
|
||||
|
||||
## Continuous tail {#anchored-surface}
|
||||
|
||||
The local `showArrow` is more than a triangular SVG. It renders `PopoverContent` through `AnchoredSurface`, producing one rounded surface with a continuous curved tail:
|
||||
|
||||
```tsx
|
||||
<PopoverContent
|
||||
side="bottom"
|
||||
showArrow={{ cornerRadius: "2xl", tailSize: "sm" }}
|
||||
className="w-80 p-0"
|
||||
viewportClassName="max-h-72 p-4"
|
||||
>
|
||||
{content}
|
||||
</PopoverContent>
|
||||
```
|
||||
|
||||
The outer surface remains `overflow: visible` so the tail is not clipped. Scrolling happens inside `data-slot="popover-viewport"`. Use `viewportClassName` when constraining content height or applying content padding.
|
||||
|
||||
`AnchoredSurface` can also render on its own, but it is visual only: it does not own anchor measurement, collision detection, focus, or a portal.
|
||||
|
||||
## Custom positioning {#positioning}
|
||||
|
||||
`PopoverContent` additionally exposes `anchor`, `positionMethod`, `arrowPadding`, `alignOffset`, and `sideOffset`. Pass virtual or custom anchors through the shared component instead of rebuilding the Base UI primitives.
|
||||
|
||||
For control outside React, create a handle with `createPopoverHandle<Payload>()` and connect it to the Root using Base UI's handle pattern.
|
||||
|
||||
## Choose an overlay {#choosing-an-overlay}
|
||||
|
||||
- Block background interaction with `Dialog` or `AlertDialog`.
|
||||
- Use `Sheet` for a task surface entering from a screen edge and `Drawer` for a touch-oriented mobile panel.
|
||||
- Use `Popover` for interactive content attached to a trigger.
|
||||
- Use `HoverCard` for a preview revealed by hover or focus.
|
||||
- Use `Tooltip` for short, non-interactive descriptions.
|
||||
|
||||
Compare basic usage with the [shadcn Popover documentation](https://ui.shadcn.com/docs/components/base/popover), but keep the Base UI `render` composition syntax.
|
||||
@@ -1,39 +1,91 @@
|
||||
---
|
||||
title: Project setup
|
||||
description: Import the global stylesheet and begin with explicit component subpaths.
|
||||
description: Configure the workspace dependency, global styles, Tailwind scanning, and the shadcn CLI.
|
||||
order: 10
|
||||
toc:
|
||||
- id: import-styles
|
||||
title: Import styles
|
||||
- id: import-a-component
|
||||
title: Import a component
|
||||
- id: entry-points
|
||||
title: Entry points
|
||||
- id: dependency
|
||||
title: Add the dependency
|
||||
- id: global-styles
|
||||
title: Global styles
|
||||
- id: imports
|
||||
title: Explicit imports
|
||||
- id: shadcn-cli
|
||||
title: shadcn CLI
|
||||
- id: browser-components
|
||||
title: Browser components
|
||||
- id: verify
|
||||
title: Verify the setup
|
||||
---
|
||||
|
||||
## Import styles {#import-styles}
|
||||
## Add the dependency {#dependency}
|
||||
|
||||
Import the global stylesheet once at the application entry:
|
||||
Applications reference the UI package through the workspace protocol:
|
||||
|
||||
```ts
|
||||
import "@workspace/ui/globals.css"
|
||||
```
|
||||
|
||||
It provides the shared Tailwind layers, design variables, font setup, and utilities expected by the components.
|
||||
|
||||
## Import a component {#import-a-component}
|
||||
|
||||
```tsx
|
||||
import { Button } from "@workspace/ui/components/button"
|
||||
|
||||
export function SaveButton() {
|
||||
return <Button>Save</Button>
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@workspace/ui": "workspace:*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Entry points {#entry-points}
|
||||
The applications in this repository are already configured this way. The package is currently private to the workspace and does not need to be installed from npm.
|
||||
|
||||
- `@workspace/ui/components/*` exposes one component module.
|
||||
- `@workspace/ui/hooks/*` exposes reusable interactions and media-query state.
|
||||
- `@workspace/ui/lib/utils` exposes shared class-name composition.
|
||||
- `@workspace/ui/locales/*` exposes language-specific catalogs.
|
||||
## Global styles {#global-styles}
|
||||
|
||||
Import the stylesheet once from the application's global CSS:
|
||||
|
||||
```css
|
||||
@import "@workspace/ui/globals.css";
|
||||
```
|
||||
|
||||
This entry loads Tailwind CSS, shadcn's Tailwind extension, animation utilities, the Inter Variable font, semantic colors, radius variables, and base styles. Themes switch through `.ui:light` and `.ui:dark` on the root element; component code should not copy these variables.
|
||||
|
||||
The `@source` directives in `globals.css` cover this repository's `apps` and component directories. Update those paths if the package moves into another directory layout, or production builds may omit utilities used by components.
|
||||
|
||||
## Explicit imports {#imports}
|
||||
|
||||
There is no aggregated barrel. Import concrete subpaths so dependencies remain visible and client bundles do not grow accidentally:
|
||||
|
||||
```tsx
|
||||
import { Button } from "@workspace/ui/components/button"
|
||||
import { SaveIcon } from "@workspace/ui/components/icon"
|
||||
import { useIsMobile } from "@workspace/ui/hooks/use-breakpoint"
|
||||
import { cn } from "@workspace/ui/lib/utils"
|
||||
```
|
||||
|
||||
Public entry points include:
|
||||
|
||||
- `@workspace/ui/components/*` for components and their local types.
|
||||
- `@workspace/ui/hooks/*` for breakpoint and ripple interactions.
|
||||
- `@workspace/ui/locales` for supported locales and message ID types.
|
||||
- `@workspace/ui/locales/en-US` and `@workspace/ui/locales/zh-Hans` for messages and calendar locales.
|
||||
- `@workspace/ui/globals.css` for global styles.
|
||||
|
||||
## shadcn CLI {#shadcn-cli}
|
||||
|
||||
Run the command from the repository root:
|
||||
|
||||
```sh
|
||||
bunx shadcn@latest add button -c apps/web
|
||||
```
|
||||
|
||||
The application and UI package `components.json` files agree on `base-vega`, neutral, CSS variables, the Lucide vocabulary, and RTL output. Their aliases place generated files under `packages/ui/src/components`, following shadcn's official [monorepo workflow](https://ui.shadcn.com/docs/monorepo).
|
||||
|
||||
Always inspect the diff after generation. The generator does not know about this workspace's Icones layer, localization, ripple behavior, or Popover extensions and can overwrite them when updating an existing component. See the official [`components.json` reference](https://ui.shadcn.com/docs/components-json) for the meaning of each setting.
|
||||
|
||||
## Browser components {#browser-components}
|
||||
|
||||
Most interactive components depend on events, portals, or browser APIs. Consumers using React Server Components should import them from their own client boundary. This workspace has `rsc: false`; component files do not receive a framework-specific directive globally, although a few components include `"use client"` when they require it.
|
||||
|
||||
## Verify the setup {#verify}
|
||||
|
||||
After changing a component or configuration, run:
|
||||
|
||||
```sh
|
||||
bun run --cwd packages/ui typecheck
|
||||
bun run lint
|
||||
bun run format:check
|
||||
```
|
||||
|
||||
When a change affects consumption, also build the application or docs so Tailwind scanning is exercised, then verify light, dark, and RTL modes.
|
||||
|
||||
Reference in New Issue
Block a user