@db-vincent/components 0.1.0 → 0.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.
Files changed (66) hide show
  1. package/package.json +3 -3
  2. package/src/astro/Avatar.astro +88 -0
  3. package/src/astro/AvatarGroup.astro +63 -0
  4. package/src/astro/Chip.astro +22 -3
  5. package/src/astro/Drawer.astro +30 -0
  6. package/src/astro/Grid.astro +7 -1
  7. package/src/astro/GridItem.astro +3 -1
  8. package/src/astro/Menu.astro +151 -0
  9. package/src/astro/MenuItem.astro +57 -0
  10. package/src/astro/Modal.astro +10 -3
  11. package/src/astro/Pagination.astro +82 -32
  12. package/src/astro/Popover.astro +51 -0
  13. package/src/astro/Progress.astro +71 -0
  14. package/src/astro/Select.astro +211 -194
  15. package/src/astro/Skeleton.astro +4 -2
  16. package/src/astro/Spinner.astro +1 -0
  17. package/src/astro/Stepper.astro +82 -0
  18. package/src/astro/Switch.astro +78 -0
  19. package/src/astro/Table.astro +90 -76
  20. package/src/astro/Tabs.astro +83 -0
  21. package/src/astro/TextField.astro +100 -82
  22. package/src/astro/Toast.astro +1 -1
  23. package/src/astro/Tooltip.astro +54 -0
  24. package/src/data/icons.ts +16 -0
  25. package/src/scripts/avatar.ts +33 -0
  26. package/src/scripts/menu.ts +218 -0
  27. package/src/scripts/tabs.ts +127 -0
  28. package/src/scripts/toast.ts +45 -11
  29. package/src/scripts/tooltip.ts +127 -0
  30. package/src/styles/accordion.css +2 -0
  31. package/src/styles/alert.css +2 -0
  32. package/src/styles/avatar.css +131 -0
  33. package/src/styles/badge.css +2 -0
  34. package/src/styles/base.css +2 -0
  35. package/src/styles/breadcrumbs.css +2 -0
  36. package/src/styles/button.css +13 -2
  37. package/src/styles/card.css +8 -4
  38. package/src/styles/chip.css +2 -0
  39. package/src/styles/choice.css +8 -2
  40. package/src/styles/code.css +2 -0
  41. package/src/styles/empty.css +2 -0
  42. package/src/styles/example.css +2 -0
  43. package/src/styles/grid.css +2 -0
  44. package/src/styles/input.css +11 -1
  45. package/src/styles/menu.css +151 -0
  46. package/src/styles/modal.css +169 -27
  47. package/src/styles/motion.css +21 -3
  48. package/src/styles/nav.css +2 -0
  49. package/src/styles/navbar.css +2 -0
  50. package/src/styles/page-header.css +3 -0
  51. package/src/styles/pagination.css +4 -0
  52. package/src/styles/popover.css +134 -0
  53. package/src/styles/progress.css +95 -0
  54. package/src/styles/section.css +2 -0
  55. package/src/styles/select.css +12 -1
  56. package/src/styles/skeleton.css +2 -0
  57. package/src/styles/spinner.css +2 -0
  58. package/src/styles/sr-only.css +14 -0
  59. package/src/styles/stepper.css +169 -0
  60. package/src/styles/switch.css +143 -0
  61. package/src/styles/table.css +2 -0
  62. package/src/styles/tabs.css +120 -0
  63. package/src/styles/theme-toggle.css +2 -0
  64. package/src/styles/toast.css +41 -23
  65. package/src/styles/tooltip.css +63 -0
  66. package/src/styles/topbar.css +2 -0
@@ -0,0 +1,131 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
3
+ @layer components {
4
+ .ds-avatar {
5
+ --ds-avatar-size: var(--avatar-size-md);
6
+ --ds-avatar-font-size: var(--avatar-font-size-md);
7
+ --ds-avatar-status-size: var(--avatar-status-size-md);
8
+ --ds-avatar-radius: var(--avatar-radius-circle);
9
+
10
+ border-radius: var(--ds-avatar-radius);
11
+ display: inline-flex;
12
+ flex: none;
13
+ height: var(--ds-avatar-size);
14
+ position: relative;
15
+ vertical-align: middle;
16
+ width: var(--ds-avatar-size);
17
+ }
18
+
19
+ .ds-avatar--sm {
20
+ --ds-avatar-size: var(--avatar-size-sm);
21
+ --ds-avatar-font-size: var(--avatar-font-size-sm);
22
+ --ds-avatar-status-size: var(--avatar-status-size-sm);
23
+ }
24
+
25
+ .ds-avatar--lg {
26
+ --ds-avatar-size: var(--avatar-size-lg);
27
+ --ds-avatar-font-size: var(--avatar-font-size-lg);
28
+ --ds-avatar-status-size: var(--avatar-status-size-lg);
29
+ }
30
+
31
+ .ds-avatar--square {
32
+ --ds-avatar-radius: var(--avatar-radius-square);
33
+ }
34
+
35
+ .ds-avatar__face {
36
+ background: var(--avatar-bg);
37
+ border: 1px solid var(--avatar-border);
38
+ border-radius: inherit;
39
+ color: var(--avatar-fg);
40
+ display: grid;
41
+ inset: 0;
42
+ overflow: hidden;
43
+ place-items: center;
44
+ position: absolute;
45
+ }
46
+
47
+ .ds-avatar__fallback {
48
+ font-family: var(--avatar-font);
49
+ font-size: var(--ds-avatar-font-size);
50
+ font-weight: var(--avatar-font-weight);
51
+ letter-spacing: var(--type-label-tracking);
52
+ line-height: 1;
53
+ user-select: none;
54
+ }
55
+
56
+ .ds-avatar__count {
57
+ font-family: var(--avatar-count-font);
58
+ font-variant-numeric: tabular-nums;
59
+ }
60
+
61
+ .ds-avatar__img {
62
+ grid-area: 1 / 1;
63
+ height: 100%;
64
+ object-fit: cover;
65
+ width: 100%;
66
+ }
67
+
68
+ .ds-avatar__fallback {
69
+ grid-area: 1 / 1;
70
+ }
71
+
72
+ .ds-avatar[data-failed] .ds-avatar__img {
73
+ display: none;
74
+ }
75
+
76
+ /* Status is never colour alone: busy carries a bar, away and offline are
77
+ hollow, and the text lives in the avatar's accessible name. */
78
+ .ds-avatar__status {
79
+ --ds-avatar-status-color: var(--avatar-status-online);
80
+
81
+ background: var(--ds-avatar-status-color);
82
+ border: 1px solid var(--ds-avatar-status-color);
83
+ border-radius: var(--avatar-radius-circle);
84
+ height: var(--ds-avatar-status-size);
85
+ inset-block-end: 0;
86
+ inset-inline-end: 0;
87
+ outline: var(--avatar-ring-width) solid var(--avatar-ring);
88
+ position: absolute;
89
+ width: var(--ds-avatar-status-size);
90
+ }
91
+
92
+ .ds-avatar__status--away {
93
+ --ds-avatar-status-color: var(--avatar-status-away);
94
+
95
+ background: var(--avatar-status-mark);
96
+ }
97
+
98
+ .ds-avatar__status--busy {
99
+ --ds-avatar-status-color: var(--avatar-status-busy);
100
+ }
101
+
102
+ .ds-avatar__status--busy::after {
103
+ background: var(--avatar-status-mark);
104
+ content: "";
105
+ height: var(--avatar-ring-width);
106
+ inset-inline: 20%;
107
+ position: absolute;
108
+ top: calc(50% - var(--avatar-ring-width) / 2);
109
+ }
110
+
111
+ .ds-avatar__status--offline {
112
+ --ds-avatar-status-color: var(--avatar-status-offline);
113
+
114
+ background: var(--avatar-status-mark);
115
+ }
116
+
117
+ .ds-avatar-group {
118
+ align-items: center;
119
+ display: inline-flex;
120
+ }
121
+
122
+ .ds-avatar-group .ds-avatar {
123
+ outline: var(--avatar-ring-width) solid var(--avatar-ring);
124
+ }
125
+
126
+ .ds-avatar-group .ds-avatar + .ds-avatar {
127
+ margin-inline-start: calc(
128
+ var(--ds-avatar-size) * -1 * var(--avatar-overlap-ratio)
129
+ );
130
+ }
131
+ }
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-badge {
3
5
  align-items: center;
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer base {
2
4
  *,
3
5
  *::before,
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-breadcrumbs {
3
5
  font-size: var(--breadcrumbs-font-size);
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-button {
3
5
  align-items: center;
@@ -20,7 +22,8 @@
20
22
  background-color var(--duration-fast) var(--ease-standard),
21
23
  border-color var(--duration-fast) var(--ease-standard),
22
24
  color var(--duration-fast) var(--ease-standard),
23
- box-shadow var(--duration-fast) var(--ease-standard);
25
+ box-shadow var(--duration-fast) var(--ease-standard),
26
+ transform var(--duration-fast) var(--ease-standard);
24
27
  user-select: none;
25
28
  white-space: nowrap;
26
29
  }
@@ -34,6 +37,10 @@
34
37
  background: var(--button-secondary-bg-active);
35
38
  }
36
39
 
40
+ .ds-button:active:not(:disabled, [aria-disabled="true"]) {
41
+ transform: scale(0.97);
42
+ }
43
+
37
44
  .ds-button:focus-visible {
38
45
  outline: var(--button-focus-width) solid var(--button-focus-color);
39
46
  outline-offset: var(--button-focus-offset);
@@ -137,7 +144,7 @@
137
144
  }
138
145
 
139
146
  .ds-button__spinner {
140
- animation: ds-button-spin var(--duration-slower) linear infinite;
147
+ animation: ds-button-spin calc(var(--duration-slower) * 2) linear infinite;
141
148
  border: var(--spinner-stroke) solid currentColor;
142
149
  border-right-color: transparent;
143
150
  border-radius: var(--radius-full);
@@ -156,6 +163,10 @@
156
163
  }
157
164
 
158
165
  @media (prefers-reduced-motion: reduce) {
166
+ .ds-button:active:not(:disabled, [aria-disabled="true"]) {
167
+ transform: none;
168
+ }
169
+
159
170
  .ds-button__spinner {
160
171
  animation-duration: 1.6s;
161
172
  }
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-card {
3
5
  background: var(--card-bg);
@@ -33,10 +35,12 @@
33
35
  text-decoration: none;
34
36
  }
35
37
 
36
- a.ds-card:hover {
37
- border-color: var(--card-hover-border);
38
- box-shadow: var(--card-raised-shadow);
39
- transform: translateY(-1px);
38
+ @media (hover: hover) and (pointer: fine) {
39
+ a.ds-card:hover {
40
+ border-color: var(--card-hover-border);
41
+ box-shadow: var(--card-raised-shadow);
42
+ transform: translateY(-1px);
43
+ }
40
44
  }
41
45
 
42
46
  a.ds-card:focus-visible {
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-chip {
3
5
  align-items: center;
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-choice {
3
5
  align-items: flex-start;
@@ -101,12 +103,16 @@
101
103
  border-radius: var(--radius-full);
102
104
  content: "";
103
105
  height: var(--radio-dot-size);
104
- transform: scale(0);
105
- transition: transform var(--duration-fast) var(--ease-standard);
106
+ opacity: 0;
107
+ transform: scale(0.5);
108
+ transition:
109
+ opacity var(--duration-fast) var(--ease-standard),
110
+ transform var(--duration-fast) var(--ease-standard);
106
111
  width: var(--radio-dot-size);
107
112
  }
108
113
 
109
114
  .ds-choice--radio .ds-choice__input:checked + .ds-choice__box::after {
115
+ opacity: 1;
110
116
  transform: scale(1);
111
117
  }
112
118
 
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-code {
3
5
  margin: 0;
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-empty {
3
5
  align-items: center;
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-example {
3
5
  display: grid;
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-grid {
3
5
  display: grid;
@@ -1,3 +1,5 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
2
4
  .ds-field {
3
5
  display: grid;
@@ -58,7 +60,7 @@
58
60
  box-shadow:
59
61
  0 0 0 var(--input-focus-width) var(--input-bg),
60
62
  0 0 0 calc(var(--input-focus-width) * 2) var(--input-ring-focus);
61
- outline: none;
63
+ outline: 2px solid transparent;
62
64
  }
63
65
 
64
66
  .ds-input--sm {
@@ -104,6 +106,14 @@
104
106
  resize: vertical;
105
107
  }
106
108
 
109
+ textarea.ds-input--resize-none {
110
+ resize: none;
111
+ }
112
+
113
+ textarea.ds-input--resize-both {
114
+ resize: both;
115
+ }
116
+
107
117
  .ds-field__hint,
108
118
  .ds-field__error {
109
119
  align-items: flex-start;
@@ -0,0 +1,151 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
3
+ /* The surface, animation and anchoring come from popover.css. */
4
+ @layer components {
5
+ .ds-menu {
6
+ max-height: min(var(--menu-max-height), calc(100dvh - var(--space-8)));
7
+ min-width: var(--menu-min-width);
8
+ overflow-y: auto;
9
+ padding: var(--menu-padding);
10
+ }
11
+
12
+ /* Focus lands on the surface after a pointer open so no row looks chosen;
13
+ the rows draw the focus ring as soon as it moves. */
14
+ .ds-menu:focus-visible {
15
+ outline: 0;
16
+ }
17
+
18
+ /* Menus align to the trigger's start edge instead of centring on it. */
19
+ @supports (position-area: block-end) {
20
+ .ds-menu.ds-popover--bottom,
21
+ .ds-menu.ds-popover--top {
22
+ justify-self: normal;
23
+ position-try-fallbacks:
24
+ flip-block,
25
+ flip-inline,
26
+ flip-block flip-inline;
27
+ }
28
+
29
+ .ds-menu.ds-popover--bottom {
30
+ position-area: block-end span-inline-end;
31
+ transform-origin: top left;
32
+ }
33
+
34
+ .ds-menu.ds-popover--top {
35
+ position-area: block-start span-inline-end;
36
+ transform-origin: bottom left;
37
+ }
38
+
39
+ .ds-menu.ds-popover--start,
40
+ .ds-menu.ds-popover--end {
41
+ align-self: normal;
42
+ position-try-fallbacks:
43
+ flip-inline,
44
+ flip-block,
45
+ flip-block flip-inline;
46
+ }
47
+
48
+ .ds-menu.ds-popover--start {
49
+ position-area: inline-start span-block-end;
50
+ transform-origin: top right;
51
+ }
52
+
53
+ .ds-menu.ds-popover--end {
54
+ position-area: inline-end span-block-end;
55
+ transform-origin: top left;
56
+ }
57
+ }
58
+
59
+ .ds-menu__item {
60
+ align-items: center;
61
+ background: transparent;
62
+ border: 0;
63
+ border-radius: var(--menu-item-radius);
64
+ color: var(--menu-item-fg);
65
+ cursor: pointer;
66
+ display: flex;
67
+ font-family: var(--font-body);
68
+ font-size: var(--menu-item-font-size);
69
+ gap: var(--menu-item-gap);
70
+ line-height: var(--menu-item-line-height);
71
+ padding: var(--menu-item-padding-y) var(--menu-item-padding-x);
72
+ text-align: start;
73
+ text-decoration: none;
74
+ width: 100%;
75
+ }
76
+
77
+ .ds-menu__item:focus {
78
+ background: var(--menu-item-bg-active);
79
+ outline: 0;
80
+ }
81
+
82
+ @media (hover: hover) and (pointer: fine) {
83
+ .ds-menu__item:hover {
84
+ background: var(--menu-item-bg-active);
85
+ }
86
+ }
87
+
88
+ .ds-menu__item:focus-visible {
89
+ outline: var(--menu-focus-width) solid var(--menu-focus-color);
90
+ outline-offset: var(--menu-focus-offset);
91
+ }
92
+
93
+ .ds-menu__item[aria-disabled="true"] {
94
+ color: var(--menu-item-fg-disabled);
95
+ cursor: not-allowed;
96
+ }
97
+
98
+ .ds-menu__item--danger {
99
+ color: var(--menu-item-danger-fg);
100
+ }
101
+
102
+ .ds-menu__item--danger:focus {
103
+ background: var(--menu-item-danger-bg-active);
104
+ }
105
+
106
+ @media (hover: hover) and (pointer: fine) {
107
+ .ds-menu__item--danger:hover:not([aria-disabled="true"]) {
108
+ background: var(--menu-item-danger-bg-active);
109
+ }
110
+ }
111
+
112
+ .ds-menu__icon {
113
+ color: var(--menu-icon-fg);
114
+ display: inline-flex;
115
+ flex: none;
116
+ }
117
+
118
+ .ds-menu__item--danger .ds-menu__icon {
119
+ color: inherit;
120
+ }
121
+
122
+ .ds-menu__item[aria-disabled="true"] .ds-menu__icon {
123
+ color: inherit;
124
+ }
125
+
126
+ .ds-menu__indicator {
127
+ color: var(--menu-indicator-fg);
128
+ display: inline-flex;
129
+ flex: none;
130
+ height: var(--menu-indicator-size);
131
+ width: var(--menu-indicator-size);
132
+ }
133
+
134
+ .ds-menu__item[aria-checked="false"] .ds-menu__indicator > * {
135
+ visibility: hidden;
136
+ }
137
+
138
+ .ds-menu__label {
139
+ color: var(--menu-label-fg);
140
+ font-size: var(--menu-label-font-size);
141
+ font-weight: var(--weight-medium);
142
+ line-height: var(--leading-xs);
143
+ padding: var(--menu-item-padding-y) var(--menu-item-padding-x);
144
+ }
145
+
146
+ .ds-menu__separator {
147
+ border-block-start: 1px solid var(--menu-separator);
148
+ height: 0;
149
+ margin-block: var(--space-1);
150
+ }
151
+ }
@@ -1,4 +1,12 @@
1
+ @layer reset, tokens, base, components, motion, utilities;
2
+
1
3
  @layer components {
4
+ /* showModal() makes the page inert but does not stop it scrolling. */
5
+ html:has(.ds-modal[open]) {
6
+ overflow: hidden;
7
+ scrollbar-gutter: stable;
8
+ }
9
+
2
10
  .ds-modal {
3
11
  background: var(--modal-bg);
4
12
  border: 1px solid var(--modal-border);
@@ -8,36 +16,159 @@
8
16
  margin: auto;
9
17
  max-height: calc(100dvh - var(--space-8));
10
18
  max-width: var(--modal-max-width-md);
19
+ opacity: 0;
11
20
  overflow: auto;
12
21
  padding: 0;
22
+ transform: scale(0.98);
23
+ transition:
24
+ opacity 120ms var(--ease-standard),
25
+ transform 120ms var(--ease-standard),
26
+ display 120ms allow-discrete,
27
+ overlay 120ms allow-discrete;
13
28
  width: calc(100% - var(--space-8));
14
29
  }
15
30
 
31
+ .ds-modal[open] {
32
+ opacity: 1;
33
+ transform: none;
34
+ transition:
35
+ opacity 200ms var(--ease-enter),
36
+ transform 200ms var(--ease-enter),
37
+ display 200ms allow-discrete,
38
+ overlay 200ms allow-discrete;
39
+ }
40
+
16
41
  .ds-modal::backdrop {
17
42
  background: var(--modal-backdrop);
43
+ opacity: 0;
44
+ transition:
45
+ opacity 180ms var(--ease-standard),
46
+ display 180ms allow-discrete,
47
+ overlay 180ms allow-discrete;
48
+ }
49
+
50
+ .ds-modal[open]::backdrop {
51
+ opacity: 1;
18
52
  }
19
53
 
20
- .ds-modal--sheet {
21
- border-end-start-radius: 0;
22
- border-end-end-radius: 0;
54
+ /* Edge-anchored dialogs (drawer: start, end, bottom) slide in from the edge
55
+ they sit on. Enter is slower than exit. */
56
+ .ds-modal--drawer {
57
+ --ds-modal-from: translateY(100%);
58
+
59
+ opacity: 1;
60
+ transform: var(--ds-modal-from);
61
+ transition:
62
+ transform var(--modal-drawer-duration-exit) var(--ease-standard),
63
+ display var(--modal-drawer-duration-exit) allow-discrete,
64
+ overlay var(--modal-drawer-duration-exit) allow-discrete;
65
+ }
66
+
67
+ .ds-modal--drawer[open] {
68
+ transform: none;
69
+ transition:
70
+ transform var(--modal-drawer-duration-enter) var(--ease-drawer),
71
+ display var(--modal-drawer-duration-enter) allow-discrete,
72
+ overlay var(--modal-drawer-duration-enter) allow-discrete;
73
+ }
74
+
75
+ /* Header and footer stay put; the body scrolls. */
76
+ .ds-modal--drawer {
77
+ border-radius: 0;
78
+ margin-block: 0;
79
+ max-width: 100%;
80
+ overflow: hidden;
81
+ }
82
+
83
+ /* Bottom: full-width sheet, top corners rounded, capped height so the page
84
+ stays visible behind it. */
85
+ .ds-modal--bottom {
86
+ border-start-end-radius: var(--modal-radius);
87
+ border-start-start-radius: var(--modal-radius);
23
88
  margin-block: auto 0;
24
89
  max-height: 90dvh;
25
90
  max-width: var(--modal-max-width-lg);
26
91
  width: 100%;
27
92
  }
28
93
 
29
- @media (max-width: 699px) {
30
- .ds-modal--sheet {
31
- max-width: 100%;
32
- }
94
+ /* Start and end: full height, pinned to one inline edge. */
95
+ .ds-modal--start,
96
+ .ds-modal--end {
97
+ height: 100dvh;
98
+ max-height: 100dvh;
99
+ width: min(var(--modal-drawer-width-md), calc(100% - var(--space-8)));
33
100
  }
34
101
 
35
- .ds-modal[open] {
36
- animation: ds-modal-in var(--duration-base) var(--ease-enter);
102
+ .ds-modal--start.ds-modal--sm,
103
+ .ds-modal--end.ds-modal--sm {
104
+ width: min(var(--modal-drawer-width-sm), calc(100% - var(--space-8)));
105
+ }
106
+
107
+ .ds-modal--start.ds-modal--lg,
108
+ .ds-modal--end.ds-modal--lg {
109
+ width: min(var(--modal-drawer-width-lg), calc(100% - var(--space-8)));
110
+ }
111
+
112
+ .ds-modal--drawer[open] {
113
+ display: flex;
114
+ flex-direction: column;
115
+ }
116
+
117
+ .ds-modal--drawer .ds-modal__header,
118
+ .ds-modal--drawer .ds-modal__footer {
119
+ flex: none;
120
+ }
121
+
122
+ .ds-modal--drawer .ds-modal__body {
123
+ flex: 1;
124
+ min-height: 0;
125
+ overflow: auto;
126
+ }
127
+
128
+ .ds-modal--start {
129
+ --ds-modal-from: translateX(-100%);
130
+
131
+ border-start-end-radius: var(--modal-radius);
132
+ border-end-end-radius: var(--modal-radius);
133
+ margin-inline: 0 auto;
134
+ }
135
+
136
+ .ds-modal--end {
137
+ --ds-modal-from: translateX(100%);
138
+
139
+ border-start-start-radius: var(--modal-radius);
140
+ border-end-start-radius: var(--modal-radius);
141
+ margin-inline: auto 0;
142
+ }
143
+
144
+ .ds-modal--start:dir(rtl) {
145
+ --ds-modal-from: translateX(100%);
146
+ }
147
+
148
+ .ds-modal--end:dir(rtl) {
149
+ --ds-modal-from: translateX(-100%);
150
+ }
151
+
152
+ @starting-style {
153
+ .ds-modal[open] {
154
+ opacity: 0;
155
+ transform: translateY(var(--space-2)) scale(0.97);
156
+ }
157
+
158
+ .ds-modal[open]::backdrop {
159
+ opacity: 0;
160
+ }
161
+
162
+ .ds-modal--drawer[open] {
163
+ opacity: 1;
164
+ transform: var(--ds-modal-from);
165
+ }
37
166
  }
38
167
 
39
- .ds-modal--sheet[open] {
40
- animation: ds-sheet-in var(--duration-base) var(--ease-enter);
168
+ @media (max-width: 699px) {
169
+ .ds-modal--bottom {
170
+ max-width: 100%;
171
+ }
41
172
  }
42
173
 
43
174
  .ds-modal--sm {
@@ -114,30 +245,41 @@
114
245
  padding: var(--space-4) var(--modal-padding);
115
246
  }
116
247
 
117
- @keyframes ds-modal-in {
118
- from {
119
- opacity: 0;
120
- transform: translateY(var(--space-2)) scale(0.985);
248
+ @media (prefers-reduced-motion: reduce) {
249
+ .ds-modal::backdrop {
250
+ transition-duration: 120ms;
121
251
  }
122
- to {
123
- opacity: 1;
252
+
253
+ .ds-modal,
254
+ .ds-modal[open] {
124
255
  transform: none;
256
+ transition-duration: 120ms;
125
257
  }
126
- }
127
258
 
128
- @keyframes ds-sheet-in {
129
- from {
130
- transform: translateY(100%);
259
+ .ds-modal--drawer {
260
+ opacity: 0;
261
+ transform: none;
262
+ transition:
263
+ opacity 120ms var(--ease-standard),
264
+ display 120ms allow-discrete,
265
+ overlay 120ms allow-discrete;
131
266
  }
132
- to {
267
+
268
+ .ds-modal--drawer[open] {
269
+ opacity: 1;
133
270
  transform: none;
271
+ transition:
272
+ opacity 120ms var(--ease-standard),
273
+ display 120ms allow-discrete,
274
+ overlay 120ms allow-discrete;
134
275
  }
135
- }
136
276
 
137
- @media (prefers-reduced-motion: reduce) {
138
- .ds-modal[open],
139
- .ds-modal--sheet[open] {
140
- animation: none;
277
+ @starting-style {
278
+ .ds-modal[open],
279
+ .ds-modal--drawer[open] {
280
+ opacity: 0;
281
+ transform: none;
282
+ }
141
283
  }
142
284
  }
143
285
  }