noph-ui 0.30.5 → 0.30.6

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.
@@ -2,6 +2,7 @@
2
2
  import CircularProgress from '../progress/CircularProgress.svelte'
3
3
  import Ripple from '../ripple/Ripple.svelte'
4
4
  import Tooltip from '../tooltip/Tooltip.svelte'
5
+ import { onMount } from 'svelte'
5
6
  import type { HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements'
6
7
  import type { ButtonProps } from './types.ts'
7
8
 
@@ -19,11 +20,27 @@
19
20
  shape = 'round',
20
21
  toggle = false,
21
22
  selected = $bindable(false),
22
- onclick,
23
23
  ...attributes
24
24
  }: ButtonProps = $props()
25
25
 
26
26
  const uid = $props.id()
27
+
28
+ let pressed = $state(false)
29
+ let pressedTimeout: ReturnType<typeof setTimeout>
30
+
31
+ const handlePress = () => {
32
+ if (disabled || loading) return
33
+ pressed = true
34
+ pressedTimeout = setTimeout(() => {
35
+ pressed = false
36
+ }, 100)
37
+ }
38
+
39
+ onMount(() => {
40
+ return () => {
41
+ clearTimeout(pressedTimeout)
42
+ }
43
+ })
27
44
  </script>
28
45
 
29
46
  {#snippet content()}
@@ -56,7 +73,10 @@
56
73
  <a
57
74
  {...attributes}
58
75
  onclick={(event) => {
59
- ;(onclick as MouseEventHandler<HTMLAnchorElement>)?.(event)
76
+ if (!toggle) {
77
+ handlePress()
78
+ }
79
+ attributes.onclick?.(event)
60
80
  }}
61
81
  aria-describedby={title ? uid : attributes['aria-describedby']}
62
82
  aria-label={title || attributes['aria-label']}
@@ -68,6 +88,7 @@
68
88
  toggle && 'toggle',
69
89
  'enabled',
70
90
  variant,
91
+ pressed && 'pressed',
71
92
  attributes.class,
72
93
  ]}
73
94
  >
@@ -86,8 +107,11 @@
86
107
  onclick={(event) => {
87
108
  if (toggle) {
88
109
  selected = !selected
110
+ } else {
111
+ handlePress()
89
112
  }
90
- ;(onclick as MouseEventHandler<HTMLButtonElement>)?.(event)
113
+ // prettier-ignore
114
+ ;(attributes.onclick as MouseEventHandler<HTMLButtonElement>)?.(event)
91
115
  }}
92
116
  class={[
93
117
  'np-button',
@@ -97,6 +121,7 @@
97
121
  selected && 'selected',
98
122
  loading && 'np-loading',
99
123
  disabled || loading ? `${variant}-disabled disabled` : `${variant} enabled`,
124
+ pressed && 'pressed',
100
125
  attributes.class,
101
126
  ]}
102
127
  >
@@ -144,7 +169,7 @@
144
169
  --np-icon-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
145
170
  transition:
146
171
  background-color 150ms linear,
147
- border-radius 150ms ease-in-out,
172
+ border-radius 100ms linear,
148
173
  box-shadow 150ms linear;
149
174
  }
150
175
  .xs {
@@ -161,7 +186,8 @@
161
186
  .xs.square {
162
187
  border-radius: var(--np-button-shape, 0.75rem);
163
188
  }
164
- .xs:active {
189
+ .xs:active,
190
+ .xs.pressed {
165
191
  border-radius: 0.5rem;
166
192
  }
167
193
  .s {
@@ -178,7 +204,8 @@
178
204
  .s.square {
179
205
  border-radius: var(--np-button-shape, 0.75rem);
180
206
  }
181
- .s:active {
207
+ .s:active,
208
+ .s.pressed {
182
209
  border-radius: 0.5rem;
183
210
  }
184
211
  .m {
@@ -195,7 +222,8 @@
195
222
  .m.square {
196
223
  border-radius: var(--np-button-shape, 1rem);
197
224
  }
198
- .m:active {
225
+ .m:active,
226
+ .m.pressed {
199
227
  border-radius: 0.75rem;
200
228
  }
201
229
  .l {
@@ -212,7 +240,8 @@
212
240
  .l.square {
213
241
  border-radius: var(--np-button-shape, 1.75rem);
214
242
  }
215
- .l:active {
243
+ .l:active,
244
+ .l.pressed {
216
245
  border-radius: 1rem;
217
246
  }
218
247
  .xl {
@@ -229,7 +258,8 @@
229
258
  .xl.square {
230
259
  border-radius: var(--np-button-shape, 1.75rem);
231
260
  }
232
- .xl:active {
261
+ .xl:active,
262
+ .xl.pressed {
233
263
  border-radius: 1rem;
234
264
  }
235
265
  .toggle {
@@ -2,6 +2,7 @@
2
2
  import CircularProgress from '../progress/CircularProgress.svelte'
3
3
  import Ripple from '../ripple/Ripple.svelte'
4
4
  import Tooltip from '../tooltip/Tooltip.svelte'
5
+ import { onMount } from 'svelte'
5
6
  import type { HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements'
6
7
  import type { IconButtonProps } from './types.ts'
7
8
 
@@ -19,12 +20,28 @@
19
20
  width = 'default',
20
21
  size = 's',
21
22
  shape = 'round',
22
- onclick,
23
23
  ...attributes
24
24
  }: IconButtonProps = $props()
25
25
 
26
26
  const uid = $props.id()
27
27
  let touchEl: HTMLSpanElement | undefined = $state()
28
+
29
+ let pressed = $state(false)
30
+ let pressedTimeout: ReturnType<typeof setTimeout>
31
+
32
+ const handlePress = () => {
33
+ if (disabled || loading) return
34
+ pressed = true
35
+ pressedTimeout = setTimeout(() => {
36
+ pressed = false
37
+ }, 100)
38
+ }
39
+
40
+ onMount(() => {
41
+ return () => {
42
+ clearTimeout(pressedTimeout)
43
+ }
44
+ })
28
45
  </script>
29
46
 
30
47
  {#snippet content()}
@@ -48,7 +65,10 @@
48
65
  <a
49
66
  {...attributes}
50
67
  onclick={(event) => {
51
- ;(onclick as MouseEventHandler<HTMLAnchorElement>)?.(event)
68
+ if (!toggle) {
69
+ handlePress()
70
+ }
71
+ attributes.onclick?.(event)
52
72
  }}
53
73
  aria-describedby={title ? uid : undefined}
54
74
  aria-label={title}
@@ -62,6 +82,7 @@
62
82
  'enabled',
63
83
  toggle && 'toggle',
64
84
  selected && 'selected',
85
+ pressed && 'pressed',
65
86
  attributes.class,
66
87
  ].filter(Boolean)}
67
88
  >
@@ -80,8 +101,11 @@
80
101
  onclick={(event) => {
81
102
  if (toggle) {
82
103
  selected = !selected
104
+ } else {
105
+ handlePress()
83
106
  }
84
- ;(onclick as MouseEventHandler<HTMLButtonElement>)?.(event)
107
+ // prettier-ignore
108
+ ;(attributes.onclick as MouseEventHandler<HTMLButtonElement>)?.(event)
85
109
  }}
86
110
  class={[
87
111
  'np-icon-button',
@@ -91,6 +115,7 @@
91
115
  disabled || loading ? `${variant}-disabled disabled` : `${variant} enabled`,
92
116
  toggle && 'toggle',
93
117
  selected && 'selected',
118
+ pressed && 'pressed',
94
119
  attributes.class,
95
120
  ]}
96
121
  >
@@ -120,7 +145,7 @@
120
145
  --np-icon-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
121
146
  transition:
122
147
  background-color 150ms linear,
123
- border-radius 150ms ease-in-out;
148
+ border-radius 100ms linear;
124
149
  }
125
150
 
126
151
  :global(.np-icon-button svg) {
@@ -141,7 +166,8 @@
141
166
  .xs.square {
142
167
  border-radius: var(--np-icon-button-shape, 0.75rem);
143
168
  }
144
- .xs:active {
169
+ .xs:active,
170
+ .xs.pressed {
145
171
  border-radius: 0.5rem;
146
172
  }
147
173
  .xs.narrow {
@@ -168,7 +194,8 @@
168
194
  .s.wide {
169
195
  width: 3.25rem;
170
196
  }
171
- .s:active {
197
+ .s:active,
198
+ .s.pressed {
172
199
  border-radius: 0.5rem;
173
200
  }
174
201
  .m {
@@ -189,7 +216,8 @@
189
216
  .m.wide {
190
217
  width: 4.5rem;
191
218
  }
192
- .m:active {
219
+ .m:active,
220
+ .m.pressed {
193
221
  border-radius: 0.75rem;
194
222
  }
195
223
  .l {
@@ -210,7 +238,8 @@
210
238
  .l.wide {
211
239
  width: 8rem;
212
240
  }
213
- .l:active {
241
+ .l:active,
242
+ .l.pressed {
214
243
  border-radius: 1rem;
215
244
  }
216
245
  .xl {
@@ -231,7 +260,8 @@
231
260
  .xl.wide {
232
261
  width: 11.5rem;
233
262
  }
234
- .xl:active {
263
+ .xl:active,
264
+ .xl.pressed {
235
265
  border-radius: 1rem;
236
266
  }
237
267
 
@@ -1,5 +1,5 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { HTMLAttributes, HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
2
+ import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
3
3
  interface ButtonButtonProps extends HTMLButtonAttributes {
4
4
  variant?: 'text' | 'filled' | 'outlined' | 'elevated' | 'tonal';
5
5
  start?: Snippet | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noph-ui",
3
- "version": "0.30.5",
3
+ "version": "0.30.6",
4
4
  "license": "MIT",
5
5
  "homepage": "https://noph.dev",
6
6
  "repository": {