UI: init InputError component
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import { createEffect, JSX, splitProps } from "solid-js";
|
import { JSX, Ref, Show, splitProps } from "solid-js";
|
||||||
import Icon, { IconVariant } from "../icon";
|
import Icon, { IconVariant } from "../icon";
|
||||||
import { Typography } from "../Typography";
|
import { Typography, TypographyProps } from "../Typography";
|
||||||
|
|
||||||
type Variants = "outlined" | "ghost";
|
type Variants = "outlined" | "ghost";
|
||||||
interface InputBaseProps {
|
interface InputBaseProps {
|
||||||
@@ -17,6 +17,9 @@ interface InputBaseProps {
|
|||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
error?: boolean;
|
error?: boolean;
|
||||||
icon?: IconVariant;
|
icon?: IconVariant;
|
||||||
|
/** Overrides the input element */
|
||||||
|
inputElem?: JSX.Element;
|
||||||
|
divRef?: Ref<HTMLDivElement>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const variantBorder: Record<Variants, string> = {
|
const variantBorder: Record<Variants, string> = {
|
||||||
@@ -27,11 +30,7 @@ const variantBorder: Record<Variants, string> = {
|
|||||||
const fgStateClasses = cx("aria-disabled:fg-def-4 aria-readonly:fg-def-3");
|
const fgStateClasses = cx("aria-disabled:fg-def-4 aria-readonly:fg-def-3");
|
||||||
|
|
||||||
export const InputBase = (props: InputBaseProps) => {
|
export const InputBase = (props: InputBaseProps) => {
|
||||||
const [, inputProps] = splitProps(props, ["class"]);
|
const [internal, inputProps] = splitProps(props, ["class", "divRef"]);
|
||||||
|
|
||||||
createEffect(() => {
|
|
||||||
console.log("InputBase", props.value, props.variant);
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cx(
|
class={cx(
|
||||||
@@ -56,7 +55,7 @@ export const InputBase = (props: InputBaseProps) => {
|
|||||||
|
|
||||||
// Cursor
|
// Cursor
|
||||||
"aria-readonly:cursor-no-drop",
|
"aria-readonly:cursor-no-drop",
|
||||||
props.class,
|
props.class
|
||||||
)}
|
)}
|
||||||
classList={{
|
classList={{
|
||||||
[cx("!border !border-semantic-1 !outline-semantic-1")]: !!props.error,
|
[cx("!border !border-semantic-1 !outline-semantic-1")]: !!props.error,
|
||||||
@@ -66,6 +65,7 @@ export const InputBase = (props: InputBaseProps) => {
|
|||||||
aria-readonly={props.readonly}
|
aria-readonly={props.readonly}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
role="textbox"
|
role="textbox"
|
||||||
|
ref={internal.divRef}
|
||||||
>
|
>
|
||||||
{props.icon && (
|
{props.icon && (
|
||||||
<i
|
<i
|
||||||
@@ -77,32 +77,39 @@ export const InputBase = (props: InputBaseProps) => {
|
|||||||
<Icon icon={props.icon} font-size="inherit" color="inherit" />
|
<Icon icon={props.icon} font-size="inherit" color="inherit" />
|
||||||
</i>
|
</i>
|
||||||
)}
|
)}
|
||||||
<input
|
<Show when={!props.inputElem} fallback={props.inputElem}>
|
||||||
tabIndex={-1}
|
<input
|
||||||
class="w-full bg-transparent outline-none aria-readonly:cursor-no-drop"
|
tabIndex={-1}
|
||||||
value={props.value}
|
class="w-full bg-transparent outline-none"
|
||||||
type={props.type ? props.type : "text"}
|
value={props.value}
|
||||||
readOnly={props.readonly}
|
type={props.type ? props.type : "text"}
|
||||||
placeholder={`${props.placeholder || ""}`}
|
readOnly={props.readonly}
|
||||||
required={props.required}
|
placeholder={`${props.placeholder || ""}`}
|
||||||
disabled={props.disabled}
|
required={props.required}
|
||||||
aria-invalid={props.error}
|
disabled={props.disabled}
|
||||||
aria-disabled={props.disabled}
|
aria-invalid={props.error}
|
||||||
aria-readonly={props.readonly}
|
aria-disabled={props.disabled}
|
||||||
{...inputProps}
|
aria-readonly={props.readonly}
|
||||||
/>
|
{...inputProps}
|
||||||
|
/>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface InputLabelProps extends JSX.LabelHTMLAttributes<HTMLLabelElement> {
|
export interface InputLabelProps
|
||||||
|
extends JSX.LabelHTMLAttributes<HTMLLabelElement> {
|
||||||
description?: string;
|
description?: string;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
error?: boolean;
|
error?: boolean;
|
||||||
help?: string;
|
help?: string;
|
||||||
|
labelAction?: JSX.Element;
|
||||||
}
|
}
|
||||||
export const InputLabel = (props: InputLabelProps) => {
|
export const InputLabel = (props: InputLabelProps) => {
|
||||||
const [labelProps, forwardProps] = splitProps(props, ["class"]);
|
const [labelProps, forwardProps] = splitProps(props, [
|
||||||
|
"class",
|
||||||
|
"labelAction",
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
class={cx("flex items-center gap-1", labelProps.class)}
|
class={cx("flex items-center gap-1", labelProps.class)}
|
||||||
@@ -112,7 +119,7 @@ export const InputLabel = (props: InputLabelProps) => {
|
|||||||
hierarchy="label"
|
hierarchy="label"
|
||||||
size="default"
|
size="default"
|
||||||
weight="bold"
|
weight="bold"
|
||||||
class="!fg-def-1"
|
class="inline-flex gap-1 align-middle !fg-def-1"
|
||||||
classList={{
|
classList={{
|
||||||
[cx("!fg-semantic-1")]: !!props.error,
|
[cx("!fg-semantic-1")]: !!props.error,
|
||||||
}}
|
}}
|
||||||
@@ -138,9 +145,33 @@ export const InputLabel = (props: InputLabelProps) => {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
{props.labelAction}
|
||||||
<Typography hierarchy="body" size="xs" weight="normal" color="secondary">
|
<Typography hierarchy="body" size="xs" weight="normal" color="secondary">
|
||||||
{props.description}
|
{props.description}
|
||||||
</Typography>
|
</Typography>
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface InputErrorProps {
|
||||||
|
error: string;
|
||||||
|
typographyProps?: TypographyProps;
|
||||||
|
}
|
||||||
|
export const InputError = (props: InputErrorProps) => {
|
||||||
|
const [typoClasses, rest] = splitProps(
|
||||||
|
props.typographyProps || { class: "" },
|
||||||
|
["class"]
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<Typography
|
||||||
|
hierarchy="body"
|
||||||
|
// @ts-expect-error: Dependent type is to complex to check how it is coupled to the override for now
|
||||||
|
size="xxs"
|
||||||
|
weight="medium"
|
||||||
|
class={cx("col-span-full px-1 !fg-semantic-4", typoClasses)}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{props.error}
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user