@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,214 @@
1
+ # fk-sidenav-link
2
+
3
+ A token-driven sidebar navigation link that renders an icon and label, automatically hiding the label when the parent `fk-app-shell` is collapsed.
4
+
5
+ ---
6
+
7
+ ## API
8
+
9
+ ### Inputs
10
+
11
+ | Input | Type | Default | Description |
12
+ | ---------- | -------------------------------- | ------- | ------------------------------------------------------------------------------ |
13
+ | icon | `string` | — | **Required.** Icon name from the icon registry |
14
+ | iconSize | `IconSize` | `"sm"` | Size of the icon (`"xs"`, `"sm"`, `"md"`, `"lg"`, `"xl"`, or custom CSS value) |
15
+ | label | `string` | — | **Required.** Visible text label |
16
+ | routerLink | `string` \| `string[]` \| `null` | `null` | Angular Router link — renders `<a>` when set |
17
+ | exact | `boolean` | `false` | Use exact match for `routerLinkActive` highlighting |
18
+
19
+ ### Methods
20
+
21
+ | Method | Description |
22
+ | --------- | ------------------------------------------------------------------------ |
23
+ | dismiss() | Calls `dismissSidenav()` on the parent app-shell (closes mobile overlay) |
24
+
25
+ ### Computed (read-only)
26
+
27
+ | Property | Type | Description |
28
+ | ----------- | ----------------- | -------------------------------------------------- |
29
+ | isCollapsed | `Signal<boolean>` | Whether the parent app-shell is in collapsed state |
30
+
31
+ ---
32
+
33
+ ## Features
34
+
35
+ - Renders `<a>` with `routerLink` when a route is provided, `<button>` otherwise
36
+ - `routerLinkActive` class applied automatically for active route highlighting
37
+ - Label hides when parent `fk-app-shell` is collapsed (icon-only rail)
38
+ - Auto-dismisses mobile sidebar overlay on click
39
+ - Works standalone (outside an app-shell) — collapse detection gracefully defaults to `false`
40
+ - Token-driven styling with full override capability
41
+
42
+ ---
43
+
44
+ ## Quick Start
45
+
46
+ ```html
47
+ <fk-sidenav-link icon="chart-activity-fill" label="Overview" routerLink="/app" [exact]="true" />
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Import
53
+
54
+ ```ts
55
+ import { SidenavLinkComponent } from '@frame-kit/ui-ng';
56
+ ```
57
+
58
+ ```ts
59
+ @Component({
60
+ selector: 'app-sidebar',
61
+ imports: [SidenavLinkComponent],
62
+ templateUrl: './sidebar.component.html',
63
+ })
64
+ export class SidebarComponent {}
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Selector
70
+
71
+ ```html
72
+ <fk-sidenav-link />
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Examples
78
+
79
+ ### With Router Link
80
+
81
+ ```html
82
+ <fk-sidenav-link icon="chart-activity-fill" label="Overview" routerLink="/app" [exact]="true" />
83
+ ```
84
+
85
+ ### Button Mode (no route)
86
+
87
+ Renders a `<button>` instead of `<a>`. Useful for actions like opening a dialog.
88
+
89
+ ```html
90
+ <fk-sidenav-link icon="email" label="Notifications" />
91
+ ```
92
+
93
+ ### Nav List
94
+
95
+ ```html
96
+ <nav style="display: flex; flex-direction: column; gap: 0.25rem;">
97
+ <fk-sidenav-link icon="chart-activity-fill" label="Overview" routerLink="/app" [exact]="true" />
98
+ <fk-sidenav-link icon="organization" label="Properties" />
99
+ <fk-sidenav-link icon="email" label="Notifications" />
100
+ <fk-sidenav-link icon="lock" label="Compliance" />
101
+ <fk-sidenav-link icon="shield-alert" label="Insurance" />
102
+ </nav>
103
+ ```
104
+
105
+ ### Inside App Shell
106
+
107
+ ```html
108
+ <fk-app-shell mode="icon">
109
+ <nav appShellSidenav>
110
+ <fk-sidenav-link icon="chart-activity-fill" label="Overview" routerLink="/app" [exact]="true" />
111
+ <fk-sidenav-link icon="organization" label="Properties" />
112
+ <fk-sidenav-link icon="email" label="Notifications" />
113
+ </nav>
114
+
115
+ <div appShellSidenavFooter>
116
+ <fk-sidenav-link icon="info" label="Help & Support" />
117
+ </div>
118
+
119
+ <div appShellContent>
120
+ <router-outlet />
121
+ </div>
122
+ </fk-app-shell>
123
+ ```
124
+
125
+ When the shell is collapsed, only icons are shown. When expanded, icons and labels are both visible.
126
+
127
+ ---
128
+
129
+ ## Accessibility
130
+
131
+ - Renders a native `<a>` or `<button>` element — keyboard accessible by default
132
+ - Supports Enter and Space through native element behavior
133
+ - `focus-visible` ring applied via CSS token
134
+ - `routerLinkActive` provides visual indication of the current route
135
+ - When collapsed, the icon remains visible and the label is removed from the DOM (not just hidden)
136
+ - When collapsed, the host carries `aria-label="<label>"` so screen readers still get a name for the link, and a tooltip appears to the right on hover or keyboard focus (via the `[fkTooltip]` directive). When expanded, the visible label text serves both purposes — `aria-label` is omitted and the tooltip is disabled.
137
+
138
+ ### Recommended
139
+
140
+ Always register the icon before use:
141
+
142
+ ```ts
143
+ provideIcons({
144
+ 'chart-activity-fill': chartActivityFill,
145
+ organization,
146
+ email,
147
+ });
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Design Tokens
153
+
154
+ ### Component Tokens
155
+
156
+ ```
157
+ --fk-sidenav-link-gap
158
+ --fk-sidenav-link-padding-block
159
+ --fk-sidenav-link-padding-inline
160
+ --fk-sidenav-link-radius
161
+ --fk-sidenav-link-bg
162
+ --fk-sidenav-link-bg-hover
163
+ --fk-sidenav-link-bg-active
164
+ --fk-sidenav-link-font-family
165
+ --fk-sidenav-link-font-size
166
+ --fk-sidenav-link-font-weight-active
167
+ --fk-sidenav-link-color
168
+ --fk-sidenav-link-color-hover
169
+ --fk-sidenav-link-color-active
170
+ --fk-sidenav-link-focus-ring
171
+ ```
172
+
173
+ Each component token falls back to a semantic token, then a raw value. For example:
174
+
175
+ ```
176
+ --fk-sidenav-link-color → --fk-color-text → #1f2d3d
177
+ --fk-sidenav-link-color-hover → --fk-color-primary → #0a84ff
178
+ --fk-sidenav-link-color-active → --fk-color-primary → #0a84ff
179
+ --fk-sidenav-link-radius → --fk-radius-md → 0.5rem
180
+ --fk-sidenav-link-bg-hover → --fk-color-surface-dim → #edf1f5
181
+ ```
182
+
183
+ ### Customizing Tokens
184
+
185
+ Override tokens at any scope:
186
+
187
+ ```css
188
+ :root {
189
+ --fk-sidenav-link-color: #4338ca;
190
+ --fk-sidenav-link-bg-hover: #eef2ff;
191
+ --fk-sidenav-link-bg-active: #e0e7ff;
192
+ --fk-sidenav-link-font-weight-active: 700;
193
+ --fk-sidenav-link-radius: 0.25rem;
194
+ }
195
+ ```
196
+
197
+ Or scope to a specific context:
198
+
199
+ ```css
200
+ .dark-theme fk-sidenav-link {
201
+ --fk-sidenav-link-color: #e2e8f0;
202
+ --fk-sidenav-link-bg-hover: #1e293b;
203
+ --fk-sidenav-link-bg-active: #334155;
204
+ }
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Behavior Notes
210
+
211
+ - When used inside `fk-app-shell`, the component injects the parent via `inject(AppShellComponent, { optional: true })` to read collapse state
212
+ - When used outside an app-shell, `isCollapsed` is always `false` and labels are always visible
213
+ - Clicking any link calls `dismissSidenav()` on the parent shell, which closes the mobile overlay
214
+ - In collapsed state, the anchor centers its icon with `justify-content: center` and removes inline padding via the `.fk-app-shell--collapsed .fk-sidenav-link__anchor` rule
@@ -0,0 +1,204 @@
1
+ # fk-tabs
2
+
3
+ A compound component system for building accessible, keyboard-navigable tabbed interfaces. Follows the [WAI-ARIA Tabs pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).
4
+
5
+ ---
6
+
7
+ ## API
8
+
9
+ ### `fk-tabs`
10
+
11
+ Root container that provides shared state to all child tab components.
12
+
13
+ | Input | Type | Default | Description |
14
+ | ------------------- | -------------------------------------- | -------------- | ----------------------------------------------- |
15
+ | `value` | `string \| undefined` | `undefined` | Controlled active tab value |
16
+ | `defaultValue` | `string \| undefined` | `undefined` | Initial active tab (uncontrolled mode) |
17
+ | `variant` | `'underline' \| 'pill' \| 'contained'` | `'underline'` | Visual style of the tabs |
18
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of tab labels |
19
+ | `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Layout direction |
20
+ | `activationMode` | `'automatic' \| 'manual'` | `'automatic'` | Whether tabs activate on focus or require Enter |
21
+ | `lazy` | `boolean` | `false` | Defer panel rendering until first activation |
22
+ | `keepMounted` | `boolean` | `true` | Keep lazy panels in DOM after deactivation |
23
+ | `stretch` | `boolean` | `false` | Stretch tabs to fill available width |
24
+ | `fullWidth` | `boolean` | `false` | Make the tab bar span full width |
25
+ | `scrollable` | `boolean` | `false` | Enable horizontal scrolling for overflow tabs |
26
+ | `showScrollButtons` | `boolean` | `false` | Show prev/next scroll buttons |
27
+ | `className` | `string` | `''` | Additional CSS classes |
28
+
29
+ | Output | Type | Description |
30
+ | ------------- | ------------------ | -------------------------------------- |
31
+ | `valueChange` | `string` | Emits new value when selection changes |
32
+ | `tabChange` | `FkTabChangeEvent` | Emits `{ previousValue, value }` |
33
+ | `tabClose` | `FkTabCloseEvent` | Emits `{ value }` when a tab is closed |
34
+
35
+ ### `fk-tab-list`
36
+
37
+ Container for tab triggers. Applies `role="tablist"` and handles keyboard navigation.
38
+
39
+ | Input | Type | Default | Description |
40
+ | ----------- | ---------------- | ------- | --------------------------------- |
41
+ | `ariaLabel` | `string \| null` | `null` | Accessible label for the tab list |
42
+ | `className` | `string` | `''` | Additional CSS classes |
43
+
44
+ ### `fk-tab`
45
+
46
+ Individual tab trigger. Applies `role="tab"` with full ARIA attributes.
47
+
48
+ | Input | Type | Default | Description |
49
+ | ----------- | --------------------------------------------- | ----------- | ------------------------------- |
50
+ | `value` | `string` (required) | — | Unique identifier for this tab |
51
+ | `disabled` | `boolean` | `false` | Prevents selection |
52
+ | `closable` | `boolean` | `false` | Shows a close button |
53
+ | `badge` | `string \| number \| undefined` | `undefined` | Badge content next to the label |
54
+ | `icon` | `TemplateRef<unknown> \| string \| undefined` | `undefined` | Icon before the label |
55
+ | `className` | `string` | `''` | Additional CSS classes |
56
+
57
+ ### `fk-tab-panel`
58
+
59
+ Content panel associated with a tab. Applies `role="tabpanel"`.
60
+
61
+ | Input | Type | Default | Description |
62
+ | ----------- | ------------------- | ------- | ----------------------------------------- |
63
+ | `value` | `string` (required) | — | Must match a corresponding `fk-tab` value |
64
+ | `className` | `string` | `''` | Additional CSS classes |
65
+
66
+ ---
67
+
68
+ ## Features
69
+
70
+ - WAI-ARIA Tabs pattern with full keyboard support (arrow keys, Home/End, Enter/Space in manual mode)
71
+ - Three visual variants: `underline` (default, with sliding indicator), `pill`, `contained`
72
+ - Three sizes: `sm`, `md`, `lg`
73
+ - Horizontal and vertical orientations
74
+ - Automatic and manual activation modes
75
+ - Lazy panel rendering with optional keep-mounted (state preservation across deactivation)
76
+ - Closable tabs with `(tabClose)` event for dynamic tab strips
77
+ - Optional badge and icon slots on each tab
78
+ - Stretch / fullWidth / scrollable layouts for dense or overflow tab strips
79
+ - Controlled and uncontrolled modes (bind `[value]` + `(valueChange)`, or pass `defaultValue`)
80
+ - Auto-select fallback when the active tab is removed
81
+
82
+ ---
83
+
84
+ ## Quick Start
85
+
86
+ ```html
87
+ <fk-tabs defaultValue="account">
88
+ <fk-tab-list>
89
+ <fk-tab value="account">Account</fk-tab>
90
+ <fk-tab value="documents">Documents</fk-tab>
91
+ <fk-tab value="settings">Settings</fk-tab>
92
+ </fk-tab-list>
93
+
94
+ <fk-tab-panel value="account">Account content</fk-tab-panel>
95
+ <fk-tab-panel value="documents">Documents content</fk-tab-panel>
96
+ <fk-tab-panel value="settings">Settings content</fk-tab-panel>
97
+ </fk-tabs>
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Import
103
+
104
+ ```ts
105
+ import { FkTabsComponent, FkTabListComponent, FkTabComponent, FkTabPanelComponent } from '@frame-kit/ui-ng';
106
+ ```
107
+
108
+ ```ts
109
+ @Component({
110
+ selector: 'app-example',
111
+ imports: [FkTabsComponent, FkTabListComponent, FkTabComponent, FkTabPanelComponent],
112
+ templateUrl: './example.component.html',
113
+ })
114
+ export class ExampleComponent {}
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Examples
120
+
121
+ ### Controlled mode
122
+
123
+ ```html
124
+ <fk-tabs [value]="activeTab()" (valueChange)="activeTab.set($event)">
125
+ <fk-tab-list>
126
+ <fk-tab value="a">A</fk-tab>
127
+ <fk-tab value="b">B</fk-tab>
128
+ </fk-tab-list>
129
+ <fk-tab-panel value="a">Panel A</fk-tab-panel>
130
+ <fk-tab-panel value="b">Panel B</fk-tab-panel>
131
+ </fk-tabs>
132
+ ```
133
+
134
+ ### Closable tabs
135
+
136
+ ```html
137
+ <fk-tabs (tabClose)="removeTab($event.value)">
138
+ <fk-tab-list>
139
+ @for (tab of tabs(); track tab.id) {
140
+ <fk-tab [value]="tab.id" [closable]="true">{{ tab.label }}</fk-tab>
141
+ }
142
+ </fk-tab-list>
143
+ @for (tab of tabs(); track tab.id) {
144
+ <fk-tab-panel [value]="tab.id">{{ tab.content }}</fk-tab-panel>
145
+ }
146
+ </fk-tabs>
147
+ ```
148
+
149
+ ### Lazy rendering
150
+
151
+ ```html
152
+ <fk-tabs defaultValue="first" [lazy]="true" [keepMounted]="true">
153
+ <fk-tab-list>
154
+ <fk-tab value="first">First</fk-tab>
155
+ <fk-tab value="second">Second</fk-tab>
156
+ </fk-tab-list>
157
+ <fk-tab-panel value="first">Rendered immediately</fk-tab-panel>
158
+ <fk-tab-panel value="second">Rendered on first activation, then kept alive</fk-tab-panel>
159
+ </fk-tabs>
160
+ ```
161
+
162
+ ### Vertical orientation
163
+
164
+ ```html
165
+ <fk-tabs defaultValue="a" orientation="vertical">
166
+ <div style="display: flex;">
167
+ <fk-tab-list>
168
+ <fk-tab value="a">Account</fk-tab>
169
+ <fk-tab value="b">Security</fk-tab>
170
+ </fk-tab-list>
171
+ <div>
172
+ <fk-tab-panel value="a">Account settings</fk-tab-panel>
173
+ <fk-tab-panel value="b">Security settings</fk-tab-panel>
174
+ </div>
175
+ </div>
176
+ </fk-tabs>
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Accessibility
182
+
183
+ - `fk-tab-list` renders `role="tablist"` with `aria-orientation`
184
+ - Each `fk-tab` renders `role="tab"` with `aria-selected`, `aria-controls`, `aria-disabled`, and roving `tabindex`
185
+ - Each `fk-tab-panel` renders `role="tabpanel"` with `aria-labelledby` and `tabindex="0"`
186
+ - Tab and panel IDs are auto-generated and cross-linked
187
+ - Keyboard navigation: `ArrowLeft`/`ArrowRight` (horizontal), `ArrowUp`/`ArrowDown` (vertical), `Home`, `End`, `Enter`/`Space` (manual mode)
188
+ - Disabled tabs are skipped during keyboard navigation
189
+
190
+ ---
191
+
192
+ ## Design Tokens
193
+
194
+ Tab styling is driven by CSS custom properties scoped under the `.fk-tabs`, `.fk-tab-list`, `.fk-tab`, and `.fk-tab-panel` blocks. Override these in your theme to adjust colors, spacing, border radius, and indicator dimensions. The component responds to the global light/dark theme tokens from `@canopy/ui-shared`.
195
+
196
+ ---
197
+
198
+ ## Behavior Notes
199
+
200
+ - **Uncontrolled mode** (default): Pass `defaultValue` and the component manages selection internally.
201
+ - **Controlled mode**: Bind `[value]` and listen to `(valueChange)` to drive selection externally.
202
+ - **Auto-select**: If no `value` or `defaultValue` is provided, the first non-disabled tab is selected automatically.
203
+ - **Fallback**: When the active tab is removed, the first remaining enabled tab is selected.
204
+ - **Indicator**: The underline variant renders a sliding indicator that tracks the active tab via DOM measurement.
@@ -0,0 +1,285 @@
1
+ # fk-timeline
2
+
3
+ A token-driven timeline component for displaying ordered steps, resolution chains, audit trails, and workflow progress with status indicators and connectors.
4
+
5
+ ---
6
+
7
+ ## API
8
+
9
+ ### Inputs
10
+
11
+ | Input | Type | Default | Description |
12
+ | ------------- | --------------------------------- | ------------ | -------------------------------------------- |
13
+ | `items` | `TimelineItemData[]` | `[]` | Declarative data for timeline entries |
14
+ | `orientation` | `'vertical' \| 'horizontal'` | `'vertical'` | Layout direction |
15
+ | `align` | `'start' \| 'end' \| 'alternate'` | `'start'` | Content alignment relative to connector line |
16
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Marker and connector sizing |
17
+ | `reverse` | `boolean` | `false` | Reverse item order |
18
+ | `ariaLabel` | `string \| null` | `null` | Accessible label |
19
+ | `id` | `string \| null` | `null` | Element ID |
20
+ | `className` | `string` | `''` | Additional CSS classes merged onto the host |
21
+
22
+ ### Types
23
+
24
+ ```ts
25
+ interface TimelineItemData {
26
+ id?: string;
27
+ title?: string;
28
+ description?: string;
29
+ timestamp?: string;
30
+ icon?: string;
31
+ status?: TimelineItemStatus;
32
+ }
33
+
34
+ type TimelineItemStatus = 'default' | 'active' | 'completed' | 'error' | 'warning';
35
+ type TimelineOrientation = 'vertical' | 'horizontal';
36
+ type TimelineAlign = 'start' | 'end' | 'alternate';
37
+ type TimelineSize = 'sm' | 'md' | 'lg';
38
+ ```
39
+
40
+ ### Outputs
41
+
42
+ None.
43
+
44
+ ---
45
+
46
+ ## Features
47
+
48
+ - Vertical and horizontal orientations
49
+ - Three alignment modes (start, end, alternate)
50
+ - Three size presets (sm, md, lg)
51
+ - Five status variants (default, active, completed, error, warning)
52
+ - Custom icon support per item
53
+ - Optional timestamp display
54
+ - Reversible item order
55
+ - Content projection for complex custom items
56
+ - Token-driven styling with two-tier fallbacks
57
+ - Full ARIA list semantics
58
+ - Dark mode support
59
+
60
+ ---
61
+
62
+ ## Quick Start
63
+
64
+ ```html
65
+ <fk-timeline
66
+ [items]="[
67
+ { title: 'Step 1', status: 'completed' },
68
+ { title: 'Step 2', status: 'active' },
69
+ { title: 'Step 3', status: 'default' }
70
+ ]"
71
+ ></fk-timeline>
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Import
77
+
78
+ ```ts
79
+ import { TimelineComponent } from '@frame-kit/ui-ng';
80
+ ```
81
+
82
+ ```ts
83
+ @Component({
84
+ selector: 'app-example',
85
+ imports: [TimelineComponent],
86
+ templateUrl: './example.component.html',
87
+ })
88
+ export class ExampleComponent {}
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Selector
94
+
95
+ ```html
96
+ <fk-timeline></fk-timeline>
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Examples
102
+
103
+ ### Default (vertical, start-aligned)
104
+
105
+ ```html
106
+ <fk-timeline [items]="items"></fk-timeline>
107
+ ```
108
+
109
+ ### Horizontal
110
+
111
+ ```html
112
+ <fk-timeline [items]="items" orientation="horizontal"></fk-timeline>
113
+ ```
114
+
115
+ ### Alternate alignment
116
+
117
+ ```html
118
+ <fk-timeline [items]="items" align="alternate"></fk-timeline>
119
+ ```
120
+
121
+ ### Sizes
122
+
123
+ ```html
124
+ <fk-timeline [items]="items" size="sm"></fk-timeline>
125
+ <fk-timeline [items]="items" size="md"></fk-timeline>
126
+ <fk-timeline [items]="items" size="lg"></fk-timeline>
127
+ ```
128
+
129
+ ### All status variants
130
+
131
+ ```html
132
+ <fk-timeline
133
+ [items]="[
134
+ { title: 'Done', status: 'completed' },
135
+ { title: 'Current', status: 'active' },
136
+ { title: 'Attention', status: 'warning' },
137
+ { title: 'Failed', status: 'error' },
138
+ { title: 'Pending', status: 'default' }
139
+ ]"
140
+ ></fk-timeline>
141
+ ```
142
+
143
+ ### With icons
144
+
145
+ ```html
146
+ <fk-timeline
147
+ [items]="[
148
+ { title: 'Submitted', icon: 'circle-check-outline', status: 'completed' },
149
+ { title: 'In Review', icon: 'shield-alert', status: 'active' },
150
+ { title: 'Approved', icon: 'lock', status: 'default' }
151
+ ]"
152
+ ></fk-timeline>
153
+ ```
154
+
155
+ ### With timestamps
156
+
157
+ ```html
158
+ <fk-timeline
159
+ [items]="[
160
+ { title: 'Created', timestamp: 'Jan 15', status: 'completed' },
161
+ { title: 'Updated', timestamp: 'Feb 1', status: 'active' }
162
+ ]"
163
+ ></fk-timeline>
164
+ ```
165
+
166
+ ### Reversed order
167
+
168
+ ```html
169
+ <fk-timeline [items]="items" [reverse]="true"></fk-timeline>
170
+ ```
171
+
172
+ ### Content projection (advanced)
173
+
174
+ ```html
175
+ <fk-timeline>
176
+ <ng-content />
177
+ </fk-timeline>
178
+ ```
179
+
180
+ ---
181
+
182
+ ## Accessibility
183
+
184
+ `fk-timeline` applies `role="list"` on the host element with `aria-orientation` reflecting the layout direction.
185
+
186
+ Accessibility behavior:
187
+
188
+ - `role="list"` on the timeline container
189
+ - `role="listitem"` on each timeline item
190
+ - `aria-orientation` reflects vertical or horizontal
191
+ - Supports `ariaLabel` for additional context
192
+
193
+ ### Recommended
194
+
195
+ ```html
196
+ <fk-timeline [items]="items" ariaLabel="Policy resolution chain"></fk-timeline>
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Design Tokens
202
+
203
+ `fk-timeline` is styled entirely through design tokens.
204
+
205
+ ### Component-specific tokens
206
+
207
+ ```
208
+ --fk-timeline-gap
209
+ --fk-timeline-item-gap
210
+ --fk-timeline-marker-size-sm
211
+ --fk-timeline-marker-size-md
212
+ --fk-timeline-marker-size-lg
213
+ --fk-timeline-marker-bg
214
+ --fk-timeline-marker-border-color
215
+ --fk-timeline-marker-border-width
216
+ --fk-timeline-marker-color
217
+ --fk-timeline-marker-active
218
+ --fk-timeline-marker-completed
219
+ --fk-timeline-marker-error
220
+ --fk-timeline-marker-warning
221
+ --fk-timeline-connector-width
222
+ --fk-timeline-connector-color
223
+ --fk-timeline-connector-length
224
+ --fk-timeline-content-gap
225
+ --fk-timeline-title-font-size
226
+ --fk-timeline-title-font-weight
227
+ --fk-timeline-title-color
228
+ --fk-timeline-description-font-size
229
+ --fk-timeline-description-color
230
+ --fk-timeline-timestamp-font-size
231
+ --fk-timeline-timestamp-color
232
+ ```
233
+
234
+ ### Shared tokens
235
+
236
+ ```
237
+ --fk-color-primary
238
+ --fk-color-success
239
+ --fk-color-danger
240
+ --fk-color-warning
241
+ --fk-color-surface
242
+ --fk-color-border
243
+ --fk-color-text
244
+ --fk-color-muted
245
+ --fk-typography-body-font-size
246
+ --fk-typography-small-font-size
247
+ --fk-typography-caption-font-size
248
+ --fk-font-weight-medium
249
+ --fk-rhythm-1
250
+ --fk-rhythm-2
251
+ --fk-rhythm-3
252
+ --fk-radius-md
253
+ ```
254
+
255
+ ### Customizing Tokens
256
+
257
+ Override tokens in your application's stylesheet:
258
+
259
+ ```scss
260
+ :root {
261
+ --fk-timeline-marker-size-md: 2rem;
262
+ --fk-timeline-connector-color: #e5e7eb;
263
+ --fk-timeline-marker-active: #6366f1;
264
+ }
265
+ ```
266
+
267
+ Or scope overrides to a specific context:
268
+
269
+ ```scss
270
+ .compact-timeline fk-timeline {
271
+ --fk-timeline-marker-size-md: 1rem;
272
+ --fk-timeline-item-gap: 0.5rem;
273
+ }
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Behavior Notes
279
+
280
+ - Horizontal timelines expand to fill the parent container width; wrap in a sized container to constrain
281
+ - Vertical timelines take only the height of their content
282
+ - The last item never renders a connector line
283
+ - Alternate alignment uses CSS grid to keep the connector line centered
284
+ - Icons must be registered via `provideIcons()` before use
285
+ - Status variants control marker fill color; the default status renders as an outlined circle