@iyulab/components 1.33.0 → 1.33.1

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
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.33.1] - 2026-08-25
4
+
5
+ ### Fixed
6
+
7
+ - **`aria-label` set on `<u-button>` never reached the accessibility tree.** The host
8
+ attribute was present, but the actual interactive node exposed to assistive technology is
9
+ the native `<button>`/`<a>` rendered inside the shadow root — ARIA content attributes on a
10
+ shadow host do not cross the shadow boundary to label a descendant. Icon-only buttons using
11
+ `aria-label` for their accessible name were announced as unnamed controls. `render()` now
12
+ forwards the host's `aria-label` onto the internal element, and attribute changes made after
13
+ connection are observed and re-rendered (previously only the initial value would have had
14
+ any chance of being picked up).
15
+
3
16
  ## [1.33.0] - 2026-08-21
4
17
 
5
18
  ### Added
@@ -93,6 +93,19 @@ export declare class UButton extends UElement {
93
93
  get form(): HTMLFormElement | null;
94
94
  connectedCallback(): void;
95
95
  disconnectedCallback(): void;
96
+ /**
97
+ * 호스트에 세팅된 `aria-label`은 실제 접근 가능한(포커스 대상) 엘리먼트가 아니라 —
98
+ * 그 안쪽 shadow DOM 의 네이티브 `<a>`/`<button>`이다. 섀도우 경계를 넘지 않으므로
99
+ * 접근성 트리에 자동 반영되지 않는다(docket #75 실측 — 속성은 붙어 있는데
100
+ * 접근성 이름이 비어 있음). `render()`가 이 값을 읽어 내부 엘리먼트에 직접 옮긴다.
101
+ *
102
+ * `aria-label`은 Lit 리액티브 프로퍼티로 선언돼 있지 않아 `observedAttributes`에
103
+ * 없다 — 그 목록에 없는 속성은 `attributeChangedCallback` 자체가 호출되지 않는다
104
+ * (커스텀 엘리먼트 표준 동작). 초기 렌더는 되지만 연결 후 동적 변경은 반영되지
105
+ * 않았다 — 목록에 명시적으로 추가해야 한다.
106
+ */
107
+ static get observedAttributes(): string[];
108
+ attributeChangedCallback(name: string, old: string | null, value: string | null): void;
96
109
  render(): TemplateResult<1>;
97
110
  private renderContent;
98
111
  private renderMask;
@@ -53,9 +53,29 @@ var UButton = class UButton extends UElement {
53
53
  this.removeEventListener("click", this.handleClick);
54
54
  super.disconnectedCallback();
55
55
  }
56
+ /**
57
+ * 호스트에 세팅된 `aria-label`은 실제 접근 가능한(포커스 대상) 엘리먼트가 아니라 —
58
+ * 그 안쪽 shadow DOM 의 네이티브 `<a>`/`<button>`이다. 섀도우 경계를 넘지 않으므로
59
+ * 접근성 트리에 자동 반영되지 않는다(docket #75 실측 — 속성은 붙어 있는데
60
+ * 접근성 이름이 비어 있음). `render()`가 이 값을 읽어 내부 엘리먼트에 직접 옮긴다.
61
+ *
62
+ * `aria-label`은 Lit 리액티브 프로퍼티로 선언돼 있지 않아 `observedAttributes`에
63
+ * 없다 — 그 목록에 없는 속성은 `attributeChangedCallback` 자체가 호출되지 않는다
64
+ * (커스텀 엘리먼트 표준 동작). 초기 렌더는 되지만 연결 후 동적 변경은 반영되지
65
+ * 않았다 — 목록에 명시적으로 추가해야 한다.
66
+ */
67
+ static get observedAttributes() {
68
+ return [...super.observedAttributes, "aria-label"];
69
+ }
70
+ attributeChangedCallback(name, old, value) {
71
+ super.attributeChangedCallback(name, old, value);
72
+ if (name === "aria-label") this.requestUpdate();
73
+ }
56
74
  render() {
75
+ const ariaLabel = this.getAttribute("aria-label") ?? void 0;
57
76
  if (this.href) return html`
58
77
  <a part="link"
78
+ aria-label=${ifDefined(ariaLabel)}
59
79
  ?disabled=${this.disabled || this.loading}
60
80
  tabindex=${this.disabled || this.loading ? -1 : 0}
61
81
  href=${ifDefined(this.disabled || this.loading ? void 0 : this.href)}
@@ -69,6 +89,7 @@ var UButton = class UButton extends UElement {
69
89
  `;
70
90
  return html`
71
91
  <button part="button"
92
+ aria-label=${ifDefined(ariaLabel)}
72
93
  type=${this.type}
73
94
  ?disabled=${this.disabled || this.loading}
74
95
  >
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@iyulab/components",
3
3
  "description": "web-components library based on lit-element made by iyulab",
4
- "version": "1.33.0",
4
+ "version": "1.33.1",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "components",
@@ -72,3 +72,20 @@ Versatile button with multiple visual variants. Renders as an `<a>` element when
72
72
  | `link` | Inner `<a>` element (when `href` is set) |
73
73
  | `content` | Content wrapper (prefix + label + suffix) |
74
74
  | `mask` | Loading overlay mask |
75
+
76
+ ## CSS Custom Properties
77
+
78
+ | Property | Description |
79
+ |----------|-------------|
80
+ | `--u-primary-color` | Base color when `color="neutral"` — set it and hover/active/surface tones auto-derive via `color-mix()` |
81
+ | `--btn-color` | The button's **fill** color. Every derived token below is `color-mix()`'d from this one — usually the only one you need to override |
82
+ | `--btn-txt-color` | Text color on the fill, read by `variant="solid"` (default `#fff`, or `--u-{role}-txt-color` when a semantic `color` is set) |
83
+ | `--btn-color-strong` | Text color on the surrounding page background, read by `variant="link"` — opposite contrast need from the fill, so it's a separate token (default: same as `--btn-color`, or `--u-{role}-color-strong` for a semantic `color`) |
84
+ | `--btn-color-hover` / `--btn-color-active` | `solid` background hover/active (default: `--btn-color` at 85%/70% + black) |
85
+ | `--btn-color-surface` / `-hover` / `-active` | `surface` background states (default: `--btn-color` at 12%/22%/32%) |
86
+ | `--btn-color-border` / `-hover` / `-active` | Border states (default: `--btn-color` at 45%/60%/75%) |
87
+ | `--btn-color-outline-hover` / `-active` | `outlined`/`ghost` background hover/active (default: 6%/12%) |
88
+ | `--btn-color-strong-hover` / `-active` | `link` text hover/active — the role value itself doesn't move; hover adds an underline instead (default: `--btn-color-strong` at 85%/70% + black) |
89
+ | `--btn-border-color` | Border color read by variant/hover/active rules (default: `transparent`) |
90
+ | `--btn-padding-block` | Vertical inner padding (default `0.5em`) |
91
+ | `--btn-padding-inline` | Horizontal inner padding (default `1em`, `0` for `variant="link"`) — overriding it does not change the min-height, which is derived from `--btn-padding-block` instead |
@@ -51,3 +51,10 @@ Content card with optional media, header, body, and footer sections.
51
51
  | `header` | Header slot wrapper |
52
52
  | `body` | Body (default slot) wrapper |
53
53
  | `footer` | Footer slot wrapper |
54
+
55
+ ## CSS Custom Properties
56
+
57
+ | Property | Description |
58
+ |----------|-------------|
59
+ | `--card-border-width` | Border thickness (`0` when `borderless`) |
60
+ | `--card-border-color` | Border color |
@@ -62,6 +62,12 @@ Side panel that slides in from any screen edge. Extends `UOverlayElement` (focus
62
62
  | `body` | Body area |
63
63
  | `close-btn` | Close button |
64
64
 
65
+ ## CSS Custom Properties
66
+
67
+ | Property | Description |
68
+ |----------|-------------|
69
+ | `--drawer-size` | Panel size along the slide axis — width for `placement="left"`/`"right"` (default `28rem`), height for `"top"`/`"bottom"` (default `16rem`). Auto-shrinks to `max-width`/`max-height: 100%` on narrow viewports |
70
+
65
71
  ---
66
72
 
67
73
  ## Edit-panel pattern
@@ -67,3 +67,10 @@ Radio group built from `u-option` children. Form-associated.
67
67
  |------|-------------|
68
68
  | `field` | Outer field wrapper |
69
69
  | `container` | Options container |
70
+
71
+ ## CSS Custom Properties
72
+
73
+ | Property | Description |
74
+ |----------|-------------|
75
+ | `--radio-color` | Base color of the selected state (default `--u-primary-color`) |
76
+ | `--radio-color-active` | Selected-state active tone (default `--radio-color` at 85% + black) |