Code

1 minutes to read May 1, 2023 154 reads

Tab Component for Svelte/SvelteKit

Imran Molla Joy

cover image of Tab Component for Svelte/SvelteKit

A tab is a versetile element to pack many related info without taking up many space. Let’s make one for Svelte/Sveltekit which can be reused in any of your future projects.

Final Result

Demands rising, not supply

10 Memes of All Time

MUST SEE: Redditor eats raw salt

More

Code

<script lang="ts">
	type Item = {
		/**
		 * The name of the tab
		 */
		name: string;
	};
	import { createEventDispatcher } from 'svelte';
	const dispatch = createEventDispatcher();

	/**
	 * The items of the tab component
	 */
	export let items: Item[] = [];
	/**
	 * The currently selected tab.
	 */
	export let selected = items[0].name;
</script>

<div class="tabs">
	{#each items as item}
		<!-- svelte-ignore a11y-missing-attribute -->
		<!-- svelte-ignore a11y-click-events-have-key-events -->
		<!-- svelte-ignore a11y-interactive-supports-focus -->
		<a
			class="tab"
			data-sveltekit-noscroll
			class:active={selected === item.name}
			role="tab"
			on:click={() => {
				dispatch('tabChanged', item.name);
			}}
		>
			<span>{item.name}</span>
		</a>
	{/each}
</div>
<div class="tab-panel">
	<slot />
</div>

<style>
	:root {
		--active: cyan;
		--on-active: black;
	}
	.tabs {
		width: 100%;
		display: flex;
		flex-wrap: nowrap;
		gap: 1rem;
		border-bottom: 1px solid var(--active);
	}
	a {
		text-decoration: none !important;
	}

	.tab {
		padding: 0.5rem;
		border-radius: 1rem 1rem 0 0;
	}
	.tab.active {
		background-color: var(--active);
		color: var(--on-active) !important;
	}
	.tab-panel {
		padding: 1rem;
		border: 1px solid var(--active);
		border-radius: 0 0 1rem 1rem;
	}
</style>

Usage

<script lang="ts">
	import Tabs from './Tabs.svelte';

	const tabItems = [{ name: 'Latest' }, { name: 'Popular' }, { name: 'Breaking' }];

	let selected = tabItems[0].name;
	function tabChanged(e) {
		selected = e.detail;
	}
</script>

<Tabs on:tabChanged={tabChanged} items={tabItems} {selected}>
	{#if selected === tabItems[0].name}
		<h4>Demands rising, not supply</h4>
		<h4>10 Memes of All Time</h4>
		<h4>MUST SEE: Redditor eats raw salt</h4>
		<p>More</p>
	{/if}
	{#if selected === tabItems[1].name}
		<h4>Protest in Pluto, Civilians Want Immediate Action</h4>
		<h4>Scientists Discover Sleeping is A Phenomenon Among All Animals</h4>
		<h4>Wild Ants Wreck Havoc in Mars Capital</h4>
		<p>More</p>
	{/if}
	{#if selected === tabItems[2].name}
		<h4>Breaking is Bad</h4>
	{/if}
</Tabs>

Last updated: May 1, 2023