mirror of https://github.com/sveltejs/svelte
parent
2d1475600d
commit
9cfe0593d4
@ -0,0 +1,17 @@
|
|||||||
|
<script>
|
||||||
|
import { getContext, onDestroy } from 'svelte';
|
||||||
|
import { TABS } from './Tabs.html';
|
||||||
|
|
||||||
|
const tab = {};
|
||||||
|
const { registerTab, unregisterTab, selectTab, selectedTab } = getContext(TABS);
|
||||||
|
|
||||||
|
registerTab(tab);
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
unregisterTab(tab);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button class:selected={$selectedTab} on:click="{() => selectTab(tab)}">
|
||||||
|
<slot></slot>
|
||||||
|
</button>
|
@ -0,0 +1,3 @@
|
|||||||
|
<div class="tab-list">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
import { getContext, onDestroy } from 'svelte';
|
||||||
|
import { TABS } from './Tabs.html';
|
||||||
|
|
||||||
|
const panel = {};
|
||||||
|
const { registerPanel, unregisterPanel, selectedPanel } = getContext(TABS);
|
||||||
|
registerPanel(panel);
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
unregisterPanel(panel);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $selected === panel}
|
||||||
|
<slot></slot>
|
||||||
|
{/if}
|
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<script context="module">
|
||||||
|
export const TABS = {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { setContext } from 'svelte';
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
const tabs = [];
|
||||||
|
const panels = [];
|
||||||
|
const selected = writable(null);
|
||||||
|
|
||||||
|
setContext(TABS, {
|
||||||
|
registerTab: tab => {
|
||||||
|
tabs.push(tab);
|
||||||
|
},
|
||||||
|
|
||||||
|
unregisterTab: tab => {
|
||||||
|
const i = tabs.indexOf(tab);
|
||||||
|
tabs.splice(i, 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
registerPanel: panel => {
|
||||||
|
panels.push(panel);
|
||||||
|
|
||||||
|
// if this is the first panel, select it
|
||||||
|
selected.update(current => current || panel);
|
||||||
|
},
|
||||||
|
|
||||||
|
unregisterPanel: panel => {
|
||||||
|
const i = panels.indexOf(panel);
|
||||||
|
panels.splice(i, 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectTab: tab => {
|
||||||
|
const i = tabs.indexOf(tab);
|
||||||
|
selected.set(panels[i]);
|
||||||
|
},
|
||||||
|
|
||||||
|
selected
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="tabs">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
@ -0,0 +1,73 @@
|
|||||||
|
export default {
|
||||||
|
html: `
|
||||||
|
<div class="tabs">
|
||||||
|
<div class="tab-list">
|
||||||
|
<button class="selected">small</button>
|
||||||
|
<button>large</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Small panel</h2>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
|
||||||
|
async test({ assert, component, target, window }) {
|
||||||
|
const click = new window.MouseEvent('click');
|
||||||
|
let buttons = target.querySelectorAll('button');
|
||||||
|
|
||||||
|
await buttons[1].dispatchEvent(click);
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, `
|
||||||
|
<div class="tabs">
|
||||||
|
<div class="tab-list">
|
||||||
|
<button>small</button>
|
||||||
|
<button class="selected">large</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Large panel</h2>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
component.show_medium = true;
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, `
|
||||||
|
<div class="tabs">
|
||||||
|
<div class="tab-list">
|
||||||
|
<button>small</button>
|
||||||
|
<button>medium</button>
|
||||||
|
<button class="selected">large</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Large panel</h2>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
buttons = target.querySelectorAll('button');
|
||||||
|
|
||||||
|
await buttons[1].dispatchEvent(click);
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, `
|
||||||
|
<div class="tabs">
|
||||||
|
<div class="tab-list">
|
||||||
|
<button>small</button>
|
||||||
|
<button class="selected">medium</button>
|
||||||
|
<button>large</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Medium panel</h2>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
component.show_medium = false;
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, `
|
||||||
|
<div class="tabs">
|
||||||
|
<div class="tab-list">
|
||||||
|
<button>small</button>
|
||||||
|
<button class="selected">large</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Large panel</h2>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,30 @@
|
|||||||
|
<script>
|
||||||
|
import Tabs from './Tabs.html';
|
||||||
|
import TabList from './TabList.html';
|
||||||
|
import Tab from './Tab.html';
|
||||||
|
import TabPanel from './TabPanel.html';
|
||||||
|
|
||||||
|
export let show_medium = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabList>
|
||||||
|
<Tab>small</Tab>
|
||||||
|
{#if show_medium}<Tab>medium</Tab>{/if}
|
||||||
|
<Tab>large</Tab>
|
||||||
|
</TabList>
|
||||||
|
|
||||||
|
<TabPanel>
|
||||||
|
<h2>Small panel</h2>
|
||||||
|
</TabPanel>
|
||||||
|
|
||||||
|
{#if show_medium}
|
||||||
|
<TabPanel>
|
||||||
|
<h2>Medium panel</h2>
|
||||||
|
</TabPanel>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<TabPanel>
|
||||||
|
<h2>Large panel</h2>
|
||||||
|
</TabPanel>
|
||||||
|
</Tabs>
|
Loading…
Reference in new issue