@neuravision/construct 2.1.3 → 2.1.5
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 +32 -0
- package/components/button.css +18 -2
- package/components/card.css +9 -0
- package/components/modal.css +8 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,38 @@ All notable changes to `@neuravision/construct` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.1.5] - 2026-07-17
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Card & Modal: the 2.1.4 `[hidden]` slot guards are replaced with `:not(:has(*))`
|
|
13
|
+
empty-slot rules — update immediately if you are on 2.1.4.** The attribute guards
|
|
14
|
+
trusted the wrapper's projection detection; ng-construct's `AfCard`/`AfModal` detection
|
|
15
|
+
(`contentChild('[header]')` resolves a template reference name, never a CSS selector)
|
|
16
|
+
reports "empty" for every slot, so 2.1.4 blanked out populated card headers/footers and
|
|
17
|
+
every modal footer in consuming apps. The slots now decide visibility purely in CSS:
|
|
18
|
+
a header/footer wrapper with no projected element hides itself, one with content always
|
|
19
|
+
renders — regardless of what the wrapper's `hidden` attribute claims. The original
|
|
20
|
+
2.1.4 goal (no ghost divider under footerless cards/modals) is preserved.
|
|
21
|
+
|
|
22
|
+
## [2.1.4] - 2026-07-17
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- Button: custom icons composed into the `.ct-button__icon` slot (a `.ct-icon` — also when
|
|
27
|
+
wrapped by a framework component host — or a bare `<svg>`) now adopt the slot's size,
|
|
28
|
+
completing the composition contract introduced for the chip slot in 2.1.3. The slot size
|
|
29
|
+
is expressed as `--ct-button-icon-size` (default `--icon-sm`); context overrides like the
|
|
30
|
+
modal header's larger close icon set the custom property and flow through to composed
|
|
31
|
+
content. Consumers that override `.ct-button__icon` dimensions directly should switch to
|
|
32
|
+
`--ct-button-icon-size` so composed icons follow.
|
|
33
|
+
- Card & Modal: header/footer slots hidden via the `hidden` attribute (e.g. by framework
|
|
34
|
+
wrappers when no content is projected) now actually disappear. The slots' `display: flex`
|
|
35
|
+
previously overrode the UA stylesheet's `[hidden] { display: none }`, so every card
|
|
36
|
+
without footer content rendered a ghost divider plus spacing at the bottom edge (same
|
|
37
|
+
for modals without a footer). New guards: `.ct-card__header[hidden]`,
|
|
38
|
+
`.ct-card__footer[hidden]`, `.ct-modal__footer[hidden]`.
|
|
39
|
+
|
|
8
40
|
## [2.1.3] - 2026-07-17
|
|
9
41
|
|
|
10
42
|
### Fixed
|
package/components/button.css
CHANGED
|
@@ -186,13 +186,29 @@
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
.ct-button__icon {
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
--ct-button-icon-size: var(--icon-sm);
|
|
190
|
+
|
|
191
|
+
width: var(--ct-button-icon-size);
|
|
192
|
+
height: var(--ct-button-icon-size);
|
|
191
193
|
display: inline-flex;
|
|
192
194
|
align-items: center;
|
|
193
195
|
justify-content: center;
|
|
194
196
|
}
|
|
195
197
|
|
|
198
|
+
/* Composed icon content adopts the slot's size — same composition
|
|
199
|
+
contract as `.ct-chip__icon` (see chip.css). `.ct-icon` carries a
|
|
200
|
+
fixed `--icon-md` box of its own that would overflow the slot; the
|
|
201
|
+
size is restated via the slot's custom property because `width: 100%`
|
|
202
|
+
does not resolve through an intermediate framework component host.
|
|
203
|
+
Context overrides (e.g. `.ct-modal__header`) set
|
|
204
|
+
`--ct-button-icon-size` and flow through to composed content. */
|
|
205
|
+
.ct-button__icon .ct-icon,
|
|
206
|
+
.ct-button__icon > svg {
|
|
207
|
+
width: var(--ct-button-icon-size);
|
|
208
|
+
height: var(--ct-button-icon-size);
|
|
209
|
+
font-size: var(--ct-button-icon-size);
|
|
210
|
+
}
|
|
211
|
+
|
|
196
212
|
@media (pointer: coarse) {
|
|
197
213
|
.ct-button {
|
|
198
214
|
min-width: var(--control-height-sm);
|
package/components/card.css
CHANGED
|
@@ -46,6 +46,15 @@
|
|
|
46
46
|
border-top: var(--border-thin) solid var(--color-border-subtle);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/* Slot wrappers render even when no content is projected into them (framework
|
|
50
|
+
wrappers cannot reliably detect projection, and the `hidden` attribute they
|
|
51
|
+
set is overridden by the display rules above). Hide slots without projected
|
|
52
|
+
content so an empty header/footer leaves no ghost spacing or divider. */
|
|
53
|
+
.ct-card__header:not(:has(*)),
|
|
54
|
+
.ct-card__footer:not(:has(*)) {
|
|
55
|
+
display: none;
|
|
56
|
+
}
|
|
57
|
+
|
|
49
58
|
:is(a, button, [role='button'], [role='link']).ct-card--interactive {
|
|
50
59
|
cursor: pointer;
|
|
51
60
|
transition: box-shadow var(--duration-fast) var(--easing-standard),
|
package/components/modal.css
CHANGED
|
@@ -46,8 +46,7 @@
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
.ct-modal__header .ct-button__icon {
|
|
49
|
-
|
|
50
|
-
height: var(--icon-lg);
|
|
49
|
+
--ct-button-icon-size: var(--icon-lg);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
.ct-modal__body {
|
|
@@ -65,6 +64,13 @@
|
|
|
65
64
|
flex-wrap: wrap;
|
|
66
65
|
}
|
|
67
66
|
|
|
67
|
+
/* The footer wrapper renders even when no content is projected into it
|
|
68
|
+
(framework wrappers cannot reliably detect projection). Hide it when
|
|
69
|
+
empty so footerless modals leave no ghost divider behind. */
|
|
70
|
+
.ct-modal__footer:not(:has(*)) {
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
68
74
|
/* Modal size variants */
|
|
69
75
|
|
|
70
76
|
.ct-modal--sm .ct-modal__dialog {
|