noph-ui 0.51.2 → 0.52.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.
Files changed (130) hide show
  1. package/dist/animation.d.ts +26 -1
  2. package/dist/animation.js +50 -2
  3. package/dist/app-bar/AppBar.svelte +71 -7
  4. package/dist/app-bar/types.d.ts +6 -0
  5. package/dist/autocomplete/AutoComplete.svelte +6 -31
  6. package/dist/autocomplete/AutoComplete.svelte.d.ts +1 -1
  7. package/dist/badge/Badge.svelte +12 -4
  8. package/dist/badge/description.d.ts +4 -0
  9. package/dist/badge/description.js +4 -0
  10. package/dist/button/Button.svelte +55 -20
  11. package/dist/button/ButtonGroup.svelte +139 -19
  12. package/dist/button/ButtonGroup.svelte.d.ts +1 -1
  13. package/dist/button/IconButton.svelte +49 -18
  14. package/dist/button/SegmentedButton.svelte +44 -4
  15. package/dist/button/SplitButton.svelte +77 -3
  16. package/dist/button/SplitButton.svelte.d.ts +1 -1
  17. package/dist/button/buttonGroup.d.ts +0 -4
  18. package/dist/button/buttonGroup.js +0 -9
  19. package/dist/button/groupContext.d.ts +10 -0
  20. package/dist/button/groupContext.js +4 -0
  21. package/dist/button/types.d.ts +19 -0
  22. package/dist/checkbox/Checkbox.svelte +5 -0
  23. package/dist/chip/ChipSet.svelte +28 -2
  24. package/dist/chip/FilterChip.svelte +32 -4
  25. package/dist/chip/InputChip.svelte +127 -26
  26. package/dist/chip/SuggestionChip.svelte +6 -22
  27. package/dist/chip/SuggestionChip.svelte.d.ts +1 -2
  28. package/dist/chip/types.d.ts +8 -1
  29. package/dist/date-picker/Calendar.svelte +4 -2
  30. package/dist/date-picker/DatePickerDialog.svelte +1 -0
  31. package/dist/date-picker/DatePickerDialog.svelte.d.ts +1 -1
  32. package/dist/date-picker/DateRangePicker.svelte +1 -0
  33. package/dist/date-picker/DateRangePicker.svelte.d.ts +1 -1
  34. package/dist/date-picker/DockedDatePicker.svelte +12 -5
  35. package/dist/date-picker/DockedDatePicker.svelte.d.ts +1 -1
  36. package/dist/date-picker/DockedDateTimePicker.svelte +12 -5
  37. package/dist/date-picker/DockedDateTimePicker.svelte.d.ts +1 -1
  38. package/dist/date-picker/YearGrid.svelte +4 -2
  39. package/dist/dialog/Dialog.svelte +171 -33
  40. package/dist/dialog/Dialog.svelte.d.ts +2 -1
  41. package/dist/dialog/types.d.ts +6 -0
  42. package/dist/divider/Divider.svelte +36 -10
  43. package/dist/divider/types.d.ts +1 -0
  44. package/dist/fab/ExtendedFab.svelte +26 -60
  45. package/dist/fab/Fab.svelte +13 -48
  46. package/dist/fab/FabMenu.svelte +102 -44
  47. package/dist/fab/FabMenu.svelte.d.ts +2 -1
  48. package/dist/fab/FabMenuItem.svelte +8 -0
  49. package/dist/fab/FabMenuItem.svelte.d.ts +4 -0
  50. package/dist/fab/index.d.ts +1 -0
  51. package/dist/fab/index.js +1 -0
  52. package/dist/fab/types.d.ts +6 -4
  53. package/dist/icons/MenuIcon.svelte +13 -0
  54. package/dist/icons/MenuIcon.svelte.d.ts +7 -0
  55. package/dist/icons/MenuOpenIcon.svelte +15 -0
  56. package/dist/icons/MenuOpenIcon.svelte.d.ts +7 -0
  57. package/dist/icons/index.d.ts +2 -0
  58. package/dist/icons/index.js +2 -0
  59. package/dist/internal/exit.css +47 -0
  60. package/dist/internal/fieldTypes.d.ts +6 -0
  61. package/dist/internal/focus-ring.css +4 -0
  62. package/dist/internal/interest.css +3 -1
  63. package/dist/keyboard-nav.d.ts +12 -1
  64. package/dist/keyboard-nav.js +104 -14
  65. package/dist/list/Item.svelte +52 -6
  66. package/dist/list/List.svelte +35 -2
  67. package/dist/list/ListItem.svelte +16 -2
  68. package/dist/list/context.d.ts +6 -0
  69. package/dist/list/context.js +4 -0
  70. package/dist/list/types.d.ts +7 -0
  71. package/dist/media.d.ts +1 -0
  72. package/dist/media.js +1 -0
  73. package/dist/menu/Menu.svelte +70 -18
  74. package/dist/menu/Menu.svelte.d.ts +2 -1
  75. package/dist/menu/MenuItem.svelte +9 -3
  76. package/dist/menu/types.d.ts +7 -1
  77. package/dist/navigation-bar/NavigationBar.svelte +9 -3
  78. package/dist/navigation-bar/NavigationBarItem.svelte +29 -13
  79. package/dist/navigation-drawer/NavigationDrawer.svelte +96 -20
  80. package/dist/navigation-drawer/NavigationDrawer.svelte.d.ts +2 -1
  81. package/dist/navigation-drawer/NavigationDrawerItem.svelte +8 -3
  82. package/dist/navigation-drawer/NavigationDrawerSection.svelte +49 -0
  83. package/dist/navigation-drawer/NavigationDrawerSection.svelte.d.ts +4 -0
  84. package/dist/navigation-drawer/index.d.ts +1 -0
  85. package/dist/navigation-drawer/index.js +1 -0
  86. package/dist/navigation-drawer/types.d.ts +12 -0
  87. package/dist/navigation-rail/NavigationRail.svelte +367 -7
  88. package/dist/navigation-rail/NavigationRail.svelte.d.ts +1 -1
  89. package/dist/navigation-rail/NavigationRailItem.svelte +190 -53
  90. package/dist/navigation-rail/NavigationRailSection.svelte +57 -0
  91. package/dist/navigation-rail/NavigationRailSection.svelte.d.ts +4 -0
  92. package/dist/navigation-rail/context.d.ts +6 -0
  93. package/dist/navigation-rail/context.js +5 -0
  94. package/dist/navigation-rail/index.d.ts +1 -0
  95. package/dist/navigation-rail/index.js +1 -0
  96. package/dist/navigation-rail/morph.d.ts +14 -0
  97. package/dist/navigation-rail/morph.js +78 -0
  98. package/dist/navigation-rail/types.d.ts +21 -0
  99. package/dist/progress/CircularProgress.svelte +2 -1
  100. package/dist/progress/LinearProgress.svelte +48 -20
  101. package/dist/progress/types.d.ts +1 -0
  102. package/dist/radio/Radio.svelte +7 -1
  103. package/dist/search/Search.svelte +245 -58
  104. package/dist/search/types.d.ts +4 -0
  105. package/dist/select/NativeSelect.svelte +20 -12
  106. package/dist/select/Option.svelte +1 -2
  107. package/dist/select/Select.svelte +59 -140
  108. package/dist/select/VirtualList.svelte +16 -1
  109. package/dist/select/VirtualList.svelte.d.ts +6 -2
  110. package/dist/sheet/Sheet.svelte +223 -5
  111. package/dist/sheet/Sheet.svelte.d.ts +3 -1
  112. package/dist/sheet/types.d.ts +10 -0
  113. package/dist/slider/Slider.svelte +1 -27
  114. package/dist/snackbar/Snackbar.svelte +3 -0
  115. package/dist/snackbar/Snackbar.svelte.d.ts +2 -1
  116. package/dist/switch/Switch.svelte +51 -11
  117. package/dist/tabs/Tab.svelte +28 -14
  118. package/dist/tabs/Tabs.svelte +28 -4
  119. package/dist/tabs/types.d.ts +3 -0
  120. package/dist/text-field/TextField.svelte +49 -13
  121. package/dist/time-picker/DockedTimePicker.svelte +6 -1
  122. package/dist/time-picker/DockedTimePicker.svelte.d.ts +1 -1
  123. package/dist/time-picker/TimePickerDialog.svelte +1 -0
  124. package/dist/time-picker/TimePickerDialog.svelte.d.ts +1 -1
  125. package/dist/toolbar/Toolbar.svelte +21 -11
  126. package/dist/toolbar/types.d.ts +1 -0
  127. package/dist/tooltip/RichTooltip.svelte.d.ts +1 -1
  128. package/dist/tooltip/Tooltip.svelte +3 -1
  129. package/dist/tooltip/Tooltip.svelte.d.ts +1 -1
  130. package/package.json +1 -1
@@ -1,14 +1,62 @@
1
1
  <script lang="ts">
2
+ import { motionOf } from '../animation.js'
3
+ import IconButton from '../button/IconButton.svelte'
4
+ import MenuIcon from '../icons/MenuIcon.svelte'
5
+ import MenuOpenIcon from '../icons/MenuOpenIcon.svelte'
2
6
  import { arrowKeyNav, rovingTabindex } from '../keyboard-nav.js'
7
+ import { reducedMotion } from '../media.js'
8
+ import { flushSync, tick, untrack } from 'svelte'
9
+ import { setNavigationRailContext } from './context.js'
10
+ import { cancel, morph, resize } from './morph.js'
3
11
  import type { NavigationRailProps } from './types.js'
4
12
 
5
13
  let {
6
14
  children,
15
+ expanded = $bindable(false),
16
+ modal = false,
17
+ hideWhenCollapsed = false,
18
+ menu = false,
19
+ menuLabel = 'Menu',
20
+ alignment = 'top',
21
+ fab,
7
22
  element = $bindable(),
8
23
  onkeydown: userKeydown,
9
24
  ...attributes
10
25
  }: NavigationRailProps = $props()
11
26
 
27
+ const uid = $props.id()
28
+ let railId = $derived(attributes.id ?? `np-navigation-rail-${uid}`)
29
+
30
+ // `expanded` is what was asked for. The layout the items show follows it through an animation:
31
+ // the modal rail opens collapsed and morphs to expanded, and morphs back before it closes.
32
+ let layoutExpanded = $state(untrack(() => expanded && !modal))
33
+ let dialogOpen = $state(false)
34
+ let inlineHidden = $state(untrack(() => hideWhenCollapsed && (!expanded || modal)))
35
+ let closing = $derived(dialogOpen && !expanded)
36
+ // Where the modal rail opens: right over the collapsed rail, so it grows out of it, measured as
37
+ // it opens. Hidden when collapsed, it has nothing to grow out of and opens from the window's edge.
38
+ // (Measured rather than anchor positioned: Safari flickers when an anchored element in the top
39
+ // layer changes size every frame.)
40
+ let anchor: string | undefined = $state()
41
+ let fromRail = $derived(anchor !== undefined)
42
+
43
+ const measureRail = () => {
44
+ if (inlineHidden || !element) return undefined
45
+ const rect = element.getBoundingClientRect()
46
+ const rtl = getComputedStyle(element).direction === 'rtl'
47
+ const start = rtl ? document.documentElement.clientWidth - rect.right : rect.left
48
+ return `inset-block: ${rect.top}px auto; inset-inline-start: ${start}px; block-size: ${rect.height}px`
49
+ }
50
+
51
+ let dialog: HTMLDialogElement | undefined = $state()
52
+ let modalRail: HTMLElement | undefined = $state()
53
+
54
+ setNavigationRailContext({
55
+ get expanded() {
56
+ return layoutExpanded
57
+ },
58
+ })
59
+
12
60
  const attach = rovingTabindex('.np-navigation-action')
13
61
  const arrowHandler = arrowKeyNav('.np-navigation-action')
14
62
 
@@ -16,30 +64,342 @@
16
64
  userKeydown?.(event)
17
65
  if (!event.defaultPrevented) arrowHandler(event)
18
66
  }
67
+
68
+ const timing = (rail: HTMLElement) => motionOf(rail, '--np-motion-standard-fast-spatial')
69
+ // The modal sheet opens on a springier curve than its items and settles a moment after them.
70
+ const sheetTiming = (rail: HTMLElement) =>
71
+ motionOf(rail, '--np-motion-expressive-default-spatial')
72
+ // A colour has no place to spring to, so it changes on an effects curve.
73
+ const colorTiming = (rail: HTMLElement) => motionOf(rail, '--np-motion-standard-slow-effects')
74
+
75
+ // Applied at once, not on a later frame: a frame painted between the new layout and the start
76
+ // of its animation would flash the end state.
77
+ const setLayout = (next: boolean) => {
78
+ layoutExpanded = next
79
+ flushSync()
80
+ }
81
+
82
+ const toggleInline = async (next: boolean) => {
83
+ const rail = element
84
+ if (!rail || reducedMotion.current) {
85
+ inlineHidden = hideWhenCollapsed && !next
86
+ layoutExpanded = next
87
+ return
88
+ }
89
+ if (!hideWhenCollapsed) {
90
+ await morph(rail, () => setLayout(next), timing(rail))
91
+ return
92
+ }
93
+ if (next) {
94
+ inlineHidden = false
95
+ setLayout(true)
96
+ await resize(rail, true, timing(rail))
97
+ return
98
+ }
99
+ await resize(rail, false, timing(rail))
100
+ if (!expanded) {
101
+ inlineHidden = true
102
+ layoutExpanded = false
103
+ await tick()
104
+ }
105
+ cancel([rail])
106
+ }
107
+
108
+ // Opening, the modal rail grows out of the collapsed rail and takes on its own container colour;
109
+ // closing, it shrinks back into it. Without a collapsed rail it grows from and shrinks to nothing.
110
+ const animateModal = async (rail: HTMLElement, opening: boolean) => {
111
+ const own = opening ? sheetTiming(rail) : timing(rail)
112
+ if (!fromRail) {
113
+ await resize(rail, opening, own)
114
+ return
115
+ }
116
+ // morph cancels what runs on the rail, so the colour starts after it.
117
+ const done = morph(rail, () => setLayout(opening), timing(rail), own)
118
+ const colors = [
119
+ getComputedStyle(element!).backgroundColor,
120
+ getComputedStyle(rail).backgroundColor,
121
+ ]
122
+ rail.animate(
123
+ [{ backgroundColor: colors[opening ? 0 : 1] }, { backgroundColor: colors[opening ? 1 : 0] }],
124
+ { ...colorTiming(rail), fill: opening ? 'none' : 'forwards' },
125
+ )
126
+ await done
127
+ }
128
+
129
+ const openModal = async () => {
130
+ anchor = measureRail()
131
+ layoutExpanded = !fromRail
132
+ dialogOpen = true
133
+ flushSync()
134
+ if (dialog && !dialog.open) dialog.showModal()
135
+ if (!modalRail || reducedMotion.current) {
136
+ layoutExpanded = true
137
+ return
138
+ }
139
+ await animateModal(modalRail, true)
140
+ }
141
+
142
+ const closeModal = async () => {
143
+ if (!dialogOpen) return
144
+ if (modalRail && !reducedMotion.current) await animateModal(modalRail, false)
145
+ if (expanded) {
146
+ cancel([modalRail ?? null])
147
+ return
148
+ }
149
+ const hadFocus = dialog?.contains(document.activeElement) ?? false
150
+ dialog?.close()
151
+ dialogOpen = false
152
+ layoutExpanded = false
153
+ // The collapsed rail's menu button was rendered anew, so focus goes back to it by hand.
154
+ if (hadFocus) {
155
+ await tick()
156
+ element?.querySelector<HTMLElement>('.np-navigation-rail-menu button')?.focus()
157
+ }
158
+ }
159
+
160
+ // The first run only acts on a modal rail that starts expanded; the rest is set up already.
161
+ let shown = untrack(() => expanded && !modal)
162
+ $effect(() => {
163
+ const next = expanded
164
+ if (next === shown) return
165
+ shown = next
166
+ // Out of the effect, so the layout can be flushed synchronously.
167
+ queueMicrotask(() => {
168
+ if (modal) {
169
+ if (next) openModal()
170
+ else closeModal()
171
+ } else {
172
+ toggleInline(next)
173
+ }
174
+ })
175
+ })
19
176
  </script>
20
177
 
178
+ {#snippet content(controls: string)}
179
+ {#if menu || fab}
180
+ <div class="np-navigation-rail-header">
181
+ {#if menu}
182
+ <div class="np-navigation-rail-menu">
183
+ <IconButton
184
+ aria-label={menuLabel}
185
+ aria-expanded={expanded}
186
+ aria-controls={controls}
187
+ onclick={() => (expanded = !expanded)}
188
+ >
189
+ <span class="np-navigation-rail-menu-icons">
190
+ <span class={['np-navigation-rail-menu-icon', expanded && 'np-away']}>
191
+ <MenuIcon />
192
+ </span>
193
+ <span
194
+ class={[
195
+ 'np-navigation-rail-menu-icon',
196
+ 'np-navigation-rail-menu-open-icon',
197
+ !expanded && 'np-away',
198
+ ]}
199
+ >
200
+ <MenuOpenIcon />
201
+ </span>
202
+ </span>
203
+ </IconButton>
204
+ </div>
205
+ {/if}
206
+ {#if fab}
207
+ <div class="np-navigation-rail-fab">{@render fab({ expanded: layoutExpanded })}</div>
208
+ {/if}
209
+ </div>
210
+ {/if}
211
+ <div class="np-navigation-rail-items">
212
+ {@render children?.()}
213
+ </div>
214
+ {/snippet}
215
+
21
216
  <nav
22
217
  {...attributes}
23
218
  {@attach attach}
24
219
  bind:this={element}
25
- class={['np-navigation-rail', attributes.class]}
220
+ id={railId}
221
+ hidden={inlineHidden}
222
+ class={[
223
+ 'np-navigation-rail',
224
+ layoutExpanded && !dialogOpen && 'np-navigation-rail-expanded',
225
+ alignment === 'center' && 'np-navigation-rail-center',
226
+ attributes.class,
227
+ ]}
26
228
  onkeydown={handleKeydown}
27
229
  >
28
- {#if children}
29
- {@render children()}
230
+ {#if !dialogOpen}
231
+ {@render content(railId)}
30
232
  {/if}
31
233
  </nav>
32
234
 
235
+ {#if modal}
236
+ <dialog
237
+ bind:this={dialog}
238
+ id="{railId}-modal"
239
+ class={['np-navigation-rail-dialog', closing && 'np-closing']}
240
+ style={anchor}
241
+ aria-label={attributes['aria-label']}
242
+ oncancel={(event) => {
243
+ event.preventDefault()
244
+ expanded = false
245
+ }}
246
+ onclose={() => {
247
+ dialogOpen = false
248
+ expanded = false
249
+ }}
250
+ onkeydown={handleKeydown}
251
+ onclick={(event) => {
252
+ // A click on the dialog itself is a click on the scrim.
253
+ if (event.target === event.currentTarget) expanded = false
254
+ }}
255
+ >
256
+ {#if dialogOpen}
257
+ <nav
258
+ {@attach attach}
259
+ bind:this={modalRail}
260
+ aria-label={attributes['aria-label']}
261
+ class={[
262
+ 'np-navigation-rail',
263
+ 'np-navigation-rail-modal',
264
+ layoutExpanded && 'np-navigation-rail-expanded',
265
+ alignment === 'center' && 'np-navigation-rail-center',
266
+ ]}
267
+ >
268
+ {@render content(`${railId}-modal`)}
269
+ </nav>
270
+ {/if}
271
+ </dialog>
272
+ {/if}
273
+
33
274
  <style>
275
+ /* Collapsed and expanded share their insets: the menu icon sits 36px in, the FAB and the
276
+ active indicators 20px, so switching between them only changes the width. */
34
277
  .np-navigation-rail {
278
+ box-sizing: border-box;
279
+ display: flex;
280
+ flex-direction: column;
281
+ flex-shrink: 0;
282
+ width: 6rem;
283
+ padding-block: 2.75rem 0.5rem;
284
+ overflow-x: hidden;
35
285
  overflow-y: auto;
36
286
  z-index: 8;
37
- background-color: var(--np-color-surface);
287
+ background-color: var(--np-navigation-rail-container-color, var(--np-color-surface));
288
+ }
289
+ .np-navigation-rail[hidden] {
290
+ display: none;
291
+ }
292
+ .np-navigation-rail-expanded {
293
+ width: max-content;
294
+ min-width: 13.75rem;
295
+ max-width: 22.5rem;
296
+ }
297
+
298
+ .np-navigation-rail-header {
38
299
  display: flex;
39
300
  flex-direction: column;
40
- justify-content: space-between;
301
+ align-items: flex-start;
302
+ gap: 0.25rem;
303
+ padding-inline: 1.25rem;
304
+ margin-block-end: 2.5rem;
305
+ }
306
+ .np-navigation-rail-menu {
307
+ display: flex;
41
308
  align-items: center;
42
- width: 80px;
43
- gap: 0.75rem;
309
+ height: 3.5rem;
310
+ margin-inline-start: 0.5rem;
311
+ }
312
+ /* The menu icon turns half a circle while it swaps, as the rail morphs. */
313
+ .np-navigation-rail-menu-icons {
314
+ display: grid;
315
+ }
316
+ .np-navigation-rail-menu-icon {
317
+ grid-area: 1 / 1;
318
+ display: flex;
319
+ }
320
+ .np-navigation-rail-menu-icon.np-away {
321
+ opacity: 0;
322
+ rotate: 90deg;
323
+ }
324
+ .np-navigation-rail-menu-open-icon.np-away {
325
+ rotate: -90deg;
326
+ }
327
+ @media (prefers-reduced-motion: no-preference) {
328
+ .np-navigation-rail-menu-icon {
329
+ transition:
330
+ rotate var(--np-motion-standard-fast-spatial),
331
+ opacity var(--np-motion-standard-fast-effects);
332
+ }
333
+ }
334
+
335
+ .np-navigation-rail-fab {
336
+ display: flex;
337
+ /* An extended FAB grows and shrinks in step with the rail. */
338
+ --np-fab-motion-spatial: var(--np-motion-standard-fast-spatial);
339
+ /* A FAB nested in the rail rests at elevation level 0. */
340
+ --np-fab-elevation: none;
341
+ }
342
+
343
+ .np-navigation-rail-items {
344
+ display: flex;
345
+ flex-direction: column;
346
+ gap: 0.25rem;
347
+ }
348
+ .np-navigation-rail-expanded .np-navigation-rail-items {
349
+ gap: 0;
350
+ }
351
+ .np-navigation-rail-center .np-navigation-rail-items {
352
+ flex: 1;
353
+ justify-content: center;
354
+ }
355
+
356
+ /* The modal rail lies over the content along the leading edge, behind a scrim. */
357
+ .np-navigation-rail-dialog {
358
+ position: fixed;
359
+ inset-block: 0;
360
+ inset-inline: 0 auto;
361
+ width: auto;
362
+ max-width: none;
363
+ height: 100%;
364
+ max-height: none;
365
+ margin: 0;
366
+ padding: 0;
367
+ border: 0;
368
+ background: none;
369
+ color: inherit;
370
+ overflow: visible;
371
+ }
372
+ .np-navigation-rail-dialog[open] {
373
+ display: flex;
374
+ }
375
+ .np-navigation-rail-dialog::backdrop {
376
+ background-color: var(--np-color-scrim);
377
+ opacity: 0.32;
378
+ }
379
+ .np-navigation-rail-modal {
380
+ height: 100%;
381
+ background-color: var(
382
+ --np-navigation-rail-modal-container-color,
383
+ var(--np-color-surface-container)
384
+ );
385
+ border-start-end-radius: var(
386
+ --np-navigation-rail-modal-container-shape,
387
+ var(--np-shape-corner-large)
388
+ );
389
+ border-end-end-radius: var(
390
+ --np-navigation-rail-modal-container-shape,
391
+ var(--np-shape-corner-large)
392
+ );
393
+ }
394
+ .np-navigation-rail-dialog.np-closing::backdrop {
395
+ opacity: 0;
396
+ }
397
+ @media (prefers-reduced-motion: no-preference) {
398
+ .np-navigation-rail-dialog::backdrop {
399
+ transition: opacity var(--np-motion-expressive-slow-effects);
400
+ @starting-style {
401
+ opacity: 0;
402
+ }
403
+ }
44
404
  }
45
405
  </style>
@@ -1,4 +1,4 @@
1
1
  import type { NavigationRailProps } from './types.js';
2
- declare const NavigationRail: import("svelte").Component<NavigationRailProps, {}, "element">;
2
+ declare const NavigationRail: import("svelte").Component<NavigationRailProps, {}, "element" | "expanded">;
3
3
  type NavigationRail = ReturnType<typeof NavigationRail>;
4
4
  export default NavigationRail;