svelte-fluentui 1.3.0 → 1.3.2
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 +12 -17
- package/dist/components/Badge.svelte +5 -1
- package/dist/components/Badge.svelte.d.ts +1 -0
- package/dist/components/QuickGrid.svelte.d.ts +2 -2
- package/dist/components/layout/Panel.svelte +311 -266
- package/dist/components/layout/Panel.svelte.d.ts +1 -0
- package/dist/components/layout/TopNav.svelte +412 -369
- package/dist/components/layout/TopNav.svelte.d.ts +4 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,369 +1,412 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type {SlotType} from "../../types/index.js"
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
class="
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
{
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
{#if
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
{#if
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
{
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
{
|
|
183
|
-
</
|
|
184
|
-
{/each}
|
|
185
|
-
</
|
|
186
|
-
{/if}
|
|
187
|
-
|
|
188
|
-
{#if
|
|
189
|
-
{#if items.length > 0
|
|
190
|
-
<hr class="topnav-drawer-separator" />
|
|
191
|
-
{/if}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
{
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
.
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
display: flex;
|
|
315
|
-
|
|
316
|
-
gap: 0.
|
|
317
|
-
padding: 0 0.75rem;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
:
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {SlotType} from "../../types/index.js"
|
|
3
|
+
import Panel from "./Panel.svelte"
|
|
4
|
+
import NavMenu from "../nav/NavMenu.svelte"
|
|
5
|
+
import NavGroup from "../nav/NavGroup.svelte"
|
|
6
|
+
import NavLinkItem from "../nav/NavLinkItem.svelte"
|
|
7
|
+
import DismissIcon from "../icons/DismissIcon.svelte"
|
|
8
|
+
|
|
9
|
+
type NavItem = {
|
|
10
|
+
label: string
|
|
11
|
+
href: string
|
|
12
|
+
icon?: string
|
|
13
|
+
onClick?: () => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type NavGroupItem = {
|
|
17
|
+
title: string
|
|
18
|
+
icon: string
|
|
19
|
+
items: Array<{label: string; href: string}>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type CollapseMode = "auto" | "always" | "never"
|
|
23
|
+
|
|
24
|
+
type Props = {
|
|
25
|
+
brand?: string
|
|
26
|
+
brandHref?: string
|
|
27
|
+
brandTemplate?: SlotType
|
|
28
|
+
items?: NavItem[]
|
|
29
|
+
children?: SlotType
|
|
30
|
+
navigationGroups?: NavGroupItem[]
|
|
31
|
+
drawerContent?: SlotType
|
|
32
|
+
collapse?: CollapseMode
|
|
33
|
+
drawerPinned?: boolean
|
|
34
|
+
drawerWidth?: string
|
|
35
|
+
height?: number
|
|
36
|
+
menuToggleSize?: number
|
|
37
|
+
menuToggleTemplate?: SlotType
|
|
38
|
+
class?: string
|
|
39
|
+
style?: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let {
|
|
43
|
+
brand = "Brand",
|
|
44
|
+
brandHref = "/",
|
|
45
|
+
brandTemplate = undefined,
|
|
46
|
+
items = [],
|
|
47
|
+
children = undefined,
|
|
48
|
+
navigationGroups = [],
|
|
49
|
+
drawerContent = undefined,
|
|
50
|
+
collapse = "auto",
|
|
51
|
+
drawerPinned = false,
|
|
52
|
+
drawerWidth = "280px",
|
|
53
|
+
height = 60,
|
|
54
|
+
menuToggleSize = 42,
|
|
55
|
+
menuToggleTemplate = undefined,
|
|
56
|
+
class: className = "",
|
|
57
|
+
style = ""
|
|
58
|
+
}: Props = $props()
|
|
59
|
+
|
|
60
|
+
let mobileMenuOpen = $state(false)
|
|
61
|
+
|
|
62
|
+
// Drawer is for collapsed nav items / groups OR custom drawerContent.
|
|
63
|
+
// The action slot is intentionally NOT counted — it stays visible at every
|
|
64
|
+
// width (search, account menu, theme toggle should remain reachable on
|
|
65
|
+
// mobile rather than being hidden inside a hamburger).
|
|
66
|
+
const hasDrawerContent = $derived(
|
|
67
|
+
items.length > 0 || navigationGroups.length > 0 || !!drawerContent
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
// Sync drawer's open state with `drawerPinned` so transitioning to pinned
|
|
71
|
+
// mode auto-reveals the rail (desktop default) and transitioning back to
|
|
72
|
+
// overlay mode starts closed (no surprise overlay on viewport resize).
|
|
73
|
+
// User toggles via the hamburger between transitions stand on their own
|
|
74
|
+
// since this effect only re-runs when drawerPinned itself changes.
|
|
75
|
+
$effect(() => {
|
|
76
|
+
mobileMenuOpen = drawerPinned
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
function toggleMobileMenu() {
|
|
80
|
+
mobileMenuOpen = !mobileMenuOpen
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function closeMobileMenu() {
|
|
84
|
+
mobileMenuOpen = false
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function handleNavClick(item: NavItem) {
|
|
88
|
+
item.onClick?.()
|
|
89
|
+
closeMobileMenu()
|
|
90
|
+
}
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<nav
|
|
94
|
+
class="topnav {className}"
|
|
95
|
+
class:topnav--force-collapse={collapse === "always"}
|
|
96
|
+
class:topnav--force-expand={collapse === "never"}
|
|
97
|
+
class:topnav--drawer-pinned={drawerPinned}
|
|
98
|
+
style="height: {height}px; --topnav-toggle-size: {menuToggleSize}px; {style}"
|
|
99
|
+
>
|
|
100
|
+
<div class="topnav-container">
|
|
101
|
+
{#if hasDrawerContent}
|
|
102
|
+
<div class="topnav-menu-toggle">
|
|
103
|
+
{#if menuToggleTemplate}
|
|
104
|
+
{@render menuToggleTemplate({open: mobileMenuOpen, toggle: toggleMobileMenu})}
|
|
105
|
+
{:else}
|
|
106
|
+
<button
|
|
107
|
+
type="button"
|
|
108
|
+
class="mobile-menu-toggle"
|
|
109
|
+
onclick={toggleMobileMenu}
|
|
110
|
+
aria-label={mobileMenuOpen ? "Close menu" : "Open menu"}
|
|
111
|
+
aria-expanded={mobileMenuOpen}
|
|
112
|
+
>
|
|
113
|
+
{#if mobileMenuOpen}
|
|
114
|
+
<DismissIcon size={Math.round(menuToggleSize * 0.48)} />
|
|
115
|
+
{:else}
|
|
116
|
+
<span class="hamburger-glyph">☰</span>
|
|
117
|
+
{/if}
|
|
118
|
+
</button>
|
|
119
|
+
{/if}
|
|
120
|
+
</div>
|
|
121
|
+
{/if}
|
|
122
|
+
|
|
123
|
+
{#if brandTemplate}
|
|
124
|
+
{@render brandTemplate()}
|
|
125
|
+
{:else}
|
|
126
|
+
<a href={brandHref} class="topnav-brand">
|
|
127
|
+
{brand}
|
|
128
|
+
</a>
|
|
129
|
+
{/if}
|
|
130
|
+
|
|
131
|
+
<div class="topnav-trailing">
|
|
132
|
+
{#if items.length > 0}
|
|
133
|
+
<div class="topnav-items">
|
|
134
|
+
{#each items as item}
|
|
135
|
+
<a
|
|
136
|
+
href={item.href}
|
|
137
|
+
class="nav-item"
|
|
138
|
+
onclick={() => handleNavClick(item)}
|
|
139
|
+
>
|
|
140
|
+
{#if item.icon}
|
|
141
|
+
<span class="nav-icon">{item.icon}</span>
|
|
142
|
+
{/if}
|
|
143
|
+
<span class="nav-text">{item.label}</span>
|
|
144
|
+
</a>
|
|
145
|
+
{/each}
|
|
146
|
+
</div>
|
|
147
|
+
{/if}
|
|
148
|
+
|
|
149
|
+
{#if children}
|
|
150
|
+
{#if items.length > 0}
|
|
151
|
+
<div class="nav-divider"></div>
|
|
152
|
+
{/if}
|
|
153
|
+
<div class="topnav-actions">
|
|
154
|
+
{@render children()}
|
|
155
|
+
</div>
|
|
156
|
+
{/if}
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
</nav>
|
|
160
|
+
|
|
161
|
+
{#if hasDrawerContent}
|
|
162
|
+
<Panel
|
|
163
|
+
bind:open={mobileMenuOpen}
|
|
164
|
+
side="start"
|
|
165
|
+
width={drawerWidth}
|
|
166
|
+
top="{height}px"
|
|
167
|
+
pinned={drawerPinned}
|
|
168
|
+
class="topnav-drawer {drawerPinned ? 'topnav-drawer--pinned' : ''}"
|
|
169
|
+
>
|
|
170
|
+
<div class="topnav-drawer-body">
|
|
171
|
+
{#if items.length > 0}
|
|
172
|
+
<div class="topnav-drawer-items">
|
|
173
|
+
{#each items as item}
|
|
174
|
+
<a
|
|
175
|
+
href={item.href}
|
|
176
|
+
class="nav-item"
|
|
177
|
+
onclick={() => handleNavClick(item)}
|
|
178
|
+
>
|
|
179
|
+
{#if item.icon}
|
|
180
|
+
<span class="nav-icon">{item.icon}</span>
|
|
181
|
+
{/if}
|
|
182
|
+
<span class="nav-text">{item.label}</span>
|
|
183
|
+
</a>
|
|
184
|
+
{/each}
|
|
185
|
+
</div>
|
|
186
|
+
{/if}
|
|
187
|
+
|
|
188
|
+
{#if navigationGroups.length > 0}
|
|
189
|
+
{#if items.length > 0}
|
|
190
|
+
<hr class="topnav-drawer-separator" />
|
|
191
|
+
{/if}
|
|
192
|
+
<NavMenu>
|
|
193
|
+
{#each navigationGroups as group}
|
|
194
|
+
<NavGroup>
|
|
195
|
+
{#snippet linkIcon()}
|
|
196
|
+
<span class="nav-icon">{group.icon}</span>
|
|
197
|
+
{/snippet}
|
|
198
|
+
{#snippet linkText()}
|
|
199
|
+
{group.title}
|
|
200
|
+
{/snippet}
|
|
201
|
+
|
|
202
|
+
{#each group.items as item}
|
|
203
|
+
<NavLinkItem href={item.href}>{item.label}</NavLinkItem>
|
|
204
|
+
{/each}
|
|
205
|
+
</NavGroup>
|
|
206
|
+
{/each}
|
|
207
|
+
</NavMenu>
|
|
208
|
+
{/if}
|
|
209
|
+
|
|
210
|
+
{#if drawerContent}
|
|
211
|
+
{#if items.length > 0 || navigationGroups.length > 0}
|
|
212
|
+
<hr class="topnav-drawer-separator" />
|
|
213
|
+
{/if}
|
|
214
|
+
{@render drawerContent(closeMobileMenu)}
|
|
215
|
+
{/if}
|
|
216
|
+
</div>
|
|
217
|
+
</Panel>
|
|
218
|
+
{/if}
|
|
219
|
+
|
|
220
|
+
<style>
|
|
221
|
+
.topnav {
|
|
222
|
+
display: flex;
|
|
223
|
+
align-items: center;
|
|
224
|
+
background: var(--neutral-layer-1, #ffffff);
|
|
225
|
+
border-bottom: 1px solid var(--neutral-stroke-layer-rest, #e0e0e0);
|
|
226
|
+
padding: 0 0.5rem;
|
|
227
|
+
container-type: inline-size;
|
|
228
|
+
container-name: topnav;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.topnav-container {
|
|
232
|
+
display: flex;
|
|
233
|
+
align-items: center;
|
|
234
|
+
width: 100%;
|
|
235
|
+
position: relative;
|
|
236
|
+
gap: 1rem;
|
|
237
|
+
min-width: 0;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.topnav-brand {
|
|
241
|
+
text-decoration: none;
|
|
242
|
+
color: inherit;
|
|
243
|
+
font-size: 1.25rem;
|
|
244
|
+
font-weight: 600;
|
|
245
|
+
flex-shrink: 0;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* Wrapper slot — owns visibility + position so a custom menuToggleTemplate
|
|
249
|
+
gets the same collapse behavior as the default button without consumers
|
|
250
|
+
needing to know about the internal rules. */
|
|
251
|
+
.topnav-menu-toggle {
|
|
252
|
+
display: none;
|
|
253
|
+
order: -1;
|
|
254
|
+
flex-shrink: 0;
|
|
255
|
+
align-items: center;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* Default toggle — plain icon target, no button chrome. Sized via
|
|
259
|
+
--topnav-toggle-size (set inline from the menuToggleSize prop).
|
|
260
|
+
Custom templates render at their natural size. */
|
|
261
|
+
.mobile-menu-toggle {
|
|
262
|
+
width: var(--topnav-toggle-size, 42px);
|
|
263
|
+
height: var(--topnav-toggle-size, 42px);
|
|
264
|
+
display: inline-flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
justify-content: center;
|
|
267
|
+
padding: 0;
|
|
268
|
+
background: transparent;
|
|
269
|
+
border: none;
|
|
270
|
+
color: inherit;
|
|
271
|
+
cursor: pointer;
|
|
272
|
+
border-radius: var(--fluent-border-radius-md, 4px);
|
|
273
|
+
transition: opacity 0.15s, background-color 0.15s;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.mobile-menu-toggle:hover {
|
|
277
|
+
opacity: 0.7;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.mobile-menu-toggle:focus-visible {
|
|
281
|
+
outline: 2px solid var(--accent-fill-rest, currentColor);
|
|
282
|
+
outline-offset: 2px;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.hamburger-glyph {
|
|
286
|
+
font-size: calc(var(--topnav-toggle-size, 42px) * 0.55);
|
|
287
|
+
line-height: 1;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* Trailing flex group: items + divider + actions. `margin-left: auto`
|
|
291
|
+
pushes it to the inline-end edge so brand stays next to hamburger
|
|
292
|
+
(or hugs the start edge when hamburger is hidden), instead of being
|
|
293
|
+
visually centered the way justify-content: space-between would do
|
|
294
|
+
with three flex children. */
|
|
295
|
+
.topnav-trailing {
|
|
296
|
+
display: flex;
|
|
297
|
+
align-items: center;
|
|
298
|
+
gap: 1.5rem;
|
|
299
|
+
min-width: 0;
|
|
300
|
+
margin-inline-start: auto;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.topnav-items {
|
|
304
|
+
display: flex;
|
|
305
|
+
gap: 1.5rem;
|
|
306
|
+
align-items: center;
|
|
307
|
+
min-width: 0;
|
|
308
|
+
overflow: hidden;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.nav-item {
|
|
312
|
+
text-decoration: none;
|
|
313
|
+
color: inherit;
|
|
314
|
+
display: flex;
|
|
315
|
+
align-items: center;
|
|
316
|
+
gap: 0.5rem;
|
|
317
|
+
padding: 0.5rem 0.75rem;
|
|
318
|
+
border-radius: var(--fluent-border-radius-md);
|
|
319
|
+
transition: background-color 0.2s;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.nav-item:hover {
|
|
323
|
+
background-color: var(--neutral-fill-stealth-hover, rgba(0, 0, 0, 0.05));
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.nav-icon {
|
|
327
|
+
font-size: 1.1rem;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.nav-divider {
|
|
331
|
+
width: 1px;
|
|
332
|
+
height: 24px;
|
|
333
|
+
background: var(--neutral-stroke-divider-rest, #e0e0e0);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.topnav-actions {
|
|
337
|
+
display: flex;
|
|
338
|
+
align-items: center;
|
|
339
|
+
gap: 0.5rem;
|
|
340
|
+
flex-shrink: 0;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/* Drawer styling — Panel handles position / transition / a11y */
|
|
344
|
+
.topnav-drawer-body {
|
|
345
|
+
flex: 1 1 0;
|
|
346
|
+
min-height: 0;
|
|
347
|
+
overflow-y: auto;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.topnav-drawer-items {
|
|
351
|
+
display: flex;
|
|
352
|
+
flex-direction: column;
|
|
353
|
+
gap: 0.125rem;
|
|
354
|
+
padding: 0 0.75rem;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.topnav-drawer-items .nav-item {
|
|
358
|
+
padding: 0.6rem 0.75rem;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.topnav-drawer-separator {
|
|
362
|
+
border: none;
|
|
363
|
+
border-top: 1px solid var(--neutral-stroke-divider-rest, #e0e0e0);
|
|
364
|
+
margin: 0.75rem 0;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
@container topnav (max-width: 960px) {
|
|
368
|
+
.topnav-menu-toggle {
|
|
369
|
+
display: flex;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.topnav-items,
|
|
373
|
+
.nav-divider {
|
|
374
|
+
display: none;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
@container topnav (max-width: 480px) {
|
|
379
|
+
.topnav-brand {
|
|
380
|
+
font-size: 1rem;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/* collapse="always" — force toggle visible + items hidden regardless of width */
|
|
385
|
+
.topnav--force-collapse .topnav-menu-toggle {
|
|
386
|
+
display: flex;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/* When drawer is pinned the toggle acts as a show/hide control for the
|
|
390
|
+
pinned rail itself, so it must stay visible at every width. */
|
|
391
|
+
.topnav--drawer-pinned .topnav-menu-toggle {
|
|
392
|
+
display: flex;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.topnav--force-collapse .topnav-items,
|
|
396
|
+
.topnav--force-collapse .nav-divider {
|
|
397
|
+
display: none;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/* collapse="never" — force items/divider visible + toggle hidden regardless of width */
|
|
401
|
+
.topnav--force-expand .topnav-menu-toggle {
|
|
402
|
+
display: none;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.topnav--force-expand .topnav-items {
|
|
406
|
+
display: flex;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.topnav--force-expand .nav-divider {
|
|
410
|
+
display: block;
|
|
411
|
+
}
|
|
412
|
+
</style>
|