Merge pull request #48 from metonym/content-switcher

feat(components): add ContentSwitcher, Switch
This commit is contained in:
Eric Liu 2019-12-20 16:37:12 -08:00 committed by GitHub
commit 1b1c3c6cb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 155 additions and 0 deletions

View file

@ -22,6 +22,8 @@ Currently, the following components are supported:
- CheckboxSkeleton
- CodeSnippet
- CodeSnippetSkeleton
- ContentSwitcher
- Switch
- Copy
- CopyButton
- DataTableSkeleton

View file

@ -0,0 +1,23 @@
<script>
export let story = undefined;
import Layout from '../../internal/ui/Layout.svelte';
import ContentSwitcher from './ContentSwitcher.svelte';
import Switch from './Switch.svelte';
</script>
<Layout>
{#if story === 'selected'}
<ContentSwitcher>
<Switch {...$$props} text="First section" />
<Switch {...$$props} text="Second section" selected />
<Switch {...$$props} text="Third section" />
</ContentSwitcher>
{:else}
<ContentSwitcher>
<Switch {...$$props} text="First section" />
<Switch {...$$props} text="Second section" />
<Switch {...$$props} text="Third section" />
</ContentSwitcher>
{/if}
</Layout>

View file

@ -0,0 +1,19 @@
import { withKnobs, boolean } from '@storybook/addon-knobs';
import Component from './ContentSwitcher.Story.svelte';
export default { title: 'ContentSwitcher', decorators: [withKnobs] };
export const Default = () => ({
Component,
props: {
disabled: boolean('Disabled (disabled)', false)
}
});
export const Selected = () => ({
Component,
props: {
story: 'selected',
disabled: boolean('Disabled (disabled)', false)
}
});

View file

@ -0,0 +1,54 @@
<script>
export let className = undefined;
export { className as class };
export let selectedIndex = 0;
export let style = undefined;
import { createEventDispatcher, setContext } from 'svelte';
import { writable } from 'svelte/store';
import { cx } from '../../lib';
const dispatch = createEventDispatcher();
const _class = cx('--content-switcher', className);
let currentId = writable(null);
let currentIndex = selectedIndex;
let switches = [];
setContext('ContentSwitcher', {
currentId,
add: ({ id, text, selected }) => {
switches = [...switches, { id, text, selected }];
if (selected) {
currentIndex = switches.length;
}
},
update: id => {
currentIndex = switches.map(({ id }) => id).indexOf(id);
},
change: direction => {
let index = currentIndex + direction;
if (index < 0) {
index = switches.length - 1;
} else if (index >= switches.length) {
index = 0;
}
currentIndex = index;
}
});
$: if (switches[currentIndex]) {
selectedIndex = currentIndex;
currentId.set(switches[currentIndex].id);
switches = switches.map((_, i) => ({ ..._, selected: i === currentIndex }));
const { id, ...rest } = switches[currentIndex];
dispatch('change', { ...rest, index: currentIndex });
}
</script>
<div role="tablist" on:click on:mouseover on:mouseenter on:mouseleave class={_class} {style}>
<slot />
</div>

View file

@ -0,0 +1,50 @@
<script>
let className = undefined;
export { className as class };
export let selected = false;
export let text = 'Provide text';
export let style = undefined;
export let disabled = false;
import { cx } from '../../lib';
import { getContext } from 'svelte';
const id = Math.random();
const { currentId, add, update, change } = getContext('ContentSwitcher');
let buttonRef = undefined;
add({ id, text, selected });
$: selected = $currentId === id;
$: if (selected && buttonRef) {
buttonRef.focus();
}
$: _class = cx('--content-switcher-btn', selected && '--content-switcher--selected', className);
</script>
<button
bind:this={buttonRef}
role="tab"
tabindex={selected ? '0' : '-1'}
aria-selected={selected}
class={_class}
on:click
on:click|preventDefault={() => {
update(id);
}}
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
on:keydown={event => {
if (event.key === 'ArrowRight') {
change(1);
} else if (event.key === 'ArrowLeft') {
change(-1);
}
}}
{disabled}
{style}>
<span class={cx('--content-switcher__label')}>{text}</span>
</button>

View file

@ -0,0 +1,4 @@
import ContentSwitcher from './ContentSwitcher.svelte';
export default ContentSwitcher;
export { default as Switch } from './Switch.svelte';

View file

@ -2,6 +2,7 @@ import Accordion, { AccordionItem, AccordionSkeleton } from './components/Accord
import Breadcrumb, { BreadcrumbItem, BreadcrumbSkeleton } from './components/Breadcrumb';
import Button, { ButtonSkeleton } from './components/Button';
import Checkbox, { CheckboxSkeleton } from './components/Checkbox';
import ContentSwitcher, { Switch } from './components/ContentSwitcher';
import Copy from './components/Copy';
import CopyButton from './components/CopyButton';
import CodeSnippet, { CodeSnippetSkeleton } from './components/CodeSnippet';
@ -46,6 +47,7 @@ export {
ClickableTile,
CodeSnippet,
CodeSnippetSkeleton,
ContentSwitcher,
Copy,
CopyButton,
DataTableSkeleton,
@ -63,6 +65,7 @@ export {
SelectableTile,
SkeletonPlaceholder,
SkeletonText,
Switch,
Tag,
TagSkeleton,
TextArea,