Skip to content

Commit

Permalink
Merge pull request #1488 from OlkaB/feat/CvRadioButton
Browse files Browse the repository at this point in the history
feat: port CvRadioButton to Vue3
  • Loading branch information
davidnixon committed Jul 31, 2023
2 parents c55fe31 + dbe5ee6 commit 79b4361
Show file tree
Hide file tree
Showing 11 changed files with 484 additions and 2 deletions.
4 changes: 4 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ import CvRow from './src/components/CvGrid/CvRow.vue';
import CvNumberInput from './src/components/CvNumberInput/CvNumberInput.vue';
import CvNumberInputSkeleton from './src/components/CvNumberInput/CvNumberInputSkeleton.vue';
import CvToggle from './src/components/CvToggle/CvToggle.vue';
import CvRadioButton from './src/components/CvRadioButton/CvRadioButton.vue';
import CvRadioGroup from './src/components/CvRadioButton/CvRadioGroup.vue';

const all = {
CvAspectRatio,
Expand Down Expand Up @@ -128,6 +130,8 @@ const all = {
CvNumberInput,
CvNumberInputSkeleton,
CvToggle,
CvRadioButton,
CvRadioGroup,
};
export default {
install(app, options) {
Expand Down
2 changes: 0 additions & 2 deletions src/components/CvDropdown/CvDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,6 @@ const wrapperStyleOverride = computed(() => {
});
const el = ref(null);
function onClickOut() {
// eslint-disable-next-line no-console
console.log('onClickOut');
open.value = false;
}
onClickOutside(el, onClickOut);
Expand Down
166 changes: 166 additions & 0 deletions src/components/CvRadioButton/CvRadioButton.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { action } from '@storybook/addon-actions';
import { CvRadioButton, CvRadioGroup } from '.';
import {
sbCompPrefix,
storyParametersObject,
} from '../../global/storybook-utils';
import { ref } from 'vue';

export default {
title: `${sbCompPrefix}/CvRadioButton`,
component: CvRadioButton,
argTypes: {
checked: {
type: 'boolean',
control: false,
table: {
type: { summary: 'boolean' },
category: 'props',
},
},
label: {
description: 'radio-button label',
control: false,
},
hideLabel: {
description:
'makes the label visually hidden but still labels the radio input',
},
labelLeft: {
type: 'boolean',
table: {
type: { summary: 'boolean' },
category: 'props',
},
description: 'position label on left',
},
vertical: {
type: 'boolean',
table: {
type: { summary: 'boolean' },
category: 'props',
},
description:
'Property of CvRadioGroup component - stacks inside radio components vertically',
},
},
};

const DefaultRadioItems = [
{
label: 'radio-1',
id: 'value-1',
checked: true,
},
{
label: 'radio-2',
id: 'value-2',
disabled: true,
},
{
label: 'radio-3',
id: 'value-3',
},
];

const DefaultStoryParameters = {
controls: {
exclude: ['change', 'update:modelValue', 'modelValue'],
},
};

const defaultTemplate = `
<cv-radio-group v-bind="args" @change="onChange">
<cv-radio-button
v-for="({id, label, checked, disabled}, index) in DefaultRadioItems"
:key="index"
name="group-1"
:label="label"
:value="id"
:checked="checked"
:disabled="disabled"
:hide-label="hideLabel"
:label-left='labelLeft'
/>
</cv-radio-group>
`;

const Template = (args, { argTypes }) => {
return {
props: Object.keys(argTypes),
components: { CvRadioButton, CvRadioGroup },
template: defaultTemplate,
setup() {
return {
args,
hideLabel: args.hideLabel,
labelLeft: args.labelLeft,
onChange: action('change'),
DefaultRadioItems,
};
},
};
};

export const Default = Template.bind({});
Default.args = {
vertical: false,
};
Default.parameters = storyParametersObject(
DefaultStoryParameters,
defaultTemplate,
Default.args
);

const vModelTemplate = `
<cv-radio-group v-bind="args" @change="onChange">
<cv-radio-button
v-for="({id, label, checked, disabled}, index) in DefaultRadioItems"
v-model="modelValue"
:key="index"
name="group-1"
:label="label"
:value="id"
:disabled="disabled"
:hide-label="hideLabel"
:label-left='labelLeft'
/>
</cv-radio-group>
<div style="margin-top:1rem; background-color: #888888; padding:1rem">
V-model:
<template
v-for="({id, label}, index) in DefaultRadioItems"
:key="index"
>
<input name="modelValue" :id="id" type="radio" @change="(ev) => {modelValue = ev.target.id}" :checked="id === modelValue" />
<label :for="id" style="margin-right: 16px;">{{label}}:</label>
</template>
<div style="margin-top: 16px;">Checked: <span style="font-weight: bold;">{{modelValue}}</span></div>
</div>
`;

const VModelTemplate = args => {
return {
components: { CvRadioButton, CvRadioGroup },
template: vModelTemplate,
setup() {
return {
args,
hideLabel: args.hideLabel,
labelLeft: args.labelLeft,
modelValue: ref(DefaultRadioItems[0].id),
onChange: action('change'),
DefaultRadioItems,
};
},
};
};

export const VModel = VModelTemplate.bind({});
VModel.parameters = storyParametersObject(
DefaultStoryParameters,
vModelTemplate,
VModel.args
);
57 changes: 57 additions & 0 deletions src/components/CvRadioButton/CvRadioButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<template>
<div
:class="[
`cv-radio-button ${carbonPrefix}--radio-button-wrapper`,
{ [`${carbonPrefix}--radio-button-wrapper--label-left`]: labelLeft },
]"
>
<input
v-bind="$attrs"
:id="cvId"
:checked="isChecked"
:class="`${carbonPrefix}--radio-button`"
ref="input"
type="radio"
:value="value"
@change="onChange"
/>
<!-- symbol causes problem in codepen? -->
<label :for="cvId" :class="`${carbonPrefix}--radio-button__label`">
<span :class="`${carbonPrefix}--radio-button__appearance`"></span>
<span
v-if="label"
:class="{ [`${carbonPrefix}--visually-hidden`]: hideLabel }"
>
{{ label }}
</span>
</label>
</div>
</template>

<script setup>
import { carbonPrefix } from '../../global/settings';
import { useCvId, propsCvId, useMethods, useRadio } from '../../use';
const props = defineProps({
modelValue: String,
checked: Boolean,
label: String,
value: { type: String, required: true },
hideLabel: Boolean,
labelLeft: Boolean,
...propsCvId,
});
const cvId = useCvId(props);
const emit = defineEmits(['update:modelValue', 'change']);
useMethods({ input: ['blur', 'focus'] });
const { isChecked, onChange } = useRadio(props, emit);
</script>

<script>
export default {
inheritAttrs: false,
};
</script>
27 changes: 27 additions & 0 deletions src/components/CvRadioButton/CvRadioGroup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<div :class="`cv-radio-group ${carbonPrefix}--form-item`">
<div
:class="[
`${carbonPrefix}--radio-button-group`,
{ [`${carbonPrefix}--radio-button-group--vertical`]: vertical },
]"
>
<slot></slot>
</div>
</div>
</template>

<script setup>
import { provide } from 'vue';
import { carbonPrefix } from '../../global/settings';
defineProps({
vertical: Boolean,
});
const emit = defineEmits(['change']);
provide('onRadioItemChange', clickedItemCvId => {
emit('change', clickedItemCvId);
});
</script>
Loading

0 comments on commit 79b4361

Please sign in to comment.