@iyulab/modern-app 0.58.0 → 0.59.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.
- package/CHANGELOG.md +18 -0
- package/dist/components/ActionBar.js +12 -10
- package/dist/components/ActionBar.styles.js +8 -1
- package/dist/components/EmptyState.js +15 -13
- package/dist/components/EmptyState.styles.js +6 -0
- package/dist/components/GroupBox.js +13 -10
- package/dist/components/GroupBox.styles.js +6 -0
- package/dist/components/InfoField.d.ts +3 -0
- package/dist/components/InfoField.js +17 -13
- package/dist/components/InfoField.styles.js +26 -8
- package/dist/components/InfoSection.styles.js +8 -1
- package/dist/components/PageHeader.js +21 -19
- package/dist/components/PageHeader.styles.js +6 -0
- package/dist/components/SidebarSection.js +12 -10
- package/dist/components/SidebarSection.styles.js +6 -0
- package/dist/react.d.ts +2 -0
- package/package.json +1 -1
- package/skills/modern-app/references/components/action-bar.md +3 -0
- package/skills/modern-app/references/components/empty-state.md +3 -0
- package/skills/modern-app/references/components/group-box.md +3 -0
- package/skills/modern-app/references/components/info-field.md +3 -0
- package/skills/modern-app/references/components/info-section.md +1 -1
- package/skills/modern-app/references/components/page-header.md +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.59.0] - 2026-10-23
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **`<u-info-section layout="strip">` type-checks in JSX.** The `@iyulab/modern-app/react` augmentation of
|
|
8
|
+
`JSX.IntrinsicElements` declared only `min` for `u-info-section`, so the documented strip layout was a `TS2322`
|
|
9
|
+
for raw-tag JSX consumers. It now takes `layout?: InfoSectionLayout`. Types only — runtime is unchanged. A test now
|
|
10
|
+
compares every augmented tag with the attributes its element declares, so the two cannot drift apart again.
|
|
11
|
+
- **Padding, borders and spacing survive a document-wide reset.** Under Tailwind's preflight
|
|
12
|
+
(`* { padding: 0; border: 0 solid; margin: 0 }`) a `u-info-section layout="strip"` cell lost its padding, a
|
|
13
|
+
`u-info-field appearance="tile"` lost its border and padding, a `u-group-box` lost its border, and `u-empty-state`,
|
|
14
|
+
`u-action-bar` and `u-page-header` lost their padding or the space under them, and a `u-info-field` trend icon
|
|
15
|
+
touched its caption. Document rules beat `:host` and
|
|
16
|
+
`::slotted()` rules whatever their specificity, so a box drawn on the host is a box any reset removes. These elements
|
|
17
|
+
now draw their box on a new `base` part inside the shadow root; the host only takes its place in the layout.
|
|
18
|
+
Restyle the box with `::part(base)` — padding or a border you set on the host now adds outside it. A strip cell that
|
|
19
|
+
is not a `u-info-field` still gets its padding as host padding.
|
|
20
|
+
|
|
3
21
|
## [0.58.0] - 2026-10-23
|
|
4
22
|
|
|
5
23
|
### Added
|
|
@@ -15,17 +15,19 @@ var l = class extends n {
|
|
|
15
15
|
}
|
|
16
16
|
render() {
|
|
17
17
|
return a`
|
|
18
|
-
<div class="
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
<div class="base" part="base">
|
|
19
|
+
<div class="danger ${this.hasDanger ? "" : "empty"}" part="danger">
|
|
20
|
+
<slot name="danger"
|
|
21
|
+
@slotchange=${(e) => this.hasDanger = r(e.target)}
|
|
22
|
+
></slot>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="summary ${this.hasSummary ? "" : "empty"}" part="summary">
|
|
25
|
+
<slot name="summary"
|
|
26
|
+
@slotchange=${(e) => this.hasSummary = r(e.target)}
|
|
27
|
+
></slot>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="main" part="main"><slot></slot></div>
|
|
22
30
|
</div>
|
|
23
|
-
<div class="summary ${this.hasSummary ? "" : "empty"}" part="summary">
|
|
24
|
-
<slot name="summary"
|
|
25
|
-
@slotchange=${(e) => this.hasSummary = r(e.target)}
|
|
26
|
-
></slot>
|
|
27
|
-
</div>
|
|
28
|
-
<div class="main" part="main"><slot></slot></div>
|
|
29
31
|
`;
|
|
30
32
|
}
|
|
31
33
|
};
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { css as e } from "lit";
|
|
2
2
|
// src/components/ActionBar.styles.ts
|
|
3
3
|
var t = e`
|
|
4
|
+
|
|
5
|
+
|
|
4
6
|
:host {
|
|
7
|
+
display: block;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.base {
|
|
5
11
|
display: flex;
|
|
6
12
|
align-items: center;
|
|
7
13
|
gap: var(--u-space-sm, 8px);
|
|
@@ -67,8 +73,9 @@ var t = e`
|
|
|
67
73
|
position: sticky;
|
|
68
74
|
bottom: 0;
|
|
69
75
|
background-color: var(--u-bg-color, #FFFFFF);
|
|
76
|
+
}
|
|
77
|
+
:host([sticky]) .base {
|
|
70
78
|
border-top: 1px solid var(--u-border-color-weak, #EEEEEE);
|
|
71
|
-
padding: var(--u-space-md, 12px) var(--action-bar-padding-inline, 0);
|
|
72
79
|
}
|
|
73
80
|
`;
|
|
74
81
|
export { t as styles };
|
|
@@ -47,19 +47,21 @@ var d = class extends n {
|
|
|
47
47
|
render() {
|
|
48
48
|
let e = this.defaults, t = this.description || e.description;
|
|
49
49
|
return o`
|
|
50
|
-
<div class="
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
<div class="base" part="base">
|
|
51
|
+
<div class="icon" part="icon" aria-hidden="true">
|
|
52
|
+
<slot name="icon">${e.icon}</slot>
|
|
53
|
+
</div>
|
|
54
|
+
<!-- 오류는 경보다 — 그 범위는 이 상태가 전하는 사실 전체(제목 + 사유)다. 사유가 다음 행동(다시 시도 · 권한 요청 ·
|
|
55
|
+
조건 고치기)을 가르므로 제목만 읽히면 듣는 사람이 다른 사실을 받는다. 행동 슬롯은 밖. -->
|
|
56
|
+
<div class="message" part="message" role=${this.variant === "error" ? "alert" : s}>
|
|
57
|
+
<p class="title" part="title">${this.title || e.title}</p>
|
|
58
|
+
${t ? o`<p class="description" part="description">${t}</p>` : s}
|
|
59
|
+
</div>
|
|
60
|
+
<div class="actions ${this.hasActions ? "" : "empty"}" part="actions">
|
|
61
|
+
<slot name="actions"
|
|
62
|
+
@slotchange=${(e) => this.hasActions = r(e.target)}
|
|
63
|
+
></slot>
|
|
64
|
+
</div>
|
|
63
65
|
</div>
|
|
64
66
|
`;
|
|
65
67
|
}
|
|
@@ -34,18 +34,21 @@ var f, p = {
|
|
|
34
34
|
render() {
|
|
35
35
|
let e = !!this.title || !!this.description || this.hasActions;
|
|
36
36
|
return a`
|
|
37
|
-
<div class="
|
|
38
|
-
<div class="
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
<div class="base" part="base">
|
|
38
|
+
<div class="header ${this.divider ? "divider" : ""} ${e ? "" : "empty"}" part="header">
|
|
39
|
+
<div class="titles">
|
|
40
|
+
${u`<${p[this.headingLevel]} class="title" part="title">${this.title}${this.title && this.meta ? a` <span class="meta" part="meta">${this.meta}</span>` : ""}</${p[this.headingLevel]}>`}
|
|
41
|
+
${this.description ? a`<p class="description" part="description">${this.description}</p>` : o}
|
|
42
|
+
</div>
|
|
43
|
+
<div class="actions ${this.hasActions ? "" : "empty"}" part="actions">
|
|
44
|
+
<slot name="actions"
|
|
45
|
+
@slotchange=${(e) => this.hasActions = r(e.target)}
|
|
46
|
+
></slot>
|
|
47
|
+
</div>
|
|
46
48
|
</div>
|
|
49
|
+
<div class="body ${this.flush ? "flush" : ""}" part="body"><slot></slot></div>
|
|
47
50
|
</div>
|
|
48
|
-
|
|
51
|
+
`;
|
|
49
52
|
}
|
|
50
53
|
};
|
|
51
54
|
t([c({ type: String }), e("design:type", Object)], m.prototype, "title", void 0), t([c({ type: String }), e("design:type", String)], m.prototype, "meta", void 0), t([c({ type: String }), e("design:type", String)], m.prototype, "description", void 0), t([c({ type: Boolean }), e("design:type", Object)], m.prototype, "divider", void 0), t([c({ type: Boolean }), e("design:type", Object)], m.prototype, "flush", void 0), t([c({
|
|
@@ -31,6 +31,7 @@ export declare function isBlank(v: unknown): boolean;
|
|
|
31
31
|
* @slot trend-icon - 추세 줄 앞의 상태 표시(예: 주의 아이콘). 추세 줄이 있을 때(`trend` · `trendLabel`) 그린다.
|
|
32
32
|
* @slot visual - 값과 같은 줄 끝의 작은 그림(추세 미니 차트 · 진행 고리 등). 값을 대신하지 않는다 — 장식이면 `aria-hidden="true"`,
|
|
33
33
|
* 그 자체로 정보면 자기 이름(`role="img"` + `aria-label`)을 준다. 비면 자리를 차지하지 않는다.
|
|
34
|
+
* @csspart base - 칸의 상자 — 타일의 면 · 테두리 · 여백과 지표 띠 칸의 여백을 호스트가 아니라 여기서 그린다(문서 전역 리셋에 지지 않게)
|
|
34
35
|
* @csspart label - 라벨
|
|
35
36
|
* @csspart value - 값
|
|
36
37
|
* @csspart unit - 단위
|
|
@@ -141,6 +142,8 @@ export declare class InfoField extends StyledElement<ElementParts> {
|
|
|
141
142
|
private nameSlottedWidgets;
|
|
142
143
|
protected updated(changed: PropertyValues): void;
|
|
143
144
|
/** `visual` 슬롯에 든 것이 있는가 — 비면 그 상자를 그리지 않는다(값 옆에 빈 간격을 남기지 않게). */
|
|
145
|
+
/** 추세 아이콘 슬롯이 찼는가 — 그 옆 간격은 섀도 안 상자가 갖는다(`::slotted` 여백은 문서의 전역 리셋에 진다). */
|
|
146
|
+
private hasTrendIcon;
|
|
144
147
|
private hasVisual;
|
|
145
148
|
private get hasSlotted();
|
|
146
149
|
private formatValue;
|
|
@@ -14,7 +14,7 @@ function f(e) {
|
|
|
14
14
|
}
|
|
15
15
|
var p = class extends n {
|
|
16
16
|
constructor(...e) {
|
|
17
|
-
super(...e), this.label = "", this.blank = "—", this.numeric = !1, this.size = "default", this.appearance = "plain", this.namedWidgets = /* @__PURE__ */ new WeakMap(), this.hasVisual = !1;
|
|
17
|
+
super(...e), this.label = "", this.blank = "—", this.numeric = !1, this.size = "default", this.appearance = "plain", this.namedWidgets = /* @__PURE__ */ new WeakMap(), this.hasTrendIcon = !1, this.hasVisual = !1;
|
|
18
18
|
}
|
|
19
19
|
static {
|
|
20
20
|
this.styles = [super.styles, r];
|
|
@@ -41,21 +41,25 @@ var p = class extends n {
|
|
|
41
41
|
render() {
|
|
42
42
|
let e = !this.hasSlotted && f(this.value), t = e && this.blankReason ? this.blankReason : void 0, n = this.numeric || this.format === "number" || this.format === "currency", r = this.trend !== void 0 || this.trendLabel !== void 0, a = this.tone ?? d(this.trend), o = this.trend === "up" ? "▲" : this.trend === "down" ? "▼" : "", s = !e && this.unit ? i`<span class="unit" part="unit">${this.unit}</span>` : "";
|
|
43
43
|
return i`
|
|
44
|
-
<div class="
|
|
45
|
-
|
|
46
|
-
<div class="value
|
|
47
|
-
|
|
48
|
-
<
|
|
44
|
+
<div class="base" part="base">
|
|
45
|
+
<div class="label" part="label">${this.label}</div>
|
|
46
|
+
<div class="value-row">
|
|
47
|
+
<div class="value ${n ? "numeric" : ""} ${e ? "blank" : ""} ${t ? "reasoned" : ""} tone-${a}" part="value">${this.hasSlotted ? i`<slot @slotchange=${() => void this.nameSlottedWidgets()}></slot>` : e ? this.blank : this.formatValue()}${s}</div>
|
|
48
|
+
<div class="visual" part="visual" ?hidden=${!this.hasVisual}>
|
|
49
|
+
<slot name="visual" @slotchange=${(e) => {
|
|
49
50
|
this.hasVisual = e.target.assignedElements().length > 0;
|
|
50
51
|
}}></slot>
|
|
52
|
+
</div>
|
|
51
53
|
</div>
|
|
54
|
+
${r ? i`
|
|
55
|
+
<div class="trend tone-${a}" part="trend">
|
|
56
|
+
<span class="trend-icon" ?hidden=${!this.hasTrendIcon}><slot name="trend-icon" @slotchange=${(e) => {
|
|
57
|
+
this.hasTrendIcon = e.target.assignedElements().length > 0;
|
|
58
|
+
}}></slot></span>${o ? i`<span aria-hidden="true">${o}</span> ` : ""}${this.trendLabel ?? ""}
|
|
59
|
+
</div>
|
|
60
|
+
` : ""}
|
|
61
|
+
${t ?? this.description ? i`<div class="description" part="description">${t ?? this.description}</div>` : ""}
|
|
52
62
|
</div>
|
|
53
|
-
${r ? i`
|
|
54
|
-
<div class="trend tone-${a}" part="trend">
|
|
55
|
-
<slot name="trend-icon"></slot>${o ? i`<span aria-hidden="true">${o}</span> ` : ""}${this.trendLabel ?? ""}
|
|
56
|
-
</div>
|
|
57
|
-
` : ""}
|
|
58
|
-
${t ?? this.description ? i`<div class="description" part="description">${t ?? this.description}</div>` : ""}
|
|
59
63
|
`;
|
|
60
64
|
}
|
|
61
65
|
};
|
|
@@ -71,5 +75,5 @@ t([o({ type: String }), e("design:type", Object)], p.prototype, "label", void 0)
|
|
|
71
75
|
}), e("design:type", Object)], p.prototype, "appearance", void 0), t([o({
|
|
72
76
|
type: String,
|
|
73
77
|
attribute: "blank-reason"
|
|
74
|
-
}), e("design:type", String)], p.prototype, "blankReason", void 0), t([o({ type: String }), e("design:type", String)], p.prototype, "description", void 0), t([s(), e("design:type", Object)], p.prototype, "hasVisual", void 0), p = t([a("u-info-field")], p);
|
|
78
|
+
}), e("design:type", String)], p.prototype, "blankReason", void 0), t([o({ type: String }), e("design:type", String)], p.prototype, "description", void 0), t([s(), e("design:type", Object)], p.prototype, "hasTrendIcon", void 0), t([s(), e("design:type", Object)], p.prototype, "hasVisual", void 0), p = t([a("u-info-field")], p);
|
|
75
79
|
export { p as InfoField, f as isBlank };
|
|
@@ -6,6 +6,17 @@ var t = e`
|
|
|
6
6
|
min-width: 0;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
.base {
|
|
14
|
+
padding: var(--_info-field-padding, 0);
|
|
15
|
+
}
|
|
16
|
+
.base > * {
|
|
17
|
+
--_info-field-padding: initial;
|
|
18
|
+
}
|
|
19
|
+
|
|
9
20
|
.label {
|
|
10
21
|
font-size: var(--u-text-caption-size, 12px);
|
|
11
22
|
font-weight: var(--u-text-caption-weight, 400);
|
|
@@ -63,28 +74,29 @@ var t = e`
|
|
|
63
74
|
}
|
|
64
75
|
|
|
65
76
|
|
|
66
|
-
:host([appearance="tile"]) {
|
|
67
|
-
|
|
77
|
+
:host([appearance="tile"]) .base {
|
|
78
|
+
box-sizing: border-box;
|
|
79
|
+
height: 100%;
|
|
80
|
+
padding: var(--_info-field-padding, var(--u-space-md, 12px));
|
|
68
81
|
border: 1px solid var(--u-border-color, #E0E0E0);
|
|
69
82
|
border-radius: var(--u-radius-xl, 8px);
|
|
70
83
|
background-color: var(--u-bg-color, #FFFFFF);
|
|
71
|
-
box-sizing: border-box;
|
|
72
84
|
}
|
|
73
85
|
|
|
74
|
-
:host([appearance="tile"][tone="warning"]) {
|
|
86
|
+
:host([appearance="tile"][tone="warning"]) .base {
|
|
75
87
|
background-color: var(--u-warning-bg-color, #FFF59D);
|
|
76
88
|
border-color: var(--u-warning-color-weak, #FFEB3B);
|
|
77
89
|
}
|
|
78
|
-
:host([appearance="tile"][tone="negative"]) {
|
|
90
|
+
:host([appearance="tile"][tone="negative"]) .base {
|
|
79
91
|
background-color: var(--u-danger-bg-color, #FFEBEE);
|
|
80
92
|
border-color: var(--u-danger-color-weak, #F44336);
|
|
81
93
|
}
|
|
82
|
-
:host([appearance="tile"][tone="positive"]) {
|
|
94
|
+
:host([appearance="tile"][tone="positive"]) .base {
|
|
83
95
|
background-color: var(--u-success-bg-color, #E8F5E9);
|
|
84
96
|
border-color: var(--u-success-color-weak, #4CAF50);
|
|
85
97
|
}
|
|
86
98
|
@media (forced-colors: active) {
|
|
87
|
-
:host([appearance="tile"]) { border-color: CanvasText; }
|
|
99
|
+
:host([appearance="tile"]) .base { border-color: CanvasText; }
|
|
88
100
|
}
|
|
89
101
|
|
|
90
102
|
|
|
@@ -146,8 +158,14 @@ var t = e`
|
|
|
146
158
|
margin-top: var(--u-space-3xs, 2px);
|
|
147
159
|
}
|
|
148
160
|
|
|
149
|
-
|
|
161
|
+
|
|
162
|
+
.trend-icon {
|
|
150
163
|
margin-inline-end: 0.3em;
|
|
164
|
+
}
|
|
165
|
+
.trend-icon[hidden] {
|
|
166
|
+
display: none;
|
|
167
|
+
}
|
|
168
|
+
::slotted([slot="trend-icon"]) {
|
|
151
169
|
vertical-align: -0.125em;
|
|
152
170
|
}
|
|
153
171
|
|
|
@@ -25,11 +25,18 @@ var t = e`
|
|
|
25
25
|
border-radius: var(--u-radius-xl, 8px);
|
|
26
26
|
overflow: hidden;
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
28
31
|
:host([layout="strip"]) ::slotted(*) {
|
|
29
32
|
flex: 1 1 calc((640px - 100%) * 999);
|
|
30
33
|
min-width: 0;
|
|
31
|
-
padding: var(--u-space-md, 12px) var(--u-space-lg, 16px);
|
|
32
34
|
background: var(--u-bg-color, #FFFFFF);
|
|
35
|
+
--_info-field-padding: var(--u-space-md, 12px) var(--u-space-lg, 16px);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:host([layout="strip"]) ::slotted(:not(u-info-field)) {
|
|
39
|
+
padding: var(--u-space-md, 12px) var(--u-space-lg, 16px);
|
|
33
40
|
}
|
|
34
41
|
`;
|
|
35
42
|
export { t as styles };
|
|
@@ -16,27 +16,29 @@ var d = class extends n {
|
|
|
16
16
|
}
|
|
17
17
|
render() {
|
|
18
18
|
return o`
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<div class="
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
<div class="base" part="base">
|
|
20
|
+
${this.back ? o`<a class="back" part="back" href=${this.back}>${this.backLabel || i(this.locale || void 0).back}</a>` : s}
|
|
21
|
+
<div class="heading" part="heading">
|
|
22
|
+
<div class="eyebrow ${this.eyebrow || this.hasEyebrow ? "" : "empty"}" part="eyebrow">
|
|
23
|
+
<slot name="eyebrow"
|
|
24
|
+
@slotchange=${(e) => this.hasEyebrow = r(e.target)}
|
|
25
|
+
>${this.eyebrow ?? s}</slot>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="title-row">
|
|
28
|
+
<h1 class="title" part="title">${this.title}</h1>
|
|
29
|
+
<span class="status ${this.hasStatus ? "" : "empty"}" part="status">
|
|
30
|
+
<slot name="status"
|
|
31
|
+
@slotchange=${(e) => this.hasStatus = r(e.target)}
|
|
32
|
+
></slot>
|
|
33
|
+
</span>
|
|
34
|
+
</div>
|
|
35
|
+
${this.subtitle ? o`<p class="subtitle" part="subtitle">${this.subtitle}</p>` : s}
|
|
25
36
|
</div>
|
|
26
|
-
<div class="
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@slotchange=${(e) => this.hasStatus = r(e.target)}
|
|
31
|
-
></slot>
|
|
32
|
-
</span>
|
|
37
|
+
<div class="actions ${this.hasActions ? "" : "empty"}" part="actions">
|
|
38
|
+
<slot name="actions"
|
|
39
|
+
@slotchange=${(e) => this.hasActions = r(e.target)}
|
|
40
|
+
></slot>
|
|
33
41
|
</div>
|
|
34
|
-
${this.subtitle ? o`<p class="subtitle" part="subtitle">${this.subtitle}</p>` : s}
|
|
35
|
-
</div>
|
|
36
|
-
<div class="actions ${this.hasActions ? "" : "empty"}" part="actions">
|
|
37
|
-
<slot name="actions"
|
|
38
|
-
@slotchange=${(e) => this.hasActions = r(e.target)}
|
|
39
|
-
></slot>
|
|
40
42
|
</div>
|
|
41
43
|
`;
|
|
42
44
|
}
|
|
@@ -14,17 +14,19 @@ var s = class extends n {
|
|
|
14
14
|
}
|
|
15
15
|
render() {
|
|
16
16
|
return i`
|
|
17
|
-
<div class="
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
<div class="base" part="base">
|
|
18
|
+
<div class="header" part="header" ?hidden=${this.compact}>
|
|
19
|
+
<span class="title" part="title">
|
|
20
|
+
${this.mainTitle}
|
|
21
|
+
</span>
|
|
22
|
+
<span class="subtitle" part="subtitle" ?hidden=${!this.subTitle}>
|
|
23
|
+
${this.subTitle}
|
|
24
|
+
</span>
|
|
25
|
+
</div>
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
<div class="items" part="items">
|
|
28
|
+
<slot></slot>
|
|
29
|
+
</div>
|
|
28
30
|
</div>
|
|
29
31
|
`;
|
|
30
32
|
}
|
package/dist/react.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { Wizard as WizardElement, WizardEventMap } from './components/Wizard.js'
|
|
|
5
5
|
import { GroupBoxLevel } from './components/GroupBox.js';
|
|
6
6
|
import { EmptyStateVariant } from './components/EmptyState.js';
|
|
7
7
|
import { TimelineItemColor } from './components/TimelineItem.js';
|
|
8
|
+
import { InfoSectionLayout } from './components/InfoSection.js';
|
|
8
9
|
import { InfoFieldFormat, InfoFieldSize, InfoFieldTrend, InfoFieldTone, InfoFieldAppearance } from './components/InfoField.js';
|
|
9
10
|
export { ScreenObserver } from './internals/ScreenObserver.js';
|
|
10
11
|
export type { ScreenSize, ScreenObserverConfig, ScreenResizeEvent } from './internals/ScreenObserver.js';
|
|
@@ -100,6 +101,7 @@ declare module 'react' {
|
|
|
100
101
|
};
|
|
101
102
|
'u-info-section': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
|
|
102
103
|
min?: number | string;
|
|
104
|
+
layout?: InfoSectionLayout;
|
|
103
105
|
};
|
|
104
106
|
'u-timeline': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
105
107
|
'u-timeline-item': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
|
package/package.json
CHANGED
|
@@ -36,10 +36,13 @@ rather than negative margins (the bar cannot know its parent's padding).
|
|
|
36
36
|
|
|
37
37
|
| Part | Description |
|
|
38
38
|
|------|-------------|
|
|
39
|
+
| `base` | The bar's box — layout, padding and the sticky top border are drawn here rather than on the host |
|
|
39
40
|
| `main` | Main action group |
|
|
40
41
|
| `danger` | Destructive action group |
|
|
41
42
|
| `summary` | Summary text wrapper |
|
|
42
43
|
|
|
44
|
+
The host only takes its place in the layout. Padding, borders and spacing live on `base` inside the shadow root, so a document-wide reset such as Tailwind's preflight (`* { padding: 0; border: 0 }`) cannot strip them — document rules beat `:host` rules whatever their specificity. Restyle the box with `::part(base)`.
|
|
45
|
+
|
|
43
46
|
## CSS Custom Properties
|
|
44
47
|
|
|
45
48
|
| Property | Description |
|
|
@@ -50,9 +50,12 @@ action is **asking for access**.
|
|
|
50
50
|
|
|
51
51
|
| Part | Description |
|
|
52
52
|
|------|-------------|
|
|
53
|
+
| `base` | The block's box — layout and padding are drawn here rather than on the host |
|
|
53
54
|
| `icon` · `title` · `description` · `actions` | The four regions |
|
|
54
55
|
| `message` | Wraps `title` and `description` — the alert of `variant="error"` |
|
|
55
56
|
|
|
57
|
+
The host only takes its place in the layout. Padding, borders and spacing live on `base` inside the shadow root, so a document-wide reset such as Tailwind's preflight (`* { padding: 0; border: 0 }`) cannot strip them — document rules beat `:host` rules whatever their specificity. Restyle the box with `::part(base)`.
|
|
58
|
+
|
|
56
59
|
## CSS Custom Properties
|
|
57
60
|
|
|
58
61
|
| Property | Description |
|
|
@@ -46,11 +46,14 @@ do).
|
|
|
46
46
|
|
|
47
47
|
| Part | Description |
|
|
48
48
|
|------|-------------|
|
|
49
|
+
| `base` | The card's box — surface, border, corner and shadow are drawn here rather than on the host |
|
|
49
50
|
| `header` · `title` · `actions` | Header row |
|
|
50
51
|
| `meta` | Secondary text inside the title |
|
|
51
52
|
| `description` | One-line description under the title |
|
|
52
53
|
| `body` | Body wrapper |
|
|
53
54
|
|
|
55
|
+
The host only takes its place in the layout. Padding, borders and spacing live on `base` inside the shadow root, so a document-wide reset such as Tailwind's preflight (`* { padding: 0; border: 0 }`) cannot strip them — document rules beat `:host` rules whatever their specificity. Restyle the box with `::part(base)`.
|
|
56
|
+
|
|
54
57
|
## CSS Custom Properties
|
|
55
58
|
|
|
56
59
|
| Property | Description |
|
|
@@ -130,11 +130,14 @@ name (`role="img"` and `aria-label`) (`0.57.0~`):
|
|
|
130
130
|
|
|
131
131
|
| Part | Description |
|
|
132
132
|
|------|-------------|
|
|
133
|
+
| `base` | The field's box — a tile's surface, border and padding (and a strip cell's padding) are drawn here rather than on the host |
|
|
133
134
|
| `label` · `value` · `trend` | The label, the value, and the (optional) trend indicator |
|
|
134
135
|
| `unit` | The unit, inside `value` (only when `unit` is set and the value is not blank) |
|
|
135
136
|
| `description` | The supporting line (when `description` is set, or the value is blank and `blankReason` is set) |
|
|
136
137
|
| `visual` | The box holding the `visual` slot (not drawn when the slot is empty) |
|
|
137
138
|
|
|
139
|
+
The host only takes its place in the layout. Padding, borders and spacing live on `base` inside the shadow root, so a document-wide reset such as Tailwind's preflight (`* { padding: 0; border: 0 }`) cannot strip them — document rules beat `:host` rules whatever their specificity. Restyle the box with `::part(base)`.
|
|
140
|
+
|
|
138
141
|
## CSS Custom Properties
|
|
139
142
|
|
|
140
143
|
| Property | Description |
|
|
@@ -51,7 +51,7 @@ A stat strip — the totals above a list, as cells rather than a sentence:
|
|
|
51
51
|
|----------|-------------|
|
|
52
52
|
| `--u-space-lg` / `--u-space-xl` | Grid gap (row / column) |
|
|
53
53
|
| `--u-border-color` · `--u-radius-xl` · `--u-bg-color` | Strip surface, dividers and corner; cell background |
|
|
54
|
-
| `--u-space-md` / `--u-space-lg` | Strip cell padding (block / inline) |
|
|
54
|
+
| `--u-space-md` / `--u-space-lg` | Strip cell padding (block / inline) — a `u-info-field` cell draws it inside its own `base` part, so a document-wide reset cannot strip it; any other child element gets it as host padding |
|
|
55
55
|
|
|
56
56
|
⚠ Column width is set via the `min` property, not a custom property — it's applied as an inline
|
|
57
57
|
style per instance, so a `--info-min` override in a stylesheet would lose to it.
|
|
@@ -39,12 +39,15 @@ screens nobody opens.
|
|
|
39
39
|
|
|
40
40
|
| Part | Description |
|
|
41
41
|
|------|-------------|
|
|
42
|
+
| `base` | The header's box — layout and the space under it are drawn here rather than on the host |
|
|
42
43
|
| `back` | Back link |
|
|
43
44
|
| `heading` | Eyebrow + title + subtitle wrapper |
|
|
44
45
|
| `eyebrow` | Eyebrow row (hidden when empty) |
|
|
45
46
|
| `title` · `subtitle` | Text elements |
|
|
46
47
|
| `status` · `actions` | Slot wrappers |
|
|
47
48
|
|
|
49
|
+
The host only takes its place in the layout. Padding, borders and spacing live on `base` inside the shadow root, so a document-wide reset such as Tailwind's preflight (`* { padding: 0; border: 0 }`) cannot strip them — document rules beat `:host` rules whatever their specificity. Restyle the box with `::part(base)`.
|
|
50
|
+
|
|
48
51
|
## CSS Custom Properties
|
|
49
52
|
|
|
50
53
|
| Property | Description |
|