feat: add common sets of props for inputs

main
Juan Olvera 11 months ago
parent ccfdecb318
commit 8449c8dd84

@ -0,0 +1,8 @@
type InputProps = {
label: string;
hideLabel?: boolean;
helpText?: string;
hasError?: boolean;
};
export type { InputProps };

@ -0,0 +1,3 @@
import * as T from "./Common.types";
export type { T };

@ -1,7 +1,7 @@
import * as React from "react";
import { match, P } from "ts-pattern";
import * as T from "./Divider.types";
import { Modal } from "../Box";
import { Box } from "../Box";
import { cx } from "../../utils";
import { dividerStyles } from "./Divider.styles";
@ -16,7 +16,7 @@ const Divider = React.forwardRef<
return match({ border })
.with({ border: true }, () => (
<div {...props} className={classes}>
<Modal className={cx(["bg-mono-border", "h-[2px]"])} />
<Box className={cx(["bg-mono-border", "h-[2px]"])} />
</div>
))
.otherwise(() => <div {...props} className={classes} ref={forwardedRef} />);

@ -0,0 +1,35 @@
import * as React from "react";
import { Primitive } from "@radix-ui/react-primitive";
import { cva, VariantProps } from "class-variance-authority";
import { cx } from "../utils";
import * as Common from "./Common";
type HelpTextElement = React.ElementRef<typeof Primitive.p>;
type HelpTextProps = React.ComponentPropsWithoutRef<typeof Primitive.p> &
VariantProps<typeof styles> &
Pick<Common.T.InputProps, "hasError"> & {};
const styles = cva(["mt-2", "text-sm", "text-mono-text"], {
variants: {
hasError: {
true: ["text-mono-error"],
},
},
defaultVariants: {
hasError: false,
},
});
const HelpText = React.forwardRef<HelpTextElement, HelpTextProps>(
({ hasError, children, ...props }, forwardedRef) => {
const classes = cx(styles({ hasError }));
return (
<p {...props} className={classes} ref={forwardedRef}>
{children}
</p>
);
}
);
export { HelpText };

@ -4,6 +4,7 @@ import { NumericFormat } from "react-number-format";
import type * as T from "./Input.types";
import { Box } from "../Box";
import { Label } from "../Label";
import { HelpText } from "../HelpText";
import { cx } from "../../utils";
import { inputStyles } from "./Input.styles";
import { match, P } from "ts-pattern";
@ -93,13 +94,7 @@ const Input = React.forwardRef<HTMLInputElement, T.InputProps>(
</Box>
{match(helpText)
.with(P.not(P.nullish), () => (
<p
className={cx(["mt-2", "text-sm", "text-mono-text"], {
"text-mono-error": hasError,
})}
>
{helpText}
</p>
<HelpText hasError={hasError}>{helpText}</HelpText>
))
.otherwise(() => null)}
</Box>

@ -18,7 +18,42 @@ const options = [
export const Default: Story = {
render: () => (
<Select placeholder="Select a fruit" tabIndex={0}>
<Select label="Fruits" placeholder="Select a fruit" tabIndex={0}>
{options.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</Select>
),
};
export const HelpText: Story = {
render: () => (
<Select
label="Fruits"
placeholder="Select a fruit"
tabIndex={0}
helpText="Select from an approved list of fruits."
>
{options.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</Select>
),
};
export const WithError: Story = {
render: () => (
<Select
label="Fruits"
placeholder="Select a fruit"
tabIndex={0}
hasError
helpText="You must select one fruit."
>
{options.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}

@ -63,6 +63,9 @@ const selectStyles = cva(base, {
fullWidth: {
true: "w-full",
},
hasError: {
true: "border-mono-error",
},
},
defaultVariants: {
fullWidth: false,

@ -1,15 +1,32 @@
import * as React from "react";
import * as $ from "@radix-ui/react-select";
import { match, P } from "ts-pattern";
import { FaCheck, FaChevronDown, FaChevronUp } from "react-icons/fa";
import * as T from "./Select.types";
import * as styles from "./Select.styles";
import { cx } from "../../utils";
import { Box } from "../Box";
import { Label } from "../Label";
import { HelpText } from "../HelpText";
const Select = React.forwardRef<T.SelectElement, T.SelectProps>(
({ hideLabel = false, fullWidth, children, className, ...props }, ref) => {
const classes = cx([styles.selectStyles({ fullWidth })], className);
(
{
label,
hideLabel = false,
helpText,
fullWidth,
hasError,
children,
className,
...props
},
ref
) => {
const classes = cx(
[styles.selectStyles({ fullWidth, hasError })],
className
);
return (
<Box className={cx(["relative"])}>
<Label
@ -18,7 +35,7 @@ const Select = React.forwardRef<T.SelectElement, T.SelectProps>(
"sr-only": hideLabel,
})}
>
Select
{label}
</Label>
<Box className={cx(["mt-1"])}>
<$.Root>
@ -46,6 +63,11 @@ const Select = React.forwardRef<T.SelectElement, T.SelectProps>(
</$.Portal>
</$.Root>
</Box>
{match(helpText)
.with(P.not(P.nullish), (helpText) => (
<HelpText hasError={hasError}>{helpText}</HelpText>
))
.otherwise(() => null)}
</Box>
);
}

@ -1,5 +1,6 @@
import * as React from "react";
import * as $ from "@radix-ui/react-select";
import * as Common from "../Common";
import { VariantProps } from "class-variance-authority";
import { selectStyles } from "./Select.styles";
@ -16,9 +17,8 @@ type SelectSection = {
type SelectElement = React.ElementRef<typeof $.Trigger>;
type SelectProps = React.ComponentPropsWithoutRef<typeof $.Trigger> &
VariantProps<typeof selectStyles> & {
hideLabel?: boolean;
};
VariantProps<typeof selectStyles> &
Common.T.InputProps & {};
type SelectItemElement = React.ElementRef<typeof $.Item>;

Loading…
Cancel
Save