Skip to content

Commit

Permalink
Merge pull request #1506 from EnergySage/CED-1815
Browse files Browse the repository at this point in the history
CED-1815  Fix accessibility issue in v3 EsRadioButton
  • Loading branch information
tomleo authored Sep 5, 2024
2 parents b366166 + d739ef0 commit 49b7228
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 82 deletions.
61 changes: 61 additions & 0 deletions es-ds-components/components/es-radio-button-group.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script setup lang="ts">
/*
Similar API to https://bootstrap-vue.org/docs/components/form-radio#component-reference
Only more restrained, and based on historical usage. Things like configurable
value field aren't supported as they weren't used downstream.
Similarly things like size are not implemented
*/
interface IOptions {
text: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
disabled?: boolean;
}
interface IProps {
id: string;
label: string;
name?: string;
options?: IOptions[];
inline?: boolean;
}
withDefaults(defineProps<IProps>(), {
inline: false,
name: '',
options: undefined,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const model = defineModel<any>();
</script>

<template>
<fieldset
:id="id"
class="form-group">
<legend
:id="`legend-${id}`"
class="font-size-100"
tabindex="-1">
{{ label }}
</legend>
<template v-if="$slots.default">
<slot />
</template>
<template v-else>
<es-radio-button
v-for="option in options"
:key="option.value"
v-model="model"
:disabled="option?.disabled || false"
:display-name="option?.text"
:group-name="name"
:inline="inline"
:value="option.value" />
</template>
</fieldset>
</template>
57 changes: 25 additions & 32 deletions es-ds-components/components/es-radio-button.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
<script setup lang="ts">
import RadioButton from 'primevue/radiobutton';
defineProps({
disabled: {
type: Boolean,
default: false,
},
displayName: {
type: String,
required: true,
default: '',
},
groupName: {
type: String,
required: false,
default: '',
},
inline: {
type: Boolean,
default: false,
},
value: {
type: String,
required: true,
default: '',
},
interface IProps {
disabled?: boolean;
displayName: string;
groupName?: string;
inline?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
}
const props = withDefaults(defineProps<IProps>(), {
disabled: false,
displayName: '',
groupName: '',
inline: false,
value: null,
});
</script>

Expand All @@ -35,13 +26,15 @@ defineProps({
input-class="custom-radio-input"
v-bind="$attrs"
:disabled="disabled"
:input-id="`${value}-${groupName}`"
:name="groupName"
:value="value" />
<label
:for="`${value}-${groupName}`"
class="custom-control-label"
>{{ displayName }}</label
>
:input-id="`${props.value}-${props.groupName}`"
:name="props.groupName"
:value="props.value" />
<slot>
<label
:for="`${props.value}-${props.groupName}`"
class="custom-control-label">
{{ props.displayName }}
</label>
</slot>
</div>
</template>
19 changes: 17 additions & 2 deletions es-ds-docs/components/ds-doc-source.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export default {
default: '',
required: false,
},
compTitle: {
type: String,
default: 'Component source',
required: false,
},
docCode: {
type: String,
default: '',
Expand All @@ -22,17 +27,25 @@ export default {
default: '',
required: false,
},
docTitle: {
type: String,
default: 'Documentation source',
required: false,
},
},
};
</script>

<template>
<div class="mt-500">
<client-only>
<es-collapse
v-if="compCode"
id="compsource">
<template #title>
<h2 class="mb-0">Component source</h2>
<h2 class="mb-0">
{{ compTitle }}
</h2>
</template>
<ds-code-block
:code="compCode"
Expand All @@ -43,7 +56,9 @@ export default {
id="docsource"
class="mt-500">
<template #title>
<h2 class="mb-0">Documentation source</h2>
<h2 class="mb-0">
{{ docTitle }}
</h2>
</template>
<ds-code-block
:code="docCode"
Expand Down
159 changes: 111 additions & 48 deletions es-ds-docs/pages/molecules/radio-button.vue
Original file line number Diff line number Diff line change
@@ -1,32 +1,27 @@
<script setup lang="ts">
import { ref } from 'vue';
const selectedFruit = ref('banana');
const fruits = ref([
{ name: 'Apple', key: 'apple' },
{ name: 'Banana', key: 'banana' },
{ name: 'Cherry', key: 'cherry' },
]);
const test2Options = [
{ text: 'Toggle this custom radio', value: 'first' },
{ text: 'Or toggle this other custom radio', value: 'second' },
{ text: 'This one is Disabled', value: 'third', disabled: true },
{ text: 'This is the 4th radio', value: { fourth: 4 } },
];
const test2Selected = ref('first');
const { $prism } = useNuxtApp();
const compCode = ref('');
const docCode = ref('');
if ($prism) {
/* eslint-disable import/no-webpack-loader-syntax, import/no-self-import */
const compSource = await import('@energysage/es-ds-components/components/es-radio-button.vue?raw');
const docSource = await import('./radio-button.vue?raw');
/* eslint-enable import/no-webpack-loader-syntax, import/no-self-import */
compCode.value = $prism.normalizeCode(compSource.default);
docCode.value = $prism.normalizeCode(docSource.default);
$prism.highlight();
}
const propTableRows = [
// Name, Type, Default, Description
const radioButtonPropTableRows = [
['disabled', 'Boolean', 'false', 'When present, it specifies that the radio button should be disabled.'],
['inline', 'Boolean', 'false', 'When present, it specifies that the radio buttons should be displayed inline.'],
['v-model', 'String', 'n/a', 'Required. The v-model directive binds the radio button to a data property.'],
['v-model', 'Any', 'n/a', 'Required. The v-model directive binds the radio button to a data property.'],
['display-name', 'String', 'n/a', 'Required. The text to display next to the radio button.'],
['value', 'String', 'n/a', 'Required. The value to be used by v-model.'],
['value', 'Any', 'n/a', 'Required. The value to be used by v-model.'],
[
'group-name',
'String',
Expand All @@ -35,11 +30,44 @@ const propTableRows = [
'use the same v-model.',
],
];
// Name, Type, Default, Description
const radioButtonGroupPropTableRows = [
['id', 'String', 'n/a', 'Required.'],
['label', 'String', 'n/a', 'Required. Corresponds to the legend value describing the group'],
['name', 'String', `''`, 'Optional. Maps to the group name for each radio input'],
[
'options',
'Array',
'undefined',
'Optional. Must provide if not using the default slot. Allows radio input values to be passed as an array.',
],
['inline', 'Boolean', 'false', 'Optional. Attribute is passed down to children when using the options attribute'],
];
const { $prism } = useNuxtApp();
const radioButtonComponentCode = ref('');
const radioButtonGroupComponentCode = ref('');
const docCode = ref('');
if ($prism) {
/* eslint-disable import/no-webpack-loader-syntax, import/no-self-import */
const radioButtonComponentSource = await import('@energysage/es-ds-components/components/es-radio-button.vue?raw');
// eslint-disable-next-line max-len
const radioButtonGroupComponentSource = await import(
'@energysage/es-ds-components/components/es-radio-button-group.vue?raw'
);
const docSource = await import('./radio-button.vue?raw');
/* eslint-enable import/no-webpack-loader-syntax, import/no-self-import */
radioButtonComponentCode.value = $prism.normalizeCode(radioButtonComponentSource.default);
radioButtonGroupComponentCode.value = $prism.normalizeCode(radioButtonGroupComponentSource.default);
docCode.value = $prism.normalizeCode(docSource.default);
$prism.highlight();
}
</script>

<template>
<div>
<h1>Radio button</h1>
<p class="mb-500">
Uses
<a
Expand All @@ -51,50 +79,85 @@ const propTableRows = [

<div class="my-500">
<h2>Inline</h2>
<p>Please choose your favorite fruit.</p>
<es-radio-button
v-for="fruit in fruits"
:key="fruit.key"
v-model="selectedFruit"
:display-name="fruit.name"
group-name="inline"
:value="fruit.key"
inline />
<es-radio-button-group
id="idFruits"
label="Please choose your favorite fruit.">
<es-radio-button
v-for="fruit in fruits"
:key="fruit.key"
v-model="selectedFruit"
:display-name="fruit.name"
group-name="inline"
:value="fruit.key"
inline />
</es-radio-button-group>
</div>

<div class="my-500">
<h2>Stacked</h2>
<p>Please choose your favorite fruit.</p>
<es-radio-button
v-for="fruit in fruits"
:key="fruit.key"
v-model="selectedFruit"
:display-name="fruit.name"
group-name="stacked"
:value="fruit.key" />
<es-radio-button-group
id="idFruits2"
label="Please choose your favorite fruit.">
<es-radio-button
v-for="fruit in fruits"
:key="fruit.key"
v-model="selectedFruit"
:display-name="fruit.name"
group-name="stacked"
:value="fruit.key" />
</es-radio-button-group>
</div>

<div class="my-500">
<h2>Disabled</h2>
<p>Please choose your favorite fruit.</p>
<es-radio-button
v-for="fruit in fruits"
:key="fruit.key"
v-model="selectedFruit"
:display-name="fruit.name"
group-name="disabled"
:value="fruit.key"
disabled />
<es-radio-button-group
id="idFruits3"
label="Please choose your favorite fruit.">
<es-radio-button
v-for="fruit in fruits"
:key="fruit.key"
v-model="selectedFruit"
:display-name="fruit.name"
group-name="disabled"
:value="fruit.key"
disabled />
</es-radio-button-group>
</div>

<div class="my-500">
<h2>Using options prop</h2>
<es-radio-button-group
id="test2RadioGroup"
v-model="test2Selected"
label="Radios using options"
:options="test2Options"
name="test2" />

<div>selected: {{ test2Selected }}</div>
</div>

<div class="mb-500">
<h2>EsRadioButton props</h2>
<ds-prop-table :rows="propTableRows" />
<ds-prop-table :rows="radioButtonPropTableRows" />
</div>

<div class="mb-500">
<h2>EsRadioButtonGroup props</h2>
<ds-prop-table :rows="radioButtonGroupPropTableRows" />
</div>

<ds-doc-source
:comp-code="compCode"
comp-source="es-ds-components/src/lib-components/es-radio-button.vue"
comp-title="Radio button component"
:comp-code="radioButtonComponentCode"
comp-source="es-ds-components/src/lib-components/es-radio-button.vue" />

<ds-doc-source
comp-title="Radio button group component"
:comp-code="radioButtonGroupComponentCode"
comp-source="es-ds-components/src/lib-components/es-radio-button-group.vue" />

<ds-doc-source
doc-title="Radio button & radio button group documentation"
:doc-code="docCode"
doc-source="es-ds-docs/pages/molecules/radio-button.vue" />
</div>
Expand Down

0 comments on commit 49b7228

Please sign in to comment.