@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,336 @@
1
+ # fk-dropdown-menu
2
+
3
+ A compound dropdown menu component that orchestrates a trigger, floating panel, and projected menu items using Angular content projection.
4
+
5
+ ---
6
+
7
+ ## API
8
+
9
+ ### fk-dropdown-menu
10
+
11
+ #### Inputs
12
+
13
+ | Input | Type | Default | Description |
14
+ | ------------ | ---------------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15
+ | `placement` | `'bottom-start'` \| `'bottom-end'` | `'bottom-end'` | Horizontal alignment of the panel |
16
+ | `disabled` | `boolean` | `false` | Disables opening the menu |
17
+ | `portal` | `boolean` | `false` | When true, the panel is teleported to `document.body` and positioned with `position: fixed`. Use this when the menu lives inside an ancestor with `overflow: hidden` (e.g. an app sidebar) that would otherwise clip it |
18
+ | `panelClass` | `string \| null` | `null` | Extra CSS class applied to the floating panel element. Useful for instance-specific overrides when the panel is portaled |
19
+ | `ariaLabel` | `string \| null` | `null` | ARIA label for the menu panel |
20
+ | `className` | `string` | `''` | Additional CSS classes for the host |
21
+ | `id` | `string \| null` | `null` | Optional ID for the host |
22
+
23
+ #### Outputs
24
+
25
+ | Output | Type | Description |
26
+ | ----------- | ------ | ---------------------------- |
27
+ | `menuOpen` | `void` | Emitted when the menu opens |
28
+ | `menuClose` | `void` | Emitted when the menu closes |
29
+
30
+ #### Methods
31
+
32
+ | Method | Description |
33
+ | ---------- | ------------------------------- |
34
+ | `open()` | Programmatically open the menu |
35
+ | `close()` | Programmatically close the menu |
36
+ | `toggle()` | Toggle the menu open/closed |
37
+
38
+ #### Content Slots
39
+
40
+ | Slot | Selector | Description |
41
+ | ----------- | --------------------- | --------------------------------------------------- |
42
+ | **Trigger** | `[fkDropdownTrigger]` | The element that opens the menu on click/keyboard |
43
+ | **Panel** | `[fkDropdownPanel]` | An `<ng-template>` containing the menu item content |
44
+
45
+ ### fkDropdownTrigger (directive)
46
+
47
+ Applied to the element that toggles the menu. Sets `aria-haspopup="menu"` and manages `aria-expanded` automatically.
48
+
49
+ ### fkDropdownPanel (directive)
50
+
51
+ Applied to an `<ng-template>` that contains menu items. The template is rendered inside a positioned panel only when the menu is open.
52
+
53
+ ### fk-menu-item
54
+
55
+ | Input | Type | Default | Description |
56
+ | ---------- | ---------------- | ------- | ----------------------------------------- |
57
+ | `icon` | `string \| null` | `null` | Optional icon name shown before the label |
58
+ | `danger` | `boolean` | `false` | Applies destructive/danger styling |
59
+ | `disabled` | `boolean` | `false` | Disables the item |
60
+
61
+ | Output | Type | Description |
62
+ | ----------- | ------ | ---------------------------------- |
63
+ | `itemClick` | `void` | Emitted when the item is activated |
64
+
65
+ The item label is provided through content projection.
66
+
67
+ ### fk-menu-separator
68
+
69
+ A visual divider between menu item groups. No inputs or outputs.
70
+
71
+ ---
72
+
73
+ ## Features
74
+
75
+ - Compound component architecture (trigger, panel, items composed independently)
76
+ - Viewport-aware panel positioning with automatic flip/shift
77
+ - Full keyboard navigation (ArrowDown/Up, Home, End, Escape, Tab)
78
+ - Outside click detection
79
+ - Auto-close on item selection
80
+ - Disabled state for entire menu or individual items
81
+ - Danger variant for destructive actions
82
+ - Token-driven styling
83
+ - Accessible by default
84
+
85
+ ---
86
+
87
+ ## Quick Start
88
+
89
+ ```html
90
+ <fk-dropdown-menu>
91
+ <button fkDropdownTrigger>Actions</button>
92
+ <ng-template fkDropdownPanel>
93
+ <fk-menu-item icon="eye">View</fk-menu-item>
94
+ <fk-menu-item icon="gear-outline">Settings</fk-menu-item>
95
+ <fk-menu-separator />
96
+ <fk-menu-item icon="open-rect-arrow-out-fill" [danger]="true">Delete</fk-menu-item>
97
+ </ng-template>
98
+ </fk-dropdown-menu>
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Import
104
+
105
+ ```ts
106
+ import { DropdownMenuComponent, DropdownTriggerDirective, DropdownPanelDirective, MenuItemComponent, MenuSeparatorComponent } from '@frame-kit/ui-ng';
107
+ ```
108
+
109
+ ```ts
110
+ @Component({
111
+ selector: 'app-example',
112
+ imports: [DropdownMenuComponent, DropdownTriggerDirective, DropdownPanelDirective, MenuItemComponent, MenuSeparatorComponent],
113
+ templateUrl: './example.component.html',
114
+ })
115
+ export class ExampleComponent {}
116
+ ```
117
+
118
+ ---
119
+
120
+ ## Selectors
121
+
122
+ ```html
123
+ <fk-dropdown-menu></fk-dropdown-menu>
124
+ <fk-menu-item></fk-menu-item>
125
+ <fk-menu-separator></fk-menu-separator>
126
+ ```
127
+
128
+ Directives:
129
+
130
+ ```html
131
+ <button fkDropdownTrigger>...</button> <ng-template fkDropdownPanel>...</ng-template>
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Examples
137
+
138
+ ### Bottom-start placement
139
+
140
+ ```html
141
+ <fk-dropdown-menu placement="bottom-start">
142
+ <button fkDropdownTrigger>Options</button>
143
+ <ng-template fkDropdownPanel>
144
+ <fk-menu-item>Copy</fk-menu-item>
145
+ <fk-menu-item>Paste</fk-menu-item>
146
+ </ng-template>
147
+ </fk-dropdown-menu>
148
+ ```
149
+
150
+ ### With disabled items
151
+
152
+ ```html
153
+ <fk-dropdown-menu>
154
+ <button fkDropdownTrigger>Options</button>
155
+ <ng-template fkDropdownPanel>
156
+ <fk-menu-item icon="eye">View</fk-menu-item>
157
+ <fk-menu-item icon="gear-outline" [disabled]="true">Settings (locked)</fk-menu-item>
158
+ <fk-menu-separator />
159
+ <fk-menu-item icon="info">Help</fk-menu-item>
160
+ </ng-template>
161
+ </fk-dropdown-menu>
162
+ ```
163
+
164
+ ### Danger items
165
+
166
+ ```html
167
+ <fk-dropdown-menu>
168
+ <button fkDropdownTrigger>Manage</button>
169
+ <ng-template fkDropdownPanel>
170
+ <fk-menu-item icon="eye">View</fk-menu-item>
171
+ <fk-menu-separator />
172
+ <fk-menu-item icon="open-rect-arrow-out-fill" [danger]="true">Remove</fk-menu-item>
173
+ </ng-template>
174
+ </fk-dropdown-menu>
175
+ ```
176
+
177
+ ### Disabled menu
178
+
179
+ ```html
180
+ <fk-dropdown-menu [disabled]="true">
181
+ <button fkDropdownTrigger>Disabled</button>
182
+ <ng-template fkDropdownPanel>
183
+ <fk-menu-item>This won't show</fk-menu-item>
184
+ </ng-template>
185
+ </fk-dropdown-menu>
186
+ ```
187
+
188
+ ### Inside an `overflow: hidden` ancestor (sidebar, drawer, scroll container)
189
+
190
+ When the dropdown sits inside a container that clips its overflow — most commonly the app-shell sidebar or a drawer — the inline-positioned panel gets cut off. Set `[portal]="true"` to teleport the panel to `document.body` and position it with `position: fixed` using viewport coordinates. The trigger stays in place; only the floating panel relocates.
191
+
192
+ ```html
193
+ <fk-dropdown-menu placement="bottom-start" [portal]="true">
194
+ <button fkDropdownTrigger>Switch workspace</button>
195
+ <ng-template fkDropdownPanel>
196
+ <fk-menu-item>Production</fk-menu-item>
197
+ <fk-menu-item>Staging</fk-menu-item>
198
+ </ng-template>
199
+ </fk-dropdown-menu>
200
+ ```
201
+
202
+ ### Custom trigger (kebab menu)
203
+
204
+ Any focusable element can serve as the trigger:
205
+
206
+ ```html
207
+ <fk-dropdown-menu>
208
+ <span fkDropdownTrigger tabindex="0" role="button">&#8942;</span>
209
+ <ng-template fkDropdownPanel>
210
+ <fk-menu-item>Edit</fk-menu-item>
211
+ <fk-menu-item [danger]="true">Delete</fk-menu-item>
212
+ </ng-template>
213
+ </fk-dropdown-menu>
214
+ ```
215
+
216
+ ### Handling item clicks
217
+
218
+ ```html
219
+ <fk-dropdown-menu>
220
+ <button fkDropdownTrigger>Actions</button>
221
+ <ng-template fkDropdownPanel>
222
+ <fk-menu-item (itemClick)="onView()">View</fk-menu-item>
223
+ <fk-menu-item (itemClick)="onEdit()">Edit</fk-menu-item>
224
+ <fk-menu-separator />
225
+ <fk-menu-item (itemClick)="onDelete()" [danger]="true">Delete</fk-menu-item>
226
+ </ng-template>
227
+ </fk-dropdown-menu>
228
+ ```
229
+
230
+ The menu automatically closes when any non-disabled item is clicked.
231
+
232
+ ---
233
+
234
+ ## Accessibility
235
+
236
+ - Trigger receives `aria-haspopup="menu"` and `aria-expanded` automatically via the `fkDropdownTrigger` directive
237
+ - Panel uses `role="menu"` with optional `aria-label`
238
+ - Items use `role="menuitem"` with `tabindex="-1"` for roving focus
239
+ - Disabled items receive `aria-disabled="true"` and are excluded from keyboard navigation
240
+ - Separators use `role="separator"`
241
+
242
+ ### Keyboard behavior
243
+
244
+ | Key | Context | Action |
245
+ | --------- | --------- | ----------------------------------- |
246
+ | Enter | Trigger | Toggle menu |
247
+ | Space | Trigger | Toggle menu |
248
+ | ArrowDown | Trigger | Open menu and focus first item |
249
+ | ArrowDown | Menu open | Move focus to next item |
250
+ | ArrowUp | Menu open | Move focus to previous item |
251
+ | Home | Menu open | Move focus to first item |
252
+ | End | Menu open | Move focus to last item |
253
+ | Escape | Menu open | Close menu, return focus to trigger |
254
+ | Tab | Menu open | Close menu |
255
+ | Enter | Menu item | Activate item |
256
+ | Space | Menu item | Activate item |
257
+
258
+ ---
259
+
260
+ ## Design Tokens
261
+
262
+ ### Panel tokens
263
+
264
+ ```
265
+ --fk-dropdown-menu-panel-z
266
+ --fk-dropdown-menu-panel-min-width
267
+ --fk-dropdown-menu-panel-padding
268
+ --fk-dropdown-menu-panel-radius
269
+ --fk-dropdown-menu-panel-bg
270
+ --fk-dropdown-menu-panel-border
271
+ --fk-dropdown-menu-panel-shadow
272
+ --fk-dropdown-menu-enter-duration
273
+ --fk-dropdown-menu-enter-easing
274
+ ```
275
+
276
+ ### Menu item tokens
277
+
278
+ ```
279
+ --fk-menu-item-gap
280
+ --fk-menu-item-padding
281
+ --fk-menu-item-radius
282
+ --fk-menu-item-font-family
283
+ --fk-menu-item-font-size
284
+ --fk-menu-item-color
285
+ --fk-menu-item-bg-hover
286
+ --fk-menu-item-focus-ring
287
+ --fk-menu-item-opacity-disabled
288
+ --fk-menu-item-transition-duration
289
+ --fk-menu-item-transition-easing
290
+ --fk-menu-item-danger-color
291
+ --fk-menu-item-danger-bg-hover
292
+ ```
293
+
294
+ ### Separator tokens
295
+
296
+ ```
297
+ --fk-menu-separator-color
298
+ ```
299
+
300
+ ### Customizing tokens
301
+
302
+ Override tokens in your application's global stylesheet or a scoped selector:
303
+
304
+ ```css
305
+ :root {
306
+ --fk-dropdown-menu-panel-radius: 0.25rem;
307
+ --fk-menu-item-bg-hover: #f5f3ff;
308
+ --fk-menu-item-danger-color: #dc2626;
309
+ }
310
+ ```
311
+
312
+ Or scope overrides to a specific instance:
313
+
314
+ ```html
315
+ <div
316
+ style="
317
+ --fk-dropdown-menu-panel-bg: #fefce8;
318
+ --fk-dropdown-menu-panel-border: #ca8a04;
319
+ --fk-menu-item-bg-hover: #fef9c3;
320
+ "
321
+ >
322
+ <fk-dropdown-menu>
323
+ <!-- ... -->
324
+ </fk-dropdown-menu>
325
+ </div>
326
+ ```
327
+
328
+ ---
329
+
330
+ ## Behavior Notes
331
+
332
+ - The panel is positioned absolutely relative to the host and flips vertically when there is not enough space below
333
+ - Horizontal placement shifts the panel to stay within the viewport
334
+ - Clicking outside the menu or pressing Tab closes it
335
+ - Items dispatch a custom `fkmenuitemselect` event that bubbles up, triggering auto-close at the panel level
336
+ - `fk-menu-item` and `fk-menu-separator` are standalone atom components that can be reused in other menu-like contexts (e.g., context menus)
@@ -0,0 +1,171 @@
1
+ # fk-editable-field
2
+
3
+ A bordered single-line text field that switches between a display read-out and a live editable input, with the affordance icon (pencil → cancel) anchored _inside_ the trailing edge. Built for form-shaped surfaces (billing details, profile pages) where every row should _look_ like a regular form input even when it's not being edited.
4
+
5
+ ## API
6
+
7
+ ### Inputs
8
+
9
+ | Input | Type | Default | Description |
10
+ | ----------------- | ------------------- | ------------------ | ----------------------------------------------------------------------------- |
11
+ | `value` | `string` | `""` | Current committed value shown in display mode. |
12
+ | `placeholder` | `string` | `"Enter a value…"` | Placeholder shown inside the input when the edit buffer is empty. |
13
+ | `size` | `EditableFieldSize` | `"md"` | `"sm" \| "md" \| "lg"` — font + spacing scale. |
14
+ | `emptyText` | `string` | `"None"` | Text rendered in display mode when `value` is empty. |
15
+ | `className` | `string` | `""` | Additional CSS classes merged onto the host. |
16
+ | `id` | `string \| null` | `null` | Optional `id` forwarded to the host element. |
17
+ | `ariaLabel` | `string \| null` | `null` | Accessible label. In display mode the rendered label is `"Edit {ariaLabel}"`. |
18
+ | `ariaDescribedBy` | `string \| null` | `null` | `aria-describedby` forwarded onto the field surface. |
19
+ | `disabled` | `boolean` | `false` | When `true`, the field is read-only and the pencil affordance is hidden. |
20
+
21
+ ### Outputs
22
+
23
+ | Output | Type | Description |
24
+ | ------------- | ---------------------- | --------------------------------------------------------- |
25
+ | `valueChange` | `EventEmitter<string>` | Fires on save with the trimmed value the user typed. |
26
+ | `editStart` | `EventEmitter<void>` | Fires when the component enters edit mode. |
27
+ | `editCancel` | `EventEmitter<void>` | Fires when the user cancels without saving (X or Escape). |
28
+
29
+ ### Content
30
+
31
+ Three optional named slots — each accepts any markup, typically an `<fk-icon>`:
32
+
33
+ | Slot | When it renders |
34
+ | -------------- | ------------------------------------------------------------------- |
35
+ | `[editIcon]` | Display mode, replaces the default pencil. |
36
+ | `[cancelIcon]` | Edit mode, replaces the default `circleXmarkOutline`. |
37
+ | `[saveIcon]` | Edit mode, replaces the default `"Save"` text on the action button. |
38
+
39
+ ```html
40
+ <fk-editable-field [value]="name" (valueChange)="onSave($event)">
41
+ <fk-icon editIcon name="pen-outline" size="sm" />
42
+ <fk-icon cancelIcon name="circle-xmark-outline" size="sm" />
43
+ </fk-editable-field>
44
+ ```
45
+
46
+ ### Types
47
+
48
+ ```ts
49
+ export type EditableFieldSize = 'sm' | 'md' | 'lg';
50
+ ```
51
+
52
+ ## Features
53
+
54
+ - Display mode reads as a full bordered input — no visual jump when the user enters edit mode.
55
+ - Affordance icon (pencil) sits inside the trailing edge, replaced by a cancel (✗) icon while editing.
56
+ - A single Save button slides in as a sibling on the right only while editing.
57
+ - Save commits via Enter or Save button; cancel via Escape or the trailing X.
58
+ - Focus ring spans the whole bordered shell, including the trailing slot.
59
+ - Custom edit / cancel / save icons via named content slots.
60
+ - Six exposed component tokens for typography, padding, colors, and the focus ring.
61
+
62
+ ## Quick Start
63
+
64
+ ```html
65
+ <fk-editable-field [value]="billingName" ariaLabel="Billing name" (valueChange)="saveBillingName($event)" />
66
+ ```
67
+
68
+ ## Import
69
+
70
+ ```ts
71
+ import { EditableFieldComponent } from '@frame-kit/ui-ng';
72
+ ```
73
+
74
+ ```ts
75
+ @Component({
76
+ selector: 'app-billing-details',
77
+ standalone: true,
78
+ imports: [EditableFieldComponent],
79
+ templateUrl: './billing-details.component.html',
80
+ })
81
+ export class BillingDetailsComponent {}
82
+ ```
83
+
84
+ ## Selector
85
+
86
+ ```
87
+ <fk-editable-field />
88
+ ```
89
+
90
+ ## Examples
91
+
92
+ ### A row in a form-shaped card
93
+
94
+ ```html
95
+ <div class="row">
96
+ <span class="label">Billing name</span>
97
+ <fk-editable-field [value]="name()" (valueChange)="onSaveName($event)" />
98
+ </div>
99
+ ```
100
+
101
+ ### Empty / placeholder state
102
+
103
+ ```html
104
+ <fk-editable-field [value]="line2 ?? ''" emptyText="Not set" placeholder="Apt / suite / care-of" (valueChange)="onSaveLine2($event)" />
105
+ ```
106
+
107
+ ### Disabled (read-only)
108
+
109
+ ```html
110
+ <fk-editable-field value="locked@acme.test" [disabled]="true" />
111
+ ```
112
+
113
+ ### Custom icons
114
+
115
+ ```html
116
+ <fk-editable-field [value]="city" (valueChange)="onSaveCity($event)">
117
+ <fk-icon editIcon name="pen-outline" size="sm" />
118
+ </fk-editable-field>
119
+ ```
120
+
121
+ ## Accessibility
122
+
123
+ - The display surface is a real `<button>` so it's reachable via Tab and activatable with Enter or Space.
124
+ - `ariaLabel` is forwarded to the display button as `"Edit {ariaLabel}"` so screen-reader users hear the intent without an extra hidden label.
125
+ - The trailing cancel button in edit mode carries `aria-label="Cancel"`; the Save button carries `aria-label="Save"`.
126
+ - Keyboard: Enter commits the edit, Escape cancels.
127
+ - Focus ring is owned by the bordered shell (via `:focus-within` in edit mode) so it spans the full visual field including the trailing slot.
128
+ - When `disabled`, the display surface is a disabled `<button>` and the pencil slot is removed entirely so the row reads as static text.
129
+
130
+ ## Design Tokens
131
+
132
+ ```scss
133
+ --fk-editable-field-bg
134
+ --fk-editable-field-border-color
135
+ --fk-editable-field-border-radius
136
+ --fk-editable-field-focus-border
137
+ --fk-editable-field-hover-border
138
+ --fk-editable-field-color
139
+ --fk-editable-field-empty-color
140
+ --fk-editable-field-font-size
141
+ --fk-editable-field-sm-font-size
142
+ --fk-editable-field-lg-font-size
143
+ --fk-editable-field-lg-font-weight
144
+ --fk-editable-field-input-padding
145
+ --fk-editable-field-trailing-padding
146
+ --fk-editable-field-gap
147
+ --fk-editable-field-trigger-color
148
+ --fk-editable-field-trigger-hover-color
149
+ --fk-editable-field-inline-btn-size
150
+ --fk-editable-field-save-bg
151
+ --fk-editable-field-save-color
152
+ --fk-editable-field-action-font-size
153
+ --fk-editable-field-disabled-opacity
154
+ ```
155
+
156
+ Override in your app stylesheet:
157
+
158
+ ```scss
159
+ :root {
160
+ --fk-editable-field-border-radius: 0.5rem;
161
+ --fk-editable-field-save-bg: var(--fk-color-success);
162
+ }
163
+ ```
164
+
165
+ ## Behavior Notes
166
+
167
+ - Saving emits the **trimmed** value — leading / trailing whitespace is stripped before `valueChange` fires.
168
+ - Save and Cancel each exit edit mode; the parent's `valueChange` handler is responsible for any network round-trip.
169
+ - The component does not re-fetch the displayed `value` after `valueChange` — the parent owns the source of truth (typically a store / signal that the input re-renders from).
170
+ - `value` is reset to `value()` on every `startEdit()` call, so external updates between sessions always win on the next edit.
171
+ - Disabled fields keep the bordered display shell but drop the pencil — clicking the row is a no-op.
@@ -0,0 +1,131 @@
1
+ # fk-icon-badge
2
+
3
+ An icon-only badge component that combines `fk-icon` with token-driven background, border, and shape styles.
4
+
5
+ ---
6
+
7
+ ## API
8
+
9
+ ### Inputs
10
+
11
+ | Input | Type | Default | Description |
12
+ | ----------------- | ------------------- | ----------- | --------------------------------------------------------------- |
13
+ | `name` | `string` (required) | — | Icon name registered in the icon registry |
14
+ | `size` | `IconSize` | `"md"` | Icon size (`xs`, `sm`, `md`, `lg`, `xl`) |
15
+ | `shape` | `IconBadgeShape` | `"circle"` | Badge shape (`circle`, `square`, etc., depending on type union) |
16
+ | `color` | `IconColor` | `"inherit"` | Icon color variant or custom when mapped to tokens |
17
+ | `borderColor` | `string \| null` | `null` | Optional custom border color |
18
+ | `backgroundColor` | `string \| null` | `null` | Optional custom background color |
19
+ | `className` | `string` | `''` | Additional CSS classes for the host element |
20
+ | `id` | `string \| null` | `null` | Optional ID |
21
+ | `ariaLabel` | `string \| null` | `null` | Accessible label when the badge conveys meaning |
22
+ | `ariaHidden` | `boolean \| null` | `null` | Explicit ARIA hidden flag; falls back to `ariaLabel` when null |
23
+
24
+ ### Outputs
25
+
26
+ `fk-icon-badge` is presentational and does not emit outputs.
27
+
28
+ ---
29
+
30
+ ## Features
31
+
32
+ - Icon-centered badge with configurable size, shape, and colors
33
+ - Accessible by default when `ariaLabel` is provided
34
+ - Token-driven styles for radius, padding, and colors
35
+ - Can be used for statuses, steps, or decorative accents
36
+
37
+ ---
38
+
39
+ ## Quick Start
40
+
41
+ ```html
42
+ <fk-icon-badge name="check-circle" color="success"></fk-icon-badge>
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Import
48
+
49
+ ```ts
50
+ import { IconBadgeComponent } from '@frame-kit/ui-ng';
51
+ ```
52
+
53
+ ```ts
54
+ @Component({
55
+ selector: 'app-example',
56
+ imports: [IconBadgeComponent],
57
+ templateUrl: './example.component.html',
58
+ })
59
+ export class ExampleComponent {}
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Selector
65
+
66
+ ```html
67
+ <fk-icon-badge></fk-icon-badge>
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Examples
73
+
74
+ ### Status badge
75
+
76
+ ```html
77
+ <fk-icon-badge name="check" color="success" ariaLabel="Completed"></fk-icon-badge>
78
+ ```
79
+
80
+ ### Warning badge with custom background
81
+
82
+ ```html
83
+ <fk-icon-badge name="alert-triangle" color="danger" [backgroundColor]="'#fef2f2'" [borderColor]="'#fecaca'" ariaLabel="Attention needed"></fk-icon-badge>
84
+ ```
85
+
86
+ ### Step indicator
87
+
88
+ ```html
89
+ <fk-icon-badge name="1" shape="square" ariaLabel="Step 1"></fk-icon-badge>
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Accessibility
95
+
96
+ - If `ariaHidden` is not explicitly set:
97
+ - When `ariaLabel` is provided, the badge uses `role="img"` and is exposed to assistive technologies.
98
+ - When `ariaLabel` is `null`, the badge is treated as decorative (`aria-hidden="true"`).
99
+ - Use `ariaLabel` for badges that indicate status or steps; omit it for purely visual decoration.
100
+
101
+ ---
102
+
103
+ ## Design Tokens
104
+
105
+ `fk-icon-badge` uses badge-related tokens such as:
106
+
107
+ ```scss
108
+ --fk-icon-badge-size-xs;
109
+ --fk-icon-badge-size-sm;
110
+ --fk-icon-badge-size-md;
111
+ --fk-icon-badge-size-lg;
112
+ --fk-icon-badge-radius-circle;
113
+ --fk-icon-badge-radius-square;
114
+ --fk-icon-badge-bg;
115
+ --fk-icon-badge-border-color;
116
+ ```
117
+
118
+ Override tokens in your theme stylesheet:
119
+
120
+ ```scss
121
+ :root {
122
+ --fk-icon-badge-bg: #eff6ff;
123
+ }
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Behavior Notes
129
+
130
+ - `borderColor` and `backgroundColor` override the corresponding token values via inline styles.
131
+ - `ariaHidden` input lets you explicitly mark the badge as decorative even when an `ariaLabel` is present elsewhere in the UI.