@reshape-biotech/design-system 2.7.25 → 2.7.26

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.
@@ -56,15 +56,15 @@
56
56
 
57
57
  <div class={`group flex items-stretch gap-3 ${className}`}>
58
58
  <div class="flex min-h-12 flex-col items-center gap-1.5">
59
- <div class="w-0.5 grow bg-neutral group-first:invisible"></div>
59
+ <div class="bg-neutral w-0.5 grow group-first:invisible"></div>
60
60
  <div
61
- class="flex h-5 w-5 shrink-0 items-center justify-center rounded p-0.5 text-secondary {ACTIVITY_BACKGROUND[
61
+ class="text-secondary flex h-5 w-5 shrink-0 items-center justify-center rounded p-0.5 {ACTIVITY_BACKGROUND[
62
62
  activity.icon
63
63
  ]}"
64
64
  >
65
65
  <ActivityIcon icon={activity.icon} />
66
66
  </div>
67
- <div class="w-0.5 grow bg-neutral group-last:invisible"></div>
67
+ <div class="bg-neutral w-0.5 grow group-last:invisible"></div>
68
68
  </div>
69
69
  <div class="flex items-center py-4">
70
70
  <div class="text-secondary">
@@ -43,7 +43,7 @@
43
43
 
44
44
  {#snippet avatar()}
45
45
  <div
46
- class="{sizeClassName} flex items-center justify-center rounded-full border border-static bg-accent text-accent"
46
+ class="{sizeClassName} border-static bg-accent text-accent flex items-center justify-center rounded-full border"
47
47
  >
48
48
  {initials}
49
49
  </div>
@@ -218,9 +218,9 @@
218
218
  </Story>
219
219
 
220
220
  <Story name="Match Trigger Width">
221
- <div class="flex gap-8 bg-base p-12">
221
+ <div class="bg-base flex gap-8 p-12">
222
222
  <div>
223
- <p class="mb-2 text-sm text-secondary">Without matchTriggerWidth</p>
223
+ <p class="text-secondary mb-2 text-sm">Without matchTriggerWidth</p>
224
224
  <Dropdown.Root open>
225
225
  <Dropdown.Trigger class="w-64">Wide Trigger Button</Dropdown.Trigger>
226
226
  <Dropdown.Portal>
@@ -237,7 +237,7 @@
237
237
  </div>
238
238
 
239
239
  <div>
240
- <p class="mb-2 text-sm text-secondary">With matchTriggerWidth</p>
240
+ <p class="text-secondary mb-2 text-sm">With matchTriggerWidth</p>
241
241
  <Dropdown.Root open>
242
242
  <Dropdown.Trigger class="w-64">Wide Trigger Button</Dropdown.Trigger>
243
243
  <Dropdown.Portal>
@@ -283,6 +283,162 @@
283
283
  </div>
284
284
  </Story>
285
285
 
286
+ <Story name="Submenu (Right)">
287
+ <div class="py-12">
288
+ <Dropdown.Root open>
289
+ <Dropdown.Trigger>Menu with Submenu</Dropdown.Trigger>
290
+ <Dropdown.Portal>
291
+ <Dropdown.Content matchTriggerWidth>
292
+ <Dropdown.Item>
293
+ <p>First item</p>
294
+ </Dropdown.Item>
295
+ <Dropdown.Sub>
296
+ <Dropdown.SubTrigger side="right">
297
+ <p>More options</p>
298
+ </Dropdown.SubTrigger>
299
+ <Dropdown.Portal>
300
+ <Dropdown.SubContent side="right">
301
+ <Dropdown.Item>
302
+ <p>Sub item 1</p>
303
+ </Dropdown.Item>
304
+ <Dropdown.Item>
305
+ <p>Sub item 2</p>
306
+ </Dropdown.Item>
307
+ <Dropdown.Item>
308
+ <p>Sub item 3</p>
309
+ </Dropdown.Item>
310
+ </Dropdown.SubContent>
311
+ </Dropdown.Portal>
312
+ </Dropdown.Sub>
313
+ <Dropdown.Item>
314
+ <p>Last item</p>
315
+ </Dropdown.Item>
316
+ </Dropdown.Content>
317
+ </Dropdown.Portal>
318
+ </Dropdown.Root>
319
+ </div>
320
+ </Story>
321
+
322
+ <Story name="Submenu (Left)">
323
+ <div class="flex min-h-[300px] items-center justify-end py-12 pr-12">
324
+ <Dropdown.Root open>
325
+ <Dropdown.Trigger>Menu with Left Submenu</Dropdown.Trigger>
326
+ <Dropdown.Portal>
327
+ <Dropdown.Content>
328
+ <Dropdown.Item>
329
+ <p>First item</p>
330
+ </Dropdown.Item>
331
+ <Dropdown.Sub>
332
+ <Dropdown.SubTrigger side="left">
333
+ <p>More options</p>
334
+ </Dropdown.SubTrigger>
335
+ <Dropdown.Portal>
336
+ <Dropdown.SubContent side="left">
337
+ <Dropdown.Item>
338
+ <p>Sub item 1</p>
339
+ </Dropdown.Item>
340
+ <Dropdown.Item>
341
+ <p>Sub item 2</p>
342
+ </Dropdown.Item>
343
+ <Dropdown.Item>
344
+ <p>Sub item 3</p>
345
+ </Dropdown.Item>
346
+ </Dropdown.SubContent>
347
+ </Dropdown.Portal>
348
+ </Dropdown.Sub>
349
+ <Dropdown.Item>
350
+ <p>Last item</p>
351
+ </Dropdown.Item>
352
+ </Dropdown.Content>
353
+ </Dropdown.Portal>
354
+ </Dropdown.Root>
355
+ </div>
356
+ </Story>
357
+
358
+ <Story name="Nested Submenus">
359
+ <div class="py-12">
360
+ <Dropdown.Root open>
361
+ <Dropdown.Trigger>Nested Menu</Dropdown.Trigger>
362
+ <Dropdown.Portal>
363
+ <Dropdown.Content>
364
+ <Dropdown.Item>
365
+ <p>First item</p>
366
+ </Dropdown.Item>
367
+ <Dropdown.Sub>
368
+ <Dropdown.SubTrigger>
369
+ <p>Settings</p>
370
+ </Dropdown.SubTrigger>
371
+ <Dropdown.Portal>
372
+ <Dropdown.SubContent>
373
+ <Dropdown.Item>
374
+ <p>Profile</p>
375
+ </Dropdown.Item>
376
+ <Dropdown.Sub>
377
+ <Dropdown.SubTrigger>
378
+ <p>Preferences</p>
379
+ </Dropdown.SubTrigger>
380
+ <Dropdown.Portal>
381
+ <Dropdown.SubContent>
382
+ <Dropdown.Item>
383
+ <p>Theme</p>
384
+ </Dropdown.Item>
385
+ <Dropdown.Item>
386
+ <p>Language</p>
387
+ </Dropdown.Item>
388
+ <Dropdown.Item>
389
+ <p>Notifications</p>
390
+ </Dropdown.Item>
391
+ </Dropdown.SubContent>
392
+ </Dropdown.Portal>
393
+ </Dropdown.Sub>
394
+ <Dropdown.Item>
395
+ <p>Security</p>
396
+ </Dropdown.Item>
397
+ </Dropdown.SubContent>
398
+ </Dropdown.Portal>
399
+ </Dropdown.Sub>
400
+ <Dropdown.Item>
401
+ <p>Help</p>
402
+ </Dropdown.Item>
403
+ </Dropdown.Content>
404
+ </Dropdown.Portal>
405
+ </Dropdown.Root>
406
+ </div>
407
+ </Story>
408
+
409
+ <Story name="Submenu with Secondary Variant">
410
+ <div class="py-12">
411
+ <Dropdown.Root open>
412
+ <Dropdown.Trigger variant="secondary">Styled Submenu</Dropdown.Trigger>
413
+ <Dropdown.Portal>
414
+ <Dropdown.Content variant="secondary">
415
+ <Dropdown.Item>
416
+ <p>First item</p>
417
+ </Dropdown.Item>
418
+ <Dropdown.Sub>
419
+ <Dropdown.SubTrigger>
420
+ <p>More options</p>
421
+ </Dropdown.SubTrigger>
422
+ <Dropdown.Portal>
423
+ <Dropdown.SubContent variant="secondary">
424
+ <Dropdown.Item>
425
+ <p>Sub item 1</p>
426
+ </Dropdown.Item>
427
+ <Dropdown.Item>
428
+ <p>Sub item 2</p>
429
+ </Dropdown.Item>
430
+ </Dropdown.SubContent>
431
+ </Dropdown.Portal>
432
+ </Dropdown.Sub>
433
+ <Dropdown.Item>
434
+ <p>Last item</p>
435
+ </Dropdown.Item>
436
+ </Dropdown.Content>
437
+ </Dropdown.Portal>
438
+ </Dropdown.Root>
439
+ </div>
440
+ </Story>
441
+
286
442
  <Story
287
443
  name="Interaction Test"
288
444
  asChild
@@ -341,7 +497,7 @@
341
497
  </Dropdown.Root>
342
498
 
343
499
  {#if selectedOption}
344
- <div class="mt-4 rounded bg-neutral p-2">
500
+ <div class="bg-neutral mt-4 rounded p-2">
345
501
  <p>You selected: <strong>{selectedOption}</strong></p>
346
502
  </div>
347
503
  {/if}
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import { DropdownMenu } from 'bits-ui';
3
+ import type { DropdownSubContentProps } from '../types';
4
+
5
+ let { children, class: className = '', variant = 'primary', ...restProps }: DropdownSubContentProps = $props();
6
+
7
+ const variantClasses: Record<string, string> = {
8
+ primary: 'bg-surface text-primary',
9
+ secondary: 'bg-base-inverse text-primary-inverse',
10
+ };
11
+
12
+ let variantClass = $derived(variantClasses[variant]);
13
+ </script>
14
+
15
+ <DropdownMenu.SubContent
16
+ class="z-10 rounded-md p-1 shadow-menu {variantClass} {className}"
17
+ {...restProps}
18
+ >
19
+ {@render children()}
20
+ </DropdownMenu.SubContent>
@@ -0,0 +1,4 @@
1
+ import type { DropdownSubContentProps } from '../types';
2
+ declare const DropdownSubContent: import("svelte").Component<DropdownSubContentProps, {}, "">;
3
+ type DropdownSubContent = ReturnType<typeof DropdownSubContent>;
4
+ export default DropdownSubContent;
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import { DropdownMenu } from 'bits-ui';
3
+ import CaretRight from 'phosphor-svelte/lib/CaretRight';
4
+ import CaretLeft from 'phosphor-svelte/lib/CaretLeft';
5
+ import { Icon } from '../../icons/index.js';
6
+ import type { DropdownSubTriggerProps } from '../types';
7
+
8
+ let { children, class: className = '', side = 'right', ...restProps }: DropdownSubTriggerProps = $props();
9
+
10
+ let chevronIcon = $derived(side === 'left' ? CaretLeft : CaretRight);
11
+ </script>
12
+
13
+ <DropdownMenu.SubTrigger
14
+ class="flex cursor-pointer items-center justify-between gap-2 rounded-lg px-2 py-1.5 text-sm outline-none transition-colors hover:bg-neutral-hover focus:bg-neutral-hover data-[disabled]:pointer-events-none data-[disabled]:opacity-50 {className}"
15
+ {...restProps}
16
+ >
17
+ {#if side === 'left'}
18
+ <Icon color="tertiary" icon={chevronIcon} size={16} />
19
+ {/if}
20
+ {@render children()}
21
+ {#if side === 'right'}
22
+ <Icon color="tertiary" icon={chevronIcon} size={16} />
23
+ {/if}
24
+ </DropdownMenu.SubTrigger>
@@ -0,0 +1,4 @@
1
+ import type { DropdownSubTriggerProps } from '../types';
2
+ declare const DropdownSubTrigger: import("svelte").Component<DropdownSubTriggerProps, {}, "">;
3
+ type DropdownSubTrigger = ReturnType<typeof DropdownSubTrigger>;
4
+ export default DropdownSubTrigger;
@@ -3,6 +3,8 @@ import Content from './components/dropdown-content.svelte';
3
3
  import Item from './components/dropdown-item.svelte';
4
4
  import Trigger from './components/dropdown-trigger.svelte';
5
5
  import FieldTrigger from './components/dropdown-field-trigger.svelte';
6
+ import SubTrigger from './components/dropdown-sub-trigger.svelte';
7
+ import SubContent from './components/dropdown-sub-content.svelte';
6
8
  export declare const Root: import("svelte").Component<{
7
9
  open?: boolean;
8
10
  onOpenChange?: import("bits-ui/dist/internal/types").OnChangeFn<boolean>;
@@ -15,13 +17,13 @@ export declare const Root: import("svelte").Component<{
15
17
  export declare const Portal: import("svelte").Component<import("bits-ui").PortalProps, {}, "">;
16
18
  export declare const Group: import("svelte").Component<DropdownMenu.GroupProps, {}, "ref">;
17
19
  export declare const Sub: import("svelte").Component<import("bits-ui").ContextMenuSubPropsWithoutHTML, {}, "open">;
18
- export declare const SubTrigger: import("svelte").Component<DropdownMenu.SubTriggerProps, {}, "ref">;
19
- export declare const SubContent: import("svelte").Component<DropdownMenu.SubContentProps, {}, "ref">;
20
20
  export declare const RadioGroup: import("svelte").Component<DropdownMenu.RadioGroupProps, {}, "value" | "ref">;
21
21
  export declare const RadioItem: import("svelte").Component<DropdownMenu.RadioItemProps, {}, "ref">;
22
22
  export declare const CheckboxItem: import("svelte").Component<DropdownMenu.CheckboxItemProps, {}, "ref" | "checked" | "indeterminate">;
23
23
  export declare const Separator: import("svelte").Component<DropdownMenu.SeparatorProps, {}, "ref">;
24
24
  export declare const Arrow: import("svelte").Component<import("bits-ui/dist/bits/utilities/arrow").ArrowProps, {}, "ref">;
25
25
  export declare const RawContent: import("svelte").Component<DropdownMenu.ContentProps, {}, "ref">;
26
- export { Content, Item, Trigger, FieldTrigger };
26
+ export declare const RawSubTrigger: import("svelte").Component<DropdownMenu.SubTriggerProps, {}, "ref">;
27
+ export declare const RawSubContent: import("svelte").Component<DropdownMenu.SubContentProps, {}, "ref">;
28
+ export { Content, Item, Trigger, FieldTrigger, SubTrigger, SubContent };
27
29
  export * from './types';
@@ -4,20 +4,22 @@ import Content from './components/dropdown-content.svelte';
4
4
  import Item from './components/dropdown-item.svelte';
5
5
  import Trigger from './components/dropdown-trigger.svelte';
6
6
  import FieldTrigger from './components/dropdown-field-trigger.svelte';
7
+ import SubTrigger from './components/dropdown-sub-trigger.svelte';
8
+ import SubContent from './components/dropdown-sub-content.svelte';
7
9
  // Re-export DropdownMenu primitives
8
10
  export const Root = DropdownMenu.Root;
9
11
  export const Portal = DropdownMenu.Portal;
10
12
  export const Group = DropdownMenu.Group;
11
13
  export const Sub = DropdownMenu.Sub;
12
- export const SubTrigger = DropdownMenu.SubTrigger;
13
- export const SubContent = DropdownMenu.SubContent;
14
14
  export const RadioGroup = DropdownMenu.RadioGroup;
15
15
  export const RadioItem = DropdownMenu.RadioItem;
16
16
  export const CheckboxItem = DropdownMenu.CheckboxItem;
17
17
  export const Separator = DropdownMenu.Separator;
18
18
  export const Arrow = DropdownMenu.Arrow;
19
- // Export raw Content for components that already have their own styling (e.g., DatePicker)
19
+ // Export raw components for advanced use cases
20
20
  export const RawContent = DropdownMenu.Content;
21
- // Export custom components
22
- export { Content, Item, Trigger, FieldTrigger };
21
+ export const RawSubTrigger = DropdownMenu.SubTrigger;
22
+ export const RawSubContent = DropdownMenu.SubContent;
23
+ // Export custom styled components
24
+ export { Content, Item, Trigger, FieldTrigger, SubTrigger, SubContent };
23
25
  export * from './types';
@@ -1,7 +1,8 @@
1
- import { type DropdownMenuContentProps as BitsDropdownMenuContentProps, type DropdownMenuItemProps as BitsDropdownMenuItemProps, type DropdownMenuTriggerProps as BitsDropdownMenuTriggerProps } from 'bits-ui';
1
+ import { type DropdownMenuContentProps as BitsDropdownMenuContentProps, type DropdownMenuItemProps as BitsDropdownMenuItemProps, type DropdownMenuTriggerProps as BitsDropdownMenuTriggerProps, type DropdownMenuSubTriggerProps as BitsDropdownMenuSubTriggerProps, type DropdownMenuSubContentProps as BitsDropdownMenuSubContentProps } from 'bits-ui';
2
2
  import type { Snippet } from 'svelte';
3
3
  import type { ButtonVariant, ButtonSize } from '../button/Button.svelte';
4
4
  export type DropdownContentVariant = 'primary' | 'secondary';
5
+ export type DropdownSubMenuSide = 'left' | 'right';
5
6
  export type DropdownTriggerProps = {
6
7
  children?: Snippet;
7
8
  customChild?: Snippet<[{
@@ -25,3 +26,13 @@ export type DropdownItemProps = {
25
26
  children: Snippet;
26
27
  class?: string;
27
28
  } & BitsDropdownMenuItemProps;
29
+ export type DropdownSubTriggerProps = {
30
+ children: Snippet;
31
+ class?: string;
32
+ side?: DropdownSubMenuSide;
33
+ } & BitsDropdownMenuSubTriggerProps;
34
+ export type DropdownSubContentProps = {
35
+ children: Snippet;
36
+ class?: string;
37
+ variant?: DropdownContentVariant;
38
+ } & BitsDropdownMenuSubContentProps;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reshape-biotech/design-system",
3
- "version": "2.7.25",
3
+ "version": "2.7.26",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build",