@expressivecss/expressive 0.1.0 → 0.2.0

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.
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Light-dismiss for native `<dialog>` elements.
3
+ *
4
+ * `showModal()` does not close on a backdrop tap. A naive `click` listener
5
+ * on the dialog (where `::backdrop` events retarget) also fires when the
6
+ * user starts a gesture on the dialog and releases on the scrim — selecting
7
+ * text, missing a button, dragging a thumb. Both ends of the pointer
8
+ * gesture must land outside the dialog's border box.
9
+ *
10
+ * Default is on. Opt out with `closedby="none"` or `closedby="closerequest"`.
11
+ * If the browser already honours `closedby="any"`, we leave that alone.
12
+ */
13
+ export declare class Dialogs {
14
+ private static _down;
15
+ static Init(): void;
16
+ static _onPointerDown(event: PointerEvent): void;
17
+ static _onPointerUp(event: PointerEvent): void;
18
+ static _onPointerCancel(): void;
19
+ /** Backdrop hits retarget to the dialog itself, never a child. */
20
+ private static _backdropDialog;
21
+ private static _outside;
22
+ private static _isPrimaryPress;
23
+ private static _lightDismissible;
24
+ private static _closedBy;
25
+ }
@@ -1,6 +1,7 @@
1
1
  export * from './components';
2
+ export { Dialogs } from './behaviors/dialogs';
2
3
  export { Forms } from './behaviors/forms';
3
4
  export { Waves } from './behaviors/waves';
4
5
  export { AutoInit } from './components/registry';
5
6
  export type { AutoInitOptions } from './components/registry';
6
- export declare const version = "0.1.0";
7
+ export declare const version = "0.2.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressivecss/expressive",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "ExpressiveCSS - a Material Design 3 front-end framework.",
5
5
  "license": "MIT",
6
6
  "author": "BaezFJ <baezdevs@gmail.com>",
@@ -13,7 +13,7 @@
13
13
  // body body-medium / on-surface-variant
14
14
  // icon 24dp, on-secondary
15
15
  // actions end-aligned, 8dp gap
16
- // scrim 32%
16
+ // scrim 32% + 12px blur
17
17
  // padding 24dp
18
18
 
19
19
  dialog,
@@ -22,6 +22,8 @@ dialog,
22
22
  --md-comp-basic-dialog-container-shape: 28px;
23
23
  --md-comp-basic-dialog-container-min-width: 280px;
24
24
  --md-comp-basic-dialog-container-max-width: 560px;
25
+ --md-comp-basic-dialog-sheet-width: 400px;
26
+ --md-comp-basic-dialog-scrim-blur: 12px;
25
27
 
26
28
  box-sizing: border-box;
27
29
  width: min(var(--md-comp-basic-dialog-container-max-width), calc(100% - 48px));
@@ -38,14 +40,23 @@ dialog,
38
40
 
39
41
  &::backdrop {
40
42
  background-color: color-mix(in oklab, var(--md-sys-color-scrim) 32%, transparent);
43
+ backdrop-filter: blur(var(--md-comp-basic-dialog-scrim-blur));
41
44
  }
42
45
  }
43
46
 
47
+ // showModal() puts the dialog in the top layer but does not lock the
48
+ // document scroller. :modal is the modal-only match — a modeless
49
+ // dialog.show() must not freeze the page.
50
+ html:has(dialog:modal) {
51
+ overflow: hidden;
52
+ }
53
+
44
54
  dialog[open],
45
55
  .modal[open] {
46
56
  display: flex;
47
57
  flex-direction: column;
48
58
  overflow: hidden;
59
+ overscroll-behavior: contain;
49
60
  }
50
61
 
51
62
  // Optional leading icon (M3 basic dialog).
@@ -84,6 +95,7 @@ dialog > div,
84
95
  flex: 1 1 auto;
85
96
  min-height: 0;
86
97
  overflow: auto;
98
+ overscroll-behavior: contain;
87
99
  margin: 0;
88
100
  padding: 0 24px 16px;
89
101
  font-family: var(--md-sys-typescale-body-medium-font-family-name);
@@ -119,9 +131,13 @@ dialog > :is(form, nav):last-child,
119
131
  }
120
132
 
121
133
  // Full-screen (M3). Takes the viewport; no corners.
134
+ // UA `dialog:modal` sets max-width: calc(100% - 2em - 6px). Without
135
+ // clearing it, width: 100% is capped and a strip of scrim shows on the
136
+ // right. Bottom sheet already overrides this.
122
137
  dialog.max,
123
138
  .modal.max {
124
139
  width: 100%;
140
+ max-width: none;
125
141
  height: 100%;
126
142
  min-width: 0;
127
143
  max-height: none;
@@ -129,8 +145,9 @@ dialog.max,
129
145
  border-radius: 0;
130
146
  }
131
147
 
132
- // Bottom sheet. M3 sheets are a sibling component; this keeps the existing
133
- // Expressive helper and BeerCSS's `bottom` name.
148
+ // Sheets. Docked to one edge; the inner corners keep the dialog shape,
149
+ // the edge against the viewport is square. `left` / `right` also float
150
+ // via the helper utilities (`!important`), so sheets reset that.
134
151
  dialog.bottom,
135
152
  dialog.bottom-sheet,
136
153
  .modal.bottom-sheet {
@@ -142,3 +159,50 @@ dialog.bottom-sheet,
142
159
  border-radius: var(--md-comp-basic-dialog-container-shape)
143
160
  var(--md-comp-basic-dialog-container-shape) 0 0;
144
161
  }
162
+
163
+ dialog.top,
164
+ dialog.top-sheet,
165
+ .modal.top-sheet {
166
+ width: 100%;
167
+ min-width: 0;
168
+ max-width: none;
169
+ max-height: 50%;
170
+ margin: 0 0 auto;
171
+ border-radius: 0 0 var(--md-comp-basic-dialog-container-shape)
172
+ var(--md-comp-basic-dialog-container-shape);
173
+ }
174
+
175
+ dialog.left,
176
+ dialog.left-sheet,
177
+ .modal.left-sheet,
178
+ dialog.right,
179
+ dialog.right-sheet,
180
+ .modal.right-sheet {
181
+ float: none !important;
182
+ width: min(var(--md-comp-basic-dialog-sheet-width), 85%);
183
+ max-width: none;
184
+ height: auto;
185
+ max-height: none;
186
+ min-width: 0;
187
+ min-height: 0;
188
+ margin: 0;
189
+ inset-block: 0;
190
+ }
191
+
192
+ dialog.left,
193
+ dialog.left-sheet,
194
+ .modal.left-sheet {
195
+ inset-inline-start: 0;
196
+ inset-inline-end: auto;
197
+ border-radius: 0 var(--md-comp-basic-dialog-container-shape)
198
+ var(--md-comp-basic-dialog-container-shape) 0;
199
+ }
200
+
201
+ dialog.right,
202
+ dialog.right-sheet,
203
+ .modal.right-sheet {
204
+ inset-inline-start: auto;
205
+ inset-inline-end: 0;
206
+ border-radius: var(--md-comp-basic-dialog-container-shape) 0 0
207
+ var(--md-comp-basic-dialog-container-shape);
208
+ }
@@ -39,15 +39,25 @@ video.responsive-video {
39
39
  height: auto;
40
40
  }
41
41
 
42
+ // 12px matches the card container shape. .circle is more specific on
43
+ // `img.responsive-img.circle` only if we exclude it here — otherwise this
44
+ // element+class pair would beat `.circle` and square the disc off.
45
+ img.responsive-img:not(.circle),
46
+ video.responsive-video {
47
+ border-radius: 12px;
48
+ }
49
+
42
50
  .video-container {
43
51
  position: relative;
44
52
  aspect-ratio: 16 / 9; // was padding-bottom: 56.25% + height: 0
45
53
  overflow: hidden;
54
+ border-radius: 12px;
46
55
 
47
56
  iframe, object, embed {
48
57
  position: absolute;
49
58
  inset: 0;
50
59
  width: 100%;
51
60
  height: 100%;
61
+ border: 0;
52
62
  }
53
63
  }