@reliability-design/web 1.4.5 → 1.4.7
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/CHANGELOG.md +211 -49
- package/dist/components/rel-accordion/README.md +132 -132
- package/dist/components/rel-alert/README.md +145 -141
- package/dist/components/rel-autocomplete/README.md +156 -61
- package/dist/components/rel-avatar/README.md +116 -130
- package/dist/components/rel-badge/README.md +98 -93
- package/dist/components/rel-breadcrumb/README.md +96 -102
- package/dist/components/rel-button/README.md +160 -130
- package/dist/components/rel-calendar/README.md +109 -109
- package/dist/components/rel-card/README.md +75 -94
- package/dist/components/rel-cardmedia/README.md +100 -127
- package/dist/components/rel-carousel/README.md +184 -166
- package/dist/components/rel-checkbox/README.md +93 -75
- package/dist/components/rel-chip/README.md +132 -121
- package/dist/components/rel-container/README.md +107 -99
- package/dist/components/rel-date-picker/README.md +200 -289
- package/dist/components/rel-divider/README.md +78 -100
- package/dist/components/rel-drawer/README.md +187 -200
- package/dist/components/rel-kbd/README.md +141 -151
- package/dist/components/rel-menu/README.md +178 -151
- package/dist/components/rel-menubar/README.md +218 -329
- package/dist/components/rel-otp/README.md +170 -440
- package/dist/components/rel-pagination/README.md +100 -424
- package/dist/components/rel-popover/README.md +203 -568
- package/dist/components/rel-progress/README.md +88 -110
- package/dist/components/rel-radio/README.md +131 -135
- package/dist/components/rel-range-picker/README.md +162 -0
- package/dist/components/rel-resizable/README.md +199 -140
- package/dist/components/rel-segmented-button/README.md +155 -141
- package/dist/components/rel-select/README.md +154 -93
- package/dist/components/rel-sheet/README.md +168 -224
- package/dist/components/rel-skeleton/README.md +103 -0
- package/dist/components/rel-slider/README.md +130 -135
- package/dist/components/rel-snackbar/README.md +162 -134
- package/dist/components/rel-stepper/README.md +158 -160
- package/dist/components/rel-switch/README.md +108 -102
- package/dist/components/rel-tab/README.md +171 -163
- package/dist/components/rel-textfield/README.md +159 -69
- package/dist/components/rel-time-picker/README.md +122 -157
- package/dist/components/rel-toast/README.md +157 -148
- package/dist/components/rel-tooltip/README.md +108 -103
- package/dist/components/rel-upload/README.md +220 -0
- package/dist/index.d.mts +1387 -350
- package/dist/index.d.ts +1387 -350
- package/dist/index.js +5863 -3600
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5864 -3592
- package/dist/index.mjs.map +1 -1
- package/dist/styles/vars.css +877 -866
- package/dist/{vars-XNMTSRVN.css → vars-JHTUGNRG.css} +877 -866
- package/package.json +4 -3
- package/dist/components/rel-accordion/rel-accordion.ts +0 -336
- package/dist/components/rel-alert/rel-alert.ts +0 -305
- package/dist/components/rel-autocomplete/rel-autocomplete.ts +0 -689
- package/dist/components/rel-avatar/rel-avatar.ts +0 -142
- package/dist/components/rel-badge/rel-badge.ts +0 -170
- package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +0 -106
- package/dist/components/rel-button/rel-button.ts +0 -560
- package/dist/components/rel-calendar/index.ts +0 -1
- package/dist/components/rel-calendar/rel-calendar.ts +0 -519
- package/dist/components/rel-card/rel-card.ts +0 -88
- package/dist/components/rel-cardmedia/rel-cardmedia.ts +0 -88
- package/dist/components/rel-carousel/index.ts +0 -1
- package/dist/components/rel-carousel/rel-carousel.ts +0 -700
- package/dist/components/rel-chart/README.md +0 -286
- package/dist/components/rel-chart/index.ts +0 -1
- package/dist/components/rel-chart/rel-chart.ts +0 -754
- package/dist/components/rel-checkbox/rel-checkbox.ts +0 -382
- package/dist/components/rel-chip/rel-chip.ts +0 -472
- package/dist/components/rel-container/rel-container.ts +0 -95
- package/dist/components/rel-date-picker/date-format.test.ts +0 -43
- package/dist/components/rel-date-picker/date-format.ts +0 -47
- package/dist/components/rel-date-picker/index.ts +0 -1
- package/dist/components/rel-date-picker/rel-date-picker.ts +0 -1237
- package/dist/components/rel-divider/rel-divider.ts +0 -54
- package/dist/components/rel-drawer/index.ts +0 -1
- package/dist/components/rel-drawer/rel-drawer-footer.ts +0 -27
- package/dist/components/rel-drawer/rel-drawer.ts +0 -604
- package/dist/components/rel-kbd/rel-kbd.ts +0 -188
- package/dist/components/rel-layout/rel-layout.ts +0 -49
- package/dist/components/rel-menu/rel-menu.ts +0 -535
- package/dist/components/rel-menubar/index.ts +0 -2
- package/dist/components/rel-menubar/rel-menubar-menu.css +0 -3
- package/dist/components/rel-menubar/rel-menubar-menu.ts +0 -17
- package/dist/components/rel-menubar/rel-menubar.ts +0 -777
- package/dist/components/rel-nav-menu/README.md +0 -289
- package/dist/components/rel-nav-menu/index.ts +0 -3
- package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +0 -243
- package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +0 -72
- package/dist/components/rel-nav-menu/rel-nav-menu.ts +0 -270
- package/dist/components/rel-navbar/README.md +0 -126
- package/dist/components/rel-navbar/rel-navbar.ts +0 -105
- package/dist/components/rel-otp/index.ts +0 -1
- package/dist/components/rel-otp/rel-otp.ts +0 -517
- package/dist/components/rel-pagination/index.ts +0 -1
- package/dist/components/rel-pagination/rel-pagination.ts +0 -509
- package/dist/components/rel-popover/index.ts +0 -2
- package/dist/components/rel-popover/rel-popover-content.ts +0 -81
- package/dist/components/rel-popover/rel-popover.ts +0 -444
- package/dist/components/rel-progress/rel-progress.ts +0 -225
- package/dist/components/rel-radio/rel-radio.ts +0 -305
- package/dist/components/rel-range-picker/rel-range-picker.ts +0 -1331
- package/dist/components/rel-resizable/index.ts +0 -3
- package/dist/components/rel-resizable/rel-resizable-group.ts +0 -405
- package/dist/components/rel-resizable/rel-resizable-handle.ts +0 -150
- package/dist/components/rel-resizable/rel-resizable-panel.ts +0 -58
- package/dist/components/rel-segmented-button/rel-segmented-button.ts +0 -213
- package/dist/components/rel-select/rel-select.ts +0 -1385
- package/dist/components/rel-sheet/rel-sheet.ts +0 -465
- package/dist/components/rel-sidebar/README.md +0 -209
- package/dist/components/rel-sidebar/rel-sidebar.ts +0 -1185
- package/dist/components/rel-skeleton/rel-skeleton.ts +0 -134
- package/dist/components/rel-slider/rel-slider.ts +0 -670
- package/dist/components/rel-snackbar/rel-snackbar.ts +0 -325
- package/dist/components/rel-stepper/rel-stepper.ts +0 -565
- package/dist/components/rel-switch/rel-switch.ts +0 -197
- package/dist/components/rel-tab/rel-tab.ts +0 -264
- package/dist/components/rel-table/README.md +0 -178
- package/dist/components/rel-table/rel-table-body.ts +0 -22
- package/dist/components/rel-table/rel-table-caption.ts +0 -30
- package/dist/components/rel-table/rel-table-cell.ts +0 -43
- package/dist/components/rel-table/rel-table-footer.ts +0 -24
- package/dist/components/rel-table/rel-table-head.ts +0 -47
- package/dist/components/rel-table/rel-table-header.ts +0 -22
- package/dist/components/rel-table/rel-table-row.ts +0 -37
- package/dist/components/rel-table/rel-table.ts +0 -62
- package/dist/components/rel-textfield/rel-textfield.ts +0 -866
- package/dist/components/rel-time-picker/rel-time-picker.ts +0 -1126
- package/dist/components/rel-toast/rel-toast.ts +0 -204
- package/dist/components/rel-tooltip/rel-tooltip.ts +0 -190
- package/dist/components/rel-topbar/rel-topbar-actions.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar-brand.ts +0 -54
- package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +0 -69
- package/dist/components/rel-topbar/rel-topbar-dropdown.ts +0 -31
- package/dist/components/rel-topbar/rel-topbar-item.ts +0 -324
- package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar-profile.ts +0 -243
- package/dist/components/rel-topbar/rel-topbar-utilities.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar.ts +0 -446
- package/dist/components/rel-upload/UPLOAD-DESIGN-CHANGES.md +0 -134
- package/dist/components/rel-upload/rel-upload-actions.ts +0 -163
- package/dist/components/rel-upload/rel-upload.ts +0 -943
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import { LitElement, html, css } from "lit";
|
|
2
|
-
import { customElement, property, state, query } from "lit/decorators.js";
|
|
3
|
-
import { RelNavMenuItem } from "./rel-nav-menu-item";
|
|
4
|
-
|
|
5
|
-
type DensityType = "comfortable" | "compact";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated rel-nav-menu has no Figma design in RelDS 2.0 and is excluded
|
|
9
|
-
* from the parity contract. Use rel-menu (with the select-option/fixed/fit
|
|
10
|
-
* types) or the Navbar recipe instead. It remains exported for
|
|
11
|
-
* compatibility but will be removed in a future major version.
|
|
12
|
-
*/
|
|
13
|
-
@customElement("rel-nav-menu")
|
|
14
|
-
export class RelNavMenu extends LitElement {
|
|
15
|
-
@property({ type: String, reflect: true }) open = "";
|
|
16
|
-
@property({ type: Boolean, reflect: true }) disabled = false;
|
|
17
|
-
@property({ type: String }) density: DensityType = "comfortable";
|
|
18
|
-
|
|
19
|
-
@state() private items: RelNavMenuItem[] = [];
|
|
20
|
-
@state() private focusedIndex = 0;
|
|
21
|
-
@state() private hoverSwitchEnabled = false;
|
|
22
|
-
|
|
23
|
-
@query(".nav-container") private container!: HTMLElement;
|
|
24
|
-
|
|
25
|
-
static styles = css`
|
|
26
|
-
:host {
|
|
27
|
-
color: var(--rel-text-default);
|
|
28
|
-
display: block;
|
|
29
|
-
font-family: var(--rel-fonts-font-family);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.nav-container {
|
|
33
|
-
display: flex;
|
|
34
|
-
align-items: center;
|
|
35
|
-
gap: var(--rel-spacing-3xs);
|
|
36
|
-
padding: var(--rel-spacing-2xs);
|
|
37
|
-
background: var(--rel-bg-surface-elevated);
|
|
38
|
-
border-radius: var(--rel-border-radius-sm);
|
|
39
|
-
border: var(--rel-stroke-sm) solid var(--rel-border-default);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.nav-container.compact {
|
|
43
|
-
padding: var(--rel-spacing-3xs);
|
|
44
|
-
gap: 0;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
:host([disabled]) .nav-container {
|
|
48
|
-
opacity: 0.5;
|
|
49
|
-
pointer-events: none;
|
|
50
|
-
}
|
|
51
|
-
`;
|
|
52
|
-
|
|
53
|
-
// ── Lifecycle ──────────────────────────────────────────────────────────────
|
|
54
|
-
|
|
55
|
-
connectedCallback() {
|
|
56
|
-
super.connectedCallback();
|
|
57
|
-
this.discoverItems();
|
|
58
|
-
document.addEventListener("click", this.handleOutsideClick);
|
|
59
|
-
// Delegate item interactions via composed events — no shadow DOM mutation.
|
|
60
|
-
this.addEventListener("rel-nav-item-click", this.handleNavItemClick as EventListener);
|
|
61
|
-
this.addEventListener("rel-nav-item-hover", this.handleNavItemHover as EventListener);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
disconnectedCallback() {
|
|
65
|
-
super.disconnectedCallback();
|
|
66
|
-
document.removeEventListener("click", this.handleOutsideClick);
|
|
67
|
-
this.removeEventListener("rel-nav-item-click", this.handleNavItemClick as EventListener);
|
|
68
|
-
this.removeEventListener("rel-nav-item-hover", this.handleNavItemHover as EventListener);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// ── Item discovery ─────────────────────────────────────────────────────────
|
|
72
|
-
|
|
73
|
-
private discoverItems() {
|
|
74
|
-
const slot = this.shadowRoot?.querySelector("slot");
|
|
75
|
-
if (slot) {
|
|
76
|
-
const nodes = slot.assignedElements() as RelNavMenuItem[];
|
|
77
|
-
this.items = nodes.filter((el) => el.tagName === "REL-NAV-MENU-ITEM");
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
private handleSlotChange() {
|
|
82
|
-
this.discoverItems();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// ── Outside-click dismissal ────────────────────────────────────────────────
|
|
86
|
-
|
|
87
|
-
private handleOutsideClick = (e: MouseEvent) => {
|
|
88
|
-
const path = e.composedPath() as HTMLElement[];
|
|
89
|
-
const isInside = path.some(
|
|
90
|
-
(el) => el === this || el.tagName === "REL-NAV-MENU-ITEM"
|
|
91
|
-
);
|
|
92
|
-
if (!isInside && this.open) {
|
|
93
|
-
this.closePanel();
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// ── Delegated item event handlers ──────────────────────────────────────────
|
|
98
|
-
|
|
99
|
-
private handleNavItemClick = (e: Event) => {
|
|
100
|
-
const { itemId, hasContent } = (e as CustomEvent).detail;
|
|
101
|
-
const item = this.items.find((i) => i.itemId === itemId);
|
|
102
|
-
if (!item || this.disabled || item.disabled) return;
|
|
103
|
-
// Plain link with no panel content — let the browser navigate.
|
|
104
|
-
if (item.href && !hasContent) return;
|
|
105
|
-
e.preventDefault();
|
|
106
|
-
if (hasContent) this.openPanel(itemId);
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
private handleNavItemHover = (e: Event) => {
|
|
110
|
-
const { itemId } = (e as CustomEvent).detail;
|
|
111
|
-
const item = this.items.find((i) => i.itemId === itemId);
|
|
112
|
-
if (!item || this.disabled || item.disabled) return;
|
|
113
|
-
if (this.open && this.hoverSwitchEnabled && item.hasContent) {
|
|
114
|
-
this.openPanel(itemId);
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
// ── Panel open/close ───────────────────────────────────────────────────────
|
|
119
|
-
|
|
120
|
-
private openPanel(itemId: string) {
|
|
121
|
-
if (this.disabled) return;
|
|
122
|
-
|
|
123
|
-
// Close the currently open item before switching.
|
|
124
|
-
if (this.open && this.open !== itemId) {
|
|
125
|
-
const prev = this.items.find((i) => i.itemId === this.open);
|
|
126
|
-
if (prev) prev.open = false;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const wasOpen = this.open === itemId;
|
|
130
|
-
this.open = wasOpen ? "" : itemId;
|
|
131
|
-
|
|
132
|
-
const item = this.items.find((i) => i.itemId === itemId);
|
|
133
|
-
if (item) item.open = !wasOpen;
|
|
134
|
-
|
|
135
|
-
if (!wasOpen) {
|
|
136
|
-
this.hoverSwitchEnabled = true;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
this.dispatchEvent(
|
|
140
|
-
new CustomEvent("rel-nav-open-change", {
|
|
141
|
-
detail: { openId: this.open },
|
|
142
|
-
bubbles: true,
|
|
143
|
-
composed: true,
|
|
144
|
-
})
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
private closePanel() {
|
|
149
|
-
if (this.open) {
|
|
150
|
-
const openItem = this.items.find((i) => i.itemId === this.open);
|
|
151
|
-
if (openItem) openItem.open = false;
|
|
152
|
-
this.open = "";
|
|
153
|
-
this.hoverSwitchEnabled = false;
|
|
154
|
-
this.dispatchEvent(
|
|
155
|
-
new CustomEvent("rel-nav-open-change", {
|
|
156
|
-
detail: { openId: "" },
|
|
157
|
-
bubbles: true,
|
|
158
|
-
composed: true,
|
|
159
|
-
})
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// ── Keyboard navigation ────────────────────────────────────────────────────
|
|
165
|
-
|
|
166
|
-
private handleKeyDown(event: KeyboardEvent) {
|
|
167
|
-
if (this.disabled) return;
|
|
168
|
-
|
|
169
|
-
const { key } = event;
|
|
170
|
-
const focusableItems = this.items.filter((item) => !item.disabled);
|
|
171
|
-
const path = event.composedPath();
|
|
172
|
-
const currentItem = focusableItems.find((item) => path.includes(item));
|
|
173
|
-
const inPanel = path.some(
|
|
174
|
-
(el) => el instanceof HTMLElement && el.classList.contains("panel")
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
// Sync the index to where focus ACTUALLY is — Tab moves focus without
|
|
178
|
-
// going through the arrow handlers, so focusedIndex went stale and
|
|
179
|
-
// Enter/arrows acted on the wrong item.
|
|
180
|
-
if (currentItem && !inPanel) {
|
|
181
|
-
this.focusedIndex = focusableItems.indexOf(currentItem);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Keys originating from inside an open panel: let its links/buttons
|
|
185
|
-
// behave natively; only Escape is ours (close + refocus the trigger).
|
|
186
|
-
if (inPanel) {
|
|
187
|
-
if (key === "Escape" && this.open) {
|
|
188
|
-
event.preventDefault();
|
|
189
|
-
const openItemId = this.open;
|
|
190
|
-
this.closePanel();
|
|
191
|
-
const openItem = this.items.find((i) => i.itemId === openItemId);
|
|
192
|
-
const trigger = openItem?.shadowRoot?.querySelector(".trigger") as HTMLElement;
|
|
193
|
-
trigger?.focus();
|
|
194
|
-
}
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (key === "ArrowRight") {
|
|
199
|
-
event.preventDefault();
|
|
200
|
-
this.focusedIndex = Math.min(focusableItems.length - 1, this.focusedIndex + 1);
|
|
201
|
-
this.focusItem(this.focusedIndex);
|
|
202
|
-
} else if (key === "ArrowLeft") {
|
|
203
|
-
event.preventDefault();
|
|
204
|
-
this.focusedIndex = Math.max(0, this.focusedIndex - 1);
|
|
205
|
-
this.focusItem(this.focusedIndex);
|
|
206
|
-
} else if (key === "Home") {
|
|
207
|
-
event.preventDefault();
|
|
208
|
-
this.focusedIndex = 0;
|
|
209
|
-
this.focusItem(this.focusedIndex);
|
|
210
|
-
} else if (key === "End") {
|
|
211
|
-
event.preventDefault();
|
|
212
|
-
this.focusedIndex = focusableItems.length - 1;
|
|
213
|
-
this.focusItem(this.focusedIndex);
|
|
214
|
-
} else if (key === "Enter" || key === " ") {
|
|
215
|
-
const item = currentItem ?? focusableItems[this.focusedIndex];
|
|
216
|
-
if (item && item.hasContent) {
|
|
217
|
-
// Only intercept panel triggers — plain link items keep their
|
|
218
|
-
// native Enter activation (preventDefault used to suppress it).
|
|
219
|
-
event.preventDefault();
|
|
220
|
-
this.openPanel(item.itemId);
|
|
221
|
-
}
|
|
222
|
-
} else if (key === "Escape") {
|
|
223
|
-
event.preventDefault();
|
|
224
|
-
if (this.open) {
|
|
225
|
-
// Capture before closePanel() clears this.open.
|
|
226
|
-
const openItemId = this.open;
|
|
227
|
-
this.closePanel();
|
|
228
|
-
const openItem = this.items.find((i) => i.itemId === openItemId);
|
|
229
|
-
if (openItem) {
|
|
230
|
-
const trigger = openItem.shadowRoot?.querySelector(".trigger") as HTMLElement;
|
|
231
|
-
trigger?.focus();
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
} else if (key === "ArrowDown" && this.open) {
|
|
235
|
-
event.preventDefault();
|
|
236
|
-
// Move focus into the open panel (now inside the item's shadow root).
|
|
237
|
-
const openItem = this.items.find((i) => i.itemId === this.open);
|
|
238
|
-
if (openItem) {
|
|
239
|
-
const panel = openItem.shadowRoot?.querySelector(".panel") as HTMLElement;
|
|
240
|
-
if (panel) {
|
|
241
|
-
const firstFocusable = panel.querySelector("a, button") as HTMLElement;
|
|
242
|
-
firstFocusable?.focus();
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
private focusItem(index: number) {
|
|
249
|
-
const focusableItems = this.items.filter((item) => !item.disabled);
|
|
250
|
-
const item = focusableItems[index];
|
|
251
|
-
if (item) {
|
|
252
|
-
const trigger = item.shadowRoot?.querySelector(".trigger") as HTMLElement;
|
|
253
|
-
trigger?.focus();
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// ── Render ─────────────────────────────────────────────────────────────────
|
|
258
|
-
|
|
259
|
-
render() {
|
|
260
|
-
return html`
|
|
261
|
-
<nav
|
|
262
|
-
class="nav-container ${this.density === "compact" ? "compact" : ""}"
|
|
263
|
-
role="navigation"
|
|
264
|
-
@keydown="${this.handleKeyDown}"
|
|
265
|
-
>
|
|
266
|
-
<slot @slotchange="${this.handleSlotChange}"></slot>
|
|
267
|
-
</nav>
|
|
268
|
-
`;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
# rel-navbar
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
A responsive navigation bar component with sticky positioning support and device-aware styling. Features three layout areas (brand, content, actions) with automatic adjustment for tablet and mobile viewports.
|
|
5
|
-
|
|
6
|
-
## Usage
|
|
7
|
-
```html
|
|
8
|
-
<!-- Basic navbar -->
|
|
9
|
-
<rel-navbar>
|
|
10
|
-
<div slot="brand">
|
|
11
|
-
<img src="logo.png" alt="Brand Logo">
|
|
12
|
-
</div>
|
|
13
|
-
|
|
14
|
-
<nav>
|
|
15
|
-
<a href="#home">Home</a>
|
|
16
|
-
<a href="#about">About</a>
|
|
17
|
-
<a href="#contact">Contact</a>
|
|
18
|
-
</nav>
|
|
19
|
-
|
|
20
|
-
<div slot="actions">
|
|
21
|
-
<button>Login</button>
|
|
22
|
-
</div>
|
|
23
|
-
</rel-navbar>
|
|
24
|
-
|
|
25
|
-
<!-- Sticky navbar -->
|
|
26
|
-
<rel-navbar sticky>
|
|
27
|
-
<div slot="brand">MyApp</div>
|
|
28
|
-
<nav>
|
|
29
|
-
<a href="#features">Features</a>
|
|
30
|
-
<a href="#pricing">Pricing</a>
|
|
31
|
-
</nav>
|
|
32
|
-
<div slot="actions">
|
|
33
|
-
<button>Sign Up</button>
|
|
34
|
-
</div>
|
|
35
|
-
</rel-navbar>
|
|
36
|
-
|
|
37
|
-
<!-- Device-specific layout -->
|
|
38
|
-
<rel-navbar device="mobile">
|
|
39
|
-
<div slot="brand">Logo</div>
|
|
40
|
-
<!-- Content slot hidden on mobile -->
|
|
41
|
-
<div slot="actions">
|
|
42
|
-
<button>☰</button>
|
|
43
|
-
</div>
|
|
44
|
-
</rel-navbar>
|
|
45
|
-
|
|
46
|
-
<!-- Tablet layout -->
|
|
47
|
-
<rel-navbar device="tablet">
|
|
48
|
-
<div slot="brand">Brand</div>
|
|
49
|
-
<nav>
|
|
50
|
-
<a href="#link1">Link 1</a>
|
|
51
|
-
<a href="#link2">Link 2</a>
|
|
52
|
-
</nav>
|
|
53
|
-
<div slot="actions">
|
|
54
|
-
<button>Profile</button>
|
|
55
|
-
</div>
|
|
56
|
-
</rel-navbar>
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## API
|
|
60
|
-
|
|
61
|
-
### Attributes/Properties
|
|
62
|
-
| Name | Type | Default | Description |
|
|
63
|
-
|------|------|---------|-------------|
|
|
64
|
-
| `sticky` (reflected) | `boolean` | `false` | If true, navbar uses `position: sticky` and stays at the top when scrolling |
|
|
65
|
-
| `device` | `"desktop" \| "tablet" \| "mobile"` | `"desktop"` | Device type for responsive styling |
|
|
66
|
-
|
|
67
|
-
## Events
|
|
68
|
-
None.
|
|
69
|
-
|
|
70
|
-
## Slots
|
|
71
|
-
| Slot | Description |
|
|
72
|
-
|------|-------------|
|
|
73
|
-
| `brand` | Brand/logo content on the left side |
|
|
74
|
-
| (default) | Main navigation content (center area, hidden on mobile) |
|
|
75
|
-
| `actions` | Action buttons/items on the right side |
|
|
76
|
-
|
|
77
|
-
## CSS Parts
|
|
78
|
-
| Part | Description |
|
|
79
|
-
|------|-------------|
|
|
80
|
-
| `container` | Main navbar container |
|
|
81
|
-
| `brand` | Brand section wrapper |
|
|
82
|
-
| `content` | Center content section wrapper |
|
|
83
|
-
| `actions` | Actions section wrapper |
|
|
84
|
-
|
|
85
|
-
## Tokens / CSS Variables
|
|
86
|
-
|
|
87
|
-
### Semantic Tokens
|
|
88
|
-
- `--rel-fonts-font-family` - Font family
|
|
89
|
-
|
|
90
|
-
### Color Tokens
|
|
91
|
-
- `--rel-bg-surface` - Background color
|
|
92
|
-
- `--rel-text-default` - Text color
|
|
93
|
-
- `--rel-border-default` - Bottom border color
|
|
94
|
-
|
|
95
|
-
### Spacing Tokens
|
|
96
|
-
- `--rel-spacing-lg` - Desktop horizontal padding
|
|
97
|
-
- `--rel-spacing-md` - Tablet/mobile horizontal padding, brand-actions gap, content padding
|
|
98
|
-
- `--rel-spacing-sm` - Action items gap, mobile padding
|
|
99
|
-
|
|
100
|
-
### Custom Properties
|
|
101
|
-
- `--rel-spacing-xl` - Content area horizontal padding
|
|
102
|
-
|
|
103
|
-
## Accessibility
|
|
104
|
-
- Uses `role="navigation"` on the main navbar container
|
|
105
|
-
- Ensure slotted navigation links are properly structured with semantic HTML
|
|
106
|
-
- Consider adding ARIA labels for brand and actions areas if content is not descriptive
|
|
107
|
-
|
|
108
|
-
### Keyboard Interactions
|
|
109
|
-
- Standard browser navigation (Tab to navigate through links/buttons)
|
|
110
|
-
|
|
111
|
-
### Focus Behavior
|
|
112
|
-
- No specific focus handling (relies on slotted content)
|
|
113
|
-
|
|
114
|
-
## Notes / Edge Cases
|
|
115
|
-
- **Sticky behavior**: When `sticky` is true, the navbar uses `position: sticky`, `top: 0`, and `z-index: 100`
|
|
116
|
-
- **Device variants**:
|
|
117
|
-
- **desktop**: Height 64px, large padding
|
|
118
|
-
- **tablet**: Height 56px, medium padding
|
|
119
|
-
- **mobile**: Height 56px, small padding, content slot is hidden (`display: none`)
|
|
120
|
-
- The component uses flexbox with `justify-content: space-between` for layout
|
|
121
|
-
- The `.content` section has `flex: 1` to take available space between brand and actions
|
|
122
|
-
- The brand and actions areas are `flex-shrink: 0` to prevent compression
|
|
123
|
-
- The navbar has a bottom border by default
|
|
124
|
-
- The `device` property must be manually set programmatically (does not auto-detect from viewport)
|
|
125
|
-
- Consider hiding or collapsing the content slot on mobile and showing a menu icon in the actions slot
|
|
126
|
-
- The sticky attribute is reflected in HTML when set
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { LitElement, html, css } from "lit";
|
|
2
|
-
import { customElement, property } from "lit/decorators.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @deprecated rel-navbar is deprecated and will be removed in a future release.
|
|
6
|
-
* Use rel-topbar and its sub-components instead:
|
|
7
|
-
* rel-topbar, rel-topbar-brand, rel-topbar-actions, rel-topbar-utilities,
|
|
8
|
-
* rel-topbar-item, rel-topbar-dropdown, rel-topbar-dropdown-item
|
|
9
|
-
*/
|
|
10
|
-
@customElement("rel-navbar")
|
|
11
|
-
export class RelNavbar extends LitElement {
|
|
12
|
-
constructor() {
|
|
13
|
-
super();
|
|
14
|
-
console.warn(
|
|
15
|
-
"[rel-navbar] rel-navbar is deprecated. Use rel-topbar instead."
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
@property({ type: Boolean, reflect: true })
|
|
20
|
-
sticky = false;
|
|
21
|
-
|
|
22
|
-
@property({ type: String })
|
|
23
|
-
device: "desktop" | "tablet" | "mobile" = "desktop";
|
|
24
|
-
|
|
25
|
-
static styles = css`
|
|
26
|
-
:host {
|
|
27
|
-
color: var(--rel-text-default);
|
|
28
|
-
display: block;
|
|
29
|
-
width: 100%;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
:host([sticky]) .navbar {
|
|
33
|
-
position: sticky;
|
|
34
|
-
top: 0;
|
|
35
|
-
z-index: 100;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.navbar {
|
|
39
|
-
display: flex;
|
|
40
|
-
align-items: center;
|
|
41
|
-
justify-content: space-between;
|
|
42
|
-
background: var(--rel-bg-surface);
|
|
43
|
-
color: var(--rel-text-default);
|
|
44
|
-
border-bottom: 1px solid var(--rel-border-default);
|
|
45
|
-
height: 64px;
|
|
46
|
-
padding: 0 var(--rel-spacing-lg);
|
|
47
|
-
box-sizing: border-box;
|
|
48
|
-
font-family: var(--rel-fonts-font-family, sans-serif);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.brand {
|
|
52
|
-
display: flex;
|
|
53
|
-
align-items: center;
|
|
54
|
-
gap: var(--rel-spacing-md);
|
|
55
|
-
flex-shrink: 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.content {
|
|
59
|
-
display: flex;
|
|
60
|
-
align-items: center;
|
|
61
|
-
gap: var(--rel-spacing-sm);
|
|
62
|
-
flex: 1;
|
|
63
|
-
justify-content: flex-start;
|
|
64
|
-
padding: 0 var(--rel-spacing-xl);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.actions {
|
|
68
|
-
display: flex;
|
|
69
|
-
align-items: center;
|
|
70
|
-
gap: var(--rel-spacing-sm);
|
|
71
|
-
flex-shrink: 0;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/* Mobile/Tablet variants */
|
|
75
|
-
:host([device="tablet"]) .navbar {
|
|
76
|
-
height: 56px;
|
|
77
|
-
padding: 0 var(--rel-spacing-md);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
:host([device="mobile"]) .navbar {
|
|
81
|
-
height: 56px;
|
|
82
|
-
padding: 0 var(--rel-spacing-sm);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
:host([device="mobile"]) .content {
|
|
86
|
-
display: none;
|
|
87
|
-
}
|
|
88
|
-
`;
|
|
89
|
-
|
|
90
|
-
render() {
|
|
91
|
-
return html`
|
|
92
|
-
<div class="navbar" part="container" role="navigation">
|
|
93
|
-
<div part="brand" class="brand">
|
|
94
|
-
<slot name="brand"></slot>
|
|
95
|
-
</div>
|
|
96
|
-
<div part="content" class="content">
|
|
97
|
-
<slot></slot>
|
|
98
|
-
</div>
|
|
99
|
-
<div part="actions" class="actions">
|
|
100
|
-
<slot name="actions"></slot>
|
|
101
|
-
</div>
|
|
102
|
-
</div>
|
|
103
|
-
`;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./rel-otp";
|