prime-ui-kit 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/chunks/{chunk-OAXJWF3L.js → chunk-3PY52JP3.js} +1764 -1764
- package/dist/chunks/{chunk-X3JT5CLR.js → chunk-4KONMO7Z.js} +1 -1
- package/dist/chunks/{chunk-MB4CXSLL.js → chunk-W6EGTNG6.js} +3772 -2888
- package/dist/color-picker.js +2 -2
- package/dist/components/data-table/ColumnsMenu.d.ts +39 -17
- package/dist/components/data-table/DataTable.d.ts +41 -12
- package/dist/components/data-table/DataTableColumnsMenu.d.ts +45 -0
- package/dist/components/data-table/Head.d.ts +18 -5
- package/dist/components/data-table/Row.d.ts +10 -4
- package/dist/components/data-table/StateRows.d.ts +5 -3
- package/dist/components/data-table/columnOrder.d.ts +14 -0
- package/dist/components/data-table/reorder.d.ts +15 -5
- package/dist/components/data-table/types.d.ts +5 -0
- package/dist/components/data-table/useFrozenColumns.d.ts +6 -2
- package/dist/components/datepicker/DatepickerPanel.d.ts +1 -1
- package/dist/components/dnd/Dnd.d.ts +9 -5
- package/dist/components/dnd/inPlaceRow.d.ts +7 -0
- package/dist/components/dnd/useDragSource.d.ts +2 -0
- package/dist/components/dnd/useSortableList.d.ts +5 -0
- package/dist/components/field-list/FieldList.d.ts +37 -15
- package/dist/components/gantt/Gantt.d.ts +1 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/kanban/Kanban.d.ts +4 -0
- package/dist/components/list/List.d.ts +9 -4
- package/dist/components/scroll-container/ScrollContainer.d.ts +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +4 -2
- package/dist/internal/ToolRow.d.ts +23 -0
- package/dist/internal/leaveGuard.d.ts +6 -0
- package/dist/internal/overlay/DialogGuard.d.ts +3 -2
- package/dist/internal/overlay/DialogParts.d.ts +14 -5
- package/dist/layout/index.d.ts +1 -1
- package/dist/layout/page/Page.d.ts +8 -14
- package/dist/skill/anti-slop.md +55 -1
- package/dist/skill/api-contract.md +2 -2
- package/dist/skill/cheatsheet.md +12 -4
- package/dist/skill/checklist.md +7 -0
- package/dist/skill/choosing.md +1 -0
- package/dist/skill/components.md +1 -1
- package/dist/skill/composition.md +196 -21
- package/dist/skill/layouts.md +1 -1
- package/dist/skill/reference/components/confirm-dialog/COMPONENT.md +1 -1
- package/dist/skill/reference/components/data-table/COMPONENT.md +110 -49
- package/dist/skill/reference/components/data-table/examples/actions-column.tsx +154 -0
- package/dist/skill/reference/components/data-table/examples/column-order.tsx +152 -0
- package/dist/skill/reference/components/data-table/examples/columns-visibility.tsx +18 -18
- package/dist/skill/reference/components/data-table/examples/controlled.tsx +32 -17
- package/dist/skill/reference/components/data-table/examples/examples.module.css +14 -36
- package/dist/skill/reference/components/data-table/examples/narrow.tsx +25 -19
- package/dist/skill/reference/components/data-table/examples/reorder.tsx +24 -2
- package/dist/skill/reference/components/data-table/examples/row-link.tsx +18 -22
- package/dist/skill/reference/components/data-table/examples/screen.tsx +12 -1
- package/dist/skill/reference/components/data-table/examples/selection.tsx +13 -18
- package/dist/skill/reference/components/data-table/examples/server.tsx +45 -31
- package/dist/skill/reference/components/data-table/examples/toolbar.tsx +22 -35
- package/dist/skill/reference/components/datepicker/COMPONENT.md +2 -2
- package/dist/skill/reference/components/dnd/COMPONENT.md +13 -7
- package/dist/skill/reference/components/dnd/examples/examples.module.css +4 -3
- package/dist/skill/reference/components/dnd/examples/handle.tsx +5 -5
- package/dist/skill/reference/components/dnd/examples/locked.tsx +1 -1
- package/dist/skill/reference/components/dnd/examples/table-columns.tsx +75 -0
- package/dist/skill/reference/components/dnd/examples/table.tsx +6 -6
- package/dist/skill/reference/components/drawer/COMPONENT.md +26 -10
- package/dist/skill/reference/components/drawer/examples/header-actions.tsx +1 -1
- package/dist/skill/reference/components/drawer/examples/loading.tsx +58 -0
- package/dist/skill/reference/components/field-list/COMPONENT.md +78 -47
- package/dist/skill/reference/components/field-list/examples/base-row.tsx +2 -1
- package/dist/skill/reference/components/field-list/examples/locked.tsx +11 -11
- package/dist/skill/reference/components/field-list/examples/narrow.tsx +108 -33
- package/dist/skill/reference/components/field-list/examples/reorder.tsx +1 -1
- package/dist/skill/reference/components/field-list/examples/row-menu.tsx +71 -0
- package/dist/skill/reference/components/field-list/examples/screen.module.css +1 -1
- package/dist/skill/reference/components/field-list/examples/screen.tsx +169 -162
- package/dist/skill/reference/components/field-list/examples/totals.tsx +9 -8
- package/dist/skill/reference/components/field-list/examples/variants.tsx +51 -0
- package/dist/skill/reference/components/gantt/COMPONENT.md +4 -4
- package/dist/skill/reference/components/kanban/COMPONENT.md +6 -2
- package/dist/skill/reference/components/kanban/examples/states.tsx +7 -5
- package/dist/skill/reference/components/list/COMPONENT.md +21 -11
- package/dist/skill/reference/components/list/examples/reorder.tsx +42 -7
- package/dist/skill/reference/components/modal/COMPONENT.md +23 -10
- package/dist/skill/reference/components/scroll-container/COMPONENT.md +1 -1
- package/dist/skill/reference/components/segmented-control/COMPONENT.md +3 -2
- package/dist/skill/reference/components/sheet/COMPONENT.md +18 -7
- package/dist/skill/reference/components/smart-filter/COMPONENT.md +2 -2
- package/dist/skill/reference/layout/page/COMPONENT.md +13 -17
- package/dist/skill/reference/layout/page/examples/screen.module.css +1 -1
- package/dist/skill/reference/layout/page/examples/screen.tsx +93 -104
- package/dist/skill/reference/layout/page/examples/sections.tsx +2 -15
- package/dist/skill/responsive.md +14 -10
- package/dist/tokens/semantic.d.ts +2 -2
- package/dist/tokens/themes/dark.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/confirm-dialog/COMPONENT.md +1 -1
- package/src/components/data-table/COMPONENT.md +110 -49
- package/src/components/data-table/examples/actions-column.tsx +154 -0
- package/src/components/data-table/examples/column-order.tsx +152 -0
- package/src/components/data-table/examples/columns-visibility.tsx +18 -18
- package/src/components/data-table/examples/controlled.tsx +32 -17
- package/src/components/data-table/examples/examples.module.css +14 -36
- package/src/components/data-table/examples/narrow.tsx +25 -19
- package/src/components/data-table/examples/reorder.tsx +24 -2
- package/src/components/data-table/examples/row-link.tsx +18 -22
- package/src/components/data-table/examples/screen.tsx +12 -1
- package/src/components/data-table/examples/selection.tsx +13 -18
- package/src/components/data-table/examples/server.tsx +45 -31
- package/src/components/data-table/examples/toolbar.tsx +22 -35
- package/src/components/datepicker/COMPONENT.md +2 -2
- package/src/components/dnd/COMPONENT.md +13 -7
- package/src/components/dnd/examples/examples.module.css +4 -3
- package/src/components/dnd/examples/handle.tsx +5 -5
- package/src/components/dnd/examples/locked.tsx +1 -1
- package/src/components/dnd/examples/table-columns.tsx +75 -0
- package/src/components/dnd/examples/table.tsx +6 -6
- package/src/components/drawer/COMPONENT.md +26 -10
- package/src/components/drawer/examples/header-actions.tsx +1 -1
- package/src/components/drawer/examples/loading.tsx +58 -0
- package/src/components/field-list/COMPONENT.md +78 -47
- package/src/components/field-list/examples/base-row.tsx +2 -1
- package/src/components/field-list/examples/locked.tsx +11 -11
- package/src/components/field-list/examples/narrow.tsx +108 -33
- package/src/components/field-list/examples/reorder.tsx +1 -1
- package/src/components/field-list/examples/row-menu.tsx +71 -0
- package/src/components/field-list/examples/screen.module.css +1 -1
- package/src/components/field-list/examples/screen.tsx +169 -162
- package/src/components/field-list/examples/totals.tsx +9 -8
- package/src/components/field-list/examples/variants.tsx +51 -0
- package/src/components/gantt/COMPONENT.md +4 -4
- package/src/components/kanban/COMPONENT.md +6 -2
- package/src/components/kanban/examples/states.tsx +7 -5
- package/src/components/list/COMPONENT.md +21 -11
- package/src/components/list/examples/reorder.tsx +42 -7
- package/src/components/modal/COMPONENT.md +23 -10
- package/src/components/scroll-container/COMPONENT.md +1 -1
- package/src/components/segmented-control/COMPONENT.md +3 -2
- package/src/components/sheet/COMPONENT.md +18 -7
- package/src/components/smart-filter/COMPONENT.md +2 -2
- package/src/layout/page/COMPONENT.md +13 -17
- package/src/layout/page/examples/screen.module.css +1 -1
- package/src/layout/page/examples/screen.tsx +93 -104
- package/src/layout/page/examples/sections.tsx +2 -15
- package/src/styles/theme-dark.css +1 -1
- package/src/styles/theme-light.css +1 -1
- package/dist/components/data-table/context.d.ts +0 -14
package/dist/index.js
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
Crossfade,
|
|
20
20
|
DEFAULT_DATEPICKER_PRESETS,
|
|
21
21
|
DataTable,
|
|
22
|
+
DataTableColumnsMenu,
|
|
22
23
|
Datepicker,
|
|
23
24
|
DescriptionList,
|
|
24
25
|
DigitInput,
|
|
@@ -87,7 +88,7 @@ import {
|
|
|
87
88
|
useSidebar,
|
|
88
89
|
useTokenValue,
|
|
89
90
|
useUploadQueue
|
|
90
|
-
} from "./chunks/chunk-
|
|
91
|
+
} from "./chunks/chunk-W6EGTNG6.js";
|
|
91
92
|
import {
|
|
92
93
|
Avatar,
|
|
93
94
|
Badge,
|
|
@@ -122,7 +123,7 @@ import {
|
|
|
122
123
|
tierMappings,
|
|
123
124
|
tones,
|
|
124
125
|
variants
|
|
125
|
-
} from "./chunks/chunk-
|
|
126
|
+
} from "./chunks/chunk-3PY52JP3.js";
|
|
126
127
|
import {
|
|
127
128
|
ControlSizeProvider,
|
|
128
129
|
useOptionalControlSize
|
|
@@ -153,6 +154,7 @@ export {
|
|
|
153
154
|
Crossfade,
|
|
154
155
|
DEFAULT_DATEPICKER_PRESETS,
|
|
155
156
|
DataTable,
|
|
157
|
+
DataTableColumnsMenu,
|
|
156
158
|
Datepicker,
|
|
157
159
|
DescriptionList,
|
|
158
160
|
DigitInput,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
type DivProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
3
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
4
|
+
};
|
|
5
|
+
type ToolGroupProps = DivProps;
|
|
6
|
+
/**
|
|
7
|
+
* A host's own items kept together in one cell that takes the free room (the Gantt's legend or
|
|
8
|
+
* title before its zoom): they wrap inside it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function ToolGroup({ className, ...rest }: ToolGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
type ToolRowProps = DivProps & {
|
|
12
|
+
/** The row has a line of its own: it wraps and its cells fill it by kind. Off — one line, every cell at its natural width. */
|
|
13
|
+
fill?: boolean;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* A row of tools as written, each in a cell of its kind: a search grows, switchers and pickers
|
|
17
|
+
* keep their content width beside it and fill a short line, buttons keep their width at the end.
|
|
18
|
+
*/
|
|
19
|
+
export declare function ToolRow({ fill, className, children, ...rest }: ToolRowProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
type ToolChipsProps = DivProps;
|
|
21
|
+
/** The applied filters (`SmartFilter.Chips`) on a line of their own under a tool row; gone while empty. */
|
|
22
|
+
export declare function ToolChips({ className, ...rest }: ToolChipsProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export {};
|
|
@@ -18,4 +18,10 @@ export declare function leaveGuardCapture(onClickCapture?: React.MouseEventHandl
|
|
|
18
18
|
* it is `busy` or `dirty` the browser asks before the tab closes or reloads (`beforeunload`).
|
|
19
19
|
*/
|
|
20
20
|
export declare function useLeaveGuard({ busy, dirty }: LeaveGuardState, ask: (leave: () => void) => void): void;
|
|
21
|
+
/**
|
|
22
|
+
* While `hold` is true the browser asks before the tab closes or reloads (`beforeunload`): a page
|
|
23
|
+
* guard, and a dialog guard (`Modal.Guard`, `Drawer.Guard`, `Sheet.Guard`) whose form is not saved.
|
|
24
|
+
* `released` lets a leave the person already agreed to go without a second prompt.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useUnloadGuard(hold: boolean, released?: () => boolean): void;
|
|
21
27
|
export {};
|
|
@@ -10,8 +10,9 @@ export type DialogGuardProps = {
|
|
|
10
10
|
};
|
|
11
11
|
/**
|
|
12
12
|
* Holds a Modal, Drawer or Sheet from inside its content, where the form state lives: put it anywhere in
|
|
13
|
-
* `Content`. Renders nothing but the «discard changes?» confirm when it is asked.
|
|
14
|
-
*
|
|
13
|
+
* `Content`. Renders nothing but the «discard changes?» confirm when it is asked. While `busy` or
|
|
14
|
+
* `dirty` the browser also asks before the tab closes or reloads, as `Page.Guard` does. Closing from
|
|
15
|
+
* code (`open={false}`) is never held.
|
|
15
16
|
*/
|
|
16
17
|
export declare function DialogGuard({ busy, dirty }: DialogGuardProps): import("react/jsx-runtime").JSX.Element;
|
|
17
18
|
export declare namespace DialogGuard {
|
|
@@ -148,9 +148,17 @@ export declare namespace DialogTitle {
|
|
|
148
148
|
var displayName: string;
|
|
149
149
|
}
|
|
150
150
|
export type DialogDescriptionProps = Omit<React.HTMLAttributes<HTMLParagraphElement>, "id"> & {
|
|
151
|
+
/**
|
|
152
|
+
* Its data loads: a `Skeleton` holds the line's place and `aria-busy` is set, so the header never moves; the data fades in.
|
|
153
|
+
*/
|
|
154
|
+
loading?: boolean;
|
|
151
155
|
ref?: React.Ref<HTMLParagraphElement>;
|
|
152
156
|
};
|
|
153
|
-
|
|
157
|
+
/**
|
|
158
|
+
* The line under the title. While its data loads (`loading`) it keeps its place with a Skeleton, so
|
|
159
|
+
* the header never moves when the data arrives; the data then fades in under the same element.
|
|
160
|
+
*/
|
|
161
|
+
export declare function DialogDescription({ loading, className, children, ...rest }: DialogDescriptionProps): import("react/jsx-runtime").JSX.Element;
|
|
154
162
|
export declare namespace DialogDescription {
|
|
155
163
|
var displayName: string;
|
|
156
164
|
}
|
|
@@ -163,9 +171,10 @@ export type DialogHeaderProps = React.HTMLAttributes<HTMLElement> & {
|
|
|
163
171
|
};
|
|
164
172
|
/**
|
|
165
173
|
* `[Icon] [Title + Description] [Actions] [close]` in one row. Layout is a CSS grid, so child
|
|
166
|
-
* order does not matter; text children stack in the text column.
|
|
174
|
+
* order does not matter; text children stack in the text column. When the row is too narrow for
|
|
175
|
+
* the title beside the actions (a phone), the actions move under the text.
|
|
167
176
|
*/
|
|
168
|
-
export declare function DialogHeader({ showClose, className, children, ...rest }: DialogHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
177
|
+
export declare function DialogHeader({ showClose, className, children, ref, ...rest }: DialogHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
169
178
|
export declare namespace DialogHeader {
|
|
170
179
|
var displayName: string;
|
|
171
180
|
}
|
|
@@ -205,13 +214,13 @@ export type DialogSectionProps = Omit<React.HTMLAttributes<HTMLElement>, "title"
|
|
|
205
214
|
* at the end of the heading row, then the content 16 below. Sections stand further apart than the
|
|
206
215
|
* plain blocks of the body.
|
|
207
216
|
*/
|
|
208
|
-
export declare function DialogSection({ label, description, className, children, ...rest }: DialogSectionProps): import("react/jsx-runtime").JSX.Element;
|
|
217
|
+
export declare function DialogSection({ label, description, className, children, ref, ...rest }: DialogSectionProps): import("react/jsx-runtime").JSX.Element;
|
|
209
218
|
export declare namespace DialogSection {
|
|
210
219
|
var displayName: string;
|
|
211
220
|
}
|
|
212
221
|
export type DialogFooterProps = React.HTMLAttributes<HTMLElement> & {
|
|
213
222
|
/**
|
|
214
|
-
* `fill`: equal-width buttons in one row; `end`: auto width, at the end. Stacked on phones (viewport below 640 px) and in a dialog narrower than 360 px.
|
|
223
|
+
* `fill`: equal-width buttons in one row, wrapping rather than cutting a label; `end`: auto width, at the end. Stacked on phones (viewport below 640 px) and in a dialog narrower than 360 px.
|
|
215
224
|
*/
|
|
216
225
|
layout?: DialogFooterLayout;
|
|
217
226
|
ref?: React.Ref<HTMLElement>;
|
package/dist/layout/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export type { AppShellFooterProps, AppShellMainProps, AppShellNavProps, AppShell
|
|
|
2
2
|
export { AppShell, useAppShellNav } from "./app-shell/AppShell";
|
|
3
3
|
export type { BottomNavActionProps, BottomNavItemCountProps, BottomNavItemIconProps, BottomNavItemProps, BottomNavLabels, BottomNavRootProps, } from "./bottom-nav/BottomNav";
|
|
4
4
|
export { BottomNav } from "./bottom-nav/BottomNav";
|
|
5
|
-
export type { PageActionsProps, PageBackButtonProps, PageBodyProps, PageCellProps, PageCellRows, PageCellSpan, PageChipsProps, PageDescriptionProps, PageDetailProps, PageGridProps, PageGuardProps, PageHeaderProps, PageHeadingProps, PageLabels, PageListProps, PageMaxWidth, PageRootProps,
|
|
5
|
+
export type { PageActionsProps, PageBackButtonProps, PageBodyProps, PageCellProps, PageCellRows, PageCellSpan, PageChipsProps, PageDescriptionProps, PageDetailProps, PageGridProps, PageGuardProps, PageHeaderProps, PageHeadingProps, PageLabels, PageListProps, PageMaxWidth, PageRootProps, PageSectionProps, PageSplitProps, PageTitleProps, PageToolsProps, PageTopBarProps, } from "./page/Page";
|
|
6
6
|
export { Page } from "./page/Page";
|
|
7
7
|
export type { SidebarAccountProps, SidebarBrandLogoProps, SidebarBrandProps, SidebarContentProps, SidebarFooterProps, SidebarGroupProps, SidebarHeaderProps, SidebarItemActionProps, SidebarItemCountProps, SidebarItemIconProps, SidebarItemProps, SidebarItemShortcutProps, SidebarLabels, SidebarMode, SidebarRootProps, SidebarSubContentProps, SidebarSubProps, SidebarSubTriggerProps, SidebarToggleProps, } from "./sidebar/Sidebar";
|
|
8
8
|
export { Sidebar, useSidebar } from "./sidebar/Sidebar";
|
|
@@ -128,14 +128,14 @@ declare namespace PageActions {
|
|
|
128
128
|
}
|
|
129
129
|
export type PageToolsProps = DivProps;
|
|
130
130
|
/**
|
|
131
|
-
* The page's tools — sections, search and filter, view — as kit controls in the order written
|
|
132
|
-
*
|
|
133
|
-
* a
|
|
134
|
-
* the
|
|
135
|
-
*
|
|
136
|
-
* a `group`.
|
|
131
|
+
* The page's tools — sections, search and filter, view — as kit controls in the order written, laid
|
|
132
|
+
* out by the one tool row (`ToolRow`, as the DataTable `toolbar`). On the bar's first line each keeps
|
|
133
|
+
* its natural width; on a line of their own a search takes the free room, switchers and pickers
|
|
134
|
+
* keep their width at the end (a `SegmentedControl.Root` and a `Datepicker.Root` are `fullWidth`
|
|
135
|
+
* unless set, so they fill a short line), and they wrap when one line is not enough. Named
|
|
136
|
+
* (`aria-label`), it is a `group`.
|
|
137
137
|
*/
|
|
138
|
-
declare function PageTools({ className,
|
|
138
|
+
declare function PageTools({ className, ...rest }: PageToolsProps): import("react/jsx-runtime").JSX.Element;
|
|
139
139
|
declare namespace PageTools {
|
|
140
140
|
var displayName: string;
|
|
141
141
|
}
|
|
@@ -151,8 +151,6 @@ declare function PageBody({ className, ...rest }: PageBodyProps): import("react/
|
|
|
151
151
|
declare namespace PageBody {
|
|
152
152
|
var displayName: string;
|
|
153
153
|
}
|
|
154
|
-
/** Where the heading of a section stands: over its content or in a column beside it. */
|
|
155
|
-
export type PageSectionLayout = "stack" | "aside";
|
|
156
154
|
export type PageSectionProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
|
|
157
155
|
/**
|
|
158
156
|
* The visible heading (`h2`); it also names the section.
|
|
@@ -162,10 +160,6 @@ export type PageSectionProps = Omit<React.HTMLAttributes<HTMLElement>, "title">
|
|
|
162
160
|
* One line of context under the heading, in secondary body-s.
|
|
163
161
|
*/
|
|
164
162
|
description?: React.ReactNode;
|
|
165
|
-
/**
|
|
166
|
-
* `stack` — the heading over the content; `aside` — a ~16rem heading column beside it (a settings page), above it once the content would get narrower than 30rem.
|
|
167
|
-
*/
|
|
168
|
-
layout?: PageSectionLayout;
|
|
169
163
|
ref?: React.Ref<HTMLElement>;
|
|
170
164
|
};
|
|
171
165
|
/**
|
|
@@ -173,7 +167,7 @@ export type PageSectionProps = Omit<React.HTMLAttributes<HTMLElement>, "title">
|
|
|
173
167
|
* at its end) over its content. Sections stand further apart than the plain blocks of the body,
|
|
174
168
|
* so the air shows where a new topic starts.
|
|
175
169
|
*/
|
|
176
|
-
declare function PageSection({ label, description,
|
|
170
|
+
declare function PageSection({ label, description, className, children, ...rest }: PageSectionProps): import("react/jsx-runtime").JSX.Element;
|
|
177
171
|
declare namespace PageSection {
|
|
178
172
|
var displayName: string;
|
|
179
173
|
}
|
package/dist/skill/anti-slop.md
CHANGED
|
@@ -242,7 +242,8 @@ The same for one value in several units — one heading, the fields in a row, th
|
|
|
242
242
|
| `<Button.Root onClick={() => location.assign(url)}>` | `<Button.Root asChild><a href={url}>…</a></Button.Root>` or `LinkButton` |
|
|
243
243
|
| a hand-built spinner, shimmer, grey placeholder box or «Loading…» text | `loading` on Button / Select / DataTable; a region: `Skeleton` of its content inside `Crossfade`; no shape to hold: `Spinner` |
|
|
244
244
|
| `{loading ? <Spinner /> : <List />}` — a state that flips | `<Crossfade state={status}>` around the region, `Skeleton` while loading |
|
|
245
|
-
| a search Input + a row of filter Selects above a table | `SmartFilter`
|
|
245
|
+
| a search Input + a row of filter Selects above a table | `SmartFilter` next to the table it filters: its toolbar and chips in the table's `toolbar` / `toolbarChips` beside KPI cards, in `Page.Tools` / `Page.Chips` when the table is the page ([where the filters go](composition.md#where-the-filters-go)) |
|
|
246
|
+
| the table's search, filter or «Колонки» in the page's bar above KPI cards | the bar keeps the title, the period that drives every block and the primary action; the table's tools go in its own `toolbar` ([where the filters go](composition.md#where-the-filters-go)) |
|
|
246
247
|
| a grid of «label: value» text pairs for one record | `DescriptionList.Root` + `DescriptionList.Item` |
|
|
247
248
|
| a Modal hand-built as «Удалить?» with your own pending flag | `ConfirmDialog.Root` with an async `onConfirm` |
|
|
248
249
|
| a `<fieldset>` reset by hand, or `disabled` on every field while saving | `<Fieldset label disabled={saving}>` |
|
|
@@ -292,6 +293,59 @@ The same for one value in several units — one heading, the fields in a row, th
|
|
|
292
293
|
/>
|
|
293
294
|
```
|
|
294
295
|
|
|
296
|
+
A bar above the table for a single button — the column chooser, an export — wastes a row and splits
|
|
297
|
+
the page's actions ([controls of a table](composition.md#controls-of-a-table)):
|
|
298
|
+
|
|
299
|
+
```tsx partial
|
|
300
|
+
// bad — a toolbar that holds one control
|
|
301
|
+
<DataTable columns={columns} rows={orders} toolbar={<Button.Root>Колонки</Button.Root>} />
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
A chooser cell in the header of a table that has no row actions is a column of nothing — an empty
|
|
305
|
+
cell in every row:
|
|
306
|
+
|
|
307
|
+
```tsx partial
|
|
308
|
+
// bad — columnsMenu with no row-actions column to stand over
|
|
309
|
+
<DataTable columns={columns} rows={orders} columnsMenu />
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
```tsx good
|
|
313
|
+
// good — a page that is the table, no row actions: the chooser is in the bar, on the state the table reads
|
|
314
|
+
// declare: const orders: { id: string; client: string; total: number }[]
|
|
315
|
+
// declare: const hidden: string[]
|
|
316
|
+
// declare: const setHidden: (hidden: string[]) => void
|
|
317
|
+
<Page.Root>
|
|
318
|
+
<Page.TopBar>
|
|
319
|
+
<Page.Heading>
|
|
320
|
+
<Page.Title>Заказы</Page.Title>
|
|
321
|
+
</Page.Heading>
|
|
322
|
+
<Page.Tools>
|
|
323
|
+
<DataTableColumnsMenu
|
|
324
|
+
columns={[
|
|
325
|
+
{ id: "id", header: "Заказ", accessor: "id", hideable: false },
|
|
326
|
+
{ id: "client", header: "Клиент", accessor: "client" },
|
|
327
|
+
{ id: "total", header: "Сумма", accessor: "total", numeric: true },
|
|
328
|
+
]}
|
|
329
|
+
hiddenColumns={hidden}
|
|
330
|
+
onHiddenColumnsChange={setHidden}
|
|
331
|
+
/>
|
|
332
|
+
</Page.Tools>
|
|
333
|
+
</Page.TopBar>
|
|
334
|
+
<Page.Body>
|
|
335
|
+
<DataTable
|
|
336
|
+
columns={[
|
|
337
|
+
{ id: "id", header: "Заказ", accessor: "id", hideable: false },
|
|
338
|
+
{ id: "client", header: "Клиент", accessor: "client" },
|
|
339
|
+
{ id: "total", header: "Сумма", accessor: "total", numeric: true },
|
|
340
|
+
]}
|
|
341
|
+
hiddenColumns={hidden}
|
|
342
|
+
rows={orders}
|
|
343
|
+
getRowKey={(row) => row.id}
|
|
344
|
+
/>
|
|
345
|
+
</Page.Body>
|
|
346
|
+
</Page.Root>
|
|
347
|
+
```
|
|
348
|
+
|
|
295
349
|
## 7b. A top bar out of its groups
|
|
296
350
|
|
|
297
351
|
The bar lays itself out only from its four groups ([the top bar](composition.md#the-top-bar)); a
|
|
@@ -23,7 +23,7 @@ import type { ControlSize, PaletteColor, TextTone, Tone, Variant } from "prime-u
|
|
|
23
23
|
| Validation | `invalid`, `hint`, `error` | Props, never parts. A non-empty `error` implies `invalid`; sets `aria-invalid`, `data-invalid`. |
|
|
24
24
|
| Value | `value` / `defaultValue` / `onValueChange(value)` | Accordion, Chat.Pinned, ChatList, ColorField, ColorPicker, ColorPresets, ColorSwatches, Composer, Datepicker, Datepicker.Panel, DigitInput, FieldList, FileUpload, FileUpload.Queue, Kanban, NativeSelect, Pagination, Radio.Group, SegmentedControl, Select, Slider, SmartFilter, Stepper, Tabs, TagSelect. |
|
|
25
25
|
| Text value | native `value` / `onChange` + `onValueChange(string)` | Input (`Input.Field`), Textarea. |
|
|
26
|
-
| Other state | `x` / `defaultX` / `onXChange(x)` | Badge `pressed`; Button `pressed`; ChartFrame `hiddenSeries`; Chat `selected`, `search`; ChatList `search`; ColorPicker `format`; CommandMenu `search`; Composer `recordMode`; DataTable `hiddenColumns`, `page`, `sort`, `selected`, `expanded`, `collapsedGroups`; ExampleFrame `viewport`, `colorScheme`; Gallery `index`; Gantt `scale`; Kanban `columnOrder`; MediaViewer `index`; Message.Media `index`; Select `search`; SmartFilter `search`; VideoNote `playing`, `transcriptExpanded`; VoicePlayer `rate`, `playing`, `transcriptExpanded`; Sidebar `mode`. |
|
|
26
|
+
| Other state | `x` / `defaultX` / `onXChange(x)` | Badge `pressed`; Button `pressed`; ChartFrame `hiddenSeries`; Chat `selected`, `search`; ChatList `search`; ColorPicker `format`; CommandMenu `search`; Composer `recordMode`; DataTable `hiddenColumns`, `columnOrder`, `page`, `sort`, `selected`, `expanded`, `collapsedGroups`; ExampleFrame `viewport`, `colorScheme`; Gallery `index`; Gantt `scale`; Kanban `columnOrder`; MediaViewer `index`; Message.Media `index`; Select `search`; SmartFilter `search`; VideoNote `playing`, `transcriptExpanded`; VoicePlayer `rate`, `playing`, `transcriptExpanded`; Sidebar `mode`. |
|
|
27
27
|
| Checked | `checked` / `defaultChecked` / `onCheckedChange(checked)` | Checkbox, Dropdown.CheckboxItem, Switch, Thumbnail. |
|
|
28
28
|
| Open | `open` / `defaultOpen` / `onOpenChange(open)` | ColorPresets, CommandMenu, ConfirmDialog, Datepicker, Drawer, Dropdown, Gallery, MediaViewer, Message.Media, Modal, Popover, Select, Sheet, TagSelect, Tooltip, Page.Split, Sidebar, Sidebar.Group, Sidebar.Sub. |
|
|
29
29
|
| Dismiss | `closeOnOutsideClick` (default `true`), `closeOnEscape` (default `true`) | Both on every overlay that opens a layer: the dialogs, the floating panels, the panels of Select, TagSelect, Datepicker and ColorPresets, the `suggestions` list of Input, the off-canvas Sidebar and the reaction bar of a message. `ConfirmDialog` takes both with `closeOnOutsideClick` default `false` (Escape is held while `onConfirm` runs). Tooltip and Notification take neither. A form holds closing with `Modal.Guard` / `Drawer.Guard` / `Sheet.Guard`. |
|
|
@@ -295,7 +295,7 @@ export function DeleteProject({ onDelete }: { onDelete: () => Promise<void> }) {
|
|
|
295
295
|
|
|
296
296
|
Leaving a form with unsaved changes is the same contract: `Modal.Guard` / `Drawer.Guard` inside the
|
|
297
297
|
content with `dirty` (any dismiss asks «Не сохранять изменения?») and `busy` (nothing closes it while
|
|
298
|
-
it saves). A form that is the whole page takes `Page.Guard` (`dirty`, `busy`) inside the page: it
|
|
298
|
+
it saves); while either holds, the browser also asks before the tab closes or reloads. A form that is the whole page takes `Page.Guard` (`dirty`, `busy`) inside the page: it
|
|
299
299
|
holds a press on `Sidebar.Item`, `BottomNav.Item` and `Breadcrumb.Item` links — router links
|
|
300
300
|
included — and the browser's own close or reload; never a `beforeunload` or a ConfirmDialog on a
|
|
301
301
|
crumb of your own.
|
package/dist/skill/cheatsheet.md
CHANGED
|
@@ -44,6 +44,7 @@ reference is each component's `COMPONENT.md` ([components.md](components.md)), t
|
|
|
44
44
|
- Copy or call next to a value: `Input.CopyButton`, `Input.Action` inside `Input.Wrapper` — not a Button beside the field; a password: `Input.RevealButton`.
|
|
45
45
|
- Records of one shape a person adds and removes (invoice lines, contacts, specs, prices by period): `<FieldList columns={[{ label: "Услуга" }, { label: "Цена", width: "m" }]} value onValueChange getId createItem addLabel renderItem={(item, row) => <>…fields without label…</>} />` — the headings stand once, every field takes its column heading as its label; not a `.map()` of fields with a `label` in every row, not «Позиция 1», «Позиция 2».
|
|
46
46
|
- Small attributes in a row of fields: an icon-only `Select` (`<Select.Trigger><Select.TriggerIcon>…</Select.TriggerIcon></Select.Trigger>`, no `Select.Value`) and a `ColorPresets` swatch in `width: "compact"` columns — not a full-width Select and a ColorField on a line of their own.
|
|
47
|
+
- FieldList row actions: `rowActions="menu"` (one «⋯») for dense rows or touch, the default «×» + handle for short lists reordered often; `variant="surface"` when the list sits among other fields, `plain` when it is the card's content — not a hand-made «⋯» or a Card around the list.
|
|
47
48
|
- A base value with overrides (a price and its changes by month): one `FieldList`, the base as the first row pinned by `getLocked` — not a separate field above a list in another geometry.
|
|
48
49
|
- Rows that add up: `FieldList renderTotals={(items) => <>…one node per column…</>}` draws «Итого» under the rows on the same tracks — not a line of text typed under the list, not a DataTable of fields.
|
|
49
50
|
- One value in several units (a deposit in ₽, $, ฿): the fields side by side in one row under one heading, each unit in `Input.InlineAffix` — not a label per field, not the unit in the label and in the field.
|
|
@@ -84,9 +85,9 @@ reference is each component's `COMPONENT.md` ([components.md](components.md)), t
|
|
|
84
85
|
|
|
85
86
|
- The app is navigation and the page: everything at the top belongs to the page's `<Page.Root>` — not an app-wide header, a global search or notifications above every page.
|
|
86
87
|
- A work screen (a list, a board, a chat, a record) titles itself in `<Page.TopBar>`: `<Page.Heading>` with `<Page.Title>` + `<Page.Description>` carrying a line of data («128 в работе · 6 ждут оплаты») — not a sentence about the page.
|
|
87
|
-
- The bar holds only its four groups: `<Page.Heading>`, `<Page.Tools aria-label>` (sections, `<SmartFilter.Toolbar
|
|
88
|
+
- The bar holds only its four groups: `<Page.Heading>`, `<Page.Tools aria-label>` (sections, the view, a shared period; `<SmartFilter.Toolbar />` of a one-list page — in reading order), `<Page.Actions>`, `<Page.Chips>` (`<SmartFilter.Chips />`) — not a hand-made flex row of title, tabs, search and buttons ([the top bar](composition.md#the-top-bar)).
|
|
88
89
|
- A nested record: `<Breadcrumb.Root>` first in `<Page.Heading>`, then `<Page.Title>` with the record's name — the path ends in the title on one line; not a title row under the path, not a breadcrumb in the body. With a router each crumb is `<Breadcrumb.Item asChild>` around its `Link`.
|
|
89
|
-
- A line of data that loads after the page opens: `<Page.Description loading={!summary}>` from the first render — not a Description mounted when the data arrives, which moves the title.
|
|
90
|
+
- A line of data that loads after the page opens: `<Page.Description loading={!summary}>` from the first render (`Drawer.Description` / `Modal.Description` alike) — not a Description mounted when the data arrives, which moves the title, nor a `Skeleton` placed in it by hand.
|
|
90
91
|
- A page that edits a record: `<Page.Guard dirty={changed} busy={saving} />` inside `Page.Root` — the Sidebar, BottomNav and path links ask before the changes are lost; not your own `beforeunload` or a confirm wired to each link.
|
|
91
92
|
- Every button of the page goes into one `<Page.Actions>`, secondary first, the primary last, each with a `<Button.Icon>` beside its label — not buttons split between two places, not a button with only text.
|
|
92
93
|
- A filtered page: `<SmartFilter.Root>` wraps `<Page.Root>` — it draws nothing; not `SmartFilter.Root` inside the bar.
|
|
@@ -97,6 +98,7 @@ reference is each component's `COMPONENT.md` ([components.md](components.md)), t
|
|
|
97
98
|
|
|
98
99
|
- `Card.Root` only for a bounded block with its own title: a KPI tile (`variant="stat-trend"`), a settings panel (`variant="panel"`), side facts — not around a whole section, a form field or a page.
|
|
99
100
|
- Never a `DataTable` inside a Card — the table is already a filled block; a card in a card only sparingly ([the rule](foundations.md#card-in-a-card)).
|
|
101
|
+
- A titled panel (a settings section, a group of a long form) is `<Card.Root>` with `<Card.Header>` (`<Card.Title as="h2">`, `<Card.Description>`) stacked in the flow — never a heading column beside its panel ([a titled block](composition.md#4-surfaces)).
|
|
100
102
|
- Section without a card: `<Page.Section label="…">` + the content (a link or button beside the heading in `Page.Actions`) — not a hand-made `<section>` + `Typography as="h2"` + own gap.
|
|
101
103
|
- The tiles of a screen (KPI cards, charts, panels): one `<Page.Grid>` with a `<Page.Cell span>` per tile — not a grid per row (the rows would stand 24 apart instead of 16). A chart beside a panel is an 8 and a 4 written next to each other — the grid pairs them at mid widths; not 6 + 6 to dodge a hole.
|
|
102
104
|
- A KPI tile whose figure loads: `<Card.Root variant="stat-trend" loading>` with its parts mounted — not Skeletons placed in `Card.Value` by hand.
|
|
@@ -108,6 +110,8 @@ reference is each component's `COMPONENT.md` ([components.md](components.md)), t
|
|
|
108
110
|
## Tables
|
|
109
111
|
|
|
110
112
|
- A list page is a `<DataTable columns rows getRowKey>` under the page's `<SmartFilter.Root fields value onValueChange>` with `<SmartFilter.Toolbar />` in its `Page.Tools` and `<SmartFilter.Chips />` in its `Page.Chips` ([where the filters go](composition.md#where-the-filters-go)); filter rows with `matchesSmartFilter` — not a search Input and a row of Selects above the table.
|
|
113
|
+
- A table beside KPI cards or a chart: `<SmartFilter.Root>` around the `<DataTable toolbar={<><SmartFilter.Toolbar /><DataTableColumnsMenu … /></>} toolbarChips={<SmartFilter.Chips />}>` — not its search, filter and «Колонки» in the page's bar above blocks they do not filter ([where the filters go](composition.md#where-the-filters-go)).
|
|
114
|
+
- The column chooser is `<DataTable columnsMenu>` over the row actions, else `<DataTableColumnsMenu>` beside the table's search on the same state; `toolbar` takes two or more controls of the table as they are — no wrapper ([controls of a table](composition.md#controls-of-a-table)) — never a toolbar for one button.
|
|
111
115
|
- Search over a table or a list page is always SmartFilter, even with no filter fields yet (`fields={[]}` is a plain search that grows into filters). A search `Input` only outside a filtered list: inside a picker, a settings section, a panel.
|
|
112
116
|
- Paging is built in: `paging="pages"` (default) with `pageSize`, `paging="infinite"` for feeds, `paging="none"` for short lists — not a separate `<Pagination>` under a DataTable.
|
|
113
117
|
- Long lists are virtualized inside the kit: pass the whole array to `DataTable` (with `scrollHeight` or `paging="infinite"`; over 100 rows — grouped, `onReorder` and `renderExpanded` bodies render every row, keep those short or paged), `TagSelect options`, `Chat.Messages items`, `Gantt rows` — never slice it by hand, never wrap a kit list in react-window / react-virtual or your own windowing. Big remote data is still paged or loaded on scroll by the server (`source="server"`, `onLoadMore`).
|
|
@@ -119,7 +123,11 @@ reference is each component's `COMPONENT.md` ([components.md](components.md)), t
|
|
|
119
123
|
- A column header that needs a word more («Маржа»): the column's `description` (an info glyph with a tooltip) — not the explanation squeezed into the header, not your own icon and Tooltip in `header`.
|
|
120
124
|
- A list row with controls of its own (a Switch, a ⋯ menu): `List.ItemActions` inside `List.Item`, a stage colour as `Badge.Dot color` in `List.ItemIcon` — not a control inside the row's button, not a row rebuilt as a `div`.
|
|
121
125
|
- Rows people order by hand: `onReorder(id, beforeId)` (apply it with `moveBefore`, return the save's Promise) — not a Dnd list rebuilt next to the table.
|
|
126
|
+
- A DataTable's grip stays at the end of the row (`reorderHandle` default); `start` or `row` only by the rule ([choosing](choosing.md#3-pairs-that-are-easy-to-confuse)) — never a grip column of your own.
|
|
127
|
+
- Columns people arrange: `columnOrder` + `onColumnOrderChange` next to `hiddenColumns` and the column chooser, both saved by the app — not up / down buttons, a settings dialog or a header drag of your own.
|
|
122
128
|
- A short list of records people order by hand (stages, priorities) is `<List.Root onReorder>` with `List.Item value` — not up / down buttons or a hand-made `Dnd.Sortable`.
|
|
129
|
+
- A toggle in a reorderable row leads it (`List.ItemActions side="start"`) and a plain settings row ends with it ([list rows](composition.md#list-rows)) — never a Switch between the label and the grip.
|
|
130
|
+
- The grip ends its row: a `Dnd.Handle` is the last child of its item, after the row's own controls, and a locked row's lock takes the same place (List, FieldList and Kanban place theirs there) — not before the row's text.
|
|
123
131
|
- Groups that fold: pass `defaultCollapsedGroups={[]}` (or the controlled `collapsedGroups` + `onCollapsedGroupsChange`) — not your own button in `renderGroupHeader` or filtering `rows`. One heatmap over several columns: the same `scale: { min, max }` on each.
|
|
124
132
|
- A trend in a table row is `<Sparkline layout="compact">` in the column's `cell` (a column `width`, series built once, not inline, the same `min` / `max` on every row when rows compare by size); the number itself goes in its own column. A missing day is `value: null`, never `0`.
|
|
125
133
|
- Properties of one record: `<DescriptionList.Root>` of `DescriptionList.Item` — not a hand-made grid of label / value text, not a one-row DataTable.
|
|
@@ -160,7 +168,7 @@ reference is each component's `COMPONENT.md` ([components.md](components.md)), t
|
|
|
160
168
|
- A destructive confirm is `<ConfirmDialog.Root title description confirmLabel onConfirm={remove}>` with a `ConfirmDialog.Trigger` — not a Modal assembled as a confirm with your own pending state; a reversible delete offers «Отменить» in the notification instead.
|
|
161
169
|
- Overlays close smoothly only if they stay mounted: render the `Root` always and drive visibility with `open` alone — never `{open && <Drawer.Root>}`, never a changing `key` on the Root. The kit keeps the last content on screen while the exit plays.
|
|
162
170
|
- Placement of a menu, popover, select or picker: leave the defaults — `side="bottom"`, `align="auto"`: it opens below the trigger, lines up with the trigger edge that has the room (a «⋯» at the end of a row grows toward the start) and flips to the top by itself. Never write `side` or `align` to restate that; set `align` only when the panel must line up with one edge of a block whatever room there is. A Popover under a wide anchor that must never be narrower than it: `<Popover.Content width="min-trigger">`.
|
|
163
|
-
- While a request runs: `<Modal.Guard busy={saving} />` inside the content (`Drawer.Guard`, `Sheet.Guard` alike) — Escape, a press outside, × and `Close` are held, × and `Close` disabled; add `dirty` to ask before unsaved changes are lost. Not `closeOnEscape={false}` or `showClose={false}` by hand
|
|
171
|
+
- While a request runs: `<Modal.Guard busy={saving} />` inside the content (`Drawer.Guard`, `Sheet.Guard` alike) — Escape, a press outside, × and `Close` are held, × and `Close` disabled; add `dirty` to ask before unsaved changes are lost; both also hold the browser's tab close. Not `closeOnEscape={false}` or `showClose={false}` by hand, not your own `beforeunload`.
|
|
164
172
|
|
|
165
173
|
## Motion — it comes with the components
|
|
166
174
|
|
|
@@ -204,7 +212,7 @@ Full rules: [responsive.md](responsive.md).
|
|
|
204
212
|
|
|
205
213
|
- Rearrange, never hide: every desktop function is on the phone, in another place or a menu — not `display: none` below a breakpoint.
|
|
206
214
|
- Breakpoints only in [their scope](responsive.md#breakpoints); inside a page — [intrinsic grids](responsive.md#intrinsic-grids) and container queries.
|
|
207
|
-
- A wide table scrolls inside itself; offer `
|
|
215
|
+
- A wide table scrolls inside itself; offer the column chooser (`columnsMenu` or `DataTableColumnsMenu`) — never drop columns by breakpoint, never hand-build the chooser.
|
|
208
216
|
- A row that opens a record page is `getRowHref` (a real link: ⌘-click, new tab), a row that opens a drawer is `onRowClick` — never `navigate()` in `onRowClick`, never your own `event.target` checks for buttons in the row.
|
|
209
217
|
- A list + detail screen is `Page.Split` (`Page.List`, `Page.Detail`) in a `Page.Root fill` page, its records a `List` (`current` on the open one) — never ghost Buttons with a soft current; a full-height table is `scrollHeight="fill"` — never a height computed from `100vh`.
|
|
210
218
|
- App sections on phones: `BottomNav` in `AppShell.Footer` — not in Main, not `position: fixed`, no own media query: the shell hides the footer while the Sidebar rail is on screen; a short task from the bottom edge: `Sheet` — Select, Dropdown, Popover and Modal become sheets below 640 by themselves.
|
package/dist/skill/checklist.md
CHANGED
|
@@ -10,11 +10,16 @@ checks.
|
|
|
10
10
|
- [ ] A nested record's path ends in its title on one line inside `Page.Heading`; no title row under the path ([the top bar](composition.md#the-top-bar)).
|
|
11
11
|
- [ ] Every button of the page is in one `Page.Actions`, the primary last, each with a `Button.Icon` ([the top bar](composition.md#the-top-bar)).
|
|
12
12
|
- [ ] `SmartFilter.Root` wraps `Page.Root`; its toolbar is in `Page.Tools`, its chips in `Page.Chips` ([the top bar](composition.md#the-top-bar)).
|
|
13
|
+
- [ ] A filter stands next to what it filters: beside KPI cards or a chart, the table's search, filter, chips and chooser are in its `toolbar` / `toolbarChips`; the bar keeps the title, the shared period and the primary action ([where the filters go](composition.md#where-the-filters-go)).
|
|
13
14
|
- [ ] A Card only for a standalone titled block — never around a table, a single field or the page ([surfaces](composition.md#4-surfaces)).
|
|
15
|
+
- [ ] A titled panel carries its heading in its `Card.Header` and stacks in the flow; no heading column beside a panel ([surfaces](composition.md#4-surfaces)).
|
|
16
|
+
- [ ] A DataTable's row grip and column order follow the rule: grip at the end, columns by `columnOrder` saved with `hiddenColumns` ([choosing](choosing.md#3-pairs-that-are-easy-to-confuse)).
|
|
17
|
+
- [ ] The column chooser is `columnsMenu` only over a row-actions column, else `DataTableColumnsMenu` beside the table's search; a DataTable `toolbar` holds two or more table controls, unwrapped, or does not exist ([controls of a table](composition.md#controls-of-a-table)).
|
|
14
18
|
|
|
15
19
|
## UX ([ux.md](ux.md))
|
|
16
20
|
- [ ] I wrote the five-line brief before the JSX ([brief](ux.md#1-brief-before-code)).
|
|
17
21
|
- [ ] Every entity is laid out by its shape: a record is one row or one block ([data shape](ux.md#2-the-shape-of-the-data-decides-the-layout)).
|
|
22
|
+
- [ ] A FieldList picks its `rowActions` (buttons or menu) and its `variant` (plain or surface) by the rules ([forms](composition.md#7-forms)).
|
|
18
23
|
- [ ] Labels on a form of rows ≤ columns + the list label; none repeated, numbered or repeating its heading ([label economy](ux.md#3-label-economy)).
|
|
19
24
|
- [ ] No text explains the layout; every hint says what the person cannot see ([label economy](ux.md#3-label-economy)).
|
|
20
25
|
- [ ] Buttons say the verb and the object, errors say how to fix it, empty states offer the next step ([words](ux.md#4-words)).
|
|
@@ -35,6 +40,7 @@ checks.
|
|
|
35
40
|
## Sizes and alignment
|
|
36
41
|
- [ ] Default size `m`; a tier changes for a whole region, never for one control ([the host tier](api-contract.md#size-and-the-host-tier)).
|
|
37
42
|
- [ ] Every row of controls uses one size and its heights line up ([density](composition.md#5-density-and-size)).
|
|
43
|
+
- [ ] A reorderable row's toggle leads it and the grip ends it; a plain settings row ends with its toggle ([list rows](composition.md#list-rows)).
|
|
38
44
|
- [ ] Controls in table cells are one tier below the table; no CSS sets row or cell heights ([size axis](foundations.md#3-size-axis)).
|
|
39
45
|
- [ ] Icon-only buttons are square (round only for media and transfers) and named ([icons](api-contract.md#icons)).
|
|
40
46
|
|
|
@@ -59,6 +65,7 @@ checks.
|
|
|
59
65
|
|
|
60
66
|
## Hierarchy
|
|
61
67
|
- [ ] One primary action per area, last in its row; the rest `soft` / `ghost` / `outline` neutral ([actions](composition.md#6-actions)).
|
|
68
|
+
- [ ] A dialog footer holds Cancel and the primary only; deleting the edited record is the last item of the header ⋯ menu ([actions](composition.md#6-actions)).
|
|
62
69
|
- [ ] The same action has the same label and variant everywhere on the screen ([secondary actions](api-contract.md#secondary-actions)).
|
|
63
70
|
|
|
64
71
|
## States
|
package/dist/skill/choosing.md
CHANGED
|
@@ -171,6 +171,7 @@ the records (tickets, letters, invoices; `current` on the open one; a row's own
|
|
|
171
171
|
| Accordion / Tabs | Accordion when the user may need several sections open or reads them in order (FAQ, settings groups). Tabs when sections are alternatives viewed one at a time. |
|
|
172
172
|
| Divider / gap | Divider inside a block between rows or a form and its footer. Between blocks and groups use air (`gap`), not lines. |
|
|
173
173
|
| Breadcrumb / back button | Breadcrumb on pages below a top-level section (Счета → № 2026-0418) and deeper; not on top-level pages. A single “Back” without hierarchy → `LinkButton` or `Button.Root variant="ghost"`. |
|
|
174
|
+
| DataTable grip `end` / `start` / `row`, column order | Rows whose order is data (stages, a price list): `onReorder` with the grip at the end of the row (`reorderHandle="end"`, the default — after the row actions); `start` only when the order is the list's main point and nothing is selected; `row` (the whole row carries) only for short rows with nothing to select, copy or follow as a link. Sorted by a column, rows do not reorder — say so, never hide the grip. Columns people arrange for themselves: `columnOrder` with `hiddenColumns` and the column chooser — a header drag (the header moves alone), Alt + ← / → and the chooser's grips; the key column `reorderable: false` (or pinned), the actions column `hideHeader`; the app saves both lists. |
|
|
174
175
|
| Pagination / infinite scroll | Pages for tables people return to or reference: DataTable `paging="pages"` (default, Pagination in the footer). `paging="infinite"` for feeds. Standalone Pagination only for lists that are not a DataTable. |
|
|
175
176
|
| Stepper / Tabs | Stepper for a sequential process with completion status; Tabs for non-sequential views. |
|
|
176
177
|
| Gantt / Timeline / Kanban / DataTable | Gantt: records with a start and an end compared across time (who is busy when, a plan with phases and milestones), moved, stretched and drawn by hand (`onBarChange`, `onBarCreate`). Timeline: a history of events at points in time, read top to bottom. Kanban: work items moved between statuses, time does not matter. DataTable: many records compared by many attributes, sorted, filtered and selected — dates are only columns. |
|
package/dist/skill/components.md
CHANGED
|
@@ -40,7 +40,7 @@ Type a value, and the field anatomy: label, hint, error.
|
|
|
40
40
|
| Label | Field label (native `<label>`) with required and optional markers. | [COMPONENT.md](reference/components/label/COMPONENT.md) · [examples](reference/components/label/examples/) |
|
|
41
41
|
| Hint | Help text or a validation error under a field. | [COMPONENT.md](reference/components/hint/COMPONENT.md) · [examples](reference/components/hint/examples/) |
|
|
42
42
|
| Fieldset | A frameless group of related form fields: a native `<fieldset>` with a `title-s` legend, the form rhythm between its fields and one `disabled` for all of them. | [COMPONENT.md](reference/components/fieldset/COMPONENT.md) · [examples](reference/components/fieldset/examples/) |
|
|
43
|
-
| FieldList | An editable list of records of one shape — invoice lines, specs, contacts, prices by period: one row per record, the column headings once above the rows,
|
|
43
|
+
| FieldList | An editable list of records of one shape — invoice lines, specs, contacts, prices by period: one row per record on one grid, the column headings once above the rows, the row's actions at its end and an add button under them. | [COMPONENT.md](reference/components/field-list/COMPONENT.md) · [examples](reference/components/field-list/examples/) |
|
|
44
44
|
|
|
45
45
|
## Selection (`selection`)
|
|
46
46
|
|