bref-ui 2.0.1 → 2.1.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.
- package/dist/button/button.svelte +67 -47
- package/dist/button/types.d.ts +1 -0
- package/dist/checkbox/checkbox.svelte +40 -35
- package/dist/combobox/combobox.svelte +2 -3
- package/dist/combobox/input.svelte +1 -1
- package/dist/combobox/list.svelte +5 -5
- package/dist/combobox/option.svelte +29 -9
- package/dist/dialog/dialog.svelte +15 -12
- package/dist/dialog/footer.svelte +2 -2
- package/dist/dialog/header.svelte +4 -4
- package/dist/icon/icon.svelte +6 -4
- package/dist/pill/content.svelte +11 -4
- package/dist/pill/content.svelte.d.ts +1 -1
- package/dist/pill/on-delete.svelte +42 -13
- package/dist/pill/pill.svelte +74 -94
- package/dist/pill/registry.json +1 -1
- package/dist/pill/types.d.ts +1 -0
- package/dist/pill-choice-group/pill-choice-group.svelte +19 -0
- package/dist/pill-choice-group/types.d.ts +1 -0
- package/dist/pill-group/pill-group.svelte +2 -0
- package/dist/pill-group/types.d.ts +1 -0
- package/dist/popover/popover.svelte +31 -6
- package/dist/popover/types.d.ts +1 -1
- package/dist/progress/progress.svelte +42 -55
- package/dist/select/empty.svelte +2 -3
- package/dist/select/list.svelte +2 -1
- package/dist/select/option.svelte +20 -6
- package/dist/select/select.svelte +7 -4
- package/dist/select/trigger.svelte +30 -7
- package/dist/spinner/spinner.svelte +8 -21
- package/dist/surface/surface.svelte +6 -1
- package/dist/surface/types.d.ts +2 -0
- package/dist/switch/switch.svelte +48 -51
- package/dist/text-area/registry.json +1 -1
- package/dist/text-area/text-area.svelte +33 -73
- package/dist/text-area/types.d.ts +1 -0
- package/dist/text-input/registry.json +1 -1
- package/dist/text-input/text-input.svelte +33 -73
- package/dist/text-input/types.d.ts +1 -0
- package/dist/theme/cli-theme.svelte +2 -0
- package/dist/theme/glass.svelte +60 -0
- package/dist/theme/glass.svelte.d.ts +26 -0
- package/dist/theme/registry.json +1 -0
- package/dist/theme/styles.svelte +6 -0
- package/dist/theme/surface.d.ts +1 -1
- package/dist/theme/surface.js +3 -2
- package/dist/theme/surfaces.svelte +23 -45
- package/dist/theme/theme.svelte +2 -0
- package/dist/tree-view/tree-node/chevron-button.svelte +9 -9
- package/dist/tree-view/tree-node/content.svelte +15 -12
- package/dist/tree-view/tree-node/delete-button.svelte +6 -5
- package/dist/tree-view/tree-node/tree-node.svelte +23 -24
- package/dist/tree-view/tree-view-section.svelte +9 -9
- package/dist/tree-view/tree-view.svelte +17 -9
- package/dist/tree-view/types.d.ts +2 -1
- package/package.json +1 -1
- package/readme.md +54 -13
- package/src/lib/button/button.svelte +67 -47
- package/src/lib/button/types.ts +1 -0
- package/src/lib/checkbox/checkbox.svelte +40 -35
- package/src/lib/combobox/combobox.svelte +2 -3
- package/src/lib/combobox/input.svelte +1 -1
- package/src/lib/combobox/list.svelte +5 -5
- package/src/lib/combobox/option.svelte +29 -9
- package/src/lib/dialog/dialog.svelte +15 -12
- package/src/lib/dialog/footer.svelte +2 -2
- package/src/lib/dialog/header.svelte +4 -4
- package/src/lib/icon/icon.svelte +6 -4
- package/src/lib/pill/content.svelte +11 -4
- package/src/lib/pill/on-delete.svelte +42 -13
- package/src/lib/pill/pill.svelte +74 -94
- package/src/lib/pill/registry.json +1 -1
- package/src/lib/pill/types.ts +1 -0
- package/src/lib/pill-choice-group/pill-choice-group.svelte +19 -0
- package/src/lib/pill-choice-group/types.ts +1 -0
- package/src/lib/pill-group/pill-group.svelte +2 -0
- package/src/lib/pill-group/types.ts +1 -0
- package/src/lib/popover/popover.svelte +31 -6
- package/src/lib/popover/types.ts +16 -1
- package/src/lib/progress/progress.svelte +42 -55
- package/src/lib/select/empty.svelte +2 -3
- package/src/lib/select/list.svelte +2 -1
- package/src/lib/select/option.svelte +20 -6
- package/src/lib/select/select.svelte +7 -4
- package/src/lib/select/trigger.svelte +30 -7
- package/src/lib/spinner/spinner.svelte +8 -21
- package/src/lib/surface/surface.svelte +6 -1
- package/src/lib/surface/types.ts +2 -0
- package/src/lib/switch/switch.svelte +48 -51
- package/src/lib/text-area/registry.json +1 -1
- package/src/lib/text-area/text-area.svelte +33 -73
- package/src/lib/text-area/types.ts +1 -0
- package/src/lib/text-input/registry.json +1 -1
- package/src/lib/text-input/text-input.svelte +33 -73
- package/src/lib/text-input/types.ts +1 -0
- package/src/lib/theme/cli-theme.svelte +2 -0
- package/src/lib/theme/glass.svelte +60 -0
- package/src/lib/theme/registry.json +1 -0
- package/src/lib/theme/styles.svelte +6 -0
- package/src/lib/theme/surface.ts +4 -2
- package/src/lib/theme/surfaces.svelte +23 -45
- package/src/lib/theme/theme.svelte +2 -0
- package/src/lib/tree-view/tree-node/chevron-button.svelte +9 -9
- package/src/lib/tree-view/tree-node/content.svelte +15 -12
- package/src/lib/tree-view/tree-node/delete-button.svelte +6 -5
- package/src/lib/tree-view/tree-node/tree-node.svelte +23 -24
- package/src/lib/tree-view/tree-view-section.svelte +9 -9
- package/src/lib/tree-view/tree-view.svelte +17 -9
- package/src/lib/tree-view/types.ts +2 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { prefersReducedMotion } from 'svelte/motion';
|
|
3
3
|
import { fly } from 'svelte/transition';
|
|
4
|
+
import { surface } from '../../theme/surface.js';
|
|
4
5
|
import ChevronButton from './chevron-button.svelte';
|
|
5
6
|
import DeleteButton from './delete-button.svelte';
|
|
6
7
|
import Content from './content.svelte';
|
|
@@ -11,6 +12,7 @@
|
|
|
11
12
|
item,
|
|
12
13
|
selection = $bindable(),
|
|
13
14
|
defaultExpanded = false,
|
|
15
|
+
glass = false,
|
|
14
16
|
onDelete,
|
|
15
17
|
indent = 0
|
|
16
18
|
}: TreeNodeProps = $props();
|
|
@@ -32,10 +34,12 @@
|
|
|
32
34
|
</script>
|
|
33
35
|
|
|
34
36
|
<div
|
|
35
|
-
|
|
37
|
+
class={selected ? surface({ variant: 'soft', color: 'primary', glass }) : undefined}
|
|
38
|
+
in:fly|global={{ x: -8, duration: prefersReducedMotion.current ? 0 : 200 }}
|
|
39
|
+
out:fly|global={{ x: -8, duration: prefersReducedMotion.current ? 0 : 150 }}
|
|
36
40
|
data-selected={selected}
|
|
37
41
|
data-disabled={item.disabled}
|
|
38
|
-
style:padding-left={`calc(0.25rem + ${indent *
|
|
42
|
+
style:padding-left={`calc(0.25rem + ${indent} * var(--tree-action-size))`}
|
|
39
43
|
>
|
|
40
44
|
{#if item.children?.length}
|
|
41
45
|
<ChevronButton
|
|
@@ -56,18 +60,20 @@
|
|
|
56
60
|
/>
|
|
57
61
|
{/if}
|
|
58
62
|
</div>
|
|
59
|
-
{#if item.children?.length}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
{#if item.children?.length && expanded}
|
|
64
|
+
{#each item.children as child (child.id)}
|
|
65
|
+
<RecursiveNode
|
|
66
|
+
indent={indent + 1}
|
|
67
|
+
item={child}
|
|
68
|
+
bind:selection
|
|
69
|
+
{defaultExpanded}
|
|
70
|
+
{onDelete}
|
|
71
|
+
{glass}
|
|
72
|
+
/>
|
|
73
|
+
{/each}
|
|
65
74
|
{/if}
|
|
66
75
|
|
|
67
76
|
<style>
|
|
68
|
-
* {
|
|
69
|
-
transition: all 150ms;
|
|
70
|
-
}
|
|
71
77
|
div[data-selected] {
|
|
72
78
|
box-sizing: border-box;
|
|
73
79
|
position: relative;
|
|
@@ -79,33 +85,26 @@
|
|
|
79
85
|
border: 1px solid transparent;
|
|
80
86
|
border-radius: 999px;
|
|
81
87
|
overflow-wrap: anywhere;
|
|
88
|
+
transition: all 150ms ease;
|
|
82
89
|
}
|
|
83
90
|
[data-spacer] {
|
|
84
91
|
flex: 0 0 var(--tree-action-size);
|
|
85
92
|
}
|
|
86
|
-
div[role='group'] {
|
|
87
|
-
display: contents;
|
|
88
|
-
}
|
|
89
|
-
div[hidden] {
|
|
90
|
-
display: none;
|
|
91
|
-
}
|
|
92
93
|
div[data-selected='true'] {
|
|
93
|
-
|
|
94
|
-
background: color-mix(in srgb, var(--color-primary) 16%, transparent);
|
|
95
|
-
color: var(--color-primary);
|
|
94
|
+
--tree-action-color: var(--color-primary);
|
|
96
95
|
}
|
|
97
96
|
div[data-selected='false']:not([data-disabled='true']):hover {
|
|
98
|
-
background: color-mix(in srgb, var(--color-
|
|
97
|
+
background: color-mix(in srgb, var(--color-foreground) 5%, transparent);
|
|
99
98
|
}
|
|
100
99
|
@media (prefers-reduced-motion: reduce) {
|
|
101
|
-
|
|
100
|
+
div[data-selected] {
|
|
102
101
|
transition: none;
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
104
|
@media (forced-colors: active) {
|
|
106
105
|
div[data-selected='true'] {
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
outline: 1px solid Highlight;
|
|
107
|
+
outline-offset: -1px;
|
|
109
108
|
}
|
|
110
109
|
}
|
|
111
110
|
</style>
|
|
@@ -18,13 +18,10 @@
|
|
|
18
18
|
display: flex;
|
|
19
19
|
flex-direction: column;
|
|
20
20
|
align-items: flex-start;
|
|
21
|
-
gap: 0.
|
|
22
|
-
padding: 0.75rem 0.
|
|
21
|
+
gap: 0.375rem;
|
|
22
|
+
padding: 1rem 0.75rem 0.75rem;
|
|
23
23
|
color: var(--color-muted);
|
|
24
|
-
|
|
25
|
-
font-weight: 600;
|
|
26
|
-
letter-spacing: 0.06em;
|
|
27
|
-
text-transform: uppercase;
|
|
24
|
+
line-height: 1.4;
|
|
28
25
|
overflow-wrap: anywhere;
|
|
29
26
|
}
|
|
30
27
|
div {
|
|
@@ -32,11 +29,14 @@
|
|
|
32
29
|
align-items: center;
|
|
33
30
|
gap: 0.5rem;
|
|
34
31
|
min-width: 0;
|
|
32
|
+
color: var(--color-foreground);
|
|
33
|
+
font-size: 0.875em;
|
|
34
|
+
font-weight: 500;
|
|
35
|
+
letter-spacing: 0.06em;
|
|
36
|
+
text-transform: uppercase;
|
|
35
37
|
}
|
|
36
38
|
p {
|
|
37
39
|
margin: 0;
|
|
38
|
-
font-
|
|
39
|
-
letter-spacing: normal;
|
|
40
|
-
text-transform: none;
|
|
40
|
+
font-size: 0.75em;
|
|
41
41
|
}
|
|
42
42
|
</style>
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
sections = [],
|
|
9
9
|
label = 'Tree view',
|
|
10
10
|
size = 'medium',
|
|
11
|
+
glass = false,
|
|
11
12
|
selection = $bindable(),
|
|
12
13
|
defaultExpanded = false,
|
|
13
14
|
onDelete,
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
{#if node}
|
|
22
23
|
{@render node(item)}
|
|
23
24
|
{:else}
|
|
24
|
-
<TreeNode {item} bind:selection {defaultExpanded} {onDelete} />
|
|
25
|
+
<TreeNode {item} bind:selection {defaultExpanded} {onDelete} {glass} />
|
|
25
26
|
{/if}
|
|
26
27
|
{/each}
|
|
27
28
|
</div>
|
|
@@ -38,28 +39,35 @@
|
|
|
38
39
|
</div>
|
|
39
40
|
|
|
40
41
|
<style>
|
|
41
|
-
div {
|
|
42
|
-
--tree-height:
|
|
43
|
-
--tree-action-size:
|
|
42
|
+
div[role='group'] {
|
|
43
|
+
--tree-height: 2rem;
|
|
44
|
+
--tree-action-size: 1.5rem;
|
|
44
45
|
display: grid;
|
|
45
46
|
gap: 0.375rem;
|
|
46
47
|
min-width: 0;
|
|
47
48
|
color: var(--color-foreground);
|
|
48
49
|
font: inherit;
|
|
50
|
+
line-height: 1.25;
|
|
49
51
|
}
|
|
50
52
|
div[data-size='small'] {
|
|
51
|
-
--tree-height:
|
|
52
|
-
--tree-action-size: 2rem;
|
|
53
|
+
--tree-height: 1.75rem;
|
|
53
54
|
font-size: 0.875rem;
|
|
54
55
|
}
|
|
55
56
|
div[data-size='large'] {
|
|
56
|
-
--tree-height:
|
|
57
|
-
--tree-action-size:
|
|
57
|
+
--tree-height: 2.5rem;
|
|
58
|
+
--tree-action-size: 2rem;
|
|
58
59
|
font-size: 1.125rem;
|
|
59
60
|
}
|
|
60
61
|
div[data-nodes] {
|
|
61
62
|
display: flex;
|
|
62
63
|
flex-direction: column;
|
|
63
|
-
gap: 0.
|
|
64
|
+
gap: 0.125rem;
|
|
65
|
+
min-width: 0;
|
|
66
|
+
}
|
|
67
|
+
@media (pointer: coarse) {
|
|
68
|
+
div[role='group'] {
|
|
69
|
+
--tree-height: 2.75rem;
|
|
70
|
+
--tree-action-size: 2.75rem;
|
|
71
|
+
}
|
|
64
72
|
}
|
|
65
73
|
</style>
|
|
@@ -17,12 +17,13 @@ export interface TreeViewProps {
|
|
|
17
17
|
sections?: TreeSectionProps[];
|
|
18
18
|
label?: string;
|
|
19
19
|
size?: BaseSize;
|
|
20
|
+
glass?: boolean;
|
|
20
21
|
selection?: string | string[];
|
|
21
22
|
defaultExpanded?: boolean;
|
|
22
23
|
onDelete?: (id: string) => void;
|
|
23
24
|
node?: Snippet<[TreeItemProps]>;
|
|
24
25
|
}
|
|
25
|
-
export interface TreeNodeProps extends Pick<TreeViewProps, 'selection' | 'defaultExpanded' | 'onDelete'> {
|
|
26
|
+
export interface TreeNodeProps extends Pick<TreeViewProps, 'selection' | 'defaultExpanded' | 'onDelete' | 'glass'> {
|
|
26
27
|
item: TreeItemProps;
|
|
27
28
|
indent?: number;
|
|
28
29
|
}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -30,22 +30,19 @@ props and theme customization on `/button`, `/icon` and `/theme`.
|
|
|
30
30
|
|
|
31
31
|
### Use the local package
|
|
32
32
|
|
|
33
|
-
The
|
|
34
|
-
from the
|
|
35
|
-
development checkout containing those changes.
|
|
36
|
-
|
|
37
|
-
In that checkout, build a local package:
|
|
33
|
+
The package includes the component CLI and canonical sources. Build a local package
|
|
34
|
+
from the development checkout:
|
|
38
35
|
|
|
39
36
|
```sh
|
|
40
37
|
bun run build
|
|
41
38
|
npm pack --ignore-scripts
|
|
42
39
|
```
|
|
43
40
|
|
|
44
|
-
This produces `bref-ui-2.
|
|
41
|
+
This produces `bref-ui-2.1.1.tgz`. In an existing Svelte 5.56.1+ project with its
|
|
45
42
|
dependencies installed, install that tarball, replacing the example path:
|
|
46
43
|
|
|
47
44
|
```sh
|
|
48
|
-
npm install /path/to/bref-ui-2.
|
|
45
|
+
npm install /path/to/bref-ui-2.1.1.tgz
|
|
49
46
|
```
|
|
50
47
|
|
|
51
48
|
Then use the components in a `.svelte` file:
|
|
@@ -86,7 +83,9 @@ Button use the same paint recipe; apply it to native HTML with the typed helper:
|
|
|
86
83
|
|
|
87
84
|
All options are optional: variant defaults to neutral and color to foreground;
|
|
88
85
|
shadow and hover accept small, medium or large. Shadow also accepts true for medium
|
|
89
|
-
and false for none.
|
|
86
|
+
and false for none. Set `glass: true` for translucent paint and backdrop blur, or use
|
|
87
|
+
`<Surface glass>` and `<Button glass>`; glass defaults to false.
|
|
88
|
+
SurfaceProps extends SurfaceBaseProps with component props.
|
|
90
89
|
Supply padding, radius and layout
|
|
91
90
|
in element styles. The helper adds classes only; Theme loads their CSS. SurfaceBaseProps
|
|
92
91
|
is available from `bref-ui/types`. Copied components include the helper in
|
|
@@ -109,13 +108,55 @@ is available from `bref-ui/types`. Copied components include the helper in
|
|
|
109
108
|
complete site generation, generative UI and interactive interfaces for agent
|
|
110
109
|
workflows.
|
|
111
110
|
|
|
112
|
-
## Copy components into a project
|
|
111
|
+
## Copy components into a project
|
|
112
|
+
|
|
113
|
+
The package includes the `bref-ui` executable, which requires Bun. After installing
|
|
114
|
+
the tarball, run commands from the consumer project's root:
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
bun run bref-ui init
|
|
118
|
+
bun run bref-ui add button
|
|
119
|
+
bun run bref-ui --help
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`init` creates `bref.config.json` and leaves an existing file untouched:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"ui": "$lib/ui"
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The default destination is `src/lib/ui`. Edit `ui` to another `$lib` path, such as
|
|
131
|
+
`$lib/bref`, to change the destination. The CLI maps `$lib` to `src/lib`; it does not
|
|
132
|
+
discover project aliases or accept an `--alias` option. Configure the same alias
|
|
133
|
+
in a plain Svelte project if using `$lib/ui` imports.
|
|
134
|
+
|
|
135
|
+
`add <component>` copies the component and its registry dependencies, then merges
|
|
136
|
+
component exports into the destination's `index.ts`. Button includes Icon and Theme.
|
|
137
|
+
The preview lists `add`, `unchanged` and `conflict` files. Each conflicting file
|
|
138
|
+
requires overwrite approval, followed by a final installation confirmation. Declining
|
|
139
|
+
a prompt cancels without writes; identical files are skipped.
|
|
140
|
+
|
|
141
|
+
Use the copied components in a `.svelte` file:
|
|
142
|
+
|
|
143
|
+
```svelte
|
|
144
|
+
<script lang="ts">
|
|
145
|
+
import { Button, Theme } from '$lib/ui';
|
|
146
|
+
</script>
|
|
147
|
+
|
|
148
|
+
<Theme />
|
|
149
|
+
<Button label="Save" />
|
|
150
|
+
```
|
|
113
151
|
|
|
114
|
-
|
|
115
|
-
|
|
152
|
+
Keep `bref-ui` installed for shared types imported from `bref-ui/types`. To copy
|
|
153
|
+
Theme separately, run `bun run bref-ui add theme`. The copied Theme uses the default
|
|
154
|
+
palette and has no `palette` prop; customize its copied CSS tokens. The package
|
|
155
|
+
Theme retains its `palette` prop.
|
|
116
156
|
|
|
117
|
-
|
|
118
|
-
|
|
157
|
+
Available component IDs: `button`, `checkbox`, `combobox`, `dialog`, `icon`, `pill`,
|
|
158
|
+
`pill-choice-group`, `pill-group`, `popover`, `progress`, `select`, `spinner`,
|
|
159
|
+
`surface`, `switch`, `text-area`, `text-input`, `theme` and `tree-view`.
|
|
119
160
|
|
|
120
161
|
## Documentation and demos
|
|
121
162
|
|
|
@@ -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 {
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
78
|
-
--internal-
|
|
79
|
-
--internal-
|
|
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:
|
|
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.
|
|
80
|
+
border-radius: 0.625rem;
|
|
90
81
|
font: inherit;
|
|
91
|
-
font-size:
|
|
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.
|
|
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(
|
|
100
|
-
--internal-padding: 0.
|
|
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(
|
|
104
|
-
--internal-padding: 1.
|
|
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(
|
|
108
|
-
--internal-padding:
|
|
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>
|
package/src/lib/button/types.ts
CHANGED
|
@@ -35,6 +35,7 @@ export type ButtonProps = {
|
|
|
35
35
|
color?: Exclude<Color, 'background'>;
|
|
36
36
|
size?: Size;
|
|
37
37
|
variant?: Variant;
|
|
38
|
+
glass?: boolean;
|
|
38
39
|
disabled?: boolean;
|
|
39
40
|
onClick?: DOMAttributes<HTMLButtonElement | HTMLAnchorElement>['onclick'];
|
|
40
41
|
} & Omit<DOMAttributes<HTMLButtonElement | HTMLAnchorElement>, 'children' | 'onclick'> &
|
|
@@ -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:
|
|
25
|
-
--internal-
|
|
26
|
-
color-mix(
|
|
27
|
-
|
|
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:
|
|
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:
|
|
62
|
-
|
|
63
|
-
|
|
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:
|
|
93
|
-
--internal-strength-dark:
|
|
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:
|
|
100
|
-
|
|
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
|
-
|
|
109
|
-
|
|
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;
|
|
@@ -54,17 +54,17 @@
|
|
|
54
54
|
|
|
55
55
|
<style>
|
|
56
56
|
div {
|
|
57
|
-
--internal-height: 2.
|
|
57
|
+
--internal-row-height: 2.125rem;
|
|
58
58
|
--internal-icon-size: 1.25rem;
|
|
59
59
|
display: grid;
|
|
60
|
-
gap: 0.
|
|
60
|
+
gap: 0.125rem;
|
|
61
61
|
}
|
|
62
62
|
div[data-size='small'] {
|
|
63
|
-
--internal-height:
|
|
63
|
+
--internal-row-height: 1.875rem;
|
|
64
64
|
--internal-icon-size: 1rem;
|
|
65
65
|
}
|
|
66
66
|
div[data-size='large'] {
|
|
67
|
-
--internal-height:
|
|
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
|
|
75
|
+
padding: 0.5rem;
|
|
76
76
|
color: var(--color-muted);
|
|
77
77
|
}
|
|
78
78
|
</style>
|