* docs(autocomplete): document Autocomplete.Value rendering in multiple mode
In multiple selection mode a bare Autocomplete.Value clones each selected
item's ListBox.Item children into the trigger, joined with locale-aware
separators, and calls render function children with isSelected: false.
This was undocumented, so decorative item content (checkboxes, avatars,
indicators) unexpectedly duplicates into the trigger.
Add a warning callout with the recommended selectedText pattern to the
Multiple Select section, and document the previously missing selectedText
render prop in the RenderProps table (en + cn).
* docs(autocomplete): refine multiple-mode Value caveat and render props table
---------
Co-authored-by: WK Wong <wingkwong.code@gmail.com>
* docs(spinner): demonstrate animation speed override in Global CSS example
* docs(spinner): document how to control animation speed with demos
---------
Co-authored-by: WK Wong <wingkwong.code@gmail.com>
* fix(styles): center table sortable column indicator icon (#6705)
* docs(web): polish component docs (#6690)
* docs(web): polish english component docs
* docs(web): polish custom style demos
* docs(web): polish chinese component docs
* docs(web): update release demos
* docs(web): polish tabs component docs
* docs(web): polish chinese component docs
* docs(web): polish chinese component docs
* docs(web): prevent href scroll jumps in card and link demos
* docs(web): sync status icons
* fix(docs): preserve locale in showcase and component doc links
* docs(web): align showcase terminology of chinese version
* fix(styles): prevent InputOTP slots from overflowing narrow containers (#6706)
* fix(docs): use theme tokens in styling examples
* fix(spinner): move accessible name from hidden svg to root status role (#6721)
The inner svg carried aria-hidden, aria-label, and role="presentation"
together: the label was dead code on a hidden element (and
aria-prohibited-attr per axe), and the spinner as a whole was absent
from the accessibility tree. Name the root span as a status live region
instead, keeping both attributes overridable via props.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(styles): restore focus outline gap for accent buttons (#6724)
* fix(styles): adopt logical CSS properties for RTL support (#6699)
* fix(styles): adopt logical CSS properties for RTL support
* fix(docs): adopt logical CSS properties for RTL support
* fix(react): adopt logical CSS properties for RTL support
* fix(storybook): adopt logical CSS properties for RTL support
* fix(docs): handle rtl for icons
* fix(storybook): handle rtl for icons
* fix(styles): handle rtl for icons
* fix(pagination): add dir="auto"
* fix(scroll-shadow): handle RTL
* fix(tabs): handle RTL
* fix(styles): handle RTL
* fix(styles): handle search icon in RTL
* chore(styles): avoid mirroring search icon
* fix(styles): handle year picker trigger indicator in RTL
* refactor(scroll-shadow): avoid getComputedStyle on every scroll
* feat(combo-box): support multiple selection (#6714)
* feat(combo-box): support multiple selection
* feat(combo-box): export ComboBoxValueRenderProps and thread selection mode generic
* chore(docs): update combo-box anatomy
* chore(docs): mark new in combo-box docs
* chore(react): move calendar and range calendar to completed
* chore(deps): update node to >= 22.x
* Merge branch 'v3' into v3.2.3
* chore(deps): bump tailwind-variants to v3.3.0 (#6733)
* fix(scroll-shadow): tolerate fractional scroll position in end detection (#6710)
* fix: react scan (#6727)
* fix: tabs list collection compatibility
* fix(react): ts expect error
* fix(tag-group): rac collection builder compatibility
* fix(select): rac collection builder compatibility
* fix(text): rac collection builder compatibility
* fix(combo-box): rac collection builder compatibility
* fix(autocomplete): rac collection builder compatibility
* fix(autocomplete): tab sequence
* feat(storybook): support react-scan in preview canvas
* chore(root): remove base-url from ts config
* fix(root): typecheck
* fix(storybook): react scan in production
* fix(autocomplete): indicator focus state
* fix(storybook): react scan in preview canvas
* chore: clean up lockfile
* docs(release): v3.2.3 release note (#6739)
* fix(icons): remove aria-label from aria-hidden decorative icons (#6741)
Every icon in the shared set carries `aria-hidden="true"` and
`role="presentation"` together with an `aria-label="... icon"`.
Because `aria-hidden="true"` removes the element from the accessibility
tree, that `aria-label` can never be announced. It is dead weight that
trips accessibility linters and audits.
Drop the `aria-label` from all 15 decorative icons and keep them hidden.
Consumers that need a name still get one from the wrapping control (e.g.
`<Button isIconOnly aria-label="...">`), and `{...props}` is still spread
last so an explicit label can be supplied per usage.
Refs #6718
* chore(docs): update release note
* fix(react): move react-aria packages to peerDependencies (#6744)
* chore(docs): update release note
---------
Co-authored-by: Stybo <84643947+Stybo@users.noreply.github.com>
Co-authored-by: Tianen Pang <32772271+tianenpang@users.noreply.github.com>
Co-authored-by: daveycodez <daveycodez@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Ted Kim <k_2684@naver.com>
Co-authored-by: Saidheerajgollu <158853598+Saidheerajgollu@users.noreply.github.com>
* fix(docs): canonicalize pages to the URLs that are actually served
Every docs page declared `https://www.heroui.com/docs/<slug>` as its
canonical, but that URL answers with two permanent redirects: `www` ->
apex, then `/docs/...` -> `/<lang>/docs/...`. Google therefore dropped
the crawled page in favour of a redirect, and both `/en` and `/cn`
variants pointed at the same English URL.
The root layout also declared the home page as canonical, which every
page without its own `alternates` inherited, self-excluding `/cn`,
`/<lang>/themes` and `/<lang>/showcase` from the index.
Canonicals now use the served locale-prefixed URL on the apex domain and
carry an hreflang cluster (en / zh-Hans / x-default). Untranslated blog
posts point at the default locale instead of self-canonicalizing a
duplicate.
* fix(docs): build the sitemap from the docs source instead of the prerender manifest
`next-sitemap` derives its URL list from Next's prerender manifest, and
every docs, blog and themes route is server-rendered on demand. The
published sitemap therefore listed 19 URLs — no documentation pages at
all — while advertising `llms-*.txt`, `manifest.webmanifest` and
`rss.xml` as indexable pages.
The App Router `sitemap.ts` enumerates the Fumadocs loader, the blog
collection and the showcase registry instead, producing 501 canonical
URLs with hreflang alternates, all of which answer 200 without a
redirect.
* fix(docs): serve robots.txt from the app and keep non-production hosts out of the index
The committed `public/robots.txt` was the artefact of an earlier
`next-sitemap` run, so its `Sitemap` and `Host` lines were pinned to
whichever host generated them — canary still advertised
`www.heroui.com`. Serving it from the app derives the sitemap URL from
the deployed host and keeps the Content Signals directive that
`MetadataRoute.Robots` cannot express.
Every route stays allowed for every crawler; nothing indexable is
blocked. Preview and development deployments opt out through
`X-Robots-Tag` instead, which is host-scoped and cannot de-index
production the way a stray `Disallow` would.
* fix(docs): exclude untranslated blog fallbacks from sitemap
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: WK Wong <wingkwong.code@gmail.com>
Uncovered while porting the Accordion component:
- `bgsurface` → `bg-surface` (invalid class, renders as a no-op): the
accordion custom-styles demo trigger (en + cn) and the text-field
"custom styles" docs example (en + cn).
- "Connect you browser" → "Connect your browser" in the accordion
custom-styles subtitle (en demo + en/cn docs).
- Trailing space before the closing quote in the first accordion
custom-styles `content` string (en demo + en/cn docs).
Docs/content only — no runtime or API changes.