Skip to content

Commit

Permalink
feat: basic form group impl with aria support
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Aug 12, 2024
1 parent a99b99c commit 014a00a
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 8 deletions.
1 change: 1 addition & 0 deletions packages/core/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const FieldTypePrefixes = {
RadioButtonGroup: 'rbg',
Slider: 'sl',
SearchField: 'sf',
FormGroup: 'fg',
} as const;

export const NOOP = () => {};
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export * from './useSpinButton';
export * from './types';
export * from './config';
export * from './form';
export * from './useFormGroup';
export * from './validation';
export { normalizePath } from './utils/path';
Empty file.
1 change: 1 addition & 0 deletions packages/core/src/useFormGroup/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useFormGroup';
45 changes: 45 additions & 0 deletions packages/core/src/useFormGroup/useFormGroup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { computed, Ref, shallowRef } from 'vue';
import { useLabel } from '../a11y/useLabel';
import { FieldTypePrefixes } from '../constants';
import { FormObject, Reactivify, TypedSchema } from '../types';
import { normalizeProps, useUniqId, withRefCapture } from '../utils/common';

export interface FormGroupProps<TInput extends FormObject = FormObject, TOutput extends FormObject = TInput> {
label?: string;
schema?: TypedSchema<TInput, TOutput>;
}

export function useFormGroup<TInput extends FormObject = FormObject, TOutput extends FormObject = TInput>(
_props: Reactivify<FormGroupProps<TInput, TOutput>>,
elementRef?: Ref<HTMLElement>,
) {
const id = useUniqId(FieldTypePrefixes.FormGroup);
const props = normalizeProps(_props);
const groupRef = elementRef || shallowRef<HTMLInputElement>();

const { labelProps, labelledByProps } = useLabel({
for: id,
label: props.label,
targetRef: groupRef,
});

const groupProps = computed(() => {
const isFieldSet = groupRef.value?.tagName === 'FIELDSET';

return withRefCapture(
{
id,
...(isFieldSet ? {} : labelledByProps.value),
role: isFieldSet ? undefined : 'group',
},
groupRef,
elementRef,
);
});

return {
groupRef,
labelProps,
groupProps,
};
}
15 changes: 7 additions & 8 deletions packages/playground/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
<template>
<div class="flex flex-col">
<InputText label="deep" name="some.deep.path" />
<InputText label="arr" name="some.array.0.path" />

<span data-testid="e2">{{ getError('some.array.0.path') }}</span>

<pre>{{ getErrors() }}</pre>
<FormGroup label="Shipping Information">
<InputText label="deep" name="some.deep.path" />
<InputText label="arr" name="some.array.0.path" />
</FormGroup>
</div>
</template>

<script lang="ts" setup>
import InputText from '@/components/InputText.vue';
import { useForm } from '@formwerk/core';
import FormGroup from '@/components/FormGroup.vue';
import { useForm, useFormGroup } from '@formwerk/core';
import { defineSchema } from '@formwerk/schema-zod';
import { z } from 'zod';
const { getError, isValid, getErrors } = useForm({
const form = useForm({
schema: defineSchema(
z.object({
some: z.object({
Expand Down
15 changes: 15 additions & 0 deletions packages/playground/src/components/FormGroup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<template>
<fieldset v-bind="groupProps">
<legend v-bind="labelProps">Shipping Address</legend>

<slot />
</fieldset>
</template>

<script setup lang="ts">
import { FormGroupProps, useFormGroup } from '@formwerk/core';
const props = defineProps<FormGroupProps>();
const { labelProps, groupProps } = useFormGroup(props);
</script>

0 comments on commit 014a00a

Please sign in to comment.