mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 18:01:06 +00:00
Merge pull request #48 from metonym/content-switcher
feat(components): add ContentSwitcher, Switch
This commit is contained in:
commit
1b1c3c6cb6
7 changed files with 155 additions and 0 deletions
|
@ -22,6 +22,8 @@ Currently, the following components are supported:
|
||||||
- CheckboxSkeleton
|
- CheckboxSkeleton
|
||||||
- CodeSnippet
|
- CodeSnippet
|
||||||
- CodeSnippetSkeleton
|
- CodeSnippetSkeleton
|
||||||
|
- ContentSwitcher
|
||||||
|
- Switch
|
||||||
- Copy
|
- Copy
|
||||||
- CopyButton
|
- CopyButton
|
||||||
- DataTableSkeleton
|
- DataTableSkeleton
|
||||||
|
|
23
src/components/ContentSwitcher/ContentSwitcher.Story.svelte
Normal file
23
src/components/ContentSwitcher/ContentSwitcher.Story.svelte
Normal 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>
|
19
src/components/ContentSwitcher/ContentSwitcher.stories.js
Normal file
19
src/components/ContentSwitcher/ContentSwitcher.stories.js
Normal 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)
|
||||||
|
}
|
||||||
|
});
|
54
src/components/ContentSwitcher/ContentSwitcher.svelte
Normal file
54
src/components/ContentSwitcher/ContentSwitcher.svelte
Normal 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>
|
50
src/components/ContentSwitcher/Switch.svelte
Normal file
50
src/components/ContentSwitcher/Switch.svelte
Normal 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>
|
4
src/components/ContentSwitcher/index.js
Normal file
4
src/components/ContentSwitcher/index.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import ContentSwitcher from './ContentSwitcher.svelte';
|
||||||
|
|
||||||
|
export default ContentSwitcher;
|
||||||
|
export { default as Switch } from './Switch.svelte';
|
|
@ -2,6 +2,7 @@ import Accordion, { AccordionItem, AccordionSkeleton } from './components/Accord
|
||||||
import Breadcrumb, { BreadcrumbItem, BreadcrumbSkeleton } from './components/Breadcrumb';
|
import Breadcrumb, { BreadcrumbItem, BreadcrumbSkeleton } from './components/Breadcrumb';
|
||||||
import Button, { ButtonSkeleton } from './components/Button';
|
import Button, { ButtonSkeleton } from './components/Button';
|
||||||
import Checkbox, { CheckboxSkeleton } from './components/Checkbox';
|
import Checkbox, { CheckboxSkeleton } from './components/Checkbox';
|
||||||
|
import ContentSwitcher, { Switch } from './components/ContentSwitcher';
|
||||||
import Copy from './components/Copy';
|
import Copy from './components/Copy';
|
||||||
import CopyButton from './components/CopyButton';
|
import CopyButton from './components/CopyButton';
|
||||||
import CodeSnippet, { CodeSnippetSkeleton } from './components/CodeSnippet';
|
import CodeSnippet, { CodeSnippetSkeleton } from './components/CodeSnippet';
|
||||||
|
@ -46,6 +47,7 @@ export {
|
||||||
ClickableTile,
|
ClickableTile,
|
||||||
CodeSnippet,
|
CodeSnippet,
|
||||||
CodeSnippetSkeleton,
|
CodeSnippetSkeleton,
|
||||||
|
ContentSwitcher,
|
||||||
Copy,
|
Copy,
|
||||||
CopyButton,
|
CopyButton,
|
||||||
DataTableSkeleton,
|
DataTableSkeleton,
|
||||||
|
@ -63,6 +65,7 @@ export {
|
||||||
SelectableTile,
|
SelectableTile,
|
||||||
SkeletonPlaceholder,
|
SkeletonPlaceholder,
|
||||||
SkeletonText,
|
SkeletonText,
|
||||||
|
Switch,
|
||||||
Tag,
|
Tag,
|
||||||
TagSkeleton,
|
TagSkeleton,
|
||||||
TextArea,
|
TextArea,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue