-
-
Notifications
You must be signed in to change notification settings - Fork 2k
feat: add support for "outside-top" label placement #5964
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: canary
Are you sure you want to change the base?
feat: add support for "outside-top" label placement #5964
Conversation
🦋 Changeset detectedLatest commit: 5d3b34d The changes in this PR will be included in the next version bump. This PR includes changesets to release 33 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 |
|
@hasegawa-101 is attempting to deploy a commit to the HeroUI Inc Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughAdds support for a new labelPlacement value "outside-top" across hooks, provider types, theme variants, components (NumberInput, Input, Select, Date/Time/Picker family), stories, docs, tests, and a changeset; introduces Changes
Sequence Diagram(s)sequenceDiagram
participant App as Consumer App
participant Provider as HeroUIProvider
participant Comp as Component (Input/NumberInput/Select/Date*)
participant Hook as useInputLabelPlacement / use-*-hook
participant Theme as Theme variants
App->>Provider: Wrap with labelPlacement="outside-top"
Comp->>Hook: call hook(props, context)
Hook->>Provider: read global labelPlacement
Hook-->>Comp: return isLabelOutside / isOutsideTop flag
Comp->>Theme: request slot classes for labelPlacement
Theme-->>Comp: return variant classes (outside-top)
Comp->>Comp: render label outside-top (flex-col, label spacing)
Note over Comp: Stories/docs/tests reflect the new placement
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 (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
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 |
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/core/theme/src/components/number-input.ts (2)
213-217: Consider adding size-based compound variants for "outside-top".Both "outside" (lines 802-841) and "outside-left" (lines 843-866) have compound variants that adjust
stepperButtonsizing based on thesizeprop. The "outside-top" placement should likely have similar adjustments for consistency.Consider adding compound variants similar to these:
+ // outside-top & size + { + labelPlacement: "outside-top", + size: "sm", + class: { + stepperButton: "before:h-4", + }, + }, + { + labelPlacement: "outside-top", + size: "md", + class: { + stepperButton: "before:h-4", + }, + }, + { + labelPlacement: "outside-top", + size: "lg", + class: { + stepperButton: "min-4 w-4 h-4 before:h-6", + }, + },
213-217: Consider adding text truncation support for "outside-top".The compound variant at lines 868-873 adds text truncation styles for
labelPlacement: ["inside", "outside"]. Labels in the "outside-top" placement may also benefit from text truncation to handle long labels gracefully.Consider updating the compound variant to include "outside-top":
{ - labelPlacement: ["inside", "outside"], + labelPlacement: ["inside", "outside", "outside-top"], class: { label: ["pe-2", "max-w-full", "text-ellipsis", "overflow-hidden"], }, },
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
.changeset/fresh-crews-grow.md(1 hunks)apps/docs/content/components/number-input/label-placements.raw.jsx(1 hunks)apps/docs/content/docs/components/number-input.mdx(2 hunks)packages/components/number-input/src/number-input.tsx(3 hunks)packages/components/number-input/src/use-number-input.ts(4 hunks)packages/components/number-input/stories/number-input.stories.tsx(3 hunks)packages/core/theme/src/components/number-input.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-25T17:08:46.283Z
Learnt from: adbjo
Repo: heroui-inc/heroui PR: 5846
File: packages/components/tabs/src/tabs.tsx:156-157
Timestamp: 2025-10-25T17:08:46.283Z
Learning: In packages/components/tabs/src/tabs.tsx, the renderTabs useMemo dependency array intentionally includes `variant` and `isVertical` to prevent potential side-effects, even though they might appear redundant based on static analysis.
Applied to files:
packages/components/number-input/src/use-number-input.ts
🧬 Code graph analysis (1)
packages/components/number-input/stories/number-input.stories.tsx (1)
packages/components/number-input/src/index.ts (1)
NumberInput(10-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: ESLint
- GitHub Check: Continuous Release
- GitHub Check: TypeScript
- GitHub Check: Build
🔇 Additional comments (13)
.changeset/fresh-crews-grow.md (1)
1-6: LGTM!The changeset correctly documents the new feature and references the related issue.
apps/docs/content/docs/components/number-input.mdx (2)
68-68: LGTM!Documentation text correctly updated to include the new "outside-top" placement option.
376-376: LGTM!API table correctly updated with the new labelPlacement option.
apps/docs/content/components/number-input/label-placements.raw.jsx (1)
4-4: LGTM!The new placement option is correctly added to the examples array.
packages/components/number-input/stories/number-input.stories.tsx (2)
44-44: LGTM!Storybook controls correctly updated to include the new placement option.
112-112: LGTM!Examples for the new "outside-top" placement are correctly added to both sections.
Also applies to: 131-136
packages/components/number-input/src/use-number-input.ts (4)
216-219: LGTM!The logic correctly includes "outside-top" in the
shouldLabelBeOutsidecheck and computesisOutsideTopappropriately.Also applies to: 225-225
228-233: LGTM!The
isLabelOutsidecondition correctly accounts for the newisOutsideTopflag.
609-609: LGTM!The new
isOutsideTopflag is correctly exposed in the hook's return value.
7-7: Verify NumberInput component compatibility with useInputLabelPlacement.The
useInputLabelPlacementhook is an officially documented HeroUI hook introduced in v2.8.0 for managing label placement in form inputs. Verify that this hook provides compatible functionality for the NumberInput component's label placement needs, particularly in the context of lines 202-205 where this hook is also applied.packages/components/number-input/src/number-input.tsx (3)
25-25: LGTM!The
isOutsideTopflag is correctly destructured from the hook.
110-110: LGTM!The rendering logic correctly prevents the label from appearing inside the input wrapper when either
isOutsideLeftorisOutsideTopis true.
143-143: LGTM!The rendering logic correctly places the label at the component's top level when either
isOutsideLeftorisOutsideTopis true, ensuring proper layout for both placement options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
apps/docs/content/docs/components/number-input.mdx (1)
68-77: Improve note structure to reduce repetition.The documentation clearly explains the new "outside-top" placement option and its behavior. However, all three notes starting at line 72 begin with the identical phrase "Note: If the", which creates stylistic repetition. Consider rewording to vary the structure.
For example:
> **Note**: If the `label` is not passed, the `labelPlacement` property will be `outside` by default. > **Note**: When `labelPlacement` is set to `outside`, the label appears outside only if a placeholder is provided. > **Note**: When using `outside-top` or `outside-left`, the label is always displayed outside, regardless of placeholder presence.apps/docs/content/docs/components/select.mdx (1)
100-100: Documentation complete, but consider improving note structure.The labelPlacement documentation is thorough and well-integrated, with helpful behavioral notes. However, the static analysis tool flagged three consecutive sentences beginning with "> Note:" (lines 104, 106, 108), which impacts readability. Consider rephrasing one note to vary the sentence structure—for example, converting line 106 to a conditional statement or merging related notes.
Suggested refactor for improved readability:
> **Note**: If the `label` is not passed, the `labelPlacement` property will be `outside` by default. - -> **Note**: If the `labelPlacement` is `outside`, `label` is outside only when a placeholder is provided. - -> **Note**: If the `labelPlacement` is `outside-top` or `outside-left`, `label` is outside even if a placeholder is not provided. + +When `labelPlacement` is `outside`, the label only appears if a placeholder is provided. For `outside-top` or `outside-left`, the label appears regardless of placeholder presence.Also applies to: 106-108, 483-483
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/docs/content/docs/components/date-input.mdx(2 hunks)apps/docs/content/docs/components/date-picker.mdx(2 hunks)apps/docs/content/docs/components/date-range-picker.mdx(2 hunks)apps/docs/content/docs/components/input.mdx(1 hunks)apps/docs/content/docs/components/number-input.mdx(2 hunks)apps/docs/content/docs/components/select.mdx(2 hunks)apps/docs/content/docs/components/time-input.mdx(2 hunks)
🧰 Additional context used
🪛 LanguageTool
apps/docs/content/docs/components/select.mdx
[style] ~108-~108: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ly when a placeholder is provided. > Note: If the labelPlacement is `outside-...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
apps/docs/content/docs/components/number-input.mdx
[style] ~76-~76: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ly when a placeholder is provided. > Note: If the labelPlacement is `outside-...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: ESLint
- GitHub Check: Continuous Release
- GitHub Check: Build
- GitHub Check: TypeScript
- GitHub Check: Tests
🔇 Additional comments (7)
apps/docs/content/docs/components/date-input.mdx (1)
63-63: Documentation updates are accurate and consistent.The prose description and API table type definition both correctly add
outside-topas a valid labelPlacement option for DateInput. The updates align with the PR objectives to support the new placement across form components.Also applies to: 373-373
apps/docs/content/docs/components/number-input.mdx (1)
380-380: API documentation is complete and accurate.The labelPlacement type has been properly updated to include the new "outside-top" option alongside existing placements.
apps/docs/content/docs/components/date-range-picker.mdx (2)
83-83: Documentation update is accurate and clear.The descriptive text correctly lists all four labelPlacement options. No issues identified.
480-484: API type definition is consistent and complete.The updated labelPlacement type correctly reflects all supported options, matching the descriptive text above. The default value ("inside") remains appropriate.
apps/docs/content/docs/components/date-picker.mdx (1)
62-62: Documentation updated consistently for "outside-top" labelPlacement.Both the main description and API table have been updated to reflect the new labelPlacement option. However, consider whether DatePicker should include the behavioral notes present in Input and Select components (e.g., label visibility depends on placeholder and labelPlacement combination). This clarification helps users understand when labels appear.
Also applies to: 410-410
apps/docs/content/docs/components/input.mdx (1)
78-78: Comprehensive documentation update for Input labelPlacement.The documentation correctly adds "outside-top" to the description, API type, and includes helpful behavioral notes explaining when labels appear based on the labelPlacement and placeholder combination. These clarifications align well with the feature's goal of providing consistent label behavior across form components.
Also applies to: 86-86, 356-356
apps/docs/content/docs/components/time-input.mdx (1)
92-98: Documentation updated for "outside-top" labelPlacement.The section header, description, and API table type have been updated to include the new labelPlacement option. Like DatePicker, TimeInput lacks the behavioral clarification notes present in Input and Select (explaining when labels appear based on labelPlacement and placeholder). Consider adding these notes for consistency and user clarity.
Also applies to: 284-284
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
packages/components/autocomplete/__tests__/autocomplete.test.tsx (1)
865-895: Consider adding test coverage for the new "outside-top" labelPlacement.The tests correctly verify
labelPlacementinheritance and precedence with the provider context. However, since this PR introduces support forlabelPlacement="outside-top"(per PR objectives), consider adding a test case that explicitly verifies the new placement option works correctly when set via HeroUIProvider and when set directly on the component.packages/components/select/__tests__/select.test.tsx (1)
1710-1763: Consider adding test coverage for the new "outside-top" labelPlacement.The tests correctly verify
labelPlacementinheritance and precedence using DOM slot selectors. This approach differs from the Autocomplete tests (which use CSS class checks), but is appropriate for Select's structure. However, consider adding test cases for the newlabelPlacement="outside-top"option introduced in this PR.packages/components/date-input/__tests__/time-input.test.tsx (1)
448-480: Consider adding test coverage for the new "outside-top" labelPlacement.The tests correctly verify
labelPlacementinheritance and prop precedence using data-slot selectors, which is consistent with the DateInput test approach. Since this PR adds support forlabelPlacement="outside-top"to TimeInput (per PR objectives), consider adding explicit test cases for the new placement option.packages/components/input/__tests__/input.test.tsx (1)
671-701: Consider adding test coverage for the new "outside-top" labelPlacement.The tests correctly verify
labelPlacementinheritance and precedence using CSS class checks (similar to Autocomplete). The regex pattern/translate-y.*100%/is appropriate for detecting the "outside" placement. Consider adding test cases for the newlabelPlacement="outside-top"option if Input supports it.packages/components/date-input/__tests__/date-input.test.tsx (1)
342-374: Consider adding test coverage for the new "outside-top" labelPlacement.The tests correctly verify
labelPlacementinheritance and prop precedence using data-slot selectors, consistent with TimeInput. Since this PR adds support forlabelPlacement="outside-top"to DateInput (per PR objectives), consider adding explicit test cases that verify the new placement option works correctly both when inherited from HeroUIProvider and when set directly on the component.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
packages/components/autocomplete/__tests__/autocomplete.test.tsx(2 hunks)packages/components/date-input/__tests__/date-input.test.tsx(2 hunks)packages/components/date-input/__tests__/time-input.test.tsx(2 hunks)packages/components/input/__tests__/input.test.tsx(2 hunks)packages/components/select/__tests__/select.test.tsx(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
packages/components/date-input/__tests__/date-input.test.tsx (1)
packages/core/system/src/provider.tsx (1)
HeroUIProvider(52-114)
packages/components/select/__tests__/select.test.tsx (1)
packages/core/system/src/provider.tsx (1)
HeroUIProvider(52-114)
packages/components/input/__tests__/input.test.tsx (2)
packages/core/system/src/provider.tsx (1)
HeroUIProvider(52-114)packages/components/input/src/index.ts (1)
Input(12-12)
packages/components/date-input/__tests__/time-input.test.tsx (1)
packages/core/system/src/provider.tsx (1)
HeroUIProvider(52-114)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Continuous Release
- GitHub Check: TypeScript
- GitHub Check: ESLint
- GitHub Check: Build
wingkwong
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Select > Label Placement. The example is overlapping.
- Update possible values in label placement in https://heroui-6nl930day-heroui.vercel.app/docs/api-references/heroui-provider
…` label placement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/docs/content/docs/components/autocomplete.mdx (1)
544-548: API table forlabelPlacementis missingoutside-topThe descriptive docs and examples show
outside-topas a validlabelPlacement, but the API row still lists onlyinside | outside | outside-left. This will confuse consumers checking the API reference.Recommend updating the type string to include
outside-top:{ attribute: "labelPlacement", - type: "inside | outside | outside-left", + type: "inside | outside | outside-left | outside-top", description: "The position of the label.", default: "inside" },
🧹 Nitpick comments (1)
apps/docs/content/components/number-input/label-placements.raw.jsx (1)
4-35: NumberInput label placements demo correctly addsoutside-top(optional layout cleanup)The example now covers all four placements, including
outside-top, and the two-column layout onmd+ screens reads well.If you want to keep layout consistent with the Autocomplete/Select examples and avoid mixing
flexandgriddisplay classes, you could simplify the root container:- return ( - <div className="flex flex-col gap-8 md:grid md:grid-cols-2"> + return ( + <div className="grid grid-cols-1 gap-8 md:grid-cols-2">Current code is perfectly valid; this is just for consistency and slightly cleaner Tailwind usage.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/docs/content/components/autocomplete/label-placements.raw.jsx(2 hunks)apps/docs/content/components/number-input/label-placements.raw.jsx(2 hunks)apps/docs/content/components/select/label-placements.raw.jsx(2 hunks)apps/docs/content/docs/api-references/heroui-provider.mdx(1 hunks)apps/docs/content/docs/components/autocomplete.mdx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
apps/docs/content/components/autocomplete/label-placements.raw.jsx (2)
apps/docs/content/components/number-input/label-placements.raw.jsx (1)
placements(4-4)apps/docs/content/components/select/label-placements.raw.jsx (1)
placements(20-20)
apps/docs/content/components/number-input/label-placements.raw.jsx (2)
apps/docs/content/components/autocomplete/label-placements.raw.jsx (1)
placements(32-32)apps/docs/content/components/select/label-placements.raw.jsx (1)
placements(20-20)
apps/docs/content/components/select/label-placements.raw.jsx (5)
apps/docs/content/components/autocomplete/label-placements.raw.jsx (1)
placements(32-32)apps/docs/content/components/number-input/label-placements.raw.jsx (1)
placements(4-4)apps/docs/content/components/date-input/label-placements.raw.jsx (1)
placements(5-5)apps/docs/content/components/date-picker/label-placements.raw.jsx (1)
placements(4-4)apps/docs/content/components/date-range-picker/label-placements.raw.jsx (1)
placements(4-4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Continuous Release
- GitHub Check: TypeScript
- GitHub Check: Build
🔇 Additional comments (6)
apps/docs/content/docs/components/autocomplete.mdx (1)
103-110: Docs text correctly reflects newoutside-topplacementThe label placements paragraph now matches the new supported values (
inside,outside,outside-left,outside-top) and aligns with the examples.apps/docs/content/docs/api-references/heroui-provider.mdx (1)
148-153: HeroUIProviderlabelPlacementdocs aligned with newoutside-topvalueThe description and possible values now correctly include
outside-top, matching the component-level support introduced elsewhere in the PR.apps/docs/content/components/autocomplete/label-placements.raw.jsx (1)
32-70: Autocomplete label placements example fully updated foroutside-topThe placements array and both “Without placeholder” / “With placeholder” sections now include
outside-top, and the responsive grid layout is consistent with the other component demos. Looks good.apps/docs/content/components/select/label-placements.raw.jsx (3)
20-20: LGTM! Consistent addition of "outside-top" placement.The addition of "outside-top" to the placements array correctly implements the PR's core objective and matches the pattern used across other form components (autocomplete, number-input, date-input, etc.).
23-23: Improved responsive layout for four placement options.The switch to a responsive grid layout (two columns on medium+ screens) effectively accommodates the fourth placement option while maintaining a clean, organized presentation. The increased gap (4 → 8) is appropriate for grid spacing.
24-26: Consistent spacing improvements.The increased gap spacing (gap-2 → gap-4) in both "Without placeholder" and "With placeholder" sections provides better visual separation between the four Select components, improving readability of the documentation examples.
Also applies to: 41-43

📝 Description
Added support for labelPlacement="outside-top" to
NumberInput, Select, DateInput, TimeInput, DatePicker, and DateRangePicker components to align with the Input component's behavior.
⛳️ Current behavior (updates)
These components do not support
labelPlacement="outside-top"🚀 New behavior
The following components now correctly render the label above the input field when labelPlacement="outside-top" is passed, matching the styling and behavior of the Input component:
This ensures consistent API and visual behavior across all form components when using
HeroUIProvider or individual props.
💣 Is this a breaking change (Yes/No):
No
📝 Additional Information
Summary by CodeRabbit
New Features
Documentation
Theme / System
Tests
✏️ Tip: You can customize this high-level summary in your review settings.