useFieldA11y
Wire a custom form control to its label, description, error and helper text, using the same contract as every plocks field. On web it links them with ids and
aria-* references; on native, where id references don't work, it composes the control's label and hint instead.A plain
TextInput wired like a plocks field. useFieldA11y({ label, description, error, helperText, required, … }) returns controlProps for the control, labelProps / descriptionProps / errorProps / helperProps for the text around it, and showError / showHelper: the error replaces the helper text, and only the text that is rendered is referenced. Web gets aria-labelledby, aria-describedby, aria-invalid and aria-required; native gets a composed label ("Username, required") and a hint built from the error, description and helper text. errorProps makes the error a polite role="alert", but iOS has no live regions, so call announce() for a new error when it must be spoken there.Loading demo…
import { useState } from 'react';
import { TextInput } from 'react-native';
import { Block, Text, useFieldA11y, useTheme } from '@plocks/ui';
const LABEL = 'Username';
const HELPER = 'Lowercase letters and numbers, 3–16 characters.';
export function Demo() {
const theme = useTheme();
const [value, setValue] = useState('');
const error = /[^a-z0-9]/.test(value) ? 'Only lowercase letters and numbers are allowed.' : undefined;
const { controlProps, labelProps, errorProps, helperProps, invalid, showError, showHelper } = useFieldA11y({
label: LABEL,
helperText: HELPER,
error,
required: true,
});
return (
<Block fullWidth maw={360} gap="xs">
<Text {...labelProps} fw="600">
{LABEL}
<Text c="error" aria-hidden>
{' *'}
</Text>
</Text>
<TextInput
{...controlProps}
value={value}
onChangeText={setValue}
autoCapitalize="none"
autoCorrect={false}
style={{
borderWidth: 1,
borderColor: invalid ? theme.colors.error[5] : theme.backgrounds.borderStrong,
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 8,
fontSize: 14,
fontFamily: theme.fontFamily,
color: theme.text.primary,
}}
/>
{showError ? (
<Block {...errorProps} accessible>
<Text size="sm" c="error">
{error}
</Text>
</Block>
) : showHelper ? (
<Text {...helperProps} size="sm" c="muted">
{HELPER}
</Text>
) : null}
</Block>
);
}React Native design for iOS, Android, and Web.
Quick Links
Resources