Skip to content

Commit

Permalink
feat(TextInput): adding size prop (#693)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Introduced a new `size` property for the `TextInput` component,
allowing users to select from multiple size options: "xs," "sm," "md,"
"lg," and "xl."
	- Default size is set to "md" if not specified.

- **Bug Fixes**
- Enhanced rendering tests for the `TextInput` component to ensure
proper styling based on selected size.

- **Documentation**
- Updated documentation to reflect the new `size` property and its
options.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
aversini authored Sep 26, 2024
1 parent c2f4564 commit 397d22f
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 7 deletions.
5 changes: 5 additions & 0 deletions packages/documentation/src/Form/TextInput.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default {
className: "",
mode: "system",
labelHidden: false,
size: "md",
},
argTypes: {
mode: {
Expand All @@ -30,6 +31,10 @@ export default {
options: ["dark", "light", "system", "alt-system"],
control: { type: "radio" },
},
size: {
options: ["xs", "sm", "md", "lg", "xl"],
control: { type: "radio" },
},
},
};

Expand Down
2 changes: 2 additions & 0 deletions packages/ui-textinput/src/components/TextInput/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(

rightElement,
spacing,
size = "md",

...extraProps
},
Expand All @@ -49,6 +50,7 @@ export const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(
noBorder,
spacing,
mode,
size,
});

/* c8 ignore start - ResizeObserver is tough to test... */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { SpacingProps } from "@versini/ui-private/dist/utilities";

export type Size = "xs" | "sm" | "md" | "lg" | "xl";

export type CommonTextInputProps = {
/**
* The label of the TextInput.
Expand Down Expand Up @@ -49,8 +51,12 @@ export type CommonTextInputProps = {
* @default false
*/
raw?: boolean;
/**
* Controls input height and horizontal padding, 'md' by default
*/
size?: Size;
} & SpacingProps &
React.InputHTMLAttributes<HTMLInputElement>;
Omit<React.InputHTMLAttributes<HTMLInputElement>, "size">;

export type TextInputProps = {
/**
Expand All @@ -59,8 +65,7 @@ export type TextInputProps = {
* elements, such a Button.
*/
rightElement?: React.ReactElement;
} & CommonTextInputProps &
React.InputHTMLAttributes<HTMLInputElement>;
} & CommonTextInputProps;

export type TextInputMaskProps = {
/**
Expand All @@ -78,5 +83,4 @@ export type TextInputMaskProps = {
* Callback fired when the user blurs out of the TextInputMask.
*/
onTextInputMaskBlur?: () => void;
} & CommonTextInputProps &
React.InputHTMLAttributes<HTMLInputElement>;
} & CommonTextInputProps;
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,74 @@ describe("TextInput (exceptions)", () => {
});
});

describe("TextInput sizes", () => {
it.each`
size | description
${"xs"} | ${"extra small"}
${"sm"} | ${"small"}
${"md"} | ${"medium"}
${"lg"} | ${"large"}
${"xl"} | ${"extra large"}
`("should render a text input with size $description", async ({ size }) => {
render(<TextInput label="hello world" name="toto" size={size} />);
const label = await screen.findAllByText("hello world");
const input = await screen.findByRole("textbox");

expect(label[0]?.className).toContain("sr-only");
expectToHaveClasses(label[1], [
"absolute",
"cursor-text",
"font-medium",
"text-copy-dark",
]);
let heightClass = "",
paddingClass = "";
switch (size) {
case "xs":
heightClass = "h-8";
paddingClass = "px-2";
break;
case "sm":
heightClass = "h-10";
paddingClass = "px-3";
break;
case "md":
heightClass = "h-12";
paddingClass = "px-4";
break;
case "lg":
heightClass = "h-14";
paddingClass = "px-4";
break;
case "xl":
heightClass = "h-16";
paddingClass = "px-4";
break;

default:
heightClass = "h-12";
paddingClass = "px-4";
break;
}
expectToHaveClasses(input, [
TEXT_INPUT_CLASSNAME,
"bg-surface-lighter",
"border-2",
"border-border-dark",
"caret-copy-dark",
"focus:outline-2",
"focus:outline-focus-dark",
"focus:outline-offset-2",
"focus:outline",
heightClass,
paddingClass,
"rounded-md",
"text-base",
"text-copy-dark",
]);
});
});

describe("TextInput modifiers", () => {
it("should render a dark or light (system) text input", async () => {
render(<TextInput label="hello world" name="toto" />);
Expand Down Expand Up @@ -137,7 +205,6 @@ describe("TextInput modifiers", () => {
/>,
);
const label = await screen.findAllByText("hello world");
screen.debug(label);
expect(label.length).toBe(1);
});

Expand Down
26 changes: 25 additions & 1 deletion packages/ui-textinput/src/components/TextInput/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
TEXT_INPUT_HELPER_TEXT_CLASSNAME,
TEXT_INPUT_WRAPPER_CLASSNAME,
} from "../../common/constants";
import type { Size } from "./TextInputTypes";

type getTextInputClassesProps = {
disabled: boolean;
Expand All @@ -15,6 +16,7 @@ type getTextInputClassesProps = {
mode: "dark" | "light" | "system" | "alt-system";
noBorder: boolean;
raw: boolean;
size: Size;

className?: string;
inputClassName?: string;
Expand Down Expand Up @@ -151,6 +153,7 @@ export const getTextInputClasses = ({
spacing,
mode,
focusMode,
size,
}: getTextInputClassesProps) => {
const wrapper = raw
? className
Expand All @@ -161,12 +164,33 @@ export const getTextInputClasses = ({
getSpacing(spacing),
);

let sizeClass = "";
switch (size) {
case "xs":
sizeClass = "h-8 px-2";
break;
case "sm":
sizeClass = "h-10 px-3";
break;
case "lg":
sizeClass = "h-14 px-4";
break;
case "xl":
sizeClass = "h-16 px-4";
break;

default:
sizeClass = "h-12 px-4";
break;
}

const input = raw
? clsx(inputClassName)
: clsx(
TEXT_INPUT_CLASSNAME,
inputClassName,
"h-12 rounded-md px-4 text-base",
sizeClass,
"rounded-md text-base",
getTextInputColorClasses({ mode }),
getTextInputFocusClasses({ focusMode }),
getTextInputBorderClasses({ noBorder, error }),
Expand Down

0 comments on commit 397d22f

Please sign in to comment.