Skip to content

Commit

Permalink
Add autocomplete attribute support
Browse files Browse the repository at this point in the history
  • Loading branch information
felipefreitag committed Jul 18, 2023
1 parent 7277b3e commit 1c7e0aa
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
117 changes: 117 additions & 0 deletions apps/web/app/routes/test-examples/field-with-autocomplete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import hljs from 'highlight.js/lib/common'
import type {
ActionFunction,
LoaderFunction,
MetaFunction,
} from '@remix-run/node'
import { formAction } from '~/formAction'
import { z } from 'zod'
import Form from '~/ui/form'
import { metaTags } from '~/helpers'
import { makeDomainFunction } from 'domain-functions'
import Example from '~/ui/example'

const title = 'Field with autocomplete'
const description =
'In this example, we pass a autocomplete prop to a field without children.'

export const meta: MetaFunction = () => metaTags({ title, description })

const schema = z.object({
name: z.string().min(1),
code: z.number().int().optional(),
organization: z.string().optional(),
organizationTitle: z.enum(['director', 'manager', 'employee']),
streetAddress: z.string().optional(),
country: z.string().optional(),
postalCode: z.string().optional(),
addressLine1: z.string().optional(),
})

export const loader: LoaderFunction = () => ({
code: hljs.highlight('', { language: 'ts' }).value,
})

const mutation = makeDomainFunction(schema)(async (values) => values)

export const action: ActionFunction = async ({ request }) =>
formAction({ request, schema, mutation })

export default function Component() {
return (
<Example title={title} description={description}>
<Form schema={schema}>
{({ Field, Errors, Button }) => (
<>
{/* Text field */}
<Field name="name" autoComplete="name" />
{/* Numeric field */}
<Field name="code">
{({ Label, Input, Errors }) => (
<>
<Label>Code</Label>
<Input type="number" autoComplete="one-time-code" />
<Errors />
</>
)}
</Field>
{/* Select field */}
<Field name="organizationTitle" autoComplete="organization-title" />
{/* Textarea field */}
<Field
name="streetAddress"
multiline
autoComplete="street-address"
/>
{/* Text field child */}
<Field name="organization" autoComplete="organization">
{({ Label, Input, Errors }) => (
<>
<Label>Organization</Label>
<Input autoComplete="organization" />
<Errors />
</>
)}
</Field>
{/* Smart input child*/}
<Field name="country">
{({ Label, SmartInput, Errors }) => (
<>
<Label>Country</Label>
<SmartInput autoComplete="country" />
<Errors />
</>
)}
</Field>
{/* Select child */}
<Field name="postalCode">
{({ Label, Select, Errors }) => (
<>
<Label>Postal code</Label>
<Select autoComplete="postal-code">
<option value="12345">12345</option>
<option value="67890">67890</option>
</Select>
<Errors />
</>
)}
</Field>
{/* Textarea child */}
<Field name="addressLine1">
{({ Label, Multiline, Errors }) => (
<>
<Label>Postal code</Label>
<Multiline autoComplete="address-line1" />

<Errors />
</>
)}
</Field>
<Errors />
<Button />
</>
)}
</Form>
</Example>
)
}
39 changes: 39 additions & 0 deletions apps/web/tests/examples/forms/field-with-autocomplete.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { test, expect } from 'tests/setup/tests'

const route = '/test-examples/field-with-autocomplete'

test('With JS enabled', async ({ example }) => {
const { page } = example

const name = example.field('name')
const code = example.field('code')
const organizationTitle = example.field('organizationTitle')
const organization = example.field('organization')
const streetAddress = example.field('streetAddress')
const country = example.field('country')
const postalCode = example.field('postalCode')
const addressLine1 = example.field('addressLine1')

await page.goto(route)

await expect(name.input).toHaveAttribute('autocomplete', 'name')
await expect(code.input).toHaveAttribute('autocomplete', 'one-time-code')
await expect(organizationTitle.input).toHaveAttribute(
'autocomplete',
'organization-title',
)
await expect(streetAddress.input).toHaveAttribute(
'autocomplete',
'street-address',
)
await expect(organization.input).toHaveAttribute(
'autocomplete',
'organization',
)
await expect(country.input).toHaveAttribute('autocomplete', 'country')
await expect(postalCode.input).toHaveAttribute('autocomplete', 'postal-code')
await expect(addressLine1.input).toHaveAttribute(
'autocomplete',
'address-line1',
)
})
4 changes: 4 additions & 0 deletions packages/remix-forms/src/createField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type FieldBaseProps<Schema extends SomeZodObject> = Omit<
> & {
name: keyof z.infer<Schema>
type?: JSX.IntrinsicElements['input']['type']
autoComplete?: JSX.IntrinsicElements['input']['autoComplete']
children?: Children<Schema>
}

Expand Down Expand Up @@ -139,6 +140,7 @@ type SmartInputProps = {
registerProps?: UseFormRegisterReturn
className?: string
a11yProps?: Record<`aria-${string}`, string | boolean | undefined>
autoComplete?: JSX.IntrinsicElements['input']['autoComplete']
}

const FieldContext = React.createContext<
Expand Down Expand Up @@ -285,6 +287,7 @@ function createField<Schema extends SomeZodObject>({
placeholder,
hidden = false,
children: childrenFn,
autoComplete,
...props
},
ref,
Expand Down Expand Up @@ -524,6 +527,7 @@ function createField<Schema extends SomeZodObject>({
autoFocus={autoFocus}
value={value}
a11yProps={a11yProps}
autoComplete={autoComplete}
/>
)

Expand Down

0 comments on commit 1c7e0aa

Please sign in to comment.