mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
63 lines
1.5 KiB
TypeScript
63 lines
1.5 KiB
TypeScript
'use client'
|
|
|
|
import type { FormEvent, ReactNode } from 'react'
|
|
import { YStack } from '@hanzo/ui'
|
|
import { Label } from '@hanzo/ui'
|
|
|
|
/**
|
|
* The two shapes every /account form is made of.
|
|
*
|
|
* The measure is the FORM's, not the page's: a text field wider than this is
|
|
* harder to read back, and each of these pages had reached for its own guess at
|
|
* it. The vertical rhythm is stated once here so a label sits closer to its own
|
|
* control than to the field above it.
|
|
*/
|
|
|
|
/** A form, and the rhythm its fields sit on. */
|
|
export function Form({
|
|
onSubmit,
|
|
children,
|
|
}: {
|
|
onSubmit: (e: FormEvent) => void
|
|
children: ReactNode
|
|
}) {
|
|
return (
|
|
<form onSubmit={onSubmit}>
|
|
<YStack gap="$6" maxW={576}>
|
|
{children}
|
|
</YStack>
|
|
</form>
|
|
)
|
|
}
|
|
|
|
/**
|
|
* A label and its control, which are one thing and are spaced as one.
|
|
*
|
|
* `grow` puts the field in a row that wraps: it takes half the width where the
|
|
* viewport has room for two and the whole of it where it does not, so a pair of
|
|
* short fields needs no breakpoint of its own. `center` sets the label over the
|
|
* middle of its control, for a form whose words are centred (the sign-in).
|
|
*/
|
|
export function Field({
|
|
id,
|
|
label,
|
|
children,
|
|
grow,
|
|
center,
|
|
}: {
|
|
id: string
|
|
label: string
|
|
children: ReactNode
|
|
grow?: boolean
|
|
center?: boolean
|
|
}) {
|
|
return (
|
|
<YStack gap="$2" {...(grow ? { flexGrow: 1, flexBasis: 220 } : null)}>
|
|
<Label htmlFor={id} self={center ? 'center' : undefined}>
|
|
{label}
|
|
</Label>
|
|
{children}
|
|
</YStack>
|
|
)
|
|
}
|