@frame-kit/ui-ng 0.0.1
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/COMPONENTS.md +683 -0
- package/DEVELOPMENT_GUIDE.md +1102 -0
- package/LICENSE +21 -0
- package/README.md +69 -0
- package/THEMING.md +130 -0
- package/core/headline/README.md +121 -0
- package/core/icon/README.md +173 -0
- package/core/image/README.md +210 -0
- package/core/link/README.md +297 -0
- package/core/separator/README.md +145 -0
- package/core/text/README.md +240 -0
- package/directives/infinite-scroll/README.md +102 -0
- package/directives/spotlight/README.md +154 -0
- package/directives/tooltip/README.md +147 -0
- package/docs/endpoint-link/README.md +142 -0
- package/docs/method-badge/README.md +154 -0
- package/fesm2022/frame-kit-ui-ng-core-headline.mjs +122 -0
- package/fesm2022/frame-kit-ui-ng-core-headline.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-icon.mjs +189 -0
- package/fesm2022/frame-kit-ui-ng-core-icon.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-image.mjs +123 -0
- package/fesm2022/frame-kit-ui-ng-core-image.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-link.mjs +369 -0
- package/fesm2022/frame-kit-ui-ng-core-link.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-separator.mjs +59 -0
- package/fesm2022/frame-kit-ui-ng-core-separator.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-text.mjs +204 -0
- package/fesm2022/frame-kit-ui-ng-core-text.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs +74 -0
- package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs +76 -0
- package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs +425 -0
- package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs +63 -0
- package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs +43 -0
- package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-forms.mjs +3632 -0
- package/fesm2022/frame-kit-ui-ng-forms.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs +239 -0
- package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs +132 -0
- package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs +133 -0
- package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs +60 -0
- package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-services-toast.mjs +166 -0
- package/fesm2022/frame-kit-ui-ng-services-toast.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs +214 -0
- package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-alert.mjs +82 -0
- package/fesm2022/frame-kit-ui-ng-ui-alert.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs +76 -0
- package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs +81 -0
- package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-badge.mjs +81 -0
- package/fesm2022/frame-kit-ui-ng-ui-badge.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs +68 -0
- package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-button.mjs +108 -0
- package/fesm2022/frame-kit-ui-ng-ui-button.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-callout.mjs +58 -0
- package/fesm2022/frame-kit-ui-ng-ui-callout.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-card.mjs +70 -0
- package/fesm2022/frame-kit-ui-ng-ui-card.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs +113 -0
- package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs +1288 -0
- package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs +456 -0
- package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs +398 -0
- package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs +398 -0
- package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs +125 -0
- package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs +113 -0
- package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs +111 -0
- package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs +103 -0
- package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs +135 -0
- package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-loader.mjs +81 -0
- package/fesm2022/frame-kit-ui-ng-ui-loader.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs +79 -0
- package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs +40 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs +110 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs +91 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs +86 -0
- package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs +443 -0
- package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-note.mjs +56 -0
- package/fesm2022/frame-kit-ui-ng-ui-note.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs +105 -0
- package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs +110 -0
- package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs +129 -0
- package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs +42 -0
- package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs +894 -0
- package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs +81 -0
- package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-toast.mjs +179 -0
- package/fesm2022/frame-kit-ui-ng-ui-toast.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs +143 -0
- package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs +191 -0
- package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng.mjs +58 -0
- package/fesm2022/frame-kit-ui-ng.mjs.map +1 -0
- package/layouts/app-shell/README.md +357 -0
- package/layouts/content-split/README.md +180 -0
- package/package.json +253 -0
- package/services/overlay-orchestrator/README.md +184 -0
- package/services/spotlight/README.md +61 -0
- package/services/toast/README.md +118 -0
- package/types/frame-kit-ui-ng-core-headline.d.ts +38 -0
- package/types/frame-kit-ui-ng-core-icon.d.ts +74 -0
- package/types/frame-kit-ui-ng-core-image.d.ts +93 -0
- package/types/frame-kit-ui-ng-core-link.d.ts +251 -0
- package/types/frame-kit-ui-ng-core-separator.d.ts +28 -0
- package/types/frame-kit-ui-ng-core-text.d.ts +186 -0
- package/types/frame-kit-ui-ng-directives-infinite-scroll.d.ts +42 -0
- package/types/frame-kit-ui-ng-directives-spotlight.d.ts +51 -0
- package/types/frame-kit-ui-ng-directives-tooltip.d.ts +70 -0
- package/types/frame-kit-ui-ng-docs-endpoint-link.d.ts +43 -0
- package/types/frame-kit-ui-ng-docs-method-badge.d.ts +30 -0
- package/types/frame-kit-ui-ng-forms.d.ts +1674 -0
- package/types/frame-kit-ui-ng-layouts-app-shell.d.ts +75 -0
- package/types/frame-kit-ui-ng-layouts-content-split.d.ts +43 -0
- package/types/frame-kit-ui-ng-services-overlay-orchestrator.d.ts +96 -0
- package/types/frame-kit-ui-ng-services-spotlight.d.ts +32 -0
- package/types/frame-kit-ui-ng-services-toast.d.ts +100 -0
- package/types/frame-kit-ui-ng-ui-accordion.d.ts +86 -0
- package/types/frame-kit-ui-ng-ui-alert.d.ts +34 -0
- package/types/frame-kit-ui-ng-ui-avatar-stack.d.ts +38 -0
- package/types/frame-kit-ui-ng-ui-avatar.d.ts +36 -0
- package/types/frame-kit-ui-ng-ui-badge.d.ts +33 -0
- package/types/frame-kit-ui-ng-ui-breadcrumb.d.ts +45 -0
- package/types/frame-kit-ui-ng-ui-button.d.ts +48 -0
- package/types/frame-kit-ui-ng-ui-callout.d.ts +26 -0
- package/types/frame-kit-ui-ng-ui-card.d.ts +30 -0
- package/types/frame-kit-ui-ng-ui-copyable-field.d.ts +62 -0
- package/types/frame-kit-ui-ng-ui-data-table.d.ts +482 -0
- package/types/frame-kit-ui-ng-ui-dialog.d.ts +166 -0
- package/types/frame-kit-ui-ng-ui-drawer.d.ts +130 -0
- package/types/frame-kit-ui-ng-ui-dropdown-menu.d.ts +77 -0
- package/types/frame-kit-ui-ng-ui-editable-field.d.ts +65 -0
- package/types/frame-kit-ui-ng-ui-icon-badge.d.ts +45 -0
- package/types/frame-kit-ui-ng-ui-icon-list.d.ts +67 -0
- package/types/frame-kit-ui-ng-ui-inline-edit.d.ts +44 -0
- package/types/frame-kit-ui-ng-ui-list-editor.d.ts +56 -0
- package/types/frame-kit-ui-ng-ui-loader.d.ts +32 -0
- package/types/frame-kit-ui-ng-ui-menu-item.d.ts +27 -0
- package/types/frame-kit-ui-ng-ui-nav-brand.d.ts +25 -0
- package/types/frame-kit-ui-ng-ui-nav-group.d.ts +60 -0
- package/types/frame-kit-ui-ng-ui-nav-separator.d.ts +33 -0
- package/types/frame-kit-ui-ng-ui-node-tree-breadcrumb.d.ts +35 -0
- package/types/frame-kit-ui-ng-ui-node-tree.d.ts +135 -0
- package/types/frame-kit-ui-ng-ui-note.d.ts +22 -0
- package/types/frame-kit-ui-ng-ui-numbered-list.d.ts +52 -0
- package/types/frame-kit-ui-ng-ui-pagination.d.ts +49 -0
- package/types/frame-kit-ui-ng-ui-progress-bar.d.ts +50 -0
- package/types/frame-kit-ui-ng-ui-sidenav-link.d.ts +24 -0
- package/types/frame-kit-ui-ng-ui-tabs.d.ts +266 -0
- package/types/frame-kit-ui-ng-ui-timeline.d.ts +42 -0
- package/types/frame-kit-ui-ng-ui-toast.d.ts +56 -0
- package/types/frame-kit-ui-ng-ui-user-menu.d.ts +87 -0
- package/types/frame-kit-ui-ng-ui-wizard-dialog.d.ts +116 -0
- package/types/frame-kit-ui-ng.d.ts +53 -0
- package/ui/accordion/README.md +261 -0
- package/ui/alert/README.md +211 -0
- package/ui/avatar/README.md +167 -0
- package/ui/avatar-stack/README.md +164 -0
- package/ui/badge/README.md +162 -0
- package/ui/breadcrumb/README.md +240 -0
- package/ui/button/README.md +184 -0
- package/ui/callout/README.md +159 -0
- package/ui/card/README.md +174 -0
- package/ui/copyable-field/README.md +235 -0
- package/ui/data-table/README.md +408 -0
- package/ui/dialog/README.md +222 -0
- package/ui/drawer/README.md +274 -0
- package/ui/dropdown-menu/README.md +336 -0
- package/ui/editable-field/README.md +171 -0
- package/ui/icon-badge/README.md +131 -0
- package/ui/icon-list/README.md +205 -0
- package/ui/inline-edit/README.md +135 -0
- package/ui/list-editor/README.md +162 -0
- package/ui/loader/README.md +160 -0
- package/ui/menu-item/README.md +204 -0
- package/ui/nav-brand/README.md +111 -0
- package/ui/nav-group/README.md +145 -0
- package/ui/nav-separator/README.md +44 -0
- package/ui/node-tree/README.md +278 -0
- package/ui/node-tree-breadcrumb/README.md +164 -0
- package/ui/note/README.md +146 -0
- package/ui/numbered-list/README.md +187 -0
- package/ui/pagination/README.md +174 -0
- package/ui/progress-bar/README.md +223 -0
- package/ui/sidenav-link/README.md +214 -0
- package/ui/tabs/README.md +204 -0
- package/ui/timeline/README.md +285 -0
- package/ui/toast/README.md +243 -0
- package/ui/user-menu/README.md +260 -0
- package/ui/wizard-dialog/README.md +283 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# fk-app-shell
|
|
2
|
+
|
|
3
|
+
A responsive application shell layout with a header, collapsible sidebar, an opt-in right-side end panel, overlay support, and a main content area. The shell handles positioning and transitions — consumers own the internal structure of each panel.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## API
|
|
8
|
+
|
|
9
|
+
### Inputs
|
|
10
|
+
|
|
11
|
+
#### Sidebar
|
|
12
|
+
|
|
13
|
+
| Input | Type | Default | Description |
|
|
14
|
+
| ---------------- | -------------------------------- | --------------------- | ------------------------------------------------------------------------------------------- |
|
|
15
|
+
| mode | `'side'` \| `'over'` \| `'icon'` | `'side'` | Sidebar behavior: push content, overlay, or icon rail |
|
|
16
|
+
| sidenavWidth | `string` | `'260px'` | Width of the expanded sidebar |
|
|
17
|
+
| collapsedWidth | `string` | `'64px'` | Width of the collapsed icon rail (icon mode only) |
|
|
18
|
+
| breakpoint | `string` | `'(min-width: 48em)'` | Media query that separates mobile from desktop layout |
|
|
19
|
+
| sticky | `boolean` | `true` | Adds the `fk-app-shell--sticky` class for sticky layout |
|
|
20
|
+
| collapseOnMobile | `boolean` | `false` | In `icon` mode, show the collapsed strip on mobile instead of hiding the sidebar off-screen |
|
|
21
|
+
|
|
22
|
+
#### End Panel
|
|
23
|
+
|
|
24
|
+
| Input | Type | Default | Description |
|
|
25
|
+
| ----------------- | -------------------------------- | --------- | ------------------------------------------------------- |
|
|
26
|
+
| endMode | `'side'` \| `'over'` \| `'icon'` | `'over'` | End panel behavior: push content, overlay, or icon rail |
|
|
27
|
+
| endWidth | `string` | `'320px'` | Width of the expanded end panel |
|
|
28
|
+
| endCollapsedWidth | `string` | `'64px'` | Width of the collapsed icon rail (icon mode only) |
|
|
29
|
+
|
|
30
|
+
### Methods
|
|
31
|
+
|
|
32
|
+
#### Sidebar
|
|
33
|
+
|
|
34
|
+
| Method | Description |
|
|
35
|
+
| ---------------- | ---------------------------------------------------------------- |
|
|
36
|
+
| openSidenav() | Opens the sidebar (on mobile, opens as temporary overlay) |
|
|
37
|
+
| closeSidenav() | Closes the sidebar and persists the closed preference |
|
|
38
|
+
| toggleSidenav() | Toggles between open and closed |
|
|
39
|
+
| dismissSidenav() | Closes the mobile overlay without persisting a closed preference |
|
|
40
|
+
|
|
41
|
+
#### End Panel
|
|
42
|
+
|
|
43
|
+
| Method | Description |
|
|
44
|
+
| ------------ | ----------------------------------------------------------- |
|
|
45
|
+
| openEnd() | Opens the end panel (on mobile, opens as temporary overlay) |
|
|
46
|
+
| closeEnd() | Closes the end panel and persists the closed preference |
|
|
47
|
+
| toggleEnd() | Toggles between open and closed |
|
|
48
|
+
| dismissEnd() | Closes the end panel and persists the closed preference |
|
|
49
|
+
|
|
50
|
+
### Computed (read-only)
|
|
51
|
+
|
|
52
|
+
#### Sidebar
|
|
53
|
+
|
|
54
|
+
| Property | Type | Description |
|
|
55
|
+
| ----------- | ----------------- | --------------------------------------------------- |
|
|
56
|
+
| sidenavOpen | `Signal<boolean>` | Whether the sidebar is currently visible |
|
|
57
|
+
| showOverlay | `Signal<boolean>` | Whether the backdrop overlay is visible |
|
|
58
|
+
| isCollapsed | `Signal<boolean>` | Whether the sidebar is in collapsed icon-rail state |
|
|
59
|
+
| isMobile | `Signal<boolean>` | Whether the viewport is below the breakpoint |
|
|
60
|
+
|
|
61
|
+
#### End Panel
|
|
62
|
+
|
|
63
|
+
| Property | Type | Description |
|
|
64
|
+
| -------------- | ----------------- | ----------------------------------------------------- |
|
|
65
|
+
| endOpen | `Signal<boolean>` | Whether the end panel is currently visible |
|
|
66
|
+
| showEndOverlay | `Signal<boolean>` | Whether the end panel backdrop overlay is visible |
|
|
67
|
+
| isEndCollapsed | `Signal<boolean>` | Whether the end panel is in collapsed icon-rail state |
|
|
68
|
+
|
|
69
|
+
### Content Projection Slots
|
|
70
|
+
|
|
71
|
+
| Attribute | Description |
|
|
72
|
+
| ----------------- | ------------------------------------------------- |
|
|
73
|
+
| `appShellHeader` | Top-level header bar (sticky, full width) |
|
|
74
|
+
| `appShellSidenav` | Sidebar content — consumer owns internal layout |
|
|
75
|
+
| `appShellContent` | Main content area |
|
|
76
|
+
| `appShellFooter` | Page-level footer bar (full width, below content) |
|
|
77
|
+
| `appShellEnd` | End panel content — consumer owns internal layout |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Features
|
|
82
|
+
|
|
83
|
+
- Three sidebar modes: side (push), over (overlay), icon (collapsible rail)
|
|
84
|
+
- Opt-in right-side end panel with the same three mode options
|
|
85
|
+
- Responsive breakpoint detection via `BreakpointObserver`
|
|
86
|
+
- Mobile overlay with backdrop dismiss
|
|
87
|
+
- Single content projection slot per panel — consumers define their own internal structure
|
|
88
|
+
- Smooth CSS transitions with `prefers-reduced-motion` support
|
|
89
|
+
- Token-driven styling
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Quick Start
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<fk-app-shell mode="icon">
|
|
97
|
+
<div appShellHeader>Header</div>
|
|
98
|
+
<div appShellSidenav>Nav links</div>
|
|
99
|
+
<div appShellContent>Page content</div>
|
|
100
|
+
<footer appShellFooter>© 2026 Company</footer>
|
|
101
|
+
</fk-app-shell>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Import
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { AppShellComponent } from '@frame-kit/ui-ng';
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
@Component({
|
|
114
|
+
selector: 'app-dashboard',
|
|
115
|
+
imports: [AppShellComponent],
|
|
116
|
+
templateUrl: './dashboard.component.html',
|
|
117
|
+
})
|
|
118
|
+
export class DashboardComponent {}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Selector
|
|
124
|
+
|
|
125
|
+
```html
|
|
126
|
+
<fk-app-shell></fk-app-shell>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Examples
|
|
132
|
+
|
|
133
|
+
### Side Mode (default)
|
|
134
|
+
|
|
135
|
+
Sidebar pushes the main content over. Collapses to zero width when closed.
|
|
136
|
+
|
|
137
|
+
```html
|
|
138
|
+
<fk-app-shell mode="side">
|
|
139
|
+
<div appShellHeader>
|
|
140
|
+
<button (click)="shell.toggleSidenav()">Toggle</button>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<nav appShellSidenav>
|
|
144
|
+
<fk-sidenav-link icon="chart-activity-fill" label="Overview" routerLink="/app" [exact]="true" />
|
|
145
|
+
<fk-sidenav-link icon="organization" label="Properties" />
|
|
146
|
+
</nav>
|
|
147
|
+
|
|
148
|
+
<div appShellContent>
|
|
149
|
+
<router-outlet />
|
|
150
|
+
</div>
|
|
151
|
+
</fk-app-shell>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Over Mode
|
|
155
|
+
|
|
156
|
+
Sidebar slides over the content with a backdrop overlay.
|
|
157
|
+
|
|
158
|
+
```html
|
|
159
|
+
<fk-app-shell mode="over">
|
|
160
|
+
<div appShellHeader>
|
|
161
|
+
<button (click)="shell.toggleSidenav()">Menu</button>
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
<nav appShellSidenav>
|
|
165
|
+
<fk-sidenav-link icon="email" label="Notifications" />
|
|
166
|
+
</nav>
|
|
167
|
+
|
|
168
|
+
<div appShellContent>
|
|
169
|
+
<router-outlet />
|
|
170
|
+
</div>
|
|
171
|
+
</fk-app-shell>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Icon Mode (collapsible rail)
|
|
175
|
+
|
|
176
|
+
Sidebar collapses to a narrow icon rail on desktop. On mobile, it behaves as an overlay. The consumer provides the internal header/nav/footer layout.
|
|
177
|
+
|
|
178
|
+
```html
|
|
179
|
+
<fk-app-shell mode="icon">
|
|
180
|
+
<div appShellHeader>
|
|
181
|
+
<button (click)="shell.toggleSidenav()">Toggle</button>
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
<div appShellSidenav style="display: flex; flex-direction: column; height: 100%;">
|
|
185
|
+
<div class="sidenav-header">
|
|
186
|
+
<button (click)="shell.toggleSidenav()">Collapse</button>
|
|
187
|
+
</div>
|
|
188
|
+
|
|
189
|
+
<nav class="sidenav-nav" style="flex: 1; overflow-y: auto;">
|
|
190
|
+
<fk-sidenav-link icon="chart-activity-fill" label="Overview" routerLink="/app" [exact]="true" />
|
|
191
|
+
<fk-sidenav-link icon="organization" label="Properties" />
|
|
192
|
+
<fk-sidenav-link icon="email" label="Notifications" />
|
|
193
|
+
</nav>
|
|
194
|
+
|
|
195
|
+
<div class="sidenav-footer">
|
|
196
|
+
<fk-sidenav-link icon="info" label="Help & Support" />
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
<div appShellContent>
|
|
201
|
+
<router-outlet />
|
|
202
|
+
</div>
|
|
203
|
+
</fk-app-shell>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### End Panel
|
|
207
|
+
|
|
208
|
+
The end panel is opt-in and starts closed. The consumer provides their own toggle button, panel content, and internal layout.
|
|
209
|
+
|
|
210
|
+
```html
|
|
211
|
+
<fk-app-shell mode="icon" endMode="over">
|
|
212
|
+
<div appShellHeader>
|
|
213
|
+
<button (click)="shell.toggleSidenav()">Toggle</button>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<nav appShellSidenav>
|
|
217
|
+
<fk-sidenav-link icon="chart-activity-fill" label="Overview" routerLink="/app" [exact]="true" />
|
|
218
|
+
</nav>
|
|
219
|
+
|
|
220
|
+
<div appShellContent>
|
|
221
|
+
<button (click)="shell.toggleEnd()">Open Details</button>
|
|
222
|
+
<router-outlet />
|
|
223
|
+
</div>
|
|
224
|
+
|
|
225
|
+
<div appShellEnd>
|
|
226
|
+
<div class="panel-header">Detail View</div>
|
|
227
|
+
<div class="panel-content">Detail content goes here</div>
|
|
228
|
+
<div class="panel-footer">Actions</div>
|
|
229
|
+
</div>
|
|
230
|
+
</fk-app-shell>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Collapse on Mobile
|
|
234
|
+
|
|
235
|
+
Keep the icon rail visible on mobile instead of hiding the sidebar. Tapping an item in the rail can call `shell.openSidenav()` to slide in the full sidebar as an overlay; tapping the backdrop returns to the rail.
|
|
236
|
+
|
|
237
|
+
```html
|
|
238
|
+
<fk-app-shell #shell mode="icon" [collapseOnMobile]="true">
|
|
239
|
+
<div appShellHeader>Header</div>
|
|
240
|
+
|
|
241
|
+
<nav appShellSidenav>
|
|
242
|
+
<button (click)="shell.openSidenav()">
|
|
243
|
+
<fk-icon name="menu-outline" />
|
|
244
|
+
</button>
|
|
245
|
+
<fk-sidenav-link icon="home" label="Home" routerLink="/" />
|
|
246
|
+
</nav>
|
|
247
|
+
|
|
248
|
+
<div appShellContent>
|
|
249
|
+
<router-outlet />
|
|
250
|
+
</div>
|
|
251
|
+
</fk-app-shell>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Custom Widths
|
|
255
|
+
|
|
256
|
+
```html
|
|
257
|
+
<fk-app-shell mode="icon" sidenavWidth="300px" collapsedWidth="80px" endWidth="400px"> ... </fk-app-shell>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Accessibility
|
|
263
|
+
|
|
264
|
+
- The overlay backdrop dismisses the sidebar or end panel on click
|
|
265
|
+
- All interactive elements within projected content should follow standard keyboard and focus practices
|
|
266
|
+
- `prefers-reduced-motion: reduce` disables all sidebar and end panel transitions
|
|
267
|
+
- Mobile mode ensures the sidebar is reachable via a toggle button in the header
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Design Tokens
|
|
272
|
+
|
|
273
|
+
### Layout Tokens
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
--fk-app-shell-sidenav-width (set via sidenavWidth input)
|
|
277
|
+
--fk-app-shell-collapsed-width (set via collapsedWidth input)
|
|
278
|
+
--fk-app-shell-end-width (set via endWidth input)
|
|
279
|
+
--fk-app-shell-end-collapsed-width (set via endCollapsedWidth input)
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Appearance Tokens — Sidebar
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
--fk-app-shell-header-z-index (default: 100)
|
|
286
|
+
--fk-app-shell-overlay-z-index (default: 200)
|
|
287
|
+
--fk-app-shell-aside-z-index (default: 201)
|
|
288
|
+
--fk-app-shell-overlay-bg (default: var(--fk-black-50, rgba(0, 0, 0, 0.5)))
|
|
289
|
+
--fk-app-shell-aside-bg (default: var(--fk-color-surface, #ffffff))
|
|
290
|
+
--fk-app-shell-mobile-sidenav-width (default: 100% — mobile overlay width)
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Appearance Tokens — End Panel
|
|
294
|
+
|
|
295
|
+
```
|
|
296
|
+
--fk-app-shell-end-bg (default: var(--fk-color-surface))
|
|
297
|
+
--fk-app-shell-end-z-index (default: 201)
|
|
298
|
+
--fk-app-shell-end-radius (default: var(--fk-radius-lg) 0 0 var(--fk-radius-lg))
|
|
299
|
+
--fk-app-shell-end-shadow (default: -4px 0 16px rgba(0, 0, 0, 0.08))
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Customizing Tokens
|
|
303
|
+
|
|
304
|
+
```css
|
|
305
|
+
:root {
|
|
306
|
+
--fk-app-shell-overlay-bg: rgba(0, 0, 0, 0.3);
|
|
307
|
+
--fk-app-shell-aside-bg: #f8fafc;
|
|
308
|
+
--fk-app-shell-end-bg: #f8fafc;
|
|
309
|
+
--fk-app-shell-end-shadow: -2px 0 12px rgba(0, 0, 0, 0.12);
|
|
310
|
+
|
|
311
|
+
/* Make the mobile sidenav a peek-style drawer instead of full-screen: */
|
|
312
|
+
--fk-app-shell-mobile-sidenav-width: 20rem;
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Behavior Notes
|
|
319
|
+
|
|
320
|
+
- On viewport resize, transitions are disabled to prevent layout flash
|
|
321
|
+
- Transitions are only enabled after explicit user interaction (toggle, open, close)
|
|
322
|
+
- `dismissSidenav()` closes the mobile overlay without persisting a closed preference — on the next desktop resize the sidebar will reappear
|
|
323
|
+
- `closeSidenav()` persists the closed preference across mobile/desktop transitions
|
|
324
|
+
- In `icon` mode, when collapsed, the aside shrinks to `collapsedWidth` and child components (like `fk-sidenav-link`) can detect collapse state to hide labels
|
|
325
|
+
- By default, the sidebar is hidden off-screen on mobile and reachable via a toggle. Set `collapseOnMobile="true"` (icon mode only) to keep the collapsed rail visible on mobile; opening the sidenav still slides it in as a full-width overlay that can be dismissed via the backdrop
|
|
326
|
+
- The mobile overlay defaults to the full viewport width (`--fk-app-shell-mobile-sidenav-width: 100%`). Override the token for a peek-style drawer. The input `sidenavWidth` only drives the desktop width
|
|
327
|
+
- The end panel starts closed by default — the consumer must explicitly open it via `openEnd()` or `toggleEnd()`
|
|
328
|
+
- Both `dismissEnd()` and `closeEnd()` persist the closed preference, since the end panel's default state is closed
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## CSS Classes
|
|
333
|
+
|
|
334
|
+
The component applies state classes to its root wrapper for consumer styling:
|
|
335
|
+
|
|
336
|
+
### Sidebar
|
|
337
|
+
|
|
338
|
+
| Class | Condition |
|
|
339
|
+
| ------------------------- | --------------------------------- |
|
|
340
|
+
| `fk-app-shell--side` | mode is `'side'` |
|
|
341
|
+
| `fk-app-shell--over` | mode is `'over'` |
|
|
342
|
+
| `fk-app-shell--icon` | mode is `'icon'` |
|
|
343
|
+
| `fk-app-shell--sticky` | `sticky` is `true` |
|
|
344
|
+
| `fk-app-shell--open` | sidebar is open |
|
|
345
|
+
| `fk-app-shell--collapsed` | sidebar is in collapsed icon rail |
|
|
346
|
+
| `fk-app-shell--mobile` | viewport is below breakpoint |
|
|
347
|
+
| `fk-app-shell--animate` | transitions are currently enabled |
|
|
348
|
+
|
|
349
|
+
### End Panel
|
|
350
|
+
|
|
351
|
+
| Class | Condition |
|
|
352
|
+
| ----------------------------- | ----------------------------------- |
|
|
353
|
+
| `fk-app-shell--end-side` | endMode is `'side'` |
|
|
354
|
+
| `fk-app-shell--end-over` | endMode is `'over'` |
|
|
355
|
+
| `fk-app-shell--end-icon` | endMode is `'icon'` |
|
|
356
|
+
| `fk-app-shell--end-open` | end panel is open |
|
|
357
|
+
| `fk-app-shell--end-collapsed` | end panel is in collapsed icon rail |
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# fk-content-split
|
|
2
|
+
|
|
3
|
+
A container-aware split-pane layout component for Angular. In wide containers, renders two side-by-side panels. In narrow containers, a rail strip with a toggle button appears and the left panel becomes an overlay drawer that slides in over the content.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## API
|
|
8
|
+
|
|
9
|
+
### Inputs
|
|
10
|
+
|
|
11
|
+
| Input | Type | Default | Description |
|
|
12
|
+
| ------------ | ---------------- | --------- | ------------------------------------------------- |
|
|
13
|
+
| `leftWidth` | `string` | `'280px'` | CSS width of the left panel |
|
|
14
|
+
| `railWidth` | `string` | `'64px'` | Width of the rail strip in narrow mode |
|
|
15
|
+
| `breakpoint` | `number` | `700` | Host width (px) below which drawer mode activates |
|
|
16
|
+
| `collapsed` | `model<boolean>` | `false` | Two-way binding for drawer open/closed state |
|
|
17
|
+
| `className` | `string` | `''` | Additional CSS classes for the host |
|
|
18
|
+
|
|
19
|
+
### Methods
|
|
20
|
+
|
|
21
|
+
| Method | Description |
|
|
22
|
+
| ----------- | --------------------------------------- |
|
|
23
|
+
| `open()` | Opens the drawer (sets collapsed=false) |
|
|
24
|
+
| `close()` | Closes the drawer (sets collapsed=true) |
|
|
25
|
+
| `toggle()` | Toggles between open and closed |
|
|
26
|
+
| `dismiss()` | Closes the drawer (alias for close) |
|
|
27
|
+
|
|
28
|
+
### Content Projection
|
|
29
|
+
|
|
30
|
+
| Slot | Description |
|
|
31
|
+
| --------------------- | ----------------------------------- |
|
|
32
|
+
| `[contentSplitLeft]` | Content for the left panel / drawer |
|
|
33
|
+
| `[contentSplitRight]` | Content for the main right panel |
|
|
34
|
+
|
|
35
|
+
### Types
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
type ContentSplitLayout = 'wide' | 'narrow';
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- Side-by-side flex layout in wide containers
|
|
46
|
+
- Overlay drawer with rail toggle in narrow containers
|
|
47
|
+
- Container-aware layout switching via `ResizeObserver` (not viewport)
|
|
48
|
+
- Overlay backdrop with click-to-dismiss
|
|
49
|
+
- Smart animation (transitions only after user action, disabled on layout switches)
|
|
50
|
+
- Two-way `[(collapsed)]` binding via Angular `model()`
|
|
51
|
+
- Token-driven styling with two-tier fallbacks
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<fk-content-split [(collapsed)]="collapsed">
|
|
59
|
+
<nav contentSplitLeft>Filters / Tree</nav>
|
|
60
|
+
<main contentSplitRight>Detail View</main>
|
|
61
|
+
</fk-content-split>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Import
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { FkContentSplitComponent } from '@frame-kit/ui-ng';
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
@Component({
|
|
74
|
+
selector: 'app-example',
|
|
75
|
+
imports: [FkContentSplitComponent],
|
|
76
|
+
templateUrl: './example.component.html',
|
|
77
|
+
})
|
|
78
|
+
export class ExampleComponent {}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Selector
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<fk-content-split></fk-content-split>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Examples
|
|
90
|
+
|
|
91
|
+
### Basic
|
|
92
|
+
|
|
93
|
+
```html
|
|
94
|
+
<fk-content-split>
|
|
95
|
+
<div contentSplitLeft>Left panel</div>
|
|
96
|
+
<div contentSplitRight>Right panel</div>
|
|
97
|
+
</fk-content-split>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Programmatic Toggle
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<fk-content-split #split [(collapsed)]="collapsed">
|
|
104
|
+
<div contentSplitLeft>Sidebar content</div>
|
|
105
|
+
<div contentSplitRight>
|
|
106
|
+
<button (click)="split.toggle()">Toggle Panel</button>
|
|
107
|
+
<p>Main content</p>
|
|
108
|
+
</div>
|
|
109
|
+
</fk-content-split>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Custom Widths and Breakpoint
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<fk-content-split leftWidth="360px" railWidth="48px" [breakpoint]="500">
|
|
116
|
+
<div contentSplitLeft>Wide sidebar</div>
|
|
117
|
+
<div contentSplitRight>Content</div>
|
|
118
|
+
</fk-content-split>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Accessibility
|
|
124
|
+
|
|
125
|
+
- Rail toggle button uses a native `<button>` with dynamic `aria-label` (`"Open panel"` / `"Close panel"`)
|
|
126
|
+
- Overlay backdrop is click-to-dismiss
|
|
127
|
+
- `prefers-reduced-motion: reduce` disables all transitions
|
|
128
|
+
- Focus ring on the rail toggle uses `--fk-focus-ring` token
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Design Tokens
|
|
133
|
+
|
|
134
|
+
`fk-content-split` is styled entirely through design tokens.
|
|
135
|
+
|
|
136
|
+
### Token Reference
|
|
137
|
+
|
|
138
|
+
| Token | Default | Description |
|
|
139
|
+
| -------------------------------------------- | ---------------------------------- | ---------------------------------------- |
|
|
140
|
+
| `--fk-content-split-left-width` | `280px` | Left panel width (capped in narrow mode) |
|
|
141
|
+
| `--fk-content-split-rail-width` | `64px` | Rail strip width in narrow mode |
|
|
142
|
+
| `--fk-content-split-left-bg` | `var(--fk-color-surface)` | Left panel / rail background |
|
|
143
|
+
| `--fk-content-split-left-border` | `1px solid var(--fk-color-border)` | Left panel / rail border |
|
|
144
|
+
| `--fk-content-split-overlay-bg` | `rgba(0, 0, 0, 0.5)` | Overlay backdrop color |
|
|
145
|
+
| `--fk-content-split-rail-toggle-color` | `var(--fk-color-muted)` | Rail toggle icon color |
|
|
146
|
+
| `--fk-content-split-rail-toggle-color-hover` | `var(--fk-color-text)` | Rail toggle hover color |
|
|
147
|
+
| `--fk-content-split-rail-toggle-bg-hover` | `var(--fk-color-surface-muted)` | Rail toggle hover background |
|
|
148
|
+
| `--fk-content-split-rail-toggle-padding` | `var(--fk-rhythm-3)` | Rail toggle button padding |
|
|
149
|
+
| `--fk-content-split-rail-toggle-color-hover` | `var(--fk-color-text)` | Rail toggle text color on hover |
|
|
150
|
+
|
|
151
|
+
### Customizing Tokens
|
|
152
|
+
|
|
153
|
+
Override tokens in your application's global stylesheet or a scoped selector:
|
|
154
|
+
|
|
155
|
+
```css
|
|
156
|
+
:root {
|
|
157
|
+
--fk-content-split-left-bg: #f8fafc;
|
|
158
|
+
--fk-content-split-overlay-bg: rgba(0, 0, 0, 0.7);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Or scope overrides to a specific context:
|
|
163
|
+
|
|
164
|
+
```css
|
|
165
|
+
.dark-theme fk-content-split {
|
|
166
|
+
--fk-content-split-left-bg: #1e293b;
|
|
167
|
+
--fk-content-split-rail-toggle-color: #94a3b8;
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Behavior Notes
|
|
174
|
+
|
|
175
|
+
- **Container-aware, not viewport-aware**: Layout switches based on the host element's width via `ResizeObserver`. The breakpoint accounts for sibling layout (e.g., app-shell sidebar being open or closed).
|
|
176
|
+
- **Auto-collapse on narrow**: When the host shrinks below the breakpoint, the left panel automatically collapses. The consumer controls reopening via the rail toggle or programmatic methods.
|
|
177
|
+
- **Drawer width capping**: In narrow mode, the drawer width is capped at `100% - rail width` so it never overflows the viewport on small devices (e.g., phones).
|
|
178
|
+
- **No auto-expand**: When the host grows past the breakpoint, it switches to wide mode. The consumer controls the collapsed state.
|
|
179
|
+
- **Animation is opt-in**: Transitions apply only after user actions (`open()`, `close()`, `toggle()`). Layout switches skip animation to avoid jank.
|
|
180
|
+
- **Rail strip**: Only visible in narrow mode. Contains a built-in hamburger toggle button. Hidden via CSS `display: none` in wide mode.
|