@reshape-biotech/design-system 1.2.7 → 2.0.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/README.md +2 -0
- package/dist/components/collapsible/index.d.ts +1 -1
- package/dist/components/combobox/index.d.ts +1 -1
- package/dist/components/select/Select.stories.svelte +190 -84
- package/dist/components/select/Select.stories.svelte.d.ts +1 -1
- package/dist/components/select/index.d.ts +10 -7
- package/dist/components/select/index.js +12 -1
- package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte +16 -1
- package/dist/components/tooltip/Tooltip.stories.svelte +22 -48
- package/dist/components/tooltip/Tooltip.svelte +37 -26
- package/dist/components/tooltip/Tooltip.svelte.d.ts +1 -1
- package/dist/components/tooltip/TooltipTest.svelte +31 -0
- package/dist/components/tooltip/TooltipTest.svelte.d.ts +11 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/tailwind.preset.d.ts +51 -5
- package/dist/tokens/colors.d.ts +51 -5
- package/dist/tokens/colors.js +20 -13
- package/dist/tokens.d.ts +147 -5
- package/dist/tokens.js +104 -4
- package/package.json +196 -202
- package/dist/components/select/Select.svelte +0 -139
- package/dist/components/select/Select.svelte.d.ts +0 -60
- package/dist/components/select-new/Select.stories.svelte +0 -219
- package/dist/components/select-new/Select.stories.svelte.d.ts +0 -19
- package/dist/components/select-new/index.d.ts +0 -10
- package/dist/components/select-new/index.js +0 -12
- /package/dist/components/{select-new → select}/components/Group.svelte +0 -0
- /package/dist/components/{select-new → select}/components/Group.svelte.d.ts +0 -0
- /package/dist/components/{select-new → select}/components/MultiSelectTrigger.svelte +0 -0
- /package/dist/components/{select-new → select}/components/MultiSelectTrigger.svelte.d.ts +0 -0
- /package/dist/components/{select-new → select}/components/SelectContent.svelte +0 -0
- /package/dist/components/{select-new → select}/components/SelectContent.svelte.d.ts +0 -0
- /package/dist/components/{select-new → select}/components/SelectGroupHeading.svelte +0 -0
- /package/dist/components/{select-new → select}/components/SelectGroupHeading.svelte.d.ts +0 -0
- /package/dist/components/{select-new → select}/components/SelectItem.svelte +0 -0
- /package/dist/components/{select-new → select}/components/SelectItem.svelte.d.ts +0 -0
- /package/dist/components/{select-new → select}/components/SelectTrigger.svelte +0 -0
- /package/dist/components/{select-new → select}/components/SelectTrigger.svelte.d.ts +0 -0
- /package/dist/components/{select-new → select}/types.d.ts +0 -0
- /package/dist/components/{select-new → select}/types.js +0 -0
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@ bun run package
|
|
|
13
13
|
bun publish
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
`bun publish` requires a valid NPM publishing token to be set in your environment.
|
|
17
|
+
|
|
16
18
|
## About the Design System
|
|
17
19
|
|
|
18
20
|
This package contains the core design system for Reshape Biotech frontend projects, providing a consistent and reusable set of components and styles.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Collapsible } from 'bits-ui';
|
|
2
|
-
export declare const Root: import("svelte").Component<Collapsible.RootProps, {}, "
|
|
2
|
+
export declare const Root: import("svelte").Component<Collapsible.RootProps, {}, "ref" | "open">;
|
|
3
3
|
export { default as Trigger } from './components/collapsible-trigger.svelte';
|
|
4
4
|
export { default as Content } from './components/collapsible-content.svelte';
|
|
5
5
|
export type { CollapsibleTriggerProps, CollapsibleContentProps } from './types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Combobox } from 'bits-ui';
|
|
2
|
-
export declare const Root: import("svelte").Component<import("bits-ui").ComboboxRootPropsWithoutHTML, {}, "
|
|
2
|
+
export declare const Root: import("svelte").Component<import("bits-ui").ComboboxRootPropsWithoutHTML, {}, "value" | "open">;
|
|
3
3
|
export declare const Item: import("svelte").Component<Combobox.ItemProps, {}, "ref">;
|
|
4
4
|
export declare const Group: import("svelte").Component<Combobox.GroupProps, {}, "ref">;
|
|
5
5
|
export declare const GroupHeading: import("svelte").Component<Combobox.GroupHeadingProps, {}, "ref">;
|
|
@@ -1,113 +1,219 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
|
-
import Select from './Select.svelte';
|
|
3
|
-
|
|
4
2
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import * as Select from './index';
|
|
4
|
+
import { Icon, type IconName } from '../icons';
|
|
5
5
|
|
|
6
6
|
const { Story } = defineMeta({
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
title: 'Design System/Select(New)',
|
|
8
|
+
|
|
9
|
+
argTypes: {
|
|
10
|
+
placeholder: { control: 'text', defaultValue: 'Select an option...' },
|
|
11
|
+
disabled: { control: 'boolean', defaultValue: false },
|
|
12
|
+
multiple: { control: 'boolean', defaultValue: false },
|
|
13
|
+
},
|
|
10
14
|
});
|
|
11
15
|
|
|
12
|
-
const
|
|
13
|
-
{ value: '
|
|
14
|
-
{ value: '
|
|
15
|
-
{ value: '
|
|
16
|
-
{ value: '
|
|
16
|
+
const foodGroups = [
|
|
17
|
+
{ value: 'fruits', label: 'Fruits' },
|
|
18
|
+
{ value: 'vegetables', label: 'Vegetables' },
|
|
19
|
+
{ value: 'grains', label: 'Grains' },
|
|
20
|
+
{ value: 'protein', label: 'Protein Foods' },
|
|
21
|
+
{ value: 'dairy', label: 'Dairy' },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const moreFruits = [
|
|
25
|
+
{ value: 'apple', label: 'Apple' },
|
|
26
|
+
{ value: 'banana', label: 'Banana' },
|
|
27
|
+
{ value: 'blueberry', label: 'Blueberry' },
|
|
28
|
+
{ value: 'grapes', label: 'Grapes' },
|
|
29
|
+
{ value: 'mango', label: 'Mango' },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
let selectedValueSingle = $state<string | undefined>(undefined);
|
|
33
|
+
let selectedValueMultiple = $state<string[]>([]);
|
|
34
|
+
let selectedValueSinglePreselected = $state<string | undefined>('vegetables');
|
|
35
|
+
let selectedValueMultiplePreselected = $state<string[]>(['fruits', 'grains']);
|
|
36
|
+
|
|
37
|
+
const customIconItems = [
|
|
38
|
+
{ value: 'insect_count', label: 'Insect count', iconName: 'Hash' },
|
|
39
|
+
{ value: 'insect_health', label: 'Insect health', iconName: 'Hash' },
|
|
40
|
+
{ value: 'leaf_area', label: 'Leaf area', iconName: 'Ruler' },
|
|
41
|
+
{ value: 'time_spent', label: 'Time spent on leaf', iconName: 'Timer' },
|
|
17
42
|
];
|
|
18
|
-
let
|
|
19
|
-
let thisChanged = $state(false);
|
|
43
|
+
let selectedCustomItems = $state<string[]>(['insect_count', 'leaf_area']);
|
|
20
44
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
45
|
+
const handleRemoveCustomItem = (itemValue: string) => {
|
|
46
|
+
selectedCustomItems = selectedCustomItems.filter((v) => v !== itemValue);
|
|
47
|
+
};
|
|
48
|
+
const handleRemoveValueMultiple = (itemValue: string) => {
|
|
49
|
+
selectedValueMultiple = selectedValueMultiple.filter((v) => v !== itemValue);
|
|
50
|
+
};
|
|
51
|
+
const handleRemoveValueMultiplePreselected = (itemValue: string) => {
|
|
52
|
+
selectedValueMultiplePreselected = selectedValueMultiplePreselected.filter(
|
|
53
|
+
(v) => v !== itemValue
|
|
54
|
+
);
|
|
55
|
+
};
|
|
24
56
|
</script>
|
|
25
57
|
|
|
26
|
-
<Story name="Default" asChild>
|
|
27
|
-
<div class="
|
|
28
|
-
<Select
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
</div>
|
|
35
|
-
</Story>
|
|
58
|
+
<Story name="Default (Single Select)" asChild>
|
|
59
|
+
<div class="p-4">
|
|
60
|
+
<Select.Root bind:value={selectedValueSingle} items={foodGroups} type="single" open>
|
|
61
|
+
<Select.Trigger
|
|
62
|
+
class="w-[250px]"
|
|
63
|
+
placeholder={'Select a food group'}
|
|
64
|
+
displayValue={foodGroups.find((f) => f.value === selectedValueSingle)?.label}
|
|
65
|
+
/>
|
|
36
66
|
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
67
|
+
<Select.Content>
|
|
68
|
+
{#each foodGroups as item (item.value)}
|
|
69
|
+
<Select.Item value={item.value} label={item.label} />
|
|
70
|
+
{/each}
|
|
71
|
+
</Select.Content>
|
|
72
|
+
</Select.Root>
|
|
73
|
+
<div class="mt-2 rounded bg-gray-100 p-2 text-sm">
|
|
74
|
+
Selected: {selectedValueSingle ?? 'Nothing'}
|
|
75
|
+
</div>
|
|
40
76
|
</div>
|
|
41
77
|
</Story>
|
|
42
78
|
|
|
43
|
-
<Story name="
|
|
44
|
-
<div class="
|
|
45
|
-
<Select
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
79
|
+
<Story name="With Groups (Single Select)" asChild>
|
|
80
|
+
<div class="p-4">
|
|
81
|
+
<Select.Root bind:value={selectedValueSingle} items={moreFruits} type="single">
|
|
82
|
+
<Select.Trigger
|
|
83
|
+
class="w-[250px]"
|
|
84
|
+
placeholder={'Select a fruit'}
|
|
85
|
+
displayValue={moreFruits.find((f) => f.value === selectedValueSingle)?.label}
|
|
86
|
+
/>
|
|
87
|
+
<Select.Portal>
|
|
88
|
+
<Select.Content>
|
|
89
|
+
<Select.Group label="Fruits">
|
|
90
|
+
{#each moreFruits.slice(0, 2) as item (item.value)}
|
|
91
|
+
<Select.Item value={item.value} label={item.label} />
|
|
92
|
+
{/each}
|
|
93
|
+
</Select.Group>
|
|
94
|
+
<Select.Group label="More Fruits">
|
|
95
|
+
{#each moreFruits.slice(2) as item (item.value)}
|
|
96
|
+
<Select.Item value={item.value} label={item.label} />
|
|
97
|
+
{/each}
|
|
98
|
+
</Select.Group>
|
|
99
|
+
</Select.Content>
|
|
100
|
+
</Select.Portal>
|
|
101
|
+
</Select.Root>
|
|
102
|
+
<div class="mt-2 rounded bg-gray-100 p-2 text-sm">
|
|
103
|
+
Selected: {selectedValueSingle ?? 'Nothing'}
|
|
104
|
+
</div>
|
|
56
105
|
</div>
|
|
57
106
|
</Story>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
107
|
+
|
|
108
|
+
<Story name="Multiple Select Example" asChild>
|
|
109
|
+
<div class="p-4">
|
|
110
|
+
<Select.Root bind:value={selectedValueMultiple} items={foodGroups} type="multiple">
|
|
111
|
+
<Select.MultiSelectTrigger
|
|
112
|
+
selectedValues={selectedValueMultiple}
|
|
113
|
+
items={foodGroups}
|
|
114
|
+
onRemoveItem={handleRemoveValueMultiple}
|
|
115
|
+
/>
|
|
116
|
+
<Select.Portal>
|
|
117
|
+
<Select.Content>
|
|
118
|
+
{#each foodGroups as item (item.value)}
|
|
119
|
+
<Select.Item value={item.value} label={item.label} />
|
|
120
|
+
{/each}
|
|
121
|
+
</Select.Content>
|
|
122
|
+
</Select.Portal>
|
|
123
|
+
</Select.Root>
|
|
124
|
+
<div class="mt-2 rounded bg-gray-100 p-2 text-sm">
|
|
125
|
+
Selected: {selectedValueMultiple.join(', ') || 'Nothing'}
|
|
126
|
+
</div>
|
|
66
127
|
</div>
|
|
67
128
|
</Story>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
129
|
+
|
|
130
|
+
<Story name="Disabled Select" asChild>
|
|
131
|
+
<div class="p-4">
|
|
132
|
+
<Select.Root items={foodGroups} type="single" disabled={true}>
|
|
133
|
+
<Select.Trigger class="w-[250px]" placeholder={'Cannot select (disabled)'} disabled={true} />
|
|
134
|
+
<Select.Portal>
|
|
135
|
+
<Select.Content>
|
|
136
|
+
{#each foodGroups as item (item.value)}
|
|
137
|
+
<Select.Item value={item.value} label={item.label} disabled={true} />
|
|
138
|
+
{/each}
|
|
139
|
+
</Select.Content>
|
|
140
|
+
</Select.Portal>
|
|
141
|
+
</Select.Root>
|
|
142
|
+
<div class="mt-2 rounded bg-gray-100 p-2 text-sm">Selected: Nothing (disabled)</div>
|
|
71
143
|
</div>
|
|
72
144
|
</Story>
|
|
73
145
|
|
|
74
|
-
<Story name="
|
|
75
|
-
<div class="
|
|
76
|
-
<Select
|
|
77
|
-
|
|
78
|
-
|
|
146
|
+
<Story name="Pre-selected (Single Select)" asChild>
|
|
147
|
+
<div class="p-4">
|
|
148
|
+
<Select.Root bind:value={selectedValueSinglePreselected} items={foodGroups} type="single">
|
|
149
|
+
<Select.Trigger
|
|
150
|
+
class="w-[250px]"
|
|
151
|
+
placeholder={'Select a food group'}
|
|
152
|
+
displayValue={foodGroups.find((f) => f.value === selectedValueSinglePreselected)?.label}
|
|
153
|
+
/>
|
|
154
|
+
<Select.Portal>
|
|
155
|
+
<Select.Content>
|
|
156
|
+
{#each foodGroups as item (item.value)}
|
|
157
|
+
<Select.Item value={item.value} label={item.label} />
|
|
158
|
+
{/each}
|
|
159
|
+
</Select.Content>
|
|
160
|
+
</Select.Portal>
|
|
161
|
+
</Select.Root>
|
|
162
|
+
<div class="mt-2 rounded bg-gray-100 p-2 text-sm">
|
|
163
|
+
Selected: {selectedValueSinglePreselected ?? 'Nothing'}
|
|
164
|
+
</div>
|
|
79
165
|
</div>
|
|
80
166
|
</Story>
|
|
81
167
|
|
|
82
|
-
<Story name="
|
|
83
|
-
<div class="
|
|
84
|
-
<Select
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
>
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
{item.label}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
</
|
|
168
|
+
<Story name="Pre-selected (Multiple Select)" asChild>
|
|
169
|
+
<div class="p-4">
|
|
170
|
+
<Select.Root bind:value={selectedValueMultiplePreselected} items={foodGroups} type="multiple">
|
|
171
|
+
<Select.MultiSelectTrigger
|
|
172
|
+
selectedValues={selectedValueMultiplePreselected}
|
|
173
|
+
items={foodGroups}
|
|
174
|
+
onRemoveItem={handleRemoveValueMultiplePreselected}
|
|
175
|
+
/>
|
|
176
|
+
<Select.Portal>
|
|
177
|
+
<Select.Content>
|
|
178
|
+
{#each foodGroups as item (item.value)}
|
|
179
|
+
<Select.Item value={item.value} label={item.label} />
|
|
180
|
+
{/each}
|
|
181
|
+
</Select.Content>
|
|
182
|
+
</Select.Portal>
|
|
183
|
+
</Select.Root>
|
|
184
|
+
<div class="mt-2 rounded bg-gray-100 p-2 text-sm">
|
|
185
|
+
Selected: {selectedValueMultiplePreselected.join(', ') || 'Nothing'}
|
|
186
|
+
</div>
|
|
101
187
|
</div>
|
|
102
188
|
</Story>
|
|
103
189
|
|
|
104
|
-
<Story name="Custom
|
|
105
|
-
<div class="
|
|
106
|
-
<Select {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
190
|
+
<Story name="Multiple Select with Custom Icons and Dismissible Tags" asChild>
|
|
191
|
+
<div class="p-4">
|
|
192
|
+
<Select.Root bind:value={selectedCustomItems} items={customIconItems} type="multiple">
|
|
193
|
+
<Select.MultiSelectTrigger
|
|
194
|
+
class="w-[350px]"
|
|
195
|
+
selectedValues={selectedCustomItems}
|
|
196
|
+
items={customIconItems}
|
|
197
|
+
placeholder="Select metrics..."
|
|
198
|
+
onRemoveItem={handleRemoveCustomItem}
|
|
199
|
+
/>
|
|
200
|
+
<Select.Portal>
|
|
201
|
+
<Select.Content>
|
|
202
|
+
{#each customIconItems as item (item.value)}
|
|
203
|
+
<Select.Item value={item.value} label={item.label}>
|
|
204
|
+
{#snippet children()}
|
|
205
|
+
<div class="flex items-center gap-2">
|
|
206
|
+
<Icon iconName={item.iconName as IconName} class="h-4 w-4" />
|
|
207
|
+
<span>{item.label}</span>
|
|
208
|
+
</div>
|
|
209
|
+
{/snippet}
|
|
210
|
+
</Select.Item>
|
|
211
|
+
{/each}
|
|
212
|
+
</Select.Content>
|
|
213
|
+
</Select.Portal>
|
|
214
|
+
</Select.Root>
|
|
215
|
+
<div class="mt-2 rounded bg-neutral p-2 text-sm">
|
|
216
|
+
Selected Values: {selectedCustomItems.join(', ') || 'Nothing'}
|
|
217
|
+
</div>
|
|
112
218
|
</div>
|
|
113
219
|
</Story>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Select from './
|
|
1
|
+
import * as Select from './index';
|
|
2
2
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
3
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
4
|
$$bindings?: Bindings;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export
|
|
1
|
+
import Content from './components/SelectContent.svelte';
|
|
2
|
+
import Item from './components/SelectItem.svelte';
|
|
3
|
+
import GroupHeading from './components/SelectGroupHeading.svelte';
|
|
4
|
+
import Trigger from './components/SelectTrigger.svelte';
|
|
5
|
+
import MultiSelectTrigger from './components/MultiSelectTrigger.svelte';
|
|
6
|
+
import Group from './components/Group.svelte';
|
|
7
|
+
export declare const Root: import("svelte").Component<import("bits-ui").ComboboxRootPropsWithoutHTML, {}, "value" | "open">;
|
|
8
|
+
export declare const Portal: import("svelte").Component<import("bits-ui").PortalProps, {}, "">;
|
|
9
|
+
export { Content, Item, Group, GroupHeading, Trigger, MultiSelectTrigger };
|
|
10
|
+
export * from './types';
|
|
@@ -1 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { Select as SelectPrimitive } from 'bits-ui';
|
|
2
|
+
// Custom Svelte components
|
|
3
|
+
import Content from './components/SelectContent.svelte';
|
|
4
|
+
import Item from './components/SelectItem.svelte';
|
|
5
|
+
import GroupHeading from './components/SelectGroupHeading.svelte';
|
|
6
|
+
import Trigger from './components/SelectTrigger.svelte';
|
|
7
|
+
import MultiSelectTrigger from './components/MultiSelectTrigger.svelte';
|
|
8
|
+
import Group from './components/Group.svelte';
|
|
9
|
+
export const Root = SelectPrimitive.Root;
|
|
10
|
+
export const Portal = SelectPrimitive.Portal;
|
|
11
|
+
export { Content, Item, Group, GroupHeading, Trigger, MultiSelectTrigger };
|
|
12
|
+
export * from './types';
|
|
@@ -48,7 +48,13 @@
|
|
|
48
48
|
: undefined
|
|
49
49
|
);
|
|
50
50
|
|
|
51
|
+
let displayValue = $state('');
|
|
52
|
+
|
|
51
53
|
const getStringValue = () => {
|
|
54
|
+
if (displayValue !== '') {
|
|
55
|
+
return displayValue;
|
|
56
|
+
}
|
|
57
|
+
|
|
52
58
|
if (value === undefined || value === null || isNaN(value)) {
|
|
53
59
|
return '';
|
|
54
60
|
}
|
|
@@ -61,6 +67,13 @@
|
|
|
61
67
|
? ''
|
|
62
68
|
: String(newValueFromInput);
|
|
63
69
|
|
|
70
|
+
const validNumberPattern = /^-?\d*\.?\d*$/;
|
|
71
|
+
if (stringifiedInput !== '' && !validNumberPattern.test(stringifiedInput)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
displayValue = stringifiedInput;
|
|
76
|
+
|
|
64
77
|
if (stringifiedInput.trim() === '') {
|
|
65
78
|
value = undefined;
|
|
66
79
|
} else {
|
|
@@ -73,7 +86,9 @@
|
|
|
73
86
|
<Input
|
|
74
87
|
bind:value={() => getStringValue(), (v) => setNumericValue(v)}
|
|
75
88
|
placeholder={String(placeholder)}
|
|
76
|
-
type={'
|
|
89
|
+
type={'text'}
|
|
90
|
+
inputmode={'decimal'}
|
|
91
|
+
pattern={config?.schema?.type === 'integer' ? '-?\\d*' : '-?\\d*\\.?\\d*'}
|
|
77
92
|
{readonly}
|
|
78
93
|
id={String(derivedAttrs.id)}
|
|
79
94
|
name={String(derivedAttrs.name)}
|
|
@@ -10,20 +10,7 @@
|
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
12
|
<Story name="Base" asChild>
|
|
13
|
-
<div class="flex justify-center">
|
|
14
|
-
<Tooltip>
|
|
15
|
-
{#snippet trigger()}
|
|
16
|
-
<button>Hover me</button>
|
|
17
|
-
{/snippet}
|
|
18
|
-
{#snippet content()}
|
|
19
|
-
<span>Hello World</span>
|
|
20
|
-
{/snippet}
|
|
21
|
-
</Tooltip>
|
|
22
|
-
</div>
|
|
23
|
-
</Story>
|
|
24
|
-
|
|
25
|
-
<Story name="Force Open" asChild>
|
|
26
|
-
<div class="flex justify-center">
|
|
13
|
+
<div class="flex justify-center py-12">
|
|
27
14
|
<Tooltip forceOpen={true}>
|
|
28
15
|
{#snippet trigger()}
|
|
29
16
|
<button>Hover me</button>
|
|
@@ -36,8 +23,8 @@
|
|
|
36
23
|
</Story>
|
|
37
24
|
|
|
38
25
|
<Story name="No Arrow" asChild>
|
|
39
|
-
<div class="flex justify-center">
|
|
40
|
-
<Tooltip showArrow={false}>
|
|
26
|
+
<div class="flex justify-center py-12">
|
|
27
|
+
<Tooltip forceOpen={true} showArrow={false}>
|
|
41
28
|
{#snippet trigger()}
|
|
42
29
|
<button>This one has no arrow</button>
|
|
43
30
|
{/snippet}
|
|
@@ -49,9 +36,9 @@
|
|
|
49
36
|
</Story>
|
|
50
37
|
|
|
51
38
|
<Story name="Different Placements" asChild>
|
|
52
|
-
<div class="
|
|
53
|
-
<div>
|
|
54
|
-
<Tooltip placement="top">
|
|
39
|
+
<div class="grid grid-cols-3 place-items-center gap-16 px-16 py-24">
|
|
40
|
+
<div class="col-start-2">
|
|
41
|
+
<Tooltip forceOpen={true} placement="top">
|
|
55
42
|
{#snippet trigger()}
|
|
56
43
|
<button>Top</button>
|
|
57
44
|
{/snippet}
|
|
@@ -60,33 +47,36 @@
|
|
|
60
47
|
{/snippet}
|
|
61
48
|
</Tooltip>
|
|
62
49
|
</div>
|
|
63
|
-
|
|
64
|
-
|
|
50
|
+
|
|
51
|
+
<div class="col-start-1">
|
|
52
|
+
<Tooltip forceOpen={true} placement="left">
|
|
65
53
|
{#snippet trigger()}
|
|
66
|
-
<button>
|
|
54
|
+
<button>Left</button>
|
|
67
55
|
{/snippet}
|
|
68
56
|
{#snippet content()}
|
|
69
|
-
<span>Tooltip on
|
|
57
|
+
<span>Tooltip on left</span>
|
|
70
58
|
{/snippet}
|
|
71
59
|
</Tooltip>
|
|
72
60
|
</div>
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
|
|
62
|
+
<div class="col-start-3">
|
|
63
|
+
<Tooltip forceOpen={true} placement="right">
|
|
75
64
|
{#snippet trigger()}
|
|
76
|
-
<button>
|
|
65
|
+
<button>Right</button>
|
|
77
66
|
{/snippet}
|
|
78
67
|
{#snippet content()}
|
|
79
|
-
<span>Tooltip on
|
|
68
|
+
<span>Tooltip on right</span>
|
|
80
69
|
{/snippet}
|
|
81
70
|
</Tooltip>
|
|
82
71
|
</div>
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
|
|
73
|
+
<div class="col-start-2">
|
|
74
|
+
<Tooltip forceOpen={true} placement="bottom">
|
|
85
75
|
{#snippet trigger()}
|
|
86
|
-
<button>
|
|
76
|
+
<button>Bottom</button>
|
|
87
77
|
{/snippet}
|
|
88
78
|
{#snippet content()}
|
|
89
|
-
<span>Tooltip on
|
|
79
|
+
<span>Tooltip on bottom</span>
|
|
90
80
|
{/snippet}
|
|
91
81
|
</Tooltip>
|
|
92
82
|
</div>
|
|
@@ -94,23 +84,7 @@
|
|
|
94
84
|
</Story>
|
|
95
85
|
|
|
96
86
|
<Story name="Custom Content" asChild>
|
|
97
|
-
<div class="flex h-28 items-end justify-center">
|
|
98
|
-
<Tooltip>
|
|
99
|
-
{#snippet trigger()}
|
|
100
|
-
<button>Hover me</button>
|
|
101
|
-
{/snippet}
|
|
102
|
-
{#snippet content()}
|
|
103
|
-
<div>
|
|
104
|
-
<h3>Custom Heading</h3>
|
|
105
|
-
<p>This is some custom content inside the tooltip.</p>
|
|
106
|
-
</div>
|
|
107
|
-
{/snippet}
|
|
108
|
-
</Tooltip>
|
|
109
|
-
</div>
|
|
110
|
-
</Story>
|
|
111
|
-
|
|
112
|
-
<Story name="Custom Content Forced Open" asChild>
|
|
113
|
-
<div class="flex h-28 items-end justify-center">
|
|
87
|
+
<div class="flex h-28 items-end justify-center py-16">
|
|
114
88
|
<Tooltip forceOpen={true}>
|
|
115
89
|
{#snippet trigger()}
|
|
116
90
|
<button>Hover me</button>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import Tooltip from '
|
|
2
|
+
import { Tooltip } from 'bits-ui';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
|
+
import { backgroundColor } from '../../tokens';
|
|
4
5
|
|
|
5
6
|
interface Props {
|
|
6
7
|
class?: string;
|
|
@@ -20,30 +21,40 @@
|
|
|
20
21
|
content,
|
|
21
22
|
}: Props = $props();
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
const sideMap = {
|
|
25
|
+
top: 'top',
|
|
26
|
+
right: 'right',
|
|
27
|
+
bottom: 'bottom',
|
|
28
|
+
left: 'left',
|
|
29
|
+
} as const;
|
|
30
|
+
|
|
31
|
+
let side = $derived(sideMap[placement]);
|
|
32
|
+
|
|
33
|
+
const arrowColor = backgroundColor['base-inverse'];
|
|
24
34
|
</script>
|
|
25
35
|
|
|
26
|
-
|
|
27
|
-
<Tooltip
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
</
|
|
36
|
+
<Tooltip.Provider>
|
|
37
|
+
<Tooltip.Root open={forceOpen} delayDuration={400}>
|
|
38
|
+
<Tooltip.Trigger>
|
|
39
|
+
{#if trigger}
|
|
40
|
+
{@render trigger()}
|
|
41
|
+
{/if}
|
|
42
|
+
</Tooltip.Trigger>
|
|
43
|
+
|
|
44
|
+
<Tooltip.Portal>
|
|
45
|
+
<Tooltip.Content
|
|
46
|
+
{side}
|
|
47
|
+
sideOffset={8}
|
|
48
|
+
class={`${className} z-50 max-w-xs text-wrap rounded bg-base-inverse px-2 py-1 text-left text-sm font-normal text-primary-inverse shadow-menu`}
|
|
49
|
+
>
|
|
50
|
+
{#if content}
|
|
51
|
+
{@render content()}
|
|
52
|
+
{/if}
|
|
53
|
+
|
|
54
|
+
{#if showArrow}
|
|
55
|
+
<Tooltip.Arrow style="color: {arrowColor}" />
|
|
56
|
+
{/if}
|
|
57
|
+
</Tooltip.Content>
|
|
58
|
+
</Tooltip.Portal>
|
|
59
|
+
</Tooltip.Root>
|
|
60
|
+
</Tooltip.Provider>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Tooltip from './Tooltip.svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
forceOpen?: boolean;
|
|
6
|
+
showArrow?: boolean;
|
|
7
|
+
placement?: 'top' | 'right' | 'bottom' | 'left';
|
|
8
|
+
class?: string;
|
|
9
|
+
triggerText: string;
|
|
10
|
+
contentText: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
forceOpen = false,
|
|
15
|
+
showArrow = true,
|
|
16
|
+
placement = 'top',
|
|
17
|
+
class: className = '',
|
|
18
|
+
triggerText,
|
|
19
|
+
contentText,
|
|
20
|
+
}: Props = $props();
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<Tooltip {forceOpen} {showArrow} {placement} class={className}>
|
|
24
|
+
{#snippet trigger()}
|
|
25
|
+
<button>{triggerText}</button>
|
|
26
|
+
{/snippet}
|
|
27
|
+
|
|
28
|
+
{#snippet content()}
|
|
29
|
+
{contentText}
|
|
30
|
+
{/snippet}
|
|
31
|
+
</Tooltip>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
forceOpen?: boolean;
|
|
3
|
+
showArrow?: boolean;
|
|
4
|
+
placement?: 'top' | 'right' | 'bottom' | 'left';
|
|
5
|
+
class?: string;
|
|
6
|
+
triggerText: string;
|
|
7
|
+
contentText: string;
|
|
8
|
+
}
|
|
9
|
+
declare const TooltipTest: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type TooltipTest = ReturnType<typeof TooltipTest>;
|
|
11
|
+
export default TooltipTest;
|