Skip to content

fix: Adjust spacings in token mode autosuggest - #5207

Open
jperals wants to merge 11 commits into
mainfrom
dev-v3-jotresse-autosuggest-consistent-spacing
Open

jperals wants to merge 11 commits into
mainfrom
dev-v3-jotresse-autosuggest-consistent-spacing

Conversation

@jperals

@jperals jperals commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Description

Internal spacings in autosuggest differ a bit depending on whether token mode is used or not:

No token mode (live example)
Screenshot 2026-11-02 at 12 23 32

Token mode (wider spacings, see live example)
Screenshot 2026-11-02 at 12 23 49

This PR addresses this by removing duplication. Since #5126, the input always render a wrapper div around the native input; we can take advantage of this and create a new internal slot in the internal input component where we pass the inline tokens instead of rendering them in autosuggest-input. This way, the internal input's styles are reused naturally.

How has this been tested?

Existing visual regression tests fail as expected.

Review checklist

The following items are to be evaluated by the author(s) and the reviewer(s).

Correctness

  • Changes include appropriate documentation updates.
  • Changes are backward-compatible if not indicated, see CONTRIBUTING.md.
  • Changes do not include unsupported browser features, see CONTRIBUTING.md.
  • Changes were manually tested for accessibility, see accessibility guidelines.

Security

Testing

  • Changes are covered with new/existing unit tests?
  • Changes are covered with new/existing integration tests?

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@codecov

codecov Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.76%. Comparing base (c8ca653) to head (d44fe7a).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5207      +/-   ##
==========================================
- Coverage   97.76%   97.76%   -0.01%     
==========================================
  Files        1003     1003              
  Lines       32572    32552      -20     
  Branches    12110    12091      -19     
==========================================
- Hits        31843    31823      -20     
- Misses        684      723      +39     
+ Partials       45        6      -39     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI 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.

🟡 Changes recommended

The observer discards zero-width measurements, causing tokens to collapse while the field is hidden and preventing recalculation when it is restored at the same width.

1 open issue
What changed in this PR

This PR adjusts token-mode autosuggest spacing by rendering tokens inside the shared input field instead of a separate field wrapper.

Changes:

  • Reuses shared input styling and adds an internal inline-content slot.
  • Calculates token overflow from the combined token and input widths.
  • Updates spacing, popover clipping, and overflow test fixtures.
File Description
src/​internal/​components/​autosuggest-input/​use-token-overflow.ts Uses token and input measurements to calculate overflow.
src/​internal/​components/​autosuggest-input/​styles.scss Removes separate field styles and adjusts token layout.
src/​internal/​components/​autosuggest-input/​inline-tokens.tsx Exposes the token root for measurement.
src/​internal/​components/​autosuggest-input/​index.tsx Renders tokens through the shared input component.
src/​internal/​components/​autosuggest-input/​__tests__/​use-token-overflow.test.tsx Updates geometry mocks and overflow checks.
src/​input/​styles.scss Adds inline-content spacing and allows popovers outside the field.
src/​input/​internal.tsx Adds an internal inline-content slot and removes borderless mode.
src/​autosuggest/​__tests__/​autosuggest-token-mode.test.tsx Updates the overflow hook mock.

Review effort: Balanced

'aria-owns': open ? ariaControls : undefined,
'aria-label': ariaLabel,
'aria-activedescendant': ariaActivedescendant,
...(isTokenMode && formFieldContext.invalid ? { 'aria-invalid': 'true' as const } : {}),

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

invalid attributes are now handled by the internal input by passing it the formFieldContext here

Copilot AI 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.

🔵 Needs a closer look

Active issues leave a measurement-only button exposed to screen readers in empty token mode and allow stale focus-suppression state to block suggestions and onFocus when the input is refocused.

No open issues 🎉

2 previously missed issues

In code that hasn't changed since last review

Medium severity Stale focus suppression blocks suggestions after returning from token

src/​internal/​components/​autosuggest-input/​index.tsx:469

Nesting tokens inside the dropdown trigger changes its focus boundary: InternalDropdown skips onFocus for token/input transitions, but entering a token still sets preventOpenOnFocusRef. Focus the input, move to a token, return to the input, then leave and refocus the input: the stale flag suppresses both suggestions and onFocus on re-entry. Please update the focus-suppression bookkeeping for the new hierarchy and cover this sequence with a regression test.

Medium severity Empty token mode leaves measurement button accessible

src/​internal/​components/​autosuggest-input/​use-token-overflow.ts:40

When mounted with tokens={[]}, InlineTokens is not rendered, so tokensRef.current is null and this returns before making the measurement container inert. That container still contains the +0 measurement button, whose styles-reset overrides the ancestor's visibility: hidden; clipping it does not remove it from the accessibility tree. Set inert before this readiness guard so screen readers do not encounter a measurement-only button in empty token mode.

1 resolved since last review

Review effort: Balanced


it('warns about overriding autosuggest-specific attributes', () => {
renderAutosuggest(<Autosuggest {...defaultProps} nativeInputAttributes={{ 'aria-autocomplete': 'both' }} />);
expect(warnOnce).toHaveBeenCalledTimes(1);

@jperals jperals Nov 2, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The warning will now be issued twice in the tests because widths are always 0 in jsdom environments (see this comment for more context), so the behavior here differs from real user experience and this assertion is not very valuable. warnOnce would deduplicate the warning anyway, so real users get only one warning in any case.

const [triggerWidth, setTriggerWidth] = useState<number | null>(null);
useResizeObserver(
() => (isTokenMode ? fieldRef.current : inputContainerRef.current),
entry => entry.borderBoxWidth > 0 && setTriggerWidth(entry.borderBoxWidth)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

When measuring the width for the purpose of setting the layout for inline tokens, keeping the width even if they are 0 is more robust (for the edge case that the tokens change while the component is hidden). I researched why the > 0 condition exists and I think it was just to satisfy unit tests, where one more render than expected was triggered because dimensions are 0 in the jsdom environment.

In a real environment, the trigger being 0 can only happen if it is hidden. This should not happen while the dropdown is being rendered, and even if it did, the dropdown width would collapse to its own width, not to 0.

Copilot AI 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.

🟢 Approval recommended

No active review issues remain for the Autosuggest spacing and token-overflow changes.

No open issues 🎉

Review effort: Balanced

This branch was successfully deployed

3 active deployments
dev-pages-react18 — d44fe7ae Deployed Nov 2, 2026 by jperals via deploy (React 18) / deploy #3105
dev-pages-react16 — d44fe7ae Deployed Nov 2, 2026 by jperals via deploy (React 16) / deploy #3105
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