@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.
Files changed (220) hide show
  1. package/COMPONENTS.md +683 -0
  2. package/DEVELOPMENT_GUIDE.md +1102 -0
  3. package/LICENSE +21 -0
  4. package/README.md +69 -0
  5. package/THEMING.md +130 -0
  6. package/core/headline/README.md +121 -0
  7. package/core/icon/README.md +173 -0
  8. package/core/image/README.md +210 -0
  9. package/core/link/README.md +297 -0
  10. package/core/separator/README.md +145 -0
  11. package/core/text/README.md +240 -0
  12. package/directives/infinite-scroll/README.md +102 -0
  13. package/directives/spotlight/README.md +154 -0
  14. package/directives/tooltip/README.md +147 -0
  15. package/docs/endpoint-link/README.md +142 -0
  16. package/docs/method-badge/README.md +154 -0
  17. package/fesm2022/frame-kit-ui-ng-core-headline.mjs +122 -0
  18. package/fesm2022/frame-kit-ui-ng-core-headline.mjs.map +1 -0
  19. package/fesm2022/frame-kit-ui-ng-core-icon.mjs +189 -0
  20. package/fesm2022/frame-kit-ui-ng-core-icon.mjs.map +1 -0
  21. package/fesm2022/frame-kit-ui-ng-core-image.mjs +123 -0
  22. package/fesm2022/frame-kit-ui-ng-core-image.mjs.map +1 -0
  23. package/fesm2022/frame-kit-ui-ng-core-link.mjs +369 -0
  24. package/fesm2022/frame-kit-ui-ng-core-link.mjs.map +1 -0
  25. package/fesm2022/frame-kit-ui-ng-core-separator.mjs +59 -0
  26. package/fesm2022/frame-kit-ui-ng-core-separator.mjs.map +1 -0
  27. package/fesm2022/frame-kit-ui-ng-core-text.mjs +204 -0
  28. package/fesm2022/frame-kit-ui-ng-core-text.mjs.map +1 -0
  29. package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs +74 -0
  30. package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs.map +1 -0
  31. package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs +76 -0
  32. package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs.map +1 -0
  33. package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs +425 -0
  34. package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs.map +1 -0
  35. package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs +63 -0
  36. package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs.map +1 -0
  37. package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs +43 -0
  38. package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs.map +1 -0
  39. package/fesm2022/frame-kit-ui-ng-forms.mjs +3632 -0
  40. package/fesm2022/frame-kit-ui-ng-forms.mjs.map +1 -0
  41. package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs +239 -0
  42. package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs.map +1 -0
  43. package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs +132 -0
  44. package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs.map +1 -0
  45. package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs +133 -0
  46. package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs.map +1 -0
  47. package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs +60 -0
  48. package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs.map +1 -0
  49. package/fesm2022/frame-kit-ui-ng-services-toast.mjs +166 -0
  50. package/fesm2022/frame-kit-ui-ng-services-toast.mjs.map +1 -0
  51. package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs +214 -0
  52. package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs.map +1 -0
  53. package/fesm2022/frame-kit-ui-ng-ui-alert.mjs +82 -0
  54. package/fesm2022/frame-kit-ui-ng-ui-alert.mjs.map +1 -0
  55. package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs +76 -0
  56. package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs.map +1 -0
  57. package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs +81 -0
  58. package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs.map +1 -0
  59. package/fesm2022/frame-kit-ui-ng-ui-badge.mjs +81 -0
  60. package/fesm2022/frame-kit-ui-ng-ui-badge.mjs.map +1 -0
  61. package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs +68 -0
  62. package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs.map +1 -0
  63. package/fesm2022/frame-kit-ui-ng-ui-button.mjs +108 -0
  64. package/fesm2022/frame-kit-ui-ng-ui-button.mjs.map +1 -0
  65. package/fesm2022/frame-kit-ui-ng-ui-callout.mjs +58 -0
  66. package/fesm2022/frame-kit-ui-ng-ui-callout.mjs.map +1 -0
  67. package/fesm2022/frame-kit-ui-ng-ui-card.mjs +70 -0
  68. package/fesm2022/frame-kit-ui-ng-ui-card.mjs.map +1 -0
  69. package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs +113 -0
  70. package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs.map +1 -0
  71. package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs +1288 -0
  72. package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs.map +1 -0
  73. package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs +456 -0
  74. package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs.map +1 -0
  75. package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs +398 -0
  76. package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs.map +1 -0
  77. package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs +398 -0
  78. package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs.map +1 -0
  79. package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs +125 -0
  80. package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs.map +1 -0
  81. package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs +113 -0
  82. package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs.map +1 -0
  83. package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs +111 -0
  84. package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs.map +1 -0
  85. package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs +103 -0
  86. package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs.map +1 -0
  87. package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs +135 -0
  88. package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs.map +1 -0
  89. package/fesm2022/frame-kit-ui-ng-ui-loader.mjs +81 -0
  90. package/fesm2022/frame-kit-ui-ng-ui-loader.mjs.map +1 -0
  91. package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs +79 -0
  92. package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs.map +1 -0
  93. package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs +40 -0
  94. package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs.map +1 -0
  95. package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs +110 -0
  96. package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs.map +1 -0
  97. package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs +91 -0
  98. package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs.map +1 -0
  99. package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs +86 -0
  100. package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs.map +1 -0
  101. package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs +443 -0
  102. package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs.map +1 -0
  103. package/fesm2022/frame-kit-ui-ng-ui-note.mjs +56 -0
  104. package/fesm2022/frame-kit-ui-ng-ui-note.mjs.map +1 -0
  105. package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs +105 -0
  106. package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs.map +1 -0
  107. package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs +110 -0
  108. package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs.map +1 -0
  109. package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs +129 -0
  110. package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs.map +1 -0
  111. package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs +42 -0
  112. package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs.map +1 -0
  113. package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs +894 -0
  114. package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs.map +1 -0
  115. package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs +81 -0
  116. package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs.map +1 -0
  117. package/fesm2022/frame-kit-ui-ng-ui-toast.mjs +179 -0
  118. package/fesm2022/frame-kit-ui-ng-ui-toast.mjs.map +1 -0
  119. package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs +143 -0
  120. package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs.map +1 -0
  121. package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs +191 -0
  122. package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs.map +1 -0
  123. package/fesm2022/frame-kit-ui-ng.mjs +58 -0
  124. package/fesm2022/frame-kit-ui-ng.mjs.map +1 -0
  125. package/layouts/app-shell/README.md +357 -0
  126. package/layouts/content-split/README.md +180 -0
  127. package/package.json +253 -0
  128. package/services/overlay-orchestrator/README.md +184 -0
  129. package/services/spotlight/README.md +61 -0
  130. package/services/toast/README.md +118 -0
  131. package/types/frame-kit-ui-ng-core-headline.d.ts +38 -0
  132. package/types/frame-kit-ui-ng-core-icon.d.ts +74 -0
  133. package/types/frame-kit-ui-ng-core-image.d.ts +93 -0
  134. package/types/frame-kit-ui-ng-core-link.d.ts +251 -0
  135. package/types/frame-kit-ui-ng-core-separator.d.ts +28 -0
  136. package/types/frame-kit-ui-ng-core-text.d.ts +186 -0
  137. package/types/frame-kit-ui-ng-directives-infinite-scroll.d.ts +42 -0
  138. package/types/frame-kit-ui-ng-directives-spotlight.d.ts +51 -0
  139. package/types/frame-kit-ui-ng-directives-tooltip.d.ts +70 -0
  140. package/types/frame-kit-ui-ng-docs-endpoint-link.d.ts +43 -0
  141. package/types/frame-kit-ui-ng-docs-method-badge.d.ts +30 -0
  142. package/types/frame-kit-ui-ng-forms.d.ts +1674 -0
  143. package/types/frame-kit-ui-ng-layouts-app-shell.d.ts +75 -0
  144. package/types/frame-kit-ui-ng-layouts-content-split.d.ts +43 -0
  145. package/types/frame-kit-ui-ng-services-overlay-orchestrator.d.ts +96 -0
  146. package/types/frame-kit-ui-ng-services-spotlight.d.ts +32 -0
  147. package/types/frame-kit-ui-ng-services-toast.d.ts +100 -0
  148. package/types/frame-kit-ui-ng-ui-accordion.d.ts +86 -0
  149. package/types/frame-kit-ui-ng-ui-alert.d.ts +34 -0
  150. package/types/frame-kit-ui-ng-ui-avatar-stack.d.ts +38 -0
  151. package/types/frame-kit-ui-ng-ui-avatar.d.ts +36 -0
  152. package/types/frame-kit-ui-ng-ui-badge.d.ts +33 -0
  153. package/types/frame-kit-ui-ng-ui-breadcrumb.d.ts +45 -0
  154. package/types/frame-kit-ui-ng-ui-button.d.ts +48 -0
  155. package/types/frame-kit-ui-ng-ui-callout.d.ts +26 -0
  156. package/types/frame-kit-ui-ng-ui-card.d.ts +30 -0
  157. package/types/frame-kit-ui-ng-ui-copyable-field.d.ts +62 -0
  158. package/types/frame-kit-ui-ng-ui-data-table.d.ts +482 -0
  159. package/types/frame-kit-ui-ng-ui-dialog.d.ts +166 -0
  160. package/types/frame-kit-ui-ng-ui-drawer.d.ts +130 -0
  161. package/types/frame-kit-ui-ng-ui-dropdown-menu.d.ts +77 -0
  162. package/types/frame-kit-ui-ng-ui-editable-field.d.ts +65 -0
  163. package/types/frame-kit-ui-ng-ui-icon-badge.d.ts +45 -0
  164. package/types/frame-kit-ui-ng-ui-icon-list.d.ts +67 -0
  165. package/types/frame-kit-ui-ng-ui-inline-edit.d.ts +44 -0
  166. package/types/frame-kit-ui-ng-ui-list-editor.d.ts +56 -0
  167. package/types/frame-kit-ui-ng-ui-loader.d.ts +32 -0
  168. package/types/frame-kit-ui-ng-ui-menu-item.d.ts +27 -0
  169. package/types/frame-kit-ui-ng-ui-nav-brand.d.ts +25 -0
  170. package/types/frame-kit-ui-ng-ui-nav-group.d.ts +60 -0
  171. package/types/frame-kit-ui-ng-ui-nav-separator.d.ts +33 -0
  172. package/types/frame-kit-ui-ng-ui-node-tree-breadcrumb.d.ts +35 -0
  173. package/types/frame-kit-ui-ng-ui-node-tree.d.ts +135 -0
  174. package/types/frame-kit-ui-ng-ui-note.d.ts +22 -0
  175. package/types/frame-kit-ui-ng-ui-numbered-list.d.ts +52 -0
  176. package/types/frame-kit-ui-ng-ui-pagination.d.ts +49 -0
  177. package/types/frame-kit-ui-ng-ui-progress-bar.d.ts +50 -0
  178. package/types/frame-kit-ui-ng-ui-sidenav-link.d.ts +24 -0
  179. package/types/frame-kit-ui-ng-ui-tabs.d.ts +266 -0
  180. package/types/frame-kit-ui-ng-ui-timeline.d.ts +42 -0
  181. package/types/frame-kit-ui-ng-ui-toast.d.ts +56 -0
  182. package/types/frame-kit-ui-ng-ui-user-menu.d.ts +87 -0
  183. package/types/frame-kit-ui-ng-ui-wizard-dialog.d.ts +116 -0
  184. package/types/frame-kit-ui-ng.d.ts +53 -0
  185. package/ui/accordion/README.md +261 -0
  186. package/ui/alert/README.md +211 -0
  187. package/ui/avatar/README.md +167 -0
  188. package/ui/avatar-stack/README.md +164 -0
  189. package/ui/badge/README.md +162 -0
  190. package/ui/breadcrumb/README.md +240 -0
  191. package/ui/button/README.md +184 -0
  192. package/ui/callout/README.md +159 -0
  193. package/ui/card/README.md +174 -0
  194. package/ui/copyable-field/README.md +235 -0
  195. package/ui/data-table/README.md +408 -0
  196. package/ui/dialog/README.md +222 -0
  197. package/ui/drawer/README.md +274 -0
  198. package/ui/dropdown-menu/README.md +336 -0
  199. package/ui/editable-field/README.md +171 -0
  200. package/ui/icon-badge/README.md +131 -0
  201. package/ui/icon-list/README.md +205 -0
  202. package/ui/inline-edit/README.md +135 -0
  203. package/ui/list-editor/README.md +162 -0
  204. package/ui/loader/README.md +160 -0
  205. package/ui/menu-item/README.md +204 -0
  206. package/ui/nav-brand/README.md +111 -0
  207. package/ui/nav-group/README.md +145 -0
  208. package/ui/nav-separator/README.md +44 -0
  209. package/ui/node-tree/README.md +278 -0
  210. package/ui/node-tree-breadcrumb/README.md +164 -0
  211. package/ui/note/README.md +146 -0
  212. package/ui/numbered-list/README.md +187 -0
  213. package/ui/pagination/README.md +174 -0
  214. package/ui/progress-bar/README.md +223 -0
  215. package/ui/sidenav-link/README.md +214 -0
  216. package/ui/tabs/README.md +204 -0
  217. package/ui/timeline/README.md +285 -0
  218. package/ui/toast/README.md +243 -0
  219. package/ui/user-menu/README.md +260 -0
  220. 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.