bref-ui 2.0.0 → 2.1.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 (109) hide show
  1. package/dist/button/button.svelte +67 -47
  2. package/dist/button/types.d.ts +1 -0
  3. package/dist/checkbox/checkbox.svelte +40 -35
  4. package/dist/combobox/combobox.svelte +2 -3
  5. package/dist/combobox/input.svelte +1 -1
  6. package/dist/combobox/list.svelte +5 -5
  7. package/dist/combobox/option.svelte +29 -9
  8. package/dist/dialog/dialog.svelte +15 -12
  9. package/dist/dialog/footer.svelte +2 -2
  10. package/dist/dialog/header.svelte +4 -4
  11. package/dist/icon/icon.svelte +6 -4
  12. package/dist/pill/content.svelte +11 -4
  13. package/dist/pill/content.svelte.d.ts +1 -1
  14. package/dist/pill/on-delete.svelte +42 -13
  15. package/dist/pill/pill.svelte +74 -94
  16. package/dist/pill/registry.json +1 -1
  17. package/dist/pill/types.d.ts +1 -0
  18. package/dist/pill-choice-group/pill-choice-group.svelte +19 -0
  19. package/dist/pill-choice-group/types.d.ts +1 -0
  20. package/dist/pill-group/pill-group.svelte +2 -0
  21. package/dist/pill-group/types.d.ts +1 -0
  22. package/dist/popover/popover.svelte +31 -6
  23. package/dist/popover/types.d.ts +1 -1
  24. package/dist/progress/progress.svelte +42 -55
  25. package/dist/select/empty.svelte +2 -3
  26. package/dist/select/list.svelte +2 -1
  27. package/dist/select/option.svelte +20 -6
  28. package/dist/select/select.svelte +7 -4
  29. package/dist/select/trigger.svelte +30 -7
  30. package/dist/spinner/spinner.svelte +8 -21
  31. package/dist/surface/surface.svelte +6 -1
  32. package/dist/surface/types.d.ts +2 -0
  33. package/dist/switch/switch.svelte +48 -51
  34. package/dist/text-area/registry.json +1 -1
  35. package/dist/text-area/text-area.svelte +33 -73
  36. package/dist/text-area/types.d.ts +1 -0
  37. package/dist/text-input/registry.json +1 -1
  38. package/dist/text-input/text-input.svelte +33 -73
  39. package/dist/text-input/types.d.ts +1 -0
  40. package/dist/theme/cli-theme.svelte +2 -0
  41. package/dist/theme/glass.svelte +60 -0
  42. package/dist/theme/glass.svelte.d.ts +26 -0
  43. package/dist/theme/registry.json +1 -0
  44. package/dist/theme/styles.svelte +6 -0
  45. package/dist/theme/surface.d.ts +1 -1
  46. package/dist/theme/surface.js +3 -2
  47. package/dist/theme/surfaces.svelte +23 -45
  48. package/dist/theme/theme.svelte +2 -0
  49. package/dist/tree-view/tree-node/chevron-button.svelte +9 -9
  50. package/dist/tree-view/tree-node/content.svelte +15 -12
  51. package/dist/tree-view/tree-node/delete-button.svelte +6 -5
  52. package/dist/tree-view/tree-node/tree-node.svelte +23 -24
  53. package/dist/tree-view/tree-view-section.svelte +9 -9
  54. package/dist/tree-view/tree-view.svelte +17 -9
  55. package/dist/tree-view/types.d.ts +2 -1
  56. package/package.json +30 -3
  57. package/readme.md +3 -1
  58. package/src/lib/button/button.svelte +67 -47
  59. package/src/lib/button/types.ts +1 -0
  60. package/src/lib/checkbox/checkbox.svelte +40 -35
  61. package/src/lib/combobox/combobox.svelte +2 -3
  62. package/src/lib/combobox/input.svelte +1 -1
  63. package/src/lib/combobox/list.svelte +5 -5
  64. package/src/lib/combobox/option.svelte +29 -9
  65. package/src/lib/dialog/dialog.svelte +15 -12
  66. package/src/lib/dialog/footer.svelte +2 -2
  67. package/src/lib/dialog/header.svelte +4 -4
  68. package/src/lib/icon/icon.svelte +6 -4
  69. package/src/lib/pill/content.svelte +11 -4
  70. package/src/lib/pill/on-delete.svelte +42 -13
  71. package/src/lib/pill/pill.svelte +74 -94
  72. package/src/lib/pill/registry.json +1 -1
  73. package/src/lib/pill/types.ts +1 -0
  74. package/src/lib/pill-choice-group/pill-choice-group.svelte +19 -0
  75. package/src/lib/pill-choice-group/types.ts +1 -0
  76. package/src/lib/pill-group/pill-group.svelte +2 -0
  77. package/src/lib/pill-group/types.ts +1 -0
  78. package/src/lib/popover/popover.svelte +31 -6
  79. package/src/lib/popover/types.ts +16 -1
  80. package/src/lib/progress/progress.svelte +42 -55
  81. package/src/lib/select/empty.svelte +2 -3
  82. package/src/lib/select/list.svelte +2 -1
  83. package/src/lib/select/option.svelte +20 -6
  84. package/src/lib/select/select.svelte +7 -4
  85. package/src/lib/select/trigger.svelte +30 -7
  86. package/src/lib/spinner/spinner.svelte +8 -21
  87. package/src/lib/surface/surface.svelte +6 -1
  88. package/src/lib/surface/types.ts +2 -0
  89. package/src/lib/switch/switch.svelte +48 -51
  90. package/src/lib/text-area/registry.json +1 -1
  91. package/src/lib/text-area/text-area.svelte +33 -73
  92. package/src/lib/text-area/types.ts +1 -0
  93. package/src/lib/text-input/registry.json +1 -1
  94. package/src/lib/text-input/text-input.svelte +33 -73
  95. package/src/lib/text-input/types.ts +1 -0
  96. package/src/lib/theme/cli-theme.svelte +2 -0
  97. package/src/lib/theme/glass.svelte +60 -0
  98. package/src/lib/theme/registry.json +1 -0
  99. package/src/lib/theme/styles.svelte +6 -0
  100. package/src/lib/theme/surface.ts +4 -2
  101. package/src/lib/theme/surfaces.svelte +23 -45
  102. package/src/lib/theme/theme.svelte +2 -0
  103. package/src/lib/tree-view/tree-node/chevron-button.svelte +9 -9
  104. package/src/lib/tree-view/tree-node/content.svelte +15 -12
  105. package/src/lib/tree-view/tree-node/delete-button.svelte +6 -5
  106. package/src/lib/tree-view/tree-node/tree-node.svelte +23 -24
  107. package/src/lib/tree-view/tree-view-section.svelte +9 -9
  108. package/src/lib/tree-view/tree-view.svelte +17 -9
  109. package/src/lib/tree-view/types.ts +2 -1
@@ -3,12 +3,13 @@
3
3
  import Icon from '../icon/icon.svelte';
4
4
  import { surface } from '../theme/surface.js';
5
5
  import type { ButtonProps } from './types.js';
6
- import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
6
+ import type { HTMLButtonAttributes } from 'svelte/elements';
7
7
 
8
8
  let {
9
9
  color = 'foreground',
10
10
  size = 'medium',
11
11
  variant = 'neutral',
12
+ glass = false,
12
13
  label,
13
14
  icon,
14
15
  trailingIcon,
@@ -22,9 +23,8 @@
22
23
  }: ButtonProps = $props();
23
24
 
24
25
  const isIcon = $derived(label === undefined);
25
- const isLink = $derived(href !== undefined);
26
26
  const common = $derived({
27
- class: ['button', surface({ variant, color, shadow: 'small', hover: 'medium' }), className],
27
+ class: ['button', surface({ variant, color, glass, hover: 'medium' }), className],
28
28
  'aria-label': attributes['aria-label'] ?? (isIcon ? (icon?.label ?? icon?.name) : undefined),
29
29
  'data-color': color,
30
30
  'data-size': size,
@@ -33,9 +33,24 @@
33
33
  'data-wide': wide && !isIcon ? '' : undefined,
34
34
  'data-rounded': rounded && isIcon ? '' : undefined
35
35
  });
36
+ const native = $derived(
37
+ href !== undefined
38
+ ? {
39
+ href: disabled ? undefined : href,
40
+ 'aria-disabled': disabled ? true : attributes['aria-disabled'],
41
+ tabindex: disabled ? -1 : attributes.tabindex
42
+ }
43
+ : { type: (attributes as HTMLButtonAttributes).type ?? 'button', disabled }
44
+ );
36
45
  </script>
37
46
 
38
- {#snippet content()}
47
+ <svelte:element
48
+ this={href !== undefined ? 'a' : 'button'}
49
+ {...attributes}
50
+ {...common}
51
+ {...native}
52
+ onclick={disabled && href !== undefined ? (event: MouseEvent) => event.preventDefault() : onClick}
53
+ >
39
54
  {#if icon}
40
55
  <span><Icon {...icon} color={undefined} label={undefined} /></span>
41
56
  {/if}
@@ -45,77 +60,64 @@
45
60
  <span><Icon {...trailingIcon} color={undefined} label={undefined} /></span>
46
61
  {/if}
47
62
  {/if}
48
- {/snippet}
49
-
50
- {#if isLink}
51
- <!-- eslint-disable svelte/no-navigation-without-resolve -- Native library links also support consumers outside SvelteKit. -->
52
- <a
53
- {...attributes as HTMLAnchorAttributes}
54
- {...common}
55
- href={disabled ? undefined : href}
56
- aria-disabled={disabled ? true : attributes['aria-disabled']}
57
- tabindex={disabled ? -1 : attributes.tabindex}
58
- onclick={disabled ? (event) => event.preventDefault() : onClick}
59
- >
60
- {@render content()}
61
- </a>
62
- <!-- eslint-enable svelte/no-navigation-without-resolve -->
63
- {:else}
64
- <button
65
- {...attributes as HTMLButtonAttributes}
66
- {...common}
67
- type={(attributes as HTMLButtonAttributes).type ?? 'button'}
68
- {disabled}
69
- onclick={onClick}
70
- >
71
- {@render content()}
72
- </button>
73
- {/if}
63
+ </svelte:element>
74
64
 
75
65
  <style>
76
66
  .button {
77
- --internal-height: max(48px, 3rem);
78
- --internal-padding: 1.125rem;
79
- --internal-icon-size: calc(var(--internal-height) / 2 + 0.25rem);
67
+ --internal-height: max(40px, 2.5rem);
68
+ --internal-target: 24px;
69
+ --internal-padding: 1rem;
70
+ --internal-icon-size: 1.25rem;
71
+ --internal-font-size: 1rem;
80
72
  box-sizing: border-box;
81
73
  display: inline-flex;
82
74
  align-items: center;
83
75
  justify-content: center;
84
- text-transform: capitalize;
85
76
  gap: 0.5rem;
86
- min-height: var(--internal-height);
87
- min-width: 24px;
77
+ min-height: max(var(--internal-height), var(--internal-target));
78
+ min-width: var(--internal-target);
88
79
  padding: 0.25rem var(--internal-padding);
89
- border-radius: 0.45rem;
80
+ border-radius: 0.625rem;
90
81
  font: inherit;
91
- font-size: 1rem;
82
+ font-size: var(--internal-font-size);
83
+ line-height: 1.25;
92
84
  text-decoration: none;
93
85
  }
94
86
  .button[data-size='x-small'] {
95
87
  --internal-height: max(28px, 1.75rem);
96
- --internal-padding: 0.5rem;
88
+ --internal-padding: 0.625rem;
89
+ --internal-icon-size: 1rem;
90
+ --internal-font-size: 0.8125rem;
97
91
  }
98
92
  .button[data-size='small'] {
99
- --internal-height: max(40px, 2.5rem);
100
- --internal-padding: 0.875rem;
93
+ --internal-height: max(32px, 2rem);
94
+ --internal-padding: 0.75rem;
95
+ --internal-icon-size: 1.125rem;
96
+ --internal-font-size: 0.875rem;
101
97
  }
102
98
  .button[data-size='large'] {
103
- --internal-height: max(64px, 4rem);
104
- --internal-padding: 1.5rem;
99
+ --internal-height: max(48px, 3rem);
100
+ --internal-padding: 1.25rem;
101
+ --internal-icon-size: 1.5rem;
105
102
  }
106
103
  .button[data-size='x-large'] {
107
- --internal-height: max(80px, 5rem);
108
- --internal-padding: 2rem;
104
+ --internal-height: max(56px, 3.5rem);
105
+ --internal-padding: 1.5rem;
106
+ --internal-icon-size: 1.75rem;
107
+ --internal-font-size: 1.125rem;
109
108
  }
110
109
  .button[data-kind='icon'] {
111
- width: var(--internal-height);
112
- height: var(--internal-height);
110
+ width: max(var(--internal-height), var(--internal-target));
111
+ height: max(var(--internal-height), var(--internal-target));
113
112
  padding: 0;
114
113
  font-size: var(--internal-icon-size);
115
114
  }
116
115
  span {
117
116
  display: inline-flex;
117
+ align-items: center;
118
+ flex-shrink: 0;
118
119
  font-size: var(--internal-icon-size);
120
+ line-height: 1;
119
121
  }
120
122
  .button[data-wide] {
121
123
  width: 100%;
@@ -123,4 +125,22 @@
123
125
  .button[data-rounded] {
124
126
  border-radius: 50%;
125
127
  }
128
+ .button:is(:disabled, [aria-disabled='true']) {
129
+ --surface-color: var(--color-muted, gray);
130
+ }
131
+ .button[data-variant='filled']:not(:disabled, [aria-disabled='true']):is(:hover, :focus-visible) {
132
+ filter: brightness(1.1);
133
+ }
134
+ .button[data-variant='filled']:not(:disabled, [aria-disabled='true']):is(
135
+ :active,
136
+ [aria-pressed='true'],
137
+ [data-surface-pressed='true']
138
+ ) {
139
+ filter: brightness(0.85);
140
+ }
141
+ @media (pointer: coarse) {
142
+ .button {
143
+ --internal-target: 44px;
144
+ }
145
+ }
126
146
  </style>
@@ -26,6 +26,7 @@ export type ButtonProps = {
26
26
  color?: Exclude<Color, 'background'>;
27
27
  size?: Size;
28
28
  variant?: Variant;
29
+ glass?: boolean;
29
30
  disabled?: boolean;
30
31
  onClick?: DOMAttributes<HTMLButtonElement | HTMLAnchorElement>['onclick'];
31
32
  } & Omit<DOMAttributes<HTMLButtonElement | HTMLAnchorElement>, 'children' | 'onclick'> & (TextButtonProps | IconButtonProps) & (HrefButtonProps | ClickButtonProps);
@@ -21,12 +21,24 @@
21
21
  --internal-size: 1.25rem;
22
22
  --internal-tint: var(--color-foreground, black);
23
23
  --internal-strength-light: 4%;
24
- --internal-strength-dark: 16%;
25
- --internal-border: light-dark(
26
- color-mix(in srgb, var(--color-foreground, black) 12%, transparent),
27
- color-mix(in srgb, var(--color-foreground, black) 30%, transparent)
24
+ --internal-strength-dark: 8%;
25
+ --internal-fill: light-dark(
26
+ color-mix(
27
+ in srgb,
28
+ var(--internal-tint) var(--internal-strength-light),
29
+ var(--color-background, white)
30
+ ),
31
+ color-mix(
32
+ in srgb,
33
+ var(--internal-tint) var(--internal-strength-dark),
34
+ var(--color-background, white)
35
+ )
36
+ );
37
+ --internal-border: color-mix(
38
+ in srgb,
39
+ var(--color-foreground, black) 48%,
40
+ var(--color-background, white)
28
41
  );
29
- --internal-highlight: color-mix(in srgb, var(--color-foreground, black) 12%, transparent);
30
42
  box-sizing: border-box;
31
43
  position: relative;
32
44
  display: inline-flex;
@@ -37,30 +49,14 @@
37
49
  block-size: var(--internal-size);
38
50
  border: 1px solid var(--internal-border);
39
51
  border-radius: calc(var(--internal-size) * 0.2);
40
- background: color-mix(
41
- in srgb,
42
- light-dark(
43
- color-mix(
44
- in srgb,
45
- var(--internal-tint) var(--internal-strength-light),
46
- var(--color-background, white)
47
- ),
48
- color-mix(
49
- in srgb,
50
- var(--internal-tint) var(--internal-strength-dark),
51
- var(--color-background, white)
52
- )
53
- )
54
- 85%,
55
- transparent
56
- );
57
- box-shadow: inset 0 1px 0 var(--internal-highlight);
52
+ background: var(--internal-fill);
58
53
  color: var(--color-foreground, black);
59
54
  font-size: calc(var(--internal-size) * 0.8);
60
55
  vertical-align: middle;
61
- transition: all 150ms ease;
62
- -webkit-backdrop-filter: blur(0.5rem) saturate(120%);
63
- backdrop-filter: blur(0.5rem) saturate(120%);
56
+ transition:
57
+ background-color 150ms ease,
58
+ border-color 150ms ease,
59
+ color 150ms ease;
64
60
  }
65
61
  input {
66
62
  position: absolute;
@@ -89,26 +85,35 @@
89
85
  --internal-size: 1.75rem;
90
86
  }
91
87
  div:has(input:hover:not(:disabled):not(:checked)) {
92
- --internal-strength-light: 6%;
93
- --internal-strength-dark: 20%;
88
+ --internal-strength-light: 8%;
89
+ --internal-strength-dark: 12%;
94
90
  }
95
91
  div:has(input:checked) {
96
92
  --internal-tint: var(--color-primary, blue);
97
93
  --internal-strength-light: 88%;
98
94
  --internal-strength-dark: 88%;
99
- --internal-border: color-mix(in srgb, var(--internal-tint) 68%, var(--color-foreground, black));
100
- --internal-highlight: color-mix(in srgb, var(--color-foreground, black) 28%, transparent);
101
- color: color-mix(in srgb, var(--color-background, white) 90%, var(--internal-tint));
95
+ --internal-border: var(--internal-fill);
96
+ color: var(--color-background, white);
102
97
  }
103
98
  div:has(input:checked:hover:not(:disabled)) {
104
99
  --internal-strength-light: 92%;
105
100
  --internal-strength-dark: 92%;
106
101
  }
102
+ div:has(input:active:not(:disabled)) {
103
+ --internal-strength-light: 12%;
104
+ --internal-strength-dark: 16%;
105
+ }
106
+ div:has(input:checked:active:not(:disabled)) {
107
+ --internal-strength-light: 96%;
108
+ --internal-strength-dark: 96%;
109
+ }
110
+ div:has(input:user-invalid),
111
+ div:has(input[aria-invalid='true']) {
112
+ --internal-border: var(--color-error, #bc2436);
113
+ }
107
114
  div:has(input:focus-visible) {
108
- --internal-border: color-mix(in srgb, var(--color-primary, blue) 55%, transparent);
109
- box-shadow:
110
- inset 0 1px 0 var(--internal-highlight),
111
- 0 0 0 3px color-mix(in srgb, var(--color-primary, blue) 16%, transparent);
115
+ outline: 2px solid var(--color-primary, blue);
116
+ outline-offset: 3px;
112
117
  }
113
118
  div:has(input:disabled) {
114
119
  opacity: 0.5;
@@ -91,9 +91,8 @@
91
91
  >
92
92
  <Popover
93
93
  bind:open={() => open, setOpen}
94
- variant="filled"
95
- spacing="small"
96
- radius="small"
94
+ spacing="x-small"
95
+ radius="0.75rem"
97
96
  shadow
98
97
  scroll
99
98
  disabled={disabled || !!attributes.readonly}
@@ -88,7 +88,7 @@
88
88
  ? undefined
89
89
  : selected.length === 1 && selected[0].icon
90
90
  ? { ...selected[0].icon }
91
- : undefined}
91
+ : { name: 'unfold_more' }}
92
92
  value={display}
93
93
  role="combobox"
94
94
  aria-autocomplete="list"
@@ -54,17 +54,17 @@
54
54
 
55
55
  <style>
56
56
  div {
57
- --internal-height: 2.5rem;
57
+ --internal-row-height: 2.125rem;
58
58
  --internal-icon-size: 1.25rem;
59
59
  display: grid;
60
- gap: 0.375rem;
60
+ gap: 0.125rem;
61
61
  }
62
62
  div[data-size='small'] {
63
- --internal-height: 2rem;
63
+ --internal-row-height: 1.875rem;
64
64
  --internal-icon-size: 1rem;
65
65
  }
66
66
  div[data-size='large'] {
67
- --internal-height: 3rem;
67
+ --internal-row-height: 2.375rem;
68
68
  --internal-icon-size: 1.5rem;
69
69
  }
70
70
  p {
@@ -72,7 +72,7 @@
72
72
  align-items: center;
73
73
  gap: 0.6rem;
74
74
  margin: 0;
75
- padding-block: 0.5rem;
75
+ padding: 0.5rem;
76
76
  color: var(--color-muted);
77
77
  }
78
78
  </style>
@@ -18,7 +18,7 @@
18
18
  >
19
19
  {#if item.icon}<span data-icon><Icon {...item.icon} /></span>{/if}
20
20
  <span data-label>{item.label}</span>
21
- {#if selected}<span data-icon><Icon name="check" /></span>{/if}
21
+ {#if selected}<span data-icon data-check><Icon name="check" /></span>{/if}
22
22
  </button>
23
23
 
24
24
  <style>
@@ -28,15 +28,16 @@
28
28
  align-items: center;
29
29
  gap: 0.6rem;
30
30
  width: 100%;
31
- min-height: var(--internal-height);
31
+ min-height: var(--internal-row-height);
32
32
  padding: 0.375rem 0.65rem;
33
33
  border: 0;
34
- border-radius: 0.4rem;
34
+ border-radius: 0.5rem;
35
35
  background: transparent;
36
36
  color: var(--color-foreground);
37
37
  font: inherit;
38
38
  text-align: left;
39
39
  cursor: pointer;
40
+ transition: background-color 150ms ease;
40
41
  }
41
42
  [data-label] {
42
43
  flex: 1;
@@ -50,13 +51,24 @@
50
51
  flex: 0 0 auto;
51
52
  font-size: var(--internal-icon-size);
52
53
  }
53
- button:hover:not(:disabled),
54
- button[aria-selected='true'],
55
- button[data-active] {
56
- background: color-mix(in srgb, var(--color-primary) 12%, transparent);
54
+ [data-check] {
57
55
  color: var(--color-primary);
58
56
  }
59
- button[data-active],
57
+ button[aria-selected='true'] {
58
+ background: color-mix(in srgb, var(--color-primary) 8%, transparent);
59
+ }
60
+ button:hover:not(:disabled, [data-active]) {
61
+ background: color-mix(in srgb, var(--color-foreground) 6%, transparent);
62
+ }
63
+ button[aria-selected='true']:hover:not(:disabled, [data-active]) {
64
+ background: color-mix(in srgb, var(--color-primary) 14%, transparent);
65
+ }
66
+ button[data-active] {
67
+ background: color-mix(in srgb, var(--color-foreground) 12%, transparent);
68
+ }
69
+ button[aria-selected='true'][data-active] {
70
+ background: color-mix(in srgb, var(--color-primary) 18%, transparent);
71
+ }
60
72
  button:focus-visible {
61
73
  outline: 2px solid var(--color-primary);
62
74
  outline-offset: -2px;
@@ -65,8 +77,16 @@
65
77
  opacity: 0.5;
66
78
  cursor: not-allowed;
67
79
  }
80
+ @media (prefers-reduced-motion: reduce) {
81
+ button {
82
+ transition: none;
83
+ }
84
+ }
68
85
  @media (forced-colors: active) {
69
- button[data-active],
86
+ button[data-active] {
87
+ outline: 2px solid Highlight;
88
+ outline-offset: -2px;
89
+ }
70
90
  button:focus-visible {
71
91
  outline-color: Highlight;
72
92
  }
@@ -4,6 +4,7 @@
4
4
  import { fly } from 'svelte/transition';
5
5
  import { prefersReducedMotion } from 'svelte/motion';
6
6
  import { MediaQuery } from 'svelte/reactivity';
7
+ import { surface } from '../theme/surface.js';
7
8
  import Header from './header.svelte';
8
9
  import Footer from './footer.svelte';
9
10
  import type { DialogProps } from './types.js';
@@ -71,6 +72,7 @@
71
72
  {#if open}
72
73
  <div
73
74
  data-surface
75
+ class={surface({ color: 'background', glass: true, shadow: 'large' })}
74
76
  use:showModal
75
77
  transition:fly|global={{
76
78
  y: prefersReducedMotion.current ? 0 : 16,
@@ -104,11 +106,7 @@
104
106
  display: flex;
105
107
  flex-direction: column;
106
108
  max-height: calc(100dvh - 2rem);
107
- border: 1px solid color-mix(in srgb, var(--color-foreground, black) 18%, transparent);
108
- border-radius: 0.75rem;
109
- background: var(--color-background, white);
110
- color: var(--color-foreground, black);
111
- box-shadow: 0 1.5rem 4rem color-mix(in srgb, var(--color-foreground, black) 20%, transparent);
109
+ border-radius: 1rem;
112
110
  }
113
111
  dialog[open] {
114
112
  display: flex;
@@ -127,26 +125,30 @@
127
125
  --internal-width: 72rem;
128
126
  }
129
127
  dialog::backdrop {
130
- background: color-mix(in srgb, var(--color-foreground, black) 48%, transparent);
131
- opacity: 0;
128
+ background: color-mix(in srgb, var(--color-background, white) 48%, transparent);
129
+ -webkit-backdrop-filter: blur(0);
132
130
  backdrop-filter: blur(0);
131
+ opacity: 0;
133
132
  transition:
134
133
  opacity 300ms ease,
134
+ -webkit-backdrop-filter 300ms ease,
135
135
  backdrop-filter 300ms ease;
136
136
  }
137
137
  dialog[data-visible='true']::backdrop {
138
- opacity: 1;
138
+ -webkit-backdrop-filter: blur(0.25rem);
139
139
  backdrop-filter: blur(0.25rem);
140
+ opacity: 1;
140
141
  }
141
142
  @starting-style {
142
143
  dialog[data-visible='true']::backdrop {
143
- opacity: 0;
144
+ -webkit-backdrop-filter: blur(0);
144
145
  backdrop-filter: blur(0);
146
+ opacity: 0;
145
147
  }
146
148
  }
147
149
  [data-content] {
148
150
  min-height: 0;
149
- padding: 1.5rem;
151
+ padding: 1.25rem 1.75rem 1.5rem;
150
152
  overflow: auto;
151
153
  }
152
154
  dialog[data-size='full-screen'] {
@@ -172,11 +174,12 @@
172
174
  }
173
175
  @media (forced-colors: active) {
174
176
  [data-surface] {
175
- border-color: CanvasText;
176
- box-shadow: none;
177
+ border: 1px solid CanvasText;
177
178
  }
178
179
  dialog::backdrop {
179
180
  background: Canvas;
181
+ -webkit-backdrop-filter: none;
182
+ backdrop-filter: none;
180
183
  }
181
184
  }
182
185
  </style>
@@ -20,7 +20,7 @@
20
20
  align-items: center;
21
21
  justify-content: flex-end;
22
22
  flex-wrap: wrap;
23
- gap: 0.5rem;
24
- padding: 0.75rem 1.5rem 1.5rem;
23
+ gap: 0.75rem;
24
+ padding: 0 1.75rem 1.5rem;
25
25
  }
26
26
  </style>
@@ -29,7 +29,7 @@
29
29
  display: flex;
30
30
  align-items: flex-start;
31
31
  gap: 1rem;
32
- padding: 1.5rem 1.5rem 0;
32
+ padding: 1.75rem 1.75rem 0;
33
33
  }
34
34
  header > div {
35
35
  flex: 1;
@@ -44,9 +44,9 @@
44
44
  h2 {
45
45
  margin: 0;
46
46
  font: inherit;
47
- font-size: 1.375rem;
48
- font-weight: 600;
49
- line-height: 1.4;
47
+ font-size: 1.5rem;
48
+ font-weight: 400;
49
+ line-height: 1.3;
50
50
  }
51
51
  p {
52
52
  margin: 0.5rem 0 0;
@@ -29,6 +29,8 @@
29
29
  height: 1em;
30
30
  align-items: center;
31
31
  justify-content: center;
32
+ flex-shrink: 0;
33
+ vertical-align: middle;
32
34
  font-family: 'Material Symbols Outlined';
33
35
  font-style: normal;
34
36
  font-weight: 100;
@@ -51,11 +53,11 @@
51
53
  }
52
54
 
53
55
  .x-small {
54
- font-size: 0.875rem;
56
+ font-size: 1rem;
55
57
  }
56
58
 
57
59
  .small {
58
- font-size: 1rem;
60
+ font-size: 1.25rem;
59
61
  }
60
62
 
61
63
  .medium {
@@ -63,11 +65,11 @@
63
65
  }
64
66
 
65
67
  .large {
66
- font-size: 2.5rem;
68
+ font-size: 2rem;
67
69
  }
68
70
 
69
71
  .x-large {
70
- font-size: 5rem;
72
+ font-size: 2.5rem;
71
73
  }
72
74
 
73
75
  .primary {
@@ -3,21 +3,28 @@
3
3
  import Icon from '../icon/icon.svelte';
4
4
  import type { PillProps } from './types.js';
5
5
 
6
- let { label, icon, size }: Pick<PillProps, 'label' | 'icon' | 'size'> = $props();
6
+ let { label, icon }: Pick<PillProps, 'label' | 'icon'> = $props();
7
7
  </script>
8
8
 
9
9
  {#if icon}
10
10
  {#key icon.name}
11
- <span data-icon in:fly>
12
- <Icon {...icon} label={undefined} {size} color={undefined} />
13
- </span>
11
+ <i data-icon in:fly>
12
+ <Icon {...icon} label={undefined} size={undefined} color={undefined} />
13
+ </i>
14
14
  {/key}
15
15
  {/if}
16
16
  <span>{label}</span>
17
17
 
18
18
  <style>
19
19
  [data-icon] {
20
+ all: unset;
20
21
  display: inline-flex;
21
22
  align-items: center;
23
+ flex-shrink: 0;
24
+ font-size: var(--pill-icon-size, 1.125rem);
25
+ }
26
+ span {
27
+ flex: 1;
28
+ text-justify: left;
22
29
  }
23
30
  </style>
@@ -1,4 +1,4 @@
1
1
  import type { PillProps } from './types.js';
2
- declare const Content: import("svelte").Component<Pick<PillProps, "size" | "label" | "icon">, {}, "">;
2
+ declare const Content: import("svelte").Component<Pick<PillProps, "label" | "icon">, {}, "">;
3
3
  type Content = ReturnType<typeof Content>;
4
4
  export default Content;
@@ -1,26 +1,55 @@
1
1
  <script lang="ts">
2
- import Button from '../button/button.svelte';
2
+ import Icon from '../icon/icon.svelte';
3
3
  import type { PillProps } from './types.js';
4
4
 
5
5
  let { label, onDelete }: Required<Pick<PillProps, 'label' | 'onDelete'>> = $props();
6
6
  </script>
7
7
 
8
- <span data-delete>
9
- <Button
10
- icon={{ name: 'close', label: `Remove ${label}` }}
11
- size="x-small"
12
- rounded
13
- onClick={(event) => {
14
- event.stopPropagation();
15
- onDelete();
16
- }}
17
- />
18
- </span>
8
+ <button
9
+ type="button"
10
+ aria-label={`Remove ${label}`}
11
+ onclick={(event) => {
12
+ event.stopPropagation();
13
+ onDelete();
14
+ }}
15
+ >
16
+ <Icon name="close" />
17
+ </button>
19
18
 
20
19
  <style>
21
- [data-delete] {
20
+ button {
21
+ box-sizing: border-box;
22
22
  position: relative;
23
23
  z-index: 1;
24
24
  display: inline-flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ flex-shrink: 0;
28
+ width: var(--pill-delete-size, 1.5rem);
29
+ height: var(--pill-delete-size, 1.5rem);
30
+ padding: 0;
31
+ border: 0;
32
+ border-radius: 50%;
33
+ background: transparent;
34
+ color: inherit;
35
+ font: inherit;
36
+ font-size: var(--pill-icon-size, 1.125rem);
37
+ cursor: pointer;
38
+ }
39
+ button:hover {
40
+ background: color-mix(in srgb, currentColor 8%, transparent);
41
+ }
42
+ button:active {
43
+ background: color-mix(in srgb, currentColor 16%, transparent);
44
+ }
45
+ button:focus-visible {
46
+ outline: 2px solid currentColor;
47
+ outline-offset: -2px;
48
+ }
49
+ @media (pointer: coarse) {
50
+ button {
51
+ min-width: 44px;
52
+ min-height: 44px;
53
+ }
25
54
  }
26
55
  </style>