@frame-kit/ui-ng 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENTS.md +0 -16
- package/fesm2022/frame-kit-ui-ng.mjs +0 -2
- package/fesm2022/frame-kit-ui-ng.mjs.map +1 -1
- package/layouts/app-shell/README.md +10 -10
- package/package.json +1 -9
- package/types/frame-kit-ui-ng.d.ts +0 -2
- package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs +0 -117
- package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs.map +0 -1
- package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs +0 -42
- package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs.map +0 -1
- package/types/frame-kit-ui-ng-ui-nav-group.d.ts +0 -67
- package/types/frame-kit-ui-ng-ui-sidenav-link.d.ts +0 -24
- package/ui/nav-group/README.md +0 -170
- package/ui/sidenav-link/README.md +0 -214
package/COMPONENTS.md
CHANGED
|
@@ -41,7 +41,6 @@ Organized by **purpose** (not Atomic Design) into six layers with strict depende
|
|
|
41
41
|
- [fk-loader](#fk-loader)
|
|
42
42
|
- [fk-menu-item](#fk-menu-item)
|
|
43
43
|
- [fk-nav-brand](#fk-nav-brand)
|
|
44
|
-
- [fk-nav-group](#fk-nav-group)
|
|
45
44
|
- [fk-nav-separator](#fk-nav-separator)
|
|
46
45
|
- [fk-node-tree](#fk-node-tree)
|
|
47
46
|
- [fk-node-tree-breadcrumb](#fk-node-tree-breadcrumb)
|
|
@@ -49,7 +48,6 @@ Organized by **purpose** (not Atomic Design) into six layers with strict depende
|
|
|
49
48
|
- [fk-numbered-list](#fk-numbered-list)
|
|
50
49
|
- [fk-pagination](#fk-pagination)
|
|
51
50
|
- [fk-progress-bar](#fk-progress-bar)
|
|
52
|
-
- [fk-sidenav-link](#fk-sidenav-link)
|
|
53
51
|
- [fk-tabs](#fk-tabs)
|
|
54
52
|
- [fk-timeline](#fk-timeline)
|
|
55
53
|
- [fk-toast](#fk-toast)
|
|
@@ -310,13 +308,6 @@ A brand/logo element used within navigation bars.
|
|
|
310
308
|
|
|
311
309
|
---
|
|
312
310
|
|
|
313
|
-
### fk-nav-group
|
|
314
|
-
|
|
315
|
-
An expandable nav group that pairs a clickable trigger row (icon + label, optionally routed) with projected child links revealed when expanded. Designed to sit inside a collapsible shell so collapsed clicks request the outer shell to open.
|
|
316
|
-
[README](https://github.com/frame-kit/packages/blob/main/packages/ui-ng/ui/nav-group/README.md)
|
|
317
|
-
|
|
318
|
-
---
|
|
319
|
-
|
|
320
311
|
### fk-nav-separator
|
|
321
312
|
|
|
322
313
|
A token-driven separator for visually dividing groups of navigation items, with vertical/horizontal orientation and decorative/semantic accessibility modes.
|
|
@@ -366,13 +357,6 @@ A token-driven progress bar for indicating how far along a single task or proces
|
|
|
366
357
|
|
|
367
358
|
---
|
|
368
359
|
|
|
369
|
-
### fk-sidenav-link
|
|
370
|
-
|
|
371
|
-
A token-driven sidebar navigation link that renders an icon and label, automatically hiding the label when the parent app-shell is collapsed.
|
|
372
|
-
[README](https://github.com/frame-kit/packages/blob/main/packages/ui-ng/ui/sidenav-link/README.md)
|
|
373
|
-
|
|
374
|
-
---
|
|
375
|
-
|
|
376
360
|
### fk-tabs
|
|
377
361
|
|
|
378
362
|
A compound component system for building accessible, keyboard-navigable tabbed interfaces. Supports underline, pill, and contained variants, controlled and uncontrolled modes, lazy rendering, closable tabs, and full WAI-ARIA Tabs pattern compliance.
|
|
@@ -34,7 +34,6 @@ export * from '@frame-kit/ui-ng/ui/list-editor';
|
|
|
34
34
|
export * from '@frame-kit/ui-ng/ui/loader';
|
|
35
35
|
export * from '@frame-kit/ui-ng/ui/menu-item';
|
|
36
36
|
export * from '@frame-kit/ui-ng/ui/nav-brand';
|
|
37
|
-
export * from '@frame-kit/ui-ng/ui/nav-group';
|
|
38
37
|
export * from '@frame-kit/ui-ng/ui/nav-separator';
|
|
39
38
|
export * from '@frame-kit/ui-ng/ui/node-tree';
|
|
40
39
|
export * from '@frame-kit/ui-ng/ui/node-tree-breadcrumb';
|
|
@@ -42,7 +41,6 @@ export * from '@frame-kit/ui-ng/ui/note';
|
|
|
42
41
|
export * from '@frame-kit/ui-ng/ui/numbered-list';
|
|
43
42
|
export * from '@frame-kit/ui-ng/ui/pagination';
|
|
44
43
|
export * from '@frame-kit/ui-ng/ui/progress-bar';
|
|
45
|
-
export * from '@frame-kit/ui-ng/ui/sidenav-link';
|
|
46
44
|
export * from '@frame-kit/ui-ng/ui/tabs';
|
|
47
45
|
export * from '@frame-kit/ui-ng/ui/timeline';
|
|
48
46
|
export * from '@frame-kit/ui-ng/ui/toast';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng.mjs","sources":["../../../../packages/ui-ng/frame-kit-ui-ng.ts"],"sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"frame-kit-ui-ng.mjs","sources":["../../../../packages/ui-ng/frame-kit-ui-ng.ts"],"sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AAEG"}
|
|
@@ -141,8 +141,8 @@ Sidebar pushes the main content over. Collapses to zero width when closed.
|
|
|
141
141
|
</div>
|
|
142
142
|
|
|
143
143
|
<nav appShellSidenav>
|
|
144
|
-
<
|
|
145
|
-
<
|
|
144
|
+
<a routerLink="/app">Overview</a>
|
|
145
|
+
<a routerLink="/properties">Properties</a>
|
|
146
146
|
</nav>
|
|
147
147
|
|
|
148
148
|
<div appShellContent>
|
|
@@ -162,7 +162,7 @@ Sidebar slides over the content with a backdrop overlay.
|
|
|
162
162
|
</div>
|
|
163
163
|
|
|
164
164
|
<nav appShellSidenav>
|
|
165
|
-
<
|
|
165
|
+
<a routerLink="/notifications">Notifications</a>
|
|
166
166
|
</nav>
|
|
167
167
|
|
|
168
168
|
<div appShellContent>
|
|
@@ -187,13 +187,13 @@ Sidebar collapses to a narrow icon rail on desktop. On mobile, it behaves as an
|
|
|
187
187
|
</div>
|
|
188
188
|
|
|
189
189
|
<nav class="sidenav-nav" style="flex: 1; overflow-y: auto;">
|
|
190
|
-
<
|
|
191
|
-
<
|
|
192
|
-
<
|
|
190
|
+
<a routerLink="/app">Overview</a>
|
|
191
|
+
<a routerLink="/properties">Properties</a>
|
|
192
|
+
<a routerLink="/notifications">Notifications</a>
|
|
193
193
|
</nav>
|
|
194
194
|
|
|
195
195
|
<div class="sidenav-footer">
|
|
196
|
-
<
|
|
196
|
+
<a routerLink="/help">Help & Support</a>
|
|
197
197
|
</div>
|
|
198
198
|
</div>
|
|
199
199
|
|
|
@@ -214,7 +214,7 @@ The end panel is opt-in and starts closed. The consumer provides their own toggl
|
|
|
214
214
|
</div>
|
|
215
215
|
|
|
216
216
|
<nav appShellSidenav>
|
|
217
|
-
<
|
|
217
|
+
<a routerLink="/app">Overview</a>
|
|
218
218
|
</nav>
|
|
219
219
|
|
|
220
220
|
<div appShellContent>
|
|
@@ -242,7 +242,7 @@ Keep the icon rail visible on mobile instead of hiding the sidebar. Tapping an i
|
|
|
242
242
|
<button (click)="shell.openSidenav()">
|
|
243
243
|
<fk-icon name="menu-outline" />
|
|
244
244
|
</button>
|
|
245
|
-
<
|
|
245
|
+
<a routerLink="/">Home</a>
|
|
246
246
|
</nav>
|
|
247
247
|
|
|
248
248
|
<div appShellContent>
|
|
@@ -321,7 +321,7 @@ Keep the icon rail visible on mobile instead of hiding the sidebar. Tapping an i
|
|
|
321
321
|
- Transitions are only enabled after explicit user interaction (toggle, open, close)
|
|
322
322
|
- `dismissSidenav()` closes the mobile overlay without persisting a closed preference — on the next desktop resize the sidebar will reappear
|
|
323
323
|
- `closeSidenav()` persists the closed preference across mobile/desktop transitions
|
|
324
|
-
- In `icon` mode, when collapsed, the aside shrinks to `collapsedWidth` and
|
|
324
|
+
- In `icon` mode, when collapsed, the aside shrinks to `collapsedWidth` and gains the `fk-app-shell--collapsed` class; sidenav content can react to it (e.g. hiding labels) via that class or the shell's `isCollapsed()` signal
|
|
325
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
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
327
|
- The end panel starts closed by default — the consumer must explicitly open it via `openEnd()` or `toggleEnd()`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frame-kit/ui-ng",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Style-agnostic, token-driven Angular UI component library for FrameKit.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -177,10 +177,6 @@
|
|
|
177
177
|
"types": "./types/frame-kit-ui-ng-ui-nav-brand.d.ts",
|
|
178
178
|
"default": "./fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs"
|
|
179
179
|
},
|
|
180
|
-
"./ui/nav-group": {
|
|
181
|
-
"types": "./types/frame-kit-ui-ng-ui-nav-group.d.ts",
|
|
182
|
-
"default": "./fesm2022/frame-kit-ui-ng-ui-nav-group.mjs"
|
|
183
|
-
},
|
|
184
180
|
"./ui/nav-separator": {
|
|
185
181
|
"types": "./types/frame-kit-ui-ng-ui-nav-separator.d.ts",
|
|
186
182
|
"default": "./fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs"
|
|
@@ -209,10 +205,6 @@
|
|
|
209
205
|
"types": "./types/frame-kit-ui-ng-ui-progress-bar.d.ts",
|
|
210
206
|
"default": "./fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs"
|
|
211
207
|
},
|
|
212
|
-
"./ui/sidenav-link": {
|
|
213
|
-
"types": "./types/frame-kit-ui-ng-ui-sidenav-link.d.ts",
|
|
214
|
-
"default": "./fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs"
|
|
215
|
-
},
|
|
216
208
|
"./ui/tabs": {
|
|
217
209
|
"types": "./types/frame-kit-ui-ng-ui-tabs.d.ts",
|
|
218
210
|
"default": "./fesm2022/frame-kit-ui-ng-ui-tabs.mjs"
|
|
@@ -34,7 +34,6 @@ export * from '@frame-kit/ui-ng/ui/list-editor';
|
|
|
34
34
|
export * from '@frame-kit/ui-ng/ui/loader';
|
|
35
35
|
export * from '@frame-kit/ui-ng/ui/menu-item';
|
|
36
36
|
export * from '@frame-kit/ui-ng/ui/nav-brand';
|
|
37
|
-
export * from '@frame-kit/ui-ng/ui/nav-group';
|
|
38
37
|
export * from '@frame-kit/ui-ng/ui/nav-separator';
|
|
39
38
|
export * from '@frame-kit/ui-ng/ui/node-tree';
|
|
40
39
|
export * from '@frame-kit/ui-ng/ui/node-tree-breadcrumb';
|
|
@@ -42,7 +41,6 @@ export * from '@frame-kit/ui-ng/ui/note';
|
|
|
42
41
|
export * from '@frame-kit/ui-ng/ui/numbered-list';
|
|
43
42
|
export * from '@frame-kit/ui-ng/ui/pagination';
|
|
44
43
|
export * from '@frame-kit/ui-ng/ui/progress-bar';
|
|
45
|
-
export * from '@frame-kit/ui-ng/ui/sidenav-link';
|
|
46
44
|
export * from '@frame-kit/ui-ng/ui/tabs';
|
|
47
45
|
export * from '@frame-kit/ui-ng/ui/timeline';
|
|
48
46
|
export * from '@frame-kit/ui-ng/ui/toast';
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, model, output, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import * as i1 from '@angular/router';
|
|
4
|
-
import { RouterModule } from '@angular/router';
|
|
5
|
-
import { SidenavLinkComponent } from '@frame-kit/ui-ng/ui/sidenav-link';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Expandable nav group — renders a trigger row (icon + label, optionally
|
|
9
|
-
* linked) and reveals projected children when `expanded` is true. Designed
|
|
10
|
-
* to sit inside a collapsible sidenav: when the outer shell is collapsed,
|
|
11
|
-
* clicking the row emits `requestOpen` so the host can pop the sidenav
|
|
12
|
-
* open, and the group auto-expands once it's visible.
|
|
13
|
-
*/
|
|
14
|
-
class NavGroupComponent {
|
|
15
|
-
// ===== INPUTS =====
|
|
16
|
-
/** Primary label text shown in the group trigger row. */
|
|
17
|
-
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
18
|
-
/** Optional icon name shown to the leading side of the label. */
|
|
19
|
-
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
20
|
-
/** Size of the leading icon. */
|
|
21
|
-
iconSize = input('sm', ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
|
|
22
|
-
/** Optional router path; when set, the trigger navigates on click in expanded sidenav mode. */
|
|
23
|
-
routerLink = input(null, ...(ngDevMode ? [{ debugName: "routerLink" }] : /* istanbul ignore next */ []));
|
|
24
|
-
/**
|
|
25
|
-
* True when the containing sidenav is in its collapsed rail state.
|
|
26
|
-
* In that mode, clicking the trigger BOTH navigates via
|
|
27
|
-
* `routerLink` AND emits `requestOpen` so the host can expand the
|
|
28
|
-
* outer shell — the user lands on the group's route with the
|
|
29
|
-
* sidenav already open. The trigger never expands its own children
|
|
30
|
-
* inside the rail (no horizontal room); the rail-to-expanded
|
|
31
|
-
* transition is what reveals them.
|
|
32
|
-
*/
|
|
33
|
-
collapsed = input(false, ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
34
|
-
/**
|
|
35
|
-
* When true and the sidenav is in its expanded state, clicking the
|
|
36
|
-
* trigger row does NOT fold the group — children stay visible.
|
|
37
|
-
* Useful when the group's children are permanent navigation rather
|
|
38
|
-
* than a collapsible disclosure (e.g. a parent nav item that should
|
|
39
|
-
* always show its sub-pages while the sidenav is open). Clicks on
|
|
40
|
-
* the trigger still navigate via `routerLink`.
|
|
41
|
-
*
|
|
42
|
-
* Has no effect in collapsed (rail) mode — clicks there still
|
|
43
|
-
* navigate via `routerLink` and emit `requestOpen`, and `expanded`
|
|
44
|
-
* stays untouched regardless of this input.
|
|
45
|
-
*/
|
|
46
|
-
lockedOpen = input(false, ...(ngDevMode ? [{ debugName: "lockedOpen" }] : /* istanbul ignore next */ []));
|
|
47
|
-
/**
|
|
48
|
-
* When true, renders a chevron at the trailing edge of the trigger row
|
|
49
|
-
* that points right while collapsed and rotates to point down while
|
|
50
|
-
* expanded. Decorative (`aria-hidden`); hidden in rail mode. Off by
|
|
51
|
-
* default so existing consumers are unaffected.
|
|
52
|
-
*/
|
|
53
|
-
showChevron = input(false, ...(ngDevMode ? [{ debugName: "showChevron" }] : /* istanbul ignore next */ []));
|
|
54
|
-
// ===== MODELS =====
|
|
55
|
-
/** Whether the group is currently expanded, showing projected child links. */
|
|
56
|
-
expanded = model(false, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
57
|
-
// ===== OUTPUTS =====
|
|
58
|
-
/**
|
|
59
|
-
* Emitted when the group is clicked while the outer sidenav is
|
|
60
|
-
* collapsed. Hosts typically listen to open their collapsible shell
|
|
61
|
-
* so the projected children become visible.
|
|
62
|
-
*/
|
|
63
|
-
requestOpen = output();
|
|
64
|
-
// ===== BASE PROPS =====
|
|
65
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
66
|
-
// ===== COMPUTED =====
|
|
67
|
-
classes = computed(() => {
|
|
68
|
-
return [
|
|
69
|
-
'fk-nav-group',
|
|
70
|
-
this.expanded() ? 'fk-nav-group--expanded' : '',
|
|
71
|
-
this.collapsed() ? 'fk-nav-group--collapsed' : '',
|
|
72
|
-
this.className(),
|
|
73
|
-
]
|
|
74
|
-
.filter(Boolean)
|
|
75
|
-
.join(' ');
|
|
76
|
-
}, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
77
|
-
get hostClass() {
|
|
78
|
-
return this.classes();
|
|
79
|
-
}
|
|
80
|
-
toggle() {
|
|
81
|
-
if (this.collapsed()) {
|
|
82
|
-
// In rail mode the children must not render inside the rail —
|
|
83
|
-
// there's no horizontal room and the visual hierarchy collapses.
|
|
84
|
-
// Just ask the host to expand the sidenav; once it does and
|
|
85
|
-
// `collapsed` flips to false, the consumer's `[expanded]`
|
|
86
|
-
// binding can push true and the children render in the now-open
|
|
87
|
-
// sidenav. We DO NOT set `expanded` here, so a click in rail
|
|
88
|
-
// mode never reveals children inside the rail itself.
|
|
89
|
-
this.requestOpen.emit();
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
// Locked-open: in expanded sidenav mode, the trigger no longer
|
|
93
|
-
// folds the group on click. Navigation via `routerLink` still
|
|
94
|
-
// fires from the inner sidenav-link; this branch just suppresses
|
|
95
|
-
// the toggle behavior so children stay visible.
|
|
96
|
-
if (this.lockedOpen()) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
this.expanded.update((v) => !v);
|
|
100
|
-
}
|
|
101
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NavGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
102
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: NavGroupComponent, isStandalone: true, selector: "fk-nav-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconSize: { classPropertyName: "iconSize", publicName: "iconSize", isSignal: true, isRequired: false, transformFunction: null }, routerLink: { classPropertyName: "routerLink", publicName: "routerLink", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, lockedOpen: { classPropertyName: "lockedOpen", publicName: "lockedOpen", isSignal: true, isRequired: false, transformFunction: null }, showChevron: { classPropertyName: "showChevron", publicName: "showChevron", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange", requestOpen: "requestOpen" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "<div class=\"fk-nav-group__row\" role=\"presentation\" (click)=\"toggle()\">\n <fk-sidenav-link\n class=\"fk-nav-group__link\"\n [icon]=\"icon() ?? ''\"\n [iconSize]=\"iconSize()\"\n [label]=\"label()\"\n [routerLink]=\"routerLink()\"\n />\n\n @if (showChevron()) {\n <span\n class=\"fk-nav-group__chevron\"\n [class.fk-nav-group__chevron--open]=\"expanded()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-nav-group__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n</div>\n\n@if (expanded()) {\n <!--\n Stop child clicks from bubbling to the fk-nav-group host. When a\n consumer binds [routerLink] on <fk-nav-group>, Angular attaches the\n RouterLink directive to the host element in addition to our input \u2014\n so an un-stopped child click would re-navigate to the parent URL\n after the child's own RouterLink fires. This is an event absorber,\n not an interactive element; keyboard activation fires click events\n that bubble through the same path, so the a11y rules don't apply.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"fk-nav-group__children\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:block}.fk-nav-group__row{display:flex;align-items:center;gap:var(--fk-nav-group-row-gap, var(--fk-rhythm-1, .25rem))}.fk-nav-group__link{flex:1;min-width:0}.fk-nav-group__chevron{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--fk-nav-group-chevron-color, var(--fk-color-muted, #64748b));transform:rotate(-90deg);transition:transform .15s ease}.fk-nav-group__chevron--open{transform:rotate(0)}.fk-nav-group__chevron-svg{display:block}:host(.fk-nav-group--collapsed) .fk-nav-group__chevron{display:none}.fk-nav-group__children{position:relative;display:flex;flex-direction:column;gap:var(--fk-nav-group-children-gap, var(--fk-rhythm-1, .25rem));padding-left:var(--fk-nav-group-children-indent, var(--fk-rhythm-6, 1.5rem));margin-top:var(--fk-nav-group-children-offset, var(--fk-rhythm-1, .25rem))}.fk-nav-group__children:before{content:\"\";position:absolute;top:0;bottom:0;left:var(--fk-nav-group-children-border-offset, var(--fk-sidenav-link-padding-inline, var(--fk-rhythm-3, .75rem)));width:var(--fk-nav-group-children-border-width, var(--fk-border-width, 1px));background:var(--fk-nav-group-children-border-color, var(--fk-color-border, #d9e2ee))}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: SidenavLinkComponent, selector: "fk-sidenav-link", inputs: ["icon", "iconSize", "label", "routerLink", "exact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
103
|
-
}
|
|
104
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NavGroupComponent, decorators: [{
|
|
105
|
-
type: Component,
|
|
106
|
-
args: [{ selector: 'fk-nav-group', standalone: true, imports: [RouterModule, SidenavLinkComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fk-nav-group__row\" role=\"presentation\" (click)=\"toggle()\">\n <fk-sidenav-link\n class=\"fk-nav-group__link\"\n [icon]=\"icon() ?? ''\"\n [iconSize]=\"iconSize()\"\n [label]=\"label()\"\n [routerLink]=\"routerLink()\"\n />\n\n @if (showChevron()) {\n <span\n class=\"fk-nav-group__chevron\"\n [class.fk-nav-group__chevron--open]=\"expanded()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-nav-group__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n</div>\n\n@if (expanded()) {\n <!--\n Stop child clicks from bubbling to the fk-nav-group host. When a\n consumer binds [routerLink] on <fk-nav-group>, Angular attaches the\n RouterLink directive to the host element in addition to our input \u2014\n so an un-stopped child click would re-navigate to the parent URL\n after the child's own RouterLink fires. This is an event absorber,\n not an interactive element; keyboard activation fires click events\n that bubble through the same path, so the a11y rules don't apply.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"fk-nav-group__children\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:block}.fk-nav-group__row{display:flex;align-items:center;gap:var(--fk-nav-group-row-gap, var(--fk-rhythm-1, .25rem))}.fk-nav-group__link{flex:1;min-width:0}.fk-nav-group__chevron{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--fk-nav-group-chevron-color, var(--fk-color-muted, #64748b));transform:rotate(-90deg);transition:transform .15s ease}.fk-nav-group__chevron--open{transform:rotate(0)}.fk-nav-group__chevron-svg{display:block}:host(.fk-nav-group--collapsed) .fk-nav-group__chevron{display:none}.fk-nav-group__children{position:relative;display:flex;flex-direction:column;gap:var(--fk-nav-group-children-gap, var(--fk-rhythm-1, .25rem));padding-left:var(--fk-nav-group-children-indent, var(--fk-rhythm-6, 1.5rem));margin-top:var(--fk-nav-group-children-offset, var(--fk-rhythm-1, .25rem))}.fk-nav-group__children:before{content:\"\";position:absolute;top:0;bottom:0;left:var(--fk-nav-group-children-border-offset, var(--fk-sidenav-link-padding-inline, var(--fk-rhythm-3, .75rem)));width:var(--fk-nav-group-children-border-width, var(--fk-border-width, 1px));background:var(--fk-nav-group-children-border-color, var(--fk-color-border, #d9e2ee))}\n"] }]
|
|
107
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], routerLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerLink", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], lockedOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockedOpen", required: false }] }], showChevron: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChevron", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], requestOpen: [{ type: i0.Output, args: ["requestOpen"] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], hostClass: [{
|
|
108
|
-
type: HostBinding,
|
|
109
|
-
args: ['class']
|
|
110
|
-
}] } });
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Generated bundle index. Do not edit.
|
|
114
|
-
*/
|
|
115
|
-
|
|
116
|
-
export { NavGroupComponent };
|
|
117
|
-
//# sourceMappingURL=frame-kit-ui-ng-ui-nav-group.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng-ui-nav-group.mjs","sources":["../../../../packages/ui-ng/ui/nav-group/nav-group.component.ts","../../../../packages/ui-ng/ui/nav-group/nav-group.component.html","../../../../packages/ui-ng/ui/nav-group/frame-kit-ui-ng-ui-nav-group.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n model,\n output,\n} from '@angular/core';\nimport { RouterModule } from '@angular/router';\n\nimport type { IconSize } from '@frame-kit/ui-ng/core/icon';\nimport { SidenavLinkComponent } from '@frame-kit/ui-ng/ui/sidenav-link';\n\n/**\n * Expandable nav group — renders a trigger row (icon + label, optionally\n * linked) and reveals projected children when `expanded` is true. Designed\n * to sit inside a collapsible sidenav: when the outer shell is collapsed,\n * clicking the row emits `requestOpen` so the host can pop the sidenav\n * open, and the group auto-expands once it's visible.\n */\n@Component({\n selector: 'fk-nav-group',\n standalone: true,\n imports: [RouterModule, SidenavLinkComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nav-group.component.html',\n styleUrl: './nav-group.component.scss',\n})\nexport class NavGroupComponent {\n // ===== INPUTS =====\n /** Primary label text shown in the group trigger row. */\n readonly label = input.required<string>();\n /** Optional icon name shown to the leading side of the label. */\n readonly icon = input<string | null>(null);\n /** Size of the leading icon. */\n readonly iconSize = input<IconSize>('sm');\n /** Optional router path; when set, the trigger navigates on click in expanded sidenav mode. */\n readonly routerLink = input<string | string[] | null>(null);\n\n /**\n * True when the containing sidenav is in its collapsed rail state.\n * In that mode, clicking the trigger BOTH navigates via\n * `routerLink` AND emits `requestOpen` so the host can expand the\n * outer shell — the user lands on the group's route with the\n * sidenav already open. The trigger never expands its own children\n * inside the rail (no horizontal room); the rail-to-expanded\n * transition is what reveals them.\n */\n readonly collapsed = input<boolean>(false);\n\n /**\n * When true and the sidenav is in its expanded state, clicking the\n * trigger row does NOT fold the group — children stay visible.\n * Useful when the group's children are permanent navigation rather\n * than a collapsible disclosure (e.g. a parent nav item that should\n * always show its sub-pages while the sidenav is open). Clicks on\n * the trigger still navigate via `routerLink`.\n *\n * Has no effect in collapsed (rail) mode — clicks there still\n * navigate via `routerLink` and emit `requestOpen`, and `expanded`\n * stays untouched regardless of this input.\n */\n readonly lockedOpen = input<boolean>(false);\n\n /**\n * When true, renders a chevron at the trailing edge of the trigger row\n * that points right while collapsed and rotates to point down while\n * expanded. Decorative (`aria-hidden`); hidden in rail mode. Off by\n * default so existing consumers are unaffected.\n */\n readonly showChevron = input<boolean>(false);\n\n // ===== MODELS =====\n /** Whether the group is currently expanded, showing projected child links. */\n readonly expanded = model<boolean>(false);\n\n // ===== OUTPUTS =====\n /**\n * Emitted when the group is clicked while the outer sidenav is\n * collapsed. Hosts typically listen to open their collapsible shell\n * so the projected children become visible.\n */\n readonly requestOpen = output<void>();\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return [\n 'fk-nav-group',\n this.expanded() ? 'fk-nav-group--expanded' : '',\n this.collapsed() ? 'fk-nav-group--collapsed' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n protected toggle(): void {\n if (this.collapsed()) {\n // In rail mode the children must not render inside the rail —\n // there's no horizontal room and the visual hierarchy collapses.\n // Just ask the host to expand the sidenav; once it does and\n // `collapsed` flips to false, the consumer's `[expanded]`\n // binding can push true and the children render in the now-open\n // sidenav. We DO NOT set `expanded` here, so a click in rail\n // mode never reveals children inside the rail itself.\n this.requestOpen.emit();\n\n return;\n }\n\n // Locked-open: in expanded sidenav mode, the trigger no longer\n // folds the group on click. Navigation via `routerLink` still\n // fires from the inner sidenav-link; this branch just suppresses\n // the toggle behavior so children stay visible.\n if (this.lockedOpen()) {\n return;\n }\n\n this.expanded.update((v) => !v);\n }\n}\n","<div class=\"fk-nav-group__row\" role=\"presentation\" (click)=\"toggle()\">\n <fk-sidenav-link\n class=\"fk-nav-group__link\"\n [icon]=\"icon() ?? ''\"\n [iconSize]=\"iconSize()\"\n [label]=\"label()\"\n [routerLink]=\"routerLink()\"\n />\n\n @if (showChevron()) {\n <span\n class=\"fk-nav-group__chevron\"\n [class.fk-nav-group__chevron--open]=\"expanded()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-nav-group__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n</div>\n\n@if (expanded()) {\n <!--\n Stop child clicks from bubbling to the fk-nav-group host. When a\n consumer binds [routerLink] on <fk-nav-group>, Angular attaches the\n RouterLink directive to the host element in addition to our input —\n so an un-stopped child click would re-navigate to the parent URL\n after the child's own RouterLink fires. This is an event absorber,\n not an interactive element; keyboard activation fires click events\n that bubble through the same path, so the a11y rules don't apply.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"fk-nav-group__children\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, inject, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import { RouterLink, RouterLinkActive } from '@angular/router';
|
|
4
|
-
import { IconComponent } from '@frame-kit/ui-ng/core/icon';
|
|
5
|
-
import { TooltipDirective } from '@frame-kit/ui-ng/directives/tooltip';
|
|
6
|
-
import { AppShellComponent } from '@frame-kit/ui-ng/layouts/app-shell';
|
|
7
|
-
|
|
8
|
-
class SidenavLinkComponent {
|
|
9
|
-
/** Optional icon name shown to the leading side of the link label. */
|
|
10
|
-
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
11
|
-
/** Size of the leading icon. */
|
|
12
|
-
iconSize = input('sm', ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
|
|
13
|
-
/** Link text displayed next to the icon and used as a tooltip when the sidenav is collapsed. */
|
|
14
|
-
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
15
|
-
/** Router path the link navigates to; when null the element renders as a non-navigable button. */
|
|
16
|
-
routerLink = input(null, ...(ngDevMode ? [{ debugName: "routerLink" }] : /* istanbul ignore next */ []));
|
|
17
|
-
/** When true, the active class is applied only on an exact route match. */
|
|
18
|
-
exact = input(false, ...(ngDevMode ? [{ debugName: "exact" }] : /* istanbul ignore next */ []));
|
|
19
|
-
shell = inject(AppShellComponent, { optional: true });
|
|
20
|
-
isCollapsed = computed(() => this.shell?.isCollapsed() ?? false, ...(ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []));
|
|
21
|
-
hostClass = 'fk-sidenav-link';
|
|
22
|
-
/** Dismisses the parent sidenav on mobile when the link is activated. */
|
|
23
|
-
dismiss() {
|
|
24
|
-
this.shell?.dismissSidenav();
|
|
25
|
-
}
|
|
26
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SidenavLinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
27
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SidenavLinkComponent, isStandalone: true, selector: "fk-sidenav-link", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconSize: { classPropertyName: "iconSize", publicName: "iconSize", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, routerLink: { classPropertyName: "routerLink", publicName: "routerLink", isSignal: true, isRequired: false, transformFunction: null }, exact: { classPropertyName: "exact", publicName: "exact", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "@if (routerLink()) {\n <a\n class=\"fk-sidenav-link__anchor\"\n [routerLink]=\"routerLink()\"\n routerLinkActive=\"fk-sidenav-link__anchor--active\"\n [routerLinkActiveOptions]=\"{ exact: exact() }\"\n [attr.aria-label]=\"isCollapsed() ? label() : null\"\n [fkTooltip]=\"label()\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"dismiss()\"\n >\n @if (icon()) {\n <fk-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (!isCollapsed()) {\n <span class=\"fk-sidenav-link__label\">{{ label() }}</span>\n }\n </a>\n} @else {\n <button\n class=\"fk-sidenav-link__anchor\"\n type=\"button\"\n [attr.aria-label]=\"isCollapsed() ? label() : null\"\n [fkTooltip]=\"label()\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"dismiss()\"\n >\n @if (icon()) {\n <fk-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (!isCollapsed()) {\n <span class=\"fk-sidenav-link__label\">{{ label() }}</span>\n }\n </button>\n}\n", styles: [".fk-sidenav-link{display:block}.fk-sidenav-link__anchor{display:flex;align-items:center;gap:var(--fk-sidenav-link-gap, var(--fk-rhythm-2, .5rem));width:100%;padding:var(--fk-sidenav-link-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidenav-link-padding-inline, var(--fk-rhythm-3, .75rem));border:none;border-radius:var(--fk-sidenav-link-radius, var(--fk-radius-md, .5rem));background:var(--fk-sidenav-link-bg, transparent);font-family:var(--fk-sidenav-link-font-family, var(--fk-font-family-base));font-size:var(--fk-sidenav-link-font-size, .9375rem);color:var(--fk-sidenav-link-color, var(--fk-color-text, #1f2d3d));text-align:left;text-decoration:none;white-space:nowrap;overflow:hidden;cursor:pointer;transition:background-color .15s ease}.fk-sidenav-link__anchor:hover{background-color:var(--fk-sidenav-link-bg-hover, var(--fk-color-surface-muted, #f7f9fb));color:var(--fk-sidenav-link-color-hover, var(--fk-color-primary, #0a84ff))}.fk-sidenav-link__anchor:focus-visible{outline:none;box-shadow:var(--fk-sidenav-link-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-sidenav-link__anchor--active,.fk-sidenav-link__anchor--active:hover{font-weight:var(--fk-sidenav-link-font-weight-active, var(--fk-font-weight-semibold, 600));color:var(--fk-sidenav-link-color-active, var(--fk-color-primary, #0a84ff));background-color:var(--fk-sidenav-link-bg-active, var(--fk-color-surface-muted, #f7f9fb))}.fk-app-shell--collapsed .fk-sidenav-link__anchor{justify-content:center;padding:var(--fk-sidenav-link-collapsed-padding, var(--fk-rhythm-2, .5rem))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: IconComponent, selector: "fk-icon", inputs: ["name", "size", "color", "className", "id", "ariaLabel", "ariaHidden"] }, { kind: "directive", type: TooltipDirective, selector: "[fkTooltip]", inputs: ["fkTooltip", "fkTooltipPosition", "fkTooltipOffset", "fkTooltipShowDelay", "fkTooltipHideDelay", "fkTooltipDisabled", "fkTooltipClassName"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
28
|
-
}
|
|
29
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SidenavLinkComponent, decorators: [{
|
|
30
|
-
type: Component,
|
|
31
|
-
args: [{ selector: 'fk-sidenav-link', standalone: true, imports: [RouterLink, RouterLinkActive, IconComponent, TooltipDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (routerLink()) {\n <a\n class=\"fk-sidenav-link__anchor\"\n [routerLink]=\"routerLink()\"\n routerLinkActive=\"fk-sidenav-link__anchor--active\"\n [routerLinkActiveOptions]=\"{ exact: exact() }\"\n [attr.aria-label]=\"isCollapsed() ? label() : null\"\n [fkTooltip]=\"label()\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"dismiss()\"\n >\n @if (icon()) {\n <fk-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (!isCollapsed()) {\n <span class=\"fk-sidenav-link__label\">{{ label() }}</span>\n }\n </a>\n} @else {\n <button\n class=\"fk-sidenav-link__anchor\"\n type=\"button\"\n [attr.aria-label]=\"isCollapsed() ? label() : null\"\n [fkTooltip]=\"label()\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"dismiss()\"\n >\n @if (icon()) {\n <fk-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (!isCollapsed()) {\n <span class=\"fk-sidenav-link__label\">{{ label() }}</span>\n }\n </button>\n}\n", styles: [".fk-sidenav-link{display:block}.fk-sidenav-link__anchor{display:flex;align-items:center;gap:var(--fk-sidenav-link-gap, var(--fk-rhythm-2, .5rem));width:100%;padding:var(--fk-sidenav-link-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidenav-link-padding-inline, var(--fk-rhythm-3, .75rem));border:none;border-radius:var(--fk-sidenav-link-radius, var(--fk-radius-md, .5rem));background:var(--fk-sidenav-link-bg, transparent);font-family:var(--fk-sidenav-link-font-family, var(--fk-font-family-base));font-size:var(--fk-sidenav-link-font-size, .9375rem);color:var(--fk-sidenav-link-color, var(--fk-color-text, #1f2d3d));text-align:left;text-decoration:none;white-space:nowrap;overflow:hidden;cursor:pointer;transition:background-color .15s ease}.fk-sidenav-link__anchor:hover{background-color:var(--fk-sidenav-link-bg-hover, var(--fk-color-surface-muted, #f7f9fb));color:var(--fk-sidenav-link-color-hover, var(--fk-color-primary, #0a84ff))}.fk-sidenav-link__anchor:focus-visible{outline:none;box-shadow:var(--fk-sidenav-link-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-sidenav-link__anchor--active,.fk-sidenav-link__anchor--active:hover{font-weight:var(--fk-sidenav-link-font-weight-active, var(--fk-font-weight-semibold, 600));color:var(--fk-sidenav-link-color-active, var(--fk-color-primary, #0a84ff));background-color:var(--fk-sidenav-link-bg-active, var(--fk-color-surface-muted, #f7f9fb))}.fk-app-shell--collapsed .fk-sidenav-link__anchor{justify-content:center;padding:var(--fk-sidenav-link-collapsed-padding, var(--fk-rhythm-2, .5rem))}\n"] }]
|
|
32
|
-
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], routerLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerLink", required: false }] }], exact: [{ type: i0.Input, args: [{ isSignal: true, alias: "exact", required: false }] }], hostClass: [{
|
|
33
|
-
type: HostBinding,
|
|
34
|
-
args: ['class']
|
|
35
|
-
}] } });
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Generated bundle index. Do not edit.
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
export { SidenavLinkComponent };
|
|
42
|
-
//# sourceMappingURL=frame-kit-ui-ng-ui-sidenav-link.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng-ui-sidenav-link.mjs","sources":["../../../../packages/ui-ng/ui/sidenav-link/sidenav-link.component.ts","../../../../packages/ui-ng/ui/sidenav-link/sidenav-link.component.html","../../../../packages/ui-ng/ui/sidenav-link/frame-kit-ui-ng-ui-sidenav-link.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n inject,\n input,\n} from '@angular/core';\nimport { RouterLink, RouterLinkActive } from '@angular/router';\n\nimport { IconComponent } from '@frame-kit/ui-ng/core/icon';\nimport type { IconSize } from '@frame-kit/ui-ng/core/icon';\nimport { TooltipDirective } from '@frame-kit/ui-ng/directives/tooltip';\nimport { AppShellComponent } from '@frame-kit/ui-ng/layouts/app-shell';\n\n@Component({\n selector: 'fk-sidenav-link',\n standalone: true,\n imports: [RouterLink, RouterLinkActive, IconComponent, TooltipDirective],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './sidenav-link.component.html',\n styleUrl: './sidenav-link.component.scss',\n})\nexport class SidenavLinkComponent {\n /** Optional icon name shown to the leading side of the link label. */\n readonly icon = input<string | null>(null);\n /** Size of the leading icon. */\n readonly iconSize = input<IconSize>('sm');\n /** Link text displayed next to the icon and used as a tooltip when the sidenav is collapsed. */\n readonly label = input.required<string>();\n /** Router path the link navigates to; when null the element renders as a non-navigable button. */\n readonly routerLink = input<string | string[] | null>(null);\n /** When true, the active class is applied only on an exact route match. */\n readonly exact = input<boolean>(false);\n\n private readonly shell = inject(AppShellComponent, { optional: true });\n\n readonly isCollapsed = computed(() => this.shell?.isCollapsed() ?? false);\n\n @HostBinding('class')\n readonly hostClass = 'fk-sidenav-link';\n\n /** Dismisses the parent sidenav on mobile when the link is activated. */\n dismiss(): void {\n this.shell?.dismissSidenav();\n }\n}\n","@if (routerLink()) {\n <a\n class=\"fk-sidenav-link__anchor\"\n [routerLink]=\"routerLink()\"\n routerLinkActive=\"fk-sidenav-link__anchor--active\"\n [routerLinkActiveOptions]=\"{ exact: exact() }\"\n [attr.aria-label]=\"isCollapsed() ? label() : null\"\n [fkTooltip]=\"label()\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"dismiss()\"\n >\n @if (icon()) {\n <fk-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (!isCollapsed()) {\n <span class=\"fk-sidenav-link__label\">{{ label() }}</span>\n }\n </a>\n} @else {\n <button\n class=\"fk-sidenav-link__anchor\"\n type=\"button\"\n [attr.aria-label]=\"isCollapsed() ? label() : null\"\n [fkTooltip]=\"label()\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"dismiss()\"\n >\n @if (icon()) {\n <fk-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (!isCollapsed()) {\n <span class=\"fk-sidenav-link__label\">{{ label() }}</span>\n }\n </button>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { IconSize } from '@frame-kit/ui-ng/core/icon';
|
|
3
|
-
export { IconSize as NavGroupIconSize } from '@frame-kit/ui-ng/core/icon';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Expandable nav group — renders a trigger row (icon + label, optionally
|
|
7
|
-
* linked) and reveals projected children when `expanded` is true. Designed
|
|
8
|
-
* to sit inside a collapsible sidenav: when the outer shell is collapsed,
|
|
9
|
-
* clicking the row emits `requestOpen` so the host can pop the sidenav
|
|
10
|
-
* open, and the group auto-expands once it's visible.
|
|
11
|
-
*/
|
|
12
|
-
declare class NavGroupComponent {
|
|
13
|
-
/** Primary label text shown in the group trigger row. */
|
|
14
|
-
readonly label: _angular_core.InputSignal<string>;
|
|
15
|
-
/** Optional icon name shown to the leading side of the label. */
|
|
16
|
-
readonly icon: _angular_core.InputSignal<string | null>;
|
|
17
|
-
/** Size of the leading icon. */
|
|
18
|
-
readonly iconSize: _angular_core.InputSignal<IconSize>;
|
|
19
|
-
/** Optional router path; when set, the trigger navigates on click in expanded sidenav mode. */
|
|
20
|
-
readonly routerLink: _angular_core.InputSignal<string | string[] | null>;
|
|
21
|
-
/**
|
|
22
|
-
* True when the containing sidenav is in its collapsed rail state.
|
|
23
|
-
* In that mode, clicking the trigger BOTH navigates via
|
|
24
|
-
* `routerLink` AND emits `requestOpen` so the host can expand the
|
|
25
|
-
* outer shell — the user lands on the group's route with the
|
|
26
|
-
* sidenav already open. The trigger never expands its own children
|
|
27
|
-
* inside the rail (no horizontal room); the rail-to-expanded
|
|
28
|
-
* transition is what reveals them.
|
|
29
|
-
*/
|
|
30
|
-
readonly collapsed: _angular_core.InputSignal<boolean>;
|
|
31
|
-
/**
|
|
32
|
-
* When true and the sidenav is in its expanded state, clicking the
|
|
33
|
-
* trigger row does NOT fold the group — children stay visible.
|
|
34
|
-
* Useful when the group's children are permanent navigation rather
|
|
35
|
-
* than a collapsible disclosure (e.g. a parent nav item that should
|
|
36
|
-
* always show its sub-pages while the sidenav is open). Clicks on
|
|
37
|
-
* the trigger still navigate via `routerLink`.
|
|
38
|
-
*
|
|
39
|
-
* Has no effect in collapsed (rail) mode — clicks there still
|
|
40
|
-
* navigate via `routerLink` and emit `requestOpen`, and `expanded`
|
|
41
|
-
* stays untouched regardless of this input.
|
|
42
|
-
*/
|
|
43
|
-
readonly lockedOpen: _angular_core.InputSignal<boolean>;
|
|
44
|
-
/**
|
|
45
|
-
* When true, renders a chevron at the trailing edge of the trigger row
|
|
46
|
-
* that points right while collapsed and rotates to point down while
|
|
47
|
-
* expanded. Decorative (`aria-hidden`); hidden in rail mode. Off by
|
|
48
|
-
* default so existing consumers are unaffected.
|
|
49
|
-
*/
|
|
50
|
-
readonly showChevron: _angular_core.InputSignal<boolean>;
|
|
51
|
-
/** Whether the group is currently expanded, showing projected child links. */
|
|
52
|
-
readonly expanded: _angular_core.ModelSignal<boolean>;
|
|
53
|
-
/**
|
|
54
|
-
* Emitted when the group is clicked while the outer sidenav is
|
|
55
|
-
* collapsed. Hosts typically listen to open their collapsible shell
|
|
56
|
-
* so the projected children become visible.
|
|
57
|
-
*/
|
|
58
|
-
readonly requestOpen: _angular_core.OutputEmitterRef<void>;
|
|
59
|
-
readonly className: _angular_core.InputSignal<string>;
|
|
60
|
-
readonly classes: _angular_core.Signal<string>;
|
|
61
|
-
get hostClass(): string;
|
|
62
|
-
protected toggle(): void;
|
|
63
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NavGroupComponent, never>;
|
|
64
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<NavGroupComponent, "fk-nav-group", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "iconSize": { "alias": "iconSize"; "required": false; "isSignal": true; }; "routerLink": { "alias": "routerLink"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; "lockedOpen": { "alias": "lockedOpen"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; "expanded": { "alias": "expanded"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; }, { "expanded": "expandedChange"; "requestOpen": "requestOpen"; }, never, ["*"], true, never>;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export { NavGroupComponent };
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { IconSize } from '@frame-kit/ui-ng/core/icon';
|
|
3
|
-
|
|
4
|
-
declare class SidenavLinkComponent {
|
|
5
|
-
/** Optional icon name shown to the leading side of the link label. */
|
|
6
|
-
readonly icon: _angular_core.InputSignal<string | null>;
|
|
7
|
-
/** Size of the leading icon. */
|
|
8
|
-
readonly iconSize: _angular_core.InputSignal<IconSize>;
|
|
9
|
-
/** Link text displayed next to the icon and used as a tooltip when the sidenav is collapsed. */
|
|
10
|
-
readonly label: _angular_core.InputSignal<string>;
|
|
11
|
-
/** Router path the link navigates to; when null the element renders as a non-navigable button. */
|
|
12
|
-
readonly routerLink: _angular_core.InputSignal<string | string[] | null>;
|
|
13
|
-
/** When true, the active class is applied only on an exact route match. */
|
|
14
|
-
readonly exact: _angular_core.InputSignal<boolean>;
|
|
15
|
-
private readonly shell;
|
|
16
|
-
readonly isCollapsed: _angular_core.Signal<boolean>;
|
|
17
|
-
readonly hostClass = "fk-sidenav-link";
|
|
18
|
-
/** Dismisses the parent sidenav on mobile when the link is activated. */
|
|
19
|
-
dismiss(): void;
|
|
20
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SidenavLinkComponent, never>;
|
|
21
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SidenavLinkComponent, "fk-sidenav-link", never, { "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "iconSize": { "alias": "iconSize"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": true; "isSignal": true; }; "routerLink": { "alias": "routerLink"; "required": false; "isSignal": true; }; "exact": { "alias": "exact"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export { SidenavLinkComponent };
|
package/ui/nav-group/README.md
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
# fk-nav-group
|
|
2
|
-
|
|
3
|
-
An expandable sidenav group — renders a clickable trigger row (icon + label, optionally routed) and reveals projected child nav items when expanded. Designed to sit inside a collapsible shell so that clicks on a collapsed rail pop the shell open and auto-expand the group.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## API
|
|
8
|
-
|
|
9
|
-
### Inputs
|
|
10
|
-
|
|
11
|
-
| Input | Type | Default | Description |
|
|
12
|
-
| ------------ | ---------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
-
| `label` | `string` | — | **Required.** Text rendered on the trigger row. |
|
|
14
|
-
| `icon` | `string \| null` | `null` | Icon name rendered before the label. |
|
|
15
|
-
| `iconSize` | `IconSize` | `"sm"` | Size passed through to the trigger's `fk-sidenav-link`. |
|
|
16
|
-
| `routerLink` | `string \| string[] \| null` | `null` | Destination for the trigger's anchor. Active in both expanded and collapsed states. |
|
|
17
|
-
| `collapsed` | `boolean` | `false` | Set this to `true` when the outer sidenav is in its collapsed rail state — clicks then both navigate AND emit `requestOpen`. |
|
|
18
|
-
| `lockedOpen` | `boolean` | `false` | When `true`, clicking an expanded group's trigger no longer folds it — children stay visible (navigation via `routerLink` still fires). No effect in collapsed rail mode. |
|
|
19
|
-
| `showChevron`| `boolean` | `false` | Renders a trailing disclosure chevron that points right while collapsed and rotates to point down while expanded. Decorative; hidden in rail mode. |
|
|
20
|
-
| `className` | `string` | `''` | Additional CSS classes merged onto the host element. |
|
|
21
|
-
|
|
22
|
-
### Models
|
|
23
|
-
|
|
24
|
-
| Model | Type | Default | Description |
|
|
25
|
-
| ---------- | --------- | ------- | --------------------------------------------------------------------------- |
|
|
26
|
-
| `expanded` | `boolean` | `false` | Two-way bound expansion state. Flipped by the built-in toggle on row click. |
|
|
27
|
-
|
|
28
|
-
### Outputs
|
|
29
|
-
|
|
30
|
-
| Output | Type | Description |
|
|
31
|
-
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
32
|
-
| `requestOpen` | `void` | Emitted only when the trigger is clicked while `collapsed` is `true`. Hosts typically listen to open their collapsible outer shell. The trigger also navigates via `routerLink` on the same click, so the user lands on the group's route with the shell already opening. |
|
|
33
|
-
|
|
34
|
-
### Content
|
|
35
|
-
|
|
36
|
-
`fk-nav-group` projects its child nav items into the expanded body:
|
|
37
|
-
|
|
38
|
-
```html
|
|
39
|
-
<fk-nav-group label="Integrations" icon="integrations">
|
|
40
|
-
<fk-sidenav-link icon="integrations" label="API Keys" routerLink="/integrations/api-keys" />
|
|
41
|
-
<fk-sidenav-link icon="integrations" label="Webhooks" routerLink="/integrations/webhooks" />
|
|
42
|
-
</fk-nav-group>
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Features
|
|
48
|
-
|
|
49
|
-
- Click-to-toggle expansion with two-way `expanded` model (suppressed by `lockedOpen`)
|
|
50
|
-
- Router integration via `routerLink` — navigates in both expanded and collapsed states
|
|
51
|
-
- `requestOpen` output bridges to a collapsible outer shell (`fk-app-shell` and friends) — fires alongside navigation when clicked in rail mode
|
|
52
|
-
- Content projection for arbitrary child rows — `fk-sidenav-link`, section titles, custom markers
|
|
53
|
-
- Token-driven spacing (`--fk-nav-group-row-gap`, `--fk-nav-group-children-gap`, `--fk-nav-group-children-indent`, `--fk-nav-group-children-offset`)
|
|
54
|
-
- Section rule — a vertical line brackets the expanded children, flush-left under the icon/label, tokenized via `--fk-nav-group-children-border-{width,color,offset}` (removable)
|
|
55
|
-
- Optional disclosure chevron (`showChevron`) — points right collapsed, rotates down when expanded; colour via `--fk-nav-group-chevron-color`
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## Quick Start
|
|
60
|
-
|
|
61
|
-
```html
|
|
62
|
-
<fk-nav-group label="Integrations" icon="integrations" iconSize="md" [routerLink]="['/integrations']" [collapsed]="sidenavCollapsed()" [(expanded)]="integrationsExpanded" (requestOpen)="openSidenav()">
|
|
63
|
-
<fk-sidenav-link icon="integrations" label="API Keys" [routerLink]="['/integrations/api-keys']" />
|
|
64
|
-
<fk-sidenav-link icon="integrations" label="Applications" [routerLink]="['/integrations/applications']" />
|
|
65
|
-
</fk-nav-group>
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## Import
|
|
71
|
-
|
|
72
|
-
```ts
|
|
73
|
-
import { NavGroupComponent } from '@frame-kit/ui-ng';
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
```ts
|
|
77
|
-
@Component({
|
|
78
|
-
selector: 'app-example',
|
|
79
|
-
imports: [NavGroupComponent],
|
|
80
|
-
templateUrl: './example.component.html',
|
|
81
|
-
})
|
|
82
|
-
export class ExampleComponent {}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## Selector
|
|
88
|
-
|
|
89
|
-
```html
|
|
90
|
-
<fk-nav-group></fk-nav-group>
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## Examples
|
|
96
|
-
|
|
97
|
-
### Flat list with auto-expansion
|
|
98
|
-
|
|
99
|
-
```html
|
|
100
|
-
<fk-nav-group label="Core Concepts" icon="book-outline" [(expanded)]="expanded">
|
|
101
|
-
<fk-sidenav-link icon="book-outline" label="Authentication" routerLink="/docs/authentication" />
|
|
102
|
-
<fk-sidenav-link icon="book-outline" label="Roles" routerLink="/docs/roles" />
|
|
103
|
-
<fk-sidenav-link icon="book-outline" label="Permissions" routerLink="/docs/permissions" />
|
|
104
|
-
</fk-nav-group>
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Inside a collapsible sidenav
|
|
108
|
-
|
|
109
|
-
```html
|
|
110
|
-
<fk-nav-group label="Docs" icon="book-outline" [collapsed]="shellCollapsed()" [(expanded)]="docsExpanded" (requestOpen)="shellCollapsed.set(false)">
|
|
111
|
-
<fk-sidenav-link label="Getting started" routerLink="/docs" />
|
|
112
|
-
</fk-nav-group>
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## Accessibility
|
|
118
|
-
|
|
119
|
-
- Trigger row is a `role="presentation"` wrapper containing a keyboard-navigable `fk-sidenav-link` — the sidenav-link handles focus and keyboard activation
|
|
120
|
-
- Expansion state is reflected through the host class `fk-nav-group--expanded`; consumers can add further ARIA attributes via `className` if needed
|
|
121
|
-
- Keyboard activation (Enter on the focused trigger) follows the same path as a mouse click — navigates via `routerLink` and, when `collapsed` is `true`, also emits `requestOpen` so screen-reader users land on the destination with the rail expanding behind them
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## Design Tokens
|
|
126
|
-
|
|
127
|
-
```scss
|
|
128
|
-
--fk-nav-group-row-gap;
|
|
129
|
-
--fk-nav-group-children-gap;
|
|
130
|
-
--fk-nav-group-children-indent;
|
|
131
|
-
--fk-nav-group-children-offset;
|
|
132
|
-
--fk-nav-group-children-border-width; // section rule width (default --fk-border-width / 1px)
|
|
133
|
-
--fk-nav-group-children-border-color; // section rule colour (default --fk-color-border)
|
|
134
|
-
--fk-nav-group-children-border-offset; // section rule x-position (see below)
|
|
135
|
-
--fk-nav-group-chevron-color; // disclosure chevron colour (default --fk-color-muted)
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
The expanded children column carries a quiet vertical **section rule** by
|
|
139
|
-
default — a line that brackets the nested items, aligned flush-left with the
|
|
140
|
-
trigger row's content-left edge (the icon when present, the label text
|
|
141
|
-
otherwise — both start at the link's inline padding, so a single offset
|
|
142
|
-
covers both, independent of icon size). The colour defaults to the semantic
|
|
143
|
-
`--fk-color-border`, so the rule adapts to dark mode through the fallback
|
|
144
|
-
chain with no dedicated dark token.
|
|
145
|
-
|
|
146
|
-
Override `--fk-nav-group-children-border-offset` to pin the line elsewhere, or
|
|
147
|
-
remove the rule by zeroing the width / making the colour transparent.
|
|
148
|
-
|
|
149
|
-
Override in your app stylesheet:
|
|
150
|
-
|
|
151
|
-
```scss
|
|
152
|
-
:root {
|
|
153
|
-
--fk-nav-group-children-indent: 1rem;
|
|
154
|
-
--fk-nav-group-children-gap: var(--fk-rhythm-2);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Remove the section rule for a particular scope:
|
|
158
|
-
.flat-nav {
|
|
159
|
-
--fk-nav-group-children-border-width: 0;
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## Behavior Notes
|
|
166
|
-
|
|
167
|
-
- The built-in `toggle()` decides what happens to `expanded` on click: in rail mode it leaves `expanded` alone and only emits `requestOpen` (children must not render inside the rail); in expanded mode it flips `expanded` unless `lockedOpen` is `true`. Navigation via `routerLink` happens independently on the inner sidenav-link's anchor in both states. If you want custom behavior, listen to `(requestOpen)` and drive `[(expanded)]` yourself.
|
|
168
|
-
- The trigger row composes `fk-sidenav-link` — you get the same active-route styling and keyboard semantics for free.
|
|
169
|
-
- The section rule is an absolutely-positioned `::before` on the children column (not a `border-left`), so its x-position can anchor to the icon or text. It spans the full height of the children and sits behind them; child rows render normally on top. It only shows while the group is expanded (the children column isn't rendered otherwise).
|
|
170
|
-
- No opinionated max-width — the trigger fills the row. Cap the width at the consumer level if you need it (e.g., docs shells clamp their top-level items to 18rem).
|
|
@@ -1,214 +0,0 @@
|
|
|
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
|