mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-16 02:41:05 +00:00
chore: lift components folder
This commit is contained in:
parent
76df51674d
commit
2200b29b92
301 changed files with 57 additions and 76 deletions
58
src/Tabs/Tab.svelte
Normal file
58
src/Tabs/Tab.svelte
Normal file
|
@ -0,0 +1,58 @@
|
|||
<script>
|
||||
export let disabled = false;
|
||||
export let href = "#";
|
||||
export let label = "";
|
||||
export let role = "presentation";
|
||||
export let tabindex = "0";
|
||||
export let id = "ccs-" + Math.random().toString(36);
|
||||
export let ref = null;
|
||||
|
||||
import { getContext } from "svelte";
|
||||
|
||||
const { selectedTab, add, update, change } = getContext("Tabs");
|
||||
|
||||
add({ id, label, disabled });
|
||||
|
||||
$: selected = $selectedTab === id;
|
||||
$: if (selected && ref) {
|
||||
ref.focus();
|
||||
}
|
||||
</script>
|
||||
|
||||
<li
|
||||
tabindex="-1"
|
||||
{role}
|
||||
class:bx--tabs__nav-item={true}
|
||||
class:bx--tabs__nav-item--disabled={disabled}
|
||||
class:bx--tabs__nav-item--selected={selected}
|
||||
{...$$restProps}
|
||||
on:click|preventDefault={() => {
|
||||
if (!disabled) {
|
||||
update(id);
|
||||
}
|
||||
}}
|
||||
on:mouseover
|
||||
on:mouseenter
|
||||
on:mouseleave
|
||||
on:keydown={({ key }) => {
|
||||
if (!disabled) {
|
||||
if (key === 'ArrowRight') {
|
||||
change(1);
|
||||
} else if (key === 'ArrowLeft') {
|
||||
change(-1);
|
||||
} else if (key === ' ' || key === 'Enter') {
|
||||
update(id);
|
||||
}
|
||||
}
|
||||
}}>
|
||||
<a
|
||||
bind:this={ref}
|
||||
role="tab"
|
||||
tabindex={disabled ? '-1' : tabindex}
|
||||
aria-selected={selected}
|
||||
aria-disabled={disabled}
|
||||
{href}
|
||||
class:bx--tabs__nav-link={true}>
|
||||
{label}
|
||||
</a>
|
||||
</li>
|
19
src/Tabs/TabContent.svelte
Normal file
19
src/Tabs/TabContent.svelte
Normal file
|
@ -0,0 +1,19 @@
|
|||
<script>
|
||||
export let id = "ccs-" + Math.random().toString(36);
|
||||
import { getContext } from "svelte";
|
||||
|
||||
const { selectedContent, addContent } = getContext("Tabs");
|
||||
|
||||
addContent({ id });
|
||||
|
||||
$: selected = $selectedContent === id;
|
||||
</script>
|
||||
|
||||
<div
|
||||
aria-hidden={!selected}
|
||||
hidden={!selected}
|
||||
class:bx--tab-content={true}
|
||||
class={$$restProps.class}
|
||||
style={$$restProps.style}>
|
||||
<slot />
|
||||
</div>
|
40
src/Tabs/Tabs.Story.svelte
Normal file
40
src/Tabs/Tabs.Story.svelte
Normal file
|
@ -0,0 +1,40 @@
|
|||
<script>
|
||||
export let story = undefined;
|
||||
|
||||
import Tab from "./Tab.svelte";
|
||||
import TabContent from "./TabContent.svelte";
|
||||
import Tabs from "./Tabs.svelte";
|
||||
import TabsSkeleton from "./TabsSkeleton.svelte";
|
||||
|
||||
const { tabProps, ...tabsProps } = $$props;
|
||||
|
||||
$: selected = 0;
|
||||
</script>
|
||||
|
||||
{#if story === 'skeleton'}
|
||||
<TabsSkeleton />
|
||||
{:else if story === 'container'}
|
||||
<Tabs {...tabsProps} type="container" bind:selected>
|
||||
<Tab {...tabProps} label="Tab label 1" />
|
||||
<Tab {...tabProps} label="Tab label 2" />
|
||||
<Tab {...tabProps} label="Tab label 3" />
|
||||
<div slot="content">
|
||||
<TabContent>Content 1</TabContent>
|
||||
<TabContent>Content 2</TabContent>
|
||||
<TabContent>Content 3</TabContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
{:else}
|
||||
<Tabs {...tabsProps} bind:selected>
|
||||
<Tab {...tabProps} label="Tab label 1" />
|
||||
<Tab {...tabProps} label="Tab label 2" />
|
||||
<Tab {...tabProps} label="Tab label 3" disabled />
|
||||
<Tab {...tabProps} label="Tab label 4" />
|
||||
<div slot="content">
|
||||
<TabContent>Content 1</TabContent>
|
||||
<TabContent>Content 2</TabContent>
|
||||
<TabContent>Content 3</TabContent>
|
||||
<TabContent>Content 4</TabContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
{/if}
|
48
src/Tabs/Tabs.stories.js
Normal file
48
src/Tabs/Tabs.stories.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { withKnobs, boolean, number, text } from "@storybook/addon-knobs";
|
||||
import Component from "./Tabs.Story.svelte";
|
||||
|
||||
export default { title: "Tabs", decorators: [withKnobs] };
|
||||
|
||||
export const Default = () => ({
|
||||
Component,
|
||||
props: {
|
||||
tabProps: {
|
||||
disabled: boolean("Disabled (disabled in <Tab>)", false),
|
||||
href: text("The href for tab (href in <Tab>)", "#"),
|
||||
role: text("ARIA role (role in <Tab>)", "presentation"),
|
||||
tabindex: text("Tab index (tabindex in <Tab>)", "0"),
|
||||
},
|
||||
tabsProps: {
|
||||
className: "some-class",
|
||||
selected: number("The index of the selected tab (selected in <Tabs>)", 1),
|
||||
triggerHref: text(
|
||||
"The href of trigger button for narrow mode (triggerHref in <Tabs>)",
|
||||
"#"
|
||||
),
|
||||
role: text("ARIA role (role in <Tabs>)", "navigation"),
|
||||
iconDescription: text(
|
||||
"The description of the trigger icon for narrow mode (iconDescription in <Tabs>)",
|
||||
"show menu options"
|
||||
),
|
||||
tabContentClassName: text(
|
||||
"The className for the child `<TabContent>` components",
|
||||
"tab-content"
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const Container = () => ({
|
||||
Component,
|
||||
props: {
|
||||
story: "container",
|
||||
tabProps: {
|
||||
disabled: boolean("Disabled (disabled in <Tab>)", false),
|
||||
href: text("The href for tab (href in <Tab>)", "#"),
|
||||
role: text("ARIA role (role in <Tab>)", "presentation"),
|
||||
tabindex: text("Tab index (tabindex in <Tab>)", "0"),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const Skeleton = () => ({ Component, props: { story: "skeleton" } });
|
122
src/Tabs/Tabs.svelte
Normal file
122
src/Tabs/Tabs.svelte
Normal file
|
@ -0,0 +1,122 @@
|
|||
<script>
|
||||
export let iconDescription = "Show menu options";
|
||||
export let role = "navigation";
|
||||
export let selected = 0;
|
||||
export let triggerHref = "#";
|
||||
export let type = "default";
|
||||
|
||||
import { createEventDispatcher, afterUpdate, setContext } from "svelte";
|
||||
import { writable, derived } from "svelte/store";
|
||||
import ChevronDownGlyph from "carbon-icons-svelte/lib/ChevronDownGlyph";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let dropdownHidden = true;
|
||||
let tabs = writable([]);
|
||||
let tabsById = derived(tabs, _ =>
|
||||
_.reduce((a, c) => ({ ...a, [c.id]: c }), {})
|
||||
);
|
||||
let currentIndex = selected;
|
||||
let selectedTab = writable(undefined);
|
||||
let content = writable([]);
|
||||
let selectedContent = writable(undefined);
|
||||
|
||||
setContext("Tabs", {
|
||||
selectedTab,
|
||||
selectedContent,
|
||||
add: data => {
|
||||
tabs.update(_ => [..._, { ...data, index: _.length }]);
|
||||
},
|
||||
addContent: data => {
|
||||
content.update(_ => [..._, { ...data, index: _.length }]);
|
||||
},
|
||||
update: id => {
|
||||
currentIndex = $tabsById[id].index;
|
||||
},
|
||||
change: direction => {
|
||||
let index = currentIndex + direction;
|
||||
|
||||
if (index < 0) {
|
||||
index = $tabs.length - 1;
|
||||
} else if (index >= $tabs.length) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
let disabled = $tabs[index].disabled;
|
||||
|
||||
while (disabled) {
|
||||
index = index + direction;
|
||||
|
||||
if (index < 0) {
|
||||
index = $tabs.length - 1;
|
||||
} else if (index >= $tabs.length) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
disabled = $tabs[index].disabled;
|
||||
}
|
||||
|
||||
currentIndex = index;
|
||||
}
|
||||
});
|
||||
|
||||
afterUpdate(() => {
|
||||
selected = currentIndex;
|
||||
});
|
||||
|
||||
$: currentIndex = selected;
|
||||
$: currentTab = $tabs[currentIndex] || undefined;
|
||||
$: currentContent = $content[currentIndex] || undefined;
|
||||
$: {
|
||||
dispatch("change", currentIndex);
|
||||
|
||||
if (currentTab) {
|
||||
selectedTab.set(currentTab.id);
|
||||
}
|
||||
|
||||
if (currentContent) {
|
||||
selectedContent.set(currentContent.id);
|
||||
}
|
||||
}
|
||||
$: if ($selectedTab) {
|
||||
dropdownHidden = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
{role}
|
||||
class:bx--tabs={true}
|
||||
class:bx--tabs--container={type === 'container'}
|
||||
{...$$restProps}>
|
||||
<div
|
||||
role="listbox"
|
||||
tabindex="0"
|
||||
class:bx--tabs-trigger={true}
|
||||
aria-label={$$props['aria-label'] || 'listbox'}
|
||||
on:click={() => {
|
||||
dropdownHidden = !dropdownHidden;
|
||||
}}
|
||||
on:keypress
|
||||
on:keypress={() => {
|
||||
dropdownHidden = !dropdownHidden;
|
||||
}}>
|
||||
<a
|
||||
tabindex="-1"
|
||||
class:bx--tabs-trigger-text={true}
|
||||
href={triggerHref}
|
||||
on:click
|
||||
on:click={() => {
|
||||
dropdownHidden = !dropdownHidden;
|
||||
}}>
|
||||
{#if currentTab}{currentTab.label}{/if}
|
||||
</a>
|
||||
<ChevronDownGlyph aria-hidden="true" title={iconDescription} />
|
||||
</div>
|
||||
<ul
|
||||
role="tablist"
|
||||
class:bx--tabs__nav={true}
|
||||
class:bx--tabs__nav--hidden={dropdownHidden}>
|
||||
<slot />
|
||||
</ul>
|
||||
</div>
|
||||
<slot name="content" />
|
22
src/Tabs/TabsSkeleton.svelte
Normal file
22
src/Tabs/TabsSkeleton.svelte
Normal file
|
@ -0,0 +1,22 @@
|
|||
<div
|
||||
class:bx--tabs={true}
|
||||
class:bx--skeleton={true}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:mouseover
|
||||
on:mouseenter
|
||||
on:mouseleave>
|
||||
<div class:bx--tabs-trigger={true}>
|
||||
<div class:bx--tabs-trigger-text={true}> </div>
|
||||
<svg width="10" height="5" viewBox="0 0 10 5" fill-rule="evenodd">
|
||||
<path d="M10 0L5 5 0 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<ul class:bx--tabs__nav={true} class:bx--tabs__nav--hidden={true}>
|
||||
{#each [0, 1, 2, 3] as item, i (item)}
|
||||
<li class:bx--tabs__nav-item={true}>
|
||||
<div class:bx--tabs__nav-link={true}> </div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
4
src/Tabs/index.js
Normal file
4
src/Tabs/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
export { default as Tabs } from "./Tabs.svelte";
|
||||
export { default as Tab } from "./Tab.svelte";
|
||||
export { default as TabContent } from "./TabContent.svelte";
|
||||
export { default as TabsSkeleton } from "./TabsSkeleton.svelte";
|
Loading…
Add table
Add a link
Reference in a new issue