Format pass

This commit is contained in:
Nik
2022-09-06 11:46:11 +10:00
parent a87dec688b
commit c7c78e7858
79 changed files with 866 additions and 727 deletions

View File

@@ -19,15 +19,15 @@
},
"devDependencies": {
"@bobthered/tailwindcss-palette-generator": "^3.0.0",
"@sveltejs/adapter-auto": "^1.0.0-next.64",
"@sveltejs/adapter-static": "^1.0.0-next.39",
"@sveltejs/kit": "^1.0.0-next.415",
"@sveltejs/package": "^1.0.0-next.1",
"@tailwindcss/forms": "^0.5.2",
"@sveltejs/adapter-auto": "^1.0.0-next.71",
"@sveltejs/adapter-static": "^1.0.0-next.42",
"@sveltejs/kit": "^1.0.0-next.471",
"@sveltejs/package": "^1.0.0-next.3",
"@tailwindcss/forms": "^0.5.3",
"@testing-library/dom": "^8.17.1",
"@testing-library/svelte": "^3.2.1",
"@typescript-eslint/eslint-plugin": "^5.35.1",
"@typescript-eslint/parser": "^5.35.1",
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"autoprefixer": "^10.4.8",
"c8": "^7.12.0",
"eslint": "^7.32.0",
@@ -39,14 +39,14 @@
"postcss-load-config": "^3.1.4",
"prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.7.0",
"svelte": "^3.49.0",
"svelte": "^3.50.0",
"svelte-check": "^2.9.0",
"svelte-preprocess": "^4.10.7",
"svelte2tsx": "^0.5.15",
"svelte2tsx": "^0.5.16",
"tailwindcss": "^3.1.8",
"tslib": "^2.4.0",
"typescript": "^4.8.2",
"vite": "^3.0.9",
"vite": "^3.1.0",
"vitest": "^0.19.1"
},
"type": "module",

View File

@@ -29,7 +29,10 @@ Otherwise, update the respective style packs (core, typography, forms) so everyo
/* === NOTE: unique doc-only styles below: ==== */
html, body { @apply h-screen overflow-hidden; }
html,
body {
@apply h-screen overflow-hidden;
}
/* Gradient Background, via: https://csshero.org/mesher/ */
body {

View File

@@ -46,5 +46,7 @@
<style>
/* Hide the left-hande arrows for details/summary */
/* Note: let's keep this localized in case users want the arrows elsewhere */
details summary::-webkit-details-marker { display: none; }
details summary::-webkit-details-marker {
display: none;
}
</style>

View File

@@ -6,7 +6,7 @@
export let duration: number = 200; // ms
export let background: string = 'bg-accent-500/30';
export let border: string = 'border-l-accent-500';
export let color: string|undefined = undefined;
export let color: string | undefined = undefined;
export let radius: string = '';
// Base Classes
@@ -23,24 +23,24 @@
<div class="alert {classesCard}" transition:fade|local={{ duration }} data-testid="alert" role="alert" aria-live="polite">
<!-- Slot: Lead -->
{#if $$slots.lead}
<section class="{cLead}">
<section class={cLead}>
<slot name="lead" />
</section>
{/if}
<!-- Content -->
<section class="{cContent}">
<section class={cContent}>
<!-- Slot: Title -->
{#if $$slots.title}<h3><slot name="title"></slot></h3>{/if}
{#if $$slots.title}<h3><slot name="title" /></h3>{/if}
<!-- Slot: Message -->
{#if $$slots.message}
<div class="{color}"><slot name="message" /></div>
<div class={color}><slot name="message" /></div>
{/if}
</section>
<!-- Slot: Trail -->
{#if $$slots.trail}
<section class="{cTail}">
<section class={cTail}>
<slot name="trail" />
</section>
{/if}

View File

@@ -1,43 +1,35 @@
<script lang="ts">
// Props
export let background: string = 'bg-surface-100 dark:bg-surface-800';
export let border: string = '';
export let padding: string = 'px-4 py-4 md:py-6';
export let shadow: string = 'shadow-xl';
export let space: string = 'space-x-4';
// Props (a11y)
export let label: string|undefined = undefined;
export let labelledby: string|undefined = undefined;
// Props
export let background: string = 'bg-surface-100 dark:bg-surface-800';
export let border: string = '';
export let padding: string = 'px-4 py-4 md:py-6';
export let shadow: string = 'shadow-xl';
export let space: string = 'space-x-4';
// Props (a11y)
export let label: string | undefined = undefined;
export let labelledby: string | undefined = undefined;
// Base Classes
const cBase: string = 'flex items-center';
const cLead: string = 'flex-none flex justify-between items-center';
const cCenter: string = 'flex-auto';
const cTrail: string = 'flex-none flex items-center space-x-4';
// Base Classes
const cBase: string = 'flex items-center';
const cLead: string = 'flex-none flex justify-between items-center';
const cCenter: string = 'flex-auto';
const cTrail: string = 'flex-none flex items-center space-x-4';
// Reactive Classes
$: classesBase = `${cBase} ${background} ${border} ${padding} ${shadow} ${space}`;
// Reactive Classes
$: classesBase = `${cBase} ${background} ${border} ${padding} ${shadow} ${space}`;
</script>
<div
class="app-bar {classesBase} {$$props.class||''}"
data-testid="app-bar"
role="toolbar"
aria-label={label}
aria-labelledby={labelledby}
>
<div class="app-bar {classesBase} {$$props.class || ''}" data-testid="app-bar" role="toolbar" aria-label={label} aria-labelledby={labelledby}>
<!-- Slot: lead -->
{#if $$slots.lead}
<div class="appbar-lead {cLead}"><slot name="lead" /></div>
{/if}
<!-- Slot: lead -->
{#if $$slots.lead}
<div class="appbar-lead {cLead}"><slot name="lead"></slot></div>
{/if}
<!-- Slot: center -->
<div class="appbar-center {cCenter}"><slot /></div>
<!-- Slot: trail -->
{#if $$slots.trail}
<div class="appbar-trail {cTrail}"><slot name="trail"></slot></div>
{/if}
<!-- Slot: center -->
<div class="appbar-center {cCenter}"><slot /></div>
<!-- Slot: trail -->
{#if $$slots.trail}
<div class="appbar-trail {cTrail}"><slot name="trail" /></div>
{/if}
</div>

View File

@@ -14,13 +14,13 @@ describe('AppBar.svelte', () => {
const { getByTestId } = render(AppBar, {
props: {
background: 'bg-primary-500',
border: 'border border-accent-500',
padding: 'p-4',
shadow: 'shadow',
space: 'space-x-2',
// a11y
label: 'TestAppShell',
labelledby: 'TestLabelAppShell',
border: 'border border-accent-500',
padding: 'p-4',
shadow: 'shadow',
space: 'space-x-2',
// a11y
label: 'TestAppShell',
labelledby: 'TestLabelAppShell'
}
});
expect(getByTestId('app-bar')).toBeTruthy();

View File

@@ -1,58 +1,52 @@
<script lang="ts">
// Props
export let sidebarLeftWidth: string = 'w-auto';
export let sidebarRightWidth: string = 'w-auto';
// Props
export let sidebarLeftWidth: string = 'w-auto';
export let sidebarRightWidth: string = 'w-auto';
// Base Classes
const cBaseAppShell: string = 'w-full h-full flex flex-col overflow-hidden';
const cContentArea: string = 'w-full h-full flex overflow-hidden';
const cPage: string = 'flex-1 overflow-x-hidden overflow-y-auto';
const cSidebarLeft: string = 'flex-none overflow-x-hidden overflow-y-auto';
const cSidebarRight: string = 'flex-none overflow-x-hidden overflow-y-auto';
// Base Classes
const cBaseAppShell: string = 'w-full h-full flex flex-col overflow-hidden';
const cContentArea: string = 'w-full h-full flex overflow-hidden';
const cPage: string = 'flex-1 overflow-x-hidden overflow-y-auto';
const cSidebarLeft: string = 'flex-none overflow-x-hidden overflow-y-auto';
const cSidebarRight: string = 'flex-none overflow-x-hidden overflow-y-auto';
// Reactive Classes
$: classesSidebarLeft = `${cSidebarLeft} ${sidebarLeftWidth}`;
$: classesSidebarRight = `${cSidebarRight} ${sidebarRightWidth}`;
// Reactive Classes
$: classesSidebarLeft = `${cSidebarLeft} ${sidebarLeftWidth}`;
$: classesSidebarRight = `${cSidebarRight} ${sidebarRightWidth}`;
</script>
<main id="appShell" class="{cBaseAppShell}" data-testid="app-shell">
<main id="appShell" class={cBaseAppShell} data-testid="app-shell">
<!-- Slot: Header -->
{#if $$slots.header}
<header class="flex-none"><slot name="header" /></header>
{/if}
<!-- Slot: Header -->
{#if $$slots.header}
<header class="flex-none"><slot name="header"></slot></header>
{/if}
<!-- Content Area -->
<div class="flex-auto {cContentArea}">
<!-- Slot: Sidebar (left) -->
{#if $$slots.sidebarLeft}
<aside class="sidebar-left {classesSidebarLeft}"><slot name="sidebarLeft" /></aside>
{/if}
<!-- Content Area -->
<div class="flex-auto {cContentArea}">
<!-- Page -->
<div id="page" class={cPage}>
<!-- Slot: Page Header -->
{#if $$slots.pageHeader}
<header id="page-header"><slot name="pageHeader">(slot:header)</slot></header>
{/if}
<!-- Slot: Sidebar (left) -->
{#if $$slots.sidebarLeft}
<aside class="sidebar-left {classesSidebarLeft}"><slot name="sidebarLeft"></slot></aside>
{/if}
<!-- Slot: Page Content (default) -->
<div id="page-content"><slot /></div>
<!-- Page -->
<div id="page" class="{cPage}">
<!-- Slot: Page Header -->
{#if $$slots.pageHeader}
<header id="page-header"><slot name="pageHeader">(slot:header)</slot></header>
{/if}
<!-- Slot: Page Content (default) -->
<div id="page-content"><slot /></div>
<!-- Slot: Page Footer -->
{#if $$slots.pageFooter}
<footer id="page-footer"><slot name="pageFooter">(slot:footer)</slot></footer>
{/if}
</div>
<!-- Slot: Sidebar (right) -->
{#if $$slots.sidebarRight}
<aside class="sidebar-right {classesSidebarRight}"><slot name="sidebarRight"></slot></aside>
{/if}
</div>
<!-- Slot: Page Footer -->
{#if $$slots.pageFooter}
<footer id="page-footer"><slot name="pageFooter">(slot:footer)</slot></footer>
{/if}
</div>
<!-- Slot: Sidebar (right) -->
{#if $$slots.sidebarRight}
<aside class="sidebar-right {classesSidebarRight}"><slot name="sidebarRight" /></aside>
{/if}
</div>
</main>

View File

@@ -14,7 +14,7 @@ describe('AppShell.svelte', () => {
const { getByTestId } = render(AppShell, {
props: {
sidebarLeftWidth: 'w-auto',
sidebarRightWidth: 'w-auto',
sidebarRightWidth: 'w-auto'
}
});
expect(getByTestId('app-shell')).toBeTruthy();

View File

@@ -42,9 +42,9 @@
$: classesAvatar = `${cBase} ${cSize} ${background} ${color} ${cOutlined} ${cHover} ${$$props.class}`;
</script>
<figure on:click class="avatar {classesAvatar}" data-testid="avatar" >
<figure on:click class="avatar {classesAvatar}" data-testid="avatar">
{#if src}
<img class="w-full h-full object-cover" {src} alt={$$props.alt || 'avatar'} use:f.filter={filter||''} />
<img class="w-full h-full object-cover" {src} alt={$$props.alt || 'avatar'} use:f.filter={filter || ''} />
{:else}
<span class={cText}>{initials.substring(0, 2).toUpperCase()}</span>
{/if}

View File

@@ -8,7 +8,6 @@ import { fireEvent } from '@testing-library/dom';
let testImgSrc = 'https://i.pravatar.cc/512';
describe('Avatar.svelte', () => {
it('Renders with minimal props', async () => {
const { getByTestId } = render(Avatar);
expect(getByTestId('avatar')).toBeTruthy();
@@ -24,7 +23,7 @@ describe('Avatar.svelte', () => {
color: 'text-white-500',
outlined: true,
hover: true,
filter: '#Emerald',
filter: '#Emerald'
}
});
expect(getByTestId('avatar')).toBeTruthy();
@@ -47,7 +46,7 @@ describe('Avatar.svelte', () => {
const { getByTestId } = render(Avatar, {
props: { src: testImgSrc }
});
const imgSrc: string|undefined = getByTestId('avatar').querySelector('img')?.src;
const imgSrc: string | undefined = getByTestId('avatar').querySelector('img')?.src;
expect(imgSrc).to.eq(testImgSrc);
});

View File

@@ -17,7 +17,7 @@ describe('Badge.svelte', () => {
color: 'text-white',
fill: 'fill-white',
rounded: 'rounded',
icon: false,
icon: false
}
});
expect(getByTestId('badge')).toBeTruthy();

View File

@@ -11,12 +11,12 @@ describe('Breadcrumb.svelte', () => {
});
it('Renders with all props', () => {
const { getByTestId } = render(Breadcrumb, {
props: {
const { getByTestId } = render(Breadcrumb, {
props: {
separator: '|',
label: 'Test Divider'
},
});
expect(getByTestId('breadcrumb')).toBeTruthy();
}
});
expect(getByTestId('breadcrumb')).toBeTruthy();
});
});

View File

@@ -23,7 +23,7 @@ describe('Button.svelte', () => {
width: 'w-[200px]',
rounded: 'rounded',
label: 'testButton1',
describedby: 'testLabel1',
describedby: 'testLabel1'
}
});
expect(getByTestId).toBeTruthy();

View File

@@ -20,7 +20,7 @@
$: classesFooter = `${footer}`;
</script>
<div class="card {classesCard} {$$props.class||''}" data-testid="card">
<div class="card {classesCard} {$$props.class || ''}" data-testid="card">
<!-- Header -->
{#if $$slots.header}
<header class="card-header {classesHeader}"><slot name="header" /></header>

View File

@@ -14,7 +14,7 @@ describe('Card.svelte', () => {
const { getByTestId } = render(Card, {
props: {
background: 'bg-primary-500',
color: 'text-white',
color: 'text-white'
}
});
expect(getByTestId('card')).toBeTruthy();

View File

@@ -14,7 +14,9 @@
// Allow shorthand 'js' alias for Javascript
function languageFormatter(lang: string): string {
if (lang === 'js') { return 'javascript'; }
if (lang === 'js') {
return 'javascript';
}
return lang;
}

View File

@@ -20,7 +20,7 @@ describe('CodeBlock.svelte', () => {
props: {
language: 'js',
code: `console.log('Hello World');`,
background: 'bg-slate-800',
background: 'bg-slate-800'
}
});
expect(getByTestId('codeblock')).toBeTruthy();

View File

@@ -1,4 +1,4 @@
import { writable, type Writable } from "svelte/store";
import { writable, type Writable } from 'svelte/store';
export const storeHighlightJs: Writable<any> = writable(undefined);

View File

@@ -31,8 +31,11 @@
function setOrientation(): void {
// prettier-iignore
switch (orientation) {
case 'v': cOrientation = `border-0 ${cWeight[weight].v} h-full`; break;
default: cOrientation = `border-0 ${cWeight[weight].h} border-t w-full`;
case 'v':
cOrientation = `border-0 ${cWeight[weight].v} h-full`;
break;
default:
cOrientation = `border-0 ${cWeight[weight].h} border-t w-full`;
}
}

View File

@@ -9,18 +9,18 @@
export let duration: number = 150;
// Props (backdrop)
export let bgBackdrop: string = 'bg-surface-400/70 dark:bg-surface-900/70';
export let display: string|undefined = undefined;
export let display: string | undefined = undefined;
export let blur: string = 'backdrop-blur-sm';
// Props (drawer)
export let bgDrawer: string = 'bg-surface-100 dark:bg-surface-800';
export let border: string|undefined = undefined;
export let rounded: string|undefined = undefined;
export let width: string|undefined = undefined;
export let height: string|undefined = undefined;
export let margin: string|undefined = undefined;
export let border: string | undefined = undefined;
export let rounded: string | undefined = undefined;
export let width: string | undefined = undefined;
export let height: string | undefined = undefined;
export let margin: string | undefined = undefined;
// Props (a11y)
export let labelledby: string|undefined = undefined;
export let describedby: string|undefined = undefined;
export let labelledby: string | undefined = undefined;
export let describedby: string | undefined = undefined;
// Base Classes
const cBaseBackdrop: string = 'fixed top-0 left-0 right-0 bottom-0 z-40 flex';
@@ -32,15 +32,15 @@
// Set Animation Values
let animParams: any = { backdrop: '', width: '', height: '', x: 0, y: 0 };
function setAnimParams(): void {
switch(position) {
switch (position) {
// prettier-ignore
case('top'):
animParams = { backdrop: 'flex-col justify-start', width: 'w-full', height: 'h-[40%]', x: 0, y: -window.innerHeight };
break;
case('bottom'):
case 'bottom':
animParams = { backdrop: 'flex-col justify-end', width: 'w-full', height: 'h-[40%]', x: 0, y: window.innerHeight };
break;
case('right'):
case 'right':
animParams = { backdrop: 'justify-end', width: 'w-[80%]', height: 'h-full', x: window.innerWidth, y: 0 };
break;
// Default: Left
@@ -53,11 +53,15 @@
// Input Handlers
function onClickBackdrop(e: any): void {
// Limit to only backdrop element
if (e.target === elemBackdrop) { close(); }
if (e.target === elemBackdrop) {
close();
}
}
function onKeydownWindow(e: any): void {
if (!$open) return;
if (e.code === 'Escape') { close(); }
if (e.code === 'Escape') {
close();
}
}
// Close
@@ -66,8 +70,12 @@
}
// Lifecycle
onMount(() => { setAnimParams(); });
afterUpdate(() => { setAnimParams(); });
onMount(() => {
setAnimParams();
});
afterUpdate(() => {
setAnimParams();
});
// Reactive
$: classesWidth = width ? width : animParams.width;
@@ -79,26 +87,28 @@
<svelte:window on:keydown={onKeydownWindow} />
{#if $open}
<!-- Backdrop -->
<div
bind:this={elemBackdrop}
class="drawer-backdrop {classesBackdrop} {$$props.class||''}"
data-testid="drawer-backdrop"
on:click={(e) => { onClickBackdrop(e) }}
transition:fade|local={{ duration }}
>
<!-- Drawer -->
<!-- Backdrop -->
<div
class="drawer {classesDrawer} {$$props.class}"
data-testid="drawer"
transition:fly|local={{ x: animParams.x, y: animParams.y, duration }}
role="dialog"
aria-modal="true"
aria-labelledby={labelledby}
aria-describedby={describedby}
bind:this={elemBackdrop}
class="drawer-backdrop {classesBackdrop} {$$props.class || ''}"
data-testid="drawer-backdrop"
on:click={(e) => {
onClickBackdrop(e);
}}
transition:fade|local={{ duration }}
>
<!-- Slot: Default -->
<slot />
<!-- Drawer -->
<div
class="drawer {classesDrawer} {$$props.class}"
data-testid="drawer"
transition:fly|local={{ x: animParams.x, y: animParams.y, duration }}
role="dialog"
aria-modal="true"
aria-labelledby={labelledby}
aria-describedby={describedby}
>
<!-- Slot: Default -->
<slot />
</div>
</div>
</div>
{/if}

View File

@@ -9,7 +9,6 @@ import Drawer from '$lib/Drawer/Drawer.svelte';
const storeTest: Writable<boolean> = writable(true);
describe('Drawer.svelte', () => {
it('Renders when draw opened', async () => {
const { getByTestId } = render(Drawer, {
props: {
@@ -19,5 +18,4 @@ describe('Drawer.svelte', () => {
expect(getByTestId('drawer-backdrop')).toBeTruthy();
expect(getByTestId('drawer')).toBeTruthy();
});
});

View File

@@ -20,7 +20,7 @@ describe('GradientHeading.svelte', () => {
tag: 'h1',
direction: 'bg-gradient-to-r',
from: 'from-primary-500',
to: 'to-accent-500',
to: 'to-accent-500'
}
});
const elem: HTMLElement = getByTestId('gradient-heading');

View File

@@ -18,7 +18,7 @@ describe('List.svelte', () => {
tag: 'ul',
title: 'testTitle1',
label: 'testList1',
labelledby: 'testLabel1',
labelledby: 'testLabel1'
}
});
expect(getByTestId('list-group')).toBeTruthy();

View File

@@ -40,7 +40,9 @@
dispatch('keydown', event);
if (['Enter', 'Space'].includes(event.code)) {
event.preventDefault();
if (parentTag === 'nav') { elemItem.click(); }
if (parentTag === 'nav') {
elemItem.click();
}
}
}

View File

@@ -49,15 +49,16 @@ describe('ListItem.svelte', () => {
// TODO: we need to define the `value` prop here, not sure the syntax
it('Renders <nav> selection list item, single value', async () => {
const { getByTestId } = render(ListItem, { props: {
parentTag: 'nav',
selected: writable('foobar'),
highlight: 'hover:bg-accent-500/10',
hover: '!bg-accent-500',
} });
const { getByTestId } = render(ListItem, {
props: {
parentTag: 'nav',
selected: writable('foobar'),
highlight: 'hover:bg-accent-500/10',
hover: '!bg-accent-500'
}
});
const element: HTMLElement = getByTestId('list-row');
expect(element).toBeTruthy();
expect(element.className).to.contain('!bg-accent-500');
});
});

View File

@@ -15,7 +15,7 @@ describe('Logo.svelte', () => {
props: {
background: 'bg-primary-500',
color: 'text-white',
text: 'text-base font-bold',
text: 'text-base font-bold'
}
});
expect(getByTestId('logo')).toBeTruthy();

View File

@@ -15,7 +15,7 @@ describe('LogoCloud.svelte', () => {
props: {
background: 'bg-primary-500',
color: 'text-white',
text: 'text-base font-bold',
text: 'text-base font-bold'
}
});
expect(getByTestId('logo-cloud')).toBeTruthy();

View File

@@ -80,13 +80,7 @@
{#if $dialogStore.length}
<!-- Backdrop Shim -->
<div
class="dialog-backdrop {classesBackdrop} {$$props.class}"
on:click={onDialogClose}
on:keydown={onKeyPress}
transition:fade|local={{ duration }}
data-testid="dialog-backdrop"
>
<div class="dialog-backdrop {classesBackdrop} {$$props.class}" on:click={onDialogClose} on:keydown={onKeyPress} transition:fade|local={{ duration }} data-testid="dialog-backdrop">
<!-- Dialog -->
<div
bind:this={elemModal}

View File

@@ -2,31 +2,36 @@ import { render } from '@testing-library/svelte';
import { describe, it, expect } from 'vitest';
// @ts-ignore
import { dialogStore, DialogAlert, DialogConfirm, DialogPrompt} from '$lib/Notifications/Stores';
import { dialogStore, DialogAlert, DialogConfirm, DialogPrompt } from '$lib/Notifications/Stores';
// @ts-ignore
import Dialog from '$lib/Notifications/Dialog.svelte';
// Dialog Payloads
const dialogAlert: DialogAlert = {
title: 'Welcome to Skeleton.',
body: 'This is a standard alert dialog.',
title: 'Welcome to Skeleton.',
body: 'This is a standard alert dialog.'
};
const dialogConfirm: DialogConfirm = {
type: 'confirm',
title: 'Please Confirm',
body: 'Are you sure you wish to proceed?',
result: (r: boolean) => { console.log(r); }
type: 'confirm',
title: 'Please Confirm',
body: 'Are you sure you wish to proceed?',
result: (r: boolean) => {
console.log(r);
}
};
const dialogPrompt: DialogPrompt = {
type: 'prompt',
title: 'Enter Name',
body: 'Provide your first name in the field below.',
value: 'foobar',
result: (r: string) => { if (r) { console.log(r); }; }
type: 'prompt',
title: 'Enter Name',
body: 'Provide your first name in the field below.',
value: 'foobar',
result: (r: string) => {
if (r) {
console.log(r);
}
}
};
describe('Dialog.svelte', () => {
it('Renders dialog alert', async () => {
dialogStore.trigger(dialogAlert);
const { getByTestId } = render(Dialog);
@@ -47,5 +52,4 @@ describe('Dialog.svelte', () => {
expect(getByTestId('dialog-backdrop')).toBeTruthy();
expect(getByTestId('dialog')).toBeTruthy();
});
});

View File

@@ -2,25 +2,28 @@ import { render } from '@testing-library/svelte';
import { describe, it, expect } from 'vitest';
// @ts-ignore
import { toastStore, ToastMessage} from '$lib/Notifications/Stores';
import { toastStore, ToastMessage } from '$lib/Notifications/Stores';
// @ts-ignore
import Toast from '$lib/Notifications/Toast.svelte';
// Toast Payload
const toastMessage: ToastMessage = {
message: 'Your Message Here',
// Optional:
autohide: true,
timeout: 5000,
button: { label: 'Greeting', action: () => { alert('Hello, Skeleton'); }}
message: 'Your Message Here',
// Optional:
autohide: true,
timeout: 5000,
button: {
label: 'Greeting',
action: () => {
alert('Hello, Skeleton');
}
}
};
describe('Toast.svelte', () => {
it('Renders dialog alert', async () => {
toastStore.trigger(toastMessage);
const { getByTestId } = render(Toast);
expect(getByTestId('toast')).toBeTruthy();
});
});

View File

@@ -23,7 +23,7 @@ describe('Paginator.svelte', () => {
select: 'bg-primary-500',
// ---
variant: 'ghost-primary',
rounded: 'rounded',
rounded: 'rounded'
}
});
expect(getByTestId('paginator')).toBeTruthy();

View File

@@ -3,14 +3,14 @@
import { afterUpdate } from 'svelte';
// Props
export let value: number|undefined = undefined; // %
export let value: number | undefined = undefined; // %
export let stroke: number = 20; // px
export let track: string = 'stroke-surface-300 dark:stroke-surface-700';
export let meter: string = 'stroke-black dark:stroke-white';
export let color: string = 'fill-black dark:fill-white';
export let font: number = 56; // px
// Ally
export let label: string|undefined = undefined;
export let label: string | undefined = undefined;
// Base Classes
const cBaseTrack: string = 'fill-transparent';

View File

@@ -13,13 +13,13 @@ describe('ProgressRadial.svelte', () => {
it('Renders with all props', () => {
const { getByTestId } = render(ProgressRadial, {
props: {
value: 50,
stroke: 20,
track: 'stroke-surface-300 dark:stroke-surface-700',
meter: 'stroke-black dark:stroke-white',
color: 'fill-black dark:fill-white',
font: 56,
label: 'testProgressRadial1',
value: 50,
stroke: 20,
track: 'stroke-surface-300 dark:stroke-surface-700',
meter: 'stroke-black dark:stroke-white',
color: 'fill-black dark:fill-white',
font: 56,
label: 'testProgressRadial1'
}
});
expect(getByTestId('progress-radial')).toBeTruthy();

View File

@@ -10,7 +10,7 @@ describe('RadioGroup.svelte', () => {
it('Renders with minimal props', async () => {
const { getByTestId } = render(RadioGroup, {
props: {
selected: writable(0),
selected: writable(0)
}
});
expect(getByTestId('radio-group')).toBeTruthy();
@@ -22,7 +22,7 @@ describe('RadioGroup.svelte', () => {
selected: writable(0),
background: 'bg-warning-500',
color: 'text-white',
width: 'w-auto',
width: 'w-auto'
}
});
expect(getByTestId('radio-group')).toBeTruthy();

View File

@@ -5,7 +5,6 @@ import { describe, it, expect } from 'vitest';
import RangeSlider from '$lib/RangeSlider/RangeSlider.svelte';
describe('RangeSlider.svelte', () => {
it('Renders with minimal props', async () => {
const { getByTestId } = render(RangeSlider);
expect(getByTestId('range-slider')).toBeTruthy();
@@ -22,7 +21,7 @@ describe('RangeSlider.svelte', () => {
value: 10,
label: 'testRangeSliderLabel1',
ticked: true,
accent: 'bg-primary-500',
accent: 'bg-primary-500'
}
});
expect(getByTestId('range-slider')).toBeTruthy();
@@ -39,6 +38,6 @@ describe('RangeSlider.svelte', () => {
const { getByTestId } = render(RangeSlider, {
props: { disabled: true }
});
expect(getByTestId('range-slider').querySelector('input')?.disabled).eq(true)
expect(getByTestId('range-slider').querySelector('input')?.disabled).eq(true);
});
});

View File

@@ -16,7 +16,7 @@ describe('SliderToggle.svelte', () => {
checked: true,
accent: 'bg-primary-500',
size: 'lg',
label: 'testSlideToggle1',
label: 'testSlideToggle1'
}
});
expect(getByTestId('slide-toggle')).toBeTruthy();

View File

@@ -1,6 +1,7 @@
<script context="module">
import { icons } from './icons';
</script>
<script lang="ts">
// Props
export let name: string = 'image';

View File

@@ -13,16 +13,16 @@ describe('SggIcon.svelte', () => {
it('Renders with all props', async () => {
const { getByTestId } = render(SvgIcon, {
name: 'image',
x: '0px',
y: '0px',
viewBox: '0 0 512 512',
// ---
fill: 'fill-black dark:fill-white',
width: 'w-5',
height: 'w-5',
// ---
title: 'testSvgIcon1',
tabindex: -1,
x: '0px',
y: '0px',
viewBox: '0 0 512 512',
// ---
fill: 'fill-black dark:fill-white',
width: 'w-5',
height: 'w-5',
// ---
title: 'testSvgIcon1',
tabindex: -1
});
expect(getByTestId('svg-icon')).toBeTruthy();
});

View File

@@ -161,6 +161,5 @@ export let icons: any = {
// Source: https://fontawesome.com/icons/rocket?s=solid&f=classic
rocket: {
path: 'M156.6 384.9L125.7 354c-8.5-8.5-11.5-20.8-7.7-32.2c3-8.9 7-20.5 11.8-33.8L24 288c-8.6 0-16.6-4.6-20.9-12.1s-4.2-16.7 .2-24.1l52.5-88.5c13-21.9 36.5-35.3 61.9-35.3l82.3 0c2.4-4 4.8-7.7 7.2-11.3C289.1-4.1 411.1-8.1 483.9 5.3c11.6 2.1 20.6 11.2 22.8 22.8c13.4 72.9 9.3 194.8-111.4 276.7c-3.5 2.4-7.3 4.8-11.3 7.2v82.3c0 25.4-13.4 49-35.3 61.9l-88.5 52.5c-7.4 4.4-16.6 4.5-24.1 .2s-12.1-12.2-12.1-20.9V380.8c-14.1 4.9-26.4 8.9-35.7 11.9c-11.2 3.6-23.4 .5-31.8-7.8zM384 168c22.1 0 40-17.9 40-40s-17.9-40-40-40s-40 17.9-40 40s17.9 40 40 40z'
},
}
};

View File

@@ -18,7 +18,7 @@ describe('Tab.svelte', () => {
selected: writable(0),
border: 'border-primary-500',
fill: 'fill-primary-500',
color: 'text-primary-500',
color: 'text-primary-500'
}
});
expect(getByTestId('tab')).toBeTruthy();

View File

@@ -21,7 +21,7 @@ describe('TabGroup.svelte', () => {
fill: 'fill-primary-500',
color: 'text-primary-500',
labeledby: 'testTabGroupLabel1',
label: 'testTabGroup1',
label: 'testTabGroup1'
}
});
expect(getByTestId('tab-group')).toBeTruthy();

View File

@@ -31,7 +31,7 @@ describe('DataTable.svelte', () => {
hover: 'hover:bg-primary-500/10',
// ---
labelledby: 'testDataTableLabel1',
describedby: 'testDataTablDescribed1',
describedby: 'testDataTablDescribed1'
}
});
expect(getByTestId('data-table')).toBeTruthy();

View File

@@ -12,10 +12,10 @@
export let rounded: string = 'rounded';
export let duration: number = 100; // ms
// Props (slots)
export let popup: string|undefined = undefined;
export let message: string|undefined = undefined;
export let arrow: string|undefined = undefined;
export let content: string|undefined = undefined;
export let popup: string | undefined = undefined;
export let message: string | undefined = undefined;
export let arrow: string | undefined = undefined;
export let content: string | undefined = undefined;
// Base Styles
const cBaseTooltip: string = 'relative inline-flex justify-center items-center';
@@ -92,7 +92,7 @@
<!-- Slot: Content -->
{#if $$slots.content}
<div class="{classesContent}" data-testid="content" on:mouseenter={onMouseEnter} on:mouseleave={onMouseLeave}>
<div class={classesContent} data-testid="content" on:mouseenter={onMouseEnter} on:mouseleave={onMouseLeave}>
<slot name="content" />
</div>
{/if}

View File

@@ -20,7 +20,7 @@ describe('Tooltip.svelte', () => {
width: 'w-auto',
whitespace: 'whitespace-nowrap',
rounded: 'rounded',
duration: 100,
duration: 100
}
});
expect(getByTestId('tooltip')).toBeTruthy();

View File

@@ -1,69 +1,71 @@
<script lang="ts">
// @ts-ignore
const pkg = __PACKAGE__;
// @ts-ignore
const pkg = __PACKAGE__;
import AppBar from '$lib/AppBar/AppBar.svelte';
import Badge from '$lib/Badge/Badge.svelte';
import LightSwitch from '$lib/LightSwitch/LightSwitch.svelte';
import SvgIcon from '$lib/SvgIcon/SvgIcon.svelte';
import AppBar from '$lib/AppBar/AppBar.svelte';
import Badge from '$lib/Badge/Badge.svelte';
import LightSwitch from '$lib/LightSwitch/LightSwitch.svelte';
import SvgIcon from '$lib/SvgIcon/SvgIcon.svelte';
// Stores
import { storeMobileDrawer } from '$lib/_documentation/stores';
// Stores
import { storeMobileDrawer } from '$lib/_documentation/stores';
// Drawer Handler
function drawerOpen(): void { storeMobileDrawer.set(true); };
// Drawer Handler
function drawerOpen(): void {
storeMobileDrawer.set(true);
}
</script>
<AppBar border="border-b border-b-surface-300 dark:border-b-surface-900">
<!-- Branding -->
<svelte:fragment slot="lead">
<!-- Drawer Menu -->
<div on:click={drawerOpen} class="lg:hidden mr-2 p-1 cursor-pointer">
<SvgIcon name="bars" width="w-6" height="h-6" fill="fill-black dark:fill-white" on:click={drawerOpen} />
</div>
<!-- Skeleton -->
<a href="/" class="text-sm sm:text-lg md:text-3xl font-bold uppercase mr-4" title="Return to Homepage">Skeleton</a>
<!-- Badge -->
<a class="hidden sm:block" href="https://github.com/Brain-Bones/skeleton/releases" target="_blank">
<Badge background="bg-surface-500/20" color="text-black dark:text-white">v{pkg.version}</Badge>
</a>
</svelte:fragment>
<!-- Branding -->
<svelte:fragment slot="lead">
<!-- Drawer Menu -->
<div on:click={drawerOpen} class="lg:hidden mr-2 p-1 cursor-pointer">
<SvgIcon name="bars" width="w-6" height="h-6" fill="fill-black dark:fill-white" on:click={drawerOpen} />
</div>
<!-- Skeleton -->
<a href="/" class="text-sm sm:text-lg md:text-3xl font-bold uppercase mr-4" title="Return to Homepage">Skeleton</a>
<!-- Badge -->
<a class="hidden sm:block" href="https://github.com/Brain-Bones/skeleton/releases" target="_blank">
<Badge background="bg-surface-500/20" color="text-black dark:text-white">v{pkg.version}</Badge>
</a>
</svelte:fragment>
<!-- Navigation -->
<svelte:fragment slot="trail">
<!-- Links -->
<section class="hidden lg:flex space-x-4 spacer-line">
<a href="/guides/install" class="navlink" aria-label="Docs">Docs</a>
<a href="/docs/why" class="navlink" aria-label="Guides">Guides</a>
<a href="/components/app-shell" class="navlink" aria-label="Components">Components</a>
<a href="/utilities/codeblocks" class="navlink" aria-label="Utilities">Utilities</a>
</section>
<!-- Navigation -->
<svelte:fragment slot="trail">
<!-- Links -->
<section class="hidden lg:flex space-x-4 spacer-line">
<a href="/guides/install" class="navlink" aria-label="Docs">Docs</a>
<a href="/docs/why" class="navlink" aria-label="Guides">Guides</a>
<a href="/components/app-shell" class="navlink" aria-label="Components">Components</a>
<a href="/utilities/codeblocks" class="navlink" aria-label="Components">Utilities</a>
</section>
<!-- Light Switch -->
<section class="flex spacer-line space-x-4">
<LightSwitch origin="tr" />
</section>
<!-- Community -->
<section class="flex space-x-4">
<a href="https://discord.gg/EXqV7W8MtY" target="_blank" aria-label="Discord">
<SvgIcon name="discord" viewBox="0 0 640 512" />
</a>
<a href="https://twitter.com/SkeletonUI" target="_blank" aria-label="Twitter">
<SvgIcon name="twitter" />
</a>
<a href="https://github.com/Brain-Bones/skeleton" target="_blank" aria-label="GitHub">
<SvgIcon name="github" />
</a>
</section>
</svelte:fragment>
<!-- Light Switch -->
<section class="flex spacer-line space-x-4">
<LightSwitch origin="tr" />
</section>
<!-- Community -->
<section class="flex space-x-4">
<a href="https://discord.gg/EXqV7W8MtY" target="_blank" aria-label="Discord">
<SvgIcon name="discord" viewBox="0 0 640 512" />
</a>
<a href="https://twitter.com/SkeletonUI" target="_blank" aria-label="Twitter">
<SvgIcon name="twitter" />
</a>
<a href="https://github.com/Brain-Bones/skeleton" target="_blank" aria-label="GitHub">
<SvgIcon name="github" />
</a>
</section>
</svelte:fragment>
</AppBar>
<style lang="postcss">
.navlink { @apply opacity-80 hover:opacity-100 hover:text-primary-500 transition-all; }
.spacer-line { @apply border-r border-r-surface-500/50 pr-4; }
.navlink {
@apply opacity-80 hover:opacity-100 hover:text-primary-500 transition-all;
}
.spacer-line {
@apply border-r border-r-surface-500/50 pr-4;
}
</style>

View File

@@ -1,77 +1,77 @@
<script lang="ts">
import Button from "$lib/Button/Button.svelte";
import Divider from "$lib/Divider/Divider.svelte";
import SvgIcon from "$lib/SvgIcon/SvgIcon.svelte";
import Button from '$lib/Button/Button.svelte';
import Divider from '$lib/Divider/Divider.svelte';
import SvgIcon from '$lib/SvgIcon/SvgIcon.svelte';
// Base Classes
const cBase: string = 'bg-white/75 dark:bg-black/10 text-xs mx-auto px-4 py-8 md:p-10 space-y-10';
const cRowOne: string = 'flex flex-col md:flex-row justify-between items-center md:items-start space-y-5 md:space-y-0';
const cRowTwo: string = 'flex flex-col md:flex-row justify-between items-center md:items-start space-y-4 md:space-y-0';
// Base Classes
const cBase: string = 'bg-white/75 dark:bg-black/10 text-xs mx-auto px-4 py-8 md:p-10 space-y-10';
const cRowOne: string = 'flex flex-col md:flex-row justify-between items-center md:items-start space-y-5 md:space-y-0';
const cRowTwo: string = 'flex flex-col md:flex-row justify-between items-center md:items-start space-y-4 md:space-y-0';
</script>
<div class="page-footer {cBase}">
<!-- Row 1 -->
<section class={cRowOne}>
<div class="space-y-2">
<span class="text-2xl font-bold uppercase">Skeleton</span>
<p class="text-lg">A fully featured Svelte + Tailwind component library.</p>
</div>
<div class="hidden md:flex items-start space-x-10">
<div class="space-y-4">
<h6>About</h6>
<ul class="space-y-2">
<li><a href="/docs/why">Contribute</a></li>
<li><a href="/docs/comparisons">Why Skeleton</a></li>
<li><a href="/docs/contributions">Comparisons</a></li>
</ul>
</div>
<div class="space-y-4">
<h6>Community</h6>
<ul class="space-y-2">
<li><a href="https://discord.gg/EXqV7W8MtY" target="_blank">Join Discord Community</a></li>
<li><a href="https://twitter.com/SkeletonUI" target="_blank">Follow on Twitter</a></li>
<li><a href="https://github.com/Brain-Bones/skeleton" target="_blank">View Github</a></li>
</ul>
</div>
<div class="space-y-4">
<h6>Project</h6>
<ul class="space-y-2">
<li><a href="https://github.com/Brain-Bones" target="_blank">Github Organization</a></li>
<li><a href="https://www.npmjs.com/org/brainandbones" target="_blank">NPM Organization</a></li>
<li><a href="https://www.npmjs.com/package/@brainandbones/skeleton" target="_blank">NPM Package</a></li>
</ul>
</div>
</div>
</section>
<!-- Row 1 -->
<section class="{cRowOne}">
<div class="space-y-2">
<span class="text-2xl font-bold uppercase">Skeleton</span>
<p class="text-lg">A fully featured Svelte + Tailwind component library.</p>
</div>
<div class="hidden md:flex items-start space-x-10">
<div class="space-y-4">
<h6>About</h6>
<ul class="space-y-2">
<li><a href="/docs/why">Contribute</a></li>
<li><a href="/docs/comparisons">Why Skeleton</a></li>
<li><a href="/docs/contributions">Comparisons</a></li>
</ul>
</div>
<div class="space-y-4">
<h6>Community</h6>
<ul class="space-y-2">
<li><a href="https://discord.gg/EXqV7W8MtY" target="_blank">Join Discord Community</a></li>
<li><a href="https://twitter.com/SkeletonUI" target="_blank">Follow on Twitter</a></li>
<li><a href="https://github.com/Brain-Bones/skeleton" target="_blank">View Github</a></li>
</ul>
</div>
<div class="space-y-4">
<h6>Project</h6>
<ul class="space-y-2">
<li><a href="https://github.com/Brain-Bones" target="_blank">Github Organization</a></li>
<li><a href="https://www.npmjs.com/org/brainandbones" target="_blank">NPM Organization</a></li>
<li><a href="https://www.npmjs.com/package/@brainandbones/skeleton" target="_blank">NPM Package</a></li>
</ul>
</div>
</div>
</section>
<Divider variant="dotted" class="border-black/10 dark:border-white/10" />
<!-- Row 2 -->
<section class="{cRowTwo}">
<p class="text-xs">
<a href="https://github.com/Brain-Bones/skeleton/blob/master/LICENSE" target="_blank">MIT License</a>
<span class="opacity-10 mx-2">|</span>
<a href="https://github.com/Brain-Bones/skeleton/graphs/contributors" target="_blank">Contributors</a>
</p>
<div class="flex space-x-4">
<Button background="bg-[#7289da]" color="!text-white" href="https://discord.gg/EXqV7W8MtY" target="_blank">
<SvgIcon name="discord" fill="fill-white" viewBox="0 0 640 512" class="-translate-y-[2px]" />
<span class="hidden md:inline-block ml-2">Discord</span>
</Button>
<Button background="bg-[#1da1f2]" color="!text-white" href="https://twitter.com/SkeletonUI" target="_blank">
<SvgIcon name="twitter" fill="fill-white" class="-translate-y-[2px]" />
<span class="hidden md:inline-block ml-2">Twitter</span>
</Button>
<Button background="bg-[#6e5494]" color="!text-white" href="https://github.com/Brain-Bones/skeleton" target="_blank">
<SvgIcon name="github" fill="fill-white" class="-translate-y-[2px]" />
<span class="hidden md:inline-block ml-2">Github</span>
</Button>
</div>
</section>
<Divider variant="dotted" class="border-black/10 dark:border-white/10" />
<!-- Row 2 -->
<section class={cRowTwo}>
<p class="text-xs">
<a href="https://github.com/Brain-Bones/skeleton/blob/master/LICENSE" target="_blank">MIT License</a>
<span class="opacity-10 mx-2">|</span>
<a href="https://github.com/Brain-Bones/skeleton/graphs/contributors" target="_blank">Contributors</a>
</p>
<div class="flex space-x-4">
<Button background="bg-[#7289da]" color="!text-white" href="https://discord.gg/EXqV7W8MtY" target="_blank">
<SvgIcon name="discord" fill="fill-white" viewBox="0 0 640 512" class="-translate-y-[2px]" />
<span class="hidden md:inline-block ml-2">Discord</span>
</Button>
<Button background="bg-[#1da1f2]" color="!text-white" href="https://twitter.com/SkeletonUI" target="_blank">
<SvgIcon name="twitter" fill="fill-white" class="-translate-y-[2px]" />
<span class="hidden md:inline-block ml-2">Twitter</span>
</Button>
<Button background="bg-[#6e5494]" color="!text-white" href="https://github.com/Brain-Bones/skeleton" target="_blank">
<SvgIcon name="github" fill="fill-white" class="-translate-y-[2px]" />
<span class="hidden md:inline-block ml-2">Github</span>
</Button>
</div>
</section>
</div>
<style lang="postcss">
a { @apply !no-underline !text-surface-500 hover:!text-primary-500 text-sm; }
a {
@apply !no-underline !text-surface-500 hover:!text-primary-500 text-sm;
}
</style>

View File

@@ -1,9 +1,9 @@
<script lang="ts">
import Drawer from "$lib/Drawer/Drawer.svelte";
import SkeletonSidebar from "./SkeletonSidebar.svelte";
import { storeMobileDrawer } from "$lib/_documentation/stores";
import Drawer from '$lib/Drawer/Drawer.svelte';
import SkeletonSidebar from './SkeletonSidebar.svelte';
import { storeMobileDrawer } from '$lib/_documentation/stores';
</script>
<Drawer open={storeMobileDrawer} display="lg:hidden">
<SkeletonSidebar embedded={true} />
<SkeletonSidebar embedded={true} />
</Drawer>

View File

@@ -1,50 +1,47 @@
<script lang="ts">
import { Badge, List, ListItem, Divider } from '@brainandbones/skeleton';
import SvgIcon from '$lib/SvgIcon/SvgIcon.svelte';
import { storeCurrentUrl, storeMobileDrawer } from '$lib/_documentation/stores';
import { menuNavLinks } from './links';
import { Badge, List, ListItem, Divider } from '@brainandbones/skeleton';
import SvgIcon from '$lib/SvgIcon/SvgIcon.svelte';
import { storeCurrentUrl, storeMobileDrawer } from '$lib/_documentation/stores';
import { menuNavLinks } from './links';
// Props
export let embedded: boolean = false;
// Props
export let embedded: boolean = false;
// ListItem Click Handler
function onListItemClick(): void {
if (!embedded) return;
storeMobileDrawer.set(false);
}
// ListItem Click Handler
function onListItemClick(): void {
if (!embedded) return;
storeMobileDrawer.set(false);
}
</script>
<div class="mb-8 {$$props.class||''}">
<div class="mb-8 {$$props.class || ''}">
{#each menuNavLinks as { title, list }, i}
<!-- Title -->
<div class="text-primary-500 text-sm font-bold uppercase p-4">{title}</div>
{#each menuNavLinks as { title, list }, i}
<!-- List -->
<List tag="nav" selected={storeCurrentUrl} {title} label={title}>
{#each list as { href, label, badge, icon }}
<ListItem {href} value={href} on:click={onListItemClick}>
<!-- Icon -->
<svelte:fragment slot="lead">
{#if icon}
<div class="bg-accent-500 w-7 h-7 flex justify-center items-center rounded shadow">
<SvgIcon name={icon} width="w-4" fill="fill-white" height="h-10" />
</div>
{/if}
</svelte:fragment>
<!-- Label -->
<span>{label}</span>
<!-- Badge -->
<svelte:fragment slot="trail">
{#if badge}<Badge background="bg-accent-500 dark/bg-accent-500/30">{badge}</Badge>{/if}
</svelte:fragment>
</ListItem>
{/each}
</List>
<!-- Title -->
<div class="text-primary-500 text-sm font-bold uppercase p-4">{title}</div>
<!-- List -->
<List tag="nav" selected={storeCurrentUrl} {title} label={title}>
{#each list as { href, label, badge, icon }}
<ListItem {href} value={href} on:click={onListItemClick}>
<!-- Icon -->
<svelte:fragment slot="lead">
{#if icon}
<div class="bg-accent-500 w-7 h-7 flex justify-center items-center rounded shadow">
<SvgIcon name={icon} width="w-4" fill="fill-white" height="h-10" />
</div>
{/if}
</svelte:fragment>
<!-- Label -->
<span>{label}</span>
<!-- Badge -->
<svelte:fragment slot="trail">
{#if badge}<Badge background="bg-accent-500 dark/bg-accent-500/30">{badge}</Badge>{/if}
</svelte:fragment>
</ListItem>
{/each}
</List>
<!-- Divider -->
{#if i + 1 < menuNavLinks.length}<Divider class="my-4 opacity-30" />{/if}
{/each}
<!-- Divider -->
{#if i + 1 < menuNavLinks.length}<Divider class="my-4 opacity-30" />{/if}
{/each}
</div>

View File

@@ -1,65 +1,65 @@
// Menu Navigation Links
export const menuNavLinks: any = [
{
title: 'Get Started',
list: [
{ href: '/guides/install', label: 'Install', icon: 'circle-check' },
{ href: '/guides/tailwind', label: 'Tailwind Settings', icon: 'tailwind' },
{ href: '/guides/themes', label: 'Themes', icon: 'swatchbook' },
{ href: '/guides/styling', label: 'Styling', icon: 'pen-ruler' },
{ href: '/guides/forms', label: 'Forms', icon: 'keyboard' },
{ href: '/guides/astro', label: 'Usage with Astro', icon: 'rocket' }
]
},
{
title: 'Docs',
list: [
{ href: '/docs/why', label: 'Why Skeleton' },
{ href: '/docs/comparisons', label: 'Comparisons' },
{ href: '/docs/contributions', label: 'Contributions' }
]
},
{
title: 'Components',
list: [
{ href: '/components/app-shell', label: 'App Shell' },
{ href: '/components/app-bar', label: 'App Bar' },
{ href: '/components/accordions', label: 'Accordions' },
{ href: '/components/alerts', label: 'Alerts' },
{ href: '/components/avatars', label: 'Avatars' },
{ href: '/components/badges', label: 'Badges' },
{ href: '/components/breadcrumbs', label: 'Breadcrumbs' },
{ href: '/components/buttons', label: 'Buttons' },
{ href: '/components/cards', label: 'Cards' },
// {href: '/components/conic-gradients', label: 'Conic Gradients'}, // keep disabled until further notice
{ href: '/components/data-tables', label: 'Data Tables' },
{ href: '/components/dividers', label: 'Dividers' },
{ href: '/components/gradient-headings', label: 'Gradient Headings' },
{ href: '/components/lists', label: 'Lists' },
{ href: '/components/logo-clouds', label: 'Logo Clouds' },
{ href: '/components/menus', label: 'Menus' },
{ href: '/components/paginators', label: 'Paginators' },
{ href: '/components/progress-bars', label: 'Progress Bars' },
{ href: '/components/progress-radials', label: 'Progress Radials' },
{ href: '/components/radio-groups', label: 'Radio Groups' },
{ href: '/components/range-sliders', label: 'Range Sliders' },
{ href: '/components/slide-toggles', label: 'Slide Toggles' },
{ href: '/components/steppers', label: 'Steppers' },
// { href: '/components/svg-icons', label: 'SVG Icons' }, // keep disabled until further notice
{ href: '/components/tabs', label: 'Tabs' },
{ href: '/components/tooltips', label: 'Tooltips' }
]
},
{
title: 'Utilities',
list: [
{ href: '/utilities/codeblocks', label: 'Code Blocks' },
{ href: '/utilities/drawers', label: 'Drawers' },
{ href: '/utilities/dialogs', label: 'Dialogs' },
{ href: '/utilities/toasts', label: 'Toasts' },
{ href: '/utilities/lightswitches', label: 'Lightswitch' },
{ href: '/utilities/filters', label: 'Filters', badge: 'Experimental' }
]
}
{
title: 'Get Started',
list: [
{ href: '/guides/install', label: 'Install', icon: 'circle-check' },
{ href: '/guides/tailwind', label: 'Tailwind Settings', icon: 'tailwind' },
{ href: '/guides/themes', label: 'Themes', icon: 'swatchbook' },
{ href: '/guides/styling', label: 'Styling', icon: 'pen-ruler' },
{ href: '/guides/forms', label: 'Forms', icon: 'keyboard' },
{ href: '/guides/astro', label: 'Usage with Astro', icon: 'rocket' }
]
},
{
title: 'Docs',
list: [
{ href: '/docs/why', label: 'Why Skeleton' },
{ href: '/docs/comparisons', label: 'Comparisons' },
{ href: '/docs/contributions', label: 'Contributions' }
]
},
{
title: 'Components',
list: [
{ href: '/components/app-shell', label: 'App Shell' },
{ href: '/components/app-bar', label: 'App Bar' },
{ href: '/components/accordions', label: 'Accordions' },
{ href: '/components/alerts', label: 'Alerts' },
{ href: '/components/avatars', label: 'Avatars' },
{ href: '/components/badges', label: 'Badges' },
{ href: '/components/breadcrumbs', label: 'Breadcrumbs' },
{ href: '/components/buttons', label: 'Buttons' },
{ href: '/components/cards', label: 'Cards' },
// {href: '/components/conic-gradients', label: 'Conic Gradients'}, // keep disabled until further notice
{ href: '/components/data-tables', label: 'Data Tables' },
{ href: '/components/dividers', label: 'Dividers' },
{ href: '/components/gradient-headings', label: 'Gradient Headings' },
{ href: '/components/lists', label: 'Lists' },
{ href: '/components/logo-clouds', label: 'Logo Clouds' },
{ href: '/components/menus', label: 'Menus' },
{ href: '/components/paginators', label: 'Paginators' },
{ href: '/components/progress-bars', label: 'Progress Bars' },
{ href: '/components/progress-radials', label: 'Progress Radials' },
{ href: '/components/radio-groups', label: 'Radio Groups' },
{ href: '/components/range-sliders', label: 'Range Sliders' },
{ href: '/components/slide-toggles', label: 'Slide Toggles' },
{ href: '/components/steppers', label: 'Steppers' },
// { href: '/components/svg-icons', label: 'SVG Icons' }, // keep disabled until further notice
{ href: '/components/tabs', label: 'Tabs' },
{ href: '/components/tooltips', label: 'Tooltips' }
]
},
{
title: 'Utilities',
list: [
{ href: '/utilities/codeblocks', label: 'Code Blocks' },
{ href: '/utilities/drawers', label: 'Drawers' },
{ href: '/utilities/dialogs', label: 'Dialogs' },
{ href: '/utilities/toasts', label: 'Toasts' },
{ href: '/utilities/lightswitches', label: 'Lightswitch' },
{ href: '/utilities/filters', label: 'Filters', badge: 'Experimental' }
]
}
];

View File

@@ -67,7 +67,7 @@
// Creates a hex shade palette from a singular hex value
function generateHexShades(key: string): void {
// Use paletteGenerator
const p: any = paletteGenerator({ names: [key], colors: [formValues[key]], });
const p: any = paletteGenerator({ names: [key], colors: [formValues[key]] });
delete p[key][950]; // drop swatch 950
hexShades[key] = p[key];
// Generate RGB shades

View File

@@ -3,7 +3,7 @@ import { writable, type Writable } from 'svelte/store';
// TODO: make these persit with window.localStorage
// Set within root layout, persists current SvelteKit $page.url.pathname
export const storeCurrentUrl: Writable<string|undefined> = writable(undefined);
export const storeCurrentUrl: Writable<string | undefined> = writable(undefined);
// Persists the tab selection for the user's preferred framework
export const storeFramework: Writable<string> = writable('sveltekit');

View File

@@ -41,7 +41,7 @@ export { default as LightSwitch } from './LightSwitch/LightSwitch.svelte';
// CodeBlock
export { storeHighlightJs } from './CodeBlock/stores';
export { default as CodeBlock } from "./CodeBlock/CodeBlock.svelte";
export { default as CodeBlock } from './CodeBlock/CodeBlock.svelte';
// Filters
export { filter } from './Filters/filter';

View File

@@ -1,7 +1,7 @@
/* --- Skeleton: Core --- */
body {
@apply font-sans bg-surface-100 dark:bg-surface-900 text-black dark:text-white;
@apply font-sans bg-surface-100 dark:bg-surface-900 text-black dark:text-white;
}
/* --- Scrollbars --- */

View File

@@ -1,12 +1,24 @@
/* --- Skeleton: Typography --- */
/* Headings */
h1 { @apply text-4xl md:text-5xl font-bold; }
h2 { @apply text-3xl md:text-3xl font-bold; }
h3 { @apply text-2xl md:text-2xl font-bold; }
h4 { @apply text-xl md:text-xl font-bold; }
h5 { @apply text-lg md:text-lg font-bold; }
h6 { @apply text-base md:text-base font-bold; }
h1 {
@apply text-4xl md:text-5xl font-bold;
}
h2 {
@apply text-3xl md:text-3xl font-bold;
}
h3 {
@apply text-2xl md:text-2xl font-bold;
}
h4 {
@apply text-xl md:text-xl font-bold;
}
h5 {
@apply text-lg md:text-lg font-bold;
}
h6 {
@apply text-base md:text-base font-bold;
}
/* Blockquote */
blockquote {
@@ -18,7 +30,7 @@ p {
@apply text-base text-surface-500 dark:text-surface-400;
}
a:not(.comp-button):not(.crumb a):not(.list-row):not(.drawer a):not(.app-bar a) {
@apply text-primary-500 underline underline-offset-4 decoration-primary-500/20 decoration-dotted ;
@apply text-primary-500 underline underline-offset-4 decoration-primary-500/20 decoration-dotted;
}
/* --- Pre and Code --- */

View File

@@ -1,5 +1,5 @@
<!-- Layout: (inner) route group -->
<div class="container mx-auto p-4 md:p-10 space-y-10">
<slot />
<slot />
</div>

View File

@@ -18,7 +18,7 @@
['hover', 'string', 'hover:bg-primary-500/10', '-', 'Provide a class to set the hover background color.'],
['spacing', 'string', 'space-y-0', '-', 'Provide a class to set spacing between title and description elements.'],
['padding', 'string', 'px-4 py-2', '-', 'Provide a class to set padding for summary and content regions.'],
['rounded', 'string', 'rounded', '-', 'Provide a class to set summary border radius.'],
['rounded', 'string', 'rounded', '-', 'Provide a class to set summary border radius.']
]
};
const tableSlots: any = {

View File

@@ -11,7 +11,7 @@
['border', 'string', '-', 'Provide a class to set border styles.'],
['padding', 'string', 'px-4 py-4 md:py-6', 'Provide a class to set padding.'],
['shadow', 'string', 'shadow-xl', 'Provide a class to define a box shadow.'],
['space', 'string', 'space-x-4', 'Provide a class to set horizontal spacing.'],
['space', 'string', 'space-x-4', 'Provide a class to set horizontal spacing.']
]
};
const tableSlots: any = {
@@ -19,7 +19,7 @@
source: [
['default', 'Provide items that reside in the center, such as a search element.'],
['lead', 'Provide leading items, such as a branding logo or page header.'],
['trail', 'Provide trailing items, such as a navigation links.'],
['trail', 'Provide trailing items, such as a navigation links.']
]
};
const tableA11y: any = {
@@ -45,7 +45,7 @@
<svelte:fragment slot="lead">
<span class="text-base md:text-3xl font-bold uppercase">Logo</span>
</svelte:fragment>
<input type="search" placeholder="Search..." class="max-w-[200px]">
<input type="search" placeholder="Search..." class="max-w-[200px]" />
<svelte:fragment slot="trail">
<SvgIcon />
</svelte:fragment>
@@ -55,13 +55,16 @@
<!-- Usage -->
<section class="space-y-4">
<h2>Usage</h2>
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<AppBar>
<svelte:fragment slot="lead">(branding)</svelte:fragment>
(search)
<svelte:fragment slot="trail">(navigation)</svelte:fragment>
</AppBar>
`.trim()} />
`.trim()}
/>
</section>
<!-- Properties -->

View File

@@ -12,7 +12,7 @@
headings: ['Prop', 'Type', 'Default', 'Required', 'Description'],
source: [
['sidebarLeftWidth', 'string', 'w-auto', '-', 'Provide a class to set the left sidebar width.'],
['sidebarRightWidth', 'string', 'w-auto', '-', 'Provide a class to set the right sidebar width.'],
['sidebarRightWidth', 'string', 'w-auto', '-', 'Provide a class to set the right sidebar width.']
]
};
const tableSlots: any = {
@@ -23,7 +23,7 @@
['sidebarLeft', 'Hidden when empty. Allows you to set fixed left sidebar content.'],
['sidebarRight', 'Hidden when empty. Allows you to set fixed right sidebar content.'],
['pageHeader', 'Insert content that resides above your page content. Great for global alerts.'],
['pageFooter', 'Insert content that resides below your page content. Add your site footer here.'],
['pageFooter', 'Insert content that resides below your page content. Add your site footer here.']
]
};
</script>
@@ -57,7 +57,9 @@
<section class="space-y-4">
<h2>Usage</h2>
<p>For best results implement this in your app's root layout. The slot order does not matter.</p>
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<AppShell>
<svelte:fragment slot="header">Header</svelte:fragment>
<svelte:fragment slot="sidebarLeft">Sidebar Left</svelte:fragment>
@@ -67,32 +69,45 @@
<!-- Be sure to insert your route <slot> in the default position --->
<slot />
</AppShell>
`.trim()} />
`.trim()}
/>
<p>The App Shell will expand to fill the parent container. Disable overflow on your <em>html</em> and <em>body</em> tags to prevent duplicate scroll bars.</p>
<CodeBlock language="css" code={`
<CodeBlock
language="css"
code={`
/* Within your global stylesheet */
html, body { @apply w-screen h-screen overflow-hidden; }
`.trim()} />
`.trim()}
/>
<h4>Header AppBar</h4>
<p>The <a href="/components/app-bar">AppBar</a> component should be embedded within the top-most <code>header</code> slot.</p>
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<AppShell>
<svelte:fragment slot="header">
<AppBar>Logo</AppBar>
</svelte:fragment>
<!-- ... -->
</AppShell>
`.trim()} />
`.trim()}
/>
<h4>Using Sidebars</h4>
<p>Please be aware that sidebars have a default width of <code>auto</code>. They will automatically collapse when empty or content is set to hidden. This is useful for hiding sidebars using media queries via <a href="https://tailwindcss.com/docs/responsive-design" target="_blank">Tailwind's responsive breakpoints</a>.</p>
<CodeBlock language="html" code={`
<p>
Please be aware that sidebars have a default width of <code>auto</code>. They will automatically collapse when empty or content is set to hidden. This is useful for hiding sidebars using media
queries via <a href="https://tailwindcss.com/docs/responsive-design" target="_blank">Tailwind's responsive breakpoints</a>.
</p>
<CodeBlock
language="html"
code={`
<AppShell>
<svelte:fragment slot="sidebarLeft">
<!-- Hidden below Tailwind's large breakpoint -->
<div id="sidebar-left" class="hidden lg:block">Sidebar</div>
</svelte:fragment>
</AppShell>
`.trim()} />
`.trim()}
/>
</section>
<!-- Properties -->
@@ -109,5 +124,7 @@ html, body { @apply w-screen h-screen overflow-hidden; }
</div>
<style lang="postcss">
.boxShape { @apply bg-warning-500/10 border border-warning-500 p-4 text-center text-xs h-full flex justify-center items-center; }
.boxShape {
@apply bg-warning-500/10 border border-warning-500 p-4 text-center text-xs h-full flex justify-center items-center;
}
</style>

View File

@@ -4,7 +4,7 @@
import { Apollo, BlueNight, Emerald, GreenFall, Noir, NoirLight, Rustic, Summer84, XPro } from '@brainandbones/skeleton';
import CodeBlock from '$lib/CodeBlock/CodeBlock.svelte';
const storeSrc: Writable<string|undefined> = writable(undefined);
const storeSrc: Writable<string | undefined> = writable(undefined);
let placeholder: string = 'https://i.pravatar.cc/';
const tableProps: any = {

View File

@@ -13,15 +13,15 @@
['ringSize', 'string', 'ring-[1px]', 'Provide a class set outline size.'],
['ringColor', 'string', 'ring-black/5 dark:ring-white/5', 'Provide a class set outline color.'],
['ringInset', 'string', 'ring-inset', 'Provide a class set outline inset style.'],
['rounded', 'string', 'rounded-lg', 'Provide a class set border radius style.'],
['rounded', 'string', 'rounded-lg', 'Provide a class set border radius style.']
]
};
const tablePropsSlots: any = {
headings: ['Prop', 'Type', 'Default', 'Description'],
source: [
['header', 'string', '-', 'Provide classes for the card\'s header slot.'],
['body', 'string', '-', 'Provide classes for the card\'s body slot.'],
['footer', 'string', '-', 'Provide classes for the card\'s footer slot.'],
['header', 'string', '-', "Provide classes for the card's header slot."],
['body', 'string', '-', "Provide classes for the card's body slot."],
['footer', 'string', '-', "Provide classes for the card's footer slot."]
]
};
const tableSlots: any = {
@@ -88,13 +88,16 @@
<CodeBlock language="html" code={`<Card>Minimal</Card>`} />
<CodeBlock language="html" code={`<Card background="bg-primary-500" color="text-white">Colored</Card>`} />
<CodeBlock language="html" code={`<Card class="hover:shadow-xl">Styled</Card>`} />
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<Card header="bg-red-500" body="bg-green-500" footer="bg-blue-500" space="space-y-1">
<svelte:fragment slot="header">(header)</svelte:fragment>
(body)
<svelte:fragment slot="footer">(footer)</svelte:fragment>
</Card>
`.trim()} />
`.trim()}
/>
</section>
<!-- Properties -->

View File

@@ -14,7 +14,7 @@
['space', 'string', 'space-y-1', 'class', 'Provide a class to set Y-axis spacing of list items.'],
['selected', 'Writable', '-', 'any', 'Nav tag only. Provide a writable store to maintain list selection.'],
['hover', 'string', 'hover:bg-primary-500/10', 'class', 'Nav tag only. Provide a class to set hover background color.'],
['highlight', 'string', '!bg-primary-500', 'class', 'Nav tag only. Provide a class for highlighted rows. Note this must be use (!) for important.'],
['highlight', 'string', '!bg-primary-500', 'class', 'Nav tag only. Provide a class for highlighted rows. Note this must be use (!) for important.']
]
};
const tablePropsItems: any = {

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import DataTable from '$lib/Table/DataTable.svelte';
import Card from '$lib/Card/Card.svelte';
import Card from '$lib/Card/Card.svelte';
import CodeBlock from '$lib/CodeBlock/CodeBlock.svelte';
// Tables
@@ -8,20 +8,18 @@
headings: ['Prop', 'Type', 'Default', 'Values', 'Required', 'Description'],
source: [
['name', '-', '-', '-', '&check;', '...'],
['name', '-', '-', '-', '-', '...'],
['name', '-', '-', '-', '-', '...']
]
};
const tableSlots: any = {
headings: ['Name', 'Description'],
source: [
['name', '...'],
]
source: [['name', '...']]
};
const tableA11y: any = {
headings: ['Prop', 'Type', 'Default', 'Values', 'Required', 'Description'],
source: [
['name', '-', '-', '-', '&check;', '...'],
['name', '-', '-', '-', '-', '...'],
['name', '-', '-', '-', '-', '...']
]
};
</script>

View File

@@ -21,7 +21,7 @@
['popup', 'string', 'false', 'Provide classes to style the popup.'],
['message', 'string', 'false', 'Provide classes to style the popup message.'],
['arrow', 'string', 'false', 'Provide classes to style the popup arrow.'],
['content', 'string', 'false', 'Provide classes to style the tooltip content wrapping element.'],
['content', 'string', 'false', 'Provide classes to style the tooltip content wrapping element.']
]
};
const tableSlots: any = {

View File

@@ -17,9 +17,11 @@
<!-- Mantine -->
<section class="space-y-4">
<h2>Mantine</h2>
<p><a href="https://mantine.dev/" target="_blank">https://mantine.dev/</a></p>
<p><a href="https://mantine.dev/" target="_blank">https://mantine.dev/</a></p>
<p>
Its no secret that Mantine has had a huge influence on the features and design of Skeleton. We love Mantines huge set of components, modular add-ons, and of course the best-in-class documentation. Were also huge fans of the deep customization provided per component. However, Mantine is unfortunately only available for React. That said, the Skeleton team hopes to bridge the gap and provide a similar experience for Svelte developers.
Its no secret that Mantine has had a huge influence on the features and design of Skeleton. We love Mantines huge set of components, modular add-ons, and of course the best-in-class
documentation. Were also huge fans of the deep customization provided per component. However, Mantine is unfortunately only available for React. That said, the Skeleton team hopes to bridge the
gap and provide a similar experience for Svelte developers.
</p>
</section>
@@ -28,9 +30,14 @@
<!-- Flowbite -->
<section class="space-y-4">
<h2>Flowbite</h2>
<p><a href="https://flowbite.com/" target="_blank">https://flowbite.com/</a></p>
<p><a href="https://flowbite.com/" target="_blank">https://flowbite.com/</a></p>
<p>
Flowbite provides a set of turnkey HTML/CSS components built with Tailwinds utility class system. Unlike other libraries, Flowbite focuses on a singular and opinionated design aesthetic. Flowbite is a general purpose library, which means it can be used within any framework, but also provides framework-specific variations like <a href="https://flowbite-svelte.com/" target="_blank">Flowbite Svelte</a>. Its relatively simple to tailor a Flowbite component to work within an existing Tailwind design system. In fact, its even possible to pair Flowbite with Skeleton, allowing you to mix and match components, while taking advantage of Skeletons theme system. See our guide below.
Flowbite provides a set of turnkey HTML/CSS components built with Tailwinds utility class system. Unlike other libraries, Flowbite focuses on a singular and opinionated design aesthetic.
Flowbite is a general purpose library, which means it can be used within any framework, but also provides framework-specific variations like <a
href="https://flowbite-svelte.com/"
target="_blank">Flowbite Svelte</a
>. Its relatively simple to tailor a Flowbite component to work within an existing Tailwind design system. In fact, its even possible to pair Flowbite with Skeleton, allowing you to mix and
match components, while taking advantage of Skeletons theme system. See our guide below.
</p>
<AccordionGroup>
<AccordionItem class="border border-surface-500/20 rounded">
@@ -40,12 +47,15 @@
<svelte:fragment slot="content">
<div class="space-y-4 pb-3">
<p>Let's integrate a <a href="https://flowbite.com/docs/components/card/" target="_blank">Flowbite Card</a>. Here's the default markup:</p>
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<a href="#" class="block p-6 max-w-sm bg-white rounded-lg border border-gray-200 shadow-md hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Flowbite Version</h5>
<p class="font-normal text-gray-700 dark:text-gray-400">Lorem, ipsum dolor sit amet consectetur adipisicing elit.</p>
</a>
`.trim()} />
`.trim()}
/>
<p>We make several small adjustements to take advantage of Skeleton's styles and theme system:</p>
<ul class="list-disc list-inside opacity-60">
<li>Replaced all instances of the <code>bg-gray-X</code> class with <code>bg-surface-X</code>.</li>
@@ -53,14 +63,20 @@
<li>Modified the the heading to be an H2 and dropped <code>text-2xl font-bold</code> classes.</li>
<li>Bumped <code>max-w-sm</code> up to <code>max-w-lg</code> to fit our content width.</li>
</ul>
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<a href="#" class="block p-6 max-w-lg bg-white rounded-lg border border-surface-200 shadow-md hover:bg-surface-100 dark:bg-surface-800 dark:border-surface-700 dark:hover:bg-surface-700 !no-underline">
<h2 class="mb-2 tracking-tight text-surface-900 dark:text-white">Flowbite + Skeleton = ❤️</h2>
<p class="font-normal text-surface-700 dark:text-surface-400">Lorem, ipsum dolor sit amet consectetur adipisicing elit.</p>
</a>
`.trim()} />
`.trim()}
/>
<p>Here's the final result. Try toggling dark mode on/off to see how the card style adapts.</p>
<a href="/docs/comparisons" class="block p-6 max-w-lg bg-white rounded-lg border border-surface-200 shadow-md hover:bg-surface-100 dark:bg-surface-800 dark:border-surface-700 dark:hover:bg-surface-700 !no-underline">
<a
href="/docs/comparisons"
class="block p-6 max-w-lg bg-white rounded-lg border border-surface-200 shadow-md hover:bg-surface-100 dark:bg-surface-800 dark:border-surface-700 dark:hover:bg-surface-700 !no-underline"
>
<h2 class="mb-2 tracking-tight text-surface-900 dark:text-white">Skeleton + Flowbite = ❤️</h2>
<p class="font-normal text-surface-700 dark:text-surface-400">Lorem, ipsum dolor sit amet consectetur adipisicing elit.</p>
</a>
@@ -75,9 +91,15 @@
<!-- Daisy UI -->
<section class="space-y-4">
<h2>Daisy UI</h2>
<p><a href="https://daisyui.com/" target="_blank">https://daisyui.com/</a></p>
<p><a href="https://daisyui.com/" target="_blank">https://daisyui.com/</a></p>
<p>
Daisy can be compared to Skeleton due to our shared use of Tailwind CSS and highly customizable theme systems. Unfortunately Daisy themes rely on hex color values which <a href="https://tailwindcss.com/docs/customizing-colors#using-css-variables" target="_blank">prevents the use of the opacity modifier syntax</a>. Likewise Daisy opts to forgo the biggest benefit of Tailwind - the deeply extensible utility class system. Instead relying on <a href="https://tailwindcss.com/docs/reusing-styles#avoiding-premature-abstraction" target="_blank">@apply</a> to generate canned style sets. On the other hand, Skeleton treats utility classes as first class citizens, providing hooks to set and override Tailwind classes within each component. Skeleton components also accept arbitrary classes allowing full customization top to bottom. However, its worth noting that Daisy is a general purpose library available to any framework, while Skeleton focuses purely on Svelte.
Daisy can be compared to Skeleton due to our shared use of Tailwind CSS and highly customizable theme systems. Unfortunately Daisy themes rely on hex color values which <a
href="https://tailwindcss.com/docs/customizing-colors#using-css-variables"
target="_blank">prevents the use of the opacity modifier syntax</a
>. Likewise Daisy opts to forgo the biggest benefit of Tailwind - the deeply extensible utility class system. Instead relying on
<a href="https://tailwindcss.com/docs/reusing-styles#avoiding-premature-abstraction" target="_blank">@apply</a> to generate canned style sets. On the other hand, Skeleton treats utility classes as
first class citizens, providing hooks to set and override Tailwind classes within each component. Skeleton components also accept arbitrary classes allowing full customization top to bottom. However,
its worth noting that Daisy is a general purpose library available to any framework, while Skeleton focuses purely on Svelte.
</p>
</section>
@@ -86,10 +108,17 @@
<!-- Svelte Material UI -->
<section class="space-y-4">
<h2>Svelte Material UI</h2>
<p><a href="https://sveltematerialui.com/" target="_blank">https://sveltematerialui.com/</a></p>
<p><a href="https://sveltematerialui.com/" target="_blank">https://sveltematerialui.com/</a></p>
<p>
The founding members of Skeleton are huge fans of Material Design and recognize its influence on modern web UI, UX, and component systems in general. Our team has extensive experience with <a href="https://material.angular.io/" target="_blank">Angular Material</a>, which adapts the Material Design conventions for the <a href="https://angular.io/" target="_blank">Angular</a> framework. This has actually influenced many of the design decisions for creating Skeleton, including our opinions on <a href="/guides/forms">form components</a>. It makes sense that Svelte Material UI would be popular, as it bridges the benefits of Material Design with the power of Svelte. However, Skeleton has chosen to shy away the look and feel or Material Design, and instead create a more unique aesthetic. Additionally, Skeleton features tight integration with Tailwind, to aid in building a fully realized design system. Allowing you to control every aspect of your interface from the ground up. If for some reason youre adverse to Tailwind or you wish to lean into the Material Design style, then we would recommend Svelte Material UI. It also has the benefit of being one of the oldest and most mature UI component libraries available for Svelte today.
The founding members of Skeleton are huge fans of Material Design and recognize its influence on modern web UI, UX, and component systems in general. Our team has extensive experience with <a
href="https://material.angular.io/"
target="_blank">Angular Material</a
>, which adapts the Material Design conventions for the <a href="https://angular.io/" target="_blank">Angular</a> framework. This has actually influenced many of the design decisions for
creating Skeleton, including our opinions on <a href="/guides/forms">form components</a>. It makes sense that Svelte Material UI would be popular, as it bridges the benefits of Material Design
with the power of Svelte. However, Skeleton has chosen to shy away the look and feel or Material Design, and instead create a more unique aesthetic. Additionally, Skeleton features tight
integration with Tailwind, to aid in building a fully realized design system. Allowing you to control every aspect of your interface from the ground up. If for some reason youre adverse to
Tailwind or you wish to lean into the Material Design style, then we would recommend Svelte Material UI. It also has the benefit of being one of the oldest and most mature UI component libraries
available for Svelte today.
</p>
</section>
</div>

View File

@@ -42,9 +42,16 @@
<h2>How to Contribute</h2>
<ul class="list-disc list-inside">
<li>
Pull requests are always welcome. Read this full guide, <a href="https://github.com/Brain-Bones/skeleton/issues" target="_blank">create or pick an issue</a>, stake your claim, and start helping!
Pull requests are always welcome. Read this full guide, <a href="https://github.com/Brain-Bones/skeleton/issues" target="_blank">create or pick an issue</a>, stake your claim, and start
helping!
</li>
<li>
Let Skeleton contributors know what you would like to see added. See the <a
href="https://github.com/Brain-Bones/skeleton/wiki/%F0%9F%9B%A3%EF%B8%8F-The-Skeleton-Roadmap-(proposal)"
target="_blank">roadmap</a
>
and and review the current <a href="https://github.com/Brain-Bones/skeleton/discussions/79" target="_blank">discussion thread</a>.
</li>
<li>Let Skeleton contributors know what you would like to see added. See the <a href="https://github.com/Brain-Bones/skeleton/wiki/%F0%9F%9B%A3%EF%B8%8F-The-Skeleton-Roadmap-(proposal)" target="_blank">roadmap</a> and and review the current <a href="https://github.com/Brain-Bones/skeleton/discussions/79" target="_blank">discussion thread</a>.</li>
<li>Help improve documentation. Send a pull request to fix typos, grammar issues, as well as correct outdated or incorrect information.</li>
<li>Spread the word. Send Skeleton to your fellow developers or share on social media. This helps a lot more than you think!</li>
</ul>
@@ -75,7 +82,8 @@
<li>If your PR meets all requirements it will be merged!</li>
</ol>
<p>
The overwhelming majority of rejected pull requests come from submissions without prior discussion, do not meet the requirements for a feature, or otherwise conflict with ongoing efforts. To avoid rejection, be a team player, don't try to be a hero!
The overwhelming majority of rejected pull requests come from submissions without prior discussion, do not meet the requirements for a feature, or otherwise conflict with ongoing efforts. To
avoid rejection, be a team player, don't try to be a hero!
</p>
</section>
@@ -85,7 +93,11 @@
<section class="space-y-4">
<h2>Pull Requests</h2>
<p>
Per common courtesy, please reach out to contributors before you start work on new features. If you're interested in creating a new feature, create a ticket on <a href="https://github.com/Brain-Bones/skeleton/issues" target="_blank">GitHub Issues</a>. This allows for open discourse and may help prevent redundant work. This includes but is not limited to: creating new components, adding new utilities, or notable alterations to existing work.
Per common courtesy, please reach out to contributors before you start work on new features. If you're interested in creating a new feature, create a ticket on <a
href="https://github.com/Brain-Bones/skeleton/issues"
target="_blank">GitHub Issues</a
>. This allows for open discourse and may help prevent redundant work. This includes but is not limited to: creating new components, adding new utilities, or notable alterations to existing
work.
</p>
<h4>Git Branches</h4>
<DataTable headings={tableBranches.headings} source={tableBranches.source} />
@@ -100,7 +112,8 @@
<section class="space-y-4">
<h2>Dependencies</h2>
<p>
Skeleton aims to keep dependencies as lean as possible. Please be leery of introducing more. If you have a valid reason to add one, please discuss with core contributors before proceeding. This can help avoid conflicts and greatly benefits end users!
Skeleton aims to keep dependencies as lean as possible. Please be leery of introducing more. If you have a valid reason to add one, please discuss with core contributors before proceeding. This
can help avoid conflicts and greatly benefits end users!
</p>
</section>
@@ -245,26 +258,35 @@ afterUpdate(() => {
<!-- Reactive Classes -->
<h3>Reactive Classes</h3>
<p>Reactive classes combine all base and dynamic classes. These are applied directly to each respective element.</p>
<CodeBlock language="typescript" code={`
<CodeBlock
language="typescript"
code={`
$: classesCard = \`\${cBase} \${cOutlined}\`; // parent element
$: classesLabel = \`\${cBaseLabel}\`; // child element
`.trim()} />
`.trim()}
/>
<p>
Apply the reactive classes as follows. Make sure to also include <code>$$props.classes</code> as a pass-through for additional classes. Note that the first class acts as an identifier for the element,
which is useful for testing and DOM manipulation.
</p>
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<div class="card {classesCard} {$$props.classes||''}">
<label class="card-label {classesLabel}">My Label</label>
</div>
`.trim()} />
`.trim()}
/>
<p>Optionaly, we can use reactive classes to simply the dynamic classes example above.</p>
<CodeBlock language="ts" code={`
<CodeBlock
language="ts"
code={`
export let outlined: boolean;
$: classesOutlined = outlined ? 'border-2 border-primary-500' : 'border-none';
$: classesCard = \`\${cBase} \${classesOutlined}\`;
`.trim()} />
`.trim()}
/>
<p>This prevents the need for the <code>afterUpdate()</code> method.</p>
</section>
@@ -294,11 +316,13 @@ $: classesCard = \`\${cBase} \${classesOutlined}\`;
</p>
<h4>Update Site Navigation</h4>
<p>
Open <code>/src/lib/_documentation/SkeletonNavigation/links.ts</code> and document the new links under the appropriate section. General rule of thumb is simple components go under <em>Components</em>, while Svelte actions and complicated features go under <em>Utilities</em>.
Open <code>/src/lib/_documentation/SkeletonNavigation/links.ts</code> and document the new links under the appropriate section. General rule of thumb is simple components go under
<em>Components</em>, while Svelte actions and complicated features go under <em>Utilities</em>.
</p>
<h4>Interactive vs Static Demos</h4>
<p>
While interactive demos are preferred, static demos are welcome too. Just make sure to provide a variety of examples to illustrate potential use cases and showcase the feature set of the component. If require assistance in setting up an interactive demo, please contact any core contributor on the team. We're happy to help!
While interactive demos are preferred, static demos are welcome too. Just make sure to provide a variety of examples to illustrate potential use cases and showcase the feature set of the
component. If require assistance in setting up an interactive demo, please contact any core contributor on the team. We're happy to help!
</p>
</section>
@@ -319,7 +343,8 @@ $: classesCard = \`\${cBase} \${classesOutlined}\`;
<section class="space-y-4">
<h2>Automated Tests</h2>
<p>
Tests are handled via <a href="https://vitest.dev/" target="_blank">Vitest</a>, which uses similar conventions and syntax to Jest. Please ensure you write and run tests before submitting a pull request. Bare minimum, these tests should test components with the minimum and maximum props. If you're unfamiliar with automated testing, contact a core contributor for help.
Tests are handled via <a href="https://vitest.dev/" target="_blank">Vitest</a>, which uses similar conventions and syntax to Jest. Please ensure you write and run tests before submitting a pull
request. Bare minimum, these tests should test components with the minimum and maximum props. If you're unfamiliar with automated testing, contact a core contributor for help.
</p>
<CodeBlock language="console" code={`npm run test`} />
</section>

View File

@@ -130,7 +130,8 @@ import WrapperExample from '../components/WrapperExample.svelte';
<p>
Please note that dynamic components must be hydrated using <a href="https://docs.astro.build/en/reference/directives-reference/#client-directives" target="_blank">Astro's Client Directives</a>.
We opted for
<code>client:visible</code>, which loads and hydrates the JavaScript component only when it enters the users viewport. If we did not do this, the component would be rendered as only HTML/CSS and the <code>triggerMessage()</code> method would not function.
<code>client:visible</code>, which loads and hydrates the JavaScript component only when it enters the users viewport. If we did not do this, the component would be rendered as only HTML/CSS
and the <code>triggerMessage()</code> method would not function.
</p>
</section>

View File

@@ -20,9 +20,14 @@
impacting your ability to customize and style each input.
</p>
<p>
However, given Skeleton's tight integration with Tailwind, an elegant solution is available via the <a href="https://github.com/tailwindlabs/tailwindcss-forms" target="_blank">official Tailwind Forms plugin</a>. This provides a no-nonsense approach to applying clean and modern styling to <em>most</em> inputs.
However, given Skeleton's tight integration with Tailwind, an elegant solution is available via the <a href="https://github.com/tailwindlabs/tailwindcss-forms" target="_blank"
>official Tailwind Forms plugin</a
>. This provides a no-nonsense approach to applying clean and modern styling to <em>most</em> inputs.
</p>
<p>
Tailwind provides an example page to <a href="https://tailwindcss-forms.vercel.app/kitchen-sink.html" target="_blank">preview the default styles here</a>. These default styles can then be
tailored to adapt your theme styling use Skeleton's modular stylesheet add-on for forms.
</p>
<p>Tailwind provides an example page to <a href="https://tailwindcss-forms.vercel.app/kitchen-sink.html" target="_blank">preview the default styles here</a>. These default styles can then be tailored to adapt your theme styling use Skeleton's modular stylesheet add-on for forms.</p>
</header>
<Divider />
@@ -69,11 +74,11 @@ module.exports = {
{#if $storeFramework === 'sveltekit'}
<p>Import form element styles before your global stylesheet in <code>/src/routes/+layout.svelte</code>.</p>
<CodeBlock language="typescript" code={`import '@brainandbones/skeleton/styles/forms.css'; // <--\nimport '../app.postcss';`} />
<!-- Framework: Vite (Svelte) -->
<!-- Framework: Vite (Svelte) -->
{:else if $storeFramework === 'vite'}
<p>Import form element styles before your global stylesheet in <code>/src/main.js</code>.</p>
<CodeBlock language="typescript" code={`import '@brainandbones/skeleton/styles/forms.css'; // <--\nimport '../app.css';`} />
<!-- Framework: Astro -->
<!-- Framework: Astro -->
{:else if $storeFramework === 'astro'}
<p>Import form element styles before your global stylesheet in <code>/src/layouts/LayoutBasic.astro</code>.</p>
<CodeBlock language="typescript" code={`import '@brainandbones/skeleton/styles/forms.css'; // <--\nimport '../styles/base.css';`} />
@@ -109,8 +114,10 @@ module.exports = {
<section class="space-y-4">
<h2>Non-Supported Inputs</h2>
<p>
While the Tailwind Forms plugin covers most common inputs, there are <a href="https://tailwindcss-forms.vercel.app/kitchen-sink.html" target="_blank">a few exceptions</a> (see page bottom). However, Skeleton provides a robust <a href="/components/range-sliders">Range Slider</a>
alternative, as well as custom components for <a href="/components/slide-toggles">Slide Toggles</a> and <a href="/components/radio-groups">Radio Groups</a>. Expect to see more of these in the future.
While the Tailwind Forms plugin covers most common inputs, there are <a href="https://tailwindcss-forms.vercel.app/kitchen-sink.html" target="_blank">a few exceptions</a> (see page bottom).
However, Skeleton provides a robust <a href="/components/range-sliders">Range Slider</a>
alternative, as well as custom components for <a href="/components/slide-toggles">Slide Toggles</a> and <a href="/components/radio-groups">Radio Groups</a>. Expect to see more of these in the
future.
</p>
</section>

View File

@@ -1,105 +1,113 @@
<script lang="ts">
import { storeFramework } from '$lib/_documentation/stores';
import { storeFramework } from '$lib/_documentation/stores';
import { Card, Divider, Button, TabGroup, Tab } from '@brainandbones/skeleton';
import CodeBlock from '$lib/CodeBlock/CodeBlock.svelte';
</script>
<div class="space-y-10">
<!-- Install -->
<section class="space-y-4">
<h1>Install Skeleton</h1>
<p>
Select your app framework of choice, then follow steps below. During this process you'll scaffold a project, install the Skeleton package, install and configure Tailwind, as well as implement a
custom theme. Make sure to follow each guide carefully.
</p>
<!-- Install -->
<section class="space-y-4">
<h1>Install Skeleton</h1>
<p>
Select your app framework of choice, then follow steps below. During this process you'll scaffold a project, install the Skeleton package, install and configure Tailwind, as well as implement a
custom theme. Make sure to follow each guide carefully.
</p>
<TabGroup selected={storeFramework} class="pt-4">
<Tab value="sveltekit">SvelteKit</Tab>
<Tab value="vite">Vite (Svelte)</Tab>
<Tab value="astro">Astro</Tab>
</TabGroup>
<TabGroup selected={storeFramework} class="pt-4">
<Tab value="sveltekit">SvelteKit</Tab>
<Tab value="vite">Vite (Svelte)</Tab>
<Tab value="astro">Astro</Tab>
</TabGroup>
<!-- Framework: SvelteKit -->
{#if $storeFramework === 'sveltekit'}
<p>
View the <a href="https://kit.svelte.dev/docs/introduction#getting-started" target="_blank">official documentation.</a>
</p>
<CodeBlock language="console" code={`
<!-- Framework: SvelteKit -->
{#if $storeFramework === 'sveltekit'}
<p>
View the <a href="https://kit.svelte.dev/docs/introduction#getting-started" target="_blank">official documentation.</a>
</p>
<CodeBlock
language="console"
code={`
npm create svelte@latest sveltekit-skeleton-app
- Create a barebones project
- Enable Typescript
cd sveltekit-skeleton-app
npm install
npm run dev
`.trim()} />
<!-- Framework: Vite (Svelte) -->
{:else if $storeFramework === 'vite'}
<p>
View the <a href="https://vitejs.dev/guide/#scaffolding-your-first-vite-project" target="_blank">official documentation</a>.
</p>
<CodeBlock language="console" code={`
`.trim()}
/>
<!-- Framework: Vite (Svelte) -->
{:else if $storeFramework === 'vite'}
<p>
View the <a href="https://vitejs.dev/guide/#scaffolding-your-first-vite-project" target="_blank">official documentation</a>.
</p>
<CodeBlock
language="console"
code={`
npm create vite@latest my-app -- --template svelte-ts
cd my-app
npm install
npm run dev
`.trim()} />
<!-- Framework: Astro -->
{:else if $storeFramework === 'astro'}
<p>
View the <a href="https://docs.astro.build/en/install/auto/" target="_blank">official documentation</a>. Once setup of Skeleton is complete, please read the dedicated <a href="/guides/astro">Usage with Astro</a> guide.
</p>
<CodeBlock language="console" code={`
`.trim()}
/>
<!-- Framework: Astro -->
{:else if $storeFramework === 'astro'}
<p>
View the <a href="https://docs.astro.build/en/install/auto/" target="_blank">official documentation</a>. Once setup of Skeleton is complete, please read the dedicated
<a href="/guides/astro">Usage with Astro</a> guide.
</p>
<CodeBlock
language="console"
code={`
npm create astro@latest astro-skeleton-app
- Create an empty project
- Install all depedencies
- Use 'Typescript: Strict'
cd astro-skeleton-app
npm run dev
`.trim()} />
<!-- Svelte -->
<h3>Install Svelte</h3>
<p>
Add Svelte integration via <a href="https://docs.astro.build/en/guides/integrations-guide/svelte/" target="_blank">@astrojs/svelte</a>
</p>
<CodeBlock language="console" code={`npx astro add svelte`} />
<!-- Tailwind -->
<h3>Install Tailwind</h3>
<p>
Add Tailwind integration via <a href="https://docs.astro.build/en/guides/integrations-guide/tailwind/" target="_blank">@astrojs/tailwind</a>
</p>
<CodeBlock language="console" code={`npx astro add tailwind`} />
<p>Add <code>/src/styles/base.css</code> to house global styles and define the following @tailwind directives:</p>
<CodeBlock language="css" code={`@tailwind base;\n@tailwind components;\n@tailwind utilities;`} />
{/if}
</section>
`.trim()}
/>
<!-- Svelte -->
<h3>Install Svelte</h3>
<p>
Add Svelte integration via <a href="https://docs.astro.build/en/guides/integrations-guide/svelte/" target="_blank">@astrojs/svelte</a>
</p>
<CodeBlock language="console" code={`npx astro add svelte`} />
<!-- Tailwind -->
<h3>Install Tailwind</h3>
<p>
Add Tailwind integration via <a href="https://docs.astro.build/en/guides/integrations-guide/tailwind/" target="_blank">@astrojs/tailwind</a>
</p>
<CodeBlock language="console" code={`npx astro add tailwind`} />
<p>Add <code>/src/styles/base.css</code> to house global styles and define the following @tailwind directives:</p>
<CodeBlock language="css" code={`@tailwind base;\n@tailwind components;\n@tailwind utilities;`} />
{/if}
</section>
<!-- Install Tailwind -->
{#if ['sveltekit', 'vite'].includes($storeFramework)}
<section class="space-y-4">
<h3>Install Tailwind</h3>
<p>
<a href="https://github.com/svelte-add/tailwindcss" target="_blank">Svelte-Add</a> makes installation a trivial process.
</p>
<CodeBlock language="console" code={`npx svelte-add@latest tailwindcss\nnpm install`} />
</section>
{/if}
<!-- Install Tailwind -->
{#if ['sveltekit', 'vite'].includes($storeFramework)}
<section class="space-y-4">
<h3>Install Tailwind</h3>
<p>
<a href="https://github.com/svelte-add/tailwindcss" target="_blank">Svelte-Add</a> makes installation a trivial process.
</p>
<CodeBlock language="console" code={`npx svelte-add@latest tailwindcss\nnpm install`} />
</section>
{/if}
<!-- Install Skeleton -->
<section class="space-y-4">
<h3>Install Skeleton</h3>
<p>
Install the core Skeleton package from <a href="https://www.npmjs.com/package/@brainandbones/skeleton" target="_blank">NPM</a>.
</p>
<CodeBlock language="console" code={`npm i @brainandbones/skeleton --save-dev`} />
</section>
<!-- Install Skeleton -->
<section class="space-y-4">
<h3>Install Skeleton</h3>
<p>
Install the core Skeleton package from <a href="https://www.npmjs.com/package/@brainandbones/skeleton" target="_blank">NPM</a>.
</p>
<CodeBlock language="console" code={`npm i @brainandbones/skeleton --save-dev`} />
</section>
<Divider />
<!-- Next Steps -->
<Card body="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0 md:space-x-4">
<p>Next, let's configure Tailwind to work with Skeleton.</p>
<Button variant="filled-accent" href="/guides/tailwind">Configure Tailwind</Button>
</Card>
<Divider />
<!-- Next Steps -->
<Card body="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0 md:space-x-4">
<p>Next, let's configure Tailwind to work with Skeleton.</p>
<Button variant="filled-accent" href="/guides/tailwind">Configure Tailwind</Button>
</Card>
</div>

View File

@@ -7,32 +7,22 @@
// Tables
const ghLibPathMaster: string = 'https://github.com/Brain-Bones/skeleton/tree/master/src/lib'; // master branch
const tableStyleAddons: any = {
headings: ['Stylesheet', 'Description', 'Plugin Required', 'Source', ],
headings: ['Stylesheet', 'Description', 'Plugin Required', 'Source'],
source: [
[
'<code>tailwind.css</code>',
'Should proceed all other add-ons. Includes only the four primary <a href="https://tailwindcss.com/docs/functions-and-directives" target="_blank">@tailwind directives</a>.',
'-',
`<a href="${ghLibPathMaster}/styles/tailwind.css" target="_blank">View</a>`,
],
[
'<code>core.css</code>',
'General styles for for body elements, scrollbars, and more.',
'-',
`<a href="${ghLibPathMaster}/styles/core.css" target="_blank">View</a>`,
],
[
'<code>typography.css</code>',
'Styles headings, paragraph, anchors, pre, code, and more.',
'-',
`<a href="${ghLibPathMaster}/styles/typography.css" target="_blank">View</a>`,
`<a href="${ghLibPathMaster}/styles/tailwind.css" target="_blank">View</a>`
],
['<code>core.css</code>', 'General styles for for body elements, scrollbars, and more.', '-', `<a href="${ghLibPathMaster}/styles/core.css" target="_blank">View</a>`],
['<code>typography.css</code>', 'Styles headings, paragraph, anchors, pre, code, and more.', '-', `<a href="${ghLibPathMaster}/styles/typography.css" target="_blank">View</a>`],
[
'<code>forms.css</code>',
'Should only be used with the <a href="https://github.com/tailwindlabs/tailwindcss-forms" target="_blank">Tailwind Forms</a> plugin. See the <a href="/guides/forms">Forms</a> for details.',
'&check;',
`<a href="${ghLibPathMaster}/styles/forms.css" target="_blank">View</a>`,
],
`<a href="${ghLibPathMaster}/styles/forms.css" target="_blank">View</a>`
]
]
};
</script>
@@ -52,10 +42,12 @@
<p>Here's a few suggested best practices to follow when creating global styles:</p>
<ul class="list-disc list-inside space-y-1">
<li>
Ensure you wrap your core page elements within a <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main" target="_blank">main element</a>. The <a href="/components/app-shell">App Shell</a> component handles this for you.
Ensure you wrap your core page elements within a <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main" target="_blank">main element</a>. The
<a href="/components/app-shell">App Shell</a> component handles this for you.
</li>
<li>
The ideal use case for <a href="https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply" target="_blank">Tailwind @apply</a> is defining global styles. Please be leery of <a href="https://tailwindcss.com/docs/reusing-styles#avoiding-premature-abstraction" target="_blank">premature abstraction</a>.
The ideal use case for <a href="https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply" target="_blank">Tailwind @apply</a> is defining global styles. Please be leery of
<a href="https://tailwindcss.com/docs/reusing-styles#avoiding-premature-abstraction" target="_blank">premature abstraction</a>.
</li>
<li>
Utilize the CSS <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:not" target="_blank">:not pseudo-class</a> to exclude and avoid conflicts with Skeleton component's inherit styles.
@@ -95,7 +87,8 @@
<Alert background="bg-accent-500/30">
<svelte:fragment slot="message">
<span class="text-black dark:text-white">
Ensure you import the <code>tailwind.css</code> add-on before all others. Remove the @tailwind directives from your global stylesheet if you choose to use these add-ons. Failure to do so will mean you have two instances of the directives in your project.
Ensure you import the <code>tailwind.css</code> add-on before all others. Remove the @tailwind directives from your global stylesheet if you choose to use these add-ons. Failure to do so will
mean you have two instances of the directives in your project.
</span>
</svelte:fragment>
<svelte:fragment slot="trail">
@@ -109,11 +102,11 @@
<!-- Per Component Styles -->
<section class="space-y-4">
<h2>Per Component Styles</h2>
<p>
Skeleton components automatically inherit and utilize your theme colors. However, there may be cases where you want to overwrite or extend the styling on a single component.
</p>
<p>Skeleton components automatically inherit and utilize your theme colors. However, there may be cases where you want to overwrite or extend the styling on a single component.</p>
<p>Special style properties are provided to customize each component. See each component's documentation for instruction.</p>
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<Button background="bg-accent-500">Prop Customized</Button>
`.trim()}
/>
@@ -129,8 +122,8 @@
</p>
<CodeBlock language="html" code={`<Button class="!p-10">Big</Button>`} />
<p>
Keep in mind that components are a single line HTML element and represent a set of HTML elements within. This means you should be mindful of your target, as the <code>class</code> attribute
is only applied to the top-most parent element. In rare cases you may need to generate a chained class definition, though we advise using this technique sparingly.
Keep in mind that components are a single line HTML element and represent a set of HTML elements within. This means you should be mindful of your target, as the <code>class</code> attribute is only
applied to the top-most parent element. In rare cases you may need to generate a chained class definition, though we advise using this technique sparingly.
</p>
<CodeBlock language="css" code={`.my-custom-class .menu-content { @apply bg-red-500; }`} />
<CodeBlock language="html" code={`<Menu class="my-custom-class">...</Menu>`} />

View File

@@ -38,7 +38,6 @@
toastStore.trigger(t);
}
);
}
// Tables
@@ -59,7 +58,9 @@
<header class="space-y-4">
<h1>Themes</h1>
<p>
Skeleton themes integrate with Tailwind using <a href="https://tailwindcss.com/docs/customizing-colors#using-css-variables" target="_blank">CSS custom properties</a> converted to RGB values. This enables the use of <a href="https://tailwindcss.com/docs/background-color#changing-the-opacity" target="_blank">background opacity</a> as well as support for <a href="https://tailwindcss.com/docs/dark-mode" target="_blank">dark mode</a>. Components intelligently implement each color from the theme's palette.
Skeleton themes integrate with Tailwind using <a href="https://tailwindcss.com/docs/customizing-colors#using-css-variables" target="_blank">CSS custom properties</a> converted to RGB values.
This enables the use of <a href="https://tailwindcss.com/docs/background-color#changing-the-opacity" target="_blank">background opacity</a> as well as support for
<a href="https://tailwindcss.com/docs/dark-mode" target="_blank">dark mode</a>. Components intelligently implement each color from the theme's palette.
</p>
</header>
@@ -91,7 +92,14 @@
<p>Tap any theme below to automatically copy the import statement to your clipboard.</p>
<nav class="grid grid-cols-1 md:grid-cols-3 gap-4">
{#each presets as preset}
<div on:click={() => { copyThemeToClipboard(preset.name) }} class="theme-set" style:background={preset.surface} target="_blank">
<div
on:click={() => {
copyThemeToClipboard(preset.name);
}}
class="theme-set"
style:background={preset.surface}
target="_blank"
>
<span class="text-sm">{preset.name}</span>
<ul class="grid grid-cols-3 gap-2">
{#each preset.colors as color}
@@ -124,9 +132,7 @@
</span>
{/if}
{#if $storeGenerator === 'hex'}
<span class="block text-center">
For advanced users. Enterhex color values to generate a completely unique theme.
</span>
<span class="block text-center"> For advanced users. Enterhex color values to generate a completely unique theme. </span>
{/if}
<Divider class="opacity-30" />
<!-- Generator Components -->
@@ -134,7 +140,11 @@
{#if $storeGenerator === 'hex'}<ThemeGenCustom />{/if}
<Divider class="opacity-30" />
</Card>
<p class="block">TIP: Use <a href="https://tailwind.simeongriggs.dev/blue/3B82F6" target="_blank">Palette Generator</a> to for complete custom palatte curation. The <a href="https://marketplace.visualstudio.com/items?itemName=dakshmiglani.hex-to-rgba" target="_blank">Hex-To-RGB extension</a> can convert colors from <strong>Hex &rarr; RGB</strong> in bulk within <strong>VS Code</strong>.</p>
<p class="block">
TIP: Use <a href="https://tailwind.simeongriggs.dev/blue/3B82F6" target="_blank">Palette Generator</a> to for complete custom palatte curation. The
<a href="https://marketplace.visualstudio.com/items?itemName=dakshmiglani.hex-to-rgba" target="_blank">Hex-To-RGB extension</a>
can convert colors from <strong>Hex &rarr; RGB</strong> in bulk within <strong>VS Code</strong>.
</p>
<!-- Instructions -->
<TabGroup selected={storeFramework}>
<Tab value="sveltekit">SvelteKit</Tab>
@@ -193,6 +203,6 @@
<style lang="postcss">
.theme-set {
@apply p-4 !no-underline !text-white flex justify-between items-center border border-white/10 rounded shadow cursor-pointer hover:border-white/50 ;
@apply p-4 !no-underline !text-white flex justify-between items-center border border-white/10 rounded shadow cursor-pointer hover:border-white/50;
}
</style>

View File

@@ -41,7 +41,10 @@
<CodeBlock language="typescript" code={`import 'highlight.js/styles/github-dark.css';`} />
<p>Finally, import the CodeBlock's writable store and pass a referenced to Highlight.js.</p>
<CodeBlock language="typescript" code={`import { storeHighlightJs } from '@brainandbones/skeleton';\nstoreHighlightJs.set(hljs);`} />
<p>This will trigger highlighting only when a supported <a href="https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md" target="_blank">language alias</a> is provided to the CodeBlock's <code>language</code> prop.</p>
<p>
This will trigger highlighting only when a supported <a href="https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md" target="_blank">language alias</a> is provided to the
CodeBlock's <code>language</code> prop.
</p>
</section>
<!-- Usage -->

View File

@@ -9,7 +9,9 @@
let position: string = 'left';
function trigger(p: string): void {
position = p;
setTimeout(() => { storeDrawer.set(true); }, 100)
setTimeout(() => {
storeDrawer.set(true);
}, 100);
}
const tableProps: any = {
@@ -17,7 +19,7 @@
source: [
['open', 'Writable(boolean)', 'writable(false)', 'boolean', '&check;', 'Provide a store to manage visible state.'],
['position', 'string', 'left', 'left | right | top | bottom', '-', 'Set the anchor position.'],
['duration', 'number', '150', 'milliseconds', '-', 'Define the Svelte transition animation duration.'],
['duration', 'number', '150', 'milliseconds', '-', 'Define the Svelte transition animation duration.']
]
};
const tablePropsBackdrop: any = {
@@ -25,7 +27,7 @@
source: [
['bgBackdrop', 'string', 'bg-surface-400/70 dark:bg-surface-900/70', 'Provide classes to set the backdrop background color'],
['display', 'string', '-', 'Provide a class to set the display (ex: <code>lg:hidden</code>)'],
['blur', 'string', 'backdrop-blur-sm', 'Provide a class to set the blur style.'],
['blur', 'string', 'backdrop-blur-sm', 'Provide a class to set the blur style.']
]
};
const tablePropsDrawer: any = {
@@ -36,20 +38,18 @@
['rounded', 'string', '-', 'Provide a class to set border radius.'],
['width', 'string', '(based on position)', 'Provide a class to override the width.'],
['height', 'string', '(based on position)', 'Provide a class to override the height.'],
['margin', 'string', '-', 'Provide classes to set margins.'],
['margin', 'string', '-', 'Provide classes to set margins.']
]
};
const tableSlots: any = {
headings: ['Name', 'Description'],
source: [
['default', 'Provide your Drawer content here.'],
]
source: [['default', 'Provide your Drawer content here.']]
};
const tableA11y: any = {
headings: ['Prop', 'Type', 'Default', 'Description'],
source: [
['labelledby', 'string', '-', 'Provide an ID of the element labeling the drawer.'],
['describedby', 'string', '-', 'Provide an ID of the element describing the drawer.'],
['describedby', 'string', '-', 'Provide an ID of the element describing the drawer.']
]
};
</script>
@@ -75,10 +75,30 @@
</Drawer>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 max-w-[600px] mx-auto">
<Button variant="ghost-primary" on:click={() => { trigger('left') }}>Left</Button>
<Button variant="ghost-primary" on:click={() => { trigger('right') }}>Right</Button>
<Button variant="ghost-primary" on:click={() => { trigger('top') }}>Top</Button>
<Button variant="ghost-primary" on:click={() => { trigger('bottom') }}>Bottom</Button>
<Button
variant="ghost-primary"
on:click={() => {
trigger('left');
}}>Left</Button
>
<Button
variant="ghost-primary"
on:click={() => {
trigger('right');
}}>Right</Button
>
<Button
variant="ghost-primary"
on:click={() => {
trigger('top');
}}>Top</Button
>
<Button
variant="ghost-primary"
on:click={() => {
trigger('bottom');
}}>Bottom</Button
>
</div>
</Card>
@@ -86,16 +106,22 @@
<section class="space-y-4">
<h2>Usage</h2>
<p>Create a <a href="https://svelte.dev/tutorial/writable-stores" target="_blank">Svelte writable store</a> to manage the state of the drawer.</p>
<CodeBlock language="typescript" code={`
<CodeBlock
language="typescript"
code={`
import { writable, type Writable } from 'svelte/store';
const storeDrawer: Writable<boolean> = writable(false);
`.trim()} />
`.trim()}
/>
<p>Implement the Drawer component, passing the store reference. For best results implement in your app's root layout for global scope.</p>
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<Drawer open={storeDrawer} position="left">
(contents)
</Drawer>
`.trim()} />
`.trim()}
/>
<p>Set the store value to <code>true</code> or <code>false</code> to open or close the Drawer.</p>
<CodeBlock language="typescript" code={`const drawerOpen: any = () => { storeDrawer.set(true) };`} />
<CodeBlock language="typescript" code={`const drawerClose: any = () => { storeDrawer.set(false) };`} />
@@ -104,10 +130,13 @@ const storeDrawer: Writable<boolean> = writable(false);
<CodeBlock language="html" code={`<Button variant="filled-primary" on:click={drawerClose}>Close</Button>`} />
<h2>Pairing with App Shell</h2>
<p>Place the Drawer above and outside the App Shell in your root layout. This will prevent content shifting as the drawer opens.</p>
<CodeBlock language="html" code={`
<CodeBlock
language="html"
code={`
<Drawer></Drawer>
<AppShell></AppShell>
`.trim()} />
`.trim()}
/>
</section>
<!-- Properties -->
<section class="space-y-4">

View File

@@ -1,5 +1,4 @@
<!-- Layout: (root) -->
<script lang="ts">
import hljs from 'highlight.js';
import 'highlight.js/styles/github-dark.css';
@@ -39,7 +38,9 @@
storeCurrentUrl.set($page.url.pathname);
// Scroll to top
const elemPage = document.querySelector('#page');
if (elemPage !== null) { elemPage.scrollTop = 0; }
if (elemPage !== null) {
elemPage.scrollTop = 0;
}
});
// Disable left sidebar on homepage
@@ -53,7 +54,6 @@
<!-- App Shell -->
<AppShell {sidebarLeftWidth}>
<!-- Header -->
<svelte:fragment slot="header">
<SkeletonAppBar />
@@ -71,5 +71,4 @@
<svelte:fragment slot="pageFooter">
<SkeletonFooter />
</svelte:fragment>
</AppShell>

View File

@@ -14,25 +14,26 @@
async function getContributors(): Promise<any> {
const http = await fetch('https://api.github.com/repos/Brain-Bones/skeleton/contributors');
const res = await http.json();
if (http.ok) { return res; } else { throw new Error(res); }
if (http.ok) {
return res;
} else {
throw new Error(res);
}
}
let contributors: Promise<any> = getContributors();
</script>
<div>
<!-- Alert: Beta -->
<Alert>
<svelte:fragment slot="lead">🚧</svelte:fragment>
<svelte:fragment slot="message">
Skeleton is available as a public beta. Expect breaking changes prior to v1.0. If you encounter issues please report them on GitHub.</svelte:fragment>
<svelte:fragment slot="message">Skeleton is available as a public beta. Expect breaking changes prior to v1.0. If you encounter issues please report them on GitHub.</svelte:fragment>
<svelte:fragment slot="trail">
<Button variant="ghost" href="https://github.com/Brain-Bones/skeleton/issues">Report Issue</Button>
</svelte:fragment>
</Alert>
<div class="container max-w-[1200px] mx-auto px-4 py-10 md:py-20 space-y-20">
<!-- Hero -->
<header>
<div class="space-y-6">
@@ -59,7 +60,10 @@
<SvgIcon name="svelte" fill="fill-white" width="w-10" height="h-10" />
</div>
<h6>Svelte Integration</h6>
<p>Tightly coupled with Svelte, including full support for <a href="https://kit.svelte.dev/" target="_blank">SvelteKit</a>, <a href="https://vitejs.dev/" target="_blank">Vite</a>, and <a href="https://astro.build/" target="_blank">Astro</a>.</p>
<p>
Tightly coupled with Svelte, including full support for <a href="https://kit.svelte.dev/" target="_blank">SvelteKit</a>, <a href="https://vitejs.dev/" target="_blank">Vite</a>, and
<a href="https://astro.build/" target="_blank">Astro</a>.
</p>
</Card>
<Card body="space-y-4">
<div class="bg-sky-500 w-14 aspect-square flex justify-center items-center rounded-lg shadow">
@@ -121,14 +125,13 @@
<!-- Shoutouts -->
<section class="grid grid-cols-1 md:grid-cols-2 gap-10 md:gap-20">
<!-- Sponsors -->
<div class="text-center space-y-8">
<h2>Sponsors</h2>
<div class="flex flex-wrap justify-center space-x-4">
<a href="https://www.brainandbonesllc.com/" target="_blank" class="opacity-90 hover:opacity-100 !no-underline">
<Card border="border border-surface-500/30" body="flex flex-col items-center space-y-4">
<img src="https://www.brainandbonesllc.com/svg/logo.svg" alt="Brain & Bones" class="h-[32px] invert dark:invert-0">
<img src="https://www.brainandbonesllc.com/svg/logo.svg" alt="Brain & Bones" class="h-[32px] invert dark:invert-0" />
<p class="text-sm">Brain & Bones</p>
</Card>
</a>
@@ -158,10 +161,6 @@
<svelte:fragment slot="trail">&rarr;</svelte:fragment>
</Button>
</div>
</section>
</div>
</div>

View File

@@ -24,7 +24,7 @@ const config = {
package: {
// strip test files from packaging
files: (filepath) => {
return filepath.indexOf('test') == -1 ? true : false
return filepath.indexOf('test') == -1 ? true : false;
}
}
};

View File

@@ -40,5 +40,5 @@
"@brainandbones/skeleton": ["src/lib/index.ts"]
},
"outDir": "package"
},
}
}

View File

@@ -11,11 +11,9 @@ const pkg = JSON.parse(json);
/** @type {import('vite').UserConfig} */
const config = {
plugins: [
sveltekit({ hot: !process.env.VITEST }),
],
plugins: [sveltekit({ hot: !process.env.VITEST })],
define: {
'__PACKAGE__': pkg
__PACKAGE__: pkg
},
resolve: {
alias: {
@@ -26,7 +24,7 @@ const config = {
globals: true,
environment: 'jsdom',
exclude: [...configDefaults.exclude, '**/package/**', '**/build/**']
},
}
};
export default config;