Skip to content
Snippets Groups Projects
Panel.svelte 3.04 KiB
Newer Older
<script lang="ts" generics="Tag extends keyof HTMLElementTagNameMap">
	type Props = {
		tag?: Tag;
		variant?: 'primary' | 'secondary' | 'success' | 'error' | 'emphasis' | 'default';
		space?: 'none' | 'sm' | 'md' | 'lg';
		shadow?: 'none' | 'sm' | 'md' | 'lg';
		borderless?: boolean;
		rounded?: boolean;
		hover?: boolean;
		active?: boolean;
		disabled?: boolean;
		flat?: boolean;
		full?: boolean;
	} & HTMLElement;

	const {
		// @ts-ignore
		tag = 'div',
		variant = 'default',
		space = 'md',
		shadow = 'md',
		borderless = false,
		rounded = false,
		hover = false,
		active = false,
		disabled = false,
		full = false,
		flat = false,
		class: className,
		children = null,
		...rest
	}: Props<Tag> = $props();
</script>

<svelte:element
	this={tag}
	class={[
		'panel',
		className,
		{
			'shadow-sm': shadow === 'sm',
			'shadow-md': shadow === 'md',
			'shadow-lg': shadow === 'lg',
			hover,
			active,
			full,
			rounded,
			borderless,
			disabled,
			flat
		},
		space,
		variant
	]}
	{disabled}
	{...rest}
>
	{@render children?.()}
</svelte:element>

<style>
	.panel {
		--component-background: var(--colour-background);
		--component-colour: var(--colour-contrast);

		display: inline-block;
		padding: var(--spacing-md);
		background-color: var(--component-background);
		color: var(--component-colour);
		border: var(--border-width) var(--border-style) var(--border-colour);
		transition: all var(--transition-medium);
	}

	.panel:not(.flat) {
		transform: translate3d(0, 0, 0);
		box-shadow: var(--shadow-md);
	}

	.panel.primary {
		--component-background: var(--colour-primary);
	}
	.panel.secondary {
		--component-background: var(--colour-secondary);
	}
	.panel.success {
		--component-background: var(--colour-success);
	}
	.panel.error {
		--component-background: var(--colour-error);
	}
	.panel.emphasis {
		--component-background: var(--colour-emphasis);
	}
	.panel.brick {
		--component-background: var(--colour-brick);
	}
	.panel.slate {
		--component-background: var(--colour-slate);
		--component-colour: var(--colour-concrete);
	}
	.panel.mustard {
		--component-background: var(--colour-mustard);
	}
	.panel.pastel {
		--component-background: var(--colour-pastel);
	}
	.panel.neon {
		--component-background: var(--colour-neon);
	}

	.panel.none {
		padding: 0;
	}
	.panel.sm {
		padding: var(--spacing-sm);
	}
	.panel.lg {
		padding: var(--spacing-lg);
	}

	.panel.shadow-sm:not(.flat) {
		box-shadow: var(--shadow-sm);
	}
	.panel.shadow-md:not(.flat) {
		box-shadow: var(--shadow-md);
	}
	.panel.shadow-lg:not(.flat) {
		box-shadow: var(--shadow-lg);
	}

	.panel.borderless {
		border: none;
	}
	.panel.rounded {
		border-radius: var(--spacing-sm);
	}

	.panel.hover:hover:not(.disabled):not(.flat) {
		transform: translate3d(-2px, -2px, 0);
		box-shadow: var(--shadow-lg);
	}

	.panel.hover.active:hover:not(.disabled):not(.flat) {
		transform: translate3d(2px, 2px, 0);
		box-shadow: var(--shadow-sm);
	}

	.panel.hover.active:active:not(.disabled):not(.flat) {
		transform: translate3d(5px, 5px, 0);
		box-shadow: none;
	}

	.panel.full {
		width: 100%;
	}
</style>