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.
- package/dist/animation.d.ts +26 -1
- package/dist/animation.js +50 -2
- package/dist/app-bar/AppBar.svelte +71 -7
- package/dist/app-bar/types.d.ts +6 -0
- package/dist/autocomplete/AutoComplete.svelte +6 -31
- package/dist/autocomplete/AutoComplete.svelte.d.ts +1 -1
- package/dist/badge/Badge.svelte +12 -4
- package/dist/badge/description.d.ts +4 -0
- package/dist/badge/description.js +4 -0
- package/dist/button/Button.svelte +55 -20
- package/dist/button/ButtonGroup.svelte +139 -19
- package/dist/button/ButtonGroup.svelte.d.ts +1 -1
- package/dist/button/IconButton.svelte +49 -18
- package/dist/button/SegmentedButton.svelte +44 -4
- package/dist/button/SplitButton.svelte +77 -3
- package/dist/button/SplitButton.svelte.d.ts +1 -1
- package/dist/button/buttonGroup.d.ts +0 -4
- package/dist/button/buttonGroup.js +0 -9
- package/dist/button/groupContext.d.ts +10 -0
- package/dist/button/groupContext.js +4 -0
- package/dist/button/types.d.ts +19 -0
- package/dist/checkbox/Checkbox.svelte +5 -0
- package/dist/chip/ChipSet.svelte +28 -2
- package/dist/chip/FilterChip.svelte +32 -4
- package/dist/chip/InputChip.svelte +127 -26
- package/dist/chip/SuggestionChip.svelte +6 -22
- package/dist/chip/SuggestionChip.svelte.d.ts +1 -2
- package/dist/chip/types.d.ts +8 -1
- package/dist/date-picker/Calendar.svelte +4 -2
- package/dist/date-picker/DatePickerDialog.svelte +1 -0
- package/dist/date-picker/DatePickerDialog.svelte.d.ts +1 -1
- package/dist/date-picker/DateRangePicker.svelte +1 -0
- package/dist/date-picker/DateRangePicker.svelte.d.ts +1 -1
- package/dist/date-picker/DockedDatePicker.svelte +12 -5
- package/dist/date-picker/DockedDatePicker.svelte.d.ts +1 -1
- package/dist/date-picker/DockedDateTimePicker.svelte +12 -5
- package/dist/date-picker/DockedDateTimePicker.svelte.d.ts +1 -1
- package/dist/date-picker/YearGrid.svelte +4 -2
- package/dist/dialog/Dialog.svelte +171 -33
- package/dist/dialog/Dialog.svelte.d.ts +2 -1
- package/dist/dialog/types.d.ts +6 -0
- package/dist/divider/Divider.svelte +36 -10
- package/dist/divider/types.d.ts +1 -0
- package/dist/fab/ExtendedFab.svelte +26 -60
- package/dist/fab/Fab.svelte +13 -48
- package/dist/fab/FabMenu.svelte +102 -44
- package/dist/fab/FabMenu.svelte.d.ts +2 -1
- package/dist/fab/FabMenuItem.svelte +8 -0
- package/dist/fab/FabMenuItem.svelte.d.ts +4 -0
- package/dist/fab/index.d.ts +1 -0
- package/dist/fab/index.js +1 -0
- package/dist/fab/types.d.ts +6 -4
- package/dist/icons/MenuIcon.svelte +13 -0
- package/dist/icons/MenuIcon.svelte.d.ts +7 -0
- package/dist/icons/MenuOpenIcon.svelte +15 -0
- package/dist/icons/MenuOpenIcon.svelte.d.ts +7 -0
- package/dist/icons/index.d.ts +2 -0
- package/dist/icons/index.js +2 -0
- package/dist/internal/exit.css +47 -0
- package/dist/internal/fieldTypes.d.ts +6 -0
- package/dist/internal/focus-ring.css +4 -0
- package/dist/internal/interest.css +3 -1
- package/dist/keyboard-nav.d.ts +12 -1
- package/dist/keyboard-nav.js +104 -14
- package/dist/list/Item.svelte +52 -6
- package/dist/list/List.svelte +35 -2
- package/dist/list/ListItem.svelte +16 -2
- package/dist/list/context.d.ts +6 -0
- package/dist/list/context.js +4 -0
- package/dist/list/types.d.ts +7 -0
- package/dist/media.d.ts +1 -0
- package/dist/media.js +1 -0
- package/dist/menu/Menu.svelte +70 -18
- package/dist/menu/Menu.svelte.d.ts +2 -1
- package/dist/menu/MenuItem.svelte +9 -3
- package/dist/menu/types.d.ts +7 -1
- package/dist/navigation-bar/NavigationBar.svelte +9 -3
- package/dist/navigation-bar/NavigationBarItem.svelte +29 -13
- package/dist/navigation-drawer/NavigationDrawer.svelte +96 -20
- package/dist/navigation-drawer/NavigationDrawer.svelte.d.ts +2 -1
- package/dist/navigation-drawer/NavigationDrawerItem.svelte +8 -3
- package/dist/navigation-drawer/NavigationDrawerSection.svelte +49 -0
- package/dist/navigation-drawer/NavigationDrawerSection.svelte.d.ts +4 -0
- package/dist/navigation-drawer/index.d.ts +1 -0
- package/dist/navigation-drawer/index.js +1 -0
- package/dist/navigation-drawer/types.d.ts +12 -0
- package/dist/navigation-rail/NavigationRail.svelte +367 -7
- package/dist/navigation-rail/NavigationRail.svelte.d.ts +1 -1
- package/dist/navigation-rail/NavigationRailItem.svelte +190 -53
- package/dist/navigation-rail/NavigationRailSection.svelte +57 -0
- package/dist/navigation-rail/NavigationRailSection.svelte.d.ts +4 -0
- package/dist/navigation-rail/context.d.ts +6 -0
- package/dist/navigation-rail/context.js +5 -0
- package/dist/navigation-rail/index.d.ts +1 -0
- package/dist/navigation-rail/index.js +1 -0
- package/dist/navigation-rail/morph.d.ts +14 -0
- package/dist/navigation-rail/morph.js +78 -0
- package/dist/navigation-rail/types.d.ts +21 -0
- package/dist/progress/CircularProgress.svelte +2 -1
- package/dist/progress/LinearProgress.svelte +48 -20
- package/dist/progress/types.d.ts +1 -0
- package/dist/radio/Radio.svelte +7 -1
- package/dist/search/Search.svelte +245 -58
- package/dist/search/types.d.ts +4 -0
- package/dist/select/NativeSelect.svelte +20 -12
- package/dist/select/Option.svelte +1 -2
- package/dist/select/Select.svelte +59 -140
- package/dist/select/VirtualList.svelte +16 -1
- package/dist/select/VirtualList.svelte.d.ts +6 -2
- package/dist/sheet/Sheet.svelte +223 -5
- package/dist/sheet/Sheet.svelte.d.ts +3 -1
- package/dist/sheet/types.d.ts +10 -0
- package/dist/slider/Slider.svelte +1 -27
- package/dist/snackbar/Snackbar.svelte +3 -0
- package/dist/snackbar/Snackbar.svelte.d.ts +2 -1
- package/dist/switch/Switch.svelte +51 -11
- package/dist/tabs/Tab.svelte +28 -14
- package/dist/tabs/Tabs.svelte +28 -4
- package/dist/tabs/types.d.ts +3 -0
- package/dist/text-field/TextField.svelte +49 -13
- package/dist/time-picker/DockedTimePicker.svelte +6 -1
- package/dist/time-picker/DockedTimePicker.svelte.d.ts +1 -1
- package/dist/time-picker/TimePickerDialog.svelte +1 -0
- package/dist/time-picker/TimePickerDialog.svelte.d.ts +1 -1
- package/dist/toolbar/Toolbar.svelte +21 -11
- package/dist/toolbar/types.d.ts +1 -0
- package/dist/tooltip/RichTooltip.svelte.d.ts +1 -1
- package/dist/tooltip/Tooltip.svelte +3 -1
- package/dist/tooltip/Tooltip.svelte.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import '../internal/exit.css'
|
|
3
|
+
import { exitAnimation } from '../animation.js'
|
|
4
|
+
import IconButton from '../button/IconButton.svelte'
|
|
2
5
|
import Divider from '../divider/Divider.svelte'
|
|
6
|
+
import CloseIcon from '../icons/CloseIcon.svelte'
|
|
3
7
|
import { syncOpenEffect } from '../popover.svelte.js'
|
|
4
8
|
import type { DialogProps } from './types.js'
|
|
5
9
|
|
|
6
10
|
let {
|
|
7
11
|
element = $bindable(),
|
|
8
12
|
open = $bindable(),
|
|
13
|
+
variant = 'basic',
|
|
14
|
+
closeLabel = 'Close',
|
|
9
15
|
quick = false,
|
|
10
16
|
children,
|
|
11
17
|
headline,
|
|
@@ -13,13 +19,18 @@
|
|
|
13
19
|
icon,
|
|
14
20
|
supportingText,
|
|
15
21
|
actions,
|
|
22
|
+
actionBar,
|
|
16
23
|
divider,
|
|
24
|
+
closedby = 'any',
|
|
25
|
+
role,
|
|
17
26
|
ontoggle,
|
|
27
|
+
oncancel,
|
|
18
28
|
'aria-labelledby': ariaLabelledby,
|
|
19
29
|
...attributes
|
|
20
30
|
}: DialogProps = $props()
|
|
21
31
|
|
|
22
32
|
const uid = $props.id()
|
|
33
|
+
let fullScreen = $derived(variant === 'full-screen')
|
|
23
34
|
|
|
24
35
|
export const show = () => {
|
|
25
36
|
if (element && !element.open) element.showModal()
|
|
@@ -37,50 +48,90 @@
|
|
|
37
48
|
)
|
|
38
49
|
</script>
|
|
39
50
|
|
|
51
|
+
{#snippet title()}
|
|
52
|
+
<svelte:element this={`h${headlineLevel}`} id="{uid}-dialog-headline" class="np-dialog-headline">
|
|
53
|
+
{headline}
|
|
54
|
+
</svelte:element>
|
|
55
|
+
{/snippet}
|
|
56
|
+
|
|
57
|
+
<!-- A basic dialog is an alert dialog on the web, as M3 asks; one that holds a task, like a
|
|
58
|
+
full-screen dialog or a picker, is a plain dialog. -->
|
|
40
59
|
<dialog
|
|
41
|
-
bind:this={element}
|
|
42
60
|
{...attributes}
|
|
43
|
-
|
|
61
|
+
bind:this={element}
|
|
62
|
+
{@attach !quick && exitAnimation}
|
|
63
|
+
{closedby}
|
|
64
|
+
role={role ?? (fullScreen ? 'dialog' : 'alertdialog')}
|
|
44
65
|
aria-labelledby={ariaLabelledby ?? (headline ? `${uid}-dialog-headline` : undefined)}
|
|
45
66
|
aria-describedby={supportingText ? `${uid}-dialog-supporting-text` : undefined}
|
|
46
|
-
class={[
|
|
67
|
+
class={[
|
|
68
|
+
'np-dialog-container',
|
|
69
|
+
fullScreen && 'np-dialog-full-screen',
|
|
70
|
+
!quick && 'np-animate np-exit-scrim',
|
|
71
|
+
attributes.class,
|
|
72
|
+
]}
|
|
47
73
|
ontoggle={(event) => {
|
|
48
74
|
open = event.newState === 'open'
|
|
49
75
|
ontoggle?.(event)
|
|
50
76
|
}}
|
|
77
|
+
oncancel={(event) => {
|
|
78
|
+
// Browsers without closedby still close on Escape.
|
|
79
|
+
if (closedby === 'none') event.preventDefault()
|
|
80
|
+
oncancel?.(event)
|
|
81
|
+
}}
|
|
51
82
|
onclick={(event) => {
|
|
52
83
|
attributes.onclick?.(event)
|
|
53
|
-
if (event.target === element) close()
|
|
84
|
+
if (event.target === element && closedby === 'any') close()
|
|
54
85
|
}}
|
|
55
86
|
>
|
|
56
87
|
<div class="np-dialog">
|
|
57
|
-
{#if
|
|
58
|
-
<div class="np-dialog-
|
|
59
|
-
{
|
|
88
|
+
{#if fullScreen}
|
|
89
|
+
<div class="np-dialog-header">
|
|
90
|
+
<IconButton type="button" aria-label={closeLabel} onclick={close}>
|
|
91
|
+
<CloseIcon />
|
|
92
|
+
</IconButton>
|
|
93
|
+
{#if headline}
|
|
94
|
+
{@render title()}
|
|
95
|
+
{/if}
|
|
96
|
+
{#if actions}
|
|
97
|
+
<div class="np-dialog-header-actions">{@render actions()}</div>
|
|
98
|
+
{/if}
|
|
60
99
|
</div>
|
|
100
|
+
{#if divider}
|
|
101
|
+
<Divider />
|
|
102
|
+
{/if}
|
|
103
|
+
{:else}
|
|
104
|
+
{#if icon}
|
|
105
|
+
<div class="np-dialog-icon">
|
|
106
|
+
{@render icon()}
|
|
107
|
+
</div>
|
|
108
|
+
{/if}
|
|
109
|
+
{#if headline}
|
|
110
|
+
<div class={['np-dialog-title', icon && 'np-dialog-title-centered']}>{@render title()}</div>
|
|
111
|
+
{/if}
|
|
112
|
+
{#if divider && (supportingText || children)}
|
|
113
|
+
<Divider style="margin-top: 1rem" --np-divider-color="var(--np-color-outline)" />
|
|
114
|
+
{/if}
|
|
61
115
|
{/if}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this={`h${headlineLevel}`}
|
|
65
|
-
id="{uid}-dialog-headline"
|
|
66
|
-
class="np-dialog-headline"
|
|
67
|
-
style={icon ? 'text-align: center' : ''}
|
|
68
|
-
>
|
|
69
|
-
{headline}
|
|
70
|
-
</svelte:element>
|
|
71
|
-
{/if}
|
|
72
|
-
{#if supportingText}
|
|
73
|
-
<p id="{uid}-dialog-supporting-text" class="np-dialog-supporting-text">{supportingText}</p>
|
|
74
|
-
{/if}
|
|
75
|
-
{#if divider}
|
|
76
|
-
<Divider style="margin-top: 1rem" --np-divider-color="var(--np-color-outline)" />
|
|
77
|
-
{/if}
|
|
78
|
-
{#if children}
|
|
116
|
+
<!-- Headline and actions stay put; everything between them scrolls. -->
|
|
117
|
+
{#if supportingText || children}
|
|
79
118
|
<div class="np-dialog-scroller">
|
|
80
|
-
{
|
|
119
|
+
{#if supportingText}
|
|
120
|
+
<p id="{uid}-dialog-supporting-text" class="np-dialog-supporting-text">
|
|
121
|
+
{supportingText}
|
|
122
|
+
</p>
|
|
123
|
+
{/if}
|
|
124
|
+
{@render children?.()}
|
|
81
125
|
</div>
|
|
82
126
|
{/if}
|
|
83
|
-
{#if
|
|
127
|
+
{#if fullScreen}
|
|
128
|
+
{#if actionBar}
|
|
129
|
+
<div class="np-dialog-action-bar">{@render actionBar()}</div>
|
|
130
|
+
{/if}
|
|
131
|
+
{:else if actions}
|
|
132
|
+
{#if divider && (supportingText || children)}
|
|
133
|
+
<Divider style="margin-bottom: 1rem" --np-divider-color="var(--np-color-outline)" />
|
|
134
|
+
{/if}
|
|
84
135
|
<div class="np-dialog-actions">
|
|
85
136
|
{@render actions()}
|
|
86
137
|
</div>
|
|
@@ -117,7 +168,9 @@
|
|
|
117
168
|
padding: var(--np-dialog-padding, 1.5rem);
|
|
118
169
|
border-radius: var(--np-dialog-container-shape, var(--np-shape-corner-extra-large));
|
|
119
170
|
box-shadow: var(--np-dialog-elevation, var(--np-elevation-3));
|
|
120
|
-
|
|
171
|
+
/* Its padding included, so it fits the window inside the container's own inset. */
|
|
172
|
+
box-sizing: border-box;
|
|
173
|
+
max-height: var(--np-dialog-max-height, calc(100dvh - 4rem));
|
|
121
174
|
scrollbar-color: var(--np-color-on-surface-variant) transparent;
|
|
122
175
|
scrollbar-width: thin;
|
|
123
176
|
position: relative;
|
|
@@ -138,33 +191,118 @@
|
|
|
138
191
|
opacity: 0.32;
|
|
139
192
|
}
|
|
140
193
|
|
|
194
|
+
/* It fades in, and closes like a menu: a short fade while it shrinks a little, its scrim
|
|
195
|
+
fading along. */
|
|
141
196
|
.np-animate {
|
|
197
|
+
--_exit: var(--np-motion-expressive-default-effects);
|
|
198
|
+
--np-exit-scrim-motion: var(--_exit);
|
|
142
199
|
transition:
|
|
143
|
-
opacity var(--
|
|
144
|
-
|
|
145
|
-
|
|
200
|
+
opacity var(--_exit),
|
|
201
|
+
scale var(--_exit),
|
|
202
|
+
display var(--_exit) allow-discrete,
|
|
203
|
+
overlay var(--_exit) allow-discrete;
|
|
146
204
|
opacity: 0;
|
|
147
205
|
}
|
|
148
206
|
.np-animate[open] {
|
|
207
|
+
--_enter: var(--np-motion-expressive-slow-effects);
|
|
208
|
+
transition:
|
|
209
|
+
opacity var(--_enter),
|
|
210
|
+
display var(--_enter) allow-discrete,
|
|
211
|
+
overlay var(--_enter) allow-discrete;
|
|
149
212
|
opacity: 1;
|
|
150
213
|
@starting-style {
|
|
151
214
|
opacity: 0;
|
|
152
215
|
}
|
|
153
216
|
}
|
|
217
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
218
|
+
.np-animate:not([open]) {
|
|
219
|
+
scale: 0.95;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
154
222
|
.np-animate::backdrop {
|
|
155
223
|
transition:
|
|
156
|
-
opacity var(--np-motion-expressive-
|
|
157
|
-
display var(--np-motion-expressive-
|
|
158
|
-
overlay var(--np-motion-expressive-
|
|
224
|
+
opacity var(--np-motion-expressive-default-effects),
|
|
225
|
+
display var(--np-motion-expressive-default-effects) allow-discrete,
|
|
226
|
+
overlay var(--np-motion-expressive-default-effects) allow-discrete;
|
|
159
227
|
opacity: 0;
|
|
160
228
|
}
|
|
161
229
|
.np-animate[open]::backdrop {
|
|
230
|
+
transition:
|
|
231
|
+
opacity var(--np-motion-expressive-slow-effects),
|
|
232
|
+
display var(--np-motion-expressive-slow-effects) allow-discrete,
|
|
233
|
+
overlay var(--np-motion-expressive-slow-effects) allow-discrete;
|
|
162
234
|
opacity: 0.32;
|
|
163
235
|
@starting-style {
|
|
164
236
|
opacity: 0;
|
|
165
237
|
}
|
|
166
238
|
}
|
|
167
239
|
|
|
240
|
+
.np-dialog-title-centered {
|
|
241
|
+
text-align: center;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* Full-screen: a 56dp header with the close button, headline and confirming action, the
|
|
245
|
+
content 24dp from the sides and an optional 56dp action bar. It fills a compact window and
|
|
246
|
+
floats, at most 560dp wide, on larger ones. */
|
|
247
|
+
.np-dialog-full-screen {
|
|
248
|
+
width: var(--np-dialog-container-width, 35rem);
|
|
249
|
+
}
|
|
250
|
+
.np-dialog-full-screen .np-dialog {
|
|
251
|
+
padding: 0;
|
|
252
|
+
}
|
|
253
|
+
.np-dialog-header {
|
|
254
|
+
flex: none;
|
|
255
|
+
display: flex;
|
|
256
|
+
align-items: center;
|
|
257
|
+
gap: 0.5rem;
|
|
258
|
+
min-height: 3.5rem;
|
|
259
|
+
padding-inline: 0.5rem 0.75rem;
|
|
260
|
+
--np-icon-button-icon-color: var(--np-color-on-surface);
|
|
261
|
+
}
|
|
262
|
+
.np-dialog-header .np-dialog-headline {
|
|
263
|
+
flex: 1;
|
|
264
|
+
min-width: 0;
|
|
265
|
+
margin: 0;
|
|
266
|
+
font-size: 1.375rem;
|
|
267
|
+
line-height: 1.75rem;
|
|
268
|
+
overflow: hidden;
|
|
269
|
+
text-overflow: ellipsis;
|
|
270
|
+
white-space: nowrap;
|
|
271
|
+
}
|
|
272
|
+
.np-dialog-header-actions {
|
|
273
|
+
display: flex;
|
|
274
|
+
gap: 0.5rem;
|
|
275
|
+
margin-inline-start: auto;
|
|
276
|
+
}
|
|
277
|
+
.np-dialog-full-screen .np-dialog-scroller {
|
|
278
|
+
padding: 1.5rem 1.5rem;
|
|
279
|
+
}
|
|
280
|
+
.np-dialog-action-bar {
|
|
281
|
+
flex: none;
|
|
282
|
+
display: flex;
|
|
283
|
+
align-items: center;
|
|
284
|
+
justify-content: flex-end;
|
|
285
|
+
gap: 0.5rem;
|
|
286
|
+
min-height: 3.5rem;
|
|
287
|
+
padding-inline: 1.5rem;
|
|
288
|
+
}
|
|
289
|
+
@media (width < 600px) {
|
|
290
|
+
.np-dialog-full-screen {
|
|
291
|
+
width: 100%;
|
|
292
|
+
height: 100%;
|
|
293
|
+
min-width: 0;
|
|
294
|
+
max-height: none;
|
|
295
|
+
margin: 0;
|
|
296
|
+
padding: 0;
|
|
297
|
+
}
|
|
298
|
+
.np-dialog-full-screen .np-dialog {
|
|
299
|
+
height: 100%;
|
|
300
|
+
max-height: none;
|
|
301
|
+
border-radius: 0;
|
|
302
|
+
box-shadow: none;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
168
306
|
.np-dialog-icon {
|
|
169
307
|
color: var(--np-color-secondary);
|
|
170
308
|
display: flex;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import '../internal/exit.css';
|
|
1
2
|
import type { DialogProps } from './types.js';
|
|
2
3
|
declare const Dialog: import("svelte").Component<DialogProps, {
|
|
3
4
|
show: () => void;
|
|
4
5
|
close: () => void;
|
|
5
|
-
}, "
|
|
6
|
+
}, "open" | "element">;
|
|
6
7
|
type Dialog = ReturnType<typeof Dialog>;
|
|
7
8
|
export default Dialog;
|
package/dist/dialog/types.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLDialogAttributes } from 'svelte/elements';
|
|
3
3
|
export interface DialogProps extends Omit<HTMLDialogAttributes, 'open'> {
|
|
4
|
+
/** A basic dialog floats over a scrim; a full-screen one fills a compact window. */
|
|
5
|
+
variant?: 'basic' | 'full-screen';
|
|
6
|
+
/** Names the close button of a full-screen dialog. */
|
|
7
|
+
closeLabel?: string;
|
|
8
|
+
/** The 56dp bar at the bottom of a full-screen dialog. */
|
|
9
|
+
actionBar?: Snippet;
|
|
4
10
|
icon?: Snippet;
|
|
5
11
|
headline?: string;
|
|
6
12
|
headlineLevel?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
@@ -1,31 +1,57 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { DividerProps } from './types.js'
|
|
3
3
|
|
|
4
|
-
let {
|
|
4
|
+
let {
|
|
5
|
+
variant = 'full',
|
|
6
|
+
orientation = 'horizontal',
|
|
7
|
+
element = $bindable(),
|
|
8
|
+
...attributes
|
|
9
|
+
}: DividerProps = $props()
|
|
5
10
|
</script>
|
|
6
11
|
|
|
7
12
|
<template
|
|
8
13
|
{...attributes}
|
|
9
14
|
bind:this={element}
|
|
10
15
|
role="separator"
|
|
11
|
-
|
|
16
|
+
aria-orientation={orientation === 'vertical' ? 'vertical' : undefined}
|
|
17
|
+
class={[
|
|
18
|
+
'np-divider',
|
|
19
|
+
variant,
|
|
20
|
+
orientation === 'vertical' && 'np-divider-vertical',
|
|
21
|
+
attributes.class,
|
|
22
|
+
]}
|
|
12
23
|
></template>
|
|
13
24
|
|
|
14
25
|
<style>
|
|
15
|
-
.
|
|
26
|
+
.np-divider {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-shrink: 0;
|
|
29
|
+
background-color: var(--np-divider-color, var(--np-color-outline-variant));
|
|
30
|
+
}
|
|
31
|
+
.np-divider:not(.np-divider-vertical) {
|
|
32
|
+
height: 1px;
|
|
33
|
+
}
|
|
34
|
+
.np-divider:not(.np-divider-vertical).full {
|
|
35
|
+
width: 100%;
|
|
36
|
+
}
|
|
37
|
+
.np-divider:not(.np-divider-vertical).inset {
|
|
16
38
|
width: calc(100% - 1rem);
|
|
17
39
|
margin-inline-start: 1rem;
|
|
18
40
|
}
|
|
19
|
-
.inset-middle {
|
|
41
|
+
.np-divider:not(.np-divider-vertical).inset-middle {
|
|
20
42
|
width: calc(100% - 2rem);
|
|
21
43
|
margin-inline: 1rem;
|
|
22
44
|
}
|
|
23
|
-
|
|
24
|
-
|
|
45
|
+
|
|
46
|
+
/* Takes the height of a flex or grid row. */
|
|
47
|
+
.np-divider-vertical {
|
|
48
|
+
width: 1px;
|
|
49
|
+
align-self: stretch;
|
|
25
50
|
}
|
|
26
|
-
.np-divider {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
51
|
+
.np-divider-vertical.inset {
|
|
52
|
+
margin-block-start: 1rem;
|
|
53
|
+
}
|
|
54
|
+
.np-divider-vertical.inset-middle {
|
|
55
|
+
margin-block: 1rem;
|
|
30
56
|
}
|
|
31
57
|
</style>
|
package/dist/divider/types.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import '../internal/focus-ring.css'
|
|
3
|
-
import { pressMorph } from '../press.svelte.js'
|
|
4
3
|
import Ripple from '../ripple/Ripple.svelte'
|
|
5
4
|
import Tooltip from '../tooltip/Tooltip.svelte'
|
|
6
5
|
import type { HTMLButtonAttributes } from 'svelte/elements'
|
|
@@ -9,9 +8,8 @@
|
|
|
9
8
|
let {
|
|
10
9
|
variant = 'primary-container',
|
|
11
10
|
size = 's',
|
|
12
|
-
shape = '
|
|
11
|
+
shape = 'square',
|
|
13
12
|
lowered = false,
|
|
14
|
-
disabled = false,
|
|
15
13
|
collapsed = false,
|
|
16
14
|
icon,
|
|
17
15
|
label,
|
|
@@ -21,16 +19,10 @@
|
|
|
21
19
|
|
|
22
20
|
const uid = $props.id()
|
|
23
21
|
|
|
24
|
-
let isLink = $derived(attributes.href != null
|
|
25
|
-
let tooltipId = $derived(collapsed && label
|
|
22
|
+
let isLink = $derived(attributes.href != null)
|
|
23
|
+
let tooltipId = $derived(collapsed && label ? uid : undefined)
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
morph.supersededBy(() => shape)
|
|
29
|
-
|
|
30
|
-
const handlePress = () => {
|
|
31
|
-
if (disabled) return
|
|
32
|
-
morph.press()
|
|
33
|
-
}
|
|
25
|
+
let tooltipNames = $derived(!!tooltipId && !attributes['aria-label'])
|
|
34
26
|
|
|
35
27
|
let classes = $derived([
|
|
36
28
|
'np-extended-fab',
|
|
@@ -40,15 +32,12 @@
|
|
|
40
32
|
shape,
|
|
41
33
|
lowered && 'np-fab-lowered',
|
|
42
34
|
collapsed && 'np-fab-collapsed',
|
|
43
|
-
morph.pressed && 'pressed',
|
|
44
35
|
attributes.class,
|
|
45
36
|
])
|
|
46
37
|
</script>
|
|
47
38
|
|
|
48
39
|
{#snippet content()}
|
|
49
|
-
{
|
|
50
|
-
<Ripple forElement={element} />
|
|
51
|
-
{/if}
|
|
40
|
+
<Ripple forElement={element} />
|
|
52
41
|
{#if icon}
|
|
53
42
|
<span class="np-fab-icon">{@render icon()}</span>
|
|
54
43
|
{/if}
|
|
@@ -60,14 +49,10 @@
|
|
|
60
49
|
{#if isLink}
|
|
61
50
|
<a
|
|
62
51
|
{...attributes}
|
|
63
|
-
onclick={(event) => {
|
|
64
|
-
handlePress()
|
|
65
|
-
attributes.onclick?.(event)
|
|
66
|
-
}}
|
|
67
52
|
bind:this={element}
|
|
68
|
-
aria-describedby={tooltipId
|
|
53
|
+
aria-describedby={(!tooltipNames && tooltipId) || attributes['aria-describedby']}
|
|
69
54
|
interestfor={tooltipId ?? attributes['interestfor']}
|
|
70
|
-
aria-label={
|
|
55
|
+
aria-label={attributes['aria-label'] ?? (collapsed ? label : undefined)}
|
|
71
56
|
class={classes}
|
|
72
57
|
>
|
|
73
58
|
{@render content()}
|
|
@@ -75,16 +60,11 @@
|
|
|
75
60
|
{:else}
|
|
76
61
|
<button
|
|
77
62
|
{...attributes as HTMLButtonAttributes}
|
|
78
|
-
onclick={(event) => {
|
|
79
|
-
handlePress()
|
|
80
|
-
attributes.onclick?.(event)
|
|
81
|
-
}}
|
|
82
63
|
bind:this={element}
|
|
83
|
-
aria-describedby={tooltipId
|
|
64
|
+
aria-describedby={(!tooltipNames && tooltipId) || attributes['aria-describedby']}
|
|
84
65
|
interestfor={tooltipId ?? attributes['interestfor']}
|
|
85
|
-
aria-label={
|
|
66
|
+
aria-label={attributes['aria-label'] ?? (collapsed ? label : undefined)}
|
|
86
67
|
type={(attributes['type'] as HTMLButtonAttributes['type']) ?? 'button'}
|
|
87
|
-
{disabled}
|
|
88
68
|
class={classes}
|
|
89
69
|
>
|
|
90
70
|
{@render content()}
|
|
@@ -129,19 +109,10 @@
|
|
|
129
109
|
.square {
|
|
130
110
|
border-radius: var(--np-fab-shape, var(--_square-radius));
|
|
131
111
|
}
|
|
132
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
133
|
-
.round:not(:disabled):is(:active, .pressed) {
|
|
134
|
-
border-radius: var(--np-fab-pressed-shape, var(--_square-radius));
|
|
135
|
-
}
|
|
136
|
-
.square:not(:disabled):is(:active, .pressed) {
|
|
137
|
-
border-radius: var(--np-fab-pressed-shape, calc(var(--_height) / 2));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
112
|
.s {
|
|
142
113
|
--_height: 3.5rem;
|
|
143
114
|
--_square-radius: 1rem;
|
|
144
|
-
--_gap: 0.
|
|
115
|
+
--_gap: 0.5rem;
|
|
145
116
|
--_padding: 1rem;
|
|
146
117
|
font-size: 1rem;
|
|
147
118
|
--np-icon-size: 1.5rem;
|
|
@@ -149,8 +120,9 @@
|
|
|
149
120
|
.m {
|
|
150
121
|
--_height: 5rem;
|
|
151
122
|
--_square-radius: 1.25rem;
|
|
152
|
-
--_gap:
|
|
153
|
-
--_padding: 1.
|
|
123
|
+
--_gap: 0.75rem;
|
|
124
|
+
--_padding: 1.625rem;
|
|
125
|
+
font-weight: 400;
|
|
154
126
|
font-size: 1.375rem;
|
|
155
127
|
--np-icon-size: 1.75rem;
|
|
156
128
|
}
|
|
@@ -158,15 +130,17 @@
|
|
|
158
130
|
--_height: 6rem;
|
|
159
131
|
--_square-radius: 1.75rem;
|
|
160
132
|
--_gap: 1rem;
|
|
161
|
-
--_padding:
|
|
133
|
+
--_padding: 1.75rem;
|
|
134
|
+
font-weight: 400;
|
|
162
135
|
font-size: 1.5rem;
|
|
163
136
|
--np-icon-size: 2.25rem;
|
|
164
137
|
}
|
|
165
138
|
|
|
139
|
+
/* Collapsed, the icon keeps its place at the start: the padding centres it in the square, and
|
|
140
|
+
only the gap and the label shrink, so the icon does not drift while the FAB changes width. */
|
|
166
141
|
.np-fab-collapsed {
|
|
167
142
|
width: var(--_height);
|
|
168
|
-
padding-inline:
|
|
169
|
-
justify-content: center;
|
|
143
|
+
padding-inline: calc((var(--_height) - var(--np-icon-size)) / 2);
|
|
170
144
|
gap: 0;
|
|
171
145
|
}
|
|
172
146
|
.np-fab-collapsed .np-fab-label {
|
|
@@ -175,25 +149,24 @@
|
|
|
175
149
|
}
|
|
176
150
|
|
|
177
151
|
.np-fab-label {
|
|
178
|
-
max-width:
|
|
152
|
+
max-width: max-content;
|
|
179
153
|
overflow: hidden;
|
|
180
|
-
text-overflow: ellipsis;
|
|
181
154
|
}
|
|
182
155
|
|
|
183
156
|
@media (prefers-reduced-motion: no-preference) {
|
|
184
157
|
.np-extended-fab {
|
|
185
158
|
transition:
|
|
186
|
-
width var(--np-motion-expressive-default-spatial),
|
|
187
|
-
gap var(--np-motion-expressive-default-spatial),
|
|
188
|
-
padding-inline var(--np-motion-expressive-default-spatial),
|
|
189
|
-
border-radius var(--np-motion-expressive-default-spatial),
|
|
159
|
+
width var(--np-fab-motion-spatial, var(--np-motion-expressive-default-spatial)),
|
|
160
|
+
gap var(--np-fab-motion-spatial, var(--np-motion-expressive-default-spatial)),
|
|
161
|
+
padding-inline var(--np-fab-motion-spatial, var(--np-motion-expressive-default-spatial)),
|
|
162
|
+
border-radius var(--np-fab-motion-spatial, var(--np-motion-expressive-default-spatial)),
|
|
190
163
|
box-shadow var(--np-motion-expressive-fast-effects),
|
|
191
164
|
background-color var(--np-motion-expressive-fast-effects);
|
|
192
165
|
}
|
|
193
166
|
.np-fab-label {
|
|
194
167
|
transition:
|
|
195
168
|
opacity var(--np-motion-expressive-fast-effects),
|
|
196
|
-
max-width var(--np-motion-expressive-default-spatial);
|
|
169
|
+
max-width var(--np-fab-motion-spatial, var(--np-motion-expressive-default-spatial));
|
|
197
170
|
}
|
|
198
171
|
}
|
|
199
172
|
|
|
@@ -227,21 +200,14 @@
|
|
|
227
200
|
}
|
|
228
201
|
|
|
229
202
|
@media (hover: hover) {
|
|
230
|
-
.np-extended-fab:
|
|
203
|
+
.np-extended-fab:hover {
|
|
231
204
|
box-shadow: var(--np-fab-elevation, var(--np-elevation-4));
|
|
232
205
|
}
|
|
233
|
-
.np-fab-lowered:
|
|
206
|
+
.np-fab-lowered:hover {
|
|
234
207
|
box-shadow: var(--np-fab-elevation, var(--np-elevation-2));
|
|
235
208
|
}
|
|
236
209
|
}
|
|
237
210
|
|
|
238
|
-
.np-extended-fab:disabled {
|
|
239
|
-
cursor: default;
|
|
240
|
-
box-shadow: none;
|
|
241
|
-
background-color: color-mix(in srgb, var(--np-color-on-surface) 12%, transparent);
|
|
242
|
-
color: color-mix(in srgb, var(--np-color-on-surface) 38%, transparent);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
211
|
.np-fab-icon {
|
|
246
212
|
display: flex;
|
|
247
213
|
flex: none;
|