@inglorious/ui 8.3.1 → 8.4.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.
Files changed (83) hide show
  1. package/package.json +4 -4
  2. package/src/controls/button/button.stories.js +1 -1
  3. package/src/controls/button/template.js +1 -1
  4. package/src/controls/button-group/button-group.stories.js +1 -1
  5. package/src/controls/button-group/template.js +1 -1
  6. package/src/controls/checkbox/checkbox.stories.js +1 -1
  7. package/src/controls/checkbox/style.css +1 -1
  8. package/src/controls/checkbox/template.js +7 -5
  9. package/src/controls/combobox/combobox.stories.js +1 -1
  10. package/src/controls/combobox/template.js +16 -11
  11. package/src/controls/fab/fab.stories.js +1 -1
  12. package/src/controls/file-upload/file-upload.stories.js +1 -1
  13. package/src/controls/file-upload/template.js +18 -7
  14. package/src/controls/icon-button/icon-button.stories.js +1 -1
  15. package/src/controls/image-cropper/image-cropper.stories.js +1 -1
  16. package/src/controls/input/input.stories.js +1 -1
  17. package/src/controls/input/template.js +16 -8
  18. package/src/controls/radio-group/radio-group.stories.js +1 -1
  19. package/src/controls/radio-group/template.js +8 -6
  20. package/src/controls/rating/rating.stories.js +1 -1
  21. package/src/controls/select/select.stories.js +1 -1
  22. package/src/controls/select/template.js +14 -12
  23. package/src/controls/slider/slider.stories.js +1 -1
  24. package/src/controls/slider/template.js +6 -4
  25. package/src/controls/switch/switch.stories.js +1 -1
  26. package/src/controls/switch/template.js +6 -4
  27. package/src/controls/textarea/template.js +17 -6
  28. package/src/controls/textarea/textarea.stories.js +1 -1
  29. package/src/data-display/avatar/avatar.stories.js +1 -1
  30. package/src/data-display/badge/badge.stories.js +1 -1
  31. package/src/data-display/before-after/before-after.stories.js +1 -1
  32. package/src/data-display/carousel/carousel.stories.js +1 -1
  33. package/src/data-display/chip/chip.stories.js +1 -1
  34. package/src/data-display/data-grid/data-grid.stories.js +1 -1
  35. package/src/data-display/divider/divider.stories.js +1 -1
  36. package/src/data-display/icon/icon-utf8.stories.js +1 -1
  37. package/src/data-display/icon/icon.stories.js +1 -1
  38. package/src/data-display/icon/template.js +1 -1
  39. package/src/data-display/list/list.stories.js +1 -1
  40. package/src/data-display/list/template.js +1 -1
  41. package/src/data-display/table/table.stories.js +1 -1
  42. package/src/data-display/table/template.js +1 -1
  43. package/src/data-display/tooltip/template.js +1 -1
  44. package/src/data-display/tooltip/tooltip.stories.js +1 -1
  45. package/src/data-display/typography/template.js +1 -1
  46. package/src/data-display/typography/typography.stories.js +1 -1
  47. package/src/examples/dashboard/dashboard.stories.js +1 -1
  48. package/src/feedback/alert/alert.stories.js +1 -1
  49. package/src/feedback/alert/template.js +1 -1
  50. package/src/feedback/backdrop/backdrop.stories.js +1 -1
  51. package/src/feedback/dialog/dialog.stories.js +1 -1
  52. package/src/feedback/progress/progress.stories.js +1 -1
  53. package/src/feedback/skeleton/skeleton.stories.js +1 -1
  54. package/src/feedback/snackbar/snackbar.stories.js +1 -1
  55. package/src/layout/container/container.stories.js +1 -1
  56. package/src/layout/container/template.js +1 -1
  57. package/src/layout/flex/flex.stories.js +1 -1
  58. package/src/layout/flex/template.js +1 -1
  59. package/src/layout/grid/grid.stories.js +1 -1
  60. package/src/navigation/bottom-navigation/bottom-navigation.stories.js +1 -1
  61. package/src/navigation/bottom-navigation/template.js +1 -1
  62. package/src/navigation/breadcrumbs/breadcrumbs.stories.js +1 -1
  63. package/src/navigation/breadcrumbs/template.js +1 -1
  64. package/src/navigation/drawer/drawer.stories.js +1 -1
  65. package/src/navigation/link/link.stories.js +1 -1
  66. package/src/navigation/link/template.js +1 -1
  67. package/src/navigation/menu/menu.stories.js +1 -1
  68. package/src/navigation/menu/template.js +1 -1
  69. package/src/navigation/pagination/pagination.stories.js +1 -1
  70. package/src/navigation/speed-dial/speed-dial.stories.js +1 -1
  71. package/src/navigation/stepper/stepper.stories.js +1 -1
  72. package/src/navigation/tabs/tabs.stories.js +1 -1
  73. package/src/shared/fallback-label.js +18 -0
  74. package/src/surfaces/accordion/accordion.stories.js +1 -1
  75. package/src/surfaces/accordion/template.js +1 -1
  76. package/src/surfaces/app-bar/app-bar.stories.js +1 -1
  77. package/src/surfaces/app-bar/template.js +1 -1
  78. package/src/surfaces/card/card.stories.js +1 -1
  79. package/src/surfaces/card/template.js +1 -1
  80. package/src/surfaces/paper/paper.stories.js +1 -1
  81. package/src/surfaces/paper/template.js +1 -1
  82. /package/src/shared/{applyElementProps.js → apply-element-props.js} +0 -0
  83. /package/src/stories/{notifyStory.js → notify-story.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inglorious/ui",
3
- "version": "8.3.1",
3
+ "version": "8.4.0",
4
4
  "description": "A design system for Inglorious Web with render-function components and customizable themes",
5
5
  "author": "Matteo Antony Mistretta <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
6
  "license": "MIT",
@@ -308,19 +308,19 @@
308
308
  "peerDependencies": {
309
309
  "@inglorious/store": "11.3.0",
310
310
  "@inglorious/utils": "5.0.0",
311
- "@inglorious/web": "6.7.2"
311
+ "@inglorious/web": "6.8.0"
312
312
  },
313
313
  "devDependencies": {
314
314
  "@iconify-icons/fa7-brands": "^2.0.0",
315
315
  "@iconify-icons/fa7-regular": "^2.0.0",
316
316
  "@iconify-icons/fa7-solid": "^2.0.0",
317
317
  "@iconify-icons/material-symbols": "^2.0.6",
318
- "@inglorious/charts": "11.1.4",
318
+ "@inglorious/charts": "11.1.5",
319
319
  "@inglorious/eslint-config": "1.1.4",
320
320
  "@inglorious/store": "11.3.0",
321
321
  "@inglorious/vite-plugin-jsx": "2.0.4",
322
322
  "@inglorious/vite-plugin-vue": "1.0.5",
323
- "@inglorious/web": "6.7.2",
323
+ "@inglorious/web": "6.8.0",
324
324
  "@storybook/addon-docs": "^10.6.0",
325
325
  "@storybook/web-components-vite": "^10.6.0",
326
326
  "happy-dom": "^20.14.0",
@@ -1,6 +1,6 @@
1
1
  import { html } from "@inglorious/web"
2
2
 
3
- import { createRender } from "../../stories/notifyStory.js"
3
+ import { createRender } from "../../stories/notify-story.js"
4
4
  import { Button } from "."
5
5
 
6
6
  export default {
@@ -7,7 +7,7 @@ import { html } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
11
 
12
12
  /**
13
13
  * Renders a themed button for actions and form submission.
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { ButtonGroup } from "."
3
3
 
4
4
  export default {
@@ -7,7 +7,7 @@ import { html } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
11
  import { Button } from "../button/index.js"
12
12
 
13
13
  /**
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Checkbox } from "."
3
3
 
4
4
  export default {
@@ -7,7 +7,7 @@
7
7
  color: var(--iw-color-text);
8
8
  cursor: pointer;
9
9
 
10
- .iw-checkbox {
10
+ .iw-checkbox-input {
11
11
  width: 1rem;
12
12
  height: 1rem;
13
13
  margin: 0;
@@ -3,11 +3,11 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
11
 
12
12
  /**
13
13
  * Renders a labeled checkbox for boolean input.
@@ -30,6 +30,8 @@ export function render(props) {
30
30
  ...rest
31
31
  } = props
32
32
 
33
+ // The label wraps the input, which is what ties the two together: it needs no
34
+ // `for`, and an empty one would point at nothing and break the click-through.
33
35
  const inputId = id || name
34
36
 
35
37
  const classes = {
@@ -40,10 +42,10 @@ export function render(props) {
40
42
  }
41
43
 
42
44
  return html`
43
- <label class=${classMap(classes)} for=${inputId}>
45
+ <label class=${classMap(classes)}>
44
46
  <input
45
- id=${inputId}
46
- class="iw-checkbox"
47
+ id=${inputId || nothing}
48
+ class="iw-checkbox-input"
47
49
  type="checkbox"
48
50
  name=${name}
49
51
  .checked=${isChecked}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createEntityRender,
3
3
  notifyActionArgType,
4
- } from "../../stories/notifyStory.js"
4
+ } from "../../stories/notify-story.js"
5
5
  import { Combobox } from "./index.js"
6
6
 
7
7
  const options = [
@@ -4,13 +4,14 @@
4
4
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
5
5
  */
6
6
 
7
- import { html } from "@inglorious/web"
7
+ import { html, nothing } from "@inglorious/web"
8
8
  import { classMap } from "@inglorious/web/directives/class-map"
9
9
  import { ref } from "@inglorious/web/directives/ref"
10
10
  import { repeat } from "@inglorious/web/directives/repeat"
11
11
  import { when } from "@inglorious/web/directives/when"
12
12
 
13
13
  import { Chip } from "../../data-display/chip/index.js"
14
+ import { fallbackLabel } from "../../shared/fallback-label.js"
14
15
  import {
15
16
  filterOptions,
16
17
  formatOption,
@@ -66,7 +67,7 @@ export const Combobox = {
66
67
  ${when(
67
68
  label,
68
69
  () =>
69
- html`<label id=${labelId || ""} class="iw-combobox-label">
70
+ html`<label id=${labelId || nothing} class="iw-combobox-label">
70
71
  ${label}
71
72
  ${when(
72
73
  isRequired,
@@ -79,14 +80,16 @@ export const Combobox = {
79
80
  ${when(
80
81
  error,
81
82
  () =>
82
- html`<span id=${messageId ?? ""} class="iw-combobox-error-message"
83
+ html`<span
84
+ id=${messageId || nothing}
85
+ class="iw-combobox-error-message"
83
86
  >${error}</span
84
87
  >`,
85
88
  )}
86
89
  ${when(
87
90
  !error && hint,
88
91
  () =>
89
- html`<span id=${messageId || ""} class="iw-combobox-hint"
92
+ html`<span id=${messageId || nothing} class="iw-combobox-hint"
90
93
  >${hint}</span
91
94
  >`,
92
95
  )}
@@ -107,6 +110,7 @@ export const Combobox = {
107
110
  renderControl(props) {
108
111
  const {
109
112
  id,
113
+ label,
110
114
  labelId,
111
115
  messageId,
112
116
  selectedValue,
@@ -134,14 +138,15 @@ export const Combobox = {
134
138
  }
135
139
 
136
140
  return html`<div
137
- id=${controlId}
141
+ id=${controlId || nothing}
138
142
  class="${classMap(frameClasses)}"
139
143
  role="combobox"
140
144
  aria-haspopup="listbox"
141
145
  aria-expanded=${isOpen ? "true" : "false"}
142
- aria-controls=${controlId ? `${controlId}-listbox` : ""}
143
- aria-labelledby=${labelId || ""}
144
- aria-describedby=${messageId || ""}
146
+ aria-controls=${controlId ? `${controlId}-listbox` : nothing}
147
+ aria-labelledby=${labelId || nothing}
148
+ aria-label=${fallbackLabel(labelId, label)}
149
+ aria-describedby=${messageId || nothing}
145
150
  aria-required=${isRequired ? "true" : "false"}
146
151
  aria-invalid=${error ? "true" : "false"}
147
152
  tabindex=${isDisabled ? -1 : 0}
@@ -235,7 +240,7 @@ export const Combobox = {
235
240
  const { id, options, size, onOptionSelect, onChange } = props
236
241
 
237
242
  const option = options.find((opt) => getOptionValue(opt) === value)
238
- const tagId = `${id}-tag-${String(value)}`
243
+ const tagId = id ? `${id}-tag-${String(value)}` : undefined
239
244
  const chipSize = size === "lg" ? "md" : "sm"
240
245
 
241
246
  return html`<span
@@ -268,7 +273,7 @@ export const Combobox = {
268
273
  const filteredOptions = filterOptions(options, searchTerm)
269
274
 
270
275
  return html`<div
271
- id=${id ? `${id}-control-listbox` : ""}
276
+ id=${id ? `${id}-control-listbox` : nothing}
272
277
  class="iw-combobox-dropdown"
273
278
  role="listbox"
274
279
  ${ref((el) => trackOutsideClick(props, el))}
@@ -354,7 +359,7 @@ export const Combobox = {
354
359
  const isFocused = index === focusedIndex
355
360
 
356
361
  return html`<div
357
- id=${id ? `${id}-option-${index}` : ""}
362
+ id=${id ? `${id}-option-${index}` : nothing}
358
363
  role="option"
359
364
  aria-selected=${isSelected ? "true" : "false"}
360
365
  class="iw-combobox-dropdown-options-option ${classMap({
@@ -1,7 +1,7 @@
1
1
  import { html } from "@inglorious/web"
2
2
 
3
3
  import { Icon } from "../../data-display/icon"
4
- import { createRender } from "../../stories/notifyStory.js"
4
+ import { createRender } from "../../stories/notify-story.js"
5
5
  import { Fab } from "."
6
6
 
7
7
  export default {
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { FileUpload } from "./index.js"
3
3
 
4
4
  export default {
@@ -3,11 +3,12 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
+ import { fallbackLabel } from "../../shared/fallback-label.js"
11
12
 
12
13
  /**
13
14
  * Renders a labeled file upload area with optional summary, hint, and error text.
@@ -36,7 +37,8 @@ export function render(props) {
36
37
  ...rest
37
38
  } = props
38
39
 
39
- const uploadId = id || name || "file-upload"
40
+ const uploadId = id || name
41
+ const messageId = (error || hint) && id ? `${id}-message` : ""
40
42
 
41
43
  const wrapperClasses = {
42
44
  "iw-upload": true,
@@ -58,7 +60,7 @@ export function render(props) {
58
60
  ${
59
61
  label
60
62
  ? html`
61
- <label for=${uploadId} class="iw-upload-label">
63
+ <label for=${uploadId || nothing} class="iw-upload-label">
62
64
  ${label}
63
65
  ${
64
66
  isRequired
@@ -72,8 +74,11 @@ export function render(props) {
72
74
 
73
75
  <div class=${classMap(fieldClasses)}>
74
76
  <input
75
- id=${uploadId}
77
+ id=${uploadId || nothing}
76
78
  name=${name}
79
+ aria-label=${fallbackLabel(uploadId, label)}
80
+ aria-describedby=${messageId || nothing}
81
+ aria-invalid=${error ? "true" : "false"}
77
82
  type="file"
78
83
  accept=${accept ?? ""}
79
84
  ?multiple=${isMultiple}
@@ -96,9 +101,15 @@ export function render(props) {
96
101
 
97
102
  ${
98
103
  error
99
- ? html`<span class="iw-upload-error-message">${error}</span>`
104
+ ? html`<span
105
+ id=${messageId || nothing}
106
+ class="iw-upload-error-message"
107
+ >${error}</span
108
+ >`
100
109
  : hint
101
- ? html`<span class="iw-upload-hint">${hint}</span>`
110
+ ? html`<span id=${messageId || nothing} class="iw-upload-hint"
111
+ >${hint}</span
112
+ >`
102
113
  : null
103
114
  }
104
115
  </div>
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { IconButton } from "."
3
3
 
4
4
  export default {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createEntityRender,
3
3
  notifyActionArgType,
4
- } from "../../stories/notifyStory.js"
4
+ } from "../../stories/notify-story.js"
5
5
  import { ImageCropper } from "./index.js"
6
6
 
7
7
  export default {
@@ -1,6 +1,6 @@
1
1
  import { html } from "@inglorious/web"
2
2
 
3
- import { createRender } from "../../stories/notifyStory.js"
3
+ import { createRender } from "../../stories/notify-story.js"
4
4
  import { Input } from "."
5
5
 
6
6
  const nativeInputTypes = [
@@ -3,20 +3,21 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
  import { when } from "@inglorious/web/directives/when"
10
10
 
11
11
  import { Icon } from "../../data-display/icon/index.js"
12
- import { applyElementProps } from "../../shared/applyElementProps.js"
12
+ import { applyElementProps } from "../../shared/apply-element-props.js"
13
+ import { fallbackLabel } from "../../shared/fallback-label.js"
13
14
 
14
15
  /**
15
16
  * Renders a labeled input field with optional icons, hint text, and error messaging.
16
17
  * Supports disabled/readonly/required states and emits `onChange` on input.
17
18
  * @example
18
19
  * // Stateless usage
19
- * input.render({ label: 'Email', type: 'email', placeholder: 'you@example.com' })
20
+ * input.render({ label: 'Email', inputType: 'email', placeholder: 'you@example.com' })
20
21
  *
21
22
  * @param {InputProps} props
22
23
  * @returns {TemplateResult}
@@ -58,7 +59,7 @@ export const Input = {
58
59
  ${when(
59
60
  label,
60
61
  () => html`
61
- <label for=${controlId} class="iw-input-label">
62
+ <label for=${controlId || nothing} class="iw-input-label">
62
63
  ${label}
63
64
  ${when(
64
65
  isRequired,
@@ -67,18 +68,18 @@ export const Input = {
67
68
  </label>
68
69
  `,
69
70
  )}
70
- ${this.renderControl?.(props)}
71
+ ${this.renderControl?.({ ...props, messageId })}
71
72
  ${when(
72
73
  error,
73
74
  () =>
74
- html`<span id=${messageId || ""} class="iw-input-error-message"
75
+ html`<span id=${messageId || nothing} class="iw-input-error-message"
75
76
  >${error}</span
76
77
  >`,
77
78
  )}
78
79
  ${when(
79
80
  !error && hint,
80
81
  () =>
81
- html`<span id=${messageId || ""} class="iw-input-hint"
82
+ html`<span id=${messageId || nothing} class="iw-input-hint"
82
83
  >${hint}</span
83
84
  >`,
84
85
  )}
@@ -91,6 +92,9 @@ export const Input = {
91
92
  id,
92
93
  type, // eslint-disable-line no-unused-vars
93
94
  name = "",
95
+ label,
96
+ hint, // eslint-disable-line no-unused-vars
97
+ messageId,
94
98
  inputType = "text",
95
99
  value = "",
96
100
  placeholder = "",
@@ -99,6 +103,7 @@ export const Input = {
99
103
  isDisabled = false,
100
104
  isReadOnly = false,
101
105
  isRequired = false,
106
+ isFullWidth, // eslint-disable-line no-unused-vars
102
107
  icon,
103
108
  iconAfter,
104
109
  onChange,
@@ -121,9 +126,12 @@ export const Input = {
121
126
  ${when(icon, () => Icon.render({ children: icon, color: "var(--iw-color-text-muted)", size }))}
122
127
 
123
128
  <input
124
- id=${controlId}
129
+ id=${controlId || nothing}
125
130
  name=${name}
126
131
  type=${inputType}
132
+ aria-label=${fallbackLabel(controlId, label)}
133
+ aria-describedby=${messageId || nothing}
134
+ aria-invalid=${error ? "true" : "false"}
127
135
  .value=${value}
128
136
  placeholder=${placeholder}
129
137
  ?disabled=${isDisabled}
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { RadioGroup } from "."
3
3
 
4
4
  export default {
@@ -3,11 +3,11 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
11
 
12
12
  /**
13
13
  * Renders a group of radio options for single selection.
@@ -30,7 +30,9 @@ export function render(props) {
30
30
  ...rest
31
31
  } = props
32
32
 
33
- const inputId = id || name
33
+ // Radios are a group by sharing a name: without one, checking an option does not
34
+ // uncheck the others and the arrow keys do not move between them.
35
+ const groupName = name || id
34
36
 
35
37
  const rootClasses = {
36
38
  "iw-radio-group": true,
@@ -50,7 +52,7 @@ export function render(props) {
50
52
  ? html`<legend class="iw-radio-group-label">${label}</legend>`
51
53
  : null
52
54
  }
53
- ${options.map((option) => {
55
+ ${options.map((option, index) => {
54
56
  const {
55
57
  label: optionLabel,
56
58
  value: optionValue,
@@ -61,10 +63,10 @@ export function render(props) {
61
63
  return html`
62
64
  <label class="iw-radio-option">
63
65
  <input
64
- id=${inputId}
66
+ id=${groupName ? `${groupName}-${index}` : nothing}
65
67
  class="iw-radio"
66
68
  type="radio"
67
- name=${name}
69
+ name=${groupName || nothing}
68
70
  value=${optionValue}
69
71
  .checked=${value === optionValue}
70
72
  ?disabled=${isDisabled || optionDisabled}
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Rating } from "."
3
3
 
4
4
  export default {
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Select } from "."
3
3
 
4
4
  export default {
@@ -3,14 +3,13 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
- import { ref } from "@inglorious/web/directives/ref"
9
8
  import { repeat } from "@inglorious/web/directives/repeat"
10
9
  import { when } from "@inglorious/web/directives/when"
11
10
 
12
11
  import { Icon } from "../../data-display/icon/index.js"
13
- import { applyElementProps } from "../../shared/applyElementProps.js"
12
+ import { fallbackLabel } from "../../shared/fallback-label.js"
14
13
  import { formatOption, getOptionValue, isOptionSelected } from "./helpers.js"
15
14
 
16
15
  /**
@@ -73,7 +72,6 @@ export const Select = {
73
72
  isFullWidth = false,
74
73
  } = props
75
74
 
76
- const labelId = label && id ? `${id}-label` : ""
77
75
  const messageId = (error || hint) && id ? `${id}-message` : ""
78
76
 
79
77
  const selectClasses = {
@@ -86,7 +84,7 @@ export const Select = {
86
84
  ${when(
87
85
  label,
88
86
  () => html`
89
- <label for=${id || name || ""} class="iw-select-label">
87
+ <label for=${id || name || nothing} class="iw-select-label">
90
88
  ${label}
91
89
  ${
92
90
  isRequired
@@ -96,18 +94,20 @@ export const Select = {
96
94
  </label>
97
95
  `,
98
96
  )}
99
- ${this.renderControl?.({ ...props, labelId, messageId })}
97
+ ${this.renderControl?.({ ...props, messageId })}
100
98
  ${when(
101
99
  error,
102
100
  () =>
103
- html`<span id=${messageId || ""} class="iw-select-error-message"
101
+ html`<span
102
+ id=${messageId || nothing}
103
+ class="iw-select-error-message"
104
104
  >${error}</span
105
105
  >`,
106
106
  )}
107
107
  ${when(
108
108
  !error && hint,
109
109
  () =>
110
- html`<span id=${messageId || ""} class="iw-select-hint"
110
+ html`<span id=${messageId || nothing} class="iw-select-hint"
111
111
  >${hint}</span
112
112
  >`,
113
113
  )}
@@ -119,6 +119,8 @@ export const Select = {
119
119
  const {
120
120
  id,
121
121
  name,
122
+ label,
123
+ messageId,
122
124
  options,
123
125
  value,
124
126
  error,
@@ -152,8 +154,11 @@ export const Select = {
152
154
  ${icon ? Icon.render({ children: icon, size }) : null}
153
155
 
154
156
  <select
155
- id=${controlId}
157
+ id=${controlId || nothing}
156
158
  name=${name}
159
+ aria-label=${ariaLabel || fallbackLabel(controlId, label)}
160
+ aria-describedby=${messageId || nothing}
161
+ aria-invalid=${error ? "true" : "false"}
157
162
  ?multiple=${isMulti}
158
163
  ?disabled=${isDisabled}
159
164
  ?required=${isRequired}
@@ -161,9 +166,6 @@ export const Select = {
161
166
  @change=${(event) => onChange?.(event.target.value)}
162
167
  @blur=${onBlur}
163
168
  @focus=${onFocus}
164
- ${ref((element) =>
165
- applyElementProps(element, { "aria-label": ariaLabel || null }),
166
- )}
167
169
  >
168
170
  ${repeat(
169
171
  options,
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Slider } from "."
3
3
 
4
4
  export default {
@@ -3,11 +3,12 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
+ import { fallbackLabel } from "../../shared/fallback-label.js"
11
12
 
12
13
  const DEFAULT_VALUE = 0
13
14
  const DEFAULT_MIN = 0
@@ -53,7 +54,7 @@ export function render(props) {
53
54
  html`<div class="iw-slider-header">
54
55
  ${
55
56
  label
56
- ? html`<label for=${inputId}>${label}</label>`
57
+ ? html`<label for=${inputId || nothing}>${label}</label>`
57
58
  : html`<span></span>`
58
59
  }
59
60
  ${
@@ -64,8 +65,9 @@ export function render(props) {
64
65
  </div>`
65
66
  }
66
67
  <input
67
- id=${inputId}
68
+ id=${inputId || nothing}
68
69
  class="iw-slider-input"
70
+ aria-label=${fallbackLabel(inputId, label)}
69
71
  type="range"
70
72
  name=${name}
71
73
  min=${min}
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Switch } from "."
3
3
 
4
4
  export default {