tide-design-system 2.1.7 → 2.1.8

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 (37) hide show
  1. package/.storybook/main.ts +1 -0
  2. package/dist/css/realm/aero.css +3 -3
  3. package/dist/css/realm/boatmart.css +1 -1
  4. package/dist/css/realm/cycle.css +1 -1
  5. package/dist/css/realm/equipment.css +1 -1
  6. package/dist/css/realm/pwc.css +1 -1
  7. package/dist/css/reset.css +7 -0
  8. package/dist/style.css +1 -1
  9. package/dist/tide-design-system.cjs +2 -2
  10. package/dist/tide-design-system.esm.d.ts +40 -22
  11. package/dist/tide-design-system.esm.js +787 -785
  12. package/dist/utilities/event.ts +4 -0
  13. package/dist/utilities/storybook.ts +4 -0
  14. package/dist/utilities/viewport.ts +44 -0
  15. package/index.ts +2 -4
  16. package/package.json +4 -1
  17. package/src/assets/css/realm/aero.css +3 -3
  18. package/src/assets/css/realm/boatmart.css +1 -1
  19. package/src/assets/css/realm/cycle.css +1 -1
  20. package/src/assets/css/realm/equipment.css +1 -1
  21. package/src/assets/css/realm/pwc.css +1 -1
  22. package/src/assets/css/reset.css +7 -0
  23. package/src/components/TideCard.vue +3 -7
  24. package/src/components/TideModal.vue +164 -132
  25. package/src/components/TidePopover.vue +167 -0
  26. package/src/stories/TideAccordionItem.stories.ts +1 -0
  27. package/src/stories/TideButtonSegmented.stories.ts +1 -0
  28. package/src/stories/TideCard.stories.ts +1 -11
  29. package/src/stories/TideCarousel.stories.ts +1 -0
  30. package/src/stories/TideModal.stories.ts +68 -6
  31. package/src/stories/TidePagination.stories.ts +1 -0
  32. package/src/stories/TidePopover.stories.ts +98 -0
  33. package/src/stories/TideSwitch.stories.ts +1 -0
  34. package/src/types/Card.ts +0 -7
  35. package/src/utilities/event.ts +4 -0
  36. package/src/utilities/storybook.ts +4 -0
  37. package/src/utilities/viewport.ts +44 -0
@@ -0,0 +1,4 @@
1
+ export const isClickOutside = (event: MouseEvent, elements: HTMLElement | HTMLElement[]): boolean => {
2
+ const targets = Array.isArray(elements) ? elements : [elements];
3
+ return !targets.some((el) => el.contains(event.target as Node));
4
+ };
@@ -95,6 +95,10 @@ export const doSomething = () => {
95
95
  alert('Did something.');
96
96
  };
97
97
 
98
+ export const doSomethingElse = () => {
99
+ alert('Did something else.');
100
+ };
101
+
98
102
  // Flatten a nested constant into a simple constant.
99
103
  export const flatten = (input: Nested): KeyString => {
100
104
  const output: KeyString = {};
@@ -0,0 +1,44 @@
1
+ import { nextTick } from 'vue';
2
+
3
+ /**
4
+ * Directly modifies the `<body>` element to apply or remove scroll lock.
5
+ * When `false` is provided, it only unlocks scroll if there are no open
6
+ * HTML dialog elements.
7
+ */
8
+ export const setScrollLock = async (isLocked: boolean) => {
9
+ const BODY_LOCK_CLASS = 'body-scroll-lock';
10
+ const body = document.body;
11
+
12
+ if (isLocked) {
13
+ if (!body.dataset.scrollLockY) {
14
+ const scrollY = window.scrollY;
15
+ body.dataset.scrollLockY = scrollY.toString();
16
+ body.style.setProperty('--saved-scroll-y', `${scrollY}px`);
17
+ body.classList.add(BODY_LOCK_CLASS);
18
+ }
19
+ } else {
20
+ await nextTick();
21
+ if (!document.querySelector('dialog[open]')) {
22
+ const savedScrollY = parseInt(body.dataset.scrollLockY || '0');
23
+ body.classList.remove(BODY_LOCK_CLASS);
24
+ body.style.removeProperty('--saved-scroll-y');
25
+ window.scrollTo({
26
+ behavior: 'auto',
27
+ top: savedScrollY,
28
+ });
29
+ delete body.dataset.scrollLockY;
30
+ }
31
+ }
32
+ };
33
+
34
+ export const TOP_LAYER_ID = 'tideTopLayer';
35
+
36
+ export const initFauxTopLayer = () => {
37
+ let topLayer = document.getElementById(TOP_LAYER_ID);
38
+ if (!topLayer) {
39
+ topLayer = document.createElement('div');
40
+ topLayer.id = TOP_LAYER_ID;
41
+ document.body.appendChild(topLayer);
42
+ }
43
+ topLayer.style.isolation = 'isolate';
44
+ };
package/index.ts CHANGED
@@ -32,7 +32,7 @@ import TideSwitch from '@/components/TideSwitch.vue';
32
32
  import { ALERT } from '@/types/Alert';
33
33
  import { BADGE, BADGE_PREMIUM, BADGE_TRUSTED } from '@/types/Badge';
34
34
  import { BREAKPOINT, MEDIA } from '@/types/Breakpoint';
35
- import { POSITION_CARD_ICON, TYPE_CARD } from '@/types/Card';
35
+ import { TYPE_CARD } from '@/types/Card';
36
36
  import { ELEMENT, ELEMENT_TEXT_AS_ICON } from '@/types/Element';
37
37
  import { FORMAT, FORMAT_REGEX } from '@/types/Formatted';
38
38
  import { ICON, ICON_REALM } from '@/types/Icon';
@@ -50,7 +50,7 @@ import type { Alert } from '@/types/Alert';
50
50
  import type { Badge, BadgePremium, BadgeTrustedYears } from '@/types/Badge';
51
51
  import type { BreadCrumb } from '@/types/BreadCrumb';
52
52
  import type { Breakpoint, Media } from '@/types/Breakpoint';
53
- import type { CardIconPosition, CardType } from '@/types/Card';
53
+ import type { CardType } from '@/types/Card';
54
54
  import type { Detail } from '@/types/Detail';
55
55
  import type { Element, ElementTextAsIcon } from '@/types/Element';
56
56
  import type { FacetComponentIdRange, RangeData } from '@/types/FacetRange';
@@ -107,7 +107,6 @@ export type {
107
107
  BreadCrumb,
108
108
  Breakpoint,
109
109
  CardType,
110
- CardIconPosition,
111
110
  CheckboxField,
112
111
  CheckboxInput,
113
112
  CssUtility,
@@ -163,7 +162,6 @@ export {
163
162
  BADGE_PREMIUM,
164
163
  BADGE_TRUSTED,
165
164
  BREAKPOINT,
166
- POSITION_CARD_ICON,
167
165
  CSS,
168
166
  ELEMENT,
169
167
  ELEMENT_TEXT_AS_ICON,
package/package.json CHANGED
@@ -61,5 +61,8 @@
61
61
  "main": "dist/tide-design-system.cjs",
62
62
  "module": "dist/tide-design-system.esm.js",
63
63
  "types": "dist/tide-design-system.esm.d.ts",
64
- "version": "2.1.7"
64
+ "version": "2.1.8",
65
+ "dependencies": {
66
+ "@floating-ui/vue": "^1.1.6"
67
+ }
65
68
  }
@@ -1,11 +1,11 @@
1
1
  /* Aero Trader Realm Colors */
2
2
  :root {
3
3
  /* Realm-specific Tonal Palette: Only to be referenced in the assignment of Color Roles below. */
4
- --tide-realm-aqua: #90E0E6;
4
+ --tide-realm-aqua: #A2DEE5;
5
5
  --tide-realm-atmosphere: #3F6EBD;
6
- --tide-realm-cloud: #E2E8F2;
6
+ --tide-realm-cloud: #E3E8F1;
7
7
  --tide-realm-sky: #AAD4F0;
8
- --tide-realm-starry: #153976;
8
+ --tide-realm-starry: #3F6EBD;
9
9
 
10
10
  /* Color Roles: Each realm will assign values to this same series of variables from a combination of the Global and Realm-specific Palettes. */
11
11
  --tide-primary: var(--tide-realm-atmosphere);
@@ -5,7 +5,7 @@
5
5
  --tide-realm-mist: #DBEDFC;
6
6
  --tide-realm-navy-dark: #143353;
7
7
  --tide-realm-navy: #1D4977;
8
- --tide-realm-orange: #FF642B;
8
+ --tide-realm-orange: #D24614;
9
9
 
10
10
  /* Color Roles: Each realm will assign values to this same series of variables from a combination of the Global and Realm-specific Palettes. */
11
11
  --tide-primary: var(--tide-realm-navy);
@@ -4,7 +4,7 @@
4
4
  --tide-realm-light-blue: #DFECF2;
5
5
  --tide-realm-pure-black: #000000;
6
6
  --tide-realm-red: #C50000;
7
- --tide-realm-steel-blue: #1C3F53;
7
+ --tide-realm-steel-blue: #253E51;
8
8
 
9
9
  /* Color Roles: Each realm will assign values to this same series of variables from a combination of the Global and Realm-specific Palettes. */
10
10
  --tide-primary: var(--tide-realm-pure-black);
@@ -3,7 +3,7 @@
3
3
  /* Realm-specific Tonal Palette: Only to be referenced in the assignment of Color Roles below. */
4
4
  --tide-realm-charcoal: #333333;
5
5
  --tide-realm-evergreen: #468200;
6
- --tide-realm-moss: #ECF6D4;
6
+ --tide-realm-moss: #EEF6D7;
7
7
  --tide-realm-steel: #494949;
8
8
  --tide-realm-yellow: #FFCE34;
9
9
 
@@ -4,7 +4,7 @@
4
4
  --tide-realm-baby-blue: #86C0F4;
5
5
  --tide-realm-blue: #0B72B8;
6
6
  --tide-realm-cantaloupe: #ECA26A;
7
- --tide-realm-foam: #DDEBF6;
7
+ --tide-realm-foam: #E0EBF5;
8
8
  --tide-realm-midnight-blue: #002344;
9
9
 
10
10
  /* Color Roles: Each realm will assign values to this same series of variables from a combination of the Global and Realm-specific Palettes. */
@@ -4,6 +4,13 @@ body {
4
4
  line-height: 1.4;
5
5
  }
6
6
 
7
+ .body-scroll-lock {
8
+ inset: 0;
9
+ margin-top: calc(0px - var(--saved-scroll-y, 0px));
10
+ overflow-y: scroll;
11
+ position: fixed;
12
+ }
13
+
7
14
  *,
8
15
  *::before,
9
16
  *::after {
@@ -1,17 +1,16 @@
1
1
  <script lang="ts" setup>
2
2
  import TideIcon from '@/components/TideIcon.vue';
3
- import { POSITION_CARD_ICON, TYPE_CARD } from '@/types/Card';
3
+ import { TYPE_CARD } from '@/types/Card';
4
4
  import { SIZE } from '@/types/Size';
5
5
  import { CSS } from '@/types/Styles';
6
6
 
7
- import type { CardIconPosition, CardType } from '@/types/Card';
7
+ import type { CardType } from '@/types/Card';
8
8
  import type { Icon } from '@/types/Icon';
9
9
 
10
10
  type Props = {
11
11
  description?: string;
12
12
  heading: string;
13
13
  icon?: Icon;
14
- iconPosition: CardIconPosition;
15
14
  selected?: boolean;
16
15
  type: CardType;
17
16
  href?: string;
@@ -21,7 +20,6 @@
21
20
  description: undefined,
22
21
  href: undefined,
23
22
  icon: undefined,
24
- iconPosition: POSITION_CARD_ICON.LEFT,
25
23
  selected: undefined,
26
24
  type: TYPE_CARD.INFORMATIONAL,
27
25
  });
@@ -39,9 +37,7 @@
39
37
  CSS.PADDING.FULL.ONE,
40
38
  CSS.WIDTH.FULL,
41
39
  CSS.ALIGN.X.LEFT,
42
- iconPosition === POSITION_CARD_ICON.LEFT
43
- ? CSS.FLEX.DIRECTION.ROW
44
- : iconPosition === POSITION_CARD_ICON.TOP && CSS.FLEX.DIRECTION.COLUMN,
40
+ CSS.FLEX.DIRECTION.COLUMN,
45
41
  type !== TYPE_CARD.INFORMATIONAL && 'hoverable',
46
42
  type === TYPE_CARD.SELECTABLE && selected && 'selected',
47
43
  ]"
@@ -1,187 +1,219 @@
1
1
  <script lang="ts" setup>
2
- import { onMounted, ref, watch } from 'vue';
2
+ import { nextTick, onMounted, ref, watch } from 'vue';
3
3
 
4
- import TideIcon from '@/components/TideIcon.vue';
4
+ import TideButtonIcon from '@/components/TideButtonIcon.vue';
5
+ import { BREAKPOINT } from '@/types/Breakpoint';
5
6
  import { ICON } from '@/types/Icon';
7
+ import { PRIORITY } from '@/types/Priority';
6
8
  import { CSS } from '@/types/Styles';
9
+ import { setScrollLock } from '@/utilities/viewport';
10
+
11
+ import type { Ref } from 'vue';
7
12
 
8
13
  type Props = {
14
+ isBackButton?: boolean;
15
+ isDismissible?: boolean;
9
16
  isOpen: boolean;
10
17
  title?: string;
11
18
  width?: string;
12
19
  };
13
20
 
14
- const props = defineProps<Props>();
15
-
16
- const emit = defineEmits(['close']);
17
-
18
- const isOpen = ref(props.isOpen);
19
- const savedScrollPosition = ref<number | null>(null); // TODO: replace body scroll lock with global structure?
20
-
21
- const handleClose = () => {
22
- isOpen.value = false;
21
+ const props = withDefaults(defineProps<Props>(), {
22
+ isBackButton: false,
23
+ isDismissible: true,
24
+ title: undefined,
25
+ width: undefined,
26
+ });
23
27
 
24
- updateModalDisplay();
25
- emit('close');
28
+ type Emits = {
29
+ (e: 'close'): void;
30
+ (e: 'back'): void;
26
31
  };
27
32
 
28
- const updateModalDisplay = () => {
29
- if (isOpen.value) {
30
- savedScrollPosition.value = window.scrollY;
31
- document.body.style.overflow = 'hidden';
32
- savedScrollPosition.value && window.scrollTo(0, savedScrollPosition.value);
33
+ const emit = defineEmits<Emits>();
33
34
 
34
- addOpenListeners();
35
- } else {
36
- document.body.style.overflow = '';
35
+ const modalContent: Ref<HTMLDivElement | undefined> = ref();
36
+ const modalDialog: Ref<HTMLDialogElement | undefined> = ref();
37
37
 
38
- removeOpenListeners();
39
- }
38
+ const triggerNativeDialogOpen = () => {
39
+ modalDialog.value?.showModal();
40
40
  };
41
41
 
42
- const handleKeyDown = (event: KeyboardEvent) => {
43
- if (event.key === 'Escape') {
44
- event.stopPropagation();
45
- handleClose();
46
- }
47
- };
48
-
49
- const addOpenListeners = () => {
50
- window.addEventListener('keydown', handleKeyDown);
42
+ const triggerNativeDialogClose = () => {
43
+ modalDialog.value?.close();
51
44
  };
52
45
 
53
- const removeOpenListeners = () => {
54
- window.removeEventListener('keydown', handleKeyDown);
46
+ const scrollContentToTop = () => {
47
+ nextTick(() => {
48
+ if (!modalContent.value) return;
49
+ modalContent.value.scrollTop = 0;
50
+ });
55
51
  };
56
52
 
57
- onMounted(() => {
58
- updateModalDisplay();
59
- });
60
-
61
53
  watch(
62
54
  () => props.isOpen,
63
55
  (newValue) => {
64
- isOpen.value = newValue;
65
- updateModalDisplay();
56
+ if (!modalDialog.value) return;
57
+ if (newValue) {
58
+ triggerNativeDialogOpen();
59
+ scrollContentToTop();
60
+ } else {
61
+ triggerNativeDialogClose();
62
+ }
63
+ setScrollLock(newValue);
66
64
  }
67
65
  );
66
+
67
+ onMounted(() => {
68
+ if (props.isOpen) {
69
+ triggerNativeDialogOpen();
70
+ }
71
+ });
68
72
  </script>
69
73
 
70
74
  <template>
71
- <Teleport to="body">
75
+ <dialog
76
+ :class="['tide-modal', CSS.BG.INITIAL, CSS.HEIGHT.FULL, CSS.WIDTH.FULL, CSS.OVERFLOW.XY.HIDDEN]"
77
+ ref="modalDialog"
78
+ :style="{ '--modal-width': props.width }"
79
+ @click.self="emit('close')"
80
+ @close="emit('close')"
81
+ >
72
82
  <div
73
83
  :class="[
74
- 'tide-modal-wrapper',
75
- CSS.POSITION.ABSOLUTE,
84
+ 'tide-modal-body',
85
+ CSS.BG.SURFACE.DEFAULT,
86
+ CSS.BORDER.RADIUS.ONE,
76
87
  CSS.DISPLAY.FLEX,
77
- CSS.AXIS1.CENTER,
78
- CSS.AXIS2.CENTER,
79
- CSS.POSITIONING.TOP,
80
- CSS.POSITIONING.LEFT,
88
+ CSS.FLEX.DIRECTION.COLUMN,
89
+ CSS.OVERFLOW.XY.HIDDEN,
90
+ CSS.POSITION.ABSOLUTE,
91
+ CSS.POSITIONING.BOTTOM,
92
+ CSS.SHADOW.TOP,
81
93
  CSS.WIDTH.FULL,
82
- CSS.HEIGHT.FULL,
83
- props.isOpen ? 'active' : CSS.POINTER_EVENTS.OFF,
84
- CSS.OVERFLOW.Y.HIDDEN,
94
+ CSS.WIDTH.MAX_FULL,
95
+ CSS.withBreakpoint([CSS.SHADOW.BOTTOM], BREAKPOINT.SM),
85
96
  ]"
86
97
  >
87
- <div
88
- :class="['tide-modal-bg', CSS.POSITION.ABSOLUTE, CSS.WIDTH.FULL, CSS.HEIGHT.FULL]"
89
- :style="{ '--tide-modal-width': props.width }"
90
- @click.self="handleClose"
91
- />
98
+ <header
99
+ :class="[
100
+ 'tide-modal-header',
101
+ CSS.DISPLAY.FLEX,
102
+ CSS.AXIS2.CENTER,
103
+ CSS.GAP.HALF,
104
+ CSS.PADDING.Y.ONE,
105
+ CSS.BORDER.BOTTOM.ONE,
106
+ CSS.BORDER.COLOR.LOW,
107
+ ]"
108
+ >
109
+ <TideButtonIcon
110
+ :icon="ICON.CHEVRON_LEFT"
111
+ :priority="PRIORITY.QUATERNARY"
112
+ @click="emit('back')"
113
+ title="Back"
114
+ v-if="isBackButton"
115
+ />
116
+
117
+ <div
118
+ :class="[CSS.FONT.ROLE.HEADLINE_2]"
119
+ v-text="title"
120
+ />
121
+
122
+ <TideButtonIcon
123
+ :class="[CSS.FLEX.GROW.OFF, CSS.FLEX.SHRINK.OFF, CSS.MARGIN.LEFT.AUTO]"
124
+ :icon="ICON.CLOSE"
125
+ :priority="PRIORITY.QUATERNARY"
126
+ @click="triggerNativeDialogClose"
127
+ v-if="isDismissible"
128
+ />
129
+ </header>
92
130
 
93
131
  <div
94
132
  :class="[
95
- 'tide-modal',
96
- CSS.BG.SURFACE.DEFAULT,
97
- CSS.FONT.COLOR.SURFACE.DEFAULT,
98
- CSS.POSITION.ABSOLUTE,
99
- CSS.DISPLAY.FLEX,
100
- CSS.FLEX.DIRECTION.COLUMN,
101
- CSS.BORDER.RADIUS.ONE,
102
- CSS.OVERFLOW.XY.HIDDEN,
103
- CSS.SHADOW.BOTTOM,
133
+ 'tide-modal-content',
134
+ CSS.DISPLAY.GRID,
135
+ CSS.OVERFLOW.Y.AUTO,
136
+ CSS.OVERFLOW.X.HIDDEN,
137
+ CSS.WIDTH.FULL,
138
+ CSS.PADDING.Y.TWO,
104
139
  ]"
140
+ ref="modalContent"
105
141
  >
106
- <header
107
- :class="[
108
- 'tide-modal-header',
109
- CSS.POSITION.RELATIVE,
110
- CSS.DISPLAY.FLEX,
111
- CSS.AXIS2.CENTER,
112
- CSS.PADDING.Y.ONE,
113
- CSS.PADDING.X.TWO,
114
- CSS.BORDER.BOTTOM.ONE,
115
- CSS.BORDER.COLOR.LOW,
116
- ]"
117
- >
118
- <div
119
- :class="[CSS.FLEX.GROW.ON, CSS.FONT.SIZE.TWENTY, CSS.FONT.WEIGHT.SEVEN_HUNDRED]"
120
- v-if="title"
121
- >
122
- {{ title }}
123
- </div>
124
-
125
- <button
126
- :class="[CSS.POSITION.ABSOLUTE, CSS.POSITIONING.RIGHT, CSS.MARGIN.RIGHT.TWO]"
127
- @click="handleClose"
128
- title="Close"
129
- >
130
- <TideIcon :icon="ICON.CLOSE" />
131
- </button>
132
- </header>
133
-
134
- <div :class="['tide-modal-content', CSS.PADDING.FULL.TWO, CSS.OVERFLOW.Y.AUTO]">
135
- <slot />
136
- </div>
137
-
138
- <template v-if="$slots.footer">
139
- <footer
140
- :class="[
141
- 'tide-bg-surface',
142
- CSS.POSITION.STICKY,
143
- CSS.POSITIONING.LEFT,
144
- CSS.POSITIONING.BOTTOM,
145
- CSS.DISPLAY.FLEX,
146
- CSS.AXIS1.END,
147
- CSS.GAP.ONE,
148
- CSS.PADDING.X.TWO,
149
- CSS.PADDING.Y.ONE,
150
- CSS.SHADOW.TOP,
151
- ]"
152
- >
153
- <slot name="footer" />
154
- </footer>
155
- </template>
142
+ <slot />
156
143
  </div>
144
+
145
+ <footer
146
+ :class="['tide-modal-footer', CSS.AXIS1.END, CSS.DISPLAY.FLEX, CSS.GAP.TWO, CSS.PADDING.Y.ONE, CSS.SHADOW.TOP]"
147
+ v-if="$slots.footer"
148
+ >
149
+ <slot name="footer" />
150
+ </footer>
157
151
  </div>
158
- </Teleport>
152
+ </dialog>
159
153
  </template>
160
154
 
161
155
  <style scoped>
162
156
  .tide-modal {
163
- width: var(--tide-modal-width);
164
- max-width: calc(100% - 2rem);
165
- max-height: calc(100% - 2rem);
166
- box-shadow: 0px 10px 25px 0px rgba(18, 43, 58, 0.2);
167
- transform: translateY(100vh);
168
- transition: var(--tide-animate);
169
- transition-property: transform;
157
+ --modal-padding-x: 20px;
158
+ max-width: unset;
159
+ max-height: unset;
160
+ place-items: center;
161
+ display: none;
162
+ transition: all var(--tide-animate) allow-discrete;
163
+ transform: translateY(100%);
170
164
  }
171
-
172
- .tide-modal-bg {
165
+ .tide-modal:open {
166
+ display: grid;
167
+ transform: translateY(0%);
168
+ }
169
+ .tide-modal::backdrop {
170
+ background-color: transparent;
171
+ transition: all var(--tide-animate) allow-discrete;
173
172
  backdrop-filter: blur(0px);
174
- background-color: rgba(255, 255, 255, 0);
175
- transition: var(--tide-animate);
176
- transition-property: backdrop-filter, background-color;
173
+ }
174
+ .tide-modal:open::backdrop {
175
+ background-color: var(--tide-transparent-400);
176
+ backdrop-filter: blur(4px);
177
+ }
178
+ @starting-style {
179
+ .tide-modal:open {
180
+ display: grid;
181
+ transform: translateY(100%);
182
+ }
183
+ .tide-modal:open::backdrop {
184
+ background-color: transparent;
185
+ backdrop-filter: blur(4px);
186
+ }
187
+ }
188
+ .tide-modal-body {
189
+ width: var(--modal-width, 576px);
190
+ max-height: calc(100% - var(--tide-spacing-2));
177
191
  }
178
192
 
179
- .active .tide-modal {
180
- transform: translateY(0);
193
+ .tide-modal-header,
194
+ .tide-modal-footer {
195
+ padding-inline: var(--modal-padding-x);
196
+ }
197
+ .tide-modal-content {
198
+ grid-template-columns: var(--modal-padding-x) 1fr var(--modal-padding-x);
199
+ }
200
+ :where(.tide-modal-content):deep(> :where(*)) {
201
+ grid-column: 2;
181
202
  }
182
203
 
183
- .active .tide-modal-bg {
184
- backdrop-filter: blur(8px);
185
- background-color: var(--tide-transparent-400);
204
+ @media (max-width: 767px) {
205
+ .tide-modal-body {
206
+ border-bottom-left-radius: 0;
207
+ border-bottom-right-radius: 0;
208
+ }
209
+ }
210
+ @media (min-width: 768px) {
211
+ .tide-modal {
212
+ --modal-padding-x: var(--tide-spacing-2);
213
+ }
214
+ .tide-modal-body {
215
+ max-height: 85%;
216
+ bottom: initial;
217
+ }
186
218
  }
187
219
  </style>