noph-ui 0.19.1 → 0.20.1

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.
@@ -1,7 +1,11 @@
1
1
  <script lang="ts">
2
2
  import Ripple from '../ripple/Ripple.svelte'
3
3
  import Tooltip from '../tooltip/Tooltip.svelte'
4
- import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements'
4
+ import type {
5
+ HTMLAnchorAttributes,
6
+ HTMLButtonAttributes,
7
+ MouseEventHandler,
8
+ } from 'svelte/elements'
5
9
  import type { ButtonProps } from './types.ts'
6
10
  import CircularProgress from '../progress/CircularProgress.svelte'
7
11
 
@@ -16,6 +20,11 @@
16
20
  loading = false,
17
21
  keepTooltipOnClick,
18
22
  loadingAriaLabel,
23
+ size = 's',
24
+ shape = 'round',
25
+ toggle = false,
26
+ selected = $bindable(false),
27
+ onclick,
19
28
  ...attributes
20
29
  }: ButtonProps = $props()
21
30
 
@@ -38,21 +47,21 @@
38
47
  <CircularProgress aria-label={loadingAriaLabel} indeterminate />
39
48
  </div>
40
49
  {/if}
41
- <div class="button-icon">
42
- {#if start}
50
+ {#if start}
51
+ <div class="button-icon">
43
52
  {@render start()}
44
- {/if}
45
- </div>
53
+ </div>
54
+ {/if}
46
55
  {#if children}
47
56
  <div class="children-wrapper">
48
57
  {@render children()}
49
58
  </div>
50
59
  {/if}
51
- <div class="button-icon">
52
- {#if end}
60
+ {#if end}
61
+ <div class="button-icon">
53
62
  {@render end()}
54
- {/if}
55
- </div>
63
+ </div>
64
+ {/if}
56
65
  {/snippet}
57
66
 
58
67
  {#if isButton(attributes) || disabled || loading}
@@ -61,9 +70,20 @@
61
70
  aria-describedby={title ? uid : attributes['aria-describedby']}
62
71
  aria-label={title || attributes['aria-label']}
63
72
  disabled={disabled || loading}
73
+ aria-pressed={selected}
64
74
  bind:this={element}
75
+ onclick={(event) => {
76
+ if (toggle) {
77
+ selected = !selected
78
+ }
79
+ ;(onclick as MouseEventHandler<HTMLButtonElement>)?.(event)
80
+ }}
65
81
  class={[
66
82
  'np-button',
83
+ size,
84
+ selected || loading ? 'square' : shape,
85
+ toggle ? 'toggle' : '',
86
+ selected ? 'selected' : '',
67
87
  loading ? 'np-loading' : '',
68
88
  disabled || loading ? `${variant}-disabled disabled` : `${variant} enabled`,
69
89
  attributes.class,
@@ -77,7 +97,7 @@
77
97
  aria-describedby={title ? uid : attributes['aria-describedby']}
78
98
  aria-label={title || attributes['aria-label']}
79
99
  bind:this={element}
80
- class={['np-button', 'enabled', variant, attributes.class]}
100
+ class={['np-button', size, selected ? 'square' : 'round', 'enabled', variant, attributes.class]}
81
101
  >
82
102
  {@render content()}
83
103
  </a>
@@ -95,7 +115,6 @@
95
115
  text-wrap: nowrap;
96
116
  }
97
117
  .circular-progress {
98
- --np-circular-progress-size: calc(var(--button-height) * 0.75);
99
118
  --np-circular-progress-color: color-mix(in srgb, var(--np-color-on-surface) 38%, transparent);
100
119
  position: absolute;
101
120
  top: 50%;
@@ -121,11 +140,95 @@
121
140
  overflow: hidden;
122
141
  font-weight: 500;
123
142
  text-decoration: none;
124
- font-size: var(--np-button-label-text-font-size, calc(var(--button-height) * 0.35));
125
- height: var(--button-height);
126
- padding-left: var(--np-button-padding-left, calc((var(--button-height) - 0.5rem) / 2));
127
- padding-right: var(--np-button-padding-right, calc((var(--button-height) - 0.5rem) / 2));
128
- gap: var(--np-button-gap, calc((var(--button-height) - 1.5rem) / 2));
143
+ transition:
144
+ background-color 150ms linear,
145
+ border-radius 150ms ease-in-out,
146
+ box-shadow 150ms linear;
147
+ }
148
+ .xs {
149
+ font-size: 0.875rem;
150
+ height: 2rem;
151
+ padding-inline: var(--np-button-padding, 0.75rem);
152
+ gap: var(--np-button-gap, 0.25rem);
153
+ --_icon-size: var(--np-button-icon-size, 1.25rem);
154
+ --np-circular-progress-size: 1.75rem;
155
+ }
156
+ .xs.round {
157
+ border-radius: 1rem;
158
+ }
159
+ .xs.square {
160
+ border-radius: var(--np-button-shape, 0.75rem);
161
+ }
162
+ .xs:active {
163
+ border-radius: 0.5rem;
164
+ }
165
+ .s {
166
+ font-size: 0.875rem;
167
+ height: 2.5rem;
168
+ padding-inline: var(--np-button-padding, 1rem);
169
+ gap: var(--np-button-gap, 0.5rem);
170
+ --_icon-size: var(--np-button-icon-size, 1.25rem);
171
+ --np-circular-progress-size: 2rem;
172
+ }
173
+ .s.round {
174
+ border-radius: 1.25rem;
175
+ }
176
+ .s.square {
177
+ border-radius: var(--np-button-shape, 0.75rem);
178
+ }
179
+ .s:active {
180
+ border-radius: 0.5rem;
181
+ }
182
+ .m {
183
+ font-size: 1rem;
184
+ height: 3.5rem;
185
+ padding-inline: var(--np-button-padding, 1.5rem);
186
+ gap: var(--np-button-gap, 0.5rem);
187
+ --_icon-size: var(--np-button-icon-size, 1.5rem);
188
+ --np-circular-progress-size: 3rem;
189
+ }
190
+ .m.round {
191
+ border-radius: 1.75rem;
192
+ }
193
+ .m.square {
194
+ border-radius: var(--np-button-shape, 1rem);
195
+ }
196
+ .m:active {
197
+ border-radius: 0.75rem;
198
+ }
199
+ .l {
200
+ font-size: 1.5rem;
201
+ height: 6rem;
202
+ padding-inline: var(--np-button-padding, 3rem);
203
+ gap: var(--np-button-gap, 0.75rem);
204
+ --_icon-size: var(--np-button-icon-size, 2rem);
205
+ --np-circular-progress-size: 5rem;
206
+ }
207
+ .l.round {
208
+ border-radius: 3rem;
209
+ }
210
+ .l.square {
211
+ border-radius: var(--np-button-shape, 1.75rem);
212
+ }
213
+ .l:active {
214
+ border-radius: 1rem;
215
+ }
216
+ .xl {
217
+ font-size: 2rem;
218
+ height: 8.5rem;
219
+ padding-inline: var(--np-button-padding, 4rem);
220
+ gap: var(--np-button-gap, 1rem);
221
+ --_icon-size: var(--np-button-icon-size, 2.5rem);
222
+ --np-circular-progress-size: 7rem;
223
+ }
224
+ .xl.round {
225
+ border-radius: 4.25rem;
226
+ }
227
+ .xl.square {
228
+ border-radius: var(--np-button-shape, 1.75rem);
229
+ }
230
+ .xl:active {
231
+ border-radius: 1rem;
129
232
  }
130
233
  .disabled {
131
234
  pointer-events: none;
@@ -136,32 +239,11 @@
136
239
  .elevated-disabled {
137
240
  background-color: color-mix(in srgb, var(--np-color-on-surface) 12%, transparent);
138
241
  }
139
- .filled-disabled {
140
- --button-height: var(--np-filled-button-container-height, 2.5rem);
141
- border-radius: var(--np-filled-button-container-shape, var(--np-shape-corner-full));
142
- }
143
- .tonal-disabled {
144
- --button-height: var(--np-tonal-button-container-height, 2.5rem);
145
- border-radius: var(--np-tonal-button-container-shape, var(--np-shape-corner-full));
146
- }
147
- .elevated-disabled {
148
- --button-height: var(--np-elevated-button-container-height, 2.5rem);
149
- border-radius: var(--np-elevated-button-container-shape, var(--np-shape-corner-full));
150
- }
151
242
  .outlined-disabled {
152
- border: 1px solid;
153
- --button-height: var(--np-outlined-button-container-height, 2.5rem);
154
- border-color: color-mix(in srgb, var(--np-color-on-surface) 12%, transparent);
155
- border-radius: var(--np-outlined-button-container-shape, var(--np-shape-corner-full));
156
- }
157
- .text-disabled {
158
- --button-height: var(--np-text-button-container-height, 2.5rem);
159
- border-radius: var(--np-text-button-container-shape, var(--np-shape-corner-full));
160
- padding-left: calc((var(--button-height) - 1.5rem) / 2);
161
- padding-right: calc((var(--button-height) - 1.5rem) / 2);
162
- }
163
- .enabled {
164
- transition: background-color 0.3s ease;
243
+ outline-style: solid;
244
+ outline-color: color-mix(in srgb, var(--np-color-on-surface) 12%, transparent);
245
+ outline-width: 1px;
246
+ outline-offset: -1px;
165
247
  }
166
248
  .enabled:focus-visible {
167
249
  outline-style: solid;
@@ -182,25 +264,24 @@
182
264
  }
183
265
  }
184
266
  .text {
185
- --button-height: var(--np-text-button-container-height, 2.5rem);
186
267
  --np-ripple-hover-color: var(--np-text-button-label-text-color, var(--np-color-primary));
187
268
  --np-ripple-pressed-color: var(--np-text-button-label-text-color, var(--np-color-primary));
188
269
  color: var(--np-text-button-label-text-color, var(--np-color-primary));
189
- border-radius: var(--np-text-button-container-shape, var(--np-shape-corner-full));
190
- padding-left: calc((var(--button-height) - 1.5rem) / 2);
191
- padding-right: calc((var(--button-height) - 1.5rem) / 2);
192
270
  }
193
271
  .filled {
194
- --button-height: var(--np-filled-button-container-height, 2.5rem);
195
272
  --np-ripple-hover-opacity: 0.12;
196
273
  --np-ripple-hover-color: var(--np-color-surface);
197
274
  --np-ripple-pressed-color: var(--np-color-surface);
198
- transition:
199
- background-color 150ms linear,
200
- box-shadow 150ms linear;
201
275
  color: var(--np-filled-button-label-text-color, var(--np-color-on-primary));
202
276
  background-color: var(--np-filled-button-container-color, var(--np-color-primary));
203
- border-radius: var(--np-filled-button-container-shape, var(--np-shape-corner-full));
277
+ }
278
+ .filled.toggle {
279
+ background-color: var(--np-color-surface-container);
280
+ color: var(--np-color-on-surface-variant);
281
+ }
282
+ .filled.selected {
283
+ background-color: var(--np-color-primary);
284
+ color: var(--np-color-on-primary);
204
285
  }
205
286
  @media (hover: hover) {
206
287
  .filled:hover {
@@ -216,15 +297,14 @@
216
297
  }
217
298
 
218
299
  .tonal {
219
- transition:
220
- background-color 150ms linear,
221
- box-shadow 150ms linear;
222
- --button-height: var(--np-tonal-button-container-height, 2.5rem);
223
300
  --np-ripple-hover-color: var(--np-tonal-button-label-text-color, var(--np-color-primary));
224
301
  --np-ripple-pressed-color: var(--np-tonal-button-label-text-color, var(--np-color-primary));
225
302
  color: var(--np-tonal-button-label-text-color, var(--np-color-on-secondary-container));
226
303
  background-color: var(--np-tonal-button-container-color, var(--np-color-secondary-container));
227
- border-radius: var(--np-tonal-button-container-shape, var(--np-shape-corner-full));
304
+ }
305
+ .tonal.selected {
306
+ background-color: var(--np-color-secondary);
307
+ color: var(--np-color-on-secondary);
228
308
  }
229
309
 
230
310
  @media (hover: hover) {
@@ -241,10 +321,6 @@
241
321
  }
242
322
 
243
323
  .elevated {
244
- transition:
245
- background-color 150ms linear,
246
- box-shadow 150ms linear;
247
- --button-height: var(--np-elevated-button-container-height, 2.5rem);
248
324
  --np-ripple-hover-color: var(--np-elevated-button-label-text-color, var(--np-color-primary));
249
325
  --np-ripple-pressed-color: var(--np-elevated-button-label-text-color, var(--np-color-primary));
250
326
  color: var(--np-elevated-button-label-text-color, var(--np-color-primary));
@@ -253,7 +329,10 @@
253
329
  var(--np-color-surface-container-low)
254
330
  );
255
331
  box-shadow: var(--np-elevation-1);
256
- border-radius: var(--np-elevated-button-container-shape, var(--np-shape-corner-full));
332
+ }
333
+ .elevated.selected {
334
+ background-color: var(--np-color-primary);
335
+ color: var(--np-color-on-primary);
257
336
  }
258
337
 
259
338
  @media (hover: hover) {
@@ -266,13 +345,19 @@
266
345
  }
267
346
  .outlined {
268
347
  background-color: var(--np-outlined-button-container-color, transparent);
269
- border: 1px solid;
270
- --button-height: var(--np-outlined-button-container-height, 2.5rem);
348
+ outline-style: solid;
349
+ outline-color: var(--np-outlined-button-outline-color, var(--np-color-outline));
350
+ outline-width: 1px;
351
+ outline-offset: -1px;
271
352
  --np-ripple-hover-color: var(--np-outlined-button-label-text-color, var(--np-color-primary));
272
353
  --np-ripple-pressed-color: var(--np-outlined-button-label-text-color, var(--np-color-primary));
273
354
  color: var(--np-outlined-button-label-text-color, var(--np-color-primary));
274
- border-color: var(--np-outlined-button-outline-color, var(--np-color-outline));
275
- border-radius: var(--np-outlined-button-container-shape, var(--np-shape-corner-full));
355
+ }
356
+
357
+ .outlined.selected {
358
+ background-color: var(--np-color-inverse-surface);
359
+ color: var(--np-color-inverse-on-surface);
360
+ outline-style: none;
276
361
  }
277
362
  .button-icon {
278
363
  display: inline-flex;
@@ -281,7 +366,6 @@
281
366
  }
282
367
 
283
368
  :global(.np-button .button-icon) {
284
- --_icon-size: var(--np-button-icon-size, calc((var(--button-height) - 0.375rem) / 2));
285
369
  --_icon-color: var(--np-button-icon-color, inherit);
286
370
  }
287
371
 
@@ -1,4 +1,4 @@
1
1
  import type { ButtonProps } from './types.ts';
2
- declare const Button: import("svelte").Component<ButtonProps, {}, "element">;
2
+ declare const Button: import("svelte").Component<ButtonProps, {}, "element" | "selected">;
3
3
  type Button = ReturnType<typeof Button>;
4
4
  export default Button;
@@ -9,6 +9,10 @@ interface ButtonButtonProps extends HTMLButtonAttributes {
9
9
  loading?: boolean;
10
10
  loadingAriaLabel?: string;
11
11
  keepTooltipOnClick?: boolean;
12
+ size?: 'xs' | 's' | 'm' | 'l' | 'xl';
13
+ toggle?: boolean;
14
+ shape?: 'round' | 'square';
15
+ selected?: boolean;
12
16
  }
13
17
  interface ButtonAnchorProps extends HTMLAnchorAttributes {
14
18
  variant?: 'text' | 'filled' | 'outlined' | 'elevated' | 'tonal';
@@ -19,6 +23,10 @@ interface ButtonAnchorProps extends HTMLAnchorAttributes {
19
23
  disabled?: boolean;
20
24
  loading?: boolean;
21
25
  loadingAriaLabel?: string;
26
+ size?: 'xs' | 's' | 'm' | 'l' | 'xl';
27
+ toggle?: boolean;
28
+ shape?: 'round' | 'square';
29
+ selected?: boolean;
22
30
  }
23
31
  interface IconButtonButtonProps extends HTMLButtonAttributes {
24
32
  variant?: 'text' | 'filled' | 'outlined' | 'tonal';
@@ -13,18 +13,17 @@
13
13
  </script>
14
14
 
15
15
  <Button
16
+ size="xs"
17
+ shape="square"
16
18
  --np-elevated-button-container-shape="var(--np-assist-chip-container-shape, var(--np-shape-corner-small))"
17
19
  --np-outlined-button-container-shape="var(--np-assist-chip-container-shape, var(--np-shape-corner-small))"
18
20
  --np-elevated-button-label-text-color="var(--np-assist-chip-label-text-color, var(--np-color-on-surface-variant))"
19
21
  --np-outlined-button-label-text-color="var(--np-assist-chip-label-text-color, var(--np-color-on-surface-variant))"
20
22
  --np-outlined-button-outline-color="var(--np-assist-chip-outline-color, var(--np-color-outline-variant))"
21
- --np-elevated-button-container-height="2rem"
22
- --np-outlined-button-container-height="2rem"
23
- --np-button-label-text-font-size="0.875rem"
24
23
  --np-button-icon-size="1.125rem"
25
- --np-button-padding-left="0.5rem"
26
- --np-button-padding-right="0.5rem"
24
+ --np-button-padding="0.5rem 1rem"
27
25
  --np-button-gap="0.5rem"
26
+ --np-button-shape="0.5rem"
28
27
  --np-button-icon-color="var(--np-color-primary)"
29
28
  --np-outlined-button-container-color="var(--np-color-surface-container-low)"
30
29
  bind:element
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noph-ui",
3
- "version": "0.19.1",
3
+ "version": "0.20.1",
4
4
  "license": "MIT",
5
5
  "homepage": "https://noph.dev",
6
6
  "repository": {
@@ -15,6 +15,7 @@
15
15
  "svelte 5",
16
16
  "material",
17
17
  "material 3",
18
+ "expressive",
18
19
  "material you",
19
20
  "material expressive",
20
21
  "m3",