@reshape-biotech/design-system 2.7.34 → 2.7.35

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.
@@ -111,6 +111,62 @@
111
111
  let customAnchorSingle = $state<HTMLElement>(null!);
112
112
  let customAnchorGrouped = $state<HTMLElement>(null!);
113
113
  let customAnchorCustom = $state<HTMLElement>(null!);
114
+
115
+ // Generate a long list of countries for scrolling demo
116
+ const countries = [
117
+ { value: 'us', label: 'United States' },
118
+ { value: 'uk', label: 'United Kingdom' },
119
+ { value: 'ca', label: 'Canada' },
120
+ { value: 'au', label: 'Australia' },
121
+ { value: 'de', label: 'Germany' },
122
+ { value: 'fr', label: 'France' },
123
+ { value: 'it', label: 'Italy' },
124
+ { value: 'es', label: 'Spain' },
125
+ { value: 'jp', label: 'Japan' },
126
+ { value: 'cn', label: 'China' },
127
+ { value: 'in', label: 'India' },
128
+ { value: 'br', label: 'Brazil' },
129
+ { value: 'mx', label: 'Mexico' },
130
+ { value: 'za', label: 'South Africa' },
131
+ { value: 'eg', label: 'Egypt' },
132
+ { value: 'ng', label: 'Nigeria' },
133
+ { value: 'ar', label: 'Argentina' },
134
+ { value: 'cl', label: 'Chile' },
135
+ { value: 'co', label: 'Colombia' },
136
+ { value: 'pe', label: 'Peru' },
137
+ { value: 'se', label: 'Sweden' },
138
+ { value: 'no', label: 'Norway' },
139
+ { value: 'dk', label: 'Denmark' },
140
+ { value: 'fi', label: 'Finland' },
141
+ { value: 'pl', label: 'Poland' },
142
+ { value: 'nl', label: 'Netherlands' },
143
+ { value: 'be', label: 'Belgium' },
144
+ { value: 'ch', label: 'Switzerland' },
145
+ { value: 'at', label: 'Austria' },
146
+ { value: 'gr', label: 'Greece' },
147
+ { value: 'pt', label: 'Portugal' },
148
+ { value: 'ie', label: 'Ireland' },
149
+ { value: 'nz', label: 'New Zealand' },
150
+ { value: 'sg', label: 'Singapore' },
151
+ { value: 'my', label: 'Malaysia' },
152
+ { value: 'th', label: 'Thailand' },
153
+ { value: 'id', label: 'Indonesia' },
154
+ { value: 'ph', label: 'Philippines' },
155
+ { value: 'vn', label: 'Vietnam' },
156
+ { value: 'kr', label: 'South Korea' },
157
+ ];
158
+
159
+ let searchValueCountries = $state('');
160
+ let selectedCountries = $state<string[]>([]);
161
+ let customAnchorCountries = $state<HTMLElement>(null!);
162
+
163
+ const filteredCountries = $derived(
164
+ searchValueCountries === ''
165
+ ? countries
166
+ : countries.filter((country) =>
167
+ country.label.toLowerCase().includes(searchValueCountries.toLowerCase())
168
+ )
169
+ );
114
170
  </script>
115
171
 
116
172
  <Story name="Multiple Selection" asChild>
@@ -265,7 +321,7 @@
265
321
  />
266
322
  <Divider />
267
323
  </div>
268
- <div class="flex max-h-80 flex-grow flex-col overflow-y-auto">
324
+ <div class="flex flex-grow flex-col">
269
325
  {#if searchValueGrouped === ''}
270
326
  {#each categories as category}
271
327
  <Combobox.Group>
@@ -307,6 +363,73 @@
307
363
  </Combobox.Root>
308
364
  </Story>
309
365
 
366
+ <Story name="Long List with Scrolling (80vh max-height)" asChild>
367
+ <Combobox.Root
368
+ onOpenChange={(o) => {
369
+ if (!o) searchValueCountries = '';
370
+ }}
371
+ type="multiple"
372
+ name="countriesSelection"
373
+ items={filteredCountries}
374
+ bind:value={selectedCountries}
375
+ >
376
+ <div class="flex flex-wrap gap-2">
377
+ {#each selectedCountries as country}
378
+ <Tag>
379
+ {country}
380
+ </Tag>
381
+ {/each}
382
+ </div>
383
+ <Combobox.Trigger>
384
+ <div bind:this={customAnchorCountries}>
385
+ <Button variant="primary" size="sm">
386
+ <Icon>
387
+ {#snippet children(props)}
388
+ <List {...props} />
389
+ {/snippet}
390
+ </Icon>
391
+ Select countries
392
+ </Button>
393
+ </div>
394
+ </Combobox.Trigger>
395
+ <Combobox.Content
396
+ class="flex flex-col justify-between"
397
+ customAnchor={customAnchorCountries}
398
+ >
399
+ <div>
400
+ <Combobox.Input
401
+ placeholder="Search for a country"
402
+ oninput={(e: Event) => (searchValueCountries = (e.target as HTMLInputElement).value)}
403
+ autofocus
404
+ />
405
+ <Divider />
406
+ </div>
407
+ <div class="flex flex-grow flex-col">
408
+ {#if filteredCountries.length > 0}
409
+ <Combobox.Group>
410
+ <Combobox.GroupHeading>Countries</Combobox.GroupHeading>
411
+ {#each filteredCountries as country (country.value)}
412
+ <Combobox.Item value={country.value} label={country.label}>
413
+ {#snippet children({ selected })}
414
+ {country.label}
415
+ {#if selected}
416
+ <Combobox.Indicator />
417
+ {/if}
418
+ {/snippet}
419
+ </Combobox.Item>
420
+ {/each}
421
+ </Combobox.Group>
422
+ {:else}
423
+ <span class="block px-5 py-2 text-sm text-muted-foreground"> No results found </span>
424
+ {/if}
425
+ </div>
426
+ </Combobox.Content>
427
+ <div class="mt-4 rounded bg-blue-50 p-2 text-xs text-blue-700">
428
+ This story demonstrates the 80vh max-height with overflow scrolling for long lists (40 countries).
429
+ </div>
430
+ </Combobox.Root>
431
+ </Story>
432
+
310
433
  <Story
311
434
  name="Interaction Test"
312
435
  asChild
@@ -28,7 +28,7 @@
28
28
  <Combobox.ScrollUpButton class="flex justify-center">
29
29
  <Icon icon={CaretUp} />
30
30
  </Combobox.ScrollUpButton>
31
- <Combobox.Viewport class={paddedContent ? 'p-1' : ''}>
31
+ <Combobox.Viewport class="{paddedContent ? 'p-1' : ''} overflow-y-auto">
32
32
  {@render children()}
33
33
  </Combobox.Viewport>
34
34
  <Combobox.ScrollDownButton class="flex justify-center">
@@ -64,6 +64,8 @@
64
64
 
65
65
  z-index: 1;
66
66
 
67
+ max-height: 80vh;
68
+
67
69
  width: 100%;
68
70
 
69
71
  border-radius: 0.75rem;
@@ -561,6 +561,26 @@
561
561
  </div>
562
562
  </Story>
563
563
 
564
+ <Story name="Long Menu with Scrolling (80vh max-height)">
565
+ <div class="py-12">
566
+ <Dropdown.Root open>
567
+ <Dropdown.Trigger>Actions Menu (30 items)</Dropdown.Trigger>
568
+ <Dropdown.Portal>
569
+ <Dropdown.Content>
570
+ {#each Array.from({ length: 30 }, (_, i) => i + 1) as num}
571
+ <Dropdown.Item onSelect={() => console.log(`Action ${num} clicked`)}>
572
+ <p>Action {num}</p>
573
+ </Dropdown.Item>
574
+ {/each}
575
+ </Dropdown.Content>
576
+ </Dropdown.Portal>
577
+ </Dropdown.Root>
578
+ <div class="mt-4 rounded bg-blue-50 p-2 text-xs text-blue-700">
579
+ This story demonstrates the 80vh max-height with overflow scrolling for long menus (30 items).
580
+ </div>
581
+ </div>
582
+ </Story>
583
+
564
584
  <Story
565
585
  name="Interaction Test"
566
586
  asChild
@@ -23,7 +23,7 @@
23
23
  </script>
24
24
 
25
25
  <DropdownMenu.Content
26
- class="z-10 flex flex-col {gap} rounded-md p-1 shadow-menu {variantClass} {widthClass} {className}"
26
+ class="z-10 flex flex-col {gap} rounded-md p-1 shadow-menu max-h-[80vh] overflow-y-auto {variantClass} {widthClass} {className}"
27
27
  {...restProps}
28
28
  >
29
29
  {@render children()}
@@ -19,7 +19,7 @@
19
19
  </script>
20
20
 
21
21
  <DropdownMenu.SubContent
22
- class="z-10 {gap} flex flex-col rounded-md p-1 shadow-menu {variantClass} {className}"
22
+ class="z-10 {gap} flex flex-col rounded-md p-1 shadow-menu max-h-[80vh] overflow-y-auto {variantClass} {className}"
23
23
  {...restProps}
24
24
  >
25
25
  {@render children()}
@@ -53,6 +53,51 @@
53
53
  (v) => v !== itemValue
54
54
  );
55
55
  };
56
+
57
+ // Generate a long list of countries to test scrolling
58
+ const countries = [
59
+ { value: 'us', label: 'United States' },
60
+ { value: 'uk', label: 'United Kingdom' },
61
+ { value: 'ca', label: 'Canada' },
62
+ { value: 'au', label: 'Australia' },
63
+ { value: 'de', label: 'Germany' },
64
+ { value: 'fr', label: 'France' },
65
+ { value: 'it', label: 'Italy' },
66
+ { value: 'es', label: 'Spain' },
67
+ { value: 'jp', label: 'Japan' },
68
+ { value: 'cn', label: 'China' },
69
+ { value: 'in', label: 'India' },
70
+ { value: 'br', label: 'Brazil' },
71
+ { value: 'mx', label: 'Mexico' },
72
+ { value: 'za', label: 'South Africa' },
73
+ { value: 'eg', label: 'Egypt' },
74
+ { value: 'ng', label: 'Nigeria' },
75
+ { value: 'ar', label: 'Argentina' },
76
+ { value: 'cl', label: 'Chile' },
77
+ { value: 'co', label: 'Colombia' },
78
+ { value: 'pe', label: 'Peru' },
79
+ { value: 'se', label: 'Sweden' },
80
+ { value: 'no', label: 'Norway' },
81
+ { value: 'dk', label: 'Denmark' },
82
+ { value: 'fi', label: 'Finland' },
83
+ { value: 'pl', label: 'Poland' },
84
+ { value: 'nl', label: 'Netherlands' },
85
+ { value: 'be', label: 'Belgium' },
86
+ { value: 'ch', label: 'Switzerland' },
87
+ { value: 'at', label: 'Austria' },
88
+ { value: 'gr', label: 'Greece' },
89
+ { value: 'pt', label: 'Portugal' },
90
+ { value: 'ie', label: 'Ireland' },
91
+ { value: 'nz', label: 'New Zealand' },
92
+ { value: 'sg', label: 'Singapore' },
93
+ { value: 'my', label: 'Malaysia' },
94
+ { value: 'th', label: 'Thailand' },
95
+ { value: 'id', label: 'Indonesia' },
96
+ { value: 'ph', label: 'Philippines' },
97
+ { value: 'vn', label: 'Vietnam' },
98
+ { value: 'kr', label: 'South Korea' },
99
+ ];
100
+ let selectedCountry = $state<string | undefined>(undefined);
56
101
  </script>
57
102
 
58
103
  <Story name="Default (Single Select)" asChild>
@@ -217,3 +262,28 @@
217
262
  </div>
218
263
  </div>
219
264
  </Story>
265
+
266
+ <Story name="Long List with Scrolling (80vh max-height)" asChild>
267
+ <div class="p-4">
268
+ <Select.Root bind:value={selectedCountry} items={countries} type="single">
269
+ <Select.Trigger
270
+ class="w-[250px]"
271
+ placeholder={'Select a country'}
272
+ displayValue={countries.find((c) => c.value === selectedCountry)?.label}
273
+ />
274
+ <Select.Portal>
275
+ <Select.Content>
276
+ {#each countries as item (item.value)}
277
+ <Select.Item value={item.value} label={item.label} />
278
+ {/each}
279
+ </Select.Content>
280
+ </Select.Portal>
281
+ </Select.Root>
282
+ <div class="mt-2 rounded bg-gray-100 p-2 text-sm">
283
+ Selected: {selectedCountry ?? 'Nothing'}
284
+ </div>
285
+ <div class="mt-2 rounded bg-blue-50 p-2 text-xs text-blue-700">
286
+ This story demonstrates the 80vh max-height with overflow scrolling for long lists (40 items).
287
+ </div>
288
+ </div>
289
+ </Story>
@@ -21,14 +21,14 @@
21
21
  {...restProps}
22
22
  {sideOffset}
23
23
  class={twMerge(
24
- 'relative z-50 w-[var(--bits-select-anchor-width)] min-w-[8rem] overflow-hidden rounded-lg bg-surface text-primary shadow-menu',
24
+ 'relative z-50 w-[var(--bits-select-anchor-width)] min-w-[8rem] max-h-[80vh] overflow-hidden rounded-lg bg-surface text-primary shadow-menu',
25
25
  className
26
26
  )}
27
27
  >
28
28
  <SelectPrimitive.ScrollUpButton class="flex justify-center">
29
29
  <Icon color="tertiary" icon={CaretUp} />
30
30
  </SelectPrimitive.ScrollUpButton>
31
- <SelectPrimitive.Viewport class="p-1 ">
31
+ <SelectPrimitive.Viewport class="p-1 overflow-y-auto">
32
32
  {@render children()}
33
33
  </SelectPrimitive.Viewport>
34
34
  <SelectPrimitive.ScrollDownButton class="flex justify-center">
package/dist/tokens.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { colors } from './tokens/colors';
2
- export type OutputName = 'cfu' | 'halo' | 'seed' | 'seedling' | 'leaf' | 'insect' | 'egg' | 'food' | 'positive' | 'negative' | 'review' | 'tntc' | 'contaminated' | 'countable' | 'full_growth' | 'reduced_growth' | 'dotted_growth';
2
+ export type OutputName = 'cfu' | 'halo' | 'seed' | 'seedling' | 'leaf' | 'insect' | 'egg' | 'food' | 'positive' | 'negative' | 'review' | 'tntc' | 'contaminated' | 'countable' | 'full_growth' | 'reduced_growth' | 'dotted_growth' | 'root' | 'shoot';
3
3
  declare const annotationOutputFadedFillColors: {
4
4
  [K in OutputName]: string;
5
5
  };
@@ -750,6 +750,8 @@ export declare const tokens: {
750
750
  full_growth: any;
751
751
  reduced_growth: any;
752
752
  dotted_growth: any;
753
+ root: any;
754
+ shoot: any;
753
755
  };
754
756
  annotationOutputFillColors: {
755
757
  cfu: string;
@@ -769,6 +771,8 @@ export declare const tokens: {
769
771
  full_growth: string;
770
772
  reduced_growth: string;
771
773
  dotted_growth: string;
774
+ root: string;
775
+ shoot: string;
772
776
  };
773
777
  annotationOutputFadedFillColors: {
774
778
  cfu: string;
@@ -788,6 +792,8 @@ export declare const tokens: {
788
792
  full_growth: string;
789
793
  reduced_growth: string;
790
794
  dotted_growth: string;
795
+ root: string;
796
+ shoot: string;
791
797
  };
792
798
  annotationOutputStrokeColors: {
793
799
  cfu: string;
@@ -807,6 +813,8 @@ export declare const tokens: {
807
813
  full_growth: string;
808
814
  reduced_growth: string;
809
815
  dotted_growth: string;
816
+ root: string;
817
+ shoot: string;
810
818
  };
811
819
  annotationOutputFadedStrokeColors: {
812
820
  cfu: string;
@@ -826,5 +834,7 @@ export declare const tokens: {
826
834
  full_growth: string;
827
835
  reduced_growth: string;
828
836
  dotted_growth: string;
837
+ root: string;
838
+ shoot: string;
829
839
  };
830
840
  };
package/dist/tokens.js CHANGED
@@ -143,11 +143,11 @@ const lightChartColor = {
143
143
  const annotationOutputBaseColors = {
144
144
  cfu: colors.periwinkle[5],
145
145
  halo: colors.yellow[5],
146
- seed: colors.lime[1],
146
+ seed: colors.orange[5],
147
147
  seedling: colors.lime[5],
148
148
  leaf: colors.green[5],
149
- insect: colors.orange[1],
150
- egg: colors.orange[2],
149
+ insect: colors.orange[5],
150
+ egg: colors.blue[5],
151
151
  food: colors.pear[5],
152
152
  positive: colors.red[5],
153
153
  negative: colors.gray[4],
@@ -158,6 +158,8 @@ const annotationOutputBaseColors = {
158
158
  full_growth: colors.gray[4],
159
159
  reduced_growth: colors.gray[4],
160
160
  dotted_growth: colors.gray[4],
161
+ root: colors.periwinkle[5],
162
+ shoot: colors.blue[5],
161
163
  };
162
164
  const annotationOutputFillColors = {
163
165
  cfu: annotationOutputBaseColors.cfu[25],
@@ -177,6 +179,8 @@ const annotationOutputFillColors = {
177
179
  full_growth: annotationOutputBaseColors.full_growth[25],
178
180
  reduced_growth: annotationOutputBaseColors.reduced_growth[25],
179
181
  dotted_growth: annotationOutputBaseColors.dotted_growth[25],
182
+ root: annotationOutputBaseColors.root[25],
183
+ shoot: annotationOutputBaseColors.shoot[25],
180
184
  };
181
185
  const annotationOutputFadedFillColors = {
182
186
  cfu: annotationOutputBaseColors.cfu[10],
@@ -196,6 +200,8 @@ const annotationOutputFadedFillColors = {
196
200
  full_growth: annotationOutputBaseColors.full_growth[10],
197
201
  reduced_growth: annotationOutputBaseColors.reduced_growth[10],
198
202
  dotted_growth: annotationOutputBaseColors.dotted_growth[10],
203
+ root: annotationOutputBaseColors.root[10],
204
+ shoot: annotationOutputBaseColors.shoot[10],
199
205
  };
200
206
  const annotationOutputStrokeColors = {
201
207
  cfu: annotationOutputBaseColors.cfu.default,
@@ -215,6 +221,8 @@ const annotationOutputStrokeColors = {
215
221
  full_growth: annotationOutputBaseColors.full_growth.default,
216
222
  reduced_growth: annotationOutputBaseColors.reduced_growth.default,
217
223
  dotted_growth: annotationOutputBaseColors.dotted_growth.default,
224
+ root: annotationOutputBaseColors.root.default,
225
+ shoot: annotationOutputBaseColors.shoot.default,
218
226
  };
219
227
  const annotationOutputFadedStrokeColors = {
220
228
  cfu: annotationOutputBaseColors.cfu[50],
@@ -234,6 +242,8 @@ const annotationOutputFadedStrokeColors = {
234
242
  full_growth: annotationOutputBaseColors.full_growth[50],
235
243
  reduced_growth: annotationOutputBaseColors.reduced_growth[50],
236
244
  dotted_growth: annotationOutputBaseColors.dotted_growth[50],
245
+ root: annotationOutputBaseColors.root[50],
246
+ shoot: annotationOutputBaseColors.shoot[50],
237
247
  };
238
248
  const darkTextColor = {
239
249
  'dark-primary': colors.base.white.default,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reshape-biotech/design-system",
3
- "version": "2.7.34",
3
+ "version": "2.7.35",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build",