prime-ui-kit 0.9.1 → 0.9.2
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 +22 -8
- package/dist/chunks/{chunk-KCQFOORX.js → chunk-IQELQNMR.js} +1 -1
- package/dist/chunks/{chunk-DB2Y3XXA.js → chunk-LXGRKN34.js} +2323 -1500
- package/dist/chunks/{chunk-NHOWNIAR.js → chunk-ZEFCDEEQ.js} +790 -536
- package/dist/color-picker.js +2 -2
- package/dist/components/data-table/DataTable.d.ts +6 -1
- package/dist/components/data-table/types.d.ts +5 -0
- package/dist/components/dnd/Dnd.d.ts +1 -1
- package/dist/components/dnd/dragSession.d.ts +9 -0
- package/dist/components/dnd/useDropTarget.d.ts +5 -0
- package/dist/components/dnd/useFlipList.d.ts +3 -3
- package/dist/components/drawer/Drawer.d.ts +8 -5
- package/dist/components/dropdown/Dropdown.d.ts +17 -0
- package/dist/components/index.d.ts +5 -1
- package/dist/components/kanban/Kanban.d.ts +129 -0
- package/dist/components/modal/Modal.d.ts +5 -2
- package/dist/components/page-toolbar/PageToolbar.d.ts +53 -0
- package/dist/components/segmented-control/SegmentedControl.d.ts +5 -2
- package/dist/components/tabs/Tabs.d.ts +5 -2
- package/dist/hooks/useEdgeOverflow.d.ts +12 -0
- package/dist/hooks/useMediaQuery.d.ts +7 -0
- package/dist/hooks/useSwipeDismiss.d.ts +34 -0
- package/dist/index.css +2271 -1163
- package/dist/index.js +10 -2
- package/dist/internal/overlay/FloatingPanel.d.ts +3 -1
- package/dist/internal/overlay/useFloatingLayer.d.ts +11 -1
- package/dist/internal/touchTarget.d.ts +4 -0
- package/dist/layout/app-header/AppHeader.d.ts +110 -0
- package/dist/layout/app-shell/AppShell.d.ts +14 -9
- package/dist/layout/bottom-nav/BottomNav.d.ts +80 -0
- package/dist/layout/index.d.ts +5 -1
- package/dist/tokens/primitives.d.ts +4 -0
- package/dist/tokens/semantic.d.ts +56 -0
- package/dist/tokens/themes/dark.d.ts +4 -0
- package/package.json +3 -2
- package/src/components/accordion/COMPONENT.md +1 -1
- package/src/components/badge/COMPONENT.md +2 -2
- package/src/components/banner/COMPONENT.md +1 -1
- package/src/components/checkbox/examples/examples.module.css +4 -2
- package/src/components/crossfade/COMPONENT.md +1 -1
- package/src/components/data-table/COMPONENT.md +19 -6
- package/src/components/data-table/examples/columns-visibility.tsx +167 -0
- package/src/components/digit-input/COMPONENT.md +10 -10
- package/src/components/digit-input/examples/examples.module.css +8 -0
- package/src/components/digit-input/examples/in-form.tsx +2 -5
- package/src/components/digit-input/examples/sizes.tsx +1 -1
- package/src/components/divider/COMPONENT.md +1 -1
- package/src/components/dnd/COMPONENT.md +3 -3
- package/src/components/drawer/COMPONENT.md +17 -9
- package/src/components/drawer/examples/date-sheet.tsx +41 -0
- package/src/components/drawer/examples/examples.module.css +5 -0
- package/src/components/drawer/examples/placement.tsx +4 -2
- package/src/components/dropdown/COMPONENT.md +19 -5
- package/src/components/dropdown/examples/checkbox-items.tsx +48 -0
- package/src/components/empty-page/COMPONENT.md +1 -1
- package/src/components/kanban/COMPONENT.md +181 -0
- package/src/components/kanban/examples/controlled.tsx +78 -0
- package/src/components/kanban/examples/examples.module.css +31 -0
- package/src/components/kanban/examples/limits.tsx +58 -0
- package/src/components/kanban/examples/narrow.tsx +76 -0
- package/src/components/kanban/examples/overview.tsx +130 -0
- package/src/components/kanban/examples/states.tsx +75 -0
- package/src/components/kanban/examples/structure.tsx +76 -0
- package/src/components/login-form/COMPONENT.md +1 -1
- package/src/components/modal/COMPONENT.md +9 -6
- package/src/components/notification/COMPONENT.md +2 -2
- package/src/components/page-content/COMPONENT.md +1 -1
- package/src/components/page-toolbar/COMPONENT.md +142 -0
- package/src/components/page-toolbar/examples/examples.module.css +16 -0
- package/src/components/page-toolbar/examples/narrow.tsx +103 -0
- package/src/components/page-toolbar/examples/overview.tsx +113 -0
- package/src/components/page-toolbar/examples/save-changes.tsx +40 -0
- package/src/components/page-toolbar/examples/without-search.tsx +60 -0
- package/src/components/popover/COMPONENT.md +4 -3
- package/src/components/progress-bar/COMPONENT.md +1 -1
- package/src/components/progress-circle/COMPONENT.md +1 -1
- package/src/components/scroll-container/COMPONENT.md +1 -1
- package/src/components/segmented-control/COMPONENT.md +8 -8
- package/src/components/segmented-control/examples/full-width.tsx +1 -1
- package/src/components/select/COMPONENT.md +2 -1
- package/src/components/skeleton/COMPONENT.md +1 -1
- package/src/components/smart-filter/COMPONENT.md +2 -0
- package/src/components/spinner/COMPONENT.md +1 -1
- package/src/components/tabs/COMPONENT.md +11 -8
- package/src/components/tabs/examples/closable.tsx +1 -1
- package/src/layout/app-header/COMPONENT.md +178 -0
- package/src/layout/app-header/examples/breadcrumbs.tsx +36 -0
- package/src/layout/app-header/examples/examples.module.css +47 -0
- package/src/layout/app-header/examples/in-app-shell.tsx +70 -0
- package/src/layout/app-header/examples/narrow.tsx +29 -0
- package/src/layout/app-header/examples/overview.tsx +36 -0
- package/src/layout/app-shell/COMPONENT.md +27 -21
- package/src/layout/app-shell/examples/examples.module.css +15 -0
- package/src/layout/app-shell/examples/footer.tsx +59 -0
- package/src/layout/app-shell/examples/overview.tsx +19 -8
- package/src/layout/bottom-nav/COMPONENT.md +153 -0
- package/src/layout/bottom-nav/examples/examples.module.css +39 -0
- package/src/layout/bottom-nav/examples/floating.tsx +89 -0
- package/src/layout/bottom-nav/examples/icon-only.tsx +41 -0
- package/src/layout/bottom-nav/examples/in-app-shell.tsx +64 -0
- package/src/layout/bottom-nav/examples/overview.tsx +44 -0
- package/src/layout/bottom-nav/examples/router.tsx +31 -0
- package/src/layout/bottom-nav/examples/structure.tsx +47 -0
- package/src/layout/sidebar/COMPONENT.md +11 -10
- package/src/styles/theme-dark.css +3 -0
- package/src/styles/theme-light.css +24 -0
- package/src/styles/tokens.css +2 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# AppHeader
|
|
2
|
+
|
|
3
|
+
**Category:** page
|
|
4
|
+
**Kind:** layout
|
|
5
|
+
|
|
6
|
+
> The bar at the top of the app's content panel: where you are, global search and a few actions.
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
- The top row of an app built on [AppShell](../app-shell/COMPONENT.md): the section title or the path, the ⌘K search entry, notifications, the account, one primary action.
|
|
10
|
+
- The phone header: the menu button that opens the off-canvas Sidebar, the title, search as an icon.
|
|
11
|
+
|
|
12
|
+
## When not to use
|
|
13
|
+
- The page heading, its description and page actions inside main → use [PageContent](../../components/page-content/COMPONENT.md) (`PageContent.Title` is the `<h1>`).
|
|
14
|
+
- Tabs, filters and search for the data on the page → use [PageToolbar](../../components/page-toolbar/COMPONENT.md).
|
|
15
|
+
- App navigation → use [Sidebar](../sidebar/COMPONENT.md) and, on a phone, [BottomNav](../bottom-nav/COMPONENT.md); the header holds at most the menu button.
|
|
16
|
+
- The search dialog itself → use [CommandMenu](../../components/command-menu/COMPONENT.md); `AppHeader.Search` only opens it.
|
|
17
|
+
|
|
18
|
+
## Import
|
|
19
|
+
```tsx
|
|
20
|
+
import { AppHeader } from "prime-ui-kit";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Anatomy
|
|
24
|
+
```
|
|
25
|
+
AppHeader.Root <header>, one sticky row as high as the Sidebar brand row
|
|
26
|
+
├─ AppHeader.Start leading zone, takes the free width
|
|
27
|
+
│ ├─ AppHeader.MenuButton opens the off-canvas Sidebar (below 768px by default)
|
|
28
|
+
│ ├─ AppHeader.Separator short vertical line between groups (a back Button | a Breadcrumb)
|
|
29
|
+
│ └─ AppHeader.Title name, truncates (or a Breadcrumb instead)
|
|
30
|
+
│ ├─ AppHeader.Icon decorative glyph on a tile shaped like a soft button m
|
|
31
|
+
│ └─ AppHeader.Description muted caption under the name
|
|
32
|
+
├─ AppHeader.Search field-looking button that opens the CommandMenu
|
|
33
|
+
└─ AppHeader.Actions trailing buttons: notifications, account, primary action
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
<!-- Generated from api.ts by `bun run docs:build`. Edit api.ts, not this section. -->
|
|
39
|
+
|
|
40
|
+
### AppHeader.Root
|
|
41
|
+
`ref` → `HTMLElement`. The `<header>` bar at the top of the content panel: one row as high as the Sidebar brand row, on the panel surface with no divider, sticky with the top safe-area inset (static below 480px of viewport height); inline padding is the shell gutter, so it lines up with the page in main (16 outside a shell). Its controls are size `m`; icon buttons inside are `soft` (a light fill), not `ghost`. A container (`prime-app-header`): below 36rem the icon tile and the description go and the search folds into an icon.
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Default | Description |
|
|
44
|
+
|---|---|---|---|
|
|
45
|
+
| `labels` | `Partial<AppHeaderLabels>` | — | Built-in strings, see Labels. |
|
|
46
|
+
| `…rest` | `HTMLAttributes<HTMLElement>` | — | `children` (`AppHeader.Start`, `AppHeader.Search`, `AppHeader.Actions`), `className` and the other attributes. |
|
|
47
|
+
|
|
48
|
+
### AppHeader.Start
|
|
49
|
+
`ref` → `HTMLDivElement`. The leading zone that takes the free width: the menu button, a back button, the title or a Breadcrumb.
|
|
50
|
+
|
|
51
|
+
| Prop | Type | Default | Description |
|
|
52
|
+
|---|---|---|---|
|
|
53
|
+
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `children`, `className` and the other div attributes. |
|
|
54
|
+
|
|
55
|
+
### AppHeader.Title
|
|
56
|
+
`ref` → `HTMLDivElement`. Where you are: an optional `AppHeader.Icon`, the name (title-s, truncates) and an optional `AppHeader.Description` under it — the anatomy of the Sidebar brand. Not a heading: the page `<h1>` is PageContent.Title.
|
|
57
|
+
|
|
58
|
+
| Prop | Type | Default | Description |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `children` (the name, `AppHeader.Icon`, `AppHeader.Description` in any order), `className` and the other div attributes. |
|
|
61
|
+
|
|
62
|
+
### AppHeader.Icon
|
|
63
|
+
`ref` → `HTMLSpanElement`. Decorative glyph before the title (`aria-hidden`) on a tile shaped like the bar's soft buttons: control m square (36), its radius and the subtle fill.
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Default | Description |
|
|
66
|
+
|---|---|---|---|
|
|
67
|
+
| `…rest` | `HTMLAttributes<HTMLSpanElement>` | — | `children` (an `Icon`), `className` and the other span attributes. |
|
|
68
|
+
|
|
69
|
+
### AppHeader.Description
|
|
70
|
+
`ref` → `HTMLSpanElement`. Muted caption under the title (a workspace, a period); hidden on a narrow header.
|
|
71
|
+
|
|
72
|
+
| Prop | Type | Default | Description |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| `…rest` | `HTMLAttributes<HTMLSpanElement>` | — | `children`, `className` and the other span attributes. |
|
|
75
|
+
|
|
76
|
+
### AppHeader.Separator
|
|
77
|
+
`ref` → `HTMLDivElement`. A short vertical `Divider` (20) between groups in a zone — a back button and the path — with 16 of air on each side.
|
|
78
|
+
|
|
79
|
+
| Prop | Type | Default | Description |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| `…rest` | `Omit<DividerProps, "orientation" \| "children">` | — | `className` and the other div attributes. |
|
|
82
|
+
|
|
83
|
+
### AppHeader.Search
|
|
84
|
+
`ref` → `HTMLButtonElement`. The global search entry: a `<button type="button">` drawn as a field (search icon, placeholder text, key hint) that opens your CommandMenu. Below 36rem of header width it folds into a square button named by its text.
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Description |
|
|
87
|
+
|---|---|---|---|
|
|
88
|
+
| `children` | `ReactNode` | — (required) | The placeholder text; also the accessible name. |
|
|
89
|
+
| `shortcut` | `ReactNode` | `"⌘K"` | The key hint at the end (a `Kbd`, hidden from assistive tech); `null` hides it. Bind the key yourself. |
|
|
90
|
+
| `…rest` | `ButtonHTMLAttributes<HTMLButtonElement>` | — | `onClick`, `className` and the other button attributes. |
|
|
91
|
+
|
|
92
|
+
### AppHeader.Actions
|
|
93
|
+
`ref` → `HTMLDivElement`. The trailing row of buttons: notifications, the account, one primary action. Never wraps.
|
|
94
|
+
|
|
95
|
+
| Prop | Type | Default | Description |
|
|
96
|
+
|---|---|---|---|
|
|
97
|
+
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `children`, `className` and the other div attributes. |
|
|
98
|
+
|
|
99
|
+
### AppHeader.MenuButton
|
|
100
|
+
`ref` → `HTMLButtonElement`. A soft neutral icon `Button` named by `labels.menu` that opens the off-canvas Sidebar; wire `onClick` and `aria-expanded`.
|
|
101
|
+
|
|
102
|
+
| Prop | Type | Default | Description |
|
|
103
|
+
|---|---|---|---|
|
|
104
|
+
| `show` | `"narrow" \| "always"` | `"narrow"` | `narrow` — only below 768px, where a Sidebar with `offCanvas="auto"` leaves the layout; `always` — on every width (`offCanvas="always"`). |
|
|
105
|
+
| `…rest` | `ButtonHTMLAttributes<HTMLButtonElement>` | — | `onClick`, `aria-expanded`, `aria-label` (replaces `labels.menu`), `className` and the other button attributes. |
|
|
106
|
+
|
|
107
|
+
## Variants
|
|
108
|
+
|
|
109
|
+
### show (MenuButton)
|
|
110
|
+
| Value | Looks like | Use when | Default |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| `narrow` | The menu button shows only below 768px | Sidebar with `offCanvas="auto"` | yes |
|
|
113
|
+
| `always` | The menu button on every width | Sidebar with `offCanvas="always"`, or you decide visibility yourself | |
|
|
114
|
+
|
|
115
|
+
### Structure
|
|
116
|
+
| Value | Looks like | Use when | Default |
|
|
117
|
+
|---|---|---|---|
|
|
118
|
+
| `AppHeader.Title` | Icon, name and a caption under it, like the Sidebar brand | A top-level section | |
|
|
119
|
+
| Breadcrumb in Start | A soft back button, `AppHeader.Separator` and the path | A nested record page | |
|
|
120
|
+
| with `AppHeader.Search` | A field-looking button with a key hint between Start and Actions | The app has a CommandMenu | |
|
|
121
|
+
| with `AppHeader.Actions` | A row of buttons at the end | Notifications, account, one primary action | |
|
|
122
|
+
|
|
123
|
+
## States
|
|
124
|
+
| State | Driven by | DOM |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| narrow header | header width below 36rem (container `prime-app-header`) | the icon tile and the description hide; the search folds into a square button, its text stays as the name |
|
|
127
|
+
| menu button hidden | `show="narrow"` and viewport from 768px | `data-show="narrow"` on MenuButton |
|
|
128
|
+
| short viewport | viewport below 480px high (a phone on its side) | Root stops sticking |
|
|
129
|
+
|
|
130
|
+
## Layout & spacing
|
|
131
|
+
- Row min height = control m + `--prime-space-2` (44), padding-block `--prime-space-3` (the top grows to the safe-area inset): 68 in all, the height of the Sidebar header, so the brand and the title share one line.
|
|
132
|
+
- Inline padding: the shell gutters (16 → 24 → 32, the same as `AppShell.Main`) in the shell's panel, so the header lines up with the page; `--prime-space-4` elsewhere.
|
|
133
|
+
- Icon buttons are `soft` neutral (MenuButton is), never `ghost`: the search folds into a filled square too, so every button on the bar has a shape.
|
|
134
|
+
- Gaps: `--prime-space-3` between zones, `--prime-space-2` inside Start and Actions; `AppHeader.Separator` adds `--prime-space-2` on each side (16 in all) and is 20 high.
|
|
135
|
+
- `AppHeader.Icon` is a 36 tile with the radius and fill of a soft neutral button m, so it lines up with the buttons on the bar.
|
|
136
|
+
- On the panel surface with no divider or shadow (depth from fill); `z-index: --prime-z-sticky`.
|
|
137
|
+
- Search: up to 288 wide, shrinks first; field tier m and the surface field fill. Controls inside are size `m`.
|
|
138
|
+
|
|
139
|
+
## Accessibility
|
|
140
|
+
|
|
141
|
+
### Keyboard
|
|
142
|
+
| Key | Action |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `Tab` | Moves through the menu button, the path links, the search and the actions in reading order. |
|
|
145
|
+
| `Enter` · `Space` | Presses the focused button: opens the menu, the search or runs the action. |
|
|
146
|
+
|
|
147
|
+
### ARIA
|
|
148
|
+
- Root is a `<header>`: the banner landmark when it sits at the top level of the page.
|
|
149
|
+
- Search is a button named by its text; the key hint is `aria-hidden`, and the app binds the shortcut.
|
|
150
|
+
- MenuButton is named by `labels.menu`; pass `aria-expanded` (whether the Sidebar is open).
|
|
151
|
+
- Title is not a heading: the page `<h1>` stays with PageContent.Title.
|
|
152
|
+
|
|
153
|
+
### Labels
|
|
154
|
+
<!-- Generated from api.ts by `bun run docs:build`. Edit api.ts, not this section. -->
|
|
155
|
+
|
|
156
|
+
| Key | Default | Used for |
|
|
157
|
+
|---|---|---|
|
|
158
|
+
| `menu` | `"Открыть меню"` | Name of `AppHeader.MenuButton`. |
|
|
159
|
+
|
|
160
|
+
## Examples
|
|
161
|
+
| Example | Shows |
|
|
162
|
+
|---|---|
|
|
163
|
+
| [overview.tsx](examples/overview.tsx) | The top bar of a screen: where you are, global search, notifications and the primary action — `AppHeader.Title`, `AppHeader.Search`, `AppHeader.Actions`. |
|
|
164
|
+
| [breadcrumbs.tsx](examples/breadcrumbs.tsx) | A nested page: a back button, a separator and the path instead of a title, actions on the record at the end — `AppHeader.Separator`, `AppHeader.Actions`. |
|
|
165
|
+
| [in-app-shell.tsx](examples/in-app-shell.tsx) | The header in the app frame: one row with the Sidebar brand across the two planes, sticky over main — `AppShell`, `Sidebar.Brand`. |
|
|
166
|
+
| [narrow.tsx](examples/narrow.tsx) | On a phone: the menu button opens the navigation, the description goes and the search folds into an icon — `AppHeader.MenuButton`, `show`. |
|
|
167
|
+
|
|
168
|
+
## Mistakes
|
|
169
|
+
- A border or shadow under the header → it sits on the panel surface; the fill is the boundary.
|
|
170
|
+
- `AppHeader.Title` as the page `<h1>` → the heading belongs to PageContent.Title in main.
|
|
171
|
+
- A real text input for global search → `AppHeader.Search` opens the CommandMenu, where typing happens.
|
|
172
|
+
- More than three actions → keep one primary action; the rest go into the page or a Dropdown.
|
|
173
|
+
- A hand-made menu button with a media query → `AppHeader.MenuButton` follows the Sidebar breakpoint.
|
|
174
|
+
- `ghost` icon buttons in the header → `variant="soft" tone="neutral"`: a light fill gives each button a shape on the bar.
|
|
175
|
+
|
|
176
|
+
## Related
|
|
177
|
+
- **Built from:** [Button](../../components/button/COMPONENT.md), [Kbd](../../components/kbd/COMPONENT.md), [Divider](../../components/divider/COMPONENT.md), Icon (`action.search`, `nav.menu`)
|
|
178
|
+
- **See also:** [AppShell](../app-shell/COMPONENT.md), [Sidebar](../sidebar/COMPONENT.md), [PageContent](../../components/page-content/COMPONENT.md), [PageToolbar](../../components/page-toolbar/COMPONENT.md), [CommandMenu](../../components/command-menu/COMPONENT.md), [Breadcrumb](../../components/breadcrumb/COMPONENT.md)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** A nested page: a back button, a separator and the path instead of a title, actions on the record at the end — `AppHeader.Separator`, `AppHeader.Actions`. */
|
|
2
|
+
import { AppHeader, Breadcrumb, Button, Icon } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
import styles from "./examples.module.css";
|
|
5
|
+
|
|
6
|
+
export default function AppHeaderBreadcrumbsExample() {
|
|
7
|
+
return (
|
|
8
|
+
<div className={styles.window}>
|
|
9
|
+
<AppHeader.Root>
|
|
10
|
+
<AppHeader.Start>
|
|
11
|
+
<Button.Root variant="soft" tone="neutral" aria-label="Назад к клиентам">
|
|
12
|
+
<Button.Icon>
|
|
13
|
+
<Icon name="nav.chevronLeft" />
|
|
14
|
+
</Button.Icon>
|
|
15
|
+
</Button.Root>
|
|
16
|
+
<AppHeader.Separator />
|
|
17
|
+
<Breadcrumb.Root>
|
|
18
|
+
<Breadcrumb.Item href="#crm">CRM</Breadcrumb.Item>
|
|
19
|
+
<Breadcrumb.Item href="#clients">Клиенты</Breadcrumb.Item>
|
|
20
|
+
<Breadcrumb.Item current>ООО «Север»</Breadcrumb.Item>
|
|
21
|
+
</Breadcrumb.Root>
|
|
22
|
+
</AppHeader.Start>
|
|
23
|
+
<AppHeader.Actions>
|
|
24
|
+
<Button.Root variant="soft" tone="neutral">
|
|
25
|
+
Экспорт
|
|
26
|
+
</Button.Root>
|
|
27
|
+
<Button.Root variant="soft" tone="neutral" aria-label="Ещё действия">
|
|
28
|
+
<Button.Icon>
|
|
29
|
+
<Icon name="action.more" />
|
|
30
|
+
</Button.Icon>
|
|
31
|
+
</Button.Root>
|
|
32
|
+
</AppHeader.Actions>
|
|
33
|
+
</AppHeader.Root>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* Layout of the AppHeader scenarios: an app window and a phone-wide screen. Semantic tokens only. */
|
|
2
|
+
|
|
3
|
+
/* The top of an app window: the content panel surface with the header on it. */
|
|
4
|
+
.window {
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
width: 100%;
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
border-radius: var(--prime-card-radius);
|
|
9
|
+
background: var(--prime-color-bg-surface);
|
|
10
|
+
box-shadow:
|
|
11
|
+
0 0 0 var(--prime-border-width) var(--prime-color-border-subtle),
|
|
12
|
+
var(--prime-shadow-raised);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* narrow.tsx: the same window, phone-wide, so the header folds its search. */
|
|
16
|
+
.phone {
|
|
17
|
+
width: min(100%, var(--prime-drawer-width-s));
|
|
18
|
+
margin-inline: auto;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* in-app-shell.tsx: a whole app window with the rail on the canvas. */
|
|
22
|
+
.stage {
|
|
23
|
+
box-sizing: border-box;
|
|
24
|
+
display: flex;
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: calc(var(--prime-space-24) * 4);
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
border-radius: var(--prime-card-radius);
|
|
29
|
+
background: var(--prime-color-bg-canvas);
|
|
30
|
+
box-shadow:
|
|
31
|
+
0 0 0 var(--prime-border-width) var(--prime-color-border-subtle),
|
|
32
|
+
var(--prime-shadow-raised);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* The shell fills the window frame instead of the viewport. */
|
|
36
|
+
.shell {
|
|
37
|
+
height: 100%;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* The product mark inside `Sidebar.BrandLogo`: an accent tile with a glyph. */
|
|
41
|
+
.logo {
|
|
42
|
+
display: grid;
|
|
43
|
+
place-items: center;
|
|
44
|
+
border-radius: var(--prime-radius-m);
|
|
45
|
+
background: var(--prime-color-accent-default);
|
|
46
|
+
color: var(--prime-color-accent-fg);
|
|
47
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** The header in the app frame: one row with the Sidebar brand across the two planes, sticky over main — `AppShell`, `Sidebar.Brand`. */
|
|
2
|
+
import { AppHeader, AppShell, Icon, PageContent, Sidebar, Typography } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
import styles from "./examples.module.css";
|
|
5
|
+
|
|
6
|
+
const ORDERS = [
|
|
7
|
+
"№ 4821 · ООО «Север» · 84 000 ₽",
|
|
8
|
+
"№ 4820 · ИП Котов · 12 500 ₽",
|
|
9
|
+
"№ 4819 · ООО «Вектор» · 230 000 ₽",
|
|
10
|
+
"№ 4818 · АО «Меридиан» · 47 900 ₽",
|
|
11
|
+
"№ 4817 · ООО «Полюс» · 9 800 ₽",
|
|
12
|
+
"№ 4816 · ИП Белова · 156 000 ₽",
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
export default function AppHeaderInAppShellExample() {
|
|
16
|
+
return (
|
|
17
|
+
<div className={styles.stage}>
|
|
18
|
+
<AppShell.Root fillViewport className={styles.shell}>
|
|
19
|
+
<AppShell.Nav>
|
|
20
|
+
<Sidebar.Root offCanvas="never">
|
|
21
|
+
<Sidebar.Header>
|
|
22
|
+
<Sidebar.Brand href="#home" description="Отдел продаж">
|
|
23
|
+
<Sidebar.BrandLogo>
|
|
24
|
+
<span className={styles.logo}>
|
|
25
|
+
<Icon name="nav.layoutGrid" />
|
|
26
|
+
</span>
|
|
27
|
+
</Sidebar.BrandLogo>
|
|
28
|
+
Acme CRM
|
|
29
|
+
</Sidebar.Brand>
|
|
30
|
+
</Sidebar.Header>
|
|
31
|
+
<Sidebar.Content>
|
|
32
|
+
<Sidebar.Item>
|
|
33
|
+
<Sidebar.ItemIcon>
|
|
34
|
+
<Icon name="nav.home" />
|
|
35
|
+
</Sidebar.ItemIcon>
|
|
36
|
+
Обзор
|
|
37
|
+
</Sidebar.Item>
|
|
38
|
+
<Sidebar.Item current>
|
|
39
|
+
<Sidebar.ItemIcon>
|
|
40
|
+
<Icon name="object.package" />
|
|
41
|
+
</Sidebar.ItemIcon>
|
|
42
|
+
Заказы
|
|
43
|
+
</Sidebar.Item>
|
|
44
|
+
</Sidebar.Content>
|
|
45
|
+
</Sidebar.Root>
|
|
46
|
+
</AppShell.Nav>
|
|
47
|
+
<AppHeader.Root>
|
|
48
|
+
<AppHeader.Start>
|
|
49
|
+
<AppHeader.Title>
|
|
50
|
+
Заказы
|
|
51
|
+
<AppHeader.Description>128 в работе</AppHeader.Description>
|
|
52
|
+
</AppHeader.Title>
|
|
53
|
+
</AppHeader.Start>
|
|
54
|
+
<AppHeader.Search>Поиск</AppHeader.Search>
|
|
55
|
+
</AppHeader.Root>
|
|
56
|
+
<AppShell.Main>
|
|
57
|
+
<PageContent.Section>
|
|
58
|
+
<PageContent.Body>
|
|
59
|
+
{ORDERS.map((order) => (
|
|
60
|
+
<Typography key={order} variant="body-m">
|
|
61
|
+
{order}
|
|
62
|
+
</Typography>
|
|
63
|
+
))}
|
|
64
|
+
</PageContent.Body>
|
|
65
|
+
</PageContent.Section>
|
|
66
|
+
</AppShell.Main>
|
|
67
|
+
</AppShell.Root>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** On a phone: the menu button opens the navigation, the description goes and the search folds into an icon — `AppHeader.MenuButton`, `show`. */
|
|
2
|
+
import { AppHeader, Button, Icon } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
import styles from "./examples.module.css";
|
|
5
|
+
|
|
6
|
+
export default function AppHeaderNarrowExample() {
|
|
7
|
+
return (
|
|
8
|
+
<div className={`${styles.window} ${styles.phone}`}>
|
|
9
|
+
<AppHeader.Root>
|
|
10
|
+
<AppHeader.Start>
|
|
11
|
+
{/* `always`: this frame is phone-wide on any screen; in an app keep the default `narrow`. */}
|
|
12
|
+
<AppHeader.MenuButton show="always" aria-expanded={false} />
|
|
13
|
+
<AppHeader.Title>
|
|
14
|
+
Заказы
|
|
15
|
+
<AppHeader.Description>128 в работе</AppHeader.Description>
|
|
16
|
+
</AppHeader.Title>
|
|
17
|
+
</AppHeader.Start>
|
|
18
|
+
<AppHeader.Search>Поиск заказов</AppHeader.Search>
|
|
19
|
+
<AppHeader.Actions>
|
|
20
|
+
<Button.Root variant="soft" tone="neutral" aria-label="Новый заказ">
|
|
21
|
+
<Button.Icon>
|
|
22
|
+
<Icon name="action.add" />
|
|
23
|
+
</Button.Icon>
|
|
24
|
+
</Button.Root>
|
|
25
|
+
</AppHeader.Actions>
|
|
26
|
+
</AppHeader.Root>
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** The top bar of a screen: where you are, global search, notifications and the primary action — `AppHeader.Title`, `AppHeader.Search`, `AppHeader.Actions`. */
|
|
2
|
+
import { AppHeader, Button, Icon } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
import styles from "./examples.module.css";
|
|
5
|
+
|
|
6
|
+
export default function AppHeaderOverviewExample() {
|
|
7
|
+
return (
|
|
8
|
+
<div className={styles.window}>
|
|
9
|
+
<AppHeader.Root>
|
|
10
|
+
<AppHeader.Start>
|
|
11
|
+
<AppHeader.Title>
|
|
12
|
+
<AppHeader.Icon>
|
|
13
|
+
<Icon name="nav.dashboard" />
|
|
14
|
+
</AppHeader.Icon>
|
|
15
|
+
Обзор
|
|
16
|
+
<AppHeader.Description>Отдел продаж · октябрь</AppHeader.Description>
|
|
17
|
+
</AppHeader.Title>
|
|
18
|
+
</AppHeader.Start>
|
|
19
|
+
<AppHeader.Search>Поиск заказов и клиентов</AppHeader.Search>
|
|
20
|
+
<AppHeader.Actions>
|
|
21
|
+
<Button.Root variant="soft" tone="neutral" aria-label="Уведомления">
|
|
22
|
+
<Button.Icon>
|
|
23
|
+
<Icon name="object.bell" />
|
|
24
|
+
</Button.Icon>
|
|
25
|
+
</Button.Root>
|
|
26
|
+
<Button.Root>
|
|
27
|
+
<Button.Icon>
|
|
28
|
+
<Icon name="action.add" />
|
|
29
|
+
</Button.Icon>
|
|
30
|
+
Новый заказ
|
|
31
|
+
</Button.Root>
|
|
32
|
+
</AppHeader.Actions>
|
|
33
|
+
</AppHeader.Root>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
# AppShell
|
|
2
2
|
|
|
3
|
-
**Category:**
|
|
3
|
+
**Category:** page
|
|
4
4
|
**Kind:** layout
|
|
5
5
|
|
|
6
6
|
> The app frame: a navigation rail on the canvas and a content panel on the surface.
|
|
7
7
|
|
|
8
8
|
## When to use
|
|
9
|
-
- The root layout of an application: navigation column, optional
|
|
9
|
+
- The root layout of an application: navigation column, an optional AppHeader, scrolling main column, a bottom bar for phone navigation.
|
|
10
10
|
- Any page that needs the kit's responsive gutters and the surface context for cards and fields.
|
|
11
11
|
|
|
12
12
|
## When not to use
|
|
13
|
-
- The navigation itself → use [Sidebar](../sidebar/COMPONENT.md) inside `AppShell.Nav`.
|
|
13
|
+
- The navigation itself → use [Sidebar](../sidebar/COMPONENT.md) inside `AppShell.Nav`, [BottomNav](../bottom-nav/COMPONENT.md) inside `AppShell.Footer`.
|
|
14
|
+
- The top bar (title, search, actions, the menu button) → use [AppHeader](../app-header/COMPONENT.md) as a child of Root.
|
|
14
15
|
- Page heading, actions and sections inside main → use [PageContent](../../components/page-content/COMPONENT.md).
|
|
15
16
|
- A temporary side panel over the page → use [Drawer](../../components/drawer/COMPONENT.md).
|
|
16
17
|
- A scroll region inside a page → use [ScrollContainer](../../components/scroll-container/COMPONENT.md).
|
|
@@ -24,9 +25,10 @@ import { AppShell } from "prime-ui-kit";
|
|
|
24
25
|
```
|
|
25
26
|
AppShell.Root grid: nav column | content panel (bg-surface)
|
|
26
27
|
├─ AppShell.Nav navigation column on the canvas (usually Sidebar.Root)
|
|
27
|
-
├─
|
|
28
|
-
|
|
29
|
-
AppShell.
|
|
28
|
+
├─ AppHeader.Root sticky top bar of the panel (a separate component)
|
|
29
|
+
├─ AppShell.Main <main>, scrolls, carries the gutters
|
|
30
|
+
└─ AppShell.Footer sticky bottom bar of the panel (usually BottomNav.Root)
|
|
31
|
+
AppShell.Template Root + Nav + the header + Main + Footer in one component
|
|
30
32
|
```
|
|
31
33
|
Every child of Root that is not `AppShell.Nav` is placed into the content panel.
|
|
32
34
|
|
|
@@ -40,7 +42,7 @@ Every child of Root that is not `AppShell.Nav` is placed into the content panel.
|
|
|
40
42
|
| Prop | Type | Default | Description |
|
|
41
43
|
|---|---|---|---|
|
|
42
44
|
| `fillViewport` | `boolean` | `false` | The shell is exactly the viewport high and only `AppShell.Main` scrolls; otherwise the document scrolls and the nav is sticky. |
|
|
43
|
-
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `children` (Nav,
|
|
45
|
+
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `children` (Nav, `AppHeader.Root`, Main, Footer), `className` and the other div attributes. |
|
|
44
46
|
|
|
45
47
|
### AppShell.Nav
|
|
46
48
|
`ref` → `HTMLDivElement`. The navigation column slot (not a landmark: Sidebar renders the `<nav>`).
|
|
@@ -49,28 +51,29 @@ Every child of Root that is not `AppShell.Nav` is placed into the content panel.
|
|
|
49
51
|
|---|---|---|---|
|
|
50
52
|
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `children` (usually `Sidebar.Root`), `className` and the other div attributes. |
|
|
51
53
|
|
|
52
|
-
### AppShell.
|
|
53
|
-
`ref` → `HTMLElement`.
|
|
54
|
+
### AppShell.Main
|
|
55
|
+
`ref` → `HTMLElement`. The `<main>` with the canonical gutters: a vertical `ScrollContainer`.
|
|
54
56
|
|
|
55
57
|
| Prop | Type | Default | Description |
|
|
56
58
|
|---|---|---|---|
|
|
59
|
+
| `contentWidth` | `"contained" \| "full"` | `"full"` | `full` — the whole panel with gutters; `contained` — a centred column up to `--prime-layout-content-max-width`. |
|
|
57
60
|
| `…rest` | `HTMLAttributes<HTMLElement>` | — | `children`, `className` and the other attributes. |
|
|
58
61
|
|
|
59
|
-
### AppShell.
|
|
60
|
-
`ref` → `
|
|
62
|
+
### AppShell.Footer
|
|
63
|
+
`ref` → `HTMLDivElement`. Sticky bottom bar of the panel for `BottomNav`; no padding of its own. A container (`prime-shell-footer`): BottomNav inside shows only while the panel is narrower than 640px.
|
|
61
64
|
|
|
62
65
|
| Prop | Type | Default | Description |
|
|
63
66
|
|---|---|---|---|
|
|
64
|
-
| `
|
|
65
|
-
| `…rest` | `HTMLAttributes<HTMLElement>` | — | `children`, `className` and the other attributes. |
|
|
67
|
+
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `children` (usually `BottomNav.Root`), `className` and the other div attributes. |
|
|
66
68
|
|
|
67
69
|
### AppShell.Template
|
|
68
|
-
`ref` → the `<main>`. Root + Nav +
|
|
70
|
+
`ref` → the `<main>`. Root + Nav + the header + Main + Footer in one; main scrolls to the top when `scrollResetKey` changes.
|
|
69
71
|
|
|
70
72
|
| Prop | Type | Default | Description |
|
|
71
73
|
|---|---|---|---|
|
|
72
74
|
| `nav` | `ReactNode` | — | Navigation column content; without it the panel takes the full width. |
|
|
73
|
-
| `header` | `ReactNode` | — |
|
|
75
|
+
| `header` | `ReactNode` | — | The top bar of the panel, an `AppHeader.Root`; no header when omitted. |
|
|
76
|
+
| `footer` | `ReactNode` | — | Footer content (`BottomNav`); no footer when omitted. |
|
|
74
77
|
| `mainProps` | `Omit<AppShellMainProps, "children">` | — | Props for Main (e.g. `contentWidth`). |
|
|
75
78
|
| `scrollResetKey` | `unknown` | — | Main scrolls back to the top whenever this value changes; pass the router pathname. |
|
|
76
79
|
| `children` | `ReactNode` | — | Page content inside Main. |
|
|
@@ -95,7 +98,8 @@ Every child of Root that is not `AppShell.Nav` is placed into the content panel.
|
|
|
95
98
|
|---|---|---|---|
|
|
96
99
|
| with `AppShell.Nav` | Two columns: canvas rail + surface panel | Apps with navigation | |
|
|
97
100
|
| without Nav | Panel takes the full width | Single-page tools, auth screens | |
|
|
98
|
-
| with `
|
|
101
|
+
| with `AppHeader.Root` | Sticky bar at the top of the panel | Title or breadcrumbs, global search, actions, the mobile menu button | |
|
|
102
|
+
| with `AppShell.Footer` | Sticky bar at the bottom of the panel, shown while it holds a visible bar | BottomNav on a phone | |
|
|
99
103
|
|
|
100
104
|
`AppShell.Template` with `nav={<Sidebar.Root …/>}` and `PageContent` inside is the standard app; `contentWidth="contained"` + `PageContent.Root maxWidth="readable"` for docs and articles.
|
|
101
105
|
|
|
@@ -104,11 +108,12 @@ Every child of Root that is not `AppShell.Nav` is placed into the content panel.
|
|
|
104
108
|
|---|---|---|
|
|
105
109
|
| fixed frame | `fillViewport` | `data-fill-viewport="true"` on Root |
|
|
106
110
|
| content width | `contentWidth` | `data-content-width` on Main |
|
|
111
|
+
| footer bar | panel width (container `prime-shell-footer` on Footer) | BottomNav inside leaves from 640px of panel width; the empty footer takes no room |
|
|
107
112
|
|
|
108
113
|
## Layout & spacing
|
|
109
114
|
- Two full-height planes edge to edge: no inset, radius, shadow or border — the boundary is the fill change (canvas → surface).
|
|
110
|
-
- Gutters in Main
|
|
111
|
-
-
|
|
115
|
+
- Gutters in Main: `--prime-layout-gutter-s` (16) → `-m` (24) from 640px → `-l` (32) from 1024px. Main top padding `--prime-space-6` (24) → `--prime-space-10` (40) from 1024px; bottom `--prime-space-16`.
|
|
116
|
+
- Footer: no padding of its own (BottomNav keeps the bottom safe-area inset), sticky at the bottom, `z-index: --prime-z-sticky`.
|
|
112
117
|
- The panel is a surface context: fields use the surface field fill, Cards inside become sunken tiles without shadow.
|
|
113
118
|
|
|
114
119
|
## Accessibility
|
|
@@ -117,7 +122,7 @@ Every child of Root that is not `AppShell.Nav` is placed into the content panel.
|
|
|
117
122
|
No keyboard interaction.
|
|
118
123
|
|
|
119
124
|
### ARIA
|
|
120
|
-
- Main is the `<main>` landmark
|
|
125
|
+
- Main is the `<main>` landmark; the banner comes from AppHeader (`<header>`), the navigation landmarks from Sidebar and BottomNav (`<nav>`).
|
|
121
126
|
- Give the page one `<h1>` (PageContent.Title).
|
|
122
127
|
|
|
123
128
|
### Labels
|
|
@@ -128,8 +133,9 @@ No `labels`.
|
|
|
128
133
|
## Examples
|
|
129
134
|
| Example | Shows |
|
|
130
135
|
|---|---|
|
|
131
|
-
| [overview.tsx](examples/overview.tsx) | The app frame: Sidebar in the nav column, breadcrumbs in the
|
|
136
|
+
| [overview.tsx](examples/overview.tsx) | The app frame: Sidebar in the nav column, breadcrumbs in the AppHeader, the page in main; only main scrolls — `fillViewport`. |
|
|
132
137
|
| [contained.tsx](examples/contained.tsx) | A shell without navigation whose main column is centred and capped for long reads — `contentWidth`. |
|
|
138
|
+
| [footer.tsx](examples/footer.tsx) | A phone-wide app: the bar in the footer stays at the bottom while main scrolls under it, and leaves once the panel is 640px wide — `AppShell.Footer`. |
|
|
133
139
|
| [template.tsx](examples/template.tsx) | Root, nav, header and main in one component; main scrolls back to the top whenever the page changes — `AppShell.Template` with `scrollResetKey`. |
|
|
134
140
|
|
|
135
141
|
## Mistakes
|
|
@@ -141,4 +147,4 @@ No `labels`.
|
|
|
141
147
|
|
|
142
148
|
## Related
|
|
143
149
|
- **Built from:** [ScrollContainer](../../components/scroll-container/COMPONENT.md)
|
|
144
|
-
- **See also:** [Sidebar](../sidebar/COMPONENT.md), [PageContent](../../components/page-content/COMPONENT.md), [Breadcrumb](../../components/breadcrumb/COMPONENT.md)
|
|
150
|
+
- **See also:** [AppHeader](../app-header/COMPONENT.md), [Sidebar](../sidebar/COMPONENT.md), [BottomNav](../bottom-nav/COMPONENT.md), [PageContent](../../components/page-content/COMPONENT.md), [Breadcrumb](../../components/breadcrumb/COMPONENT.md)
|
|
@@ -27,3 +27,18 @@
|
|
|
27
27
|
.shell {
|
|
28
28
|
height: 100%;
|
|
29
29
|
}
|
|
30
|
+
|
|
31
|
+
/* footer.tsx: the same window, phone-wide, so the bar in the footer stays (it leaves from 640px). */
|
|
32
|
+
.phone {
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
display: flex;
|
|
35
|
+
width: min(100%, var(--prime-drawer-width-s));
|
|
36
|
+
height: calc(var(--prime-space-24) * 5);
|
|
37
|
+
margin-inline: auto;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
border-radius: var(--prime-card-radius);
|
|
40
|
+
background: var(--prime-color-bg-surface);
|
|
41
|
+
box-shadow:
|
|
42
|
+
0 0 0 var(--prime-border-width) var(--prime-color-border-subtle),
|
|
43
|
+
var(--prime-shadow-raised);
|
|
44
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/** A phone-wide app: the bar in the footer stays at the bottom while main scrolls under it, and leaves once the panel is 640px wide — `AppShell.Footer`. */
|
|
2
|
+
import { AppHeader, AppShell, BottomNav, Icon, PageContent, Typography } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
import styles from "./examples.module.css";
|
|
5
|
+
|
|
6
|
+
const SECTIONS = [
|
|
7
|
+
{ label: "Главная", icon: "nav.home" },
|
|
8
|
+
{ label: "Счета", icon: "object.receipt" },
|
|
9
|
+
{ label: "Клиенты", icon: "object.users" },
|
|
10
|
+
{ label: "Ещё", icon: "action.more" },
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
const INVOICES = [
|
|
14
|
+
"Счёт № 1207 · 84 000 ₽",
|
|
15
|
+
"Счёт № 1206 · 12 500 ₽",
|
|
16
|
+
"Счёт № 1205 · 230 000 ₽",
|
|
17
|
+
"Счёт № 1204 · 47 900 ₽",
|
|
18
|
+
"Счёт № 1203 · 9 800 ₽",
|
|
19
|
+
"Счёт № 1202 · 156 000 ₽",
|
|
20
|
+
"Счёт № 1201 · 31 200 ₽",
|
|
21
|
+
"Счёт № 1200 · 64 700 ₽",
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export default function AppShellFooterExample() {
|
|
25
|
+
return (
|
|
26
|
+
<div className={styles.phone}>
|
|
27
|
+
<AppShell.Root fillViewport className={styles.shell}>
|
|
28
|
+
<AppHeader.Root>
|
|
29
|
+
<AppHeader.Start>
|
|
30
|
+
<AppHeader.Title>Счета</AppHeader.Title>
|
|
31
|
+
</AppHeader.Start>
|
|
32
|
+
</AppHeader.Root>
|
|
33
|
+
<AppShell.Main>
|
|
34
|
+
<PageContent.Section>
|
|
35
|
+
<PageContent.Body>
|
|
36
|
+
{INVOICES.map((invoice) => (
|
|
37
|
+
<Typography key={invoice} variant="body-m">
|
|
38
|
+
{invoice}
|
|
39
|
+
</Typography>
|
|
40
|
+
))}
|
|
41
|
+
</PageContent.Body>
|
|
42
|
+
</PageContent.Section>
|
|
43
|
+
</AppShell.Main>
|
|
44
|
+
<AppShell.Footer>
|
|
45
|
+
<BottomNav.Root>
|
|
46
|
+
{SECTIONS.map((item, index) => (
|
|
47
|
+
<BottomNav.Item key={item.label} current={index === 1}>
|
|
48
|
+
<BottomNav.ItemIcon>
|
|
49
|
+
<Icon name={item.icon} />
|
|
50
|
+
</BottomNav.ItemIcon>
|
|
51
|
+
{item.label}
|
|
52
|
+
</BottomNav.Item>
|
|
53
|
+
))}
|
|
54
|
+
</BottomNav.Root>
|
|
55
|
+
</AppShell.Footer>
|
|
56
|
+
</AppShell.Root>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
/** The app frame: Sidebar in the nav column, breadcrumbs in the
|
|
2
|
-
import {
|
|
1
|
+
/** The app frame: Sidebar in the nav column, breadcrumbs in the AppHeader, the page in main; only main scrolls — `fillViewport`. */
|
|
2
|
+
import {
|
|
3
|
+
AppHeader,
|
|
4
|
+
AppShell,
|
|
5
|
+
Breadcrumb,
|
|
6
|
+
Button,
|
|
7
|
+
Icon,
|
|
8
|
+
PageContent,
|
|
9
|
+
Sidebar,
|
|
10
|
+
Typography,
|
|
11
|
+
} from "prime-ui-kit";
|
|
3
12
|
|
|
4
13
|
import styles from "./examples.module.css";
|
|
5
14
|
|
|
@@ -37,12 +46,14 @@ export default function AppShellOverviewExample() {
|
|
|
37
46
|
</Sidebar.Content>
|
|
38
47
|
</Sidebar.Root>
|
|
39
48
|
</AppShell.Nav>
|
|
40
|
-
<
|
|
41
|
-
<
|
|
42
|
-
<Breadcrumb.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
<AppHeader.Root>
|
|
50
|
+
<AppHeader.Start>
|
|
51
|
+
<Breadcrumb.Root>
|
|
52
|
+
<Breadcrumb.Item href="#crm">CRM</Breadcrumb.Item>
|
|
53
|
+
<Breadcrumb.Item current>Обзор</Breadcrumb.Item>
|
|
54
|
+
</Breadcrumb.Root>
|
|
55
|
+
</AppHeader.Start>
|
|
56
|
+
</AppHeader.Root>
|
|
46
57
|
<AppShell.Main>
|
|
47
58
|
<PageContent.Section>
|
|
48
59
|
<PageContent.Header>
|