@rcarls/rc-navigation-bar 0.4.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/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # `@rcarls/rc-navigation-bar`
2
+
3
+ Bottom navigation layout that styles consumer-authored links.
4
+
5
+ Docs: [https://richardcarls.github.io/rc-webcomponents/components/rc-navigation-bar](https://richardcarls.github.io/rc-webcomponents/components/rc-navigation-bar).
6
+
7
+ Use this for compact PWA navigation where native links should keep working before custom element
8
+ upgrade and remain compatible with framework routers.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @rcarls/rc-navigation-bar
14
+ ```
15
+
16
+ ## Import
17
+
18
+ ```js
19
+ import '@rcarls/rc-navigation-bar/define';
20
+ ```
21
+
22
+ ## Basic usage
23
+
24
+ ```html
25
+ <nav aria-label="Main navigation">
26
+ <rc-navigation-bar>
27
+ <a href="/recipes" aria-current="page">
28
+ <span data-rc-navigation-icon aria-hidden="true">R</span>
29
+ <span>Recipes</span>
30
+ </a>
31
+ <a href="/settings">
32
+ <span data-rc-navigation-icon aria-hidden="true">S</span>
33
+ <span>Settings</span>
34
+ </a>
35
+ </rc-navigation-bar>
36
+ </nav>
37
+ ```
38
+
39
+ The consumer-authored `<nav>` provides the navigation landmark and accessible
40
+ label. `rc-navigation-bar` deliberately provides no landmark semantics. The
41
+ component reads `aria-current` from the native links; use `active-selector`
42
+ when a router exposes active state through classes instead.
43
+
44
+ ## Adaptive usage
45
+
46
+ Render this component from app layout code for windows narrower than 600 CSS pixels. At 600 CSS
47
+ pixels, switch the same destination data to `rc-navigation-rail`; at 840 CSS pixels, the app may
48
+ allow and persist rail expansion. Keep that breakpoint
49
+ policy outside the component so route matching, view transitions, and page
50
+ layout stay coordinated.
51
+
52
+ ## API
53
+
54
+ | Property | Attribute | Type | Default | Description |
55
+ | --- | --- | --- | --- | --- |
56
+ | `activeSelector` | `active-selector` | `string` | `a[aria-current]:not([aria-current="false"])` | Selector used to find the active link. |
57
+ | `indicatorTarget` | `indicator-target` | `string` | `[data-rc-navigation-indicator], [data-rc-navigation-icon]` | Selector inside the active link used for indicator geometry. |
58
+
59
+ | Part | Description |
60
+ | --- | --- |
61
+ | `nav` | Navigation layout container. |
62
+ | `indicator` | Active item indicator. |
@@ -0,0 +1,277 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "readme": "",
4
+ "modules": [
5
+ {
6
+ "kind": "javascript-module",
7
+ "path": "src/define.ts",
8
+ "declarations": [],
9
+ "exports": [
10
+ {
11
+ "kind": "custom-element-definition",
12
+ "name": "rc-navigation-bar",
13
+ "declaration": {
14
+ "name": "RCNavigationBar",
15
+ "module": "/src/index.js"
16
+ }
17
+ },
18
+ {
19
+ "kind": "js",
20
+ "name": "*",
21
+ "declaration": {
22
+ "name": "*",
23
+ "module": "src/index.js"
24
+ }
25
+ }
26
+ ]
27
+ },
28
+ {
29
+ "kind": "javascript-module",
30
+ "path": "src/index.ts",
31
+ "declarations": [],
32
+ "exports": [
33
+ {
34
+ "kind": "js",
35
+ "name": "*",
36
+ "declaration": {
37
+ "name": "*",
38
+ "module": "src/rc-navigation-bar"
39
+ }
40
+ }
41
+ ]
42
+ },
43
+ {
44
+ "kind": "javascript-module",
45
+ "path": "src/rc-navigation-bar.ts",
46
+ "declarations": [
47
+ {
48
+ "kind": "class",
49
+ "description": "Bottom navigation layout that styles consumer-authored links.\n\n`rc-navigation-bar` preserves native `<a>` elements in light DOM for router\ninterop and progressive enhancement. Mark the current link with\n`aria-current=\"page\"` or provide `active-selector` for router active classes.\nWrap the component in a consumer-authored `<nav>` when it represents a\nnavigation landmark.",
50
+ "name": "RCNavigationBar",
51
+ "cssProperties": [
52
+ {
53
+ "description": "Navigation surface background.",
54
+ "name": "--rc-navigation-bar-bg",
55
+ "default": "Canvas"
56
+ },
57
+ {
58
+ "description": "Navigation text color.",
59
+ "name": "--rc-navigation-bar-color",
60
+ "default": "CanvasText"
61
+ },
62
+ {
63
+ "description": "Minimum block size for the bar.",
64
+ "name": "--rc-navigation-bar-block-size",
65
+ "default": "4rem"
66
+ },
67
+ {
68
+ "description": "Bar block-axis padding.",
69
+ "name": "--rc-navigation-bar-padding-block",
70
+ "default": "0"
71
+ },
72
+ {
73
+ "description": "Bar inline-axis padding.",
74
+ "name": "--rc-navigation-bar-padding-inline",
75
+ "default": "0"
76
+ },
77
+ {
78
+ "description": "Gap between slotted items.",
79
+ "name": "--rc-navigation-bar-gap",
80
+ "default": "0"
81
+ },
82
+ {
83
+ "description": "Gap between item icon and label.",
84
+ "name": "--rc-navigation-bar-item-gap",
85
+ "default": "0.25rem"
86
+ },
87
+ {
88
+ "description": "Minimum item block size.",
89
+ "name": "--rc-navigation-bar-item-min-block-size",
90
+ "default": "3rem"
91
+ },
92
+ {
93
+ "description": "Item block-axis padding.",
94
+ "name": "--rc-navigation-bar-item-padding-block",
95
+ "default": "0.5rem"
96
+ },
97
+ {
98
+ "description": "Item inline-axis padding.",
99
+ "name": "--rc-navigation-bar-item-padding-inline",
100
+ "default": "0.75rem"
101
+ },
102
+ {
103
+ "description": "Resting item text color.",
104
+ "name": "--rc-navigation-bar-item-color",
105
+ "default": "inherit"
106
+ },
107
+ {
108
+ "description": "Slotted link text decoration (defers to native anchor text-decoration when unset).",
109
+ "name": "--rc-navigation-bar-item-text-decoration"
110
+ },
111
+ {
112
+ "description": "Active item text color. Falls back to `--rc-navigation-bar-item-color`, then `inherit`.",
113
+ "name": "--rc-navigation-bar-active-color"
114
+ },
115
+ {
116
+ "description": "Active indicator background.",
117
+ "name": "--rc-navigation-bar-indicator-bg",
118
+ "default": "transparent"
119
+ },
120
+ {
121
+ "description": "Active indicator border.",
122
+ "name": "--rc-navigation-bar-indicator-border",
123
+ "default": "1px solid Highlight"
124
+ },
125
+ {
126
+ "description": "Active indicator corner radius.",
127
+ "name": "--rc-navigation-bar-indicator-radius",
128
+ "default": "0"
129
+ },
130
+ {
131
+ "description": "Active indicator transition duration.",
132
+ "name": "--rc-navigation-bar-indicator-duration",
133
+ "default": "0ms"
134
+ },
135
+ {
136
+ "description": "Active indicator transition easing.",
137
+ "name": "--rc-navigation-bar-indicator-easing",
138
+ "default": "ease"
139
+ },
140
+ {
141
+ "description": "Slotted link focus outline (defers to native outline when unset).",
142
+ "name": "--rc-navigation-bar-focus-ring"
143
+ },
144
+ {
145
+ "description": "Slotted link outline offset.",
146
+ "name": "--rc-navigation-bar-focus-ring-offset",
147
+ "default": "2px"
148
+ }
149
+ ],
150
+ "cssParts": [
151
+ {
152
+ "description": "The navigation layout container.",
153
+ "name": "nav"
154
+ },
155
+ {
156
+ "description": "The active item indicator.",
157
+ "name": "indicator"
158
+ }
159
+ ],
160
+ "slots": [
161
+ {
162
+ "description": "Navigation links. Direct `<a>` children are recommended.",
163
+ "name": "default"
164
+ }
165
+ ],
166
+ "members": [
167
+ {
168
+ "kind": "field",
169
+ "name": "activeSelector",
170
+ "type": {
171
+ "text": "string"
172
+ },
173
+ "default": "'a[aria-current]:not([aria-current=\"false\"])'",
174
+ "description": "Selector used to find the active link. Defaults to `aria-current`.",
175
+ "attribute": "active-selector"
176
+ },
177
+ {
178
+ "kind": "field",
179
+ "name": "indicatorTarget",
180
+ "type": {
181
+ "text": "string"
182
+ },
183
+ "default": "'[data-rc-navigation-indicator], [data-rc-navigation-icon]'",
184
+ "description": "Selector inside the active link used for indicator geometry.",
185
+ "attribute": "indicator-target"
186
+ },
187
+ {
188
+ "kind": "field",
189
+ "name": "_$slot",
190
+ "type": {
191
+ "text": "HTMLSlotElement"
192
+ },
193
+ "privacy": "private"
194
+ },
195
+ {
196
+ "kind": "field",
197
+ "name": "_$nav",
198
+ "type": {
199
+ "text": "HTMLElement"
200
+ },
201
+ "privacy": "private"
202
+ },
203
+ {
204
+ "kind": "field",
205
+ "name": "_$indicator",
206
+ "type": {
207
+ "text": "HTMLElement"
208
+ },
209
+ "privacy": "private"
210
+ },
211
+ {
212
+ "kind": "field",
213
+ "name": "_indicatorCtrl",
214
+ "privacy": "private",
215
+ "readonly": true,
216
+ "default": "new NavigationIndicatorController(this, { slot: () => this._$slot ?? null, container: () => this._$nav ?? null, indicator: () => this._$indicator ?? null, activeSelector: () => this.activeSelector, indicatorTargetSelector: () => this.indicatorTarget, })"
217
+ },
218
+ {
219
+ "kind": "method",
220
+ "name": "_handleSlotChange",
221
+ "privacy": "private",
222
+ "return": {
223
+ "type": {
224
+ "text": "void"
225
+ }
226
+ }
227
+ }
228
+ ],
229
+ "attributes": [
230
+ {
231
+ "description": "Selector used to find the active link. Defaults to `aria-current`.",
232
+ "name": "active-selector",
233
+ "type": {
234
+ "text": "string"
235
+ },
236
+ "default": "'a[aria-current]:not([aria-current=\"false\"])'",
237
+ "fieldName": "activeSelector"
238
+ },
239
+ {
240
+ "description": "Selector inside the active link used for indicator geometry.",
241
+ "name": "indicator-target",
242
+ "type": {
243
+ "text": "string"
244
+ },
245
+ "default": "'[data-rc-navigation-indicator], [data-rc-navigation-icon]'",
246
+ "fieldName": "indicatorTarget"
247
+ }
248
+ ],
249
+ "superclass": {
250
+ "name": "LitElement",
251
+ "package": "lit"
252
+ },
253
+ "tagName": "rc-navigation-bar",
254
+ "customElement": true
255
+ }
256
+ ],
257
+ "exports": [
258
+ {
259
+ "kind": "js",
260
+ "name": "RCNavigationBar",
261
+ "declaration": {
262
+ "name": "RCNavigationBar",
263
+ "module": "src/rc-navigation-bar.ts"
264
+ }
265
+ },
266
+ {
267
+ "kind": "js",
268
+ "name": "default",
269
+ "declaration": {
270
+ "name": "RCNavigationBar",
271
+ "module": "src/rc-navigation-bar.ts"
272
+ }
273
+ }
274
+ ]
275
+ }
276
+ ]
277
+ }
@@ -0,0 +1,156 @@
1
+ import { css as v, LitElement as g, html as p } from "lit";
2
+ import { property as l, query as o } from "lit/decorators.js";
3
+ import { NavigationIndicatorController as b } from "@rcarls/rc-common";
4
+ const h = v`
5
+ :host {
6
+ display: block;
7
+ color-scheme: inherit;
8
+ color: var(--rc-navigation-bar-color, CanvasText);
9
+ background: var(--rc-navigation-bar-bg, Canvas);
10
+ }
11
+
12
+ :host([hidden]) {
13
+ display: none;
14
+ }
15
+
16
+ [part='nav'] {
17
+ position: relative;
18
+ display: flex;
19
+ align-items: stretch;
20
+ justify-content: stretch;
21
+ min-block-size: var(--rc-navigation-bar-block-size, 4rem);
22
+ padding-block: var(--rc-navigation-bar-padding-block, 0);
23
+ padding-inline: var(--rc-navigation-bar-padding-inline, 0);
24
+ overflow: hidden;
25
+ }
26
+
27
+ slot {
28
+ display: flex;
29
+ flex: 1 1 auto;
30
+ align-items: stretch;
31
+ justify-content: space-around;
32
+ gap: var(--rc-navigation-bar-gap, 0);
33
+ }
34
+
35
+ ::slotted(a) {
36
+ position: relative;
37
+ z-index: 1;
38
+ display: inline-flex;
39
+ flex: 1 1 0;
40
+ flex-direction: column;
41
+ align-items: center;
42
+ justify-content: center;
43
+ gap: var(--rc-navigation-bar-item-gap, 0.25rem);
44
+ min-inline-size: 0;
45
+ min-block-size: var(--rc-navigation-bar-item-min-block-size, 3rem);
46
+ padding-block: var(--rc-navigation-bar-item-padding-block, 0.5rem);
47
+ padding-inline: var(--rc-navigation-bar-item-padding-inline, 0.75rem);
48
+ box-sizing: border-box;
49
+ color: var(--rc-navigation-bar-item-color, inherit);
50
+ font: inherit;
51
+ text-align: center;
52
+ text-decoration: var(--rc-navigation-bar-item-text-decoration, revert);
53
+ outline-offset: var(--rc-navigation-bar-focus-ring-offset, 2px);
54
+ -webkit-tap-highlight-color: transparent;
55
+ }
56
+
57
+ ::slotted(a:focus-visible) {
58
+ outline: var(--rc-navigation-bar-focus-ring, revert);
59
+ }
60
+
61
+ ::slotted(a[aria-current]:not([aria-current='false'])) {
62
+ color: var(--rc-navigation-bar-active-color, LinkText);
63
+ }
64
+
65
+ #indicator {
66
+ position: absolute;
67
+ inset-block-start: 0;
68
+ inset-inline-start: 0;
69
+ z-index: 0;
70
+ box-sizing: border-box;
71
+ border: var(--rc-navigation-bar-indicator-border, 1px solid Highlight);
72
+ border-radius: var(--rc-navigation-bar-indicator-radius, 0);
73
+ background: var(--rc-navigation-bar-indicator-bg, transparent);
74
+ pointer-events: none;
75
+ transition:
76
+ transform var(--rc-navigation-bar-indicator-duration, 0ms)
77
+ var(--rc-navigation-bar-indicator-easing, ease),
78
+ inline-size var(--rc-navigation-bar-indicator-duration, 0ms)
79
+ var(--rc-navigation-bar-indicator-easing, ease),
80
+ block-size var(--rc-navigation-bar-indicator-duration, 0ms)
81
+ var(--rc-navigation-bar-indicator-easing, ease),
82
+ opacity var(--rc-navigation-bar-indicator-duration, 0ms) ease;
83
+ }
84
+
85
+ #indicator[hidden] {
86
+ display: block;
87
+ opacity: 0;
88
+ }
89
+
90
+ @media (forced-colors: active) {
91
+ #indicator {
92
+ border: 1px solid Highlight;
93
+ background: transparent;
94
+ }
95
+ }
96
+
97
+ @media (prefers-reduced-motion: reduce) {
98
+ #indicator {
99
+ transition-duration: 0s;
100
+ }
101
+ }
102
+ `;
103
+ var u = Object.defineProperty, r = (c, t, s, m) => {
104
+ for (var a = void 0, n = c.length - 1, d; n >= 0; n--)
105
+ (d = c[n]) && (a = d(t, s, a) || a);
106
+ return a && u(t, s, a), a;
107
+ };
108
+ const e = class e extends g {
109
+ constructor() {
110
+ super(...arguments), this.activeSelector = 'a[aria-current]:not([aria-current="false"])', this.indicatorTarget = "[data-rc-navigation-indicator], [data-rc-navigation-icon]", this._indicatorCtrl = new b(this, {
111
+ slot: () => this._$slot ?? null,
112
+ container: () => this._$nav ?? null,
113
+ indicator: () => this._$indicator ?? null,
114
+ activeSelector: () => this.activeSelector,
115
+ indicatorTargetSelector: () => this.indicatorTarget
116
+ });
117
+ }
118
+ firstUpdated() {
119
+ this._indicatorCtrl.sync();
120
+ }
121
+ updated(t) {
122
+ (t.has("activeSelector") || t.has("indicatorTarget")) && this._indicatorCtrl.sync();
123
+ }
124
+ render() {
125
+ return p`
126
+ <div part="nav">
127
+ <div id="indicator" part="indicator" hidden></div>
128
+ <slot @slotchange=${this._handleSlotChange}></slot>
129
+ </div>
130
+ `;
131
+ }
132
+ _handleSlotChange() {
133
+ this._indicatorCtrl.sync();
134
+ }
135
+ };
136
+ e.styles = [h];
137
+ let i = e;
138
+ r([
139
+ l({ type: String, attribute: "active-selector" })
140
+ ], i.prototype, "activeSelector");
141
+ r([
142
+ l({ type: String, attribute: "indicator-target" })
143
+ ], i.prototype, "indicatorTarget");
144
+ r([
145
+ o("slot")
146
+ ], i.prototype, "_$slot");
147
+ r([
148
+ o('[part="nav"]')
149
+ ], i.prototype, "_$nav");
150
+ r([
151
+ o("#indicator")
152
+ ], i.prototype, "_$indicator");
153
+ export {
154
+ i as R
155
+ };
156
+ //# sourceMappingURL=rc-navigation-bar-CNk5Kuwk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-navigation-bar-CNk5Kuwk.js","sources":["../src/rc-navigation-bar.styles.ts","../src/rc-navigation-bar.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const navigationBarStyles = css`\n :host {\n display: block;\n color-scheme: inherit;\n color: var(--rc-navigation-bar-color, CanvasText);\n background: var(--rc-navigation-bar-bg, Canvas);\n }\n\n :host([hidden]) {\n display: none;\n }\n\n [part='nav'] {\n position: relative;\n display: flex;\n align-items: stretch;\n justify-content: stretch;\n min-block-size: var(--rc-navigation-bar-block-size, 4rem);\n padding-block: var(--rc-navigation-bar-padding-block, 0);\n padding-inline: var(--rc-navigation-bar-padding-inline, 0);\n overflow: hidden;\n }\n\n slot {\n display: flex;\n flex: 1 1 auto;\n align-items: stretch;\n justify-content: space-around;\n gap: var(--rc-navigation-bar-gap, 0);\n }\n\n ::slotted(a) {\n position: relative;\n z-index: 1;\n display: inline-flex;\n flex: 1 1 0;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--rc-navigation-bar-item-gap, 0.25rem);\n min-inline-size: 0;\n min-block-size: var(--rc-navigation-bar-item-min-block-size, 3rem);\n padding-block: var(--rc-navigation-bar-item-padding-block, 0.5rem);\n padding-inline: var(--rc-navigation-bar-item-padding-inline, 0.75rem);\n box-sizing: border-box;\n color: var(--rc-navigation-bar-item-color, inherit);\n font: inherit;\n text-align: center;\n text-decoration: var(--rc-navigation-bar-item-text-decoration, revert);\n outline-offset: var(--rc-navigation-bar-focus-ring-offset, 2px);\n -webkit-tap-highlight-color: transparent;\n }\n\n ::slotted(a:focus-visible) {\n outline: var(--rc-navigation-bar-focus-ring, revert);\n }\n\n ::slotted(a[aria-current]:not([aria-current='false'])) {\n color: var(--rc-navigation-bar-active-color, LinkText);\n }\n\n #indicator {\n position: absolute;\n inset-block-start: 0;\n inset-inline-start: 0;\n z-index: 0;\n box-sizing: border-box;\n border: var(--rc-navigation-bar-indicator-border, 1px solid Highlight);\n border-radius: var(--rc-navigation-bar-indicator-radius, 0);\n background: var(--rc-navigation-bar-indicator-bg, transparent);\n pointer-events: none;\n transition:\n transform var(--rc-navigation-bar-indicator-duration, 0ms)\n var(--rc-navigation-bar-indicator-easing, ease),\n inline-size var(--rc-navigation-bar-indicator-duration, 0ms)\n var(--rc-navigation-bar-indicator-easing, ease),\n block-size var(--rc-navigation-bar-indicator-duration, 0ms)\n var(--rc-navigation-bar-indicator-easing, ease),\n opacity var(--rc-navigation-bar-indicator-duration, 0ms) ease;\n }\n\n #indicator[hidden] {\n display: block;\n opacity: 0;\n }\n\n @media (forced-colors: active) {\n #indicator {\n border: 1px solid Highlight;\n background: transparent;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n #indicator {\n transition-duration: 0s;\n }\n }\n`;\n\nexport default navigationBarStyles;\n","import { LitElement, html } from 'lit';\nimport type { PropertyValues } from 'lit';\nimport { property, query } from 'lit/decorators.js';\n\nimport { NavigationIndicatorController } from '@rcarls/rc-common';\n\nimport navigationBarStyles from './rc-navigation-bar.styles.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-navigation-bar': RCNavigationBar;\n }\n}\n\n/**\n * Bottom navigation layout that styles consumer-authored links.\n *\n * `rc-navigation-bar` preserves native `<a>` elements in light DOM for router\n * interop and progressive enhancement. Mark the current link with\n * `aria-current=\"page\"` or provide `active-selector` for router active classes.\n * Wrap the component in a consumer-authored `<nav>` when it represents a\n * navigation landmark.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-navigation-bar rc-navigation-bar docs}\n * @see {@link https://m3.material.io/components/navigation-bar/overview Material 3 navigation bar}\n *\n * @slot default - Navigation links. Direct `<a>` children are recommended.\n *\n * @csspart nav - The navigation layout container.\n * @csspart indicator - The active item indicator.\n *\n * @cssprop [--rc-navigation-bar-bg=Canvas] - Navigation surface background.\n * @cssprop [--rc-navigation-bar-color=CanvasText] - Navigation text color.\n * @cssprop [--rc-navigation-bar-block-size=4rem] - Minimum block size for the bar.\n * @cssprop [--rc-navigation-bar-padding-block=0] - Bar block-axis padding.\n * @cssprop [--rc-navigation-bar-padding-inline=0] - Bar inline-axis padding.\n * @cssprop [--rc-navigation-bar-gap=0] - Gap between slotted items.\n * @cssprop [--rc-navigation-bar-item-gap=0.25rem] - Gap between item icon and label.\n * @cssprop [--rc-navigation-bar-item-min-block-size=3rem] - Minimum item block size.\n * @cssprop [--rc-navigation-bar-item-padding-block=0.5rem] - Item block-axis padding.\n * @cssprop [--rc-navigation-bar-item-padding-inline=0.75rem] - Item inline-axis padding.\n * @cssprop [--rc-navigation-bar-item-color=inherit] - Resting item text color.\n * @cssprop [--rc-navigation-bar-item-text-decoration] - Slotted link text decoration (defers to\n * native anchor text-decoration when unset).\n * @cssprop [--rc-navigation-bar-active-color] - Active item text color. Falls back to\n * `--rc-navigation-bar-item-color`, then `inherit`.\n * @cssprop [--rc-navigation-bar-indicator-bg=transparent] - Active indicator background.\n * @cssprop [--rc-navigation-bar-indicator-border=1px solid Highlight] - Active indicator border.\n * @cssprop [--rc-navigation-bar-indicator-radius=0] - Active indicator corner radius.\n * @cssprop [--rc-navigation-bar-indicator-duration=0ms] - Active indicator transition duration.\n * @cssprop [--rc-navigation-bar-indicator-easing=ease] - Active indicator transition easing.\n * @cssprop [--rc-navigation-bar-focus-ring] - Slotted link focus outline (defers to native\n * outline when unset).\n * @cssprop [--rc-navigation-bar-focus-ring-offset=2px] - Slotted link outline offset.\n *\n * @attr active-selector - Selector used to find the active link.\n * @attr indicator-target - Selector inside the active link used for indicator geometry.\n */\nexport class RCNavigationBar extends LitElement {\n static override styles = [navigationBarStyles];\n\n /** Selector used to find the active link. Defaults to `aria-current`. */\n @property({ type: String, attribute: 'active-selector' })\n activeSelector = 'a[aria-current]:not([aria-current=\"false\"])';\n\n /** Selector inside the active link used for indicator geometry. */\n @property({ type: String, attribute: 'indicator-target' })\n indicatorTarget = '[data-rc-navigation-indicator], [data-rc-navigation-icon]';\n\n @query('slot') private _$slot!: HTMLSlotElement;\n\n @query('[part=\"nav\"]') private _$nav!: HTMLElement;\n\n @query('#indicator') private _$indicator!: HTMLElement;\n\n private readonly _indicatorCtrl = new NavigationIndicatorController(this, {\n slot: () => this._$slot ?? null,\n container: () => this._$nav ?? null,\n indicator: () => this._$indicator ?? null,\n activeSelector: () => this.activeSelector,\n indicatorTargetSelector: () => this.indicatorTarget,\n });\n\n protected override firstUpdated(): void {\n this._indicatorCtrl.sync();\n }\n\n protected override updated(changed: PropertyValues<this>): void {\n if (changed.has('activeSelector') || changed.has('indicatorTarget')) {\n this._indicatorCtrl.sync();\n }\n }\n\n protected override render() {\n return html`\n <div part=\"nav\">\n <div id=\"indicator\" part=\"indicator\" hidden></div>\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n\n private _handleSlotChange(): void {\n this._indicatorCtrl.sync();\n }\n}\n\nexport default RCNavigationBar;\n"],"names":["navigationBarStyles","css","_RCNavigationBar","LitElement","NavigationIndicatorController","changed","html","RCNavigationBar","__decorateClass","property","query"],"mappings":";;;AAEO,MAAMA,IAAsBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;ACwD5B,MAAMC,IAAN,MAAMA,UAAwBC,EAAW;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA,GAKL,KAAA,iBAAiB,+CAIjB,KAAA,kBAAkB,6DAQlB,KAAiB,iBAAiB,IAAIC,EAA8B,MAAM;AAAA,MACxE,MAAM,MAAM,KAAK,UAAU;AAAA,MAC3B,WAAW,MAAM,KAAK,SAAS;AAAA,MAC/B,WAAW,MAAM,KAAK,eAAe;AAAA,MACrC,gBAAgB,MAAM,KAAK;AAAA,MAC3B,yBAAyB,MAAM,KAAK;AAAA,IAAA,CACrC;AAAA,EAAA;AAAA,EAEkB,eAAqB;AACtC,SAAK,eAAe,KAAA;AAAA,EACtB;AAAA,EAEmB,QAAQC,GAAqC;AAC9D,KAAIA,EAAQ,IAAI,gBAAgB,KAAKA,EAAQ,IAAI,iBAAiB,MAChE,KAAK,eAAe,KAAA;AAAA,EAExB;AAAA,EAEmB,SAAS;AAC1B,WAAOC;AAAA;AAAA;AAAA,4BAGiB,KAAK,iBAAiB;AAAA;AAAA;AAAA,EAGhD;AAAA,EAEQ,oBAA0B;AAChC,SAAK,eAAe,KAAA;AAAA,EACtB;AACF;AA9CEJ,EAAgB,SAAS,CAACF,CAAmB;AADxC,IAAMO,IAANL;AAKLM,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,WAAW,mBAAmB;AAAA,GAJ7CF,EAKX,WAAA,gBAAA;AAIAC,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,WAAW,oBAAoB;AAAA,GAR9CF,EASX,WAAA,iBAAA;AAEuBC,EAAA;AAAA,EAAtBE,EAAM,MAAM;AAAA,GAXFH,EAWY,WAAA,QAAA;AAEQC,EAAA;AAAA,EAA9BE,EAAM,cAAc;AAAA,GAbVH,EAaoB,WAAA,OAAA;AAEFC,EAAA;AAAA,EAA5BE,EAAM,YAAY;AAAA,GAfRH,EAekB,WAAA,aAAA;"}
@@ -0,0 +1,6 @@
1
+ import { R as a } from "./rc-navigation-bar-CNk5Kuwk.js";
2
+ customElements.get("rc-navigation-bar") || customElements.define("rc-navigation-bar", a);
3
+ export {
4
+ a as RCNavigationBar
5
+ };
6
+ //# sourceMappingURL=rc-navigation-bar-define.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-navigation-bar-define.js","sources":["../src/define.ts"],"sourcesContent":["import { RCNavigationBar } from './index.js';\n\ncustomElements.get('rc-navigation-bar') ||\n customElements.define('rc-navigation-bar', RCNavigationBar);\n\nexport * from './index.js';\n"],"names":["RCNavigationBar"],"mappings":";AAEA,eAAe,IAAI,mBAAmB,KACpC,eAAe,OAAO,qBAAqBA,CAAe;"}
@@ -0,0 +1,5 @@
1
+ import { R as r } from "./rc-navigation-bar-CNk5Kuwk.js";
2
+ export {
3
+ r as RCNavigationBar
4
+ };
5
+ //# sourceMappingURL=rc-navigation-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-navigation-bar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1 @@
1
+ export * from './index.js';
@@ -0,0 +1 @@
1
+ export * from './rc-navigation-bar';
@@ -0,0 +1,66 @@
1
+ import { LitElement, PropertyValues } from 'lit';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'rc-navigation-bar': RCNavigationBar;
5
+ }
6
+ }
7
+ /**
8
+ * Bottom navigation layout that styles consumer-authored links.
9
+ *
10
+ * `rc-navigation-bar` preserves native `<a>` elements in light DOM for router
11
+ * interop and progressive enhancement. Mark the current link with
12
+ * `aria-current="page"` or provide `active-selector` for router active classes.
13
+ * Wrap the component in a consumer-authored `<nav>` when it represents a
14
+ * navigation landmark.
15
+ *
16
+ * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-navigation-bar rc-navigation-bar docs}
17
+ * @see {@link https://m3.material.io/components/navigation-bar/overview Material 3 navigation bar}
18
+ *
19
+ * @slot default - Navigation links. Direct `<a>` children are recommended.
20
+ *
21
+ * @csspart nav - The navigation layout container.
22
+ * @csspart indicator - The active item indicator.
23
+ *
24
+ * @cssprop [--rc-navigation-bar-bg=Canvas] - Navigation surface background.
25
+ * @cssprop [--rc-navigation-bar-color=CanvasText] - Navigation text color.
26
+ * @cssprop [--rc-navigation-bar-block-size=4rem] - Minimum block size for the bar.
27
+ * @cssprop [--rc-navigation-bar-padding-block=0] - Bar block-axis padding.
28
+ * @cssprop [--rc-navigation-bar-padding-inline=0] - Bar inline-axis padding.
29
+ * @cssprop [--rc-navigation-bar-gap=0] - Gap between slotted items.
30
+ * @cssprop [--rc-navigation-bar-item-gap=0.25rem] - Gap between item icon and label.
31
+ * @cssprop [--rc-navigation-bar-item-min-block-size=3rem] - Minimum item block size.
32
+ * @cssprop [--rc-navigation-bar-item-padding-block=0.5rem] - Item block-axis padding.
33
+ * @cssprop [--rc-navigation-bar-item-padding-inline=0.75rem] - Item inline-axis padding.
34
+ * @cssprop [--rc-navigation-bar-item-color=inherit] - Resting item text color.
35
+ * @cssprop [--rc-navigation-bar-item-text-decoration] - Slotted link text decoration (defers to
36
+ * native anchor text-decoration when unset).
37
+ * @cssprop [--rc-navigation-bar-active-color] - Active item text color. Falls back to
38
+ * `--rc-navigation-bar-item-color`, then `inherit`.
39
+ * @cssprop [--rc-navigation-bar-indicator-bg=transparent] - Active indicator background.
40
+ * @cssprop [--rc-navigation-bar-indicator-border=1px solid Highlight] - Active indicator border.
41
+ * @cssprop [--rc-navigation-bar-indicator-radius=0] - Active indicator corner radius.
42
+ * @cssprop [--rc-navigation-bar-indicator-duration=0ms] - Active indicator transition duration.
43
+ * @cssprop [--rc-navigation-bar-indicator-easing=ease] - Active indicator transition easing.
44
+ * @cssprop [--rc-navigation-bar-focus-ring] - Slotted link focus outline (defers to native
45
+ * outline when unset).
46
+ * @cssprop [--rc-navigation-bar-focus-ring-offset=2px] - Slotted link outline offset.
47
+ *
48
+ * @attr active-selector - Selector used to find the active link.
49
+ * @attr indicator-target - Selector inside the active link used for indicator geometry.
50
+ */
51
+ export declare class RCNavigationBar extends LitElement {
52
+ static styles: import('lit').CSSResult[];
53
+ /** Selector used to find the active link. Defaults to `aria-current`. */
54
+ activeSelector: string;
55
+ /** Selector inside the active link used for indicator geometry. */
56
+ indicatorTarget: string;
57
+ private _$slot;
58
+ private _$nav;
59
+ private _$indicator;
60
+ private readonly _indicatorCtrl;
61
+ protected firstUpdated(): void;
62
+ protected updated(changed: PropertyValues<this>): void;
63
+ protected render(): import('lit').TemplateResult<1>;
64
+ private _handleSlotChange;
65
+ }
66
+ export default RCNavigationBar;
@@ -0,0 +1,2 @@
1
+ export declare const navigationBarStyles: import('lit').CSSResult;
2
+ export default navigationBarStyles;
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@rcarls/rc-navigation-bar",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.4.0",
7
+ "description": "Bottom navigation layout that styles consumer-authored links.",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/richardcarls/rc-webcomponents.git",
11
+ "directory": "packages/rc-navigation-bar"
12
+ },
13
+ "homepage": "https://richardcarls.github.io/rc-webcomponents/components/rc-navigation-bar",
14
+ "license": "MIT",
15
+ "type": "module",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "module": "./dist/rc-navigation-bar.js",
20
+ "exports": {
21
+ ".": {
22
+ "import": {
23
+ "types": "./dist/types/packages/rc-navigation-bar/src/index.d.ts",
24
+ "default": "./dist/rc-navigation-bar.js"
25
+ }
26
+ },
27
+ "./define": {
28
+ "import": {
29
+ "types": "./dist/types/packages/rc-navigation-bar/src/define.d.ts",
30
+ "default": "./dist/rc-navigation-bar-define.js"
31
+ }
32
+ }
33
+ },
34
+ "types": "./dist/types/packages/rc-navigation-bar/src/index.d.ts",
35
+ "sideEffects": [
36
+ "./dist/rc-navigation-bar-define.js"
37
+ ],
38
+ "customElements": "dist/custom-elements.json",
39
+ "scripts": {
40
+ "build": "tsc && vite build && cem analyze",
41
+ "cem:analyze": "cem analyze",
42
+ "preview": "vite preview",
43
+ "test:browser": "vitest --run",
44
+ "test:browser:chrome": "vitest --run --project=chromium",
45
+ "test:browser:firefox": "vitest --run --project=firefox"
46
+ },
47
+ "dependencies": {
48
+ "@rcarls/rc-common": "workspace:*"
49
+ },
50
+ "devDependencies": {
51
+ "@custom-elements-manifest/analyzer": "0.11.0",
52
+ "@vitest/browser-playwright": "4.1.5",
53
+ "lit": "^3.0.0",
54
+ "playwright": "^1.56.0",
55
+ "rollup": "^4.60.2",
56
+ "typescript": "~5.9.3",
57
+ "vite": "^7.1.7",
58
+ "vite-plugin-dts": "^4.5.4",
59
+ "vitest": "^4.0.6",
60
+ "vitest-browser-lit": "^1.0.1"
61
+ },
62
+ "peerDependencies": {
63
+ "lit": "^3.0.0"
64
+ }
65
+ }