@expressivecss/expressive 0.5.0 → 0.7.0-rc.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.
@@ -6,4 +6,4 @@ export { Forms } from './behaviors/forms';
6
6
  export { Waves } from './behaviors/waves';
7
7
  export { AutoInit } from './components/registry';
8
8
  export type { AutoInitOptions } from './components/registry';
9
- export declare const version = "0.5.0";
9
+ export declare const version = "0.7.0-rc.0";
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@expressivecss/expressive",
3
- "version": "0.5.0",
3
+ "version": "0.7.0-rc.0",
4
4
  "description": "ExpressiveCSS - a Material Design 3 front-end framework.",
5
5
  "license": "MIT",
6
6
  "author": "BaezFJ <baezdevs@gmail.com>",
7
- "homepage": "https://github.com/BaezFJ/ExpressiveCSS#readme",
7
+ "homepage": "https://www.expressivecss.com",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "git+https://github.com/BaezFJ/ExpressiveCSS.git"
@@ -73,6 +73,11 @@
73
73
  inset-block-start: calc((100% - var(--md-comp-badge-icon-size)) / 2);
74
74
  inset-inline-end: calc((100% - var(--md-comp-badge-icon-size)) / 2);
75
75
  transform: translate(50%, -50%);
76
+
77
+ &:dir(rtl),
78
+ [dir="rtl"] & {
79
+ transform: translate(-50%, -50%);
80
+ }
76
81
  }
77
82
  }
78
83
 
@@ -35,3 +35,4 @@
35
35
  @forward "timepicker";
36
36
  @forward "breadcrumb";
37
37
  @forward "pagination";
38
+ @forward "panes";
@@ -0,0 +1,294 @@
1
+ @use "../abstracts" as *;
2
+
3
+ // Material 3 Canonical Pane Layouts.
4
+ //
5
+ // Anatomy is the HTML. A container (`.panes` or `.pane-layout` or `.list-detail`)
6
+ // contains two (or three) `.pane` children.
7
+ //
8
+ // Canonical Layouts:
9
+ // 1. List-Detail (.list-detail, .panes.list-detail):
10
+ // - Compact (< 840px / < 601px): Single pane visible at a time.
11
+ // - Expanded (>= 840px): 360dp list pane + 1fr detail pane.
12
+ // 2. Supporting Pane (.supporting-pane-layout, .panes.supporting):
13
+ // - 1fr primary pane + 360-400dp supporting pane (on trailing or leading side).
14
+ // 3. Equal / Proportional (.panes.equal, .panes.proportional):
15
+ // - 1fr 1fr side-by-side.
16
+ //
17
+ // Appearances:
18
+ // - Coplanar (default): Full-bleed surfaces with a 1px outline-variant divider.
19
+ // - Separated / Floating (.separated, .floating): 16dp/24dp rounded surfaces
20
+ // with surface-container-low and a 24dp gap.
21
+ //
22
+ // Tokens follow https://m3.material.io/foundations/adaptive-design/canonical-layouts
23
+ // --md-comp-pane-gap 24px
24
+ // --md-comp-pane-divider-color outline-variant
25
+ // --md-comp-pane-container-color surface
26
+ // --md-comp-pane-container-shape 0px
27
+ // --md-comp-pane-list-width 360px
28
+ // --md-comp-pane-supporting-width 360px
29
+ // --md-comp-pane-primary-min-width 360px
30
+
31
+ .panes,
32
+ .pane-layout,
33
+ .list-detail,
34
+ .supporting-pane-layout {
35
+ --md-comp-pane-gap: 24px;
36
+ --md-comp-pane-divider-color: var(--md-sys-color-outline-variant);
37
+ --md-comp-pane-container-color: var(--md-sys-color-surface);
38
+ --md-comp-pane-container-shape: 0px;
39
+ --md-comp-pane-list-width: 360px;
40
+ --md-comp-pane-supporting-width: 360px;
41
+ --md-comp-pane-primary-min-width: 360px;
42
+
43
+ box-sizing: border-box;
44
+ display: grid;
45
+ width: 100%;
46
+ height: 100%;
47
+ min-height: 0;
48
+ margin: 0;
49
+ padding: 0;
50
+ container-type: inline-size;
51
+ background-color: var(--md-comp-pane-container-color);
52
+ color: var(--md-sys-color-on-surface);
53
+
54
+ // Default (Single-Pane on compact screens < 840px / < 601px)
55
+ grid-template-columns: 1fr;
56
+ gap: 0;
57
+
58
+ // Panes in compact mode: list/primary visible by default, detail/supporting hidden
59
+ // unless marked .active
60
+ > :is(.pane, .list-pane, .primary-pane, .detail-pane, .supporting-pane) {
61
+ display: none;
62
+ min-width: 0;
63
+ min-height: 0;
64
+ overflow: hidden;
65
+
66
+ &.active {
67
+ display: flex;
68
+ }
69
+ }
70
+
71
+ &:not(:has(> :is(.pane, .list-pane, .primary-pane, .detail-pane, .supporting-pane).active)) {
72
+ > :is(.pane, .list-pane, .primary-pane, .detail-pane, .supporting-pane):first-child {
73
+ display: flex;
74
+ }
75
+ }
76
+
77
+ // Expanded Viewports: Dual-pane side-by-side (via container query or breakpoint)
78
+ @media (width >= 840px) {
79
+ grid-template-columns: var(--md-comp-pane-list-width) 1fr;
80
+ gap: 0;
81
+
82
+ > :is(.pane, .list-pane, .primary-pane, .detail-pane, .supporting-pane) {
83
+ display: flex !important;
84
+ }
85
+ }
86
+
87
+ @container (min-width: 840px) {
88
+ grid-template-columns: var(--md-comp-pane-list-width) 1fr;
89
+ gap: 0;
90
+
91
+ > :is(.pane, .list-pane, .primary-pane, .detail-pane, .supporting-pane) {
92
+ display: flex !important;
93
+ }
94
+ }
95
+ }
96
+
97
+ // ---------------------------------------------------------------------------
98
+ // Canonical Variants
99
+ // ---------------------------------------------------------------------------
100
+
101
+ // 1. Supporting Pane Layout
102
+ .supporting-pane-layout,
103
+ .panes.supporting {
104
+ @media (width >= 840px) {
105
+ grid-template-columns: 1fr var(--md-comp-pane-supporting-width);
106
+ }
107
+
108
+ @container (min-width: 840px) {
109
+ grid-template-columns: 1fr var(--md-comp-pane-supporting-width);
110
+ }
111
+
112
+ // Leading supporting pane (.start / .left)
113
+ &.start,
114
+ &.left {
115
+ @media (width >= 840px) {
116
+ grid-template-columns: var(--md-comp-pane-supporting-width) 1fr;
117
+ }
118
+
119
+ @container (min-width: 840px) {
120
+ grid-template-columns: var(--md-comp-pane-supporting-width) 1fr;
121
+ }
122
+ }
123
+ }
124
+
125
+ // 2. Equal / Proportional Pane Layout
126
+ .panes.equal,
127
+ .pane-layout.equal {
128
+ @media (width >= 840px) {
129
+ grid-template-columns: 1fr 1fr;
130
+ }
131
+
132
+ @container (min-width: 840px) {
133
+ grid-template-columns: 1fr 1fr;
134
+ }
135
+ }
136
+
137
+ // 3. Three-Pane Layout (List + Primary Focus + Supporting)
138
+ .panes.three-pane,
139
+ .pane-layout.three-pane {
140
+ @media (width >= 1200px) {
141
+ grid-template-columns: var(--md-comp-pane-list-width) 1fr var(--md-comp-pane-supporting-width);
142
+ }
143
+
144
+ @container (min-width: 1200px) {
145
+ grid-template-columns: var(--md-comp-pane-list-width) 1fr var(--md-comp-pane-supporting-width);
146
+ }
147
+ }
148
+
149
+ // ---------------------------------------------------------------------------
150
+ // Separated / Floating Appearance
151
+ // ---------------------------------------------------------------------------
152
+ .panes.separated,
153
+ .panes.floating,
154
+ .pane-layout.separated,
155
+ .pane-layout.floating {
156
+ --md-comp-pane-container-shape: 16px;
157
+ --md-comp-pane-container-color: transparent;
158
+ gap: var(--md-comp-pane-gap);
159
+ padding: var(--md-comp-pane-gap);
160
+
161
+ > :is(.pane, .list-pane, .primary-pane, .detail-pane, .supporting-pane) {
162
+ border: none;
163
+ border-radius: var(--md-comp-pane-container-shape);
164
+ background-color: var(--md-sys-color-surface-container-low);
165
+ @include z-depth("0");
166
+
167
+ &.elevated {
168
+ background-color: var(--md-sys-color-surface-container-low);
169
+ @include z-depth("1");
170
+ }
171
+
172
+ &.outlined {
173
+ background-color: var(--md-sys-color-surface);
174
+ border: 1px solid var(--md-comp-pane-divider-color);
175
+ }
176
+ }
177
+ }
178
+
179
+ // ---------------------------------------------------------------------------
180
+ // Coplanar / Docked Dividers (Default)
181
+ // ---------------------------------------------------------------------------
182
+ :is(.panes, .pane-layout, .list-detail, .supporting-pane-layout):not(.separated, .floating) {
183
+ > :is(.pane, .list-pane, .primary-pane, .detail-pane, .supporting-pane):not(:last-child) {
184
+ @media (width >= 840px) {
185
+ border-inline-end: 1px solid var(--md-comp-pane-divider-color);
186
+ }
187
+
188
+ @container (min-width: 840px) {
189
+ border-inline-end: 1px solid var(--md-comp-pane-divider-color);
190
+ }
191
+ }
192
+ }
193
+
194
+ // ---------------------------------------------------------------------------
195
+ // Pane Internal Anatomy
196
+ // ---------------------------------------------------------------------------
197
+ .pane,
198
+ .list-pane,
199
+ .primary-pane,
200
+ .detail-pane,
201
+ .supporting-pane {
202
+ box-sizing: border-box;
203
+ flex-direction: column;
204
+ position: relative;
205
+ width: 100%;
206
+ height: 100%;
207
+ min-width: 0;
208
+ min-height: 0;
209
+
210
+ // Header Bar (64dp height, Title Large, action icons)
211
+ > :is(header, .pane-header) {
212
+ display: flex;
213
+ align-items: center;
214
+ gap: 12px;
215
+ flex: 0 0 auto;
216
+ box-sizing: border-box;
217
+ min-height: 64px;
218
+ margin: 0;
219
+ padding: 8px 16px;
220
+ background: none;
221
+
222
+ > :is(h1, h2, h3, h4, h5, h6, .pane-title) {
223
+ flex: 1 1 auto;
224
+ min-width: 0;
225
+ margin: 0;
226
+ padding: 0;
227
+ color: var(--md-sys-color-on-surface);
228
+ @include typescale("title-large");
229
+ white-space: nowrap;
230
+ overflow: hidden;
231
+ text-overflow: ellipsis;
232
+ }
233
+
234
+ > :is(button, a.button):has(> i:only-child) {
235
+ flex: 0 0 48px;
236
+ box-sizing: border-box;
237
+ width: 48px;
238
+ height: 48px;
239
+ min-width: 48px;
240
+ padding: 0;
241
+ border: none;
242
+ border-radius: 50%;
243
+ background-color: transparent;
244
+ color: var(--md-sys-color-on-surface-variant);
245
+ box-shadow: none;
246
+
247
+ > i {
248
+ font-size: 24px;
249
+ width: 24px;
250
+ height: 24px;
251
+ line-height: 24px;
252
+ }
253
+
254
+ &:hover {
255
+ background-color: color-mix(in oklab, var(--md-sys-color-on-surface) 8%, transparent);
256
+ }
257
+
258
+ &:focus-visible {
259
+ outline: 3px solid var(--md-sys-color-secondary);
260
+ outline-offset: 2px;
261
+ }
262
+ }
263
+ }
264
+
265
+ // Scrollable Content Body
266
+ > :is(main, .pane-content, .pane-body, div:not(.pane-header, .pane-footer)) {
267
+ flex: 1 1 auto;
268
+ min-height: 0;
269
+ overflow-y: auto;
270
+ overscroll-behavior: contain;
271
+ padding: 16px 24px;
272
+ }
273
+
274
+ // Direct list inside pane (fills list seamlessly without padding clip)
275
+ > .list {
276
+ flex: 1 1 auto;
277
+ min-height: 0;
278
+ overflow-y: auto;
279
+ overscroll-behavior: contain;
280
+ margin: 0;
281
+ }
282
+
283
+ // Footer / Action Bar
284
+ > :is(footer, .pane-footer, nav:last-child) {
285
+ display: flex;
286
+ align-items: center;
287
+ gap: 8px;
288
+ flex: 0 0 auto;
289
+ box-sizing: border-box;
290
+ min-height: 56px;
291
+ padding: 8px 16px;
292
+ border-block-start: 1px solid var(--md-comp-pane-divider-color);
293
+ }
294
+ }