feat(components): add RadioButtonGroup

Closes #25
This commit is contained in:
Eric Liu 2019-12-21 17:16:15 -08:00
commit 4f73b8b71a
9 changed files with 128 additions and 11 deletions

View file

@ -44,6 +44,7 @@ Currently, the following components are supported:
- ProgressStep
- RadioButton
- RadioButtonSkeleton
- RadioButtonGroup
- Search
- SearchSkeleton
- SkeletonPlaceholder

View file

@ -1,14 +1,14 @@
<script>
let className = undefined;
export { className as class };
export let props = {};
export let style = undefined;
import { cx } from '../../lib';
const _class = cx('--radio-button-wrapper', className);
</script>
<div {...props} class={_class}>
<div on:click on:mouseover on:mouseenter on:mouseleave class={_class} {style}>
<div class={cx('--radio-button', '--skeleton')} />
<span class={cx('--radio-button__label', '--skeleton')} />
</div>

View file

@ -8,11 +8,8 @@
</script>
<Layout>
{#if story === 'skeleton'}
<div>
<RadioButtonSkeleton />
</div>
<RadioButtonSkeleton />
{:else}
<RadioButton {...$$props} id="radio-1" />
{/if}

View file

@ -9,26 +9,38 @@
export let hideLabel = false;
export let labelPosition = 'right';
export let name = '';
export let props = {};
export let style = undefined;
import { getContext } from 'svelte';
import { writable } from 'svelte/store';
import { cx } from '../../lib';
const ctx = getContext('RadioButtonGroup');
const _class = cx(
'--radio-button-wrapper',
labelPosition !== 'right' && `--radio-button-wrapper--label-${labelPosition}`,
className
);
const _innerLabelClass = cx(hideLabel && '--visually-hidden');
let selected = ctx ? ctx.selected : writable(checked ? value : undefined);
if (ctx) {
ctx.add({ id, checked, disabled, value });
}
$: checked = $selected === value;
</script>
<div class={_class}>
<div class={_class} {style}>
<input
{...props}
type="radio"
class={cx('--radio-button')}
on:change
on:change={event => {
value = event.target.value;
on:change={() => {
if (ctx) {
ctx.update(value);
}
}}
{id}
{name}

View file

@ -0,0 +1,16 @@
<script>
import Layout from '../../internal/ui/Layout.svelte';
import RadioButtonGroup from './RadioButtonGroup.svelte';
import RadioButton from '../RadioButton';
import { FormGroup } from '../Form';
</script>
<Layout>
<FormGroup legendText="Radio Button heading">
<RadioButtonGroup {...$$props.group} defaultSelected="default-selected" legend="Group Legend">
<RadioButton {...$$props.radio} value="standard" id="radio-1" />
<RadioButton {...$$props.radio} value="default-selected" id="radio-2" />
<RadioButton {...$$props.radio} value="disabled" id="radio-3" />
</RadioButtonGroup>
</FormGroup>
</Layout>

View file

@ -0,0 +1,40 @@
import { withKnobs, text, select, boolean } from '@storybook/addon-knobs';
import Component from './RadioButtonGroup.Story.svelte';
export default { title: 'RadioButtonGroup', decorators: [withKnobs] };
const values = {
standard: 'standard',
'default-selected': 'default-selected',
disabled: 'disabled'
};
const orientations = {
'Horizontal (horizontal)': 'horizontal',
'Vertical (vertical)': 'vertical'
};
const labelPositions = {
'Left (left)': 'left',
'Right (right)': 'right'
};
export const Default = () => ({
Component,
props: {
group: {
name: text('The form control name (name in <RadioButtonGroup>)', 'radio-button-group'),
valueSelected: select(
'Value of the selected button (valueSelected in <RadioButtonGroup>)',
values,
'default-selected'
),
orientation: select('Radio button orientation (orientation)', orientations, 'horizontal'),
labelPosition: select('Label position (labelPosition)', labelPositions, 'right')
},
radio: {
disabled: boolean('Disabled (disabled in <RadioButton>)', false),
labelText: text('Label text (labelText in <RadioButton>)', 'Radio button label')
}
}
});

View file

@ -0,0 +1,46 @@
<script>
let className = undefined;
export { className as class };
export let orientation = 'horizontal';
export let labelPosition = 'right';
export let defaultSelected = undefined;
export let disabled = false;
export let style = undefined;
import { createEventDispatcher, setContext } from 'svelte';
import { writable } from 'svelte/store';
import { cx } from '../../lib';
const dispatch = createEventDispatcher();
const _class = cx(
'--radio-button-group',
orientation === 'vertical' && `--radio-button-group--${orientation}`,
labelPosition && `--radio-button-group--label-${labelPosition}`,
className
);
let selected = writable(defaultSelected);
setContext('RadioButtonGroup', {
selected,
add: ({ checked, value }) => {
if (checked) {
selected.set(value);
}
},
update: value => {
selected.set(value);
}
});
$: {
defaultSelected = $selected;
dispatch('change', $selected);
}
</script>
<div on:click on:mouseover on:mouseenter on:mouseleave class={cx('--form-item')} {style}>
<div class={_class} {disabled}>
<slot />
</div>
</div>

View file

@ -0,0 +1,3 @@
import RadioButtonGroup from './RadioButtonGroup.svelte';
export default RadioButtonGroup;

View file

@ -25,6 +25,7 @@ import ProgressIndicator, {
ProgressStep
} from './components/ProgressIndicator';
import RadioButton, { RadioButtonSkeleton } from './components/RadioButton';
import RadioButtonGroup from './components/RadioButtonGroup';
import Search, { SearchSkeleton } from './components/Search';
import SkeletonPlaceholder from './components/SkeletonPlaceholder';
import SkeletonText from './components/SkeletonText';
@ -80,6 +81,7 @@ export {
ProgressStep,
RadioButton,
RadioButtonSkeleton,
RadioButtonGroup,
Search,
SearchSkeleton,
SelectableTile,