Skip to content

feat(app-ui): LinkButton, linkProps, ref forwarding; accessible Tag and Max - #875

Merged
cakeinpanic merged 2 commits into
mainfrom
fix/app-ui-review-4-links-buttons
Oct 30, 2026
Merged

cakeinpanic merged 2 commits into
mainfrom
fix/app-ui-review-4-links-buttons

Conversation

@exromany

@exromany exromany commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Links and actions: one place for external/disabled link logic, a new LinkButton, linkProps, ref forwarding, and an accessible Tag and RichInput Max.

What / why

  • Anchor (S-14): the internal Anchor owns external and disabled for TextLink, NavLink and ActionElement. SmallCard, Logo and BreadcrumbItem gain external. Why: the copies had drifted, and a consumer tabIndex could override disabled.
  • Disabled links (K-6, K-7): render role="link" aria-disabled="true" with no tabindex. Why: they were role-less <a tabindex=-1> that a click could still focus.
  • download={false} (K-8): goes through LinkProvider again. Why: it caused a full page reload.
  • TextLink (C-9): size='inherit' flows and wraps with running text, because it forced 14px inline-flex.
  • LinkButton (K-2): a Button-styled routed <a> for navigation CTAs, which until now had to be <button>s.
  • linkProps (K-3): typed per-link router options (prefetch, replace…) through LinkRouterProps augmentation.
  • Ref forwarding (K-4): TextLink, SmallCard, Tag and Counter forward ref, so they can anchor a Popover.
  • Tag (E-1): with onClick it is a keyboard-operable role=button span, as='button' gives a native button, href a routed link and disabled a disabled button. Why: a clickable Tag had no role, focus or keyboard support. With onClose it stays passive, and Remove no longer fires onClick.
  • RichInput Max (E-1): a native <button> that doesn't refocus the input, so the mobile keyboard no longer pops up.
  • Counter slot (E-2, E-6): counter={3} renders a Counter pill, and counterLabel is announced with the button name. Why: raw numbers rendered unstyled, and count && … leaked a 0.
  • Button / IconButton states (E-4, E-9, E-12):
    • One disabled/loading rule that also covers aria-disabled.
    • cursor: wait while loading.
    • The disabled IconButton icon is dimmed.
    • surface has a pressed state.
  • Typography: new font-description-semibold mixin (E-11).

Watch for

  • counter={0} now shows a "0" pill, so use count || null to hide it.
  • Tag onClick is MouseEventHandler<HTMLElement>, and RichInput onMaxClick is MouseEventHandler<HTMLButtonElement>.
  • The forwardRef components' ComponentProps now include ref.
  • This collides with feat/app-ui-hex in Button.module.css: keep hex's values and these aria-disabled selectors.

Screenshots (Storybook)

C-9: At 375px a size='inherit' link wraps with the paragraph.

after

K-2: LinkButton variants, including the disabled state.

after

E-1: One Tab reaches the clickable Tag and shows its focus ring. Before, it was skipped.

Before

before

After

after

E-4, E-9, E-12: Disabled IconButton icons are dimmed now.

Before

before

After

after

Stack 5/7.

@exromany
exromany requested a review from a team as a code owner October 25, 2026 18:50
@exromany
exromany added this pull request to stack #879 October 25, 2026 19:57
@preview-stands

preview-stands Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Preview stand status

Stand was demolished

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

When onMaxClick is omitted, Max renders as a passive span, losing keyboard access and allowing clicks to focus the input and reopen the mobile keyboard.

1 open issue
What changed in this PR

This PR expands lido-app-ui navigation and action components with shared link handling, a new LinkButton, ref forwarding, and accessibility improvements.

Changes:

  • Centralizes external and disabled link behavior and adds typed router options.
  • Improves Tag and Max controls, counter announcements, and button states.
  • Adds regression tests and updates Storybook examples and shared typography.
File Description
packages/​lido-app-ui/​styles/​typography-mixins.css Adds semibold description typography.
packages/​lido-app-ui/​src/​utils/​ActionElement.tsx Delegates link behavior to Anchor.
packages/​lido-app-ui/​src/​utils/​ActionElement.test.tsx Tests routing, disabled behavior, and refs.
packages/​lido-app-ui/​src/​utils/​ActionElement.stories.tsx Simplifies story configuration.
packages/​lido-app-ui/​src/​text-link/​TextLink.tsx Adds ref forwarding and inherited sizing.
packages/​lido-app-ui/​src/​text-link/​TextLink.test.tsx Tests sizing and centralized link behavior.
packages/​lido-app-ui/​src/​text-link/​TextLink.stories.tsx Adds an inline wrapping example.
packages/​lido-app-ui/​src/​text-link/​TextLink.module.css Supports inherited typography and wrapping.
packages/​lido-app-ui/​src/​text-link/​index.ts Exports TextLinkSize.
packages/​lido-app-ui/​src/​tag/​Tag.tsx Adds keyboard interaction, native actions, and refs.
packages/​lido-app-ui/​src/​tag/​Tag.test.tsx Tests interactive and removable forms.
packages/​lido-app-ui/​src/​tag/​Tag.stories.tsx Updates interaction documentation.
packages/​lido-app-ui/​src/​tag/​Tag.module.css Adds focus and disabled styling.
packages/​lido-app-ui/​src/​smoke.test.tsx Adds LinkButton smoke coverage.
packages/​lido-app-ui/​src/​small-card/​SmallCard.tsx Adds refs, external links, and router options.
packages/​lido-app-ui/​src/​small-card/​SmallCard.test.tsx Tests external-link attributes.
packages/​lido-app-ui/​src/​small-card/​SmallCard.stories.tsx Demonstrates external links.
packages/​lido-app-ui/​src/​rich-input/​RichInput.tsx Replaces MaxTag with Tag’s button form.
packages/​lido-app-ui/​src/​rich-input/​RichInput.test.tsx Tests Max clicks, disabling, and focus.
packages/​lido-app-ui/​src/​rich-input/​RichInput.stories.tsx Simplifies story metadata.
packages/​lido-app-ui/​src/​rich-input/​RichInput.module.css Removes Max-specific and balance-error styles.
packages/​lido-app-ui/​src/​link-provider/​linkStubs.test-utils.tsx Shares router and external-link test adapters.
packages/​lido-app-ui/​src/​link-provider/​LinkProvider.tsx Adds augmentable router prop types.
packages/​lido-app-ui/​src/​link-provider/​LinkProvider.test.tsx Adds adapter typing coverage.
packages/​lido-app-ui/​src/​link-provider/​LinkProvider.stories.tsx Adds navigation and breadcrumb examples.
packages/​lido-app-ui/​src/​link-provider/​index.ts Exports LinkRouterProps.
packages/​lido-app-ui/​src/​link-provider/​Anchor.tsx Centralizes link state and router prop handling.
packages/​lido-app-ui/​src/​link-provider/​Anchor.test.tsx Covers disabled, external, download, and router options.
packages/​lido-app-ui/​src/​icon-button/​IconButton.tsx Adds counter labels to accessible names.
packages/​lido-app-ui/​src/​icon-button/​IconButton.test.tsx Tests numeric counters and announcements.
packages/​lido-app-ui/​src/​icon-button/​IconButton.stories.tsx Updates counter and state examples.
packages/​lido-app-ui/​src/​icon-button/​IconButton.module.css Adds pressed styling and disabled icon dimming.
packages/​lido-app-ui/​src/​counter/​CounterSlot.tsx Wraps scalar counts and adds spoken labels.
packages/​lido-app-ui/​src/​counter/​CounterSlot.module.css Adds offset fallbacks and hidden-label styling.
packages/​lido-app-ui/​src/​counter/​Counter.tsx Forwards refs to the counter span.
packages/​lido-app-ui/​src/​counter/​Counter.stories.tsx Simplifies story metadata.
packages/​lido-app-ui/​src/​counter/​Counter.module.css Uses shared typography and adjusts line height.
packages/​lido-app-ui/​src/​colors/​tokenReferences.test.ts Removes a private-token exemption.
packages/​lido-app-ui/​src/​button/​types.ts Extracts shared button properties.
packages/​lido-app-ui/​src/​button/​LinkButton.tsx Adds button-styled routed links.
packages/​lido-app-ui/​src/​button/​LinkButton.test.tsx Tests routing, refs, disabling, and labels.
packages/​lido-app-ui/​src/​button/​index.ts Exports LinkButton and its props.
packages/​lido-app-ui/​src/​button/​ButtonContent.tsx Shares button content and counter labeling.
packages/​lido-app-ui/​src/​button/​Button.tsx Uses shared content and accessible counter labels.
packages/​lido-app-ui/​src/​button/​Button.test.tsx Expands loading and counter coverage.
packages/​lido-app-ui/​src/​button/​Button.stories.tsx Adds LinkButton examples.
packages/​lido-app-ui/​src/​button/​Button.module.css Unifies disabled states and supports link styling.

Review effort: Balanced

@cakeinpanic cakeinpanic 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.

please resolve copilot comments

@exromany
exromany force-pushed the fix/app-ui-review-4-links-buttons branch from a8815fb to abb03a0 Compare October 28, 2026 17:31
@exromany
exromany requested a review from cakeinpanic October 28, 2026 17:32
@exromany
exromany force-pushed the fix/app-ui-review-4-links-buttons branch from abb03a0 to b865f2b Compare October 28, 2026 20:28
@exromany
exromany force-pushed the fix/app-ui-review-4-links-buttons branch from b865f2b to cfd1390 Compare October 29, 2026 14:55
@cakeinpanic
cakeinpanic force-pushed the fix/app-ui-review-4-links-buttons branch 2 times, most recently from e261821 to 5f8f8ea Compare October 30, 2026 10:42
Base automatically changed from fix/app-ui-review-3-overlays to main October 30, 2026 10:43
@cakeinpanic
cakeinpanic force-pushed the fix/app-ui-review-4-links-buttons branch from 5f8f8ea to 6503b00 Compare October 30, 2026 10:43
…and Max accessible

- LinkButton and ButtonContent; Button, IconButton and Counter polish
- LinkProvider: linkProps for router-only options, forwardRef adapters, shared ActionElement
- TextLink, SmallCard, Tag (href), RichInput (Max button) a11y and ref forwarding
- typography mixin refinements
@exromany
exromany force-pushed the fix/app-ui-review-4-links-buttons branch from 6503b00 to ec009a3 Compare October 30, 2026 12:39
@cakeinpanic
cakeinpanic merged commit be5cd49 into main Oct 30, 2026
10 checks passed
@cakeinpanic
cakeinpanic deleted the fix/app-ui-review-4-links-buttons branch October 30, 2026 14:42
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.

3 participants