@vaadin/card 25.4.0-alpha4 → 25.4.0-alpha6

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.
@@ -33,7 +33,7 @@
33
33
  "type": {
34
34
  "text": "string"
35
35
  },
36
- "description": "The title of the card. When set, any custom slotted title is removed and this string-based title is used instead. If this title is used, an `aria-labelledby` attribute that points to the generated title element is set.",
36
+ "description": "The title of the card. A custom slotted title takes precedence over this property. The card is labelled with `aria-labelledby` by the title element in the `title` slot, generated or custom.",
37
37
  "attribute": "card-title"
38
38
  },
39
39
  {
@@ -64,7 +64,7 @@
64
64
  "type": {
65
65
  "text": "string"
66
66
  },
67
- "description": "The title of the card. When set, any custom slotted title is removed and this string-based title is used instead. If this title is used, an `aria-labelledby` attribute that points to the generated title element is set.",
67
+ "description": "The title of the card. A custom slotted title takes precedence over this property. The card is labelled with `aria-labelledby` by the title element in the `title` slot, generated or custom.",
68
68
  "fieldName": "cardTitle"
69
69
  },
70
70
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/card",
3
- "version": "25.4.0-alpha4",
3
+ "version": "25.4.0-alpha6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,20 +34,20 @@
34
34
  "web-component"
35
35
  ],
36
36
  "dependencies": {
37
- "@vaadin/component-base": "25.4.0-alpha4",
38
- "@vaadin/vaadin-themable-mixin": "25.4.0-alpha4",
37
+ "@vaadin/component-base": "25.4.0-alpha6",
38
+ "@vaadin/vaadin-themable-mixin": "25.4.0-alpha6",
39
39
  "lit": "^3.0.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@vaadin/aura": "25.4.0-alpha4",
43
- "@vaadin/avatar": "25.4.0-alpha4",
44
- "@vaadin/button": "25.4.0-alpha4",
45
- "@vaadin/chai-plugins": "25.4.0-alpha4",
46
- "@vaadin/icon": "25.4.0-alpha4",
47
- "@vaadin/icons": "25.4.0-alpha4",
48
- "@vaadin/test-runner-commands": "25.4.0-alpha4",
42
+ "@vaadin/aura": "25.4.0-alpha6",
43
+ "@vaadin/avatar": "25.4.0-alpha6",
44
+ "@vaadin/button": "25.4.0-alpha6",
45
+ "@vaadin/chai-plugins": "25.4.0-alpha6",
46
+ "@vaadin/icon": "25.4.0-alpha6",
47
+ "@vaadin/icons": "25.4.0-alpha6",
48
+ "@vaadin/test-runner-commands": "25.4.0-alpha6",
49
49
  "@vaadin/testing-helpers": "^2.0.0",
50
- "@vaadin/vaadin-lumo-styles": "25.4.0-alpha4",
50
+ "@vaadin/vaadin-lumo-styles": "25.4.0-alpha6",
51
51
  "sinon": "^22.0.0"
52
52
  },
53
53
  "customElements": "custom-elements.json",
@@ -55,5 +55,5 @@
55
55
  "web-types.json",
56
56
  "web-types.lit.json"
57
57
  ],
58
- "gitHead": "7809e4c099538333a6dbd11d8da18a0c6ec30dad"
58
+ "gitHead": "4ead7de23a27c47e5ef4cb172481f8c54e86691a"
59
59
  }
@@ -3,12 +3,12 @@
3
3
  * Copyright (c) 2024 - 2026 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { SlotChildObserveController } from '@vaadin/component-base/src/slot-child-observe-controller.js';
6
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
7
7
 
8
8
  /**
9
9
  * A controller to manage the card title element.
10
10
  */
11
- export class TitleController extends SlotChildObserveController {
11
+ export class TitleController extends SlotController {
12
12
  constructor(host: HTMLElement);
13
13
 
14
14
  /**
@@ -3,15 +3,19 @@
3
3
  * Copyright (c) 2024 - 2026 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { SlotChildObserveController } from '@vaadin/component-base/src/slot-child-observe-controller.js';
6
+ import { addValuesToAttribute, removeValuesFromAttribute } from '@vaadin/component-base/src/dom-utils.js';
7
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
7
8
 
8
9
  /**
9
10
  * A controller to manage the card title element.
10
11
  */
11
- export class TitleController extends SlotChildObserveController {
12
+ export class TitleController extends SlotController {
13
+ /** @type {string | undefined} */
14
+ #labelId;
15
+
12
16
  constructor(host) {
13
17
  // Do not provide tag name, as we create the title lazily.
14
- super(host, 'title', null, { uniqueIdPrefix: 'card-title' });
18
+ super(host, 'title', null, { useUniqueId: true, uniqueIdPrefix: 'card-title' });
15
19
  }
16
20
 
17
21
  /**
@@ -23,15 +27,13 @@ export class TitleController extends SlotChildObserveController {
23
27
  this.title = title;
24
28
 
25
29
  if (title && title.trim() !== '') {
26
- // The string title replaces a custom slotted title, if any.
30
+ // A custom slotted title takes precedence over the string title.
27
31
  const child = this.getSlotChild();
28
- if (child && child !== this.defaultNode) {
29
- child.remove();
32
+ if (!child) {
33
+ this.restoreDefaultNode();
34
+ } else if (child === this.defaultNode) {
35
+ this.updateDefaultNode(child);
30
36
  }
31
-
32
- // Create or restore the default title node.
33
- this.restoreDefaultNode();
34
- this.updateDefaultNode(this.node);
35
37
  } else if (this.node && this.node === this.defaultNode) {
36
38
  // Clearing the string title removes the generated node.
37
39
  this.node.remove();
@@ -53,59 +55,65 @@ export class TitleController extends SlotChildObserveController {
53
55
  }
54
56
 
55
57
  /**
56
- * Override method inherited from `SlotController` to set up the default
57
- * title node as a heading and label the card by it. The heading role and
58
- * `aria-labelledby` are only applied to the generated string title, never
59
- * to a custom slotted title.
58
+ * Override method inherited from `SlotController` to label the card by
59
+ * the title node instead of the previous one, and to set up the generated
60
+ * title node as a heading. A custom title keeps its own role.
60
61
  *
61
62
  * @param {Node} node
62
63
  * @protected
63
64
  * @override
64
65
  */
65
66
  initNode(node) {
66
- if (node && node === this.defaultNode) {
67
+ if (!node) {
68
+ return;
69
+ }
70
+
71
+ if (node === this.defaultNode) {
67
72
  node.setAttribute('role', 'heading');
68
- this.host.setAttribute('aria-labelledby', node.id);
69
73
  }
74
+
75
+ removeValuesFromAttribute(this.host, 'aria-labelledby', this.#labelId);
76
+ this.#labelId = node.id;
77
+ addValuesToAttribute(this.host, 'aria-labelledby', this.#labelId);
70
78
  }
71
79
 
72
80
  /**
73
- * Override method inherited from `SlotChildObserveController` to handle a
74
- * custom title element. Skips the default `super` call so the custom node
75
- * keeps no generated ID. Clears the string title property, as a custom
76
- * title takes over.
81
+ * Override method inherited from `SlotController` to set a generated ID
82
+ * on a custom title without one.
77
83
  *
78
- * @param {Node} _node
84
+ * @param {Node} node
79
85
  * @protected
80
86
  * @override
81
87
  */
82
- initCustomNode(_node) {
83
- this.host.cardTitle = '';
88
+ initCustomNode(node) {
89
+ if (!node.id) {
90
+ node.id = this.defaultId;
91
+ }
84
92
  }
85
93
 
86
94
  /**
87
- * Override method inherited from `SlotChildObserveController` to drop the
88
- * labelling once the generated title node leaves the slot and is not
89
- * replaced by a custom title.
95
+ * Override method inherited from `SlotController` to drop the labelling
96
+ * once the slot is empty, and to restore the generated title once a custom
97
+ * title leaves an empty slot. A title that replaces another one is
98
+ * initialized before the old one is torn down.
90
99
  *
91
- * @param {Node} node
100
+ * @param {Node} _node
92
101
  * @protected
93
102
  * @override
94
103
  */
95
- teardownNode(node) {
96
- if (this.getSlotChild() !== this.defaultNode) {
97
- this.host.removeAttribute('aria-labelledby');
98
- }
104
+ teardownNode(_node) {
105
+ if (!this.getSlotChild()) {
106
+ removeValuesFromAttribute(this.host, 'aria-labelledby', this.#labelId);
107
+ this.#labelId = undefined;
99
108
 
100
- super.teardownNode(node);
109
+ this.restoreDefaultNode();
110
+ }
101
111
  }
102
112
 
103
113
  /**
104
- * Override method inherited from `SlotChildObserveController`
105
- * to create the default title element lazily as needed.
114
+ * Create and update the default title element lazily as needed.
106
115
  *
107
116
  * @protected
108
- * @override
109
117
  */
110
118
  restoreDefaultNode() {
111
119
  const { title } = this;
@@ -115,25 +123,20 @@ export class TitleController extends SlotChildObserveController {
115
123
  this.tagName = 'div';
116
124
 
117
125
  const node = this.attachDefaultNode();
126
+ node.id = this.defaultId;
118
127
  this.initNode(node);
128
+ this.updateDefaultNode(node);
119
129
  }
120
130
  }
121
131
 
122
132
  /**
123
- * Override method inherited from `SlotChildObserveController`
124
- * to update the default title element.
133
+ * Update the default title element.
125
134
  *
126
- * @param {Node | undefined} node
135
+ * @param {Node} node
127
136
  * @protected
128
- * @override
129
137
  */
130
138
  updateDefaultNode(node) {
131
- if (node) {
132
- node.textContent = this.title;
133
- node.setAttribute('aria-level', this.level || 2);
134
- }
135
-
136
- // Notify the host after update.
137
- super.updateDefaultNode(node);
139
+ node.textContent = this.title;
140
+ node.setAttribute('aria-level', this.level || 2);
138
141
  }
139
142
  }
@@ -57,7 +57,7 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
57
57
  */
58
58
  declare class Card extends ElementMixin(ThemableMixin(HTMLElement)) {
59
59
  /**
60
- * The title of the card. When set, any custom slotted title is removed and this string-based title is used instead. If this title is used, an `aria-labelledby` attribute that points to the generated title element is set.
60
+ * The title of the card. A custom slotted title takes precedence over this property. The card is labelled with `aria-labelledby` by the title element in the `title` slot, generated or custom.
61
61
  * @attr {string} card-title
62
62
  */
63
63
  cardTitle: string;
@@ -82,7 +82,7 @@ class Card extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(Li
82
82
  static get properties() {
83
83
  return {
84
84
  /**
85
- * The title of the card. When set, any custom slotted title is removed and this string-based title is used instead. If this title is used, an `aria-labelledby` attribute that points to the generated title element is set.
85
+ * The title of the card. A custom slotted title takes precedence over this property. The card is labelled with `aria-labelledby` by the title element in the `title` slot, generated or custom.
86
86
  *
87
87
  * @attr {string} card-title
88
88
  */
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/card",
4
- "version": "25.4.0-alpha4",
4
+ "version": "25.4.0-alpha6",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -12,7 +12,7 @@
12
12
  "attributes": [
13
13
  {
14
14
  "name": "card-title",
15
- "description": "The title of the card. When set, any custom slotted title is removed and this string-based title is used instead. If this title is used, an `aria-labelledby` attribute that points to the generated title element is set.",
15
+ "description": "The title of the card. A custom slotted title takes precedence over this property. The card is labelled with `aria-labelledby` by the title element in the `title` slot, generated or custom.",
16
16
  "value": {
17
17
  "type": [
18
18
  "string"
@@ -52,7 +52,7 @@
52
52
  "properties": [
53
53
  {
54
54
  "name": "cardTitle",
55
- "description": "The title of the card. When set, any custom slotted title is removed and this string-based title is used instead. If this title is used, an `aria-labelledby` attribute that points to the generated title element is set.",
55
+ "description": "The title of the card. A custom slotted title takes precedence over this property. The card is labelled with `aria-labelledby` by the title element in the `title` slot, generated or custom.",
56
56
  "value": {
57
57
  "type": [
58
58
  "string"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/card",
4
- "version": "25.4.0-alpha4",
4
+ "version": "25.4.0-alpha6",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -21,7 +21,7 @@
21
21
  "attributes": [
22
22
  {
23
23
  "name": ".cardTitle",
24
- "description": "The title of the card. When set, any custom slotted title is removed and this string-based title is used instead. If this title is used, an `aria-labelledby` attribute that points to the generated title element is set.",
24
+ "description": "The title of the card. A custom slotted title takes precedence over this property. The card is labelled with `aria-labelledby` by the title element in the `title` slot, generated or custom.",
25
25
  "value": {
26
26
  "kind": "expression"
27
27
  }