Skip to content

Commit

Permalink
fix(Radio): use generic type for Radio modelValue
Browse files Browse the repository at this point in the history
  • Loading branch information
lukicenturi authored and kelsos committed Sep 19, 2024
1 parent 91776a6 commit 6505a43
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 35 deletions.
3 changes: 2 additions & 1 deletion example/src/views/RadioView.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<script lang="ts" setup>
import { type RadioProps, RuiRadio, RuiRadioGroup } from '@rotki/ui-library';
type RadioData = RadioProps & {
type RadioData = RadioProps<string> & {
label?: string;
modelValue?: string;
};
const radios = ref<RadioData[]>([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@ import { describe, expect, it } from 'vitest';
import { type ComponentMountingOptions, mount } from '@vue/test-utils';
import RuiRadioGroup from '@/components/forms/radio-button/radio-group/RuiRadioGroup.vue';

function createWrapper(options?: ComponentMountingOptions<typeof RuiRadioGroup>) {
return mount(RuiRadioGroup, { ...options, global: { stubs: ['icon'] } });
function createWrapper(options?: ComponentMountingOptions<typeof RuiRadioGroup<string>>) {
const opts: ComponentMountingOptions<typeof RuiRadioGroup<string>> = {
...options,
global: {
stubs: ['icon'],
},
};

return mount(RuiRadioGroup, opts);
}

describe('forms/RadioButton/RadioGroup', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { contextColors } from '@/consts/colors';
import RuiRadioGroup, { type Props } from '@/components/forms/radio-button/radio-group/RuiRadioGroup.vue';
import type { Meta, StoryFn, StoryObj } from '@storybook/vue3';

const render: StoryFn<Props> = args => ({
type RuiRadioGroupProps = Props & { modelValue: string };
const render: StoryFn<RuiRadioGroupProps> = args => ({
components: { RuiRadio, RuiRadioGroup },
setup() {
const modelValue = computed({
Expand All @@ -23,7 +24,7 @@ const render: StoryFn<Props> = args => ({
</RuiRadioGroup>`,
});

const meta: Meta<Props> = {
const meta: Meta<RuiRadioGroupProps> = {
argTypes: {
color: { control: 'select', options: contextColors },
disabled: { control: 'boolean', table: { category: 'State' } },
Expand All @@ -35,13 +36,13 @@ const meta: Meta<Props> = {
size: { control: 'select', options: ['medium', 'sm', 'lg'] },
successMessages: { control: 'object' },
},
component: RuiRadioGroup,
component: RuiRadioGroup as any,
render,
tags: ['autodocs'],
title: 'Components/Forms/Radio/RadioGroup',
};

type Story = StoryObj<Props>;
type Story = StoryObj<RuiRadioGroupProps>;

export const Default: Story = {
args: {},
Expand Down
13 changes: 3 additions & 10 deletions src/components/forms/radio-button/radio-group/RuiRadioGroup.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
<script setup lang="ts">
<script lang="ts" setup generic='TValue'>
import { objectPick } from '@vueuse/shared';
import { Fragment, isVNode } from 'vue';
import RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';
import type { ContextColorsType } from '@/consts/colors';
type ModelValue = string | number | boolean;
export interface Props {
modelValue?: ModelValue;
inline?: boolean;
label?: string;
hint?: string;
Expand All @@ -25,7 +22,6 @@ defineOptions({
});
withDefaults(defineProps<Props>(), {
modelValue: '',
inline: false,
label: '',
hint: '',
Expand All @@ -37,9 +33,7 @@ withDefaults(defineProps<Props>(), {
size: undefined,
});
const emit = defineEmits<{
(e: 'update:modelValue', value: ModelValue): void;
}>();
const modelValue = defineModel<TValue>({ required: false });
const radioGroupName = ref('');
Expand Down Expand Up @@ -75,10 +69,9 @@ const css = useCssModule();
v-for="(child, i) in children"
v-bind="objectPick($props, ['disabled', 'color', 'size'])"
:key="i"
:model-value="modelValue"
v-model="modelValue"
hide-details
:name="radioGroupName"
@update:model-value="emit('update:modelValue', $event)"
/>
</div>
<RuiFormTextDetail
Expand Down
4 changes: 2 additions & 2 deletions src/components/forms/radio-button/radio/RuiRadio.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { contextColors } from '@/consts/colors';
import RuiRadio, { type RadioProps } from '@/components/forms/radio-button/radio/RuiRadio.vue';
import type { Meta, StoryFn, StoryObj } from '@storybook/vue3';

type PropsAndLabel = RadioProps & { label: string };
type PropsAndLabel = RadioProps<string> & { label: string; modelValue: string };

const render: StoryFn<PropsAndLabel> = args => ({
components: { RuiRadio },
Expand Down Expand Up @@ -37,7 +37,7 @@ const meta: Meta<PropsAndLabel> = {
size: { control: 'select', options: ['medium', 'sm', 'lg'] },
value: { control: 'text' },
},
component: RuiRadio,
component: RuiRadio as any,
parameters: {
docs: {
controls: { exclude: ['default'] },
Expand Down
26 changes: 10 additions & 16 deletions src/components/forms/radio-button/radio/RuiRadio.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
<script lang="ts" setup>
<script lang="ts" setup generic='TValue'>
import { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';
import RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';
import RuiIcon from '@/components/icons/RuiIcon.vue';
import type { ContextColorsType } from '@/consts/colors';
type ModelValue = string | number | boolean;
export interface RadioProps {
value: ModelValue;
modelValue?: ModelValue;
export interface RadioProps<TValue> {
value: TValue;
disabled?: boolean;
color?: ContextColorsType;
size?: 'sm' | 'lg';
Expand All @@ -24,8 +21,7 @@ defineOptions({
inheritAttrs: false,
});
const props = withDefaults(defineProps<RadioProps>(), {
modelValue: '',
const props = withDefaults(defineProps<RadioProps<TValue>>(), {
disabled: false,
color: undefined,
size: undefined,
Expand All @@ -36,25 +32,23 @@ const props = withDefaults(defineProps<RadioProps>(), {
hideDetails: false,
});
const emit = defineEmits<{
(e: 'update:modelValue', modelValue: ModelValue): void;
}>();
const modelValue = defineModel<TValue>({ required: false });
const { modelValue, size, value, successMessages, errorMessages }
const { value, successMessages, errorMessages }
= toRefs(props);
function input(event: Event) {
const checked = (event.target as HTMLInputElement).checked;
if (checked)
emit('update:modelValue', get(value));
set(modelValue, get(value));
}
const iconSize: ComputedRef<number> = computed(() => {
const sizeVal = get(size);
if (sizeVal === 'lg')
const size = props.size;
if (size === 'lg')
return 28;
if (sizeVal === 'sm')
if (size === 'sm')
return 20;
return 24;
Expand Down

0 comments on commit 6505a43

Please sign in to comment.