148 lines
3.9 KiB
TypeScript
148 lines
3.9 KiB
TypeScript
import "hono/jsx"
|
|
import type { JSX, FC } from "hono/jsx"
|
|
import { VStack, HStack } from "./stack"
|
|
import { Section } from "./section"
|
|
import { H2 } from "./text"
|
|
import { CodeExamples } from "./code"
|
|
|
|
export type ButtonProps = JSX.IntrinsicElements["button"] & {
|
|
variant?: "primary" | "secondary" | "outline" | "ghost" | "destructive"
|
|
size?: "sm" | "md" | "lg"
|
|
}
|
|
|
|
export const Button: FC<ButtonProps> = (props) => {
|
|
const { variant = "primary", size = "md", style, ...buttonProps } = props
|
|
|
|
const baseStyles: JSX.CSSProperties = {
|
|
display: "inline-flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
fontWeight: "500",
|
|
transition: "all 0.2s",
|
|
outline: "none",
|
|
cursor: "pointer",
|
|
borderRadius: "4px",
|
|
border: "1px solid transparent",
|
|
}
|
|
|
|
const variantStyles: Record<string, JSX.CSSProperties> = {
|
|
primary: {
|
|
backgroundColor: "#3b82f6",
|
|
color: "#ffffff",
|
|
},
|
|
secondary: {
|
|
backgroundColor: "#64748b",
|
|
color: "#ffffff",
|
|
},
|
|
outline: {
|
|
backgroundColor: "transparent",
|
|
color: "#000000",
|
|
borderColor: "#d1d5db",
|
|
},
|
|
ghost: {
|
|
backgroundColor: "transparent",
|
|
color: "#000000",
|
|
},
|
|
destructive: {
|
|
backgroundColor: "#ef4444",
|
|
color: "#ffffff",
|
|
},
|
|
}
|
|
|
|
const sizeStyles: Record<string, JSX.CSSProperties> = {
|
|
sm: {
|
|
height: "32px",
|
|
padding: "0 12px",
|
|
fontSize: "14px",
|
|
},
|
|
md: {
|
|
height: "40px",
|
|
padding: "0 16px",
|
|
fontSize: "14px",
|
|
},
|
|
lg: {
|
|
height: "48px",
|
|
padding: "0 24px",
|
|
fontSize: "16px",
|
|
},
|
|
}
|
|
|
|
const combinedStyles: JSX.CSSProperties = {
|
|
...baseStyles,
|
|
...variantStyles[variant],
|
|
...sizeStyles[size],
|
|
...(style as JSX.CSSProperties),
|
|
}
|
|
|
|
return <button {...buttonProps} style={combinedStyles} />
|
|
}
|
|
|
|
export const Test = () => {
|
|
return (
|
|
<Section>
|
|
{/* API Usage Examples */}
|
|
<CodeExamples
|
|
examples={[
|
|
'<Button>Click Me</Button>',
|
|
'<Button variant="secondary">Secondary</Button>',
|
|
'<Button variant="outline" size="lg">Large</Button>',
|
|
'<Button onClick={handleClick}>Action</Button>',
|
|
]}
|
|
/>
|
|
|
|
{/* Variants */}
|
|
<VStack gap={4}>
|
|
<H2>Button Variants</H2>
|
|
<HStack gap={4}>
|
|
<Button variant="primary">Primary</Button>
|
|
<Button variant="secondary">Secondary</Button>
|
|
<Button variant="outline">Outline</Button>
|
|
<Button variant="ghost">Ghost</Button>
|
|
<Button variant="destructive">Destructive</Button>
|
|
</HStack>
|
|
</VStack>
|
|
|
|
{/* Sizes */}
|
|
<VStack gap={4}>
|
|
<H2>Button Sizes</H2>
|
|
<HStack gap={4} v="end">
|
|
<Button size="sm">Small</Button>
|
|
<Button size="md">Medium</Button>
|
|
<Button size="lg">Large</Button>
|
|
</HStack>
|
|
</VStack>
|
|
|
|
{/* With custom content */}
|
|
<VStack gap={4}>
|
|
<H2>Custom Content</H2>
|
|
<HStack gap={4}>
|
|
<Button variant="primary">
|
|
<span>🚀</span>
|
|
<span style={{ marginLeft: "8px" }}>Launch</span>
|
|
</Button>
|
|
<Button variant="outline" style={{ flexDirection: "column", height: "80px", width: "96px" }}>
|
|
<span style={{ fontSize: "24px" }}>💳</span>
|
|
<span style={{ fontSize: "12px", marginTop: "4px" }}>Card</span>
|
|
</Button>
|
|
</HStack>
|
|
</VStack>
|
|
|
|
{/* Native attributes work */}
|
|
<VStack gap={4}>
|
|
<H2>Native Attributes</H2>
|
|
<HStack gap={4}>
|
|
<Button onClick={() => alert("Clicked!")} variant="primary">
|
|
Click Me
|
|
</Button>
|
|
<Button disabled variant="secondary" style={{ opacity: 0.5, pointerEvents: "none" }}>
|
|
Disabled
|
|
</Button>
|
|
<Button type="submit" variant="outline">
|
|
Submit
|
|
</Button>
|
|
</HStack>
|
|
</VStack>
|
|
</Section>
|
|
)
|
|
}
|