mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(input): label position and styles (#1901)
* fix(input): label position and styles * fix(textarea): invalid state
This commit is contained in:
parent
a3cbb5997b
commit
6a6d426b10
8
.changeset/angry-waves-sit.md
Normal file
8
.changeset/angry-waves-sit.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
"@nextui-org/select": patch
|
||||
"@nextui-org/input": patch
|
||||
"@nextui-org/theme": patch
|
||||
---
|
||||
|
||||
- Label position changed for Select and Input, this avoids to break the layout when having long descriptions and no placeholder
|
||||
- Input/Select styles improved, label opacity removed
|
||||
@ -16,8 +16,7 @@ const Input = forwardRef<"input", InputProps>((props, ref) => {
|
||||
endContent,
|
||||
labelPlacement,
|
||||
hasHelper,
|
||||
isLabelOutside,
|
||||
isLabelOutsideAsPlaceholder,
|
||||
isOutsideLeft,
|
||||
shouldLabelBeOutside,
|
||||
errorMessage,
|
||||
getBaseProps,
|
||||
@ -86,7 +85,7 @@ const Input = forwardRef<"input", InputProps>((props, ref) => {
|
||||
return (
|
||||
<div {...getMainWrapperProps()}>
|
||||
<div {...getInputWrapperProps()}>
|
||||
{isLabelOutsideAsPlaceholder ? labelContent : null}
|
||||
{!isOutsideLeft ? labelContent : null}
|
||||
{innerWrapper}
|
||||
</div>
|
||||
{helperWrapper}
|
||||
@ -107,7 +106,6 @@ const Input = forwardRef<"input", InputProps>((props, ref) => {
|
||||
labelPlacement,
|
||||
helperWrapper,
|
||||
shouldLabelBeOutside,
|
||||
isLabelOutsideAsPlaceholder,
|
||||
labelContent,
|
||||
innerWrapper,
|
||||
errorMessage,
|
||||
@ -120,7 +118,7 @@ const Input = forwardRef<"input", InputProps>((props, ref) => {
|
||||
|
||||
return (
|
||||
<Component {...getBaseProps()}>
|
||||
{isLabelOutside ? labelContent : null}
|
||||
{isOutsideLeft ? labelContent : null}
|
||||
{mainWrapper}
|
||||
</Component>
|
||||
);
|
||||
|
||||
@ -195,6 +195,7 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
|
||||
? (!domRef.current.value || domRef.current.value === "" || !inputValue || inputValue === "") &&
|
||||
hasPlaceholder
|
||||
: false;
|
||||
const isOutsideLeft = labelPlacement === "outside-left";
|
||||
|
||||
const hasStartContent = !!startContent;
|
||||
const isLabelOutside = shouldLabelBeOutside
|
||||
@ -445,6 +446,7 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
|
||||
hasHelper,
|
||||
hasStartContent,
|
||||
isLabelOutside,
|
||||
isOutsideLeft,
|
||||
isLabelOutsideAsPlaceholder,
|
||||
shouldLabelBeOutside,
|
||||
shouldLabelBeInside,
|
||||
|
||||
@ -150,17 +150,27 @@ const LabelPlacementTemplate = (args) => (
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3>Without placeholder</h3>
|
||||
<div className="w-full max-w-xl flex flex-row items-end gap-4">
|
||||
<Input {...args} />
|
||||
<Input {...args} labelPlacement="outside" />
|
||||
<Input {...args} labelPlacement="outside-left" />
|
||||
<Input {...args} description="inside" />
|
||||
<Input {...args} description="outside" labelPlacement="outside" />
|
||||
<Input {...args} description="outside-left" labelPlacement="outside-left" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3>With placeholder</h3>
|
||||
<div className="w-full max-w-xl flex flex-row items-end gap-4">
|
||||
<Input {...args} placeholder="Enter your email" />
|
||||
<Input {...args} labelPlacement="outside" placeholder="Enter your email" />
|
||||
<Input {...args} labelPlacement="outside-left" placeholder="Enter your email" />
|
||||
<Input {...args} description="inside" placeholder="Enter your email" />
|
||||
<Input
|
||||
{...args}
|
||||
description="outside"
|
||||
labelPlacement="outside"
|
||||
placeholder="Enter your email"
|
||||
/>
|
||||
<Input
|
||||
{...args}
|
||||
description="outside-left"
|
||||
labelPlacement="outside-left"
|
||||
placeholder="Enter your email"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -28,6 +28,7 @@ function Select<T extends object>(props: Props<T>, ref: ForwardedRef<HTMLSelectE
|
||||
endContent,
|
||||
placeholder,
|
||||
renderValue,
|
||||
isOutsideLeft,
|
||||
disableAnimation,
|
||||
getBaseProps,
|
||||
getLabelProps,
|
||||
@ -37,7 +38,6 @@ function Select<T extends object>(props: Props<T>, ref: ForwardedRef<HTMLSelectE
|
||||
getPopoverProps,
|
||||
getSpinnerProps,
|
||||
getMainWrapperProps,
|
||||
shouldLabelBeOutside,
|
||||
getInnerWrapperProps,
|
||||
getHiddenSelectProps,
|
||||
getHelperWrapperProps,
|
||||
@ -115,10 +115,10 @@ function Select<T extends object>(props: Props<T>, ref: ForwardedRef<HTMLSelectE
|
||||
return (
|
||||
<div {...getBaseProps()}>
|
||||
<HiddenSelect {...getHiddenSelectProps()} />
|
||||
{shouldLabelBeOutside ? labelContent : null}
|
||||
{isOutsideLeft ? labelContent : null}
|
||||
<div {...getMainWrapperProps()}>
|
||||
<Component {...getTriggerProps()}>
|
||||
{!shouldLabelBeOutside ? labelContent : null}
|
||||
{!isOutsideLeft ? labelContent : null}
|
||||
<div {...getInnerWrapperProps()}>
|
||||
{startContent}
|
||||
<span {...getValueProps()}>
|
||||
|
||||
@ -262,6 +262,7 @@ export function useSelect<T extends object>(originalProps: UseSelectProps<T>) {
|
||||
labelPlacement === "outside-left" ||
|
||||
(labelPlacement === "outside" && (hasPlaceholder || !!originalProps.isMultiline));
|
||||
const shouldLabelBeInside = labelPlacement === "inside";
|
||||
const isOutsideLeft = labelPlacement === "outside-left";
|
||||
const isFilled =
|
||||
state.isOpen ||
|
||||
hasPlaceholder ||
|
||||
@ -582,6 +583,7 @@ export function useSelect<T extends object>(originalProps: UseSelectProps<T>) {
|
||||
hasPlaceholder,
|
||||
renderValue,
|
||||
selectionMode,
|
||||
isOutsideLeft,
|
||||
disableAnimation,
|
||||
shouldLabelBeOutside,
|
||||
shouldLabelBeInside,
|
||||
|
||||
@ -33,19 +33,15 @@ const input = tv({
|
||||
"block",
|
||||
"text-small",
|
||||
"text-foreground-500",
|
||||
"opacity-70",
|
||||
"group-data-[filled-within=true]:opacity-100",
|
||||
],
|
||||
mainWrapper: "h-full",
|
||||
inputWrapper:
|
||||
"relative w-full inline-flex tap-highlight-transparent flex-row items-center shadow-sm px-3 gap-3",
|
||||
innerWrapper: "inline-flex w-full items-center h-full box-border",
|
||||
input: [
|
||||
"opacity-70",
|
||||
"w-full font-normal bg-transparent !outline-none placeholder:text-foreground-500 focus-visible:outline-none",
|
||||
"data-[has-start-content=true]:ps-1.5",
|
||||
"data-[has-end-content=true]:pe-1.5",
|
||||
"group-data-[has-value=true]:opacity-100",
|
||||
],
|
||||
clearButton: [
|
||||
"p-2",
|
||||
@ -77,8 +73,6 @@ const input = tv({
|
||||
"data-[hover=true]:bg-default-200",
|
||||
"group-data-[focus=true]:bg-default-100",
|
||||
],
|
||||
input: "placeholder:text-default-foreground",
|
||||
label: "text-default-foreground",
|
||||
},
|
||||
faded: {
|
||||
inputWrapper: [
|
||||
@ -87,8 +81,7 @@ const input = tv({
|
||||
"border-default-200",
|
||||
"data-[hover=true]:border-default-400",
|
||||
],
|
||||
input: "placeholder:text-default-foreground",
|
||||
label: "text-default-foreground",
|
||||
value: "group-data-[has-value=true]:text-default-foreground",
|
||||
},
|
||||
bordered: {
|
||||
inputWrapper: [
|
||||
@ -97,8 +90,6 @@ const input = tv({
|
||||
"data-[hover=true]:border-default-400",
|
||||
"group-data-[focus=true]:border-default-foreground",
|
||||
],
|
||||
input: "placeholder:text-foreground",
|
||||
label: "text-foreground",
|
||||
},
|
||||
underlined: {
|
||||
inputWrapper: [
|
||||
@ -124,14 +115,11 @@ const input = tv({
|
||||
"group-data-[focus=true]:after:w-full",
|
||||
],
|
||||
innerWrapper: "pb-1",
|
||||
input: "placeholder:text-foreground",
|
||||
label: "text-foreground",
|
||||
label: "group-data-[filled-within=true]:text-foreground",
|
||||
},
|
||||
},
|
||||
color: {
|
||||
default: {
|
||||
label: "group-data-[filled-within=true]:opacity-80",
|
||||
},
|
||||
default: {},
|
||||
primary: {},
|
||||
secondary: {},
|
||||
success: {},
|
||||
@ -175,7 +163,6 @@ const input = tv({
|
||||
},
|
||||
labelPlacement: {
|
||||
outside: {
|
||||
label: "text-foreground pb-1.5",
|
||||
mainWrapper: "flex flex-col",
|
||||
},
|
||||
"outside-left": {
|
||||
@ -211,7 +198,7 @@ const input = tv({
|
||||
isInvalid: {
|
||||
true: {
|
||||
label: "!text-danger",
|
||||
input: "placeholder:text-danger text-danger",
|
||||
input: "!placeholder:text-danger !text-danger",
|
||||
},
|
||||
},
|
||||
isRequired: {
|
||||
@ -257,6 +244,13 @@ const input = tv({
|
||||
},
|
||||
compoundVariants: [
|
||||
// flat & color
|
||||
{
|
||||
variant: "flat",
|
||||
color: "default",
|
||||
class: {
|
||||
input: "group-data-[has-value=true]:text-default-foreground",
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: "flat",
|
||||
color: "primary",
|
||||
@ -380,6 +374,13 @@ const input = tv({
|
||||
},
|
||||
},
|
||||
// underlined & color
|
||||
{
|
||||
variant: "underlined",
|
||||
color: "default",
|
||||
class: {
|
||||
input: "group-data-[has-value=true]:text-foreground",
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: "underlined",
|
||||
color: "primary",
|
||||
@ -461,6 +462,22 @@ const input = tv({
|
||||
label: "text-danger",
|
||||
},
|
||||
},
|
||||
// labelPlacement=inside & default
|
||||
{
|
||||
labelPlacement: "inside",
|
||||
color: "default",
|
||||
class: {
|
||||
label: "group-data-[filled-within=true]:text-default-600",
|
||||
},
|
||||
},
|
||||
// labelPlacement=outside & default
|
||||
{
|
||||
labelPlacement: "outside",
|
||||
color: "default",
|
||||
class: {
|
||||
label: "group-data-[filled-within=true]:text-foreground",
|
||||
},
|
||||
},
|
||||
// radius-full & size
|
||||
{
|
||||
radius: "full",
|
||||
|
||||
@ -15,8 +15,6 @@ const select = tv({
|
||||
"text-small",
|
||||
"text-foreground-500",
|
||||
"pointer-events-none",
|
||||
"opacity-70",
|
||||
"group-data-[filled=true]:opacity-100",
|
||||
],
|
||||
mainWrapper: "w-full flex flex-col",
|
||||
trigger:
|
||||
@ -25,13 +23,7 @@ const select = tv({
|
||||
"inline-flex h-full w-[calc(100%_-_theme(spacing.unit-6))] min-h-unit-4 items-center gap-1.5 box-border",
|
||||
selectorIcon: "absolute right-3 w-unit-4 h-unit-4",
|
||||
spinner: "absolute right-3",
|
||||
value: [
|
||||
"font-normal",
|
||||
"w-full",
|
||||
"text-left",
|
||||
"opacity-70",
|
||||
"group-data-[has-value=true]:opacity-100",
|
||||
],
|
||||
value: ["text-foreground-500", "font-normal", "w-full", "text-left"],
|
||||
listboxWrapper: "scroll-py-6 max-h-64 w-full",
|
||||
listbox: "",
|
||||
popoverContent: "w-full p-1 overflow-hidden",
|
||||
@ -47,8 +39,6 @@ const select = tv({
|
||||
"data-[hover=true]:bg-default-200",
|
||||
"group-data-[focus=true]:bg-default-100",
|
||||
],
|
||||
label: "text-default-foreground",
|
||||
value: "placeholder:text-default-foreground",
|
||||
},
|
||||
faded: {
|
||||
trigger: [
|
||||
@ -57,8 +47,7 @@ const select = tv({
|
||||
"border-default-200",
|
||||
"data-[hover=true]:border-default-400",
|
||||
],
|
||||
label: "text-default-foreground",
|
||||
value: "placeholder:text-default-foreground",
|
||||
value: "group-data-[has-value=true]:text-default-foreground",
|
||||
},
|
||||
bordered: {
|
||||
trigger: [
|
||||
@ -69,8 +58,6 @@ const select = tv({
|
||||
"data-[focus=true]:border-default-foreground",
|
||||
"data-[focus=true]:border-default-foreground",
|
||||
],
|
||||
label: "text-foreground",
|
||||
value: "placeholder:text-foreground",
|
||||
},
|
||||
underlined: {
|
||||
trigger: [
|
||||
@ -96,14 +83,11 @@ const select = tv({
|
||||
"data-[open=true]:after:w-full",
|
||||
"data-[focus=true]:after:w-full",
|
||||
],
|
||||
label: "text-foreground",
|
||||
value: "placeholder:text-foreground",
|
||||
label: "group-data-[filled=true]:text-foreground",
|
||||
},
|
||||
},
|
||||
color: {
|
||||
default: {
|
||||
label: "group-data-[filled=true]:opacity-80",
|
||||
},
|
||||
default: {},
|
||||
primary: {},
|
||||
secondary: {},
|
||||
success: {},
|
||||
@ -145,11 +129,10 @@ const select = tv({
|
||||
labelPlacement: {
|
||||
outside: {
|
||||
base: "flex flex-col",
|
||||
label: "text-foreground pb-1.5",
|
||||
},
|
||||
"outside-left": {
|
||||
base: "flex-row items-center flex-nowrap items-start",
|
||||
label: "relative text-foreground pr-2",
|
||||
label: "relative pr-2 text-foreground",
|
||||
},
|
||||
inside: {
|
||||
label: "text-tiny cursor-pointer",
|
||||
@ -228,6 +211,13 @@ const select = tv({
|
||||
},
|
||||
compoundVariants: [
|
||||
// flat & color
|
||||
{
|
||||
variant: "flat",
|
||||
color: "default",
|
||||
class: {
|
||||
value: "group-data-[has-value=true]:text-default-foreground",
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: "flat",
|
||||
color: "primary",
|
||||
@ -343,6 +333,14 @@ const select = tv({
|
||||
},
|
||||
},
|
||||
// underlined & color
|
||||
// underlined & color
|
||||
{
|
||||
variant: "underlined",
|
||||
color: "default",
|
||||
class: {
|
||||
value: "group-data-[has-value=true]:text-foreground",
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: "underlined",
|
||||
color: "primary",
|
||||
@ -424,6 +422,22 @@ const select = tv({
|
||||
label: "text-danger",
|
||||
},
|
||||
},
|
||||
// labelPlacement=outside & default
|
||||
{
|
||||
labelPlacement: "inside",
|
||||
color: "default",
|
||||
class: {
|
||||
label: "group-data-[filled=true]:text-default-600",
|
||||
},
|
||||
},
|
||||
// labelPlacement=outside & default
|
||||
{
|
||||
labelPlacement: "outside",
|
||||
color: "default",
|
||||
class: {
|
||||
label: "group-data-[filled=true]:text-foreground",
|
||||
},
|
||||
},
|
||||
// radius-full & size
|
||||
{
|
||||
radius: "full",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user