@reshape-biotech/design-system 2.7.32 → 2.7.34

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/app.css CHANGED
@@ -112,4 +112,11 @@
112
112
  html:has(.drawer-auto-gutter .drawer-toggle:checked) {
113
113
  scrollbar-gutter: auto;
114
114
  }
115
+
116
+ /* Global focus styles using brand colors */
117
+ *:focus-visible {
118
+ outline: 2px solid theme('borderColor.hover');
119
+ outline-offset: 1px;
120
+ border-radius: theme('borderRadius.lg');
121
+ }
115
122
  }
@@ -38,7 +38,7 @@
38
38
  loading = false,
39
39
  disabled = false,
40
40
  accessibilityLabel = '',
41
- size = 'lg',
41
+ size = 'md',
42
42
  id = undefined,
43
43
  tabindex = undefined,
44
44
  variant = 'primary',
@@ -463,6 +463,104 @@
463
463
  </div>
464
464
  </Story>
465
465
 
466
+ <Story name="Custom Gap">
467
+ <div class="flex gap-8 py-12">
468
+ <div>
469
+ <p class="mb-2 text-sm text-secondary">Default (gap-1)</p>
470
+ <Dropdown.Root open>
471
+ <Dropdown.Trigger>Default Gap</Dropdown.Trigger>
472
+ <Dropdown.Portal>
473
+ <Dropdown.Content>
474
+ <Dropdown.Item>
475
+ <p>Item 1</p>
476
+ </Dropdown.Item>
477
+ <Dropdown.Item>
478
+ <p>Item 2</p>
479
+ </Dropdown.Item>
480
+ <Dropdown.Item>
481
+ <p>Item 3</p>
482
+ </Dropdown.Item>
483
+ </Dropdown.Content>
484
+ </Dropdown.Portal>
485
+ </Dropdown.Root>
486
+ </div>
487
+
488
+ <div>
489
+ <p class="mb-2 text-sm text-secondary">No gap (gap-0)</p>
490
+ <Dropdown.Root open>
491
+ <Dropdown.Trigger>No Gap</Dropdown.Trigger>
492
+ <Dropdown.Portal>
493
+ <Dropdown.Content gap="gap-0">
494
+ <Dropdown.Item>
495
+ <p>Item 1</p>
496
+ </Dropdown.Item>
497
+ <Dropdown.Item>
498
+ <p>Item 2</p>
499
+ </Dropdown.Item>
500
+ <Dropdown.Item>
501
+ <p>Item 3</p>
502
+ </Dropdown.Item>
503
+ </Dropdown.Content>
504
+ </Dropdown.Portal>
505
+ </Dropdown.Root>
506
+ </div>
507
+
508
+ <div>
509
+ <p class="mb-2 text-sm text-secondary">Large gap (gap-3)</p>
510
+ <Dropdown.Root open>
511
+ <Dropdown.Trigger>Large Gap</Dropdown.Trigger>
512
+ <Dropdown.Portal>
513
+ <Dropdown.Content gap="gap-3">
514
+ <Dropdown.Item>
515
+ <p>Item 1</p>
516
+ </Dropdown.Item>
517
+ <Dropdown.Item>
518
+ <p>Item 2</p>
519
+ </Dropdown.Item>
520
+ <Dropdown.Item>
521
+ <p>Item 3</p>
522
+ </Dropdown.Item>
523
+ </Dropdown.Content>
524
+ </Dropdown.Portal>
525
+ </Dropdown.Root>
526
+ </div>
527
+ </div>
528
+ </Story>
529
+
530
+ <Story name="Submenu with Custom Gap">
531
+ <div class="py-12">
532
+ <Dropdown.Root open>
533
+ <Dropdown.Trigger>Submenu Gap Example</Dropdown.Trigger>
534
+ <Dropdown.Portal>
535
+ <Dropdown.Content gap="gap-2">
536
+ <Dropdown.Item>
537
+ <p>First item</p>
538
+ </Dropdown.Item>
539
+ <Dropdown.Sub open>
540
+ <Dropdown.SubTrigger>
541
+ <p>More options</p>
542
+ </Dropdown.SubTrigger>
543
+ <Dropdown.SubContent gap="gap-0">
544
+ <Dropdown.Item>
545
+ <p>Sub item 1 (no gap)</p>
546
+ </Dropdown.Item>
547
+ <Dropdown.Item>
548
+ <p>Sub item 2 (no gap)</p>
549
+ </Dropdown.Item>
550
+ <Dropdown.Item>
551
+ <p>Sub item 3 (no gap)</p>
552
+ </Dropdown.Item>
553
+ </Dropdown.SubContent>
554
+ </Dropdown.Sub>
555
+ <Dropdown.Item>
556
+ <p>Last item</p>
557
+ </Dropdown.Item>
558
+ </Dropdown.Content>
559
+ </Dropdown.Portal>
560
+ </Dropdown.Root>
561
+ </div>
562
+ </Story>
563
+
466
564
  <Story
467
565
  name="Interaction Test"
468
566
  asChild
@@ -7,6 +7,7 @@
7
7
  class: className = '',
8
8
  variant = 'primary',
9
9
  matchTriggerWidth = false,
10
+ gap = 'gap-1',
10
11
  ...restProps
11
12
  }: DropdownContentProps = $props();
12
13
 
@@ -22,7 +23,7 @@
22
23
  </script>
23
24
 
24
25
  <DropdownMenu.Content
25
- class="z-10 rounded-md p-1 shadow-menu {variantClass} {widthClass} {className}"
26
+ class="z-10 flex flex-col {gap} rounded-md p-1 shadow-menu {variantClass} {widthClass} {className}"
26
27
  {...restProps}
27
28
  >
28
29
  {@render children()}
@@ -18,7 +18,7 @@
18
18
  {:else}
19
19
  <div
20
20
  {...props}
21
- class="h-9 cursor-pointer items-center 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 [&_a]:no-underline {className}"
21
+ class="flex h-9 cursor-pointer items-center 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 [&_a]:no-underline {className}"
22
22
  >
23
23
  {@render children?.()}
24
24
  </div>
@@ -2,7 +2,13 @@
2
2
  import { DropdownMenu } from 'bits-ui';
3
3
  import type { DropdownSubContentProps } from '../types';
4
4
 
5
- let { children, class: className = '', variant = 'primary', ...restProps }: DropdownSubContentProps = $props();
5
+ let {
6
+ children,
7
+ class: className = '',
8
+ variant = 'primary',
9
+ gap = 'gap-1',
10
+ ...restProps
11
+ }: DropdownSubContentProps = $props();
6
12
 
7
13
  const variantClasses: Record<string, string> = {
8
14
  primary: 'bg-surface text-primary',
@@ -13,7 +19,7 @@
13
19
  </script>
14
20
 
15
21
  <DropdownMenu.SubContent
16
- class="z-10 rounded-md p-1 shadow-menu {variantClass} {className}"
22
+ class="z-10 {gap} flex flex-col rounded-md p-1 shadow-menu {variantClass} {className}"
17
23
  {...restProps}
18
24
  >
19
25
  {@render children()}
@@ -17,7 +17,7 @@
17
17
  {:else}
18
18
  <div
19
19
  {...props}
20
- class="flex h-8 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 [&_a]:no-underline {className}"
20
+ class="flex h-9 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 [&_a]:no-underline {className}"
21
21
  >
22
22
  {#if !hideChevron && side === 'left'}
23
23
  <Icon color="tertiary" icon={chevronIcon} size={16} />
@@ -21,6 +21,7 @@ export type DropdownContentProps = {
21
21
  class?: string;
22
22
  variant?: DropdownContentVariant;
23
23
  matchTriggerWidth?: boolean;
24
+ gap?: string;
24
25
  } & BitsDropdownMenuContentProps;
25
26
  export type DropdownItemProps = {
26
27
  children?: Snippet;
@@ -42,4 +43,5 @@ export type DropdownSubContentProps = {
42
43
  children: Snippet;
43
44
  class?: string;
44
45
  variant?: DropdownContentVariant;
46
+ gap?: string;
45
47
  } & BitsDropdownMenuSubContentProps;
@@ -170,7 +170,7 @@ input::placeholder {
170
170
 
171
171
  div:not(:focus-within):hover {
172
172
 
173
- border-color: #5750ee40
173
+ border-color: #5750ee80
174
174
  }
175
175
 
176
176
  div:focus-within {
@@ -1,5 +1,6 @@
1
1
  <script module lang="ts">
2
2
  import Warning from 'phosphor-svelte/lib/Warning';
3
+ import SealCheck from 'phosphor-svelte/lib/SealCheck';
3
4
  import { defineMeta } from '@storybook/addon-svelte-csf';
4
5
  import { Root as ModalRootForMeta } from './index';
5
6
  import * as Modal from './index';
@@ -29,10 +30,10 @@
29
30
  </Modal.Trigger>
30
31
  <Modal.Content>
31
32
  <Modal.Title>Edit Profile</Modal.Title>
32
- <div class="space-y-4">
33
- <p class="text-sm text-secondary">
34
- Make changes to your profile here. Click save when you're done.
35
- </p>
33
+ <Modal.Description>
34
+ Make changes to your profile here. Click save when you're done.
35
+ </Modal.Description>
36
+ <div class="space-y-4 py-2">
36
37
  <div class="space-y-2">
37
38
  <label class="text-sm font-medium" for="name">Name</label>
38
39
  <input id="name" class="w-full rounded border border-input px-3 py-2" value="John Doe" />
@@ -61,7 +62,7 @@
61
62
  </Modal.Trigger>
62
63
  <Modal.Content>
63
64
  <Modal.Title>Are you absolutely sure?</Modal.Title>
64
- <Modal.Description class="text-sm leading-[1.43] tracking-[1.14%] text-secondary">
65
+ <Modal.Description>
65
66
  This action cannot be undone. This will permanently delete your account and remove your data
66
67
  from our servers.
67
68
  </Modal.Description>
@@ -75,16 +76,16 @@
75
76
  </Modal.Root>
76
77
  </Story>
77
78
 
78
- <Story name="Alert Modal (Figma Design)" asChild>
79
+ <Story name="Alert Modal" asChild>
79
80
  <Modal.Root open>
80
81
  <Modal.Trigger>
81
82
  <Button variant="primary">Open Alert Modal</Button>
82
83
  </Modal.Trigger>
83
- <Modal.Content class="w-[544px] max-w-[544px] p-0">
84
+ <Modal.Content withClose={false}>
84
85
  <Modal.Title>
85
86
  {#snippet icon()}
86
87
  <div class="flex h-12 w-12 items-center justify-center rounded-lg bg-danger p-2">
87
- <Icon class="h-7 w-7 text-danger">
88
+ <Icon class="text-icon-danger" size={24}>
88
89
  {#snippet children(props)}
89
90
  <Warning {...props} />
90
91
  {/snippet}
@@ -93,9 +94,8 @@
93
94
  {/snippet}
94
95
  Delete this job?
95
96
  </Modal.Title>
96
- <Modal.Description class="text-sm text-secondary">
97
- "CFU Air" will be permanently deleted for all users in your organization. This action cannot
98
- be undone.
97
+ <Modal.Description>
98
+ This modal doesn't have a close button. You must select one of the action buttons below.
99
99
  </Modal.Description>
100
100
 
101
101
  <Modal.Bottom>
@@ -106,6 +106,46 @@
106
106
  </Modal.Root>
107
107
  </Story>
108
108
 
109
+ <Story name="Sticky Header" asChild>
110
+ <Modal.Root open>
111
+ <Modal.Trigger>
112
+ <Button variant="primary">Modal with Sticky Header</Button>
113
+ </Modal.Trigger>
114
+ <Modal.Content class="flex flex-col p-0" withClose={true}>
115
+ <Modal.Title sticky>
116
+ {#snippet icon()}
117
+ <Icon class="h-5 w-5 text-icon-secondary">
118
+ {#snippet children(props)}
119
+ <SealCheck {...props} />
120
+ {/snippet}
121
+ </Icon>
122
+ {/snippet}
123
+ Sticky Header
124
+ </Modal.Title>
125
+ <Modal.ScrollContent>
126
+ <h4 class="font-semibold">Information</h4>
127
+ <p class="text-sm text-secondary mt-2">
128
+ This is content to demonstrate scrolling. The sticky header and footer will remain visible
129
+ at the top and bottom as you scroll through this modal content.
130
+ </p>
131
+ <div class="space-y-2 mt-4">
132
+ {#each Array(10) as _, i}
133
+ <div class="bg-surface rounded-lg p-3 border border-input">
134
+ <p class="text-sm">Item {i + 1}</p>
135
+ <p class="text-xs text-secondary mt-1">
136
+ This is item number {i + 1} in the list. Continue scrolling to see more items.
137
+ </p>
138
+ </div>
139
+ {/each}
140
+ </div>
141
+ </Modal.ScrollContent>
142
+ <Modal.Bottom sticky>
143
+ <Modal.Close variant="primary">Continue</Modal.Close>
144
+ </Modal.Bottom>
145
+ </Modal.Content>
146
+ </Modal.Root>
147
+ </Story>
148
+
109
149
  <Story name="Custom Button Rendering" asChild>
110
150
  <Modal.Root open>
111
151
  <Modal.Trigger>
@@ -113,7 +153,7 @@
113
153
  </Modal.Trigger>
114
154
  <Modal.Content>
115
155
  <Modal.Title>Custom Button Rendering</Modal.Title>
116
- <Modal.Description class="text-sm text-secondary">
156
+ <Modal.Description>
117
157
  This modal demonstrates rendering custom buttons within Modal.Close components for proper
118
158
  functionality.
119
159
  </Modal.Description>
@@ -130,32 +170,13 @@
130
170
  </Modal.Root>
131
171
  </Story>
132
172
 
133
- <Story name="No Close Button" asChild>
134
- <Modal.Root open>
135
- <Modal.Trigger>
136
- <Button variant="primary">Open Modal (No Close)</Button>
137
- </Modal.Trigger>
138
- <Modal.Content withClose={false}>
139
- <Modal.Title>Alert</Modal.Title>
140
- <div class="space-y-4">
141
- <p class="text-sm text-secondary">
142
- This modal doesn't have a close button. You must use the action buttons below.
143
- </p>
144
- </div>
145
- <Modal.Bottom>
146
- <Modal.Close variant="secondary">Cancel</Modal.Close>
147
- <Modal.Close variant="primary">Continue</Modal.Close>
148
- </Modal.Bottom>
149
- </Modal.Content>
150
- </Modal.Root>
151
- </Story>
152
173
 
153
174
  <Story name="Custom Styling" asChild>
154
175
  <Modal.Root open>
155
176
  <Modal.Trigger>
156
177
  <Button variant="primary">Open Custom Modal</Button>
157
178
  </Modal.Trigger>
158
- <Modal.Content class="min-w-full bg-accent p-8">
179
+ <Modal.Content class="w-2xs bg-accent-inverse" withClose={false}>
159
180
  <Modal.Title class="text-xl text-primary-inverse">Custom Styled Modal</Modal.Title>
160
181
  <div class="space-y-4 pt-4">
161
182
  <p class="text-sm text-secondary-inverse">
@@ -167,7 +188,7 @@
167
188
  </div>
168
189
  </div>
169
190
  <Modal.Bottom>
170
- <Modal.Close variant="secondary">Close</Modal.Close>
191
+ <Modal.Close variant="secondary-inverse">Close</Modal.Close>
171
192
  </Modal.Bottom>
172
193
  </Modal.Content>
173
194
  </Modal.Root>
@@ -226,10 +247,10 @@
226
247
  </Modal.Trigger>
227
248
  <Modal.Content withPortal={false}>
228
249
  <Modal.Title>Edit Profile</Modal.Title>
229
- <div class="space-y-4">
230
- <p class="text-sm text-secondary">
231
- Make changes to your profile here. Click save when you're done.
232
- </p>
250
+ <Modal.Description>
251
+ Make changes to your profile here. Click save when you're done.
252
+ </Modal.Description>
253
+ <div class="space-y-4 py-2">
233
254
  <div class="space-y-2">
234
255
  <label class="text-sm font-medium" for="name">Name</label>
235
256
  <input id="name" class="w-full rounded border border-input px-3 py-2" value="John Doe" />
@@ -2,14 +2,22 @@
2
2
  import { twMerge } from 'tailwind-merge';
3
3
  import type { ModalBottomProps } from '../types';
4
4
 
5
- let { children, class: className = '', ...restProps }: ModalBottomProps = $props();
5
+ let { children, class: className = '', sticky = false, ...restProps }: ModalBottomProps = $props();
6
6
 
7
- const baseClasses = 'border-t border-static -mx-5';
7
+ const baseClasses = '-mx-5';
8
8
  const finalClasses = twMerge(baseClasses, className);
9
9
  </script>
10
10
 
11
- <div class={finalClasses} {...restProps}>
12
- <div class="flex justify-end gap-4 px-5 py-4 pb-0">
13
- {@render children()}
11
+ {#if sticky}
12
+ <div class={twMerge('sticky bottom-0 z-10 w-full shrink-0 bg-surface border-t border-static', className)} {...restProps}>
13
+ <div class="flex justify-end gap-4 px-4 py-3 w-full">
14
+ {@render children()}
15
+ </div>
14
16
  </div>
15
- </div>
17
+ {:else}
18
+ <div class={finalClasses} {...restProps}>
19
+ <div class="flex justify-end gap-4 px-5 pt-4 pb-0">
20
+ {@render children()}
21
+ </div>
22
+ </div>
23
+ {/if}
@@ -1,6 +1,9 @@
1
1
  <script lang="ts">
2
2
  import { Dialog } from 'bits-ui';
3
+ import X from 'phosphor-svelte/lib/X';
3
4
  import Button from '../../button/Button.svelte';
5
+ import { IconButton } from '../../icon-button';
6
+ import { Icon } from '../../icons';
4
7
  import type { ModalCloseProps } from '../types';
5
8
 
6
9
  let {
@@ -13,7 +16,13 @@
13
16
  </script>
14
17
 
15
18
  <Dialog.Close class={className} {...restProps} {disabled}>
16
- <Button {variant} {disabled} tabindex={-1}>
17
- {@render children()}
18
- </Button>
19
+ {#if children}
20
+ <Button {variant} {disabled} tabindex={-1}>
21
+ {@render children()}
22
+ </Button>
23
+ {:else}
24
+ <IconButton variant="transparent" size="sm" {disabled} tabindex={-1} rounded={false}>
25
+ <Icon icon={X} />
26
+ </IconButton>
27
+ {/if}
19
28
  </Dialog.Close>
@@ -1,11 +1,10 @@
1
1
  <script lang="ts">
2
- import X from 'phosphor-svelte/lib/X';
3
- import { Icon } from '../../icons/index.js';
4
2
  import { Dialog } from 'bits-ui';
5
3
  import { scale } from 'svelte/transition';
6
4
  import { twMerge } from 'tailwind-merge';
7
5
  import type { ModalContentProps } from '../types';
8
6
  import Overlay from './modal-overlay.svelte';
7
+ import Close from './modal-close.svelte';
9
8
 
10
9
  let {
11
10
  children,
@@ -17,17 +16,13 @@
17
16
  }: ModalContentProps = $props();
18
17
 
19
18
  const baseClasses =
20
- 'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 bg-surface p-5 shadow-lg sm:rounded-lg';
19
+ 'fixed left-1/2 top-1/2 z-50 flex flex-col w-[calc(100%-2rem)] max-w-lg -translate-x-1/2 -translate-y-1/2 p-5 bg-surface shadow-menu rounded-xl overflow-hidden max-h-[calc(100vh-4rem)]';
21
20
  const finalClasses = twMerge(baseClasses, className);
22
21
  </script>
23
22
 
24
23
  {#snippet withCloseButton()}
25
24
  {#if withClose}
26
- <Dialog.Close
27
- class="ring-offset-background focus:ring-ring absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none"
28
- >
29
- <Icon icon={X} />
30
- </Dialog.Close>
25
+ <Close class="absolute right-2 top-2 z-20" />
31
26
  {/if}
32
27
  {/snippet}
33
28
 
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import { Dialog } from 'bits-ui';
3
+ import type { ModalDescriptionProps } from '../types';
4
+ import { twMerge } from 'tailwind-merge';
5
+
6
+ let { children, class: className = '', ...restProps }: ModalDescriptionProps = $props();
7
+
8
+ const baseClasses = 'text-sm text-secondary py-2';
9
+ const finalClasses = twMerge(baseClasses, className);
10
+ </script>
11
+
12
+ <Dialog.Description class={finalClasses} {...restProps}>
13
+ {@render children()}
14
+ </Dialog.Description>
15
+
@@ -0,0 +1,4 @@
1
+ import type { ModalDescriptionProps } from '../types';
2
+ declare const ModalDescription: import("svelte").Component<ModalDescriptionProps, {}, "">;
3
+ type ModalDescription = ReturnType<typeof ModalDescription>;
4
+ export default ModalDescription;
@@ -0,0 +1,14 @@
1
+ <script lang="ts">
2
+ import { twMerge } from 'tailwind-merge';
3
+ import type { ModalScrollContentProps } from '../types';
4
+
5
+ let { children, class: className = '', ...restProps }: ModalScrollContentProps = $props();
6
+
7
+ const baseClasses = 'flex-1 overflow-y-auto min-h-0 p-5';
8
+ const finalClasses = twMerge(baseClasses, className);
9
+ </script>
10
+
11
+ <div class={finalClasses} tabindex="-1" {...restProps}>
12
+ {@render children()}
13
+ </div>
14
+
@@ -0,0 +1,4 @@
1
+ import type { ModalScrollContentProps } from '../types';
2
+ declare const ModalScrollContent: import("svelte").Component<ModalScrollContentProps, {}, "">;
3
+ type ModalScrollContent = ReturnType<typeof ModalScrollContent>;
4
+ export default ModalScrollContent;
@@ -3,19 +3,38 @@
3
3
  import type { ModalTitleProps } from '../types';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
 
6
- let { children, class: className = '', icon, ...restProps }: ModalTitleProps = $props();
6
+ let { children, class: className = '', icon, sticky = false, ...restProps }: ModalTitleProps = $props();
7
7
 
8
- const baseClasses = 'text-xl font-semibold tracking-tight text-primary';
9
- const finalClasses = twMerge(baseClasses, className);
8
+ const baseClasses = $derived(sticky
9
+ ? 'text-base font-semibold tracking-tight text-primary'
10
+ : 'text-xl font-semibold tracking-tight text-primary');
11
+ const finalClasses = $derived(twMerge(baseClasses, className));
10
12
  </script>
11
13
 
12
- <div class="space-y-6">
13
- {#if icon}
14
- <div class="flex justify-start">
15
- {@render icon()}
14
+ {#if sticky}
15
+ <div class="sticky top-0 z-10 w-full h-12 shrink-0 bg-surface border-b border-static">
16
+ <div class="flex h-12 items-center justify-between overflow-hidden px-4 py-2 w-full">
17
+ <div class="flex gap-2 items-center relative shrink-0">
18
+ {#if icon}
19
+ <div class="relative shrink-0 text-icon-secondary">
20
+ {@render icon()}
21
+ </div>
22
+ {/if}
23
+ <Dialog.Title class={finalClasses} {...restProps}>
24
+ {@render children()}
25
+ </Dialog.Title>
26
+ </div>
16
27
  </div>
17
- {/if}
18
- <Dialog.Title class={finalClasses} {...restProps}>
19
- {@render children()}
20
- </Dialog.Title>
21
- </div>
28
+ </div>
29
+ {:else}
30
+ <div class="space-y-5">
31
+ {#if icon}
32
+ <div class="flex justify-start">
33
+ {@render icon()}
34
+ </div>
35
+ {/if}
36
+ <Dialog.Title class={finalClasses} {...restProps}>
37
+ {@render children()}
38
+ </Dialog.Title>
39
+ </div>
40
+ {/if}
@@ -1,12 +1,12 @@
1
- import { Dialog } from 'bits-ui';
2
1
  import Content from './components/modal-content.svelte';
3
2
  import Overlay from './components/modal-overlay.svelte';
4
3
  import Trigger from './components/modal-trigger.svelte';
5
4
  import Title from './components/modal-title.svelte';
5
+ import Description from './components/modal-description.svelte';
6
+ import ScrollContent from './components/modal-scroll-content.svelte';
6
7
  import Bottom from './components/modal-bottom.svelte';
7
8
  import Close from './components/modal-close.svelte';
8
9
  export declare const Root: import("svelte").Component<import("bits-ui").AlertDialogRootPropsWithoutHTML, {}, "open">;
9
10
  export declare const Portal: import("svelte").Component<import("bits-ui").PortalProps, {}, "">;
10
- export declare const Description: import("svelte").Component<Dialog.DescriptionProps, {}, "ref">;
11
- export { Content, Overlay, Trigger, Title, Bottom, Close };
11
+ export { Content, Overlay, Trigger, Title, Description, ScrollContent, Bottom, Close };
12
12
  export * from './types';
@@ -4,12 +4,13 @@ import Content from './components/modal-content.svelte';
4
4
  import Overlay from './components/modal-overlay.svelte';
5
5
  import Trigger from './components/modal-trigger.svelte';
6
6
  import Title from './components/modal-title.svelte';
7
+ import Description from './components/modal-description.svelte';
8
+ import ScrollContent from './components/modal-scroll-content.svelte';
7
9
  import Bottom from './components/modal-bottom.svelte';
8
10
  import Close from './components/modal-close.svelte';
9
11
  // Re-export Dialog primitives
10
12
  export const Root = Dialog.Root;
11
13
  export const Portal = Dialog.Portal;
12
- export const Description = Dialog.Description;
13
14
  // Export custom components
14
- export { Content, Overlay, Trigger, Title, Bottom, Close };
15
+ export { Content, Overlay, Trigger, Title, Description, ScrollContent, Bottom, Close };
15
16
  export * from './types';
@@ -1,4 +1,4 @@
1
- import { type DialogContentProps as BitsDialogContentProps, type DialogOverlayProps as BitsDialogOverlayProps, type DialogTriggerProps as BitsDialogTriggerProps, type DialogTitleProps as BitsDialogTitleProps, type DialogCloseProps as BitsDialogCloseProps } from 'bits-ui';
1
+ import { type DialogContentProps as BitsDialogContentProps, type DialogOverlayProps as BitsDialogOverlayProps, type DialogTriggerProps as BitsDialogTriggerProps, type DialogTitleProps as BitsDialogTitleProps, type DialogDescriptionProps as BitsDialogDescriptionProps, type DialogCloseProps as BitsDialogCloseProps } from 'bits-ui';
2
2
  import type { Snippet } from 'svelte';
3
3
  import type { HTMLAttributes } from 'svelte/elements';
4
4
  import type { ButtonVariant } from '../button/Button.svelte';
@@ -18,13 +18,23 @@ export type ModalTitleProps = {
18
18
  children: Snippet;
19
19
  class?: string;
20
20
  icon?: Snippet;
21
+ sticky?: boolean;
21
22
  } & BitsDialogTitleProps;
23
+ export type ModalDescriptionProps = {
24
+ children: Snippet;
25
+ class?: string;
26
+ } & BitsDialogDescriptionProps;
27
+ export type ModalScrollContentProps = {
28
+ children: Snippet;
29
+ class?: string;
30
+ } & HTMLAttributes<HTMLDivElement>;
22
31
  export type ModalBottomProps = {
23
32
  children: Snippet;
24
33
  class?: string;
34
+ sticky?: boolean;
25
35
  } & HTMLAttributes<HTMLDivElement>;
26
36
  export type ModalCloseProps = {
27
- children: Snippet;
37
+ children?: Snippet;
28
38
  class?: string;
29
39
  variant?: ButtonVariant;
30
40
  onclick?: (event: MouseEvent) => void;
@@ -494,6 +494,28 @@ declare const config: {
494
494
  hover: string;
495
495
  focus: string;
496
496
  };
497
+ ringColor: {
498
+ 'dark-static': string;
499
+ 'dark-input': string;
500
+ 'dark-interactive': string;
501
+ 'dark-hover': string;
502
+ 'dark-focus': string;
503
+ 'dark-danger': string;
504
+ static: string;
505
+ input: string;
506
+ interactive: string;
507
+ hover: string;
508
+ focus: string;
509
+ danger: string;
510
+ 'static-inverse': string;
511
+ 'interactive-inverse': string;
512
+ 'blue-inverse': string;
513
+ 'orange-inverse': string;
514
+ 'pink-inverse': string;
515
+ 'lime-inverse': string;
516
+ white: string;
517
+ axis: string;
518
+ };
497
519
  fontFamily: {
498
520
  mono: string[];
499
521
  sans: string[];
@@ -11,6 +11,9 @@ const config = {
11
11
  textColor,
12
12
  boxShadow,
13
13
  outlineColor,
14
+ ringColor: {
15
+ ...borderColor,
16
+ },
14
17
  fontFamily: {
15
18
  mono: ['"Geist Mono"', 'monospace'],
16
19
  sans: ['"af Another Sans"', 'sans-serif'],
package/dist/tokens.js CHANGED
@@ -43,7 +43,7 @@ const lightBorderColor = {
43
43
  static: colors.base.midnight[8],
44
44
  input: colors.base.midnight[10],
45
45
  interactive: colors.base.midnight[15],
46
- hover: colors.periwinkle[5][25],
46
+ hover: colors.periwinkle[5][50],
47
47
  focus: colors.periwinkle[5].default,
48
48
  danger: colors.red[5].default,
49
49
  'static-inverse': colors.base.white[10],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reshape-biotech/design-system",
3
- "version": "2.7.32",
3
+ "version": "2.7.34",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build",