184 lines
5.3 KiB
TypeScript
184 lines
5.3 KiB
TypeScript
import { Section } from "./section"
|
|
import { H2, H3, H4, H5, Text, SmallText } from "./text"
|
|
import "hono/jsx"
|
|
import type { JSX, FC } from "hono/jsx"
|
|
import { VStack, HStack } from "./stack"
|
|
|
|
export type InputProps = JSX.IntrinsicElements["input"] & {
|
|
labelPosition?: "above" | "left" | "right"
|
|
children?: any
|
|
}
|
|
|
|
export const Input: FC<InputProps> = (props) => {
|
|
const { labelPosition = "above", children, style, ...inputProps } = props
|
|
|
|
const inputStyle: JSX.CSSProperties = {
|
|
height: "40px",
|
|
padding: "8px 12px",
|
|
borderRadius: "6px",
|
|
border: "1px solid #d1d5db",
|
|
backgroundColor: "white",
|
|
fontSize: "14px",
|
|
outline: "none",
|
|
...(style as JSX.CSSProperties),
|
|
}
|
|
|
|
if (!children) {
|
|
return <input style={inputStyle} {...inputProps} />
|
|
}
|
|
|
|
const labelStyle: JSX.CSSProperties = {
|
|
fontSize: "14px",
|
|
fontWeight: "500",
|
|
color: "#111827",
|
|
}
|
|
|
|
const labelElement = (
|
|
<label for={inputProps.id} style={labelStyle}>
|
|
{children}
|
|
</label>
|
|
)
|
|
|
|
if (labelPosition === "above") {
|
|
return (
|
|
<div style={{ display: "flex", flexDirection: "column", gap: "4px", flex: 1, minWidth: 0 }}>
|
|
{labelElement}
|
|
<input style={inputStyle} {...inputProps} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (labelPosition === "left") {
|
|
return (
|
|
<div style={{ display: "flex", alignItems: "center", gap: "4px", flex: 1 }}>
|
|
{labelElement}
|
|
<input style={{ ...inputStyle, flex: 1 }} {...inputProps} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (labelPosition === "right") {
|
|
return (
|
|
<div style={{ display: "flex", alignItems: "center", gap: "4px", flex: 1 }}>
|
|
<input style={{ ...inputStyle, flex: 1 }} {...inputProps} />
|
|
{labelElement}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
export const Test = () => {
|
|
return (
|
|
<Section maxWidth="448px">
|
|
{/* Basic inputs */}
|
|
<VStack gap={4}>
|
|
<H2>Basic Inputs</H2>
|
|
<VStack gap={4}>
|
|
<Input placeholder="Enter your name" />
|
|
<Input type="email" placeholder="Enter your email" />
|
|
<Input type="password" placeholder="Enter your password" />
|
|
</VStack>
|
|
</VStack>
|
|
|
|
{/* Custom styling */}
|
|
<VStack gap={4}>
|
|
<H2>Custom Styling</H2>
|
|
<VStack gap={4}>
|
|
<Input style={{ height: "32px", fontSize: "12px" }} placeholder="Small input" />
|
|
<Input placeholder="Default input" />
|
|
<Input style={{ height: "48px", fontSize: "16px" }} placeholder="Large input" />
|
|
</VStack>
|
|
</VStack>
|
|
|
|
{/* With values */}
|
|
<VStack gap={4}>
|
|
<H2>With Values</H2>
|
|
<VStack gap={4}>
|
|
<Input value="John Doe" placeholder="Name" />
|
|
<Input type="email" value="john@example.com" placeholder="Email" />
|
|
</VStack>
|
|
</VStack>
|
|
|
|
{/* Disabled state */}
|
|
<VStack gap={4}>
|
|
<H2>Disabled State</H2>
|
|
<VStack gap={4}>
|
|
<Input disabled placeholder="Disabled input" style={{ opacity: 0.5, cursor: "not-allowed" }} />
|
|
<Input disabled value="Disabled with value" style={{ opacity: 0.5, cursor: "not-allowed" }} />
|
|
</VStack>
|
|
</VStack>
|
|
|
|
{/* Label above */}
|
|
<VStack gap={4}>
|
|
<H2>Label Above</H2>
|
|
<VStack gap={4}>
|
|
<Input placeholder="Enter your name">Name</Input>
|
|
<Input type="email" placeholder="Enter your email">
|
|
Email
|
|
</Input>
|
|
<Input type="password" placeholder="Enter your password">
|
|
Password
|
|
</Input>
|
|
</VStack>
|
|
</VStack>
|
|
|
|
{/* Label to the left */}
|
|
<VStack gap={4}>
|
|
<H2>Label Left</H2>
|
|
<VStack gap={4}>
|
|
<Input labelPosition="left" placeholder="Enter your name">
|
|
Name
|
|
</Input>
|
|
<Input labelPosition="left" type="email" placeholder="Enter your email">
|
|
Email
|
|
</Input>
|
|
<Input labelPosition="left" type="password" placeholder="Enter your password">
|
|
Password
|
|
</Input>
|
|
</VStack>
|
|
</VStack>
|
|
|
|
{/* Label to the right */}
|
|
<VStack gap={4}>
|
|
<H2>Label Right</H2>
|
|
<VStack gap={4}>
|
|
<Input labelPosition="right" placeholder="Enter your name">
|
|
Name
|
|
</Input>
|
|
<Input labelPosition="right" type="email" placeholder="Enter your email">
|
|
Email
|
|
</Input>
|
|
<Input labelPosition="right" type="password" placeholder="Enter your password">
|
|
Password
|
|
</Input>
|
|
</VStack>
|
|
</VStack>
|
|
|
|
{/* Horizontal layout */}
|
|
<VStack gap={4}>
|
|
<H2>Horizontal Layout</H2>
|
|
<HStack gap={4}>
|
|
<Input placeholder="First name">First</Input>
|
|
<Input placeholder="Last name">Last</Input>
|
|
<Input placeholder="Age">Age</Input>
|
|
</HStack>
|
|
</VStack>
|
|
|
|
{/* Custom styling */}
|
|
<VStack gap={4}>
|
|
<H2>Custom Input Styling</H2>
|
|
<VStack gap={4}>
|
|
<Input style={{ borderColor: "#93c5fd" }} placeholder="Custom styled input">
|
|
<span style={{ color: "#2563eb", fontWeight: "bold" }}>Custom Label</span>
|
|
</Input>
|
|
<Input labelPosition="left" placeholder="Required input">
|
|
<span style={{ color: "#dc2626", minWidth: "96px" }}>Required Field</span>
|
|
</Input>
|
|
</VStack>
|
|
</VStack>
|
|
</VStack>
|
|
)
|
|
}
|