feat: Skeleton Plugin refactor (#1660)

This commit is contained in:
CokaKoala
2023-07-05 17:05:25 -04:00
committed by GitHub
parent 1034074563
commit dbd2ec03c2
108 changed files with 3989 additions and 695 deletions

1
.gitignore vendored
View File

@@ -15,5 +15,6 @@ vite.config.ts.timestamp-**.mjs
/packages/* /packages/*
!/packages/create-skeleton-app !/packages/create-skeleton-app
!/packages/skeleton !/packages/skeleton
!/packages/plugin
/sites/* /sites/*
!/sites/skeleton.dev !/sites/skeleton.dev

View File

@@ -8,6 +8,7 @@
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
"getall": "node scripts/checkout.cjs && pnpm i", "getall": "node scripts/checkout.cjs && pnpm i",
"postinstall": "pnpm -r sync", "postinstall": "pnpm -r sync",
"dev": "pnpm --no-sort --filter=skeleton.dev --filter=@skeletonlabs/tw-plugin dev",
"csa": "node ./packages/create-skeleton-app/src/index.js --types=typescript --prettier --eslint --playwright=false --vitest=false --codeblocks --popups --typography --forms -t=skeleton --skeletontemplate=welcome -p=sites --monorepo --inspector", "csa": "node ./packages/create-skeleton-app/src/index.js --types=typescript --prettier --eslint --playwright=false --vitest=false --codeblocks --popups --typography --forms -t=skeleton --skeletontemplate=welcome -p=sites --monorepo --inspector",
"csl": "node ./packages/create-skeleton-app/src/index.js --types=typescript --library --prettier --eslint --playwright --vitest --codeblocks --popups --typography --forms -t=skeleton --skeletontemplate=bare -p=packages --monorepo --inspector", "csl": "node ./packages/create-skeleton-app/src/index.js --types=typescript --library --prettier --eslint --playwright --vitest --codeblocks --popups --typography --forms -t=skeleton --skeletontemplate=bare -p=packages --monorepo --inspector",
"templategen": "node ./scripts/template-gen.js", "templategen": "node ./scripts/template-gen.js",

View File

@@ -0,0 +1,16 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
plugins: ['@typescript-eslint'],
ignorePatterns: ['*.cjs', 'dist/**/*'],
overrides: [],
env: {
es2017: true,
node: true
},
rules: {
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }]
}
};

13
packages/plugin/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
.DS_Store
node_modules
build
.svelte-kit
dist
.env
.env.*
!.env.example
coverage
.temp
src/tailwind/generated
*.tgz
*.log

View File

@@ -0,0 +1,18 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
/coverage
pnpm-lock.yaml
.vscode
.github
/static/font-awesome
/static/fonts
/.temp
/dist
/scripts/tw-settings.json
src/tailwind/generated

View File

@@ -0,0 +1,6 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 140
}

View File

@@ -0,0 +1,71 @@
{
"name": "@skeletonlabs/tw-plugin",
"version": "0.0.1",
"description": "Core plugin for Skeleton.",
"private": true,
"scripts": {
"dev": "pnpm build && node ./scripts/watcher.js",
"build": "tsx ./scripts/generate-jss.ts && tsup",
"sync": "pnpm build:jss && tsup",
"package": "pnpm build:jss && tsup",
"lint": "prettier --ignore-path .prettierignore --check --plugin-search-dir=. . && eslint --fix --ignore-path .gitignore .",
"format": "prettier --ignore-path .prettierignore --write --plugin-search-dir=. .",
"build:jss": "tsx ./scripts/generate-jss.ts",
"convert": "tsx ./scripts/convert-theme.ts && pnpm format"
},
"repository": {
"type": "git",
"url": "https://github.com/skeletonlabs/skeleton.git"
},
"bugs": {
"url": "https://github.com/skeletonlabs/skeleton/issues"
},
"keywords": [
"cli",
"components",
"ui",
"component",
"svelte",
"component-library",
"ui-components",
"ui-framework",
"tailwind",
"tailwindcss",
"components-library",
"sveltekit"
],
"license": "MIT",
"homepage": "https://skeleton.dev/",
"devDependencies": {
"@types/node": "18.16.16",
"@types/postcss-import": "^14.0.0",
"@typescript-eslint/eslint-plugin": "5.59.9",
"@typescript-eslint/parser": "5.59.9",
"chokidar": "^3.5.3",
"eslint": "8.42.0",
"eslint-config-prettier": "8.8.0",
"postcss": "8.4.24",
"postcss-import": "15.1.0",
"postcss-js": "4.0.1",
"postcss-load-config": "4.0.1",
"postcss-selector-parser": "^6.0.13",
"prettier": "2.8.8",
"tailwindcss": "3.3.2",
"tslib": "2.5.3",
"tsup": "^6.7.0",
"tsx": "^3.12.7",
"typescript": "5.0.3"
},
"peerDependencies": {
"tailwindcss": ">=3.0.0"
},
"type": "commonjs",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"./dist/**/*.js",
"./dist/**/*.d.ts",
"./dist/**/*.cjs",
"./dist/**/*.d.cts"
]
}

1876
packages/plugin/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
const tailwindcss = require('tailwindcss');
const config = {
plugins: [
require('postcss-import'),
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss()
]
};
module.exports = config;

View File

@@ -0,0 +1,36 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
// Type definitions for postcss-js 4.0
// Project: https://github.com/postcss/postcss-js
// Definitions by: Adam Thompson-Sharpe <https://github.com/MysteryBlokHed>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
declare module 'postcss-js' {
type CssInJs = Record<string, any>;
/**
* Convert a PostCSS `Root` into a CSS-in-JS object
* @param root The root to convert
* @returns CSS-in-JS object
*/
function objectify(root: import('postcss').Root): CssInJs;
/**
* Parse a CSS-in-JS object into a PostCSS `Root`
* @param obj The CSS-in-JS to parse
* @returns A PostCSS `Root`
*/
function parse(obj: CssInJs): import('postcss').Root;
/**
* Create a PostCSS processor with a simple API
* @param plugins Synchronous plugins to use with PostCSS
* @returns A processor function that accepts (idk) and returns a CSS-in-JS object
*/
function sync(plugins: import('postcss').AcceptedPlugin[]): (input: CssInJs) => CssInJs;
/**
* Create a PostCSS processor with a simple API, allowing asynchronous plugins
* @param plugins Plugins to use with PostCSS
* @returns A processor function that accepts (idk) and returns a CSS-in-JS object
*/
function async(plugins: import('postcss').AcceptedPlugin[]): (input: CssInJs) => Promise<CssInJs>;
}

View File

@@ -1,18 +1,23 @@
const postcss = require('postcss'); import postcss, { type PluginCreator } from 'postcss';
const postcssJs = require('postcss-js'); import postcssJs from 'postcss-js';
const fs = require('fs'); import { readFileSync } from 'fs';
const postcssImport = require('postcss-import'); import postcssImport from 'postcss-import';
const tailwindcss = require('tailwindcss'); import tw from 'tailwindcss';
import type { Config } from 'tailwindcss';
import { corePlugin } from '../src/tailwind/core.js';
// tailwind needs to fix their exports :]
const tailwindcss = tw as unknown as PluginCreator<string | Config | { config: string | Config }>;
// Transpiles all of our library's CSS to JS // Transpiles all of our library's CSS to JS
async function transpileCssToJs(cssEntryPath, plugins = []) { export async function transpileCssToJs(cssEntryPath: string, plugins: Config['plugins'] = []) {
const selectors = []; const selectors: string[] = [];
// We'll first get all the custom the class names, // We'll first get all the custom class names,
// then we can feed that into the TW preprocessor as the `content` // then we can feed that into the TW preprocessor as the `content`
// so that TW can detect and generate them properly // so that TW can detect and generate them properly
const css = fs.readFileSync(cssEntryPath, 'utf8'); const css = readFileSync(cssEntryPath, 'utf8');
const processor = postcss([postcssImport()]); const processor = postcss([postcssImport()]);
const result = await processor.process(css, { from: cssEntryPath }); const result = await processor.process(css, { from: cssEntryPath });
@@ -27,11 +32,11 @@ async function transpileCssToJs(cssEntryPath, plugins = []) {
darkMode: 'class', darkMode: 'class',
content: [{ raw: selectors.join(' ') }], content: [{ raw: selectors.join(' ') }],
plugins: [ plugins: [
require('../src/lib/tailwind/core.cjs'), corePlugin,
// add skeleton component classes for the base styles // add skeleton component classes for the base styles
...plugins ...plugins
] ]
}; } satisfies Config;
const result2 = await postcss([postcssImport(), tailwindcss(twConfig)]).process(css, { from: cssEntryPath }); const result2 = await postcss([postcssImport(), tailwindcss(twConfig)]).process(css, { from: cssEntryPath });
if (result2.root.type === 'document') throw Error('This should never happen'); if (result2.root.type === 'document') throw Error('This should never happen');
@@ -44,10 +49,10 @@ async function transpileCssToJs(cssEntryPath, plugins = []) {
// Generates all TW base styles so that we can use this to // Generates all TW base styles so that we can use this to
// the remove duplicates in our plugin. // the remove duplicates in our plugin.
// Takes ~600ms second to run. // Takes ~600ms second to run.
async function generateBaseTWStyles() { export async function generateBaseTWStyles() {
const twConfig = { const twConfig = {
content: [{ raw: 'w-1' }] content: [{ raw: 'w-1' }]
}; } satisfies Config;
const result = await postcss(tailwindcss(twConfig)).process('@tailwind base', { from: undefined }); const result = await postcss(tailwindcss(twConfig)).process('@tailwind base', { from: undefined });
if (result.root.type === 'document') throw Error('This should never happen'); if (result.root.type === 'document') throw Error('This should never happen');
@@ -56,5 +61,3 @@ async function generateBaseTWStyles() {
return cssInJs; return cssInJs;
} }
module.exports = { transpileCssToJs, generateBaseTWStyles };

View File

@@ -0,0 +1,35 @@
import { readFileSync } from 'fs';
import { writeFile } from 'fs/promises';
import postcss from 'postcss';
import postcssJs from 'postcss-js';
import type { Theme } from '../src/tailwind/themes';
// Converts a theme's .css file into a .ts file.
export async function convertTheme(name: string) {
const cssEntryPath = `./src/themes/theme-${name}.css`;
const css = readFileSync(cssEntryPath, 'utf8');
const result = postcss().process(css, { from: cssEntryPath });
const cssInJs = postcssJs.objectify(result.root);
const properties = { ...cssInJs[':root'] };
delete cssInJs[':root'];
const theme = {
properties: properties,
enhancements: { ...cssInJs }
} satisfies Theme;
// Creates the generated CSS-in-JS file
await writeFile(
`./src/tailwind/themes/${name}.ts`,
`import type { Theme } from './index.js';
const ${name} = ${JSON.stringify(theme, undefined, '\t')} satisfies Theme;
export default ${name};`
).catch((e) => console.error(e));
}
convertTheme('vintage');

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env tsx
import type { CssInJs } from 'postcss-js';
import { generateBaseTWStyles, transpileCssToJs } from './compile-css-to-js.js';
import { mkdir, writeFile } from 'fs/promises';
import plugin from 'tailwindcss/plugin.js';
const INTELLISENSE_FILE_NAME = 'generated-classes.js';
const GENERATED_DIR_PATH = `./src/tailwind/generated`;
async function exec() {
// Makes directory that stores our generated CSS-in-JS
await mkdir(GENERATED_DIR_PATH).catch(() => {
// directory already exists
});
const baseTWStyles = await generateBaseTWStyles();
const generatedComponentJSS = await transpileCssToJs('./src/styles/components.css');
const cleanedComponentClasses = removeDuplicateClasses(generatedComponentJSS, baseTWStyles);
const componentClasses = patchMediaQueries(cleanedComponentClasses);
const componentPlugin = plugin(({ addComponents }) => {
addComponents(componentClasses);
});
const generatedBaseJSS = await transpileCssToJs('./src/styles/base.css', [componentPlugin]);
const baseStyles = removeDuplicateClasses(generatedBaseJSS, baseTWStyles);
// Creates the generated CSS-in-JS file
await writeFile(
`${GENERATED_DIR_PATH}/${INTELLISENSE_FILE_NAME}`,
`module.exports = { components: ${JSON.stringify(componentClasses)}, base: ${JSON.stringify(baseStyles)} };`
).catch((e) => console.error(e));
}
// Purges the generated CSS-in-JS file of duplicate TW classes
function removeDuplicateClasses(cssInJs: CssInJs, baseTWStyles: CssInJs) {
// We'll delete all the TW Base styles (i.e. html {...} body {...} etc.)
for (const key of Object.keys(cssInJs)) {
if (baseTWStyles[key] !== undefined) delete cssInJs[key];
}
return cssInJs;
}
// Moves all of the media queries towards the end of the cssInJs object.
function patchMediaQueries(cssInJs: CssInJs) {
const mediaQueries: CssInJs = {};
for (const key of Object.keys(cssInJs)) {
if (key.startsWith('@media')) {
mediaQueries[key] = cssInJs[key];
delete cssInJs[key];
}
}
for (const key of Object.keys(mediaQueries)) {
cssInJs[key] = mediaQueries[key];
}
return cssInJs;
}
exec();

View File

@@ -0,0 +1,24 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const chokidar = require('chokidar');
const { join, resolve, basename } = require('path');
const { exec } = require('child_process');
const pathToStyles = resolve('.', join('src'));
// We want to ignore the `generated` dir so we don't have an endless loop
const generatedPath = resolve('.', join('src', 'tailwind', 'generated'));
// Simple watcher to detect changes in /packages/plugin/src
// This will rebuild the package on any `src` file changes.
let locked = false;
chokidar.watch(pathToStyles, { ignored: [generatedPath] }).on('change', (path) => {
const now = Date.now();
console.log(`[Build Start]: File Updated: ${basename(path)}`);
if (!locked) {
locked = true;
exec('pnpm -F @skeletonlabs/tw-plugin build', () => {
console.log(`[Build End]: Completed in ${Date.now() - now}ms`);
locked = false;
});
}
});

View File

@@ -0,0 +1,73 @@
import plugin from 'tailwindcss/plugin.js';
import postcssJs from 'postcss-js';
import { coreConfig, coreUtilities, getSkeletonClasses } from './tailwind/core.js';
import { themes, getThemeProperties } from './tailwind/themes/index.js';
import { prefixSelector } from './tailwind/prefixSelector.js';
import type { CSSRuleObject } from 'tailwindcss/types/config.js';
import type { ConfigOptions, CustomThemeConfig, PresetThemeConfig, ThemeConfig } from './types.js';
const skeleton = plugin.withOptions<ConfigOptions>(
// Plugin Creator
(options) => {
return ({ addBase, addComponents, addUtilities }) => {
const { components, base } = getSkeletonClasses();
let baseStyles: CSSRuleObject = {};
let componentStyles = components;
// Base styles configuration
if (options?.base !== false) {
baseStyles = { ...base };
}
// Custom Themes configuration
options?.themes?.custom?.forEach((theme) => {
// it's a custom theme
baseStyles[`:root [data-theme='${theme.name}']`] = theme.properties;
});
// Preset Themes configuration
options?.themes?.preset?.forEach((theme) => {
// it's a preset theme but just the name was passed in
if (typeof theme === 'string') {
const themeName = theme;
// we only want the properties
baseStyles[`:root [data-theme='${themeName}']`] = themes[themeName].properties;
return;
}
// it's a preset theme
if (!('properties' in theme)) {
baseStyles[`:root [data-theme='${theme.name}']`] = themes[theme.name].properties;
if (theme.enhancements === true) {
// enhancements are opt-in
baseStyles = { ...baseStyles, ...themes[theme.name].enhancements };
}
return;
}
});
// Prefix component classes
if (options?.prefix) {
const prefix = options?.prefix;
const root = postcssJs.parse(components);
root.walkRules((rule) => {
rule.selector = prefixSelector(prefix, rule.selector);
});
componentStyles = postcssJs.objectify(root);
}
addBase(baseStyles);
addUtilities(coreUtilities);
addComponents(componentStyles, { respectPrefix: false });
};
},
// Config
() => {
return { ...coreConfig };
}
);
export { getThemeProperties, skeleton };
export type { CustomThemeConfig, ConfigOptions, PresetThemeConfig, ThemeConfig };

View File

@@ -0,0 +1,2 @@
@import 'tailwind.css';
@import 'base/index.css';

View File

@@ -5,6 +5,8 @@
body { body {
@apply bg-surface-50-900-token; @apply bg-surface-50-900-token;
/* Typography */
@apply text-base font-token text-token;
} }
/* === Selection === */ /* === Selection === */
@@ -46,21 +48,9 @@
scrollbar-color: rgba(255, 255, 255, 0.1) rgba(0, 0, 0, 0.05); scrollbar-color: rgba(255, 255, 255, 0.1) rgba(0, 0, 0, 0.05);
} }
/* Hide Scrollbars */
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.hide-scrollbar {
-ms-overflow-style: none; /* IE/Edge */
scrollbar-width: none; /* Firefox */
}
/* === Horizontal Rules === */ /* === Horizontal Rules === */
hr:not(.divider) { hr:not(.divider) {
@apply block border-t border-solid border-surface-300-600-token; @apply block border-t border-solid border-surface-300-600-token;
} }
.divider-vertical {
@apply inline-block border-l border-solid border-surface-300-600-token min-h-[10px] mx-auto;
}
} }

View File

@@ -0,0 +1,35 @@
/* Tailwind Elements: elements.css */
@layer base {
/* === States === */
/* File Input Button */
input[type='file']:not(.file-dropzone-input)::file-selector-button {
@apply border-0 btn variant-filled btn-sm mr-2;
}
/* Range Input */
/* https://developer.mozilla.org/en-US/docs/Web/CSS/accent-color */
[type='range'] {
@apply w-full accent-surface-900 dark:accent-surface-50;
}
/* === Sort Styles ==== */
[data-sort] {
@apply hover:bg-primary-hover-token cursor-pointer;
/* Sort Icon - invisible by default */
@apply after:opacity-0 after:!ml-2 after:!content-['↓'];
}
/* === Popup === */
[data-popup] {
/* https://floating-ui.com/docs/computeposition#usage */
@apply absolute top-0 left-0;
/* Set hidden on page load */
@apply hidden;
/* Transitions */
@apply transition-opacity duration-150;
}
}

View File

@@ -0,0 +1,63 @@
/* Stylesheet: forms.css */
@layer base {
/* === Resets === */
fieldset,
legend,
label {
@apply block;
}
/* Placeholders */
::-moz-placeholder {
@apply text-surface-500-400-token;
}
:-ms-input-placeholder {
@apply text-surface-500-400-token;
}
::placeholder {
@apply text-surface-500-400-token;
}
/* Date Calendar Picker (Webkit) */
input::-webkit-calendar-picker-indicator {
@apply dark:invert;
}
/* Search Input "X" Cancel Button (Webkit) */
/* Source: https://stackoverflow.com/a/64267916 */
input[type='search']::-webkit-search-cancel-button {
-webkit-appearance: none;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z'/%3E%3C/svg%3E")
no-repeat 50% 50%;
@apply h-4 w-4 rounded-full bg-contain opacity-0 pointer-events-none;
}
input[type='search']:focus::-webkit-search-cancel-button {
@apply opacity-100 pointer-events-auto;
}
input[type='search']::-webkit-search-cancel-button {
@apply dark:invert;
}
/* Progress Bar */
progress {
webkit-appearance: none;
-moz-appearance: none;
appearance: none;
@apply w-full h-2 overflow-hidden rounded-token;
@apply bg-surface-400-500-token;
}
progress::-webkit-progress-bar {
@apply bg-surface-400-500-token;
}
progress::-webkit-progress-value {
@apply bg-surface-900-50-token;
}
::-moz-progress-bar {
@apply bg-surface-900-50-token;
}
:indeterminate::-moz-progress-bar {
width: 0;
}
}

View File

@@ -0,0 +1,4 @@
/* Core should be optional in the plugin */
@import 'core.css';
@import 'forms.css';
@import 'elements.css';

View File

@@ -0,0 +1,2 @@
@import 'tailwind.css';
@import 'components/index.css';

View File

@@ -1,16 +1,6 @@
/* Tailwind Elements: breadcrumbs.css */ /* Tailwind Elements: breadcrumbs.css */
@layer components { @layer components {
/* Hide Scrollbars */
/* Duplicated from core.css to support `skeleton-minimal.css` */
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.hide-scrollbar {
-ms-overflow-style: none; /* IE/Edge */
scrollbar-width: none; /* Firefox */
}
.breadcrumb, .breadcrumb,
.breadcrumb-nonresponsive { .breadcrumb-nonresponsive {
@apply flex items-center space-x-4 w-full hide-scrollbar overflow-x-auto; @apply flex items-center space-x-4 w-full hide-scrollbar overflow-x-auto;

View File

@@ -3,10 +3,6 @@
@layer components { @layer components {
/* === States === */ /* === States === */
button:disabled {
@apply !opacity-50 !cursor-not-allowed active:scale-100 hover:brightness-100;
}
.button-base-styles { .button-base-styles {
/* Size (match base) */ /* Size (match base) */
@apply text-base; @apply text-base;
@@ -29,6 +25,10 @@
@apply button-base-styles rounded-token active:scale-[95%] active:brightness-90; @apply button-base-styles rounded-token active:scale-[95%] active:brightness-90;
} }
.btn:disabled {
@apply !opacity-50 !cursor-not-allowed active:scale-100 hover:brightness-100;
}
/* Button: Sizes */ /* Button: Sizes */
/* Note: Default values are built into `.btn` */ /* Note: Default values are built into `.btn` */
.btn-sm { .btn-sm {
@@ -71,11 +71,6 @@
@apply text-xl aspect-square w-[63px]; @apply text-xl aspect-square w-[63px];
} }
/* File Input Button */
input[type='file']:not(.file-dropzone-input)::file-selector-button {
@apply border-0 btn variant-filled btn-sm mr-2;
}
/* === Button Groups === */ /* === Button Groups === */
.btn-group { .btn-group {

View File

@@ -0,0 +1,7 @@
@layer components {
/* === Horizontal Rules === */
.divider-vertical {
@apply inline-block border-l border-solid border-surface-300-600-token min-h-[10px] mx-auto;
}
}

View File

@@ -1,72 +1,6 @@
/* Stylesheet: forms.css */ /* Stylesheet: forms.css */
@layer base { @layer components {
/* === Resets === */
fieldset,
legend,
label {
@apply block;
}
/* Placeholders */
::-moz-placeholder {
@apply text-surface-500-400-token;
}
:-ms-input-placeholder {
@apply text-surface-500-400-token;
}
::placeholder {
@apply text-surface-500-400-token;
}
/* Date Calendar Picker (Webkit) */
input::-webkit-calendar-picker-indicator {
@apply dark:invert;
}
/* Search Input "X" Cancel Button (Webkit) */
/* Source: https://stackoverflow.com/a/64267916 */
input[type='search']::-webkit-search-cancel-button {
-webkit-appearance: none;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z'/%3E%3C/svg%3E")
no-repeat 50% 50%;
@apply h-4 w-4 rounded-full bg-contain opacity-0 pointer-events-none;
}
input[type='search']:focus::-webkit-search-cancel-button {
@apply opacity-100 pointer-events-auto;
}
input[type='search']::-webkit-search-cancel-button {
@apply dark:invert;
}
/* Progress Bar */
progress {
webkit-appearance: none;
-moz-appearance: none;
appearance: none;
@apply w-full h-2 overflow-hidden rounded-token;
@apply bg-surface-400-500-token;
}
progress::-webkit-progress-bar {
@apply bg-surface-400-500-token;
}
progress::-webkit-progress-value {
@apply bg-surface-900-50-token;
}
::-moz-progress-bar {
@apply bg-surface-900-50-token;
}
:indeterminate::-moz-progress-bar {
width: 0;
}
/* Range Input */
/* https://developer.mozilla.org/en-US/docs/Web/CSS/accent-color */
[type='range'] {
@apply w-full accent-surface-900 dark:accent-surface-50;
}
/* === Text Labeling === */ /* === Text Labeling === */
.legend { .legend {

View File

@@ -0,0 +1,23 @@
@import 'scrollbars.css';
@import 'dividers.css';
@import 'typography.css';
/* Elements */
@import 'alerts.css';
@import 'badges.css';
@import 'breadcrumbs.css';
@import 'buttons.css';
@import 'cards.css';
@import 'codeblocks.css';
@import 'chips.css';
@import 'forms.css';
@import 'lists.css';
@import 'logo-clouds.css';
@import 'placeholders.css';
@import 'tables.css';
/* Utilities */
@import 'modals.css';
@import 'popups.css';
@import 'variants.css';

View File

@@ -0,0 +1,17 @@
/* Tailwind Elements: modals.css */
@layer components {
/* === Modal (helpers) === */
.w-modal-slim {
@apply w-full max-w-[400px];
}
.w-modal {
@apply w-full max-w-[640px];
}
.w-modal-wide {
@apply w-full max-w-[80%];
}
}

View File

@@ -0,0 +1,9 @@
/* Tailwind Elements: popups.css */
@layer components {
/* === Popup === */
[data-popup] .arrow {
@apply absolute rotate-45 w-2 h-2;
}
}

View File

@@ -0,0 +1,11 @@
@layer components {
/* === Hide Scrollbars === */
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.hide-scrollbar {
-ms-overflow-style: none; /* IE/Edge */
scrollbar-width: none; /* Firefox */
}
}

View File

@@ -25,12 +25,6 @@
/* === Sort Styles ==== */ /* === Sort Styles ==== */
[data-sort] {
@apply hover:bg-primary-hover-token cursor-pointer;
/* Sort Icon - invisible by default */
@apply after:opacity-0 after:!ml-2 after:!content-['↓'];
}
.table-sort-asc { .table-sort-asc {
@apply after:opacity-50 after:!content-['↑']; @apply after:opacity-50 after:!content-['↑'];
} }

View File

@@ -2,14 +2,9 @@
/* /*
This represents the OPT-IN typography styles. This represents the OPT-IN typography styles.
IMPORTANT: take care to maintain parity with typography.css!
*/ */
@layer base { @layer components {
body {
@apply text-base font-token text-token;
}
/* === Headings === */ /* === Headings === */
.h1 { .h1 {

View File

@@ -0,0 +1,32 @@
/* Stylesheet: tailwind.css */
/*
https://tailwindcss.com/docs/functions-and-directives
*/
/**
* This injects Tailwind's base styles and any base styles registered by
* plugins.
*/
@tailwind base;
/**
* This injects Tailwind's component classes and any component classes
* registered by plugins.
*/
@tailwind components;
/**
* This injects Tailwind's utility classes and any utility classes registered
* by plugins.
*/
@tailwind utilities;
/**
* Use this directive to control where Tailwind injects the hover, focus,
* responsive, dark mode, and other variants of each class.
*
* If omitted, Tailwind will append these classes to the very end of
* your stylesheet by default.
*/
@tailwind variants;

View File

@@ -1,18 +1,24 @@
// Extends Tailwind with Skeleton theme-specific colors values // Extends Tailwind with Skeleton theme-specific colors values
// Doc: https://tailwindcss.com/docs/customizing-colors#using-css-variables // Doc: https://tailwindcss.com/docs/customizing-colors#using-css-variables
const settings = require('../settings.cjs'); import settings from './settings.js';
type Shade = { [shadeValue: number]: string };
// ex: `50: 'rgb(var(--color-primary-50) / <alpha-value>)'` // ex: `50: 'rgb(var(--color-primary-50) / <alpha-value>)'`
function generatePaletteShades(colorName) { function generatePaletteShades(colorName: string) {
const shadeObj = {}; const shadeObj: Shade = {};
settings.colorShades.forEach((s) => (shadeObj[s] = `rgb(var(--color-${colorName}-${s}) / <alpha-value>)`)); settings.colorShades.forEach((s) => (shadeObj[s] = `rgb(var(--color-${colorName}-${s}) / <alpha-value>)`));
return shadeObj; return shadeObj;
} }
type Palette = { [colorName: string]: Shade };
// Generate a a color shade palette 50-900 per each color available // Generate a a color shade palette 50-900 per each color available
module.exports = () => { export const colors = () => {
const paletteObj = {}; const paletteObj: Palette = {};
settings.colorNames.forEach((n) => (paletteObj[n] = generatePaletteShades(n))); settings.colorNames.forEach((n) => (paletteObj[n] = generatePaletteShades(n)));
return paletteObj; return paletteObj;
}; };
export default colors;

View File

@@ -0,0 +1,59 @@
/* eslint-disable @typescript-eslint/no-var-requires */
// The Skeleton Tailwind Plugin
// Tailwind Docs: https://tailwindcss.com/docs/plugins
// Skeleton Docs: https://www.skeleton.dev/docs/get-started
import plugin from 'tailwindcss/plugin.js';
// Skeleton Theme Modules
import themeColors from './colors.js';
// Skeleton Design Token Modules
import tokensBackgrounds from './tokens/backgrounds.js';
import tokensBorders from './tokens/borders.js';
import tokensBorderRadius from './tokens/border-radius.js';
import tokensFills from './tokens/fills.js';
import tokensText from './tokens/text.js';
import tokensRings from './tokens/rings.js';
export const coreUtilities = {
// Implement Skeleton design token classes
...tokensBackgrounds(),
...tokensBorders(),
...tokensBorderRadius(),
...tokensFills(),
...tokensText(),
...tokensRings()
};
export const coreConfig = {
theme: {
extend: {
// Implement Skeleton theme colors
colors: themeColors()
}
}
};
// export const coreClasses = getSkeletonClasses();
export function getSkeletonClasses() {
// try/catch because it will throw when generated-classes.js isn't generated yet
try {
const { components, base } = require('./generated/generated-classes.js');
if (typeof components !== 'object' || typeof base !== 'object') {
console.error('Failed to load Skeleton classes');
process.exitCode = 1;
}
return { components, base };
} catch {
console.error("generated-classes.js hasn't generated yet");
}
return { components: undefined, base: undefined };
}
export const corePlugin = plugin(({ addUtilities }) => {
addUtilities(coreUtilities);
}, coreConfig);

View File

@@ -0,0 +1,28 @@
// Credits: https://github.com/tailwindlabs/tailwindcss/blob/master/src/util/prefixSelector.js
import parser from 'postcss-selector-parser';
/**
* Prefix all classes in the selector with the given prefix
*/
export function prefixSelector(prefix: string, selector: string, prependNegative = false): string {
if (prefix === '') {
return selector;
}
const ast = parser().astSync(selector);
ast.walkClasses((classSelector) => {
const baseClass = classSelector.value;
// don't modify the dark class
if (baseClass === 'dark') {
return;
}
const shouldPlaceNegativeBeforePrefix = prependNegative && baseClass.startsWith('-');
classSelector.value = shouldPlaceNegativeBeforePrefix ? `-${prefix}${baseClass.slice(1)}` : `${prefix}${baseClass}`;
});
return ast.toString();
}

View File

@@ -1,6 +1,6 @@
// Common Shared Settings and Constants // Common Shared Settings and Constants
module.exports = { export const settings = {
colorNames: ['primary', 'secondary', 'tertiary', 'success', 'warning', 'error', 'surface'], colorNames: ['primary', 'secondary', 'tertiary', 'success', 'warning', 'error', 'surface'],
colorShades: [50, 100, 200, 300, 400, 500, 600, 700, 800, 900], colorShades: [50, 100, 200, 300, 400, 500, 600, 700, 800, 900],
colorPairings: [ colorPairings: [
@@ -17,4 +17,10 @@ module.exports = {
{ light: 600, dark: 300 }, { light: 600, dark: 300 },
{ light: 500, dark: 400 } { light: 500, dark: 400 }
] ]
} as const;
export type CssClasses = {
[className: string]: string | CssClasses;
}; };
export default settings;

View File

@@ -0,0 +1,94 @@
import type { Theme } from './index.js';
const crimson = {
properties: {
'--theme-font-family-base':
"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,\n\t\t'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'",
'--theme-font-family-heading': 'system-ui',
'--theme-font-color-base': 'var(--color-surface-900)',
'--theme-font-color-dark': 'var(--color-surface-50)',
'--theme-rounded-base': '24px',
'--theme-rounded-container': '24px',
'--theme-border-base': '1px',
'--on-primary': '255 255 255',
'--on-secondary': '255 255 255',
'--on-tertiary': '0 0 0',
'--on-success': '0 0 0',
'--on-warning': '0 0 0',
'--on-error': '0 0 0',
'--on-surface': '255 255 255',
'--color-primary-50': '249 220 226',
'--color-primary-100': '246 208 216',
'--color-primary-200': '244 197 206',
'--color-primary-300': '238 162 177',
'--color-primary-400': '225 92 119',
'--color-primary-500': '212 22 60',
'--color-primary-600': '191 20 54',
'--color-primary-700': '159 17 45',
'--color-primary-800': '127 13 36',
'--color-primary-900': '104 11 29',
'--color-secondary-50': '227 237 243',
'--color-secondary-100': '218 231 239',
'--color-secondary-200': '209 225 235',
'--color-secondary-300': '181 206 223',
'--color-secondary-400': '126 170 199',
'--color-secondary-500': '70 133 175',
'--color-secondary-600': '63 120 158',
'--color-secondary-700': '53 100 131',
'--color-secondary-800': '42 80 105',
'--color-secondary-900': '34 65 86',
'--color-tertiary-50': '246 244 244',
'--color-tertiary-100': '242 240 240',
'--color-tertiary-200': '239 237 236',
'--color-tertiary-300': '230 226 225',
'--color-tertiary-400': '211 204 203',
'--color-tertiary-500': '192 182 180',
'--color-tertiary-600': '173 164 162',
'--color-tertiary-700': '144 137 135',
'--color-tertiary-800': '115 109 108',
'--color-tertiary-900': '94 89 88',
'--color-success-50': '246 250 239',
'--color-success-100': '243 248 234',
'--color-success-200': '240 247 229',
'--color-success-300': '230 241 213',
'--color-success-400': '212 231 182',
'--color-success-500': '193 221 151',
'--color-success-600': '174 199 136',
'--color-success-700': '145 166 113',
'--color-success-800': '116 133 91',
'--color-success-900': '95 108 74',
'--color-warning-50': '251 246 231',
'--color-warning-100': '250 243 223',
'--color-warning-200': '248 240 215',
'--color-warning-300': '244 231 191',
'--color-warning-400': '236 212 142',
'--color-warning-500': '228 194 94',
'--color-warning-600': '205 175 85',
'--color-warning-700': '171 146 71',
'--color-warning-800': '137 116 56',
'--color-warning-900': '112 95 46',
'--color-error-50': '248 236 236',
'--color-error-100': '246 229 230',
'--color-error-200': '244 223 224',
'--color-error-300': '237 204 205',
'--color-error-400': '224 165 167',
'--color-error-500': '210 127 129',
'--color-error-600': '189 114 116',
'--color-error-700': '158 95 97',
'--color-error-800': '126 76 77',
'--color-error-900': '103 62 63',
'--color-surface-50': '223 224 226',
'--color-surface-100': '213 213 217',
'--color-surface-200': '202 203 207',
'--color-surface-300': '170 171 179',
'--color-surface-400': '107 109 121',
'--color-surface-500': '43 46 64',
'--color-surface-600': '39 41 58',
'--color-surface-700': '32 35 48',
'--color-surface-800': '26 28 38',
'--color-surface-900': '21 23 31'
},
enhancements: {}
} satisfies Theme;
export default crimson;

View File

@@ -0,0 +1,117 @@
import type { Theme } from './index.js';
const goldNouveau = {
properties: {
'--theme-font-family-base': 'system-ui, sans-serif',
'--theme-font-family-heading': "'Quicksand', sans-serif",
'--theme-font-color-base': 'var(--color-surface-900)',
'--theme-font-color-dark': 'var(--color-surface-50)',
'--theme-rounded-base': '4px',
'--theme-rounded-container': '4px',
'--theme-border-base': '1px',
'--on-primary': '255 255 255',
'--on-secondary': '255 255 255',
'--on-tertiary': '255 255 255',
'--on-success': '0 0 0',
'--on-warning': '0 0 0',
'--on-error': '255 255 255',
'--on-surface': '255 255 255',
'--color-primary-50': '250 248 252',
'--color-primary-100': '242 238 247',
'--color-primary-200': '229 220 239',
'--color-primary-300': '209 192 226',
'--color-primary-400': '162 129 197',
'--color-primary-500': '116 74 161',
'--color-primary-600': '83 53 115',
'--color-primary-700': '60 39 84',
'--color-primary-800': '35 22 49',
'--color-primary-900': '18 11 24',
'--color-secondary-50': '218 234 251',
'--color-secondary-100': '205 227 250',
'--color-secondary-200': '193 220 249',
'--color-secondary-300': '155 199 245',
'--color-secondary-400': '81 156 237',
'--color-secondary-500': '6 114 229',
'--color-secondary-600': '5 103 206',
'--color-secondary-700': '5 86 172',
'--color-secondary-800': '4 68 137',
'--color-secondary-900': '3 56 112',
'--color-tertiary-50': '236 235 250',
'--color-tertiary-100': '229 228 248',
'--color-tertiary-200': '223 221 247',
'--color-tertiary-300': '204 201 241',
'--color-tertiary-400': '165 161 231',
'--color-tertiary-500': '127 120 221',
'--color-tertiary-600': '114 108 199',
'--color-tertiary-700': '95 90 166',
'--color-tertiary-800': '76 72 133',
'--color-tertiary-900': '62 59 108',
'--color-success-50': '234 246 237',
'--color-success-100': '227 243 231',
'--color-success-200': '220 241 225',
'--color-success-300': '199 232 206',
'--color-success-400': '156 214 170',
'--color-success-500': '114 197 133',
'--color-success-600': '103 177 120',
'--color-success-700': '86 148 100',
'--color-success-800': '68 118 80',
'--color-success-900': '56 97 65',
'--color-warning-50': '251 236 218',
'--color-warning-100': '250 229 206',
'--color-warning-200': '249 223 193',
'--color-warning-300': '245 204 156',
'--color-warning-400': '238 165 82',
'--color-warning-500': '231 127 8',
'--color-warning-600': '208 114 7',
'--color-warning-700': '173 95 6',
'--color-warning-800': '139 76 5',
'--color-warning-900': '113 62 4',
'--color-error-50': '238 219 222',
'--color-error-100': '233 207 211',
'--color-error-200': '227 195 200',
'--color-error-300': '210 159 167',
'--color-error-400': '177 87 100',
'--color-error-500': '143 15 34',
'--color-error-600': '129 14 31',
'--color-error-700': '107 11 26',
'--color-error-800': '86 9 20',
'--color-error-900': '70 7 17',
'--color-surface-50': '250 248 252',
'--color-surface-100': '242 238 247',
'--color-surface-200': '229 220 239',
'--color-surface-300': '209 192 226',
'--color-surface-400': '162 129 197',
'--color-surface-500': '116 74 161',
'--color-surface-600': '83 53 115',
'--color-surface-700': '60 39 84',
'--color-surface-800': '35 22 49',
'--color-surface-900': '18 11 24'
},
enhancements: {
".dark [data-theme='gold-nouveau']": {
'--on-primary': '0 0 0',
'--color-primary-50': '251 247 224',
'--color-primary-100': '250 244 214',
'--color-primary-200': '249 241 204',
'--color-primary-300': '245 233 173',
'--color-primary-400': '238 217 112',
'--color-primary-500': '230 200 51',
'--color-primary-600': '207 180 46',
'--color-primary-700': '173 150 38',
'--color-primary-800': '138 120 31',
'--color-primary-900': '113 98 25'
},
"[data-theme='gold-nouveau'] h1,\n[data-theme='gold-nouveau'] h2,\n[data-theme='gold-nouveau'] h3,\n[data-theme='gold-nouveau'] h4,\n[data-theme='gold-nouveau'] h5,\n[data-theme='gold-nouveau'] h6":
{ fontWeight: 'bold' },
"[data-theme='gold-nouveau']": {
backgroundImage:
'radial-gradient(at 0% 100%, rgba(var(--color-secondary-500) / 0.33) 0px, transparent 50%),\n\t\tradial-gradient(at 98% 100%, rgba(var(--color-error-500) / 0.33) 0px, transparent 50%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
}
}
} satisfies Theme;
export default goldNouveau;

View File

@@ -0,0 +1,103 @@
import type { Theme } from './index.js';
const hamlindigo = {
properties: {
'--theme-font-family-base':
"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,\n\t\t'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'",
'--theme-font-family-heading': 'serif',
'--theme-font-color-base': '0 0 0',
'--theme-font-color-dark': '255 255 255',
'--theme-rounded-base': '2px',
'--theme-rounded-container': '2px',
'--theme-border-base': '2px',
'--on-primary': '0 0 0',
'--on-secondary': '255 255 255',
'--on-tertiary': '255 255 255',
'--on-success': '255 255 255',
'--on-warning': '0 0 0',
'--on-error': '255 255 255',
'--on-surface': '255 255 255',
'--color-primary-50': '242 245 253',
'--color-primary-100': '238 242 252',
'--color-primary-200': '233 239 252',
'--color-primary-300': '220 229 249',
'--color-primary-400': '194 210 245',
'--color-primary-500': '168 190 241',
'--color-primary-600': '151 171 217',
'--color-primary-700': '126 143 181',
'--color-primary-800': '101 114 145',
'--color-primary-900': '82 93 118',
'--color-secondary-50': '241 238 230',
'--color-secondary-100': '237 232 222',
'--color-secondary-200': '232 227 214',
'--color-secondary-300': '219 210 189',
'--color-secondary-400': '191 176 140',
'--color-secondary-500': '164 142 91',
'--color-secondary-600': '148 128 82',
'--color-secondary-700': '123 107 68',
'--color-secondary-800': '98 85 55',
'--color-secondary-900': '80 70 45',
'--color-tertiary-50': '231 239 241',
'--color-tertiary-100': '223 234 237',
'--color-tertiary-200': '216 229 232',
'--color-tertiary-300': '192 213 218',
'--color-tertiary-400': '144 182 191',
'--color-tertiary-500': '97 151 163',
'--color-tertiary-600': '87 136 147',
'--color-tertiary-700': '73 113 122',
'--color-tertiary-800': '58 91 98',
'--color-tertiary-900': '48 74 80',
'--color-success-50': '227 239 236',
'--color-success-100': '218 234 229',
'--color-success-200': '209 228 223',
'--color-success-300': '181 212 203',
'--color-success-400': '126 180 164',
'--color-success-500': '71 148 125',
'--color-success-600': '64 133 113',
'--color-success-700': '53 111 94',
'--color-success-800': '43 89 75',
'--color-success-900': '35 73 61',
'--color-warning-50': '249 242 226',
'--color-warning-100': '248 238 216',
'--color-warning-200': '246 234 207',
'--color-warning-300': '240 221 178',
'--color-warning-400': '229 195 120',
'--color-warning-500': '218 169 62',
'--color-warning-600': '196 152 56',
'--color-warning-700': '164 127 47',
'--color-warning-800': '131 101 37',
'--color-warning-900': '107 83 30',
'--color-error-50': '241 231 234',
'--color-error-100': '236 223 227',
'--color-error-200': '232 216 221',
'--color-error-300': '218 192 200',
'--color-error-400': '190 144 158',
'--color-error-500': '162 97 117',
'--color-error-600': '146 87 105',
'--color-error-700': '122 73 88',
'--color-error-800': '97 58 70',
'--color-error-900': '79 48 57',
'--color-surface-50': '232 234 241',
'--color-surface-100': '224 228 237',
'--color-surface-200': '216 221 232',
'--color-surface-300': '193 200 218',
'--color-surface-400': '146 159 191',
'--color-surface-500': '99 118 163',
'--color-surface-600': '89 106 147',
'--color-surface-700': '74 89 122',
'--color-surface-800': '59 71 98',
'--color-surface-900': '49 58 80'
},
enhancements: {
"[data-theme='hamlindigo']": {
backgroundImage:
"url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cg fill='%23e0e4ed' fill-opacity='0.5'%3E%3Cpath fill-rule='evenodd' d='M0 0h4v4H0V0zm4 4h4v4H4V4z'/%3E%3C/g%3E%3C/svg%3E\")"
},
".dark [data-theme='hamlindigo']": {
backgroundImage:
"url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cg fill='%233b4762' fill-opacity='0.2'%3E%3Cpath fill-rule='evenodd' d='M0 0h4v4H0V0zm4 4h4v4H4V4z'/%3E%3C/g%3E%3C/svg%3E\")"
}
}
} satisfies Theme;
export default hamlindigo;

View File

@@ -0,0 +1,119 @@
import crimson from './crimson.js';
import goldNouveau from './gold-nouveau.js';
import hamlindigo from './hamlindigo.js';
import modern from './modern.js';
import rocket from './rocket.js';
import sahara from './sahara.js';
import seafoam from './seafoam.js';
import skeleton from './skeleton.js';
import vintage from './vintage.js';
import type { CSSRuleObject } from 'tailwindcss/types/config.js';
export const themes = { crimson, 'gold-nouveau': goldNouveau, hamlindigo, modern, rocket, sahara, seafoam, skeleton, vintage };
export type PresetTheme = ObjectKeys<typeof themes>;
export function getThemeProperties(themeName: PresetTheme) {
return themes[themeName].properties;
}
export type ObjectValues<T> = T[keyof T];
export type ObjectKeys<T> = keyof T;
export type Theme = { properties: ThemeProperties; enhancements: CSSRuleObject };
export type ThemeProperties = {
/* =~= Theme Properties =~= */
'--theme-font-family-base': string;
'--theme-font-family-heading': string;
'--theme-font-color-base': string;
'--theme-font-color-dark': string;
'--theme-rounded-base': string;
'--theme-rounded-container': string;
'--theme-border-base': string;
/* =~= Theme On-X Colors =~= */
'--on-primary': string;
'--on-secondary': string;
'--on-tertiary': string;
'--on-success': string;
'--on-warning': string;
'--on-error': string;
'--on-surface': string;
/* =~= Theme Colors =~= */
/* primary */
'--color-primary-50': string;
'--color-primary-100': string;
'--color-primary-200': string;
'--color-primary-300': string;
'--color-primary-400': string;
'--color-primary-500': string;
'--color-primary-600': string;
'--color-primary-700': string;
'--color-primary-800': string;
'--color-primary-900': string;
/* secondary */
'--color-secondary-50': string;
'--color-secondary-100': string;
'--color-secondary-200': string;
'--color-secondary-300': string;
'--color-secondary-400': string;
'--color-secondary-500': string;
'--color-secondary-600': string;
'--color-secondary-700': string;
'--color-secondary-800': string;
'--color-secondary-900': string;
/* tertiary */
'--color-tertiary-50': string;
'--color-tertiary-100': string;
'--color-tertiary-200': string;
'--color-tertiary-300': string;
'--color-tertiary-400': string;
'--color-tertiary-500': string;
'--color-tertiary-600': string;
'--color-tertiary-700': string;
'--color-tertiary-800': string;
'--color-tertiary-900': string;
/* success */
'--color-success-50': string;
'--color-success-100': string;
'--color-success-200': string;
'--color-success-300': string;
'--color-success-400': string;
'--color-success-500': string;
'--color-success-600': string;
'--color-success-700': string;
'--color-success-800': string;
'--color-success-900': string;
/* warning */
'--color-warning-50': string;
'--color-warning-100': string;
'--color-warning-200': string;
'--color-warning-300': string;
'--color-warning-400': string;
'--color-warning-500': string;
'--color-warning-600': string;
'--color-warning-700': string;
'--color-warning-800': string;
'--color-warning-900': string;
/* error */
'--color-error-50': string;
'--color-error-100': string;
'--color-error-200': string;
'--color-error-300': string;
'--color-error-400': string;
'--color-error-500': string;
'--color-error-600': string;
'--color-error-700': string;
'--color-error-800': string;
'--color-error-900': string;
/* surface */
'--color-surface-50': string;
'--color-surface-100': string;
'--color-surface-200': string;
'--color-surface-300': string;
'--color-surface-400': string;
'--color-surface-500': string;
'--color-surface-600': string;
'--color-surface-700': string;
'--color-surface-800': string;
'--color-surface-900': string;
};

View File

@@ -0,0 +1,112 @@
import type { Theme } from './index.js';
const modern = {
properties: {
'--theme-font-family-base': "'Quicksand', sans-serif",
'--theme-font-family-heading': "'Quicksand', sans-serif",
'--theme-font-color-base': 'var(--color-surface-900)',
'--theme-font-color-dark': 'var(--color-tertiary-50)',
'--theme-rounded-base': '9999px',
'--theme-rounded-container': '24px',
'--theme-border-base': '3px',
'--on-primary': '255 255 255',
'--on-secondary': '0 0 0',
'--on-tertiary': '0 0 0',
'--on-success': '0 0 0',
'--on-warning': '0 0 0',
'--on-error': '255 255 255',
'--on-surface': '255 255 255',
'--color-primary-50': '252 228 240',
'--color-primary-100': '251 218 235',
'--color-primary-200': '250 209 230',
'--color-primary-300': '247 182 214',
'--color-primary-400': '242 127 184',
'--color-primary-500': '236 72 153',
'--color-primary-600': '212 65 138',
'--color-primary-700': '177 54 115',
'--color-primary-800': '142 43 92',
'--color-primary-900': '116 35 75',
'--color-secondary-50': '218 244 249',
'--color-secondary-100': '205 240 246',
'--color-secondary-200': '193 237 244',
'--color-secondary-300': '155 226 238',
'--color-secondary-400': '81 204 225',
'--color-secondary-500': '6 182 212',
'--color-secondary-600': '5 164 191',
'--color-secondary-700': '5 137 159',
'--color-secondary-800': '4 109 127',
'--color-secondary-900': '3 89 104',
'--color-tertiary-50': '220 244 242',
'--color-tertiary-100': '208 241 237',
'--color-tertiary-200': '196 237 233',
'--color-tertiary-300': '161 227 219',
'--color-tertiary-400': '91 205 193',
'--color-tertiary-500': '20 184 166',
'--color-tertiary-600': '18 166 149',
'--color-tertiary-700': '15 138 125',
'--color-tertiary-800': '12 110 100',
'--color-tertiary-900': '10 90 81',
'--color-success-50': '237 247 220',
'--color-success-100': '230 245 208',
'--color-success-200': '224 242 197',
'--color-success-300': '206 235 162',
'--color-success-400': '169 219 92',
'--color-success-500': '132 204 22',
'--color-success-600': '119 184 20',
'--color-success-700': '99 153 17',
'--color-success-800': '79 122 13',
'--color-success-900': '65 100 11',
'--color-warning-50': '252 244 218',
'--color-warning-100': '251 240 206',
'--color-warning-200': '250 236 193',
'--color-warning-300': '247 225 156',
'--color-warning-400': '240 202 82',
'--color-warning-500': '234 179 8',
'--color-warning-600': '211 161 7',
'--color-warning-700': '176 134 6',
'--color-warning-800': '140 107 5',
'--color-warning-900': '115 88 4',
'--color-error-50': '253 227 227',
'--color-error-100': '252 218 218',
'--color-error-200': '251 208 208',
'--color-error-300': '249 180 180',
'--color-error-400': '244 124 124',
'--color-error-500': '239 68 68',
'--color-error-600': '215 61 61',
'--color-error-700': '179 51 51',
'--color-error-800': '143 41 41',
'--color-error-900': '117 33 33',
'--color-surface-50': '232 232 253',
'--color-surface-100': '224 224 252',
'--color-surface-200': '216 217 252',
'--color-surface-300': '193 194 249',
'--color-surface-400': '146 148 245',
'--color-surface-500': '99 102 241',
'--color-surface-600': '89 92 217',
'--color-surface-700': '74 77 181',
'--color-surface-800': '59 61 145',
'--color-surface-900': '49 50 118'
},
enhancements: {
"[data-theme='modern'] h1,\n[data-theme='modern'] h2,\n[data-theme='modern'] h3,\n[data-theme='modern'] h4,\n[data-theme='modern'] h5,\n[data-theme='modern'] h6,\n[data-theme='modern'] a,\n[data-theme='modern'] button":
{ fontWeight: 'bold' },
"[data-theme='modern']": {
backgroundImage:
'radial-gradient(at 76% 0%, hsla(189,100%,56%,0.36) 0px, transparent 50%),\n\t\tradial-gradient(at 1% 0%, hsla(340,100%,76%,0.26) 0px, transparent 50%),\n\t\tradial-gradient(at 20% 100%, hsla(241,100%,70%,0.47) 0px, transparent 50%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
},
".dark [data-theme='modern']": {
backgroundImage:
'radial-gradient(at 76% 0%, hsla(189,100%,56%,0.20) 0px, transparent 50%),\n\t\tradial-gradient(at 1% 0%, hsla(340,100%,76%,0.15) 0px, transparent 50%),\n\t\tradial-gradient(at 20% 100%, hsla(241,100%,70%,0.30) 0px, transparent 50%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
}
}
} satisfies Theme;
export default modern;

View File

@@ -0,0 +1,104 @@
import type { Theme } from './index.js';
const rocket = {
properties: {
'--theme-font-family-base': 'system-ui',
'--theme-font-family-heading': "'Space Grotesk', sans-serif",
'--theme-font-color-base': 'var(--color-primary-900)',
'--theme-font-color-dark': 'var(--color-primary-100)',
'--theme-rounded-base': '0px',
'--theme-rounded-container': '0px',
'--theme-border-base': '0px',
'--on-primary': '0 0 0',
'--on-secondary': '255 255 255',
'--on-tertiary': '255 255 255',
'--on-success': '0 0 0',
'--on-warning': '0 0 0',
'--on-error': '255 255 255',
'--on-surface': '255 255 255',
'--color-primary-50': '218 244 249',
'--color-primary-100': '205 240 246',
'--color-primary-200': '193 237 244',
'--color-primary-300': '155 226 238',
'--color-primary-400': '81 204 225',
'--color-primary-500': '6 182 212',
'--color-primary-600': '5 164 191',
'--color-primary-700': '5 137 159',
'--color-primary-800': '4 109 127',
'--color-primary-900': '3 89 104',
'--color-secondary-50': '226 236 254',
'--color-secondary-100': '216 230 253',
'--color-secondary-200': '206 224 253',
'--color-secondary-300': '177 205 251',
'--color-secondary-400': '118 168 249',
'--color-secondary-500': '59 130 246',
'--color-secondary-600': '53 117 221',
'--color-secondary-700': '44 98 185',
'--color-secondary-800': '35 78 148',
'--color-secondary-900': '29 64 121',
'--color-tertiary-50': '242 230 254',
'--color-tertiary-100': '238 221 253',
'--color-tertiary-200': '233 213 253',
'--color-tertiary-300': '220 187 252',
'--color-tertiary-400': '194 136 249',
'--color-tertiary-500': '168 85 247',
'--color-tertiary-600': '151 77 222',
'--color-tertiary-700': '126 64 185',
'--color-tertiary-800': '101 51 148',
'--color-tertiary-900': '82 42 121',
'--color-success-50': '228 247 220',
'--color-success-100': '219 245 208',
'--color-success-200': '210 242 197',
'--color-success-300': '183 234 161',
'--color-success-400': '130 219 91',
'--color-success-500': '76 203 21',
'--color-success-600': '68 183 19',
'--color-success-700': '57 152 16',
'--color-success-800': '46 122 13',
'--color-success-900': '37 99 10',
'--color-warning-50': '253 246 223',
'--color-warning-100': '253 243 212',
'--color-warning-200': '252 240 202',
'--color-warning-300': '251 230 170',
'--color-warning-400': '247 212 106',
'--color-warning-500': '244 193 42',
'--color-warning-600': '220 174 38',
'--color-warning-700': '183 145 32',
'--color-warning-800': '146 116 25',
'--color-warning-900': '120 95 21',
'--color-error-50': '244 223 230',
'--color-error-100': '240 213 221',
'--color-error-200': '237 202 213',
'--color-error-300': '225 171 187',
'--color-error-400': '203 107 136',
'--color-error-500': '181 44 85',
'--color-error-600': '163 40 77',
'--color-error-700': '136 33 64',
'--color-error-800': '109 26 51',
'--color-error-900': '89 22 42',
'--color-surface-50': '232 234 238',
'--color-surface-100': '224 227 232',
'--color-surface-200': '216 220 226',
'--color-surface-300': '193 199 209',
'--color-surface-400': '147 158 174',
'--color-surface-500': '100 116 139',
'--color-surface-600': '90 104 125',
'--color-surface-700': '75 87 104',
'--color-surface-800': '60 70 83',
'--color-surface-900': '49 57 68'
},
enhancements: {
"[data-theme='rocket'] h1,\n[data-theme='rocket'] h2,\n[data-theme='rocket'] h3,\n[data-theme='rocket'] h4,\n[data-theme='rocket'] h5,\n[data-theme='rocket'] h6":
{ fontWeight: 'bold' },
"[data-theme='rocket']": {
backgroundImage:
'radial-gradient(at 0% 0%, rgba(var(--color-secondary-500) / 0.33) 0px, transparent 50%),\n\t\t\tradial-gradient(at 98% 1%, rgba(var(--color-error-500) / 0.33) 0px, transparent 50%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
}
}
} satisfies Theme;
export default rocket;

View File

@@ -0,0 +1,115 @@
import type { Theme } from './index.js';
const sahara = {
properties: {
'--theme-font-family-base':
"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,\n\t\t'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'",
'--theme-font-family-heading':
"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',\n\t\tArial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'",
'--theme-font-color-base': 'var(--color-secondary-900)',
'--theme-font-color-dark': 'var(--color-primary-100)',
'--theme-rounded-base': '9999px',
'--theme-rounded-container': '24px',
'--theme-border-base': '1px',
'--on-primary': '0 0 0',
'--on-secondary': '0 0 0',
'--on-tertiary': '0 0 0',
'--on-success': '0 0 0',
'--on-warning': '0 0 0',
'--on-error': '255 255 255',
'--on-surface': '255 255 255',
'--color-primary-50': '252 242 225',
'--color-primary-100': '251 238 215',
'--color-primary-200': '250 234 205',
'--color-primary-300': '247 221 175',
'--color-primary-400': '242 196 114',
'--color-primary-500': '236 170 54',
'--color-primary-600': '212 153 49',
'--color-primary-700': '177 128 41',
'--color-primary-800': '142 102 32',
'--color-primary-900': '116 83 26',
'--color-secondary-50': '225 247 245',
'--color-secondary-100': '216 245 241',
'--color-secondary-200': '206 242 238',
'--color-secondary-300': '176 234 227',
'--color-secondary-400': '117 219 207',
'--color-secondary-500': '58 203 186',
'--color-secondary-600': '52 183 167',
'--color-secondary-700': '44 152 140',
'--color-secondary-800': '35 122 112',
'--color-secondary-900': '28 99 91',
'--color-tertiary-50': '245 250 237',
'--color-tertiary-100': '241 249 231',
'--color-tertiary-200': '238 247 225',
'--color-tertiary-300': '228 242 207',
'--color-tertiary-400': '207 233 170',
'--color-tertiary-500': '187 223 134',
'--color-tertiary-600': '168 201 121',
'--color-tertiary-700': '140 167 101',
'--color-tertiary-800': '112 134 80',
'--color-tertiary-900': '92 109 66',
'--color-success-50': '237 247 220',
'--color-success-100': '230 245 208',
'--color-success-200': '224 242 197',
'--color-success-300': '206 235 162',
'--color-success-400': '169 219 92',
'--color-success-500': '132 204 22',
'--color-success-600': '119 184 20',
'--color-success-700': '99 153 17',
'--color-success-800': '79 122 13',
'--color-success-900': '65 100 11',
'--color-warning-50': '251 246 230',
'--color-warning-100': '250 243 221',
'--color-warning-200': '249 240 213',
'--color-warning-300': '245 230 188',
'--color-warning-400': '237 212 137',
'--color-warning-500': '229 193 87',
'--color-warning-600': '206 174 78',
'--color-warning-700': '172 145 65',
'--color-warning-800': '137 116 52',
'--color-warning-900': '112 95 43',
'--color-error-50': '250 231 240',
'--color-error-100': '248 222 235',
'--color-error-200': '246 214 230',
'--color-error-300': '241 190 215',
'--color-error-400': '230 141 186',
'--color-error-500': '219 92 156',
'--color-error-600': '197 83 140',
'--color-error-700': '164 69 117',
'--color-error-800': '131 55 94',
'--color-error-900': '107 45 76',
'--color-surface-50': '249 228 232',
'--color-surface-100': '248 220 224',
'--color-surface-200': '246 211 217',
'--color-surface-300': '240 184 193',
'--color-surface-400': '229 131 147',
'--color-surface-500': '218 78 101',
'--color-surface-600': '196 70 91',
'--color-surface-700': '164 59 76',
'--color-surface-800': '131 47 61',
'--color-surface-900': '107 38 49'
},
enhancements: {
"[data-theme='sahara'] h1,\n[data-theme='sahara'] h2,\n[data-theme='sahara'] h3,\n[data-theme='sahara'] h4,\n[data-theme='sahara'] h5,\n[data-theme='sahara'] h6":
{ fontWeight: '600' },
"[data-theme='sahara'] p": { fontWeight: '400' },
"[data-theme='sahara']": {
backgroundImage:
'radial-gradient(at 100% 36%, hsla(37,81%,56%,0.15) 0px, transparent 50%),\n\t\tradial-gradient(at 7% 0%, hsla(37,81%,56%,0.20) 0px, transparent 50%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
},
".dark [data-theme='sahara']": {
backgroundImage:
'radial-gradient(at 100% 36%, hsla(37,81%,56%,0.15) 0px, transparent 50%),\n\t\tradial-gradient(at 7% 0%, hsla(37,81%,56%,0.20) 0px, transparent 50%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
}
}
} satisfies Theme;
export default sahara;

View File

@@ -0,0 +1,111 @@
import type { Theme } from './index.js';
const seafoam = {
properties: {
'--theme-font-family-base':
"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,\n\t\t'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'",
'--theme-font-family-heading': "'Playfair Display', serif",
'--theme-font-color-base': 'var(--color-surface-900)',
'--theme-font-color-dark': 'var(--color-secondary-100)',
'--theme-rounded-base': '16px',
'--theme-rounded-container': '16px',
'--theme-border-base': '3px',
'--on-primary': '0 0 0',
'--on-secondary': '255 255 255',
'--on-tertiary': '255 255 255',
'--on-success': '0 0 0',
'--on-warning': '0 0 0',
'--on-error': '255 255 255',
'--on-surface': '0 0 0',
'--color-primary-50': '237 248 247',
'--color-primary-100': '231 246 245',
'--color-primary-200': '225 243 242',
'--color-primary-300': '207 236 234',
'--color-primary-400': '170 222 219',
'--color-primary-500': '134 208 203',
'--color-primary-600': '121 187 183',
'--color-primary-700': '101 156 152',
'--color-primary-800': '80 125 122',
'--color-primary-900': '66 102 99',
'--color-secondary-50': '222 224 230',
'--color-secondary-100': '211 214 221',
'--color-secondary-200': '200 204 213',
'--color-secondary-300': '166 173 187',
'--color-secondary-400': '100 112 136',
'--color-secondary-500': '33 51 85',
'--color-secondary-600': '30 46 77',
'--color-secondary-700': '25 38 64',
'--color-secondary-800': '20 31 51',
'--color-secondary-900': '16 25 42',
'--color-tertiary-50': '255 226 217',
'--color-tertiary-100': '255 216 204',
'--color-tertiary-200': '255 207 191',
'--color-tertiary-300': '255 177 153',
'--color-tertiary-400': '255 119 77',
'--color-tertiary-500': '255 61 0',
'--color-tertiary-600': '230 55 0',
'--color-tertiary-700': '191 46 0',
'--color-tertiary-800': '153 37 0',
'--color-tertiary-900': '125 30 0',
'--color-success-50': '218 251 241',
'--color-success-100': '205 250 236',
'--color-success-200': '193 249 232',
'--color-success-300': '155 245 218',
'--color-success-400': '81 237 190',
'--color-success-500': '6 229 162',
'--color-success-600': '5 206 146',
'--color-success-700': '5 172 122',
'--color-success-800': '4 137 97',
'--color-success-900': '3 112 79',
'--color-warning-50': '252 251 230',
'--color-warning-100': '251 250 221',
'--color-warning-200': '250 249 213',
'--color-warning-300': '247 245 188',
'--color-warning-400': '240 237 137',
'--color-warning-500': '234 229 87',
'--color-warning-600': '211 206 78',
'--color-warning-700': '176 172 65',
'--color-warning-800': '140 137 52',
'--color-warning-900': '115 112 43',
'--color-error-50': '248 227 227',
'--color-error-100': '246 218 218',
'--color-error-200': '244 209 209',
'--color-error-300': '237 181 181',
'--color-error-400': '224 126 126',
'--color-error-500': '210 70 70',
'--color-error-600': '189 63 63',
'--color-error-700': '158 53 53',
'--color-error-800': '126 42 42',
'--color-error-900': '103 34 34',
'--color-surface-50': '222 248 249',
'--color-surface-100': '211 246 246',
'--color-surface-200': '201 244 244',
'--color-surface-300': '168 237 238',
'--color-surface-400': '102 223 225',
'--color-surface-500': '37 209 212',
'--color-surface-600': '33 188 191',
'--color-surface-700': '28 157 159',
'--color-surface-800': '22 125 127',
'--color-surface-900': '18 102 104'
},
enhancements: {
"[data-theme='seafoam'] h1,\n[data-theme='seafoam'] h2,\n[data-theme='seafoam'] h3,\n[data-theme='seafoam'] h4,\n[data-theme='seafoam'] h5,\n[data-theme='seafoam'] h6":
{ fontWeight: 'bold', fontStyle: 'italic', letterSpacing: '1px' },
"[data-theme='seafoam']": {
background: 'linear-gradient(0deg, rgba(203, 221, 254, 0.75) 0%, rgba(163, 209, 206, 0.75) 100%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
},
".dark [data-theme='seafoam']": {
background: 'linear-gradient(0deg, rgba(33, 50, 83, 1) 0%, rgba(8, 132, 124, 1) 100%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
}
}
} satisfies Theme;
export default seafoam;

View File

@@ -0,0 +1,104 @@
import type { Theme } from './index.js';
const skeleton = {
properties: {
'--theme-font-family-base': 'system-ui',
'--theme-font-family-heading': 'system-ui',
'--theme-font-color-base': '0 0 0',
'--theme-font-color-dark': '255 255 255',
'--theme-rounded-base': '9999px',
'--theme-rounded-container': '8px',
'--theme-border-base': '1px',
'--on-primary': '0 0 0',
'--on-secondary': '255 255 255',
'--on-tertiary': '0 0 0',
'--on-success': '0 0 0',
'--on-warning': '0 0 0',
'--on-error': '255 255 255',
'--on-surface': '255 255 255',
'--color-primary-50': '219 245 236',
'--color-primary-100': '207 241 230',
'--color-primary-200': '195 238 224',
'--color-primary-300': '159 227 205',
'--color-primary-400': '87 207 167',
'--color-primary-500': '15 186 129',
'--color-primary-600': '14 167 116',
'--color-primary-700': '11 140 97',
'--color-primary-800': '9 112 77',
'--color-primary-900': '7 91 63',
'--color-secondary-50': '229 227 251',
'--color-secondary-100': '220 218 250',
'--color-secondary-200': '211 209 249',
'--color-secondary-300': '185 181 245',
'--color-secondary-400': '132 126 237',
'--color-secondary-500': '79 70 229',
'--color-secondary-600': '71 63 206',
'--color-secondary-700': '59 53 172',
'--color-secondary-800': '47 42 137',
'--color-secondary-900': '39 34 112',
'--color-tertiary-50': '219 242 252',
'--color-tertiary-100': '207 237 251',
'--color-tertiary-200': '195 233 250',
'--color-tertiary-300': '159 219 246',
'--color-tertiary-400': '86 192 240',
'--color-tertiary-500': '14 165 233',
'--color-tertiary-600': '13 149 210',
'--color-tertiary-700': '11 124 175',
'--color-tertiary-800': '8 99 140',
'--color-tertiary-900': '7 81 114',
'--color-success-50': '237 247 220',
'--color-success-100': '230 245 208',
'--color-success-200': '224 242 197',
'--color-success-300': '206 235 162',
'--color-success-400': '169 219 92',
'--color-success-500': '132 204 22',
'--color-success-600': '119 184 20',
'--color-success-700': '99 153 17',
'--color-success-800': '79 122 13',
'--color-success-900': '65 100 11',
'--color-warning-50': '252 244 218',
'--color-warning-100': '251 240 206',
'--color-warning-200': '250 236 193',
'--color-warning-300': '247 225 156',
'--color-warning-400': '240 202 82',
'--color-warning-500': '234 179 8',
'--color-warning-600': '211 161 7',
'--color-warning-700': '176 134 6',
'--color-warning-800': '140 107 5',
'--color-warning-900': '115 88 4',
'--color-error-50': '249 221 234',
'--color-error-100': '246 209 228',
'--color-error-200': '244 198 221',
'--color-error-300': '238 163 200',
'--color-error-400': '225 94 159',
'--color-error-500': '212 25 118',
'--color-error-600': '191 23 106',
'--color-error-700': '159 19 89',
'--color-error-800': '127 15 71',
'--color-error-900': '104 12 58',
'--color-surface-50': '228 230 238',
'--color-surface-100': '219 222 233',
'--color-surface-200': '210 214 227',
'--color-surface-300': '182 189 210',
'--color-surface-400': '128 140 177',
'--color-surface-500': '73 90 143',
'--color-surface-600': '66 81 129',
'--color-surface-700': '55 68 107',
'--color-surface-800': '44 54 86',
'--color-surface-900': '36 44 70'
},
enhancements: {
"[data-theme='skeleton'] h1,\n[data-theme='skeleton'] h2,\n[data-theme='skeleton'] h3,\n[data-theme='skeleton'] h4,\n[data-theme='skeleton'] h5,\n[data-theme='skeleton'] h6":
{ fontWeight: 'bold' },
"[data-theme='skeleton']": {
backgroundImage:
'radial-gradient(at 0% 0%, rgba(var(--color-secondary-500) / 0.33) 0px, transparent 50%),\n\t\t\tradial-gradient(at 98% 1%, rgba(var(--color-error-500) / 0.33) 0px, transparent 50%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
}
}
} satisfies Theme;
export default skeleton;

View File

@@ -0,0 +1,113 @@
import type { Theme } from './index.js';
const vintage = {
properties: {
'--theme-font-family-base':
"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,\n\t\t'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'",
'--theme-font-family-heading': "'Abril Fatface', cursive",
'--theme-font-color-base': 'var(--color-primary-900)',
'--theme-font-color-dark': 'var(--color-primary-100)',
'--theme-rounded-base': '2px',
'--theme-rounded-container': '4px',
'--theme-border-base': '1px',
'--on-primary': '0 0 0',
'--on-secondary': '0 0 0',
'--on-tertiary': '0 0 0',
'--on-success': '0 0 0',
'--on-warning': '0 0 0',
'--on-error': '0 0 0',
'--on-surface': '255 255 255',
'--color-primary-50': '252 237 221',
'--color-primary-100': '251 231 209',
'--color-primary-200': '250 225 198',
'--color-primary-300': '247 207 163',
'--color-primary-400': '240 170 95',
'--color-primary-500': '234 134 26',
'--color-primary-600': '211 121 23',
'--color-primary-700': '176 101 20',
'--color-primary-800': '140 80 16',
'--color-primary-900': '115 66 13',
'--color-secondary-50': '239 248 242',
'--color-secondary-100': '234 245 237',
'--color-secondary-200': '229 243 233',
'--color-secondary-300': '213 235 219',
'--color-secondary-400': '182 221 192',
'--color-secondary-500': '151 206 165',
'--color-secondary-600': '136 185 149',
'--color-secondary-700': '113 155 124',
'--color-secondary-800': '91 124 99',
'--color-secondary-900': '74 101 81',
'--color-tertiary-50': '218 244 249',
'--color-tertiary-100': '205 240 246',
'--color-tertiary-200': '193 237 244',
'--color-tertiary-300': '155 226 238',
'--color-tertiary-400': '81 204 225',
'--color-tertiary-500': '6 182 212',
'--color-tertiary-600': '5 164 191',
'--color-tertiary-700': '5 137 159',
'--color-tertiary-800': '4 109 127',
'--color-tertiary-900': '3 89 104',
'--color-success-50': '237 247 231',
'--color-success-100': '230 245 223',
'--color-success-200': '224 242 215',
'--color-success-300': '206 234 190',
'--color-success-400': '169 219 142',
'--color-success-500': '132 203 93',
'--color-success-600': '119 183 84',
'--color-success-700': '99 152 70',
'--color-success-800': '79 122 56',
'--color-success-900': '65 99 46',
'--color-warning-50': '253 243 222',
'--color-warning-100': '252 238 211',
'--color-warning-200': '252 234 200',
'--color-warning-300': '250 222 167',
'--color-warning-400': '246 197 101',
'--color-warning-500': '242 172 35',
'--color-warning-600': '218 155 32',
'--color-warning-700': '182 129 26',
'--color-warning-800': '145 103 21',
'--color-warning-900': '119 84 17',
'--color-error-50': '249 236 235',
'--color-error-100': '247 229 228',
'--color-error-200': '245 223 221',
'--color-error-300': '238 203 201',
'--color-error-400': '226 165 161',
'--color-error-500': '213 126 120',
'--color-error-600': '192 113 108',
'--color-error-700': '160 95 90',
'--color-error-800': '128 76 72',
'--color-error-900': '104 62 59',
'--color-surface-50': '226 225 224',
'--color-surface-100': '217 215 214',
'--color-surface-200': '207 205 204',
'--color-surface-300': '178 175 173',
'--color-surface-400': '121 115 111',
'--color-surface-500': '63 55 49',
'--color-surface-600': '57 50 44',
'--color-surface-700': '47 41 37',
'--color-surface-800': '38 33 29',
'--color-surface-900': '31 27 24'
},
enhancements: {
"[data-theme='vintage'] h1,\n[data-theme='vintage'] h2,\n[data-theme='vintage'] h3,\n[data-theme='vintage'] h4,\n[data-theme='vintage'] h5,\n[data-theme='vintage'] h6":
{ letterSpacing: '1px' },
"[data-theme='vintage']": {
backgroundImage:
'radial-gradient(at 100% 0%, hsla(135,34%,70%,0.20) 0px, transparent 50%),\n\t\tradial-gradient(at 85% 100%, hsla(31,83%,50%,0.20) 0px, transparent 50%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
},
".dark [data-theme='vintage']": {
backgroundImage:
'radial-gradient(at 100% 0%, hsla(135,34%,70%,0.14) 0px, transparent 50%),\n\t\tradial-gradient(at 85% 100%, hsla(31,83%,50%,0.14) 0px, transparent 50%)',
backgroundAttachment: 'fixed',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
}
}
} satisfies Theme;
export default vintage;

View File

@@ -1,14 +1,14 @@
// Design Tokens: Background // Design Tokens: Background
// Doc: https://www.skeleton.dev/docs/tokens // Doc: https://www.skeleton.dev/docs/tokens
const settings = require('../settings.cjs'); import { settings, type CssClasses } from '../settings.js';
// Defaults // Defaults
const backdropAlpha = 0.7; const backdropAlpha = 0.7;
const hoverAlpha = 0.1; const hoverAlpha = 0.1;
module.exports = () => { export const backgrounds = (): CssClasses => {
const classes = {}; const classes: CssClasses = {};
settings.colorNames.forEach((n) => { settings.colorNames.forEach((n) => {
// Backdrops // Backdrops
// Example: .bg-primary-backdrop-token // Example: .bg-primary-backdrop-token
@@ -37,3 +37,5 @@ module.exports = () => {
}); });
return classes; return classes;
}; };
export default backgrounds;

View File

@@ -1,9 +1,10 @@
// Design Tokens: Border Radius // Design Tokens: Border Radius
// Doc: https://www.skeleton.dev/docs/tokens // Doc: https://www.skeleton.dev/docs/tokens
// const settings = require('../settings.cjs'); import { CssClasses } from '../settings.js';
module.exports = () => { // const settings = require('../settings.cjs');
export const borderRadius = (): CssClasses => {
return { return {
// Base // Base
'.rounded-token': { 'border-radius': 'var(--theme-rounded-base)' }, '.rounded-token': { 'border-radius': 'var(--theme-rounded-base)' },
@@ -19,3 +20,5 @@ module.exports = () => {
'.rounded-br-container-token': { 'border-bottom-right-radius': 'var(--theme-rounded-container)' } '.rounded-br-container-token': { 'border-bottom-right-radius': 'var(--theme-rounded-container)' }
}; };
}; };
export default borderRadius;

View File

@@ -1,10 +1,10 @@
// Design Tokens: Borders // Design Tokens: Borders
// Doc: https://www.skeleton.dev/docs/tokens // Doc: https://www.skeleton.dev/docs/tokens
const settings = require('../settings.cjs'); import { settings, type CssClasses } from '../settings.js';
module.exports = () => { export const borders = (): CssClasses => {
const classes = { const classes: CssClasses = {
// Border Width - ex: .border-token // Border Width - ex: .border-token
'.border-token': { 'border-width': 'var(--theme-border-base)' } '.border-token': { 'border-width': 'var(--theme-border-base)' }
}; };
@@ -18,3 +18,5 @@ module.exports = () => {
}); });
return classes; return classes;
}; };
export default borders;

View File

@@ -1,10 +1,10 @@
// Design Tokens: SVG Fill // Design Tokens: SVG Fill
// Doc: https://www.skeleton.dev/docs/tokens // Doc: https://www.skeleton.dev/docs/tokens
const settings = require('../settings.cjs'); import { settings, type CssClasses } from '../settings.js';
module.exports = () => { export const fills = (): CssClasses => {
const classes = { const classes: CssClasses = {
'.fill-base-token': { fill: 'rgba(var(--theme-font-color-base))' }, '.fill-base-token': { fill: 'rgba(var(--theme-font-color-base))' },
'.fill-dark-token': { fill: 'rgba(var(--theme-font-color-dark))' }, '.fill-dark-token': { fill: 'rgba(var(--theme-font-color-dark))' },
// Fill Token - ex: .fill-token // Fill Token - ex: .fill-token
@@ -18,3 +18,5 @@ module.exports = () => {
}); });
return classes; return classes;
}; };
export default fills;

View File

@@ -1,7 +1,7 @@
// Design Tokens: Rings // Design Tokens: Rings
// Doc: https://www.skeleton.dev/docs/tokens // Doc: https://www.skeleton.dev/docs/tokens
const settings = require('../settings.cjs'); import { settings, type CssClasses } from '../settings.js';
// Local // Local
const ringTokenTheme = { const ringTokenTheme = {
@@ -18,8 +18,8 @@ const ringOutlineShared = {
'--tw-ring-inset': 'inset' '--tw-ring-inset': 'inset'
}; };
module.exports = () => { export const rings = (): CssClasses => {
const classes = { const classes: CssClasses = {
'.ring-token': { '.ring-token': {
...ringTokenTheme ...ringTokenTheme
}, },
@@ -48,3 +48,5 @@ module.exports = () => {
}); });
return classes; return classes;
}; };
export default rings;

View File

@@ -1,10 +1,10 @@
// Design Tokens: Text // Design Tokens: Text
// Doc: https://www.skeleton.dev/docs/tokens // Doc: https://www.skeleton.dev/docs/tokens
const settings = require('../settings.cjs'); import { settings, type CssClasses } from '../settings.js';
module.exports = () => { export const text = (): CssClasses => {
const classes = { const classes: CssClasses = {
// Font Family // Font Family
'.font-heading-token': { 'font-family': 'var(--theme-font-family-heading)' }, '.font-heading-token': { 'font-family': 'var(--theme-font-family-heading)' },
'.font-token': { 'font-family': 'var(--theme-font-family-base)' }, '.font-token': { 'font-family': 'var(--theme-font-family-base)' },
@@ -15,6 +15,7 @@ module.exports = () => {
'.text-token': { color: 'rgba(var(--theme-font-color-base))' }, '.text-token': { color: 'rgba(var(--theme-font-color-base))' },
'.dark .text-token': { color: 'rgba(var(--theme-font-color-dark))' } '.dark .text-token': { color: 'rgba(var(--theme-font-color-dark))' }
}; };
settings.colorNames.forEach((n) => { settings.colorNames.forEach((n) => {
// On-X Text Colors // On-X Text Colors
// Example: .text-on-primary-token // Example: .text-on-primary-token
@@ -29,3 +30,5 @@ module.exports = () => {
}); });
return classes; return classes;
}; };
export default text;

View File

@@ -0,0 +1,145 @@
import type { CSSRuleObject } from 'tailwindcss/types/config';
import type { PresetTheme, ThemeProperties } from './tailwind/themes';
export type ConfigOptions = {
/**
* Prefixes Skeleton component classes with a specified string.
*
* This should be used when there are Skeleton class names
* that conflict with other plugins. For example, our `btn` class
* can often conflict with other UI libraries.
*
* **NOTE:** Only use this if you're using this plugin WITHOUT
* our accompanying component library, `@skeletonlabs/skeleton`.
*
* @example
* // Skeleton classes will be prefixed with 'sk-' (e.g., sk-btn)
* prefix = 'sk-'
*
* @default ''
*/
prefix?: string;
/**
* Whether to include Skeleton's base styles.
* @default true
*/
base?: boolean;
/**
* Theme config for configuring your themes.
*/
themes?: ThemeConfig;
};
export type ThemeConfig = {
/**
* Custom themes can be enabled by passing them to this option.
*
* @example
* custom = [
* {
* name: "my-custom-theme",
* properties: {
* '--theme-font-family-base': 'system-ui',
* '--theme-font-family-heading': "'Space Grotesk', sans-serif",
* '--theme-font-color-base': 'var(--color-primary-900)',
* '--theme-font-color-dark': 'var(--color-primary-100)',
* // ...
* },
* enhancements: { // optional
* "[data-theme='my-custom-theme'] h1": {
* fontWeight: "400"
* }
* }
* }
* ]
*
*
*/
custom?: Array<CustomThemeConfig>;
/**
* Preset themes can be enabled by passing them to this option.
*
* @example
* // Preset themes can be enabled by simply passing their names
* preset = [ "skeleton", "modern", "rocket" ]
*
* @example
* // Or by passing an object, enabling the ability
* // to enable a preset's `enhancements`
* preset = [
* { name: "skeleton", enhancements: true },
* { name: "modern", enhancements: true },
* ]
*
*/
preset?: Array<PresetThemeConfig | PresetTheme>;
};
export type CustomThemeConfig = {
/**
* The name of your custom theme.
*
* This is the required value to activate your
* theme with the `data-theme` attribute in your `body` element.
*
* @example
* // If name = "my-custom-theme"
* <body data-theme="my-custom-theme">
*/
name: string;
/**
* Define your own custom theme properties here.
*
* To generate a custom theme, visit our Theme Generator.
* @see https://skeleton.dev/docs/generator
*
* @example
* properties = {
* '--theme-font-family-base': 'system-ui',
* '--theme-font-family-heading': "'Space Grotesk', sans-serif",
* '--theme-font-color-base': 'var(--color-primary-900)',
* '--theme-font-color-dark': 'var(--color-primary-100)',
* // ...
* }
*
* @example
* // If you wish to extend one of our preset themes, you can do so
* // with our provided `getThemeProperties()` function.
* import { getThemeProperties } from "@skeletonlabs/tw-plugin";
*
* properties = {
* ...getThemeProperties("skeleton"),
* '--color-primary-50': '240 228 254',
* '--color-primary-100': '235 219 253',
* '--color-primary-200': '231 210 253',
* '--color-primary-300': '216 183 251',
* '--color-primary-400': '186 130 248',
* '--color-primary-500': '157 76 245',
* '--color-primary-600': '141 68 221',
* '--color-primary-700': '118 57 184',
* '--color-primary-800': '94 46 147',
* '--color-primary-900': '77 37 120'
* }
*/
properties: ThemeProperties;
};
export type PresetThemeConfig = {
/**
* Name of one of our provided theme presets.
*/
name: PresetTheme;
/**
* Whether to include the preset theme enhancements. Disabled by default.
*
* This implements additional settings such as background gradients,
* header font weights, and more.
*
* @example
* // These are disabled by default, so you must enable them to opt-in
* skeleton({ themes: [{ name: "skeleton", enhancements: true }] })
*
* @default false
*/
enhancements?: boolean;
};

View File

@@ -0,0 +1,10 @@
import { Config } from 'tailwindcss';
import { corePlugin } from './src/tailwind/core.js';
const config = {
darkMode: 'class',
content: [],
plugins: [corePlugin]
} satisfies Config;
export default config;

View File

@@ -0,0 +1,18 @@
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "nodenext",
"lib": ["ES2020"],
"target": "ES2020",
"module": "CommonJS",
"typeRoots": ["./node_modules/@types", "./scripts/@types"]
},
"include": ["src", "scripts"]
}

View File

@@ -0,0 +1,12 @@
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
outDir: 'dist',
sourcemap: true,
format: ['cjs'],
dts: true,
clean: true,
tsconfig: 'tsconfig.json',
ignoreWatch: ['src/tailwind/generated']
});

View File

@@ -6,7 +6,7 @@
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
"build": "vite build", "build": "vite build",
"package": "node ./scripts/pre-build.js && pnpm build:jss && svelte-kit sync && svelte-package && node ./scripts/post-build.js", "package": "node ./scripts/pre-build.js && svelte-kit sync && svelte-package && node ./scripts/post-build.js",
"preview": "vite preview", "preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
@@ -14,8 +14,7 @@
"format": "prettier --ignore-path .prettierignore --write --plugin-search-dir=. .", "format": "prettier --ignore-path .prettierignore --write --plugin-search-dir=. .",
"test": "vitest", "test": "vitest",
"coverage": "vitest run --coverage", "coverage": "vitest run --coverage",
"sync": "svelte-kit sync && pnpm build:jss", "sync": "svelte-kit sync"
"build:jss": "node ./scripts/generate-jss.js --package"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -82,21 +81,12 @@
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"svelte": "./dist/index.js", "svelte": "./dist/index.js",
"default": "./dist/index.js" "default": "./dist/index.js"
},
"./styles/*": "./dist/styles/*",
"./themes/*": "./dist/themes/*",
"./tailwind/skeleton.cjs": {
"types": "./dist/tailwind/skeleton.cts",
"default": "./dist/tailwind/skeleton.cjs"
} }
}, },
"typesVersions": { "typesVersions": {
">4.0": { ">4.0": {
"index.d.ts": [ "index.d.ts": [
"./dist/index.d.ts" "./dist/index.d.ts"
],
"tailwind/skeleton.cjs": [
"./dist/tailwind/skeleton.d.cts"
] ]
} }
} }
@@ -116,9 +106,6 @@
"./dist/**/*.d.ts", "./dist/**/*.d.ts",
"./dist/**/*.cjs", "./dist/**/*.cjs",
"./dist/**/*.d.cts", "./dist/**/*.d.cts",
"./dist/styles/*",
"./dist/tailwind/*",
"./dist/themes/*",
"!./dist/**/*.test.*" "!./dist/**/*.test.*"
] ]
} }

View File

@@ -1,64 +0,0 @@
#!/usr/bin/env node
import { generateBaseTWStyles, transpileCssToJs } from './compile-css-to-js.cjs';
import { mkdir, writeFile, unlink } from 'fs/promises';
const INTELLISENSE_FILE_NAME = 'intellisense-classes.cjs';
exec();
async function exec() {
// Deletes the previously generated CSS-in-JS file. If we don't, our plugin will
// add duplicate classes to our newly generated CSS-in-JS file.
await unlink(`./src/lib/tailwind/generated/${INTELLISENSE_FILE_NAME}`).catch(() => {
// file doesn't exist, don't worry about it
});
// Makes directory that stores our generated CSS-in-JS
await mkdir('./src/lib/tailwind/generated').catch(() => {
// directory already exists
});
const baseTWStyles = await generateBaseTWStyles();
const generatedComponentJSS = await transpileCssToJs('./src/lib/styles/skeleton.css');
const cleanedComponentClasses = removeDuplicateClasses(generatedComponentJSS, baseTWStyles);
const componentClasses = patchMediaQueries(cleanedComponentClasses);
// Creates the generated CSS-in-JS file
await writeFile(`./src/lib/tailwind/generated/${INTELLISENSE_FILE_NAME}`, `module.exports = ${JSON.stringify(componentClasses)}`).catch(
(e) => console.error(e)
);
}
// Purges the generated CSS-in-JS file of duplicate TW classes
function removeDuplicateClasses(cssInJs, baseTWStyles) {
for (const key of Object.keys(cssInJs)) {
// We'll delete all the TW Base styles (i.e. html {...} body {...} etc.)
if (baseTWStyles[key] !== undefined) delete cssInJs[key];
if (key.includes(':is')) continue;
if (key.startsWith('@media')) continue;
// deletes the dark variant of type selectors (ex: .dark body {...})
if (key.startsWith('.dark') && key[6] !== '.') delete cssInJs[key];
// if it's not a class selector, delete it (only want classes in the intellisense)
if (key[0] !== '.') delete cssInJs[key];
}
return cssInJs;
}
// Moves all of the media queries towards the end of the cssInJs object.
function patchMediaQueries(cssInJs) {
const mediaQueries = {};
for (const key of Object.keys(cssInJs)) {
if (key.startsWith('@media')) {
mediaQueries[key] = cssInJs[key];
delete cssInJs[key];
}
}
for (const key of Object.keys(mediaQueries)) {
cssInJs[key] = mediaQueries[key];
}
return cssInJs;
}

View File

@@ -1,10 +1 @@
#!/usr/bin/env node #!/usr/bin/env node
import { rmSync } from 'fs';
try {
// We'll delete the .temp directory to force the regeneration of all of the TW Classes
rmSync('.temp', { recursive: true });
} catch {
// Directory doesn't exist, don't worry about it
}

View File

@@ -1,30 +0,0 @@
/* Stylesheet: skeleton.css */
/*
- Will be replaced by `skeleton.css` in the next major release.
- All available stylesheets are imported
- Typography using on-by-default system
*/
/* NOTE: The order shown below is required */
/* Import AFTER your theme, but BEFORE your global stylesheet. */
/* Tailwind Directives */
@import 'partials/tailwind.css';
/* === OPTIONAL STYLESHEETS === */
/* Core Styles */
@import 'partials/core.css';
/* Typography Settings */
@import 'partials/typography.css';
/* DEPRECATED: 'partials/typography-prose.css' must now be imported directly */
/* === REQUIRED STYLESHEETS === */
/* Imports all Tailwind Elements */
@import 'partials/elements.css';
/* Imports all Variant Styles */
@import 'partials/variants.css';

View File

@@ -1,15 +0,0 @@
/* Tailwind Elements: modals.css */
/* === Modal (helpers) === */
.w-modal-slim {
@apply w-full max-w-[400px];
}
.w-modal {
@apply w-full max-w-[640px];
}
.w-modal-wide {
@apply w-full max-w-[80%];
}

View File

@@ -1,16 +0,0 @@
/* Tailwind Elements: popups.css */
/* === Popup === */
[data-popup] {
/* https://floating-ui.com/docs/computeposition#usage */
@apply absolute top-0 left-0;
/* Set hidden on page load */
@apply hidden;
/* Transitions */
@apply transition-opacity duration-150;
}
[data-popup] .arrow {
@apply absolute rotate-45 w-2 h-2;
}

View File

@@ -1,20 +0,0 @@
/* Stylesheet: elements.css */
/* Import AFTER your theme, but BEFORE your global stylesheet. */
/* Recommended as the LAST stylesheet in the set */
@import '../elements/alerts.css';
@import '../elements/badges.css';
@import '../elements/breadcrumbs.css';
@import '../elements/buttons.css';
@import '../elements/cards.css';
@import '../elements/codeblocks.css';
@import '../elements/chips.css';
@import '../elements/forms.css';
@import '../elements/lists.css';
@import '../elements/logo-clouds.css';
@import '../elements/placeholders.css';
@import '../elements/tables.css';
/* Utilities */
@import '../elements/modals.css';
@import '../elements/popups.css';

View File

@@ -1,16 +0,0 @@
/* Stylesheet: tailwind.css */
/*
https://tailwindcss.com/docs/functions-and-directives
IMPORTANT:
Be sure to remove these directives from your global CSS stylesheet.
Tailwind directives should only be included ONCE per project.
These directives should precede ALL Skeleton stylesheets.
*/
@tailwind base;
@tailwind components;
@tailwind utilities;
@tailwind variants;

View File

@@ -1,49 +0,0 @@
/* Stylesheet: typography-prose.css */
/* Provides default styling for the Tailwind Typography plugin via element modifiers. */
/* https://tailwindcss.com/docs/typography-plugin */
.prose {
@apply text-base font-token text-token;
/* Element Modifiers */
/* https://tailwindcss.com/docs/typography-plugin#element-modifiers */
@apply prose-headings:text-token;
/* @apply prose-lead:{utility}; */
@apply prose-h1:font-heading-token prose-h1:text-3xl prose-h1:md:text-5xl;
@apply prose-h2:font-heading-token prose-h2:text-2xl prose-h2:md:text-4xl;
@apply prose-h3:font-heading-token prose-h3:text-xl prose-h3:md:text-2xl;
@apply prose-h4:font-heading-token prose-h4:text-lg prose-h4:md:text-xl;
@apply prose-p:text-base;
/* @apply prose-a:{utility}; */
@apply prose-a:text-primary-700 prose-a:dark:text-primary-500 prose-a:hover:brightness-110 prose-a:underline;
@apply prose-blockquote:text-token prose-blockquote:text-base prose-blockquote:!border-secondary-500;
/* @apply prose-figure:{utility}; */
@apply prose-figcaption:text-token prose-figcaption:!text-sm prose-figcaption:italic prose-figcaption:text-center mt-3;
@apply prose-strong:text-token;
@apply prose-em:text-token;
/* @apply prose-ol:{utility}; */
/* @apply prose-ul:{utility}; */
@apply prose-li:text-base;
/* @apply prose-table:{utility}; */
/* @apply prose-thead:{utility}; */
/* @apply prose-tr:{utility}; */
/* @apply prose-th:{utility}; */
/* @apply prose-td:{utility}; */
/* @apply prose-img:{utility}; */
/* @apply prose-video:{utility}; */
/* @apply prose-hr:{utility}; */
/* The following have special use cases and must be handled seperately */
/* @apply prose-code:{utility}; */
/* @apply prose-pre:{utility}; */
}
/* NOTE: keep these in sync with typography.css */
.prose pre:not(.code-block pre) {
@apply font-mono text-base bg-neutral-900/90 text-white p-4 whitespace-pre-wrap overflow-x-auto rounded-container-token;
}
.prose code:is(:not(pre *)) {
@apply font-mono text-xs text-primary-700 dark:text-primary-400 whitespace-nowrap;
@apply bg-primary-500/30 dark:bg-primary-500/20;
@apply py-0.5 px-1 rounded;
}

View File

@@ -1,99 +0,0 @@
/* Stylesheet: typography.css */
/*
This represents the ON-BY-DEFAULT typography styles.
IMPORTANT: take care to maintain parity with typography-next.css!
*/
@layer base {
body {
@apply text-base font-token text-token;
}
/* === Headings === */
h1:not(.unstyled) {
@apply font-heading-token text-3xl md:text-5xl;
}
h2:not(.unstyled) {
@apply font-heading-token text-2xl md:text-4xl;
}
h3:not(.unstyled) {
@apply font-heading-token text-xl md:text-2xl;
}
h4:not(.unstyled) {
@apply font-heading-token text-lg md:text-xl;
}
h5:not(.unstyled) {
@apply font-heading-token text-base md:text-lg;
}
h6:not(.unstyled) {
@apply font-heading-token text-sm md:text-base;
}
/* === Elements === */
/* p { ... } */
a:not(.unstyled):not(.permalink):not(.btn):not(.btn-icon):not(.app-bar a):not(.logo-item):not(a.card):not(.list-nav a) {
@apply text-primary-700 dark:text-primary-500 hover:brightness-110 underline;
}
blockquote:not(.unstyled) {
@apply text-token text-base italic border-l-8 border-secondary-500 px-4 pl-4;
}
/* Keyboard */
kbd:not(.unstyled) {
@apply font-sans font-bold text-sm;
@apply bg-surface-300-600-token px-1.5 py-[3px] rounded;
@apply ring-[1px] ring-surface-900 ring-inset;
@apply border-b-2 border-surface-900;
}
/* Timestamps */
time:not(.unstyled) {
@apply text-sm text-surface-500 dark:text-surface-400;
}
/* === Preformatted / Code === */
/* For use outside of Skeleton's CodeBlock component */
pre:not(.unstyled):not(.code-block pre) {
@apply font-mono text-base bg-neutral-900/90 text-white p-4 whitespace-pre-wrap overflow-x-auto rounded-container-token;
}
code:not(.unstyled):is(:not(pre *)) {
@apply font-mono text-xs text-primary-700 dark:text-primary-400 whitespace-nowrap;
@apply bg-primary-500/30 dark:bg-primary-500/20;
@apply py-0.5 px-1 rounded;
}
/* === Insertions / Deletions ==== */
/* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins */
/* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del */
ins:not(.unstyled),
del:not(.unstyled) {
@apply block relative p-0.5 pl-5;
text-decoration: none;
}
ins:not(.unstyled)::before,
del:not(.unstyled)::before {
@apply absolute left-1 font-mono;
}
ins:not(.unstyled)::before {
content: '+';
}
del:not(.unstyled)::before {
content: '';
}
ins:not(.unstyled) {
@apply font-mono bg-success-500 text-on-success-token;
}
del:not(.unstyled) {
@apply font-mono bg-error-500 text-on-error-token;
}
}

View File

@@ -1,30 +0,0 @@
/* Stylesheet: skeleton-minimal.css */
/*
- Only required stylesheets are provided.
- Optional stylesheets are not included.
- Typography using opt-in system
*/
/* NOTE: The order shown below is required */
/* Import AFTER your theme, but BEFORE your global stylesheet. */
/* Tailwind Directives */
@import 'partials/tailwind.css';
/* === OPTIONAL STYLESHEETS === */
/* Core Styles */
/* (excluded - supplied by developer) */
/* Typography Settings */
@import 'partials/typography-next.css';
/* (prose excluded - supplied by developer) */
/* === REQUIRED STYLESHEETS === */
/* Imports all Tailwind Elements */
@import 'partials/elements.css';
/* Imports all Variant Styles */
@import 'partials/variants.css';

View File

@@ -1,30 +0,0 @@
/* Stylesheet: skeleton.css */
/*
- Slated to replace `all.css` in the next major release
- All available stylesheets are imported
- Typography using opt-in system
*/
/* NOTE: The order shown below is required */
/* Import AFTER your theme, but BEFORE your global stylesheet. */
/* Tailwind Directives */
@import 'partials/tailwind.css';
/* === OPTIONAL STYLESHEETS === */
/* Core Styles */
@import 'partials/core.css';
/* Typography Settings */
@import 'partials/typography-next.css';
/* DEPRECATED: 'partials/typography-prose.css' must now be imported directly */
/* === REQUIRED STYLESHEETS === */
/* Imports all Tailwind Elements */
@import 'partials/elements.css';
/* Imports all Variant Styles */
@import 'partials/variants.css';

View File

@@ -1,37 +0,0 @@
// The Skeleton Tailwind Plugin
// Tailwind Docs: https://tailwindcss.com/docs/plugins
// Skeleton Docs: https://www.skeleton.dev/docs/get-started
const plugin = require('tailwindcss/plugin');
// Skeleton Theme Modules
const themeColors = require('./theme/colors.cjs');
// Skeleton Design Token Modules
const tokensBackgrounds = require('./tokens/backgrounds.cjs');
const tokensBorders = require('./tokens/borders.cjs');
const tokensBorderRadius = require('./tokens/border-radius.cjs');
const tokensFills = require('./tokens/fills.cjs');
const tokensText = require('./tokens/text.cjs');
const tokensRings = require('./tokens/rings.cjs');
module.exports = plugin(
({ addUtilities }) => {
addUtilities({
// Implement Skeleton design token classes
...tokensBackgrounds(),
...tokensBorders(),
...tokensBorderRadius(),
...tokensFills(),
...tokensText(),
...tokensRings()
});
},
{
theme: {
extend: {
// Implement Skeleton theme colors
colors: themeColors()
}
}
}
);

View File

@@ -1,21 +0,0 @@
// The Skeleton Intellisense Tailwind Plugin
// Tailwind Docs: https://tailwindcss.com/docs/plugins
// Skeleton Docs: https://www.skeleton.dev/docs/get-started
const plugin = require('tailwindcss/plugin');
module.exports = plugin(({ addComponents }) => {
// The following will generate the non-token classes PURELY for Intellisense.
// These are excluded from production, which means we still need to lean into
// using the `skeleton.css` stylesheet to import non-token styles.
if (process.env.NODE_ENV !== 'production') {
// try/catch because it will throw when allComponents.cjs isn't generated yet
try {
const all = require('./generated/intellisense-classes.cjs');
addComponents(all, {
respectImportant: true,
respectPrefix: true
});
} catch {}
}
});

View File

@@ -1,19 +0,0 @@
// The Skeleton Tailwind Plugin
// Tailwind Docs: https://tailwindcss.com/docs/plugins
// Skeleton Docs: https://www.skeleton.dev/docs/get-started
const intellisensePlugin = require('./intellisense.cjs');
const corePlugin = require('./core.cjs');
// The default export is a function that returns an array of plugins
// and accepts an optional config that determines which plugins are included.
// By default, all plugins are included.
module.exports = function (config = { intellisense: true }) {
const { intellisense } = config;
const plugins = [corePlugin];
// Add the plugin if the option is not explicitly set to false
if (intellisense !== false) plugins.push(intellisensePlugin);
return plugins;
};

View File

@@ -1,14 +0,0 @@
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
darkMode: 'class',
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {
fontFamily: {
sans: ['Inter', ...defaultTheme.fontFamily.sans]
}
}
},
plugins: [...require('./src/lib/tailwind/skeleton.cjs')({ intellisense: false })]
};

View File

@@ -0,0 +1,8 @@
import { skeleton } from '../../packages/plugin/dist/index.js';
/** @type {import("tailwindcss").Config} */
export default {
darkMode: 'class',
content: ['./src/**/*.{html,js,svelte,ts}'],
plugins: [skeleton]
};

View File

@@ -23,6 +23,7 @@
"@faker-js/faker": "^8.0.2", "@faker-js/faker": "^8.0.2",
"@floating-ui/dom": "^1.2.9", "@floating-ui/dom": "^1.2.9",
"@skeletonlabs/skeleton": "workspace:*", "@skeletonlabs/skeleton": "workspace:*",
"@skeletonlabs/tw-plugin": "workspace:*",
"@sveltejs/adapter-vercel": "^3.0.1", "@sveltejs/adapter-vercel": "^3.0.1",
"@sveltejs/kit": "^1.20.2", "@sveltejs/kit": "^1.20.2",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",

View File

@@ -11,6 +11,9 @@ devDependencies:
'@floating-ui/dom': '@floating-ui/dom':
specifier: ^1.2.9 specifier: ^1.2.9
version: 1.2.9 version: 1.2.9
'@skeletonlabs/tw-plugin':
specifier: workspace:*
version: link:../../packages/plugin
'@skeletonlabs/skeleton': '@skeletonlabs/skeleton':
specifier: workspace:* specifier: workspace:*
version: link:../../packages/skeleton version: link:../../packages/skeleton

View File

@@ -16,7 +16,7 @@
<link href="/font-awesome/css/solid.min.css" rel="stylesheet" /> <link href="/font-awesome/css/solid.min.css" rel="stylesheet" />
</head> </head>
<body data-theme="skeleton"> <body data-theme="">
<div class="h-full overflow-hidden contents">%sveltekit.body%</div> <div class="h-full overflow-hidden contents">%sveltekit.body%</div>
</body> </body>
</html> </html>

View File

@@ -1,5 +1,7 @@
/* Global Stylesheet */ /* Global Stylesheet */
@import 'tailwind.postcss';
/* Ad Styles */ /* Ad Styles */
@import 'app-ads.postcss'; @import 'app-ads.postcss';

View File

@@ -0,0 +1,18 @@
import type { Handle } from '@sveltejs/kit';
export const handle: Handle = async ({ event, resolve }) => {
let theme = '';
const cookieTheme = event.cookies.get('theme');
if (cookieTheme) {
theme = cookieTheme;
} else {
event.cookies.set('theme', 'skeleton');
theme = 'skeleton';
}
return await resolve(event, {
transformPageChunk: ({ html }) => html.replace('data-theme=""', `data-theme="${theme}"`)
});
};

View File

@@ -14,8 +14,8 @@
import { AppBar, LightSwitch, popup, modalStore } from '@skeletonlabs/skeleton'; import { AppBar, LightSwitch, popup, modalStore } from '@skeletonlabs/skeleton';
// Stores // Stores
import { storeTheme } from '$lib/stores/stores';
import { drawerStore } from '@skeletonlabs/skeleton'; import { drawerStore } from '@skeletonlabs/skeleton';
import { storeTheme } from '$lib/stores/stores';
// Local // Local
let isOsMac = false; let isOsMac = false;
@@ -66,15 +66,14 @@
// { type: 'test', name: 'Test', icon: '🚧' }, // { type: 'test', name: 'Test', icon: '🚧' },
]; ];
const setTheme: SubmitFunction = () => { const setTheme: SubmitFunction = ({ formData }) => {
return async ({ result, update }) => { const theme = formData.get('theme')?.toString();
await update();
if (result.type === 'success') { if (theme) {
const theme = result.data?.theme as string; document.body.setAttribute('data-theme', theme);
storeTheme.set(theme); $storeTheme = theme;
} }
}; };
};
</script> </script>
<!-- NOTE: using stopPropagation to override Chrome for Windows search shortcut --> <!-- NOTE: using stopPropagation to override Chrome for Windows search shortcut -->
@@ -151,7 +150,7 @@
<!-- Theme --> <!-- Theme -->
<div> <div>
<!-- trigger --> <!-- trigger -->
<button class="btn hover:variant-soft-primary" use:popup={{ event: 'click', target: 'theme' }}> <button class="btn hover:variant-soft-primary" use:popup={{ event: 'click', target: 'theme', closeQuery: 'a[href]' }}>
<i class="fa-solid fa-palette text-lg md:!hidden" /> <i class="fa-solid fa-palette text-lg md:!hidden" />
<span class="hidden md:inline-block">Theme</span> <span class="hidden md:inline-block">Theme</span>
<i class="fa-solid fa-caret-down opacity-50" /> <i class="fa-solid fa-caret-down opacity-50" />

View File

@@ -12,6 +12,7 @@
// Local Utils // Local Utils
import { storePreview } from './stores'; import { storePreview } from './stores';
import { storeTheme } from '$lib/stores/stores';
import type { ColorSettings, FormTheme, ContrastReport } from './types'; import type { ColorSettings, FormTheme, ContrastReport } from './types';
import { inputSettings, fontSettings } from './settings'; import { inputSettings, fontSettings } from './settings';
import { type Palette, generatePalette, generateA11yOnColor, hexValueIsValid, getPassReport } from './colors'; import { type Palette, generatePalette, generateA11yOnColor, hexValueIsValid, getPassReport } from './colors';
@@ -71,7 +72,6 @@
function onPreviewToggle(): void { function onPreviewToggle(): void {
if ($storePreview === false) { if ($storePreview === false) {
localStorage.removeItem('storeThemGenForm'); localStorage.removeItem('storeThemGenForm');
location.reload(); // required
} }
} }

Some files were not shown because too many files have changed in this diff Show More