@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 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
@@ -186,13 +186,29 @@
186
186
  }
187
187
 
188
188
  .ct-button__icon {
189
- width: var(--icon-sm);
190
- height: var(--icon-sm);
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);
@@ -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),
@@ -46,8 +46,7 @@
46
46
  }
47
47
 
48
48
  .ct-modal__header .ct-button__icon {
49
- width: var(--icon-lg);
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuravision/construct",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
4
4
  "description": "Construct Design System - Accessible, token-based design system for modern web applications",
5
5
  "license": "MIT",
6
6
  "repository": {