-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
359 additions
and
133 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import { DateInput } from "../DateInput"; | ||
|
||
const meta = { | ||
title: "Inputs/DateInput", | ||
component: DateInput, | ||
} satisfies Meta<typeof DateInput>; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof meta>; | ||
|
||
export const Default: Story = { | ||
args: { | ||
onChange: (date: string) => console.log(date), | ||
}, | ||
}; | ||
export const WithLabel: Story = { | ||
args: { | ||
label: "Date", | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import "../../../style/baseTheme.scss"; | ||
|
||
interface Props { | ||
value?: string; | ||
label?: string; | ||
onChange?: (newDate: string) => void; | ||
className?: string; | ||
id?: string; | ||
} | ||
|
||
const DateInput: React.FC<Props> = ({ label, value, onChange, className, id }) => { | ||
const handleDateChange = (e: { target: { value: string } }) => { | ||
const selectedDate = e.target.value; | ||
onChange?.(selectedDate); | ||
}; | ||
|
||
const formatValue = (value: string | undefined) => { | ||
// if not value, return the actual date | ||
if (!value) return new Date().toISOString().split("T")[0]; | ||
|
||
// take the date string and format it to yyyy-mm-dd | ||
// if the value is empty, return an empty string | ||
// if the value is not empty, return the formatted value | ||
return new Date(value).toISOString().split("T")[0]; | ||
}; | ||
|
||
return ( | ||
<div className="position-relative flex flex-col w-fit px-2 py-1 transition-all ring-1 ring-primary border-primary/50 rounded-lg focus-within:shadow-lg hover:ring-2 focus-within:ring-accent/50 "> | ||
{label && ( | ||
<label className="text-xs" htmlFor="date"> | ||
{label} | ||
</label> | ||
)} | ||
<input | ||
type="date" | ||
name="date" | ||
id={id} | ||
className={` | ||
bg-transparent | ||
outline-none | ||
${className}`} | ||
value={formatValue(value)} | ||
onChange={handleDateChange} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default DateInput; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as DateInput } from "./DateInput"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import { Field } from "../Field"; | ||
|
||
const meta = { | ||
title: "Inputs/Field", | ||
component: Field, | ||
} satisfies Meta<typeof Field>; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof meta>; | ||
|
||
export const Default: Story = { | ||
args: { | ||
label: "Input", | ||
}, | ||
}; | ||
export const WithValue: Story = { | ||
args: { | ||
label: "Input", | ||
value: "This is a value", | ||
}, | ||
}; | ||
export const NumberType: Story = { | ||
args: { | ||
label: "Number Input", | ||
type: "number", | ||
}, | ||
}; | ||
export const HelperText: Story = { | ||
args: { | ||
label: "Input", | ||
helperText: "This is a helper text", | ||
}, | ||
}; | ||
export const InputWithError: Story = { | ||
args: { | ||
label: "Input", | ||
error: "This is an error", | ||
}, | ||
}; | ||
export const InputWithHelperTextAndError: Story = { | ||
args: { | ||
label: "Input", | ||
helperText: "This is a helper text", | ||
error: "This is an error", | ||
}, | ||
}; | ||
export const Disabled: Story = { | ||
args: { | ||
disabled: true, | ||
}, | ||
}; | ||
export const MaxLength: Story = { | ||
args: { | ||
maxLength: 10, | ||
}, | ||
}; | ||
export const Multiline: Story = { | ||
args: { | ||
multiline: true, | ||
}, | ||
}; | ||
export const MultilineWithLabels: Story = { | ||
args: { | ||
label: "Input", | ||
multiline: true, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import { ChangeEvent } from "react"; | ||
import { containerStyles, inputStyles, labelStyles } from "./Styled"; | ||
import React from "react"; | ||
interface Props<T> { | ||
label?: string; | ||
name?: string; | ||
type?: "text" | "number" | "password" | "email" | "date" | "time" | "url" | "search" | "tel"; | ||
value?: T; | ||
multiline?: boolean; | ||
onChange?: (value: T) => void; | ||
error?: string; | ||
className?: string; | ||
disabled?: boolean; | ||
required?: boolean; | ||
helperText?: string; | ||
maxLength?: number; | ||
fullWidth?: boolean; | ||
size?: "small" | "normal" | "large"; | ||
props?: Omit<React.InputHTMLAttributes<HTMLInputElement>, keyof Props<T>>; | ||
} | ||
|
||
const Field = <T extends string | number>({ | ||
label, | ||
value = undefined, | ||
onChange, | ||
disabled, | ||
required, | ||
type = "text", | ||
error, | ||
multiline, | ||
helperText, | ||
className, | ||
maxLength, | ||
fullWidth = false, | ||
size = "normal", | ||
...props | ||
}: Props<T>) => { | ||
const handleChange = (e: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>) => { | ||
const inputValue = e.target.value; | ||
let newValue: T = inputValue as T; | ||
if (!onChange) return; | ||
|
||
if (type === "number") { | ||
newValue = Number(inputValue) as T; | ||
if (isNaN(newValue as number)) { | ||
newValue = "" as T; | ||
} | ||
} | ||
if (!newValue) return; | ||
|
||
onChange(newValue); | ||
}; | ||
const [focused, setFocused] = React.useState(false); | ||
const hasValue = | ||
typeof value === "number" || | ||
type === "date" || | ||
type === "time" || | ||
type === "number" || | ||
Boolean(value?.length); | ||
return ( | ||
<div className={containerStyles()}> | ||
{multiline ? ( | ||
<textarea | ||
onFocus={() => setFocused(true)} | ||
rows={5} | ||
disabled={disabled ?? false} | ||
maxLength={maxLength} | ||
required={required} | ||
defaultValue={value ?? ""} | ||
onChange={handleChange} | ||
className={inputStyles() + className} | ||
/> | ||
) : ( | ||
<input | ||
{...(props as Omit<React.InputHTMLAttributes<HTMLInputElement>, keyof Props<T>>)} | ||
type={type} | ||
onFocus={() => setFocused(true)} | ||
maxLength={maxLength} | ||
required={required} | ||
disabled={disabled} | ||
defaultValue={value ?? ""} | ||
onChange={handleChange} | ||
className={inputStyles() + className} | ||
/> | ||
)} | ||
{Boolean(label) && ( | ||
<label className={labelStyles({ isUp: hasValue || focused })}> | ||
{label} | ||
{required && `*`} | ||
</label> | ||
)} | ||
{Boolean(helperText) && <span className="color-primary/60 text-xs">{helperText}</span>} | ||
{Boolean(error) && <span className="text-xs text-red-500">{error}</span>} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Field; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { tv } from "tailwind-variants"; | ||
|
||
export const containerStyles = tv({ | ||
base: `flex flex-col gap-1 relative w-full text-primary transition-all `, | ||
}); | ||
|
||
export const labelStyles = tv({ | ||
base: `label | ||
transition-all | ||
absolute | ||
text-primary/60 | ||
top-0 left-2 | ||
translate-y-1 | ||
p-1 | ||
pointer-events-none `, | ||
variants: { | ||
isUp: { | ||
true: "text-primary py-0 translate-y-[-50%] bg-white text-sm focus:text-accent", | ||
false: " ", | ||
}, | ||
}, | ||
|
||
defaultVariants: { | ||
isUp: false, | ||
}, | ||
}); | ||
|
||
export const inputStyles = tv({ | ||
base: `transition-all | ||
outline-none | ||
rounded-lg | ||
p-2 | ||
ring-1 | ||
ring-primary | ||
hover:shadow-lg | ||
focus:ring-accent | ||
peer`, | ||
variants: { | ||
multiline: { | ||
true: "input peer min-h-[100px] max-h-[300px] resize-y", | ||
false: "input peer ", | ||
}, | ||
}, | ||
defaultVariants: { | ||
multiline: false, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as Field } from './Field'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.