Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/lukebennett88/luke-ui. ui.lukebennett.dev
Something went wrong. Try again.
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121import { zodResolver } from '@hookform/resolvers/zod';import { Box } from '@luke-ui/react/box';import { Button } from '@luke-ui/react/button';import { Cluster } from '@luke-ui/react/cluster';import { Heading } from '@luke-ui/react/heading';import { Stack } from '@luke-ui/react/stack';import { Text } from '@luke-ui/react/text';import { TextField } from '@luke-ui/react/text-field';import { useState } from 'react';import { Controller, useForm } from 'react-hook-form';import * as z from 'zod';
const DIGIT_PATTERN = /\d/;
const schema = z.object({ email: z.email('Enter an email address in the form you@example.com.'), password: z.string().refine((value) => value.length >= 8 && DIGIT_PATTERN.test(value), { message: 'At least 8 characters, including a number.', }),});
export default () => { const form = useForm({ defaultValues: { email: '', password: '' }, resolver: zodResolver(schema), });
const handleSubmit = form.handleSubmit((values) => { setSignedInAs(values.email); });
// Set on a valid submit only, so the confirmation never tracks keystrokes. const [signedInAs, setSignedInAs] = useState<string | null>(null);
return ( <Box // These utility props turn a plain Box into a card. Background, border, // radius, and shadow all come from the theme scale. backgroundColor="surface.floating" borderColor="decorative" borderRadius="surface" borderStyle="solid" borderWidth="thin" boxShadow="raised" inlineSize="100%" marginInline="auto" maxInlineSize="26rem" // Utility props take an object keyed by breakpoint. Breakpoints are // container queries resolved against the theme root, so this follows the // preview's inline size. paddingBlock={{ initial: 'sp32', bp768: 'sp64', }} paddingInline={{ initial: 'sp24', bp768: 'sp48', }} render={(props) => <form {...props} onSubmit={handleSubmit} />} > <Stack gap="sp24"> <Heading level={2}>Sign in</Heading> <Stack gap="sp16"> <Controller control={form.control} name="email" render={({ field, fieldState }) => ( <TextField autoComplete="email" errorMessage={fieldState.error?.message} inputRef={field.ref} isRequired label="Email" name="email" onBlur={field.onBlur} onChange={field.onChange} placeholder="Enter your email address" type="email" validationBehavior="aria" value={field.value} /> )} /> <Controller control={form.control} name="password" render={({ field, fieldState }) => ( <TextField autoComplete="current-password" description="At least 8 characters, including a number." errorMessage={fieldState.error?.message} inputRef={field.ref} isRequired label="Password" minLength={8} name="password" onBlur={field.onBlur} onChange={field.onChange} type="password" validationBehavior="aria" value={field.value} /> )} /> </Stack> <Cluster gap="sp12" justifyContent="flex-end"> <Button type="button">Create an account</Button> <Button prominence="high" type="submit"> Sign in </Button> </Cluster> {signedInAs ? ( <Box backgroundColor="success.subtle.rest" borderRadius="control" padding="sp12"> <Text elementType="p">Signed in as {signedInAs}</Text> </Box> ) : null} </Stack> </Box> );};