Skip to content

Commit

Permalink
fix(textarea): styles issues and start/end content props added (#1923)
Browse files Browse the repository at this point in the history
* fix(textarea): styles issues and start/end content props added

* chore(textarea): multiple rows prop renamed
  • Loading branch information
jrgarciadev authored Nov 8, 2023
1 parent 1149345 commit 9189b3f
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 38 deletions.
7 changes: 7 additions & 0 deletions .changeset/fresh-gorillas-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@nextui-org/shared-icons": patch
"@nextui-org/input": patch
"@nextui-org/theme": patch
---

Textarea style rounded full styles issues fixed, start and end content props added
66 changes: 34 additions & 32 deletions apps/docs/content/docs/components/textarea.mdx

Large diffs are not rendered by default.

29 changes: 25 additions & 4 deletions packages/components/input/src/textarea.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {dataAttr} from "@nextui-org/shared-utils";
import {forwardRef} from "@nextui-org/system";
import {mergeProps} from "@react-aria/utils";
import {useState} from "react";
import {useMemo, useState} from "react";
import TextareaAutosize from "react-textarea-autosize";

import {UseInputProps, useInput} from "./use-input";
Expand All @@ -26,7 +26,7 @@ export type TextareaHeightChangeMeta = {
rowHeight: number;
};

export interface TextAreaProps extends Omit<UseInputProps, OmittedInputProps> {
export interface TextAreaProps extends Omit<UseInputProps<HTMLTextAreaElement>, OmittedInputProps> {
/**
* Whether the textarea should automatically grow vertically to accomodate content.
* @default false
Expand Down Expand Up @@ -75,23 +75,30 @@ const Textarea = forwardRef<"textarea", TextAreaProps>(
Component,
label,
description,
startContent,
endContent,
shouldLabelBeOutside,
shouldLabelBeInside,
errorMessage,
getBaseProps,
getLabelProps,
getInputProps,
getInnerWrapperProps,
getInputWrapperProps,
getHelperWrapperProps,
getDescriptionProps,
getErrorMessageProps,
} = useInput<HTMLTextAreaElement>({...otherProps, ref, isMultiline: true});

const [hasMultipleRows, setIsHasMultipleRows] = useState(minRows > 1);
const [isLimitReached, setIsLimitReached] = useState(false);
const labelContent = <label {...getLabelProps()}>{label}</label>;
const inputProps = getInputProps();

const handleHeightChange = (height: number, meta: TextareaHeightChangeMeta) => {
if (minRows === 1) {
setIsHasMultipleRows(height >= meta.rowHeight * 2);
}
if (maxRows > minRows) {
const limitReached = height >= maxRows * meta.rowHeight;

Expand All @@ -115,12 +122,26 @@ const Textarea = forwardRef<"textarea", TextAreaProps>(
/>
);

const innerWrapper = useMemo(() => {
if (startContent || endContent) {
return (
<div {...getInnerWrapperProps()}>
{startContent}
{content}
{endContent}
</div>
);
}

return <div {...getInnerWrapperProps()}>{content}</div>;
}, [startContent, inputProps, endContent, getInnerWrapperProps]);

return (
<Component {...getBaseProps()}>
{shouldLabelBeOutside ? labelContent : null}
<div {...getInputWrapperProps()}>
<div {...getInputWrapperProps()} data-has-multiple-rows={dataAttr(hasMultipleRows)}>
{shouldLabelBeInside ? labelContent : null}
{content}
{innerWrapper}
</div>
<div {...getHelperWrapperProps()}>
{errorMessage ? (
Expand Down
68 changes: 68 additions & 0 deletions packages/components/input/stories/textarea.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import {Meta} from "@storybook/react";
import {input} from "@nextui-org/theme";
import {SendFilledIcon, PlusFilledIcon} from "@nextui-org/shared-icons";

import {Textarea, TextAreaProps} from "../src";

Expand Down Expand Up @@ -71,6 +72,17 @@ const Template = (args: TextAreaProps) => (
</div>
);

const ControlledTemplate = (args: TextAreaProps) => {
const [value, setValue] = React.useState("");

return (
<div className="w-full flex-col gap-2 max-w-[440px]">
<Textarea {...args} value={value} onValueChange={setValue} />
<p className="text-default-500 text-small">Textarea value: {value}</p>
</div>
);
};

const MinRowsTemplate = (args: TextAreaProps) => (
<div className="w-full max-w-xl flex flex-row gap-4">
<Textarea {...args} description="Default minRows is 3" />
Expand All @@ -95,6 +107,23 @@ export const Default = {
},
};

export const FullRounded = {
render: Template,

args: {
...defaultProps,
minRows: 1,
label: null,
classNames: {
input: "py-1",
},
"aria-label": "Description",
placeholder: "Enter your description",
variant: "bordered",
radius: "full",
},
};

export const Required = {
render: Template,

Expand Down Expand Up @@ -126,6 +155,45 @@ export const ReadOnly = {
},
};

export const WithStartContent = {
render: Template,

args: {
...defaultProps,
startContent: <PlusFilledIcon className="text-xl" />,
},
};

export const WithEndContent = {
render: Template,

args: {
...defaultProps,
minRows: 1,
label: null,
endContent: (
<div className="p-1">
<SendFilledIcon className="text-xl" />
</div>
),
classNames: {
input: "py-1",
},
"aria-label": "Description",
placeholder: "Enter your description",
variant: "bordered",
radius: "full",
},
};

export const Controlled = {
render: ControlledTemplate,

args: {
...defaultProps,
},
};

export const MinRows = {
render: MinRowsTemplate,

Expand Down
22 changes: 20 additions & 2 deletions packages/core/theme/src/components/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const input = tv({
// focus ring
...dataFocusVisibleClasses,
],
helperWrapper: "p-1 flex relative flex-col gap-1.5",
helperWrapper: "hidden group-data-[has-helper=true]:flex p-1 relative flex-col gap-1.5",
description: "text-tiny text-foreground-400",
errorMessage: "text-tiny text-danger",
},
Expand Down Expand Up @@ -210,7 +210,8 @@ const input = tv({
true: {
label: "relative",
inputWrapper: "!h-auto",
input: "resize-none py-2 data-[hide-scroll=true]:scrollbar-hide",
innerWrapper: "items-start group-data-[has-label=true]:items-start",
input: "resize-none data-[hide-scroll=true]:scrollbar-hide",
},
},
disableAnimation: {
Expand Down Expand Up @@ -812,6 +813,14 @@ const input = tv({
label: "group-data-[has-helper=true]:pt-4",
},
},
// labelPlacement=[outside, outside-left] & isMultiline
{
labelPlacement: ["outside", "outside-left"],
isMultiline: true,
class: {
inputWrapper: "py-2",
},
},
// isMultiline & labelPlacement="outside"
{
labelPlacement: "outside",
Expand All @@ -825,6 +834,7 @@ const input = tv({
labelPlacement: "inside",
isMultiline: true,
class: {
label: "pb-0.5",
input: "pt-0",
},
},
Expand All @@ -843,6 +853,14 @@ const input = tv({
label: ["pe-2", "max-w-full", "text-ellipsis", "overflow-hidden"],
},
},
// isMultiline & radius=full
{
isMultiline: true,
radius: "full",
class: {
inputWrapper: "data-[has-multiple-rows=true]:rounded-large",
},
},
],
});

Expand Down
2 changes: 2 additions & 0 deletions packages/utilities/shared-icons/src/bold/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export * from "./pet";
export * from "./volume-high";
export * from "./volume-low";
export * from "./shopping-cart";
export * from "./send";
export * from "./plus";
21 changes: 21 additions & 0 deletions packages/utilities/shared-icons/src/bold/plus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {IconSvgProps} from "../types";

export const PlusFilledIcon = (props: IconSvgProps) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
clipRule="evenodd"
d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22ZM12.75 9C12.75 8.58579 12.4142 8.25 12 8.25C11.5858 8.25 11.25 8.58579 11.25 9L11.25 11.25H9C8.58579 11.25 8.25 11.5858 8.25 12C8.25 12.4142 8.58579 12.75 9 12.75H11.25V15C11.25 15.4142 11.5858 15.75 12 15.75C12.4142 15.75 12.75 15.4142 12.75 15L12.75 12.75H15C15.4142 12.75 15.75 12.4142 15.75 12C15.75 11.5858 15.4142 11.25 15 11.25H12.75V9Z"
fill="currentColor"
fillRule="evenodd"
/>
</svg>
);
28 changes: 28 additions & 0 deletions packages/utilities/shared-icons/src/bold/send.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {IconSvgProps} from "../types";

export const SendFilledIcon = (props: IconSvgProps) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<g clipPath="url(#clip0_2703_16)">
<path
clipRule="evenodd"
d="M15.9518 16.8594L11.0969 19.2869C7.67397 20.9984 5.96247 21.8541 4.97025 21.5914C4.02634 21.3415 3.28914 20.6043 3.03925 19.6604C2.77657 18.6682 3.63232 16.9567 5.34381 13.5337C5.61861 12.9841 5.75602 12.7093 5.81297 12.4217C5.86816 12.143 5.86816 11.8561 5.81297 11.5774C5.75602 11.2898 5.61862 11.015 5.34381 10.4654C3.63232 7.0424 2.77657 5.3309 3.03925 4.33869C3.28914 3.39478 4.02635 2.65757 4.97025 2.40768C5.96247 2.145 7.67396 3.00075 11.097 4.71225L15.9518 7.13967C20.1929 9.26023 22.3135 10.3205 22.3135 11.9996C22.3135 13.6786 20.1929 14.7389 15.9518 16.8594ZM10.5157 11.9627C10.518 11.5485 10.8556 11.2146 11.2698 11.2169L17.1916 11.2497C17.6058 11.252 17.9397 11.5896 17.9374 12.0038C17.9351 12.418 17.5975 12.7519 17.1833 12.7497L11.2615 12.7168C10.8473 12.7145 10.5134 12.3769 10.5157 11.9627Z"
fill="currentColor"
fillRule="evenodd"
/>
</g>
<defs>
<clipPath id="clip0_2703_16">
<rect fill="white" height="24" width="24" />
</clipPath>
</defs>
</svg>
);

2 comments on commit 9189b3f

@vercel
Copy link

@vercel vercel bot commented on 9189b3f Nov 8, 2023

Choose a reason for hiding this comment

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

@vercel
Copy link

@vercel vercel bot commented on 9189b3f Nov 8, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.