fix(system-rsc): extendVariants Fix/compound variants types#5847
Conversation
🦋 Changeset detectedLatest commit: 5eb049e The changes in this PR will be included in the next version bump. This PR includes changesets to release 37 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@ITBoomBKStudio is attempting to deploy a commit to the HeroUI Inc Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughReworks variant typings to add slot-awareness (new generic S) across Variants, DefaultVariants, CompoundVariants and ExtendVariants; updates extendVariants runtime getSlots to an explicit traversal; exports ExtendVariantWithSlotsProps and updates tests and changesets accordingly. (48 words) Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer (calls extendVariants)
participant TS as Type system (compile-time)
participant Runtime as extendVariants runtime
participant Component as Extended component
Note over Dev,TS: compile-time type flow (new S generic)
Dev->>TS: supply CP, V, SV, CV, S
TS-->>Dev: validate CV extends CompoundVariants<V,SV,ComponentSlots<CP>> and infer props using GetSuggestedValues<S>
Note over Dev,Runtime: runtime slot extraction
Dev->>Runtime: pass variant groups/configs
Runtime-->>Dev: traverse groups/configs -> return null-proto map of slot names
Dev->>Component: create extended component (typed + runtime slots)
Component-->>Dev: component with slot-aware compoundVariants
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used🧠 Learnings (1)📚 Learning: 2025-10-25T17:08:46.283ZApplied to files:
🔇 Additional comments (3)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/core/system-rsc/src/extend-variants.d.ts (2)
51-54: CompoundVariants slots support looks good; consider a small readability tweak.You can express the value type via the existing helper to reduce repetition.
Apply:
type CompoundVariants<V, SV, S> = Array< VariantValue<V, SV> & - ClassProp<S extends undefined ? ClassValue : ClassValue | SlotsClassValue<S>> + ClassProp<ClassValue | GetSuggestedValues<S>> >;
98-99: Use the already-bound S instead of recomputing ComponentSlots.Keeps generics consistent and may help inference.
- CV extends CompoundVariants<V, SV, ComponentSlots<CP>>, + CV extends CompoundVariants<V, SV, S>,
Replaces the conditional ClassProp logic with a simpler, consistent form to fix incorrect slot value inference. Before: ClassProp<S extends undefined ? ClassValue : ClassValue | SlotsClassValue<S>> After: ClassProp<ClassValue | GetSuggestedValues<S>> This ensures GetSuggestedValues<S> is used for slot-aware variants and avoids duplicated conditional branches for undefined slots.
I’m keeping CV extends CompoundVariants<V, SV, ComponentSlots<CP>> on purpose. |
…NonNullable Simplifies the return type of ExtendVariants to ensure no required props are enforced at the HOC level. This aligns with the intended API contract where extended components expose all props as optional. - All keys (CP ∪ V) are optional - Preserve CP type hints and booleanized V values - Added NonNullable<V[key]> guard to prevent undefined indexing
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/core/system-rsc/__tests__/extend-variants.test.tsx(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/core/system-rsc/__tests__/extend-variants.test.tsx (4)
packages/core/system-rsc/src/extend-variants.js (1)
styles(105-105)packages/core/system-rsc/src/extend-variants.d.ts (1)
ExtendVariantWithSlotsProps(76-80)packages/core/system/src/index.ts (1)
ExtendVariantWithSlotsProps(16-16)packages/core/system-rsc/src/index.ts (1)
ExtendVariantWithSlotsProps(29-29)
🔇 Additional comments (3)
packages/core/system-rsc/__tests__/extend-variants.test.tsx (3)
1-1: LGTM!The import of
ExtendVariantWithSlotsPropsis necessary to support the updated type signature for the slots-based test helper and aligns with the PR's objective to expose slots-aware compound variant types.
40-40: LGTM!The parameter type change from
ExtendVariantPropstoExtendVariantWithSlotsPropscorrectly reflects that slots-based components require compound variants to support per-slot class definitions (e.g.,class: { header: "..." }), which is demonstrated in the new test at lines 274-276.
264-292: Well-structured test for slots-aware compound variants.This test effectively validates both forms of compound variant classes:
- String class applied to the base slot (line 270)
- Record class applied to specific slots like
header(lines 274-276)The test aligns well with the PR objective to ensure proper type inference for slots-aware compound variants.
However, the same concern applies here: both compound variants reference
radius: "md"(lines 269, 273), which is not defined in the extendedradiusvariants. If this is intentional to test compound variants referencing base component variants not overridden in the extension, consider adding a comment explaining this edge case.
@heroui/accordion
@heroui/alert
@heroui/autocomplete
@heroui/avatar
@heroui/badge
@heroui/breadcrumbs
@heroui/button
@heroui/calendar
@heroui/card
@heroui/checkbox
@heroui/chip
@heroui/code
@heroui/date-input
@heroui/date-picker
@heroui/divider
@heroui/drawer
@heroui/dropdown
@heroui/form
@heroui/image
@heroui/input
@heroui/input-otp
@heroui/kbd
@heroui/link
@heroui/listbox
@heroui/menu
@heroui/modal
@heroui/navbar
@heroui/number-input
@heroui/pagination
@heroui/popover
@heroui/progress
@heroui/radio
@heroui/ripple
@heroui/scroll-shadow
@heroui/select
@heroui/skeleton
@heroui/slider
@heroui/snippet
@heroui/spacer
@heroui/spinner
@heroui/switch
@heroui/table
@heroui/tabs
@heroui/toast
@heroui/tooltip
@heroui/user
@heroui/react
@heroui/system
@heroui/system-rsc
@heroui/theme
@heroui/use-aria-accordion
@heroui/use-aria-accordion-item
@heroui/use-aria-button
@heroui/use-aria-link
@heroui/use-aria-modal-overlay
@heroui/use-aria-multiselect
@heroui/use-aria-overlay
@heroui/use-callback-ref
@heroui/use-clipboard
@heroui/use-data-scroll-overflow
@heroui/use-disclosure
@heroui/use-draggable
@heroui/use-form-reset
@heroui/use-image
@heroui/use-infinite-scroll
@heroui/use-intersection-observer
@heroui/use-is-mobile
@heroui/use-is-mounted
@heroui/use-measure
@heroui/use-pagination
@heroui/use-real-shape
@heroui/use-ref-state
@heroui/use-resize
@heroui/use-safe-layout-effect
@heroui/use-scroll-position
@heroui/use-ssr
@heroui/use-theme
@heroui/use-update-effect
@heroui/use-viewport-size
@heroui/aria-utils
@heroui/dom-animation
@heroui/framer-utils
@heroui/react-rsc-utils
@heroui/react-utils
@heroui/shared-icons
@heroui/shared-utils
@heroui/stories-utils
@heroui/test-utils
commit: |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/core/system-rsc/__tests__/extend-variants.test.tsx (1)
76-88: Default compound variant fix addresses previous review.The change from
radius: "md"toradius: "none"correctly uses a value from the extended variant set. The fallback logic withstyles?.compoundVariants ?? [...]is clean and well-structured.Optional: Consider adding test coverage for the first compound variant.
The default compound variant at lines 77-81 (
shadow: "none"+radius: "none") is never explicitly tested. The test at line 270-284 usesradius: "sm", so only the second compound variant (lines 82-87) is exercised. Adding a test case withradius="none" shadow="none"would verify that the fix for the previous review comment works correctly.Example test:
test("should apply compound variant when shadow and radius are none", () => { const Card2 = createExtendSlotsComponent(); const {getByTestId} = render( <Card2 radius="none" shadow="none"> Card Content </Card2>, ); const baseEl = getByTestId("base"); expect(baseEl).toHaveClass("rounded-sm"); // from compound variant, overriding radius="none"'s "rounded-xs" });
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/core/system-rsc/__tests__/extend-variants.test.tsx(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/core/system-rsc/__tests__/extend-variants.test.tsx (2)
packages/core/system-rsc/src/extend-variants.js (1)
styles(105-105)packages/core/system-rsc/src/extend-variants.d.ts (1)
ExtendVariantWithSlotsProps(76-80)
🔇 Additional comments (3)
packages/core/system-rsc/__tests__/extend-variants.test.tsx (3)
1-1: LGTM! Import addition aligns with slots-aware type improvements.The new
ExtendVariantWithSlotsPropstype is correctly imported and used on line 40 to support compound variants with slot-specific styling.
40-40: Correct type change for slots-aware compound variants.Using
ExtendVariantWithSlotsPropsenables the test helper to accept compound variants with slot-specific class values, matching the updated type system.
270-314: Excellent test coverage for compound variants.The two new test cases correctly verify:
- Default compound variants work alongside regular variants (lines 270-284)
- Custom compound variants passed via
stylesparameter override defaults (lines 286-314)The tests validate both base-level and slot-specific compound variant application, ensuring the slots-aware type improvements function correctly at runtime.
Replace PropsWithoutRef with explicit Exclude<'ref'> in mapped keys and intersect with RefAttributes<InferRef<C>>. This prevents @types/react’s internal UNDEFINED_VOID_ONLY from leaking into the public .d.ts and fixes declaration emit for components like extended Autocomplete.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/core/system-rsc/src/extend-variants.d.ts (1)
103-107: Verify that making all keys optional is the intended behavior.The current mapped type uses
?:on line 104, making all keys optional—including those that may be required in the base component propsCP. A past review raised this concern and suggested preservingCP's original optionality by separating CP keys (which would retain their required/optional status) from V-only keys (which would be optional).That review was marked as addressed by updating tests to provide required props. If the intention is for extended components to always have optional props, the current implementation is correct. However, if base component contracts should be preserved (required props remain required), consider this alternative:
{ // CP keys preserve their original optionality [K in keyof CP]: K extends keyof V ? CP[K] | StringToBoolean<keyof NonNullable<V[K]>> : CP[K] } & { // V-only keys are optional [K in Exclude<keyof V, keyof CP>]?: StringToBoolean<keyof NonNullable<V[K]>> } & RefAttributes<InferRef<C>>This would maintain stricter type-safety by preventing accidental omission of required base props while still allowing variant props to be optional.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/core/system-rsc/src/extend-variants.d.ts(4 hunks)
🔇 Additional comments (3)
packages/core/system-rsc/src/extend-variants.d.ts (3)
2-2: LGTM! Missing import added.The
JSXElementConstructorimport is correctly added and used in theComponentPropshelper (line 12) andExtendVariantsconstraint (line 86).
46-48: Slots-aware compound variants implemented correctly.The addition of the
Sgeneric parameter and use ofGetSuggestedValues<S>properly extends compound variants to support both plain class values and slot-keyed class values, maintaining backward compatibility when slots are undefined.
92-92: Appropriate use ofComponentSlots<CP>for broader type coverage.Using
ComponentSlots<CP>instead of the bound genericSensures compound variants have access to the full slot surface of the base component, maintaining type-safety and authoring ergonomics as noted in the PR objectives.
Yes, this behavior is intentional for components created with extendVariants. extendVariants is designed as a styling HOC, not a strict type-safe wrapper. If we preserved CP’s required props, every extended component instance would force full prop specification, which defeats the purpose of variant composition. |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/core/system-rsc/src/extend-variants.js (1)
13-41: Consider simplifying the duplicate check.The
hasOwnPropertycheck on line 33 is redundant when usingObject.create(null)since null-prototype objects have no inherited properties. You can simplify to:for (const slotName of Object.keys(config)) { - if (!Object.prototype.hasOwnProperty.call(acc, slotName)) { + if (!(slotName in acc)) { acc[slotName] = ""; } }Alternatively, since there's no prototype pollution risk, you could assign directly without checking:
acc[slotName] = "";This would work correctly because reassigning the same key to
""is idempotent.
The overall traversal logic correctly implements the documented behavior: variants → groups → configs → slot names. The filtering for non-objects, arrays, and String objects ensures robust slot extraction.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.changeset/four-guests-sneeze.md(1 hunks)packages/core/system-rsc/src/extend-variants.js(1 hunks)
🔇 Additional comments (2)
packages/core/system-rsc/src/extend-variants.js (1)
7-12: LGTM: Clear JSDoc documentation.The JSDoc accurately describes the traversal pattern and return type. The parameter and return descriptions provide helpful context for maintainers.
.changeset/four-guests-sneeze.md (1)
1-5: LGTM: Changeset correctly documents the fix.The changeset appropriately marks this as a
minorversion bump and clearly describes the slot detection improvements. The description aligns with the implementation changes ingetSlots().
… from SuggestedVariants
|
Hey @wingkwong, I just pushed an update:
Happy to go through any part in detail if needed. |
wingkwong
left a comment
There was a problem hiding this comment.
- please combine two changeset into one and use patch instead of minor or major
- those 2 cases mentioned in comment seems not resolved using this PR build.
- does this PR cover issue 4148? There's a few more related to extendVariants. Just wanna know which of them could be solved in this PR.
In case you need faster communication / discussion, please free feel to ping me at discord (same user id)
|
Even though this should've been fixed in 2.8.6 according to release notes, it is not. Also, still an issue in 2.8.7. @wingkwong |
|
Hey @wingkwong 👋 Just pushed a new commit and everything is working smoothly now.
Also, regarding your note about the On top of that, I added tests for the relevant scenarios, and everything passes cleanly. Lmk if you want me to highlight the specific type changes in the diff. |
* fix(theme): hide password reveal button (#5990) * fix(link): link overriding role (#5999) * fix(link): allow overriding role * chore(link): changeset * chore(deps): upgrade react-aria (v1.14.0) (#5996) * chore(deps): upgrade react-aria (v1.14.0) * refactor(react): group client components * fix(dropdown): keyDown test cases * chore(react): rollback * fix(theme): default transition-duration (#6011) * fix(theme): default transitionDuration * chore(deps): bump @heroui/theme peer dep * ci(changesets): version packages (#5991) Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> * fix(use-image): resolve race condition with cached images on Firefox/Safari (#6041) * fix(use-image): resolve race condition with cached images on Firefox/Safari The bug occurred because event handlers (onload/onerror) were attached AFTER setting the image src. For cached images, browsers fire onload synchronously when src is set, causing the event to be missed and images to remain stuck at opacity-0. Changes: - Attach handlers BEFORE setting src to catch synchronous callbacks - Check both naturalWidth AND naturalHeight (per CodeRabbit review on #4523) - Handle synchronous error callbacks for failed cached images - Add comprehensive test coverage (15 tests) including: - Synchronous cached image success (Firefox/Safari race condition) - Synchronous cached image error - Dynamic src changes - All props (crossOrigin, srcSet, sizes, loading) - Callback invocation verification Reproduction and investigation performed using Claude Opus 4.5. Fixes #4534, #2259 * fix(use-image): add ignoreFallback to useCallback dependencies Address CodeRabbit review feedback: the `ignoreFallback` prop was used inside the `load` callback (line 104) but was missing from the dependency array, creating a stale closure bug. Without this fix, if `ignoreFallback` changes from `true` to `false` dynamically, the `load` callback would retain the stale `true` value, preventing the image from ever loading. Changes: - Add `ignoreFallback` to useCallback dependency array - Add tests for dynamic `ignoreFallback` changes (both directions) - Update changeset to document this fix Verification performed using Claude Opus 4.5. --------- Co-authored-by: Brian Meek <brian@current.space> * fix(docs): broken links in Form page (#6077) * fix(pagination): improve layout for large page counts (#6034) * fix(pagination): improve layout for large page counts/style of paagination compnents * fix(pagination): refine item sizing to balance small and large page numbers * ci(changesets): add pagination sizing changeset * fix(pagination): ensure cursor fully covers button without changing radius * chore(changeset): revise message and add issue numbers --------- Co-authored-by: WK Wong <wingkwong.code@gmail.com> * fix(date-picker): open date-picker when clicking border (#6084) * fix(date-picker): add pointer interaction to open date picker on wrapper click * chore: add changeset * chore(changeset): add issue number --------- Co-authored-by: WK <wingkwong.code@gmail.com> * fix(accordion): click behaviour for dynamically generated accordion items (#6133) * fix(accordion): add collection state * chore: add changeset * fix: update change set * refactor(theme): remove flat dependency (#6157) * chore(deps): remove flat library * refactor(theme): replace flatten from flat * chore: add changeset * fix(listbox): prevent option focus from start/end content slots (#6060) * fix(listbox): prevent option focus from start/end content slots * test: add test code about when clicking non-interactive slot content, and prevented focus leakage from interactive start/end content such as buttons. * docs: add changeset * chore(changeset): add issue number --------- Co-authored-by: WK <wingkwong.code@gmail.com> * fix(system-rsc): extendVariants & compound variants types (#5847) * fix(extendVariants): return component type error * fix(CompoundVariants): correct type inference for extended/compound variants and composition * test: cover compound/extend inference; enforce CP required props * fix(types): correct CompoundVariants class value inference Replaces the conditional ClassProp logic with a simpler, consistent form to fix incorrect slot value inference. Before: ClassProp<S extends undefined ? ClassValue : ClassValue | SlotsClassValue<S>> After: ClassProp<ClassValue | GetSuggestedValues<S>> This ensures GetSuggestedValues<S> is used for slot-aware variants and avoids duplicated conditional branches for undefined slots. * fix(system-rsc): correct slot detection in getSlots() * fix(types): make ExtendVariants props optional and guard V[key] with NonNullable Simplifies the return type of ExtendVariants to ensure no required props are enforced at the HOC level. This aligns with the intended API contract where extended components expose all props as optional. - All keys (CP ∪ V) are optional - Preserve CP type hints and booleanized V values - Added NonNullable<V[key]> guard to prevent undefined indexing * test(extendVariants): add compoundVariants integration test * fix(system-rsc): getSlots() brief JSDoc comment added * test(extendVariants): new styles - extended & fixed styles - original tests for slots component * test(extendVariants): fixed slot component variant styles extended test * fix(types): avoid leaking React internals by removing PropsWithoutRef Replace PropsWithoutRef with explicit Exclude<'ref'> in mapped keys and intersect with RefAttributes<InferRef<C>>. This prevents @types/react’s internal UNDEFINED_VOID_ONLY from leaking into the public .d.ts and fixes declaration emit for components like extended Autocomplete. * chore(changeset): add patch for extendVariants and CompoundVariants type fix * chore(system-rsc): add changeset for getSlots() slot detection fix * refactor(types): unify slot value inference via GetSuggestedValues<S> for consistent variant typing * fix(extendVariants): improved as-prop handling and exclude classNames from SuggestedVariants * fix(system-rsc): add polymorphic 'as' prop support to extendVariants * chore(system-rsc): add missing tests --------- Co-authored-by: doki- <1335902682@qq.com> Co-authored-by: WK Wong <wingkwong.code@gmail.com> * chore(docs): update meta (#6168) * ci(changesets): version packages (#6059) Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> --------- Co-authored-by: Hayato Hasegawa <hase1225hayato@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> Co-authored-by: brianatdetections <brian@detections.ai> Co-authored-by: Brian Meek <brian@current.space> Co-authored-by: Dominik Hryshaiev <domhryshaiev@gmail.com> Co-authored-by: creative-atish <149860680+atishkr25@users.noreply.github.com> Co-authored-by: KyZy7 <29321162+KyZy7@users.noreply.github.com> Co-authored-by: Deepansh Bhargava <deepansh940@gmail.com> Co-authored-by: KumJungMin <37934668+KumJungMin@users.noreply.github.com> Co-authored-by: Bohdan Kulinchenko <35272606+ITBoomBKStudio@users.noreply.github.com> Co-authored-by: doki- <1335902682@qq.com>
* fix(theme): hide password reveal button (#5990) * fix(link): link overriding role (#5999) * fix(link): allow overriding role * chore(link): changeset * chore(deps): upgrade react-aria (v1.14.0) (#5996) * chore(deps): upgrade react-aria (v1.14.0) * refactor(react): group client components * fix(dropdown): keyDown test cases * chore(react): rollback * fix(theme): default transition-duration (#6011) * fix(theme): default transitionDuration * chore(deps): bump @heroui/theme peer dep * ci(changesets): version packages (#5991) Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> * fix(use-image): resolve race condition with cached images on Firefox/Safari (#6041) * fix(use-image): resolve race condition with cached images on Firefox/Safari The bug occurred because event handlers (onload/onerror) were attached AFTER setting the image src. For cached images, browsers fire onload synchronously when src is set, causing the event to be missed and images to remain stuck at opacity-0. Changes: - Attach handlers BEFORE setting src to catch synchronous callbacks - Check both naturalWidth AND naturalHeight (per CodeRabbit review on #4523) - Handle synchronous error callbacks for failed cached images - Add comprehensive test coverage (15 tests) including: - Synchronous cached image success (Firefox/Safari race condition) - Synchronous cached image error - Dynamic src changes - All props (crossOrigin, srcSet, sizes, loading) - Callback invocation verification Reproduction and investigation performed using Claude Opus 4.5. Fixes #4534, #2259 * fix(use-image): add ignoreFallback to useCallback dependencies Address CodeRabbit review feedback: the `ignoreFallback` prop was used inside the `load` callback (line 104) but was missing from the dependency array, creating a stale closure bug. Without this fix, if `ignoreFallback` changes from `true` to `false` dynamically, the `load` callback would retain the stale `true` value, preventing the image from ever loading. Changes: - Add `ignoreFallback` to useCallback dependency array - Add tests for dynamic `ignoreFallback` changes (both directions) - Update changeset to document this fix Verification performed using Claude Opus 4.5. --------- Co-authored-by: Brian Meek <brian@current.space> * fix(docs): broken links in Form page (#6077) * fix(pagination): improve layout for large page counts (#6034) * fix(pagination): improve layout for large page counts/style of paagination compnents * fix(pagination): refine item sizing to balance small and large page numbers * ci(changesets): add pagination sizing changeset * fix(pagination): ensure cursor fully covers button without changing radius * chore(changeset): revise message and add issue numbers --------- Co-authored-by: WK Wong <wingkwong.code@gmail.com> * fix(date-picker): open date-picker when clicking border (#6084) * fix(date-picker): add pointer interaction to open date picker on wrapper click * chore: add changeset * chore(changeset): add issue number --------- Co-authored-by: WK <wingkwong.code@gmail.com> * fix(accordion): click behaviour for dynamically generated accordion items (#6133) * fix(accordion): add collection state * chore: add changeset * fix: update change set * refactor(theme): remove flat dependency (#6157) * chore(deps): remove flat library * refactor(theme): replace flatten from flat * chore: add changeset * fix(listbox): prevent option focus from start/end content slots (#6060) * fix(listbox): prevent option focus from start/end content slots * test: add test code about when clicking non-interactive slot content, and prevented focus leakage from interactive start/end content such as buttons. * docs: add changeset * chore(changeset): add issue number --------- Co-authored-by: WK <wingkwong.code@gmail.com> * fix(system-rsc): extendVariants & compound variants types (#5847) * fix(extendVariants): return component type error * fix(CompoundVariants): correct type inference for extended/compound variants and composition * test: cover compound/extend inference; enforce CP required props * fix(types): correct CompoundVariants class value inference Replaces the conditional ClassProp logic with a simpler, consistent form to fix incorrect slot value inference. Before: ClassProp<S extends undefined ? ClassValue : ClassValue | SlotsClassValue<S>> After: ClassProp<ClassValue | GetSuggestedValues<S>> This ensures GetSuggestedValues<S> is used for slot-aware variants and avoids duplicated conditional branches for undefined slots. * fix(system-rsc): correct slot detection in getSlots() * fix(types): make ExtendVariants props optional and guard V[key] with NonNullable Simplifies the return type of ExtendVariants to ensure no required props are enforced at the HOC level. This aligns with the intended API contract where extended components expose all props as optional. - All keys (CP ∪ V) are optional - Preserve CP type hints and booleanized V values - Added NonNullable<V[key]> guard to prevent undefined indexing * test(extendVariants): add compoundVariants integration test * fix(system-rsc): getSlots() brief JSDoc comment added * test(extendVariants): new styles - extended & fixed styles - original tests for slots component * test(extendVariants): fixed slot component variant styles extended test * fix(types): avoid leaking React internals by removing PropsWithoutRef Replace PropsWithoutRef with explicit Exclude<'ref'> in mapped keys and intersect with RefAttributes<InferRef<C>>. This prevents @types/react’s internal UNDEFINED_VOID_ONLY from leaking into the public .d.ts and fixes declaration emit for components like extended Autocomplete. * chore(changeset): add patch for extendVariants and CompoundVariants type fix * chore(system-rsc): add changeset for getSlots() slot detection fix * refactor(types): unify slot value inference via GetSuggestedValues<S> for consistent variant typing * fix(extendVariants): improved as-prop handling and exclude classNames from SuggestedVariants * fix(system-rsc): add polymorphic 'as' prop support to extendVariants * chore(system-rsc): add missing tests --------- Co-authored-by: doki- <1335902682@qq.com> Co-authored-by: WK Wong <wingkwong.code@gmail.com> * chore(docs): update meta (#6168) * ci(changesets): version packages (#6059) Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> --------- Co-authored-by: Hayato Hasegawa <hase1225hayato@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> Co-authored-by: brianatdetections <brian@detections.ai> Co-authored-by: Brian Meek <brian@current.space> Co-authored-by: Dominik Hryshaiev <domhryshaiev@gmail.com> Co-authored-by: creative-atish <149860680+atishkr25@users.noreply.github.com> Co-authored-by: KyZy7 <29321162+KyZy7@users.noreply.github.com> Co-authored-by: Deepansh Bhargava <deepansh940@gmail.com> Co-authored-by: KumJungMin <37934668+KumJungMin@users.noreply.github.com> Co-authored-by: Bohdan Kulinchenko <35272606+ITBoomBKStudio@users.noreply.github.com> Co-authored-by: doki- <1335902682@qq.com>
* fix(theme): hide password reveal button (#5990) * fix(link): link overriding role (#5999) * fix(link): allow overriding role * chore(link): changeset * chore(deps): upgrade react-aria (v1.14.0) (#5996) * chore(deps): upgrade react-aria (v1.14.0) * refactor(react): group client components * fix(dropdown): keyDown test cases * chore(react): rollback * fix(theme): default transition-duration (#6011) * fix(theme): default transitionDuration * chore(deps): bump @heroui/theme peer dep * ci(changesets): version packages (#5991) Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> * fix(use-image): resolve race condition with cached images on Firefox/Safari (#6041) * fix(use-image): resolve race condition with cached images on Firefox/Safari The bug occurred because event handlers (onload/onerror) were attached AFTER setting the image src. For cached images, browsers fire onload synchronously when src is set, causing the event to be missed and images to remain stuck at opacity-0. Changes: - Attach handlers BEFORE setting src to catch synchronous callbacks - Check both naturalWidth AND naturalHeight (per CodeRabbit review on #4523) - Handle synchronous error callbacks for failed cached images - Add comprehensive test coverage (15 tests) including: - Synchronous cached image success (Firefox/Safari race condition) - Synchronous cached image error - Dynamic src changes - All props (crossOrigin, srcSet, sizes, loading) - Callback invocation verification Reproduction and investigation performed using Claude Opus 4.5. Fixes #4534, #2259 * fix(use-image): add ignoreFallback to useCallback dependencies Address CodeRabbit review feedback: the `ignoreFallback` prop was used inside the `load` callback (line 104) but was missing from the dependency array, creating a stale closure bug. Without this fix, if `ignoreFallback` changes from `true` to `false` dynamically, the `load` callback would retain the stale `true` value, preventing the image from ever loading. Changes: - Add `ignoreFallback` to useCallback dependency array - Add tests for dynamic `ignoreFallback` changes (both directions) - Update changeset to document this fix Verification performed using Claude Opus 4.5. --------- Co-authored-by: Brian Meek <brian@current.space> * fix(docs): broken links in Form page (#6077) * fix(pagination): improve layout for large page counts (#6034) * fix(pagination): improve layout for large page counts/style of paagination compnents * fix(pagination): refine item sizing to balance small and large page numbers * ci(changesets): add pagination sizing changeset * fix(pagination): ensure cursor fully covers button without changing radius * chore(changeset): revise message and add issue numbers --------- Co-authored-by: WK Wong <wingkwong.code@gmail.com> * fix(date-picker): open date-picker when clicking border (#6084) * fix(date-picker): add pointer interaction to open date picker on wrapper click * chore: add changeset * chore(changeset): add issue number --------- Co-authored-by: WK <wingkwong.code@gmail.com> * fix(accordion): click behaviour for dynamically generated accordion items (#6133) * fix(accordion): add collection state * chore: add changeset * fix: update change set * refactor(theme): remove flat dependency (#6157) * chore(deps): remove flat library * refactor(theme): replace flatten from flat * chore: add changeset * fix(listbox): prevent option focus from start/end content slots (#6060) * fix(listbox): prevent option focus from start/end content slots * test: add test code about when clicking non-interactive slot content, and prevented focus leakage from interactive start/end content such as buttons. * docs: add changeset * chore(changeset): add issue number --------- Co-authored-by: WK <wingkwong.code@gmail.com> * fix(system-rsc): extendVariants & compound variants types (#5847) * fix(extendVariants): return component type error * fix(CompoundVariants): correct type inference for extended/compound variants and composition * test: cover compound/extend inference; enforce CP required props * fix(types): correct CompoundVariants class value inference Replaces the conditional ClassProp logic with a simpler, consistent form to fix incorrect slot value inference. Before: ClassProp<S extends undefined ? ClassValue : ClassValue | SlotsClassValue<S>> After: ClassProp<ClassValue | GetSuggestedValues<S>> This ensures GetSuggestedValues<S> is used for slot-aware variants and avoids duplicated conditional branches for undefined slots. * fix(system-rsc): correct slot detection in getSlots() * fix(types): make ExtendVariants props optional and guard V[key] with NonNullable Simplifies the return type of ExtendVariants to ensure no required props are enforced at the HOC level. This aligns with the intended API contract where extended components expose all props as optional. - All keys (CP ∪ V) are optional - Preserve CP type hints and booleanized V values - Added NonNullable<V[key]> guard to prevent undefined indexing * test(extendVariants): add compoundVariants integration test * fix(system-rsc): getSlots() brief JSDoc comment added * test(extendVariants): new styles - extended & fixed styles - original tests for slots component * test(extendVariants): fixed slot component variant styles extended test * fix(types): avoid leaking React internals by removing PropsWithoutRef Replace PropsWithoutRef with explicit Exclude<'ref'> in mapped keys and intersect with RefAttributes<InferRef<C>>. This prevents @types/react’s internal UNDEFINED_VOID_ONLY from leaking into the public .d.ts and fixes declaration emit for components like extended Autocomplete. * chore(changeset): add patch for extendVariants and CompoundVariants type fix * chore(system-rsc): add changeset for getSlots() slot detection fix * refactor(types): unify slot value inference via GetSuggestedValues<S> for consistent variant typing * fix(extendVariants): improved as-prop handling and exclude classNames from SuggestedVariants * fix(system-rsc): add polymorphic 'as' prop support to extendVariants * chore(system-rsc): add missing tests --------- Co-authored-by: doki- <1335902682@qq.com> Co-authored-by: WK Wong <wingkwong.code@gmail.com> * chore(docs): update meta (#6168) * ci(changesets): version packages (#6059) Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> * fix(system-rsc): extendVariants rendering behavior with as (#6215) * fix(system-rsc): fix components rendering with 'as' prop * fix(system-rsc): fix compoundVariants and slots inheritance in extendVariants * fix(system-rsc): extendVariants test file cleaned * chore(deps): bump RA dependencies (#6221) * chore(deps): bump RA dependencies * chore(date-picker): revise test cases * fix(button): correct disableRipple prop precedence (#6199) * ci(changesets): version packages (#6227) Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> --------- Co-authored-by: Hayato Hasegawa <hase1225hayato@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> Co-authored-by: brianatdetections <brian@detections.ai> Co-authored-by: Brian Meek <brian@current.space> Co-authored-by: Dominik Hryshaiev <domhryshaiev@gmail.com> Co-authored-by: creative-atish <149860680+atishkr25@users.noreply.github.com> Co-authored-by: KyZy7 <29321162+KyZy7@users.noreply.github.com> Co-authored-by: Deepansh Bhargava <deepansh940@gmail.com> Co-authored-by: KumJungMin <37934668+KumJungMin@users.noreply.github.com> Co-authored-by: Bohdan Kulinchenko <35272606+ITBoomBKStudio@users.noreply.github.com> Co-authored-by: doki- <1335902682@qq.com> Co-authored-by: Chris Nowak <krzysztofmareknowak@gmail.com>

Closes #5778
📝 Description
Supersedes #5795.
Builds on the initial work by @IsDyh01 to address the incorrect return type in
extendVariants, and additionally fixes long-standing typing issues with CompoundVariants (observed since early NextUI days).This PR:
extendVariantstype fix.Credits:
Original approach by @IsDyh01 (commits preserved via cherry-pick / attribution).
Authored by @ITBoomBKStudio.
⚽️ Current behavior (updates)
extendVariantscan yield an incorrect component return type, leading to type errors when using the extended variant API.🚀 New behavior
extendVariantsnow preserves and exposes the correct component/props type in the returned value.CompoundVariants inference is stable when:
asneeded).Added unit tests covering:
extendVariants,No runtime changes; all changes are type-level and test-only.
💣 Is this a breaking change (Yes/No):
No.
The change improves type inference without removing or renaming public APIs. Existing correct usages continue to type-check. In cases where code previously relied on loose/incorrect inference, the compiler now catches mistakes earlier (desired tightening, not a breaking API change).
📝 Additional Information
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.