Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CED-1754 Create v3 EsFormRadioCards #1525

Merged
merged 30 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2a7e7b9
feat: wip
tomleo Sep 5, 2024
bca817b
feat: wip
tomleo Sep 6, 2024
728e0b2
Merge remote-tracking branch 'origin/esds-3.0-vue3-primevue' into CED…
tomleo Sep 6, 2024
1a20c93
feat: explicit prop passing
tomleo Sep 10, 2024
8d02e2b
feat: rewrite of radio-button with native element
tomleo Sep 10, 2024
2bb4eb6
feat: rewrite without prime button
tomleo Sep 10, 2024
636c48c
feat: begin wiring up radio-cards
tomleo Sep 11, 2024
90f46ae
feat: rewrite radio cards
tomleo Sep 11, 2024
316a8e3
feat: fleshing out radio card docs
tomleo Sep 11, 2024
cfc529e
feat: add detach label example
tomleo Sep 12, 2024
5e02500
feat: add disabled styling
tomleo Sep 12, 2024
6f624c3
Merge remote-tracking branch 'origin/esds-3.0-vue3-primevue' into CED…
tomleo Sep 12, 2024
b8d694d
chore: apply formatting
tomleo Sep 12, 2024
abaceee
chore: apply formatting
tomleo Sep 12, 2024
a419390
Merge remote-tracking branch 'origin/esds-3.0-vue3-primevue' into CED…
tomleo Sep 13, 2024
ae7a6f7
chore: tweaks after merge
tomleo Sep 13, 2024
1643672
chore: formatting
tomleo Sep 13, 2024
e4d6ae4
Merge branch 'esds-3.0-vue3-primevue' into CED-1754
nathanielwarner Sep 16, 2024
f02d866
chore: interface tweak
tomleo Sep 17, 2024
6978e85
chore: clean-up comments and test files
tomleo Sep 17, 2024
eab7832
feat: add migration docs
tomleo Sep 17, 2024
bdfd56a
chore: re-order props
tomleo Sep 17, 2024
5c207ed
feat: remove unused prop from example
tomleo Sep 17, 2024
77033d6
fix: sr-only prop behavior
tomleo Sep 17, 2024
5caf663
fix: header level
tomleo Sep 17, 2024
26471cd
chore: add inline comment for clarity
tomleo Sep 17, 2024
d00f497
chore: apply formatting
tomleo Sep 17, 2024
cb9ac9c
fix: doc-source references
tomleo Sep 18, 2024
1c3d672
feat: add focus state logic
tomleo Sep 18, 2024
32c01d8
chore: apply formatting
tomleo Sep 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions es-ds-components/components/es-form-radio-card.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<script setup lang="ts">
import { useFocus } from '@vueuse/core';

const inputElem = useTemplateRef('input-elem');
const { focused: inputFocused } = useFocus(inputElem);

/* eslint-disable @typescript-eslint/no-explicit-any */
interface IProps {
id: string;
name: string;
value: any;
disabled?: boolean;
inline?: boolean;
displayName?: string;
}

const props = withDefaults(defineProps<IProps>(), {
disabled: false,
inline: false,
displayName: '',
});

// Need to define the implicit emit from v-model, so that it can also get fired
// from the label clicks
const emit = defineEmits(['update:modelValue']);

function handleRadioButtonClick() {
if (!props.disabled) {
emit('update:modelValue', props.value);
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const model = defineModel<any>();
const isChecked = computed(() => props.value === model.value);
</script>

<template>
<label
class="es-form-radio-card es-card interactive w-100 btn btn-outline-primary"
:class="{ active: isChecked, disabled: props.disabled, focus: isChecked || inputFocused }"
@click="handleRadioButtonClick">
<input
:id="id"
ref="input-elem"
v-model="model"
:disabled="props.disabled"
type="radio"
name="props.name"
:value="props.value"
:checked="isChecked"
@click="handleRadioButtonClick" />
<slot>
{{ displayName }}
</slot>
</label>
</template>
78 changes: 78 additions & 0 deletions es-ds-components/components/es-form-radio-cards.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<script setup lang="ts">
interface Option {
id: string;
text: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
disabled?: boolean;
inline?: boolean;
}

interface Props {
id: string;
label: string;
name?: string;
options?: Option[];
inline?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
modelValue?: any;
hasIcon?: boolean;
labelClass?: string;
labelSrOnly?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
name: '',
options: undefined,
inline: false,
modelValue: undefined,
hasIcon: false,
labelClass: 'font-size-h3',
labelSrOnly: false,
});

const emit = defineEmits(['update:model-value']);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function handleUpdate(value: any) {
emit('update:model-value', value);
}
</script>

<template>
<fieldset
:id="`${props.id}-fieldset`"
class="form-group">
<legend
:id="`${props.id}-legend`"
class="font-size-h1 font-weight-bolder mb-200 pb-0 text-dark"
:class="{ 'sr-only': props.labelSrOnly }"
tabindex="-1">
{{ props.label }}
</legend>
<div>
<div
:id="`${props.id}-radiogroup`"
role="radiogroup"
tabindex="-1"
class="es-form-radio-cards d-flex justify-content-center btn-group-vertical"
:class="{ 'has-icon': props.hasIcon }">
<slot :options="options">
<es-form-radio-card
v-for="option in options"
:id="option.id"
:key="option.value"
:disabled="option?.disabled || false"
:name="props.name"
:value="option.value"
:model-value="props.modelValue"
:inline="props.inline || false"
@update:model-value="handleUpdate">
<span :class="props.labelClass">
{{ option.text }}
</span>
</es-form-radio-card>
</slot>
</div>
</div>
</fieldset>
</template>
42 changes: 17 additions & 25 deletions es-ds-components/components/es-radio-button-group.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
<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 {
id: string;
text: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
Expand All @@ -21,41 +13,41 @@ interface IProps {
name?: string;
options?: IOptions[];
inline?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
modelValue?: any;
}

withDefaults(defineProps<IProps>(), {
const props = withDefaults(defineProps<IProps>(), {
inline: false,
name: '',
options: undefined,
modelValue: undefined,
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const model = defineModel<any>();
defineEmits(['update:model-value']);
</script>

<template>
<fieldset
:id="id"
class="form-group">
<legend
:id="`legend-${id}`"
:id="`${props.id}-legend`"
class="font-size-100"
tabindex="-1">
{{ label }}
{{ props.label }}
</legend>
<template v-if="$slots.default">
<slot />
</template>
<template v-else>
<slot :options="options">
<es-radio-button
v-for="option in options"
:id="option.id"
:key="option.value"
v-model="model"
:disabled="option?.disabled || false"
:display-name="option?.text"
:group-name="name"
:inline="inline"
:value="option.value" />
</template>
:name="props.name"
:value="option.value"
:model-value="props.modelValue"
:inline="props.inline || false"
:display-name="option.text"
@update:model-value="$emit('update:model-value', option.value)" />
</slot>
</fieldset>
</template>
65 changes: 41 additions & 24 deletions es-ds-components/components/es-radio-button.vue
Original file line number Diff line number Diff line change
@@ -1,40 +1,57 @@
<script setup lang="ts">
import RadioButton from 'primevue/radiobutton';

/* eslint-disable @typescript-eslint/no-explicit-any */
interface IProps {
name: string;
value: any;
id: string;
disabled?: boolean;
displayName: string;
groupName?: string;
inline?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
displayName?: string;
}

const props = withDefaults(defineProps<IProps>(), {
disabled: false,
displayName: '',
groupName: '',
inline: false,
value: null,
displayName: '',
});

// Need to define the implicit emit from v-model, so that it can also get fired
// from the label clicks
const emit = defineEmits(['update:modelValue']);
function handleRadioButtonClick() {
if (!props.disabled) {
emit('update:modelValue', props.value);
}
}

// Similar to the API of https://bootstrap-vue.org/docs/components/form-radio#changing-the-option-field-names
// the value can be a string, number, or simple object. Avoid using complex types in values.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const model = defineModel<any>();
tomleo marked this conversation as resolved.
Show resolved Hide resolved
const isChecked = computed(() => props.value === model.value);
</script>

<template>
<div :class="`custom-control custom-radio custom-control${inline ? '-inline' : ''}`">
<radio-button
<div
class="custom-control custom-radio"
:class="{ 'custom-control-inline': props.inline }">
<input
:id="id"
v-model="model"
:disabled="props.disabled"
type="radio"
:name="props.name"
class="custom-control-input"
input-class="custom-radio-input"
v-bind="$attrs"
:disabled="disabled"
: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>
:value="props.value"
:checked="isChecked"
@click="handleRadioButtonClick" />
<label
class="custom-control-label"
:for="id"
@click="handleRadioButtonClick">
<slot>
{{ displayName }}
</slot>
</label>
</div>
</template>
1 change: 1 addition & 0 deletions es-ds-components/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export default defineNuxtConfig({
'@vuelidate/core',
'@vuelidate/validators',
'html-truncate',
'@vueuse/core',
'primevue/accordion',
'primevue/accordiontab',
'primevue/breadcrumb',
Expand Down
Loading
Loading