Skip to content

refactor(ui5-input-icon): simplify public API and forward value state via CSS - #13873

Merged
MapTo0 merged 3 commits into
mainfrom
input-icon-fixes
Jul 28, 2026
Merged

refactor(ui5-input-icon): simplify public API and forward value state via CSS#13873
MapTo0 merged 3 commits into
mainfrom
input-icon-fixes

Conversation

@MapTo0

@MapTo0 MapTo0 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Simplifies the ui5-input-icon public API and switches value-state forwarding from imperative DOM mutation to pure CSS custom-property inheritance.

Public API changes on ui5-input-icon

Removes four public properties that either duplicated state owned by the parent ui5-input or were unnecessary opt-ins:

  • disabled — removed. The icon has no notion of parent state; consumers who want a non-interactive icon should not slot it.
  • readonly — removed. Same rationale as above.
  • showTooltip — removed. Tooltip is now always on when accessibleName is set (no opt-in flag).
  • valueState — removed as a JS property. Visual value-state styling is preserved via CSS inheritance (see below).

Also removes the private _parentDisabled flag. The icon now uses tabindex=\"-1\" so it stays out of the tab chain — the parent input is what the user tabs to, not each icon.

Value-state forwarding: setAttribute → CSS custom properties

Before: Parent Input walked every slotted icon in onBeforeRendering and called setAttribute(\"value-state\", …) on each. The icon's CSS then read that attribute via seven distinct :host([value-state=\"Negative\"]), […\"Critical\"], etc. selector blocks (~70 lines of duplication).

After: Parent Input publishes state-specific CSS custom properties on its own host via :host([value-state=\"Negative\"]) { --_ui5_input_icon_state_padding: …; --_ui5_input_icon_state_pressed_shadow: …; … }. Those custom properties inherit through the shadow boundary into every slotted ui5-input-icon's shadow root — no JS wiring needed. The icon's CSS collapses to a single set of rules reading var(--_ui5_input_icon_state_*, fallback).

Benefits:

  • Zero JS DOM mutation per render cycle (no more this.icon.forEach in onBeforeRendering).
  • Single source of truth: the parent Input's own value-state selectors also publish the derived icon vars.
  • No stale attributes on the icon in the DOM inspector.
  • ~70 lines of CSS duplication collapsed to ~20 lines.

Docs

Adds packages/website/docs/_components_pages/main/Input/InputIcon.mdx (modelled on SuggestionItem.mdx) so InputIcon appears as a related page under Input in the website sidebar. Docusaurus's autogenerated sidebar picks it up automatically.

Test coverage

The Cypress InputIcon Integration block in Input.cy.tsx now:

  • Retains the three unchanged tests (render, multiple icons + clear icon, click events).
  • Rewrites the value-state sync test to verify the CSS custom property inherits into the icon's shadow root, matching the new mechanism.

All 131 tests in Input.cy.tsx pass.

Verification

  • `yarn ts` — passes across the monorepo.
  • `yarn test:cypress:single cypress/specs/Input.cy.tsx` from `packages/main` — 131/131 passing, including all 4 InputIcon Integration tests.

… via CSS

- Remove `disabled`, `readonly`, `showTooltip`, and `valueState` public
  properties from `ui5-input-icon`. Also remove the private
  `_parentDisabled` flag — the icon has no notion of parent state.
- Tooltip is now always on when `accessibleName` is set (no opt-in flag).
- Icon uses `tabindex="-1"` so it stays out of the tab chain.
- Forward the parent Input's value state to slotted icons via inherited
  CSS custom properties instead of imperative `setAttribute` in
  `onBeforeRendering`. Parent Input's `:host([value-state="…"])`
  publishes `--_ui5_input_icon_state_*` custom properties that inherit
  through the shadow boundary into slotted icons — no JS DOM mutation
  per render, no stale attributes on the icon.
- Collapse InputIcon.css from seven state-specific selector blocks to a
  single set of rules reading the inherited custom properties, with
  fallbacks preserving the plain (no-value-state) appearance.
- Add `InputIcon.mdx` under Input's docs folder so it appears as a
  related page under Input in the website sidebar (auto-picked up by
  the autogenerated sidebar).
- Update Cypress test to verify value-state forwarding via inherited
  CSS custom properties rather than the removed attribute.
@MapTo0
MapTo0 temporarily deployed to netlify-preview July 28, 2026 12:23 — with GitHub Actions Inactive
@MapTo0
MapTo0 requested a review from ivoplashkov July 28, 2026 12:23
@github-actions

Copy link
Copy Markdown

👋 Heads-up: dev close is in effect

Thanks for the contribution! This repository is currently in dev close ahead of release 2.25 (scheduled 2026-07-29, UTC). See the release schedule for the full timeline.

This PR appears to introduce public-API changes (detected by diffing the Custom Elements Manifest against the latest published version on npm):

@ui5/webcomponents

  • ➕ added interface: IInputSuggestionItem
  • ➕ added element: InputIcon
  • ➕ added property: accessibleName
  • ➕ added property: name
  • ➕ added event: click
  • ➕ added attribute: accessible-name
  • ➕ added attribute: name
  • 🔄 changed attribute value-state (type)

Could you please hold off on merging into main until the release ships? Public-API changes are best landed in the next dev cycle so they don't slip into the release at the last minute. Once the release is out, this PR is good to go.

If this change must ship in the current release, please request a review from one or two members of @UI5/ui5-team-webc so the team can sign off explicitly.

💬 False positive? If you believe this PR doesn't actually change the public API (e.g. only internal refactoring, or an entry the detector mis-attributed), please reply on this thread — your feedback helps us improve the detection during this trial run.

Posted automatically by the Dev Close Notice workflow.

… CSS custom properties

Extend the same CSS-custom-property forwarding pattern used for value
state to the parent Input's disabled state:

- Parent Input publishes `--_ui5_input_icon_state_opacity`,
  `--_ui5_input_icon_state_pointer_events`, and
  `--_ui5_input_icon_state_cursor` on `:host([disabled])`.
- Icon reads them via `var(…, default)` — defaults preserve the plain
  interactive appearance. Native `pointer-events: none` blocks
  hover/active/click, so the icon's `:not(.inputIcon--disabled)` guards
  (dead selectors since the disabled property was removed) are also
  cleaned up.
- Adds a Cypress test verifying the vars actually inherit into a
  slotted icon when the parent input is disabled.
@MapTo0
MapTo0 temporarily deployed to netlify-preview July 28, 2026 12:28 — with GitHub Actions Inactive
@sap-ui5-webcomponents-release

Copy link
Copy Markdown

@ivoplashkov ivoplashkov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I would prefer if we trim the obvious comments from the code, or atleast make them shorter.
  2. Also when the input is readonly and has custom icon, the active state of the icon is still applied on hover. In UI5 in case of readonly input the icon get's removed from the input itself.

… CSS custom properties

Mirror the disabled forwarding pattern for readonly:

- Parent Input's `:host([readonly]:not([disabled]))` publishes
  `--_ui5_input_icon_state_pointer_events: none` and
  `--_ui5_input_icon_state_cursor: default`. No opacity change —
  readonly inputs stay readable, they don't dim.
- Interactive icons (search, voice, camera, …) become non-interactive
  alongside the input; the icon reads the inherited vars via the same
  `var(…, default)` pattern already in place.
- Cypress test asserts the vars actually inherit into a slotted icon
  when the parent is readonly, and that opacity is *not* forwarded.
@MapTo0
MapTo0 temporarily deployed to netlify-preview July 28, 2026 12:52 — with GitHub Actions Inactive
@MapTo0
MapTo0 merged commit 94f99cd into main Jul 28, 2026
34 of 37 checks passed
@MapTo0
MapTo0 deleted the input-icon-fixes branch July 28, 2026 14:31
@MapTo0
MapTo0 deployed to netlify-preview July 28, 2026 14:32 — with GitHub Actions Active
@sap-ui5-webcomponents-release

Copy link
Copy Markdown

🧹 Preview deployment cleaned up: https://pr-13873--ui5-webcomponents.netlify.app

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants