Refine frontend contrib guides
Apply small follow-up edits to the frontend documentation: the AGENTS index, the forms, react-components, and ui guides. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -22,6 +22,7 @@ Detailed guides for specific subsystems live in `contrib/claude/`:
|
|||||||
- [`contrib/claude/agent.md`](contrib/claude/agent.md) — Agent orchestration framework (tools, handoffs, execution)
|
- [`contrib/claude/agent.md`](contrib/claude/agent.md) — Agent orchestration framework (tools, handoffs, execution)
|
||||||
- [`contrib/claude/app-arborescence.md`](contrib/claude/app-arborescence.md) — Frontend app folder layout (pages, routes at resource folders, loaders, skeletons, _components, _lib, _locales)
|
- [`contrib/claude/app-arborescence.md`](contrib/claude/app-arborescence.md) — Frontend app folder layout (pages, routes at resource folders, loaders, skeletons, _components, _lib, _locales)
|
||||||
- [`contrib/claude/relay.md`](contrib/claude/relay.md) — Frontend Relay client (queries, fragments, mutations, pagination)
|
- [`contrib/claude/relay.md`](contrib/claude/relay.md) — Frontend Relay client (queries, fragments, mutations, pagination)
|
||||||
|
- [`contrib/claude/hooks.md`](contrib/claude/hooks.md) — Custom hooks (_lib placement, awaitable useMutation primitive, auto error handling)
|
||||||
- [`contrib/claude/react-components.md`](contrib/claude/react-components.md) — React component shape (file/export, props, configure vs data via hooks, naming/suffix taxonomy, error props)
|
- [`contrib/claude/react-components.md`](contrib/claude/react-components.md) — React component shape (file/export, props, configure vs data via hooks, naming/suffix taxonomy, error props)
|
||||||
- [`contrib/claude/ui.md`](contrib/claude/ui.md) — @probo/ui v2 kit (Base UI headless, Tailwind, tailwind-variants, flat folders, bundle-safe skeletons)
|
- [`contrib/claude/ui.md`](contrib/claude/ui.md) — @probo/ui v2 kit (Base UI headless, Tailwind, tailwind-variants, flat folders, bundle-safe skeletons)
|
||||||
- [`contrib/claude/v2-tokens.md`](contrib/claude/v2-tokens.md) — v2 design tokens (color, typography, radius, shadow scales; native spacing)
|
- [`contrib/claude/v2-tokens.md`](contrib/claude/v2-tokens.md) — v2 design tokens (color, typography, radius, shadow scales; native spacing)
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ Server-side errors map onto the `Form` `errors` prop in **every** tier (see [Ser
|
|||||||
Most forms need nothing more. Base UI validates native HTML constraints, and `<Field.Error>` renders the message. Use `match` to supply your own copy (and i18n) per validity state.
|
Most forms need nothing more. Base UI validates native HTML constraints, and `<Field.Error>` renders the message. Use `match` to supply your own copy (and i18n) per validity state.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Form } from "@base-ui-components/react/form";
|
import { Form } from "@base-ui/react/form";
|
||||||
import { Field } from "@base-ui-components/react/field";
|
import { Field } from "@base-ui/react/field";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export function CreateMeasureForm({ onSubmit }: CreateMeasureFormProps) {
|
export function CreateMeasureForm({ onSubmit }: CreateMeasureFormProps) {
|
||||||
@@ -78,7 +78,7 @@ Async `validate` (e.g. a uniqueness check) is supported; note Base UI does not b
|
|||||||
When validation is complex or needs specific messages, parse a zod schema in `onFormSubmit` and feed the flattened field errors to `Form`'s `errors` prop. This keeps a single typed schema as the source of truth **without** pulling in react-hook-form.
|
When validation is complex or needs specific messages, parse a zod schema in `onFormSubmit` and feed the flattened field errors to `Form`'s `errors` prop. This keeps a single typed schema as the source of truth **without** pulling in react-hook-form.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Form } from "@base-ui-components/react/form";
|
import { Form } from "@base-ui/react/form";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ These rules are the **source of truth**. Where existing code (e.g. `apps/console
|
|||||||
| Routing, navigation, URL state, auth | [`contrib/claude/routing.md`](routing.md) |
|
| Routing, navigation, URL state, auth | [`contrib/claude/routing.md`](routing.md) |
|
||||||
| Client state (Relay / URL / local / context / zustand) | [`contrib/claude/state-management.md`](state-management.md) |
|
| Client state (Relay / URL / local / context / zustand) | [`contrib/claude/state-management.md`](state-management.md) |
|
||||||
| Permission-gated UI | [`contrib/claude/permissions.md`](permissions.md) |
|
| Permission-gated UI | [`contrib/claude/permissions.md`](permissions.md) |
|
||||||
|
| Custom hooks, `_lib` placement, mutation hooks | [`contrib/claude/hooks.md`](hooks.md) |
|
||||||
|
|
||||||
## Destructuring
|
## Destructuring
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ These rules are the **source of truth**. The legacy tree (`Atoms/`, `Molecules/`
|
|||||||
| Styling | **Tailwind v4** with the Radix-scale tokens (`bg-sand-3`, `text-sand-12`, `rounded-3`, `text-4`, …). |
|
| Styling | **Tailwind v4** with the Radix-scale tokens (`bg-sand-3`, `text-sand-12`, `rounded-3`, `text-4`, …). |
|
||||||
| Variants API | **`tailwind-variants`** only — `import { tv } from "tailwind-variants"`. |
|
| Variants API | **`tailwind-variants`** only — `import { tv } from "tailwind-variants"`. |
|
||||||
| Class composition | **Do not use `clsx` or `tailwind-merge`.** All conditional styling goes through `tv` variants and slots. |
|
| Class composition | **Do not use `clsx` or `tailwind-merge`.** All conditional styling goes through `tv` variants and slots. |
|
||||||
| Headless primitives | **Base UI** (`@base-ui-components/react`). We **style** these primitives; we do not re-implement their behavior. |
|
| Headless primitives | **Base UI** (`@base-ui/react`). We **style** these primitives; we do not re-implement their behavior. |
|
||||||
|
|
||||||
Preview components with Storybook from `packages/ui`: `npm run dev` (Storybook on port 6006).
|
Preview components with Storybook from `packages/ui`: `npm run dev` (Storybook on port 6006).
|
||||||
|
|
||||||
> Base UI is migrating its package name from `@base-ui-components/react` to `@base-ui/react`. Import from whichever name the installed version publishes; examples below use `@base-ui-components/react`.
|
> Base UI is published as `@base-ui/react` (the earlier `@base-ui-components/react` name is frozen at an RC — do not use it). Import parts from per-component subpaths, e.g. `@base-ui/react/dialog`.
|
||||||
|
|
||||||
## Headless primitives: style, don't re-implement
|
## Headless primitives: style, don't re-implement
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ export function Dialog({ trigger, ref, children }: Props) {
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
// Good — thin styling over Base UI; consumers use the lib's open/onOpenChange directly
|
// Good — thin styling over Base UI; consumers use the lib's open/onOpenChange directly
|
||||||
import { Dialog as BaseDialog } from "@base-ui-components/react/dialog";
|
import { Dialog as BaseDialog } from "@base-ui/react/dialog";
|
||||||
import { tv } from "tailwind-variants";
|
import { tv } from "tailwind-variants";
|
||||||
|
|
||||||
const dialog = tv({
|
const dialog = tv({
|
||||||
@@ -457,13 +457,13 @@ const imageCard = tv({ slots: { shell: "...", image: "...", text: "..." } });
|
|||||||
|
|
||||||
## User feedback (toasts)
|
## User feedback (toasts)
|
||||||
|
|
||||||
Transient feedback for an action's outcome uses **Base UI's Toast** (`@base-ui-components/react/toast`) — never `alert`, a hand-rolled banner, or a `console.log`. As with every other primitive, we **style** Base UI's toast; we do not build our own toast system. The legacy kit `useToast` / `Toaster` is non-compliant and is being removed — do not use it in v2.
|
Transient feedback for an action's outcome uses **Base UI's Toast** (`@base-ui/react/toast`) — never `alert`, a hand-rolled banner, or a `console.log`. As with every other primitive, we **style** Base UI's toast; we do not build our own toast system. The legacy kit `useToast` / `Toaster` is non-compliant and is being removed — do not use it in v2.
|
||||||
|
|
||||||
The kit exposes a styled **`Toaster`** (a `Toast.Portal` + `Toast.Viewport` rendering styled `Toast.Root`s, keyed off each toast's `type`). Mount Base UI's `Toast.Provider` and the `Toaster` **once** at the app root; everything else queues toasts through Base UI's manager.
|
The kit exposes a styled **`Toaster`** (a `Toast.Portal` + `Toast.Viewport` rendering styled `Toast.Root`s, keyed off each toast's `type`). Mount Base UI's `Toast.Provider` and the `Toaster` **once** at the app root; everything else queues toasts through Base UI's manager.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
// app root — Base UI provider + the kit's styled viewport, mounted once
|
// app root — Base UI provider + the kit's styled viewport, mounted once
|
||||||
import { Toast } from "@base-ui-components/react/toast";
|
import { Toast } from "@base-ui/react/toast";
|
||||||
import { Toaster } from "@probo/ui";
|
import { Toaster } from "@probo/ui";
|
||||||
|
|
||||||
<Toast.Provider>
|
<Toast.Provider>
|
||||||
@@ -475,7 +475,7 @@ import { Toaster } from "@probo/ui";
|
|||||||
Queue a toast with `Toast.useToastManager().add(...)` — the same API Base UI exposes. Use `type` to drive the styled variant.
|
Queue a toast with `Toast.useToastManager().add(...)` — the same API Base UI exposes. Use `type` to drive the styled variant.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Toast } from "@base-ui-components/react/toast";
|
import { Toast } from "@base-ui/react/toast";
|
||||||
|
|
||||||
function CreateMeasureButton() {
|
function CreateMeasureButton() {
|
||||||
const toast = Toast.useToastManager();
|
const toast = Toast.useToastManager();
|
||||||
|
|||||||
Reference in New Issue
Block a user