├── .firebaserc ├── .github └── workflows │ ├── firebase-hosting-merge.yml │ ├── firebase-hosting-pull-request.yml │ ├── main.yml │ └── tests.yml ├── .gitignore ├── .npmignore ├── LICENSE ├── build ├── bundle-sizes.js ├── extras.js ├── postcss-combine-selectors.cjs ├── props.js ├── to-figmatokens.js ├── to-object.js ├── to-style-dictionary.js ├── to-stylesheet.js ├── to-tokens.js └── utils.js ├── docsite ├── .gitignore ├── color-copy.css ├── index.css ├── index.html ├── index.js ├── js │ ├── animations.js │ ├── brand-colors.js │ ├── color-convert.js │ ├── color-copy.js │ ├── easing.js │ ├── scrollspy.js │ ├── select.js │ └── slider.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── adaptive-buttons.png │ ├── apple-touch-icon.png │ ├── cards.png │ ├── color-schemes.png │ ├── favicon.ico │ ├── favicon.svg │ ├── hero-layout.png │ ├── icon-192-maskable.png │ ├── icon-192.png │ ├── icon-512-maskable.png │ ├── icon-512.png │ ├── manifest.json │ ├── normalize-codepen.png │ ├── open-props-social.jpg │ ├── pagination.png │ ├── pop-animation.png │ ├── theme-switch.png │ └── theme-toggle.js └── syntax-highlight.css ├── firebase.json ├── package-lock.json ├── package.json ├── postcss.config.cjs ├── readme.md ├── src ├── extra │ ├── brand.css │ ├── buttons.css │ ├── buttons.dark.css │ ├── buttons.light.css │ ├── durations.css │ ├── normalize.css │ ├── normalize.dark.css │ ├── normalize.light.css │ ├── normalize.src.css │ ├── theme.css │ ├── theme.dark.css │ ├── theme.dark.switch.css │ ├── theme.light.css │ ├── theme.light.switch.css │ └── utilities.css ├── index.css ├── index.js ├── props.animations.css ├── props.animations.js ├── props.aspects.css ├── props.aspects.js ├── props.blue-hsl.css ├── props.blue.css ├── props.borders.css ├── props.borders.js ├── props.brand-colors.css ├── props.brand-colors.js ├── props.brown-hsl.css ├── props.brown.css ├── props.camo-hsl.css ├── props.camo.css ├── props.choco-hsl.css ├── props.choco.css ├── props.colors-hsl.css ├── props.colors-hsl.js ├── props.colors-oklch-hues.css ├── props.colors-oklch-hues.js ├── props.colors-oklch.css ├── props.colors-oklch.js ├── props.colors.css ├── props.colors.js ├── props.colors.src.js ├── props.cyan-hsl.css ├── props.cyan.css ├── props.easing.css ├── props.easing.js ├── props.fonts.css ├── props.fonts.js ├── props.gradients.css ├── props.gradients.js ├── props.gradients.src.js ├── props.gray-hsl.css ├── props.gray-oklch.css ├── props.gray-oklch.js ├── props.gray.css ├── props.green-hsl.css ├── props.green.css ├── props.highlights.css ├── props.indigo-hsl.css ├── props.indigo.css ├── props.jungle-hsl.css ├── props.jungle.css ├── props.layouts.css ├── props.lime-hsl.css ├── props.lime.css ├── props.masks.corner-cuts.css ├── props.masks.corner-cuts.js ├── props.masks.edges.css ├── props.masks.edges.js ├── props.media.css ├── props.media.js ├── props.orange-hsl.css ├── props.orange.css ├── props.pink-hsl.css ├── props.pink.css ├── props.purple-hsl.css ├── props.purple.css ├── props.red-hsl.css ├── props.red.css ├── props.sand-hsl.css ├── props.sand.css ├── props.shadows.css ├── props.shadows.js ├── props.sizes.css ├── props.sizes.js ├── props.stone-hsl.css ├── props.stone.css ├── props.supports.css ├── props.svg.css ├── props.svg.js ├── props.teal-hsl.css ├── props.teal.css ├── props.violet-hsl.css ├── props.violet.css ├── props.yellow-hsl.css ├── props.yellow.css ├── props.zindex.css └── props.zindex.js ├── test └── basic.test.cjs └── tsconfig.json /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "open-props" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.github/workflows/firebase-hosting-merge.yml: -------------------------------------------------------------------------------- 1 | # This file was auto-generated by the Firebase CLI 2 | # https://github.com/firebase/firebase-tools 3 | 4 | name: Deploy to Firebase Hosting on merge 5 | 'on': 6 | push: 7 | branches: 8 | - main 9 | jobs: 10 | build_and_deploy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - run: cd docsite && npm ci && npm run build 15 | - uses: FirebaseExtended/action-hosting-deploy@v0 16 | with: 17 | repoToken: '${{ secrets.GITHUB_TOKEN }}' 18 | firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_OPEN_PROPS }}' 19 | channelId: live 20 | projectId: open-props 21 | -------------------------------------------------------------------------------- /.github/workflows/firebase-hosting-pull-request.yml: -------------------------------------------------------------------------------- 1 | # This file was auto-generated by the Firebase CLI 2 | # https://github.com/firebase/firebase-tools 3 | 4 | name: Deploy to Firebase Hosting on PR 5 | 'on': pull_request 6 | jobs: 7 | build_and_preview: 8 | if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}' 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - run: cd docsite && npm ci && npm run build 13 | - uses: FirebaseExtended/action-hosting-deploy@v0 14 | with: 15 | repoToken: '${{ secrets.GITHUB_TOKEN }}' 16 | firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_OPEN_PROPS }}' 17 | projectId: open-props 18 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: NPM Publish 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-node@v2 13 | - run: npm ci 14 | - run: npm run build 15 | - run: npm run bundle 16 | - run: npm test 17 | - uses: JS-DevTools/npm-publish@v1 18 | with: 19 | token: ${{ secrets.NPM_TOKEN }} 20 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: actions/setup-node@v2 11 | - run: npm ci 12 | - run: npm run build 13 | - run: npm run bundle 14 | - run: npm test 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | dist/ 3 | .cache/ 4 | node_modules/ 5 | *.min.css 6 | src/shadow.*.css 7 | *.json 8 | *.ts 9 | *.d.ts -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .firebaserc 2 | .github 3 | firebase.json 4 | docsite/ 5 | test/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Adam Argyle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /build/bundle-sizes.js: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | import postcss from 'postcss'; 3 | import fs from 'node:fs/promises'; 4 | import pkg from '../postcss.config.cjs'; 5 | import { createRequire } from 'node:module'; 6 | import { sync as brotli } from 'brotli-size'; 7 | import { gzipSizeSync as gzip } from 'gzip-size'; 8 | 9 | // Comes in handy later when we run postcss 10 | const { plugins } = pkg; 11 | 12 | // @ts-ignore 13 | const require = createRequire(import.meta.url); 14 | const { scripts } = require('../package.json'); 15 | /** 16 | * We build up an object with script:command pairs from package.json 17 | * 18 | * @type {Object.} 19 | */ 20 | const filtered = Object.keys(scripts) 21 | .filter((key) => key.startsWith('lib:')) 22 | .reduce((obj, key) => { 23 | obj[key] = scripts[key]; 24 | return obj; 25 | }, {}); 26 | 27 | /** 28 | * The regex captures a filepath and filename group from an npm command. 29 | * 30 | * Captures for the command `postcss src/extra/normalize.light.css -o normalize.light.min.css` yields 31 | * { 32 | * groups: { 33 | * filepath: 'src/extra/normalize.light.css', 34 | * filename: 'normalize.light.min.css' 35 | * } 36 | * } 37 | */ 38 | const regex = /postcss\s(?\S+)\s\-[o]\s(?.*\.css)(?:.*$)/; 39 | 40 | /** 41 | * @typedef {Object} Size 42 | * @property {number} raw - Unminified size in bytes 43 | * @property {string} size - Unminified size in KiB 44 | * @property {string} minified - Minified size in KiB 45 | * @property {string} brotli - Brotli compressed minified size in KiB 46 | * @property {string} gzip - Gzip compressed minified size in KiB 47 | */ 48 | /** @type {Object.} sizes */ 49 | let sizes = {} 50 | 51 | for (const [_, script] of Object.entries(filtered)) { 52 | const found = script.match(regex); 53 | 54 | if (!found) continue; 55 | 56 | /** 57 | * @typedef {object} CaptureGroup 58 | * @property {string} filepath 59 | * @property {string} filename 60 | */ 61 | /** @type {CaptureGroup} */ 62 | const { filepath, filename } = found.groups; 63 | 64 | /** 65 | * @type {import('postcss').ProcessOptions} 66 | */ 67 | const options = { from: path.resolve(`../${filepath}`), to: undefined }; 68 | const css = await fs.readFile(path.resolve(`../${filepath}`), 'utf-8'); 69 | /** 70 | * Run the css through PostCSS (just like Open-Props). 71 | * plugins.slice(0, -1) remove `cssnano` plugin so we can get the size of the unminified code 72 | */ 73 | const code = await postcss(plugins.slice(0, -1)).process(css, options); 74 | /** 75 | * This time we want to get the minified size. 76 | */ 77 | const minified = await postcss(plugins).process(css, options); 78 | 79 | /** 80 | * Build the sizes object. 81 | * Strip `.min` from the filename 82 | */ 83 | sizes[filename.replace('.min', '')] = { 84 | raw: code.css.length, // in bytes 85 | size: (code.css.length / 1024).toFixed(2), // in KiB 86 | minified: (minified.css.length / 1024).toFixed(2), // KiB 87 | brotli: (brotli(minified.css) / 1024).toFixed(2), // in KiB 88 | gzip: (gzip(minified.css) / 1024).toFixed(2), // in KiB 89 | } 90 | } 91 | 92 | await fs.writeFile('bundle-sizes.json', JSON.stringify(sizes, null, 2), { encoding: 'utf8' }); 93 | -------------------------------------------------------------------------------- /build/extras.js: -------------------------------------------------------------------------------- 1 | import {readFile, writeFile} from 'fs' 2 | 3 | readFile('./normalize.min.css', 'utf-8', (err, contents) => { 4 | if (err) return console.log(err) 5 | const replaced = contents.replace(/:where\(html\)/g, ':host') 6 | 7 | writeFile('./normalize.shadow.min.css', replaced, 'utf-8', err => { 8 | console.log(err) 9 | }) 10 | }) -------------------------------------------------------------------------------- /build/postcss-combine-selectors.cjs: -------------------------------------------------------------------------------- 1 | const creator = () => { 2 | return { 3 | postcssPlugin: 'postcss-combine-selectors', 4 | OnceExit(root) { 5 | const rulesToCombine = new Map() 6 | 7 | root.walkRules(rule => { 8 | if (isKeyframesRule(rule)) { 9 | return 10 | } 11 | 12 | const key = ruleKey(rule) 13 | const existing = rulesToCombine.get(key) 14 | 15 | // Existing group: 16 | // - add rule to the group 17 | if (existing) { 18 | existing.rules.push(rule) 19 | return 20 | } 21 | 22 | // New group: 23 | // - first rule is the one we're going to combine into 24 | // - create an empty slice for other rules to be added to 25 | rulesToCombine.set(key, { 26 | first: rule, 27 | rules: [] 28 | }) 29 | }) 30 | 31 | // Iterate over all groups 32 | for (const { first, rules } of rulesToCombine.values()) { 33 | // If there was only one rule for a given group, there's nothing to combine 34 | if (rules.length === 0) { 35 | continue 36 | } 37 | 38 | // Append all contents of all subsequent rules to the first rule 39 | for (const rule of rules) { 40 | rule.each((child) => { 41 | child.remove() 42 | first.append(child) 43 | }) 44 | 45 | // Remove the now-empty rule 46 | rule.remove() 47 | } 48 | } 49 | }, 50 | } 51 | } 52 | 53 | /** 54 | * Construct a key that is specific to the AST ancestry of the rule. 55 | * Only rules with the same key can be combined. 56 | * 57 | * @param {import('postcss').Rule} rule 58 | * @returns {string} 59 | */ 60 | function ruleKey(rule) { 61 | let key = `[rule ${rule.selector}]` 62 | 63 | let ancestor = rule.parent 64 | while (ancestor) { 65 | if (ancestor.type === 'atrule') { 66 | key = `[${ancestor.name} ${ancestor.params}]${key}` 67 | } else if (ancestor.type === 'rule') { 68 | key = `[rule ${ancestor.selector}]${key}` 69 | } else if (ancestor.type === 'root') { 70 | break 71 | } 72 | 73 | ancestor = ancestor.parent 74 | } 75 | 76 | return key 77 | } 78 | 79 | function isKeyframesRule(rule) { 80 | if (rule.parent?.type === 'atrule' && rule.parent.name === 'keyframes') { 81 | return true 82 | } 83 | 84 | return false 85 | } 86 | 87 | module.exports = creator 88 | module.exports.postcss = true 89 | -------------------------------------------------------------------------------- /build/props.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | 3 | import Animations from '../src/props.animations.js' 4 | import Sizes from '../src/props.sizes.js' 5 | import * as Colors from '../src/props.colors.js' 6 | import * as ColorsHSL from '../src/props.colors-hsl.js' 7 | import ColorsOKLCH from '../src/props.colors-oklch.js' 8 | import ColorsOKLCHgray from '../src/props.gray-oklch.js' 9 | import ColorHues from '../src/props.colors-oklch-hues.js' 10 | import Fonts from '../src/props.fonts.js' 11 | import Borders from '../src/props.borders.js' 12 | import Aspects from '../src/props.aspects.js' 13 | import Easings from '../src/props.easing.js' 14 | import Gradients from '../src/props.gradients.js' 15 | import Shadows from '../src/props.shadows.js' 16 | import SVG from '../src/props.svg.js' 17 | import Zindex from '../src/props.zindex.js' 18 | import MaskEdges from '../src/props.masks.edges.js' 19 | import MaskCornerCuts from '../src/props.masks.corner-cuts.js' 20 | import BrandColors from '../src/props.brand-colors.js' 21 | 22 | import {buildPropsStylesheet} from './to-stylesheet.js' 23 | import {toTokens} from './to-tokens.js' 24 | import {toObject} from './to-object.js' 25 | import {toFigmaTokens} from './to-figmatokens.js' 26 | import {toStyleDictionary} from './to-style-dictionary.js' 27 | 28 | const [,,prefix='',useWhere,customSubject='',filePrefix=''] = process.argv 29 | 30 | const subject = customSubject === '' ? 'html' : customSubject 31 | const selector = useWhere === 'true' ? `:where(${subject})` : subject 32 | const pfx = filePrefix ? filePrefix + '.' : '' 33 | 34 | const mainbundle = { 35 | [`${pfx}props.fonts.css`]: Fonts, 36 | [`${pfx}props.sizes.css`]: Sizes, 37 | [`${pfx}props.easing.css`]: Easings, 38 | [`${pfx}props.zindex.css`]: Zindex, 39 | [`${pfx}props.shadows.css`]: Shadows, 40 | [`${pfx}props.aspects.css`]: Aspects, 41 | [`${pfx}props.colors.css`]: Colors.default, 42 | // [`${pfx}props.svg.css`]: SVG, 43 | [`${pfx}props.gradients.css`]: Gradients, 44 | [`${pfx}props.animations.css`]: Animations, 45 | [`${pfx}props.borders.css`]: Borders, 46 | } 47 | 48 | const individual_colors = Object.keys(Colors) 49 | .filter(exportName => exportName !== "default") 50 | .reduce((root, hueName) => ({ 51 | ...root, 52 | [`${pfx}props.${hueName.toLowerCase()}.css`]: Colors[hueName] 53 | }), {}) 54 | 55 | const individual_colors_hsl = Object.keys(ColorsHSL) 56 | .filter(exportName => exportName !== "default") 57 | .reduce((root, hueName) => ({ 58 | ...root, 59 | [`${pfx}props.${hueName.toLowerCase()}-hsl.css`]: ColorsHSL[hueName] 60 | }), {}) 61 | 62 | const individuals = { 63 | [`${pfx}props.masks.edges.css`]: MaskEdges, 64 | [`${pfx}props.masks.corner-cuts.css`]: MaskCornerCuts, 65 | } 66 | 67 | // gen design tokens 68 | const jsonbundle = Object.entries({ 69 | ...Object.assign({}, ...Object.values(individual_colors)), 70 | ...Sizes, 71 | ...Easings, 72 | ...Zindex, 73 | ...Aspects, 74 | ...Gradients, 75 | ...Borders, 76 | }).reverse() 77 | 78 | const designtokens = toTokens(jsonbundle) 79 | const JSONtokens = fs.createWriteStream('../open-props.tokens.json') 80 | JSONtokens.end(JSON.stringify(Object.fromEntries(designtokens), null, 2)) 81 | 82 | // gen style-dictionary tokens 83 | const styledictionarytokens = toStyleDictionary(jsonbundle) 84 | const StyleDictionaryTokens = fs.createWriteStream('../open-props.style-dictionary-tokens.json') 85 | StyleDictionaryTokens.end(JSON.stringify(styledictionarytokens, null, 2)) 86 | 87 | // gen figma tokens 88 | const figmatokens = toFigmaTokens(jsonbundle) 89 | const FigmaTokens = fs.createWriteStream('../open-props.figma-tokens.json') 90 | FigmaTokens.end(JSON.stringify(figmatokens, null, 2)) 91 | 92 | const figmatokensSYNC = { 'open-props': { ...figmatokens } } 93 | const FigmaTokensSync = fs.createWriteStream('../open-props.figma-tokens.sync.json') 94 | FigmaTokensSync.end(JSON.stringify(figmatokensSYNC, null, 2)) 95 | 96 | if (!fs.existsSync('../dist')) 97 | fs.mkdirSync('../dist') 98 | 99 | const JS = fs.createWriteStream('../dist/open-props.js') 100 | JS.end(`var OpenProps = ${JSON.stringify(toObject(), null, 2)}`) 101 | 102 | const ES = fs.createWriteStream('../dist/open-props.module.js') 103 | ES.end(`export default ${JSON.stringify(toObject(), null, 2)}`) 104 | 105 | const CJS = fs.createWriteStream('../dist/open-props.cjs') 106 | CJS.end(`module.exports = ${JSON.stringify(toObject(), null, 2)}`) 107 | 108 | // const UMD = fs.createWriteStream('../dist/open-props.umd.js') 109 | // UMD.end(`module.exports = ${JSON.stringify(toObject(), null, 2)}`) 110 | 111 | 112 | // gen prop variants 113 | Object.entries({ 114 | ...mainbundle, 115 | ...individual_colors, 116 | ...individual_colors_hsl, 117 | ...individuals, 118 | }).forEach(([filename, props]) => { 119 | buildPropsStylesheet({filename, props}, {selector, prefix}) 120 | }) 121 | 122 | // gen color hsl main file 123 | buildPropsStylesheet({ 124 | filename: pfx + 'props.colors-hsl.css', 125 | props: ColorsHSL.default}, 126 | {selector, prefix} 127 | ) 128 | 129 | // gen color oklch files 130 | buildPropsStylesheet({ 131 | filename: pfx + 'props.colors-oklch.css', 132 | props: ColorsOKLCH}, 133 | { 134 | selector: useWhere === 'true' ? `:where(*)` : '*', 135 | prefix 136 | } 137 | ) 138 | buildPropsStylesheet({ 139 | filename: pfx + 'props.gray-oklch.css', 140 | props: ColorsOKLCHgray}, 141 | { 142 | selector: useWhere === 'true' ? `:where(*)` : '*', 143 | prefix 144 | } 145 | ) 146 | buildPropsStylesheet({ 147 | filename: pfx + 'props.colors-oklch-hues.css', 148 | props: ColorHues}, 149 | {selector, prefix} 150 | ) 151 | 152 | buildPropsStylesheet( 153 | {filename: pfx + 'props.brand-colors.css', props: BrandColors}, 154 | {selector, prefix} 155 | ) 156 | 157 | // gen index.css 158 | const entry = fs.createWriteStream(`../src/${pfx}index.css`) 159 | entry.write(`@import 'props.media.css'; 160 | `) 161 | Object.keys(mainbundle).forEach(filename => { 162 | entry.write(`@import '${filename}';\n`) 163 | }) 164 | entry.end() -------------------------------------------------------------------------------- /build/to-figmatokens.js: -------------------------------------------------------------------------------- 1 | import * as Colors from '../src/props.colors.js' 2 | 3 | export const toFigmaTokens = props => { 4 | const figmatokens = {} 5 | 6 | props.map(([key, token]) => { 7 | let meta = {} 8 | 9 | let isLength = key.includes('size') && !key.includes('border-size') 10 | let isBorder = key.includes('border-size') 11 | let isRadius = key.includes('radius') 12 | let isShadow = key.includes('shadow') 13 | let colors = Object.keys(Colors) 14 | .filter(exportName => exportName !== "default") 15 | .map(hueName => hueName.toLowerCase()) 16 | let isColor = colors.some(color => key.includes(color)) 17 | 18 | if (isLength) meta.type = 'sizing' 19 | else if (isBorder) meta.type = 'borderWidth' 20 | else if (isRadius) meta.type = 'borderRadius' 21 | else if (isShadow) meta.type = 'boxShadow' 22 | else if (isColor) meta.type = 'color' 23 | else meta.type = 'other' 24 | 25 | if (!(meta.type in figmatokens)) figmatokens[meta.type] = {} 26 | 27 | if (isColor) { 28 | let color = /--(.+?)-/.exec(key)[1] 29 | if (!(color in figmatokens[meta.type])) figmatokens[meta.type][color] = {} 30 | figmatokens[meta.type][color][key] = { 31 | value: token, 32 | ...meta, 33 | } 34 | } else { 35 | figmatokens[meta.type][key] = { 36 | value: token, 37 | ...meta, 38 | } 39 | } 40 | }) 41 | 42 | return figmatokens 43 | } -------------------------------------------------------------------------------- /build/to-object.js: -------------------------------------------------------------------------------- 1 | import Animations from '../src/props.animations.js' 2 | import Sizes from '../src/props.sizes.js' 3 | import Colors from '../src/props.colors.js' 4 | import ColorsHSL from '../src/props.colors-hsl.js' 5 | import Fonts from '../src/props.fonts.js' 6 | import Borders from '../src/props.borders.js' 7 | import Aspects from '../src/props.aspects.js' 8 | import Easings from '../src/props.easing.js' 9 | import Gradients from '../src/props.gradients.js' 10 | import Shadows from '../src/props.shadows.js' 11 | import SVG from '../src/props.svg.js' 12 | import Zindex from '../src/props.zindex.js' 13 | import MaskEdges from '../src/props.masks.edges.js' 14 | import MaskCornerCuts from '../src/props.masks.corner-cuts.js' 15 | 16 | import {mapToObjectNotation} from './utils.js' 17 | 18 | export const toObject = () => { 19 | return mapToObjectNotation({ 20 | ...Animations, 21 | ...Sizes, 22 | ...Colors, 23 | ...ColorsHSL, 24 | ...Fonts, 25 | ...Borders, 26 | ...Aspects, 27 | ...Easings, 28 | ...SVG, 29 | ...Gradients, 30 | ...Shadows, 31 | ...Zindex, 32 | ...MaskEdges, 33 | ...MaskCornerCuts, 34 | }) 35 | } -------------------------------------------------------------------------------- /build/to-style-dictionary.js: -------------------------------------------------------------------------------- 1 | import * as Colors from '../src/props.colors.js' 2 | 3 | // Mapping of CSS variable names to dictionary keys 4 | const dictionaryMap = { 5 | "size-px": "px", 6 | "size-relative": "relative", 7 | "size-fluid": "fluid", 8 | "size-header": "header", 9 | "size-content": "content", 10 | "border-size": "size", 11 | "radius-conditional": "conditional", 12 | "radius-blob": "blob" 13 | } 14 | 15 | // Map a value to a dictionary key using the dictionaryMap 16 | const mapToDictionaryKey = (value) => dictionaryMap[value] || value 17 | 18 | // Determine the type key based on the metaType 19 | const getTypeKey = (metaType) => { 20 | if (metaType === "size" || metaType === "border-radius") { 21 | return metaType === "size" ? "size" : "radius" 22 | } else if (metaType === "border-width") { 23 | return "border" 24 | } 25 | return metaType 26 | } 27 | 28 | // Count the occurrences of a character in a string 29 | const countOccurrences = (str, letter) => (str.match(new RegExp(letter, 'g')) || []).length 30 | 31 | // Regular expression to match CSS variable usages 32 | const cssVarUsageRegex = /var\(--([a-zA-Z0-9-]+)\)/g 33 | 34 | // Replace the last occurrence of a pattern with a replacement 35 | /* https://www.30secondsofcode.org/js/s/replace-last-occurrence/ */ 36 | const replaceLast = (str, pattern, replacement) => { 37 | const match = 38 | typeof pattern === 'string' 39 | ? pattern 40 | : (str.match(new RegExp(pattern.source, 'g')) || []).slice(-1)[0] 41 | if (!match) return str 42 | const last = str.lastIndexOf(match) 43 | return last !== -1 44 | ? `${str.slice(0, last)}${replacement}${str.slice(last + match.length)}` 45 | : str 46 | } 47 | 48 | // Helper function to convert CSS variable name to token reference 49 | const tokenizeCSSVar = (variableName, metaType) => { 50 | const tokenName = replaceLast(variableName, '-', '.') 51 | const hyphenCount = countOccurrences(variableName, '-') 52 | 53 | if (hyphenCount > 2 && metaType === "other") { 54 | const [firstPart, ...restParts] = tokenName.split('-') 55 | return `{${metaType}.${firstPart}.${restParts.join('-')}.value}` 56 | } 57 | 58 | return `{${tokenName}.value}` 59 | }; 60 | 61 | // Convert CSS variable usages to token references 62 | const cssVarToToken = (input, metaType) => { 63 | if (!input.toString().includes("var")) { 64 | return input 65 | } 66 | 67 | return input.replace(cssVarUsageRegex, (match, variableName) => { 68 | return tokenizeCSSVar(variableName, metaType) 69 | }) 70 | }; 71 | 72 | // Create a token object based on metaType and dictionary key 73 | const createTokenObject = ({ 74 | baseObj, 75 | mainKey, 76 | metaType, 77 | dictionarykey, 78 | index, 79 | token 80 | }) => { 81 | const typeKey = getTypeKey(metaType) 82 | const targetObj = baseObj[typeKey] = baseObj[typeKey] || {} 83 | 84 | if (typeKey === "size" || typeKey === "radius") { 85 | const shouldReplace = mainKey !== dictionarykey 86 | handleKey(targetObj, dictionarykey, index, token, metaType, shouldReplace) 87 | } else if (typeKey !== "other") { 88 | handleKey(targetObj, dictionarykey, index, token, metaType, true) 89 | } else { 90 | handleOtherTypes(targetObj, dictionarykey, index, token, metaType) 91 | } 92 | 93 | return baseObj 94 | } 95 | 96 | // Handle cases where meta.type != "other" 97 | function handleKey(targetObj, dictionarykey, index, token, metaType, shouldReplace) { 98 | if (shouldReplace) { 99 | targetObj[dictionarykey] = targetObj[dictionarykey] || {} 100 | targetObj[dictionarykey][index] = { value: token, type: metaType } 101 | } else { 102 | targetObj[index] = { value: token, type: metaType } 103 | } 104 | } 105 | 106 | // Handle cases where meta.type = "other" 107 | function handleOtherTypes(targetObj, dictionarykey, index, token, metaType) { 108 | const keyParts = dictionarykey.split("-") 109 | 110 | if (keyParts.length > 1) { 111 | const groupName = keyParts[0] 112 | targetObj[groupName] = targetObj[groupName] || {} 113 | targetObj[groupName][index] = { value: token, type: metaType } 114 | 115 | const rest = keyParts.slice(1) 116 | const subKey = rest.join("-") 117 | 118 | targetObj[groupName][subKey] = targetObj[groupName][subKey] || {} 119 | targetObj[groupName][subKey][index] = { value: token, type: metaType } 120 | } 121 | } 122 | 123 | // Generate a style dictionary 124 | export const toStyleDictionary = props => { 125 | const colors = Object.keys(Colors) 126 | .filter(exportName => exportName !== "default") 127 | .map(hueName => hueName.toLowerCase()) 128 | 129 | return props.reduce((styledictionarytokens, [key, token]) => { 130 | const meta = {} 131 | 132 | const isLength = key.includes('size') && !key.includes('border-size') 133 | const isBorder = key.includes('border-size') 134 | const isRadius = key.includes('radius') 135 | const isShadow = key.includes('shadow') 136 | const isColor = colors.some(color => key.includes(color)) 137 | 138 | if (isLength) meta.type = 'size' 139 | else if (isBorder) meta.type = 'border-width' 140 | else if (isRadius) meta.type = 'border-radius' 141 | else if (isShadow) meta.type = 'box-shadow' 142 | else if (isColor) meta.type = 'color' 143 | else meta.type = 'other' 144 | 145 | const keyWithoutPrefix = key.replace('--', '') 146 | const keyParts = keyWithoutPrefix.split('-') 147 | const mainKey = keyParts.length > 1 ? keyParts.slice(0, -1).join('-') : keyParts[0] 148 | const index = keyParts.length > 1 ? keyParts[keyParts.length - 1] : 0 149 | 150 | const dictionarykey = mapToDictionaryKey(mainKey) 151 | 152 | return createTokenObject({ 153 | baseObj: styledictionarytokens, 154 | mainKey, 155 | metaType: meta.type, 156 | dictionarykey, 157 | index, 158 | token: cssVarToToken(token, meta.type) 159 | }) 160 | }, {}) 161 | } 162 | -------------------------------------------------------------------------------- /build/to-stylesheet.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | 3 | export const buildPropsStylesheet = ({filename,props}, {selector,prefix}) => { 4 | const file = fs.createWriteStream("../src/" + filename) 5 | 6 | let appendedMeta = '' 7 | 8 | if (filename.includes('shadows') || filename.includes('animations')) { 9 | file.write(`@import 'props.media.css';\n\n`) 10 | } 11 | 12 | if (filename.includes('shadows')) { 13 | let dark_propsMeta = `` 14 | let dark_props = Object.entries(props) 15 | .filter(([prop, val]) => 16 | prop.includes('-@media:dark')) 17 | 18 | dark_props.forEach(([prop, val], index) => { 19 | let v = props[prop] 20 | let extract = prop.slice(2, prop.length-('-@media:dark'.length)) 21 | let p = prefix && prefix !== "''" 22 | ? `--${prefix}-` + extract 23 | : `--${extract}` 24 | 25 | dark_propsMeta += ` ${p}: ${val};${index !== dark_props.length-1 ? '\n' : ''}` 26 | }) 27 | appendedMeta += ` 28 | @media (--OSdark) { 29 | ${selector} { 30 | ${dark_propsMeta} 31 | } 32 | }` 33 | } 34 | 35 | // Add @supports block to gradients 36 | if (filename.includes('gradients')) { 37 | appendedMeta += ` 38 | @supports (background: linear-gradient(to right in oklab, #000, #fff)) { 39 | ${selector} { 40 | --gradient-space: in oklab; 41 | } 42 | }`; 43 | } 44 | 45 | file.write(`${selector} {\n`) 46 | 47 | Object.entries(props).forEach(([prop, val]) => { 48 | if (prop.includes('-@')) 49 | return 50 | 51 | if (prop.includes('animation')) { 52 | let keyframes = props[`${prop}-@`] 53 | appendedMeta += keyframes 54 | } 55 | 56 | if (prefix && prefix !== "''") { 57 | prop = `--${prefix}-` + prop.slice(2) 58 | if (typeof(val) == "string" && val.includes("var(--")) 59 | val = val.replace(/var\(--/g, `var(--${prefix}-`) 60 | } 61 | 62 | file.write(` ${prop}: ${val};\n`) 63 | }) 64 | 65 | if (filename.includes('animations')) { 66 | let dark_props = Object.entries(props) 67 | .filter(([prop, val]) => 68 | prop.includes('-@media:dark')) 69 | 70 | dark_props.forEach(([prop, val], index) => { 71 | let hasDarkKeyframe = prop.endsWith('-@media:dark') && val.trim().startsWith('@keyframe') 72 | if (hasDarkKeyframe) { 73 | appendedMeta += ` 74 | @media (--OSdark) { 75 | ${val.trim().replace(/\n/g, '\n ')} 76 | }` 77 | } 78 | }) 79 | } 80 | 81 | file.write('}\n') 82 | file.end(appendedMeta) 83 | } -------------------------------------------------------------------------------- /build/to-tokens.js: -------------------------------------------------------------------------------- 1 | import * as Colors from '../src/props.colors.js' 2 | 3 | export const toTokens = props => 4 | props.map(([key, token]) => { 5 | let meta = {} 6 | 7 | let isLength = key.includes('size') 8 | let isEasing = key.includes('ease') 9 | let colors = Object.keys(Colors) 10 | .filter(exportName => exportName !== "default") 11 | .map(hueName => hueName.toLowerCase()) 12 | let isColor = colors.some(color => key.includes(color)) 13 | 14 | if (isLength) meta.$type = 'dimension' 15 | else if (isEasing) meta.$type = 'cubic-bezier' 16 | else if (isColor) meta.$type = 'color' 17 | 18 | return [key, { 19 | $value: token, 20 | ...meta, 21 | }] 22 | }) -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | export const camelize = text => { 2 | text = text.replace(/[-]+(.)?/g, (_, c) => c 3 | ? c.toUpperCase() 4 | : '') 5 | return text.substr(0, 1).toLowerCase() + text.substr(1) 6 | } 7 | 8 | export const mapToObjectNotation = props => { 9 | for (var prop in props) 10 | props[camelize(prop)] = props[prop] 11 | return props 12 | } -------------------------------------------------------------------------------- /docsite/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .cache/ 4 | dist/ 5 | node_modules/ -------------------------------------------------------------------------------- /docsite/color-copy.css: -------------------------------------------------------------------------------- 1 | .copy-options { 2 | font-family: var(--font-sans); 3 | display: flex; 4 | flex-wrap: wrap; 5 | flex-direction: row; 6 | gap: var(--size-3); 7 | 8 | & .example { 9 | font-style: italic; 10 | color: var(--text-2); 11 | } 12 | 13 | [data-theme="light"] & .example { 14 | color: var(--gray-7); 15 | } 16 | 17 | & input:is(:disabled) { 18 | cursor: not-allowed; 19 | 20 | &~label { 21 | color: var(--gray-5); 22 | cursor: not-allowed; 23 | } 24 | } 25 | 26 | @media (--md-n-below) { 27 | flex-direction: column; 28 | } 29 | } 30 | 31 | .options { 32 | display: flex; 33 | flex-wrap: wrap; 34 | gap: var(--size-7); 35 | align-items: center; 36 | justify-content: flex-start; 37 | padding-inline: var(--size-4); 38 | padding-block: var(--size-3); 39 | margin: var(--size-2) 0; 40 | overflow: auto; 41 | border-radius: var(--radius-conditional-2); 42 | border: var(--border-size-1) solid var(--surface-3); 43 | background: white; 44 | box-shadow: var(--shadow-4); 45 | 46 | [data-theme="dark"] & { 47 | background: var(--surface-2); 48 | box-shadow: var(--shadow-3); 49 | } 50 | 51 | @media (max-width: 768px) { 52 | flex-direction: column; 53 | align-items: start; 54 | } 55 | } 56 | 57 | .options:nth-child(2) { 58 | gap: var(--size-5); 59 | } 60 | 61 | .input-group { 62 | display: flex; 63 | align-items: center; 64 | /* justify-content: flex-start; */ 65 | & > label { 66 | padding-inline-start: var(--size-2); 67 | } 68 | } 69 | 70 | .color-format:has(:disabled) { 71 | color: var(--gray-5); 72 | } 73 | 74 | .tooltip { 75 | position: absolute; 76 | left: 50%; 77 | transform: translateX(-50%); 78 | top: -100%; 79 | min-width: max-content; 80 | border-radius: var(--radius-round); 81 | padding: var(--size-1) var(--size-2); 82 | font-size: var(--size-2); 83 | background-color: #000; 84 | color: #fff; 85 | z-index: 9999; 86 | pointer-events: none; 87 | 88 | } 89 | 90 | .tooltip-show { 91 | animation: var(--animation-fade-in) forwards; 92 | animation-duration: 0.5s; 93 | } 94 | 95 | .tooltip-hide { 96 | animation: var(--animation-fade-out) forwards; 97 | animation-duration: 0.5s; 98 | } 99 | 100 | .color-swatch:has(.tooltip) { 101 | position: relative; 102 | } 103 | 104 | .color-swatch-list { 105 | list-style: none; 106 | } -------------------------------------------------------------------------------- /docsite/index.js: -------------------------------------------------------------------------------- 1 | import 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.16.0/prism.min.js' 2 | import 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.16.0/plugins/normalize-whitespace/prism-normalize-whitespace.min.js' 3 | 4 | import '/js/easing.js' 5 | import '/js/animations.js' 6 | import '/js/slider.js' 7 | import '/js/scrollspy.js' 8 | import '/js/select.js' 9 | 10 | import '/js/color-copy.js' 11 | -------------------------------------------------------------------------------- /docsite/js/animations.js: -------------------------------------------------------------------------------- 1 | import {showPlayIcon} from './easing.js' 2 | 3 | const cleanup = e => { 4 | setTimeout(()=> { 5 | e.target.style = '' 6 | showPlayIcon(e.target.querySelector('button')) 7 | }, 500) 8 | } 9 | 10 | document 11 | .querySelectorAll('.animation-demo') 12 | .forEach(group => { 13 | group.addEventListener('click', e => { 14 | if (e.target.nodeName !== 'BUTTON') return 15 | 16 | let sample = e.target.closest('.animation-demo-target') 17 | 18 | if (sample.dataset.startingStyles) { 19 | sample.style = sample.dataset.startingStyles 20 | 21 | setTimeout(()=> { 22 | sample.style.animation = `var(--animation-${sample.dataset.animation}) forwards` 23 | sample.addEventListener('animationend', cleanup, {once:true}) 24 | }, 300) 25 | } 26 | else if (sample.style.animation != '') { 27 | sample.style.animation = null 28 | sample.removeEventListener('animationend', cleanup) 29 | } 30 | else { 31 | sample.style.animation = `var(--animation-${sample.dataset.animation}) forwards` 32 | sample.addEventListener('animationend', cleanup, {once:true}) 33 | } 34 | }) 35 | }) -------------------------------------------------------------------------------- /docsite/js/brand-colors.js: -------------------------------------------------------------------------------- 1 | console.log( 2 | Object.keys(import('../../src/props.brand-colors.js')) 3 | .map((brand) => [brand.replace(/-/g, ' ').replace('brand ', ''), brand]) 4 | .map( 5 | ([brandTitlecase, brand]) => 6 | `

    ${brandTitlecase}

` 7 | ) 8 | .join('') 9 | ) 10 | -------------------------------------------------------------------------------- /docsite/js/color-convert.js: -------------------------------------------------------------------------------- 1 | 2 | // https://css-tricks.com/converting-color-spaces-in-javascript/ 3 | function RGBToHex(r, g, b) { 4 | let r_str = r.toString(16); 5 | let g_str = g.toString(16); 6 | let b_str = b.toString(16); 7 | 8 | if (r_str.length == 1) r_str = '0' + r_str; 9 | if (g_str.length == 1) g_str = '0' + g_str; 10 | if (b_str.length == 1) b_str = '0' + b_str; 11 | 12 | return '#' + r_str + g_str + b_str; 13 | } 14 | 15 | // https://css-tricks.com/converting-color-spaces-in-javascript/ 16 | function RGBToHSL(r, g, b) { 17 | r /= 255; 18 | g /= 255; 19 | b /= 255; 20 | 21 | let cmin = Math.min(r, g, b), 22 | cmax = Math.max(r, g, b), 23 | delta = cmax - cmin, 24 | h = 0, 25 | s = 0, 26 | l = 0; 27 | 28 | if (delta == 0) h = 0; 29 | else if (cmax == r) h = ((g - b) / delta) % 6; 30 | else if (cmax == g) h = (b - r) / delta + 2; 31 | else h = (r - g) / delta + 4; 32 | 33 | h = Math.round(h * 60); 34 | 35 | if (h < 0) h += 360; 36 | 37 | l = (cmax + cmin) / 2; 38 | 39 | s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1)); 40 | 41 | s = +(s * 100).toFixed(1); 42 | l = +(l * 100).toFixed(1); 43 | 44 | return 'hsl(' + h + ' ' + s + '% ' + l + '%)'; 45 | } 46 | 47 | export { RGBToHSL, RGBToHex }; 48 | -------------------------------------------------------------------------------- /docsite/js/color-copy.js: -------------------------------------------------------------------------------- 1 | import { rovingIndex } from 'roving-ux'; 2 | import { RGBToHSL, RGBToHex } from './color-convert'; 3 | 4 | function addTooltip(e, value) { 5 | 6 | const tooltip = document.createElement('span'); 7 | tooltip.className = 'tooltip tooltip-show'; 8 | tooltip.innerHTML = `${value} copied to clipboard!`; 9 | 10 | e.appendChild(tooltip); 11 | 12 | setTimeout(() => { 13 | tooltip.className = 'tooltip tooltip-hide'; 14 | }, 1500); 15 | 16 | setTimeout(() => { 17 | e.removeChild(tooltip); 18 | }, 2000); 19 | } 20 | 21 | function hyphenateCSS(input) { 22 | if (input === 'cssFloat') { 23 | return 'float'; 24 | } 25 | 26 | return input.replace(/[A-Z]/g, (match) => '-' + match.toLowerCase() ); 27 | } 28 | 29 | function copyPropertyToClipboard(e, property) { 30 | const cb_prop = document.querySelector('#prop'); 31 | const cb_color = document.querySelector('#color-code'); 32 | 33 | const cb_hex = document.querySelector('#hex'); 34 | const cb_rgb = document.querySelector('#rgb'); 35 | const cb_hsl = document.querySelector('#hsl'); 36 | 37 | let copiedText = ''; 38 | 39 | if (cb_prop?.checked) { 40 | copiedText = e.style[property]; 41 | } 42 | 43 | if (cb_color?.checked) { 44 | let rgb = window 45 | .getComputedStyle(e) 46 | .getPropertyValue(hyphenateCSS(property)); 47 | 48 | if (cb_rgb?.checked) { 49 | copiedText = rgb; 50 | } 51 | 52 | rgb = rgb.match(/\d+/g); 53 | const r = parseInt(rgb[0]), g = parseInt(rgb[1]), b = parseInt(rgb[2]); 54 | if (cb_hex?.checked) { 55 | copiedText = RGBToHex(r, g, b); 56 | } 57 | 58 | if (cb_hsl?.checked) { 59 | copiedText = RGBToHSL(r, g, b); 60 | } 61 | } 62 | 63 | if (copiedText === '') 64 | return; 65 | 66 | navigator.clipboard.writeText(copiedText); 67 | return copiedText; 68 | } 69 | 70 | function attachCopyEvent(query, property) { 71 | const elements = document.querySelectorAll(query); 72 | 73 | elements.forEach((element) => { 74 | element.addEventListener('click', function (e) { 75 | const copiedText = copyPropertyToClipboard(e.target, property); 76 | addTooltip(e.target, copiedText); 77 | }); 78 | }); 79 | } 80 | 81 | function selectCopyFormat() { 82 | const cb_prop = document.querySelector('#prop'); 83 | const color_format_inputs = document.querySelectorAll( 84 | 'input[name="color-format"]' 85 | ); 86 | 87 | if (cb_prop?.checked) { 88 | color_format_inputs.forEach((input) => { 89 | input.disabled = true; 90 | }); 91 | } else { 92 | color_format_inputs.forEach((input) => { 93 | input.disabled = false; 94 | }); 95 | } 96 | } 97 | 98 | function attachSelectCopyFormat() { 99 | const cb_prop = document.querySelector('#prop'); 100 | const cb_color = document.querySelector('#color-code'); 101 | 102 | cb_prop?.addEventListener('change', selectCopyFormat); 103 | cb_color?.addEventListener('change', selectCopyFormat); 104 | } 105 | 106 | function initializeCopy() { 107 | attachCopyEvent('.color-swatch', 'backgroundColor'); 108 | attachSelectCopyFormat(); 109 | 110 | document.querySelectorAll('.color-swatch-list').forEach((list) => { 111 | rovingIndex({element: list, target: 'button'}); 112 | }); 113 | } 114 | 115 | document.addEventListener('DOMContentLoaded', initializeCopy); 116 | -------------------------------------------------------------------------------- /docsite/js/easing.js: -------------------------------------------------------------------------------- 1 | // easing controls 2 | document 3 | .querySelectorAll('.animation-control-header > button') 4 | .forEach(button => { 5 | button.addEventListener('click', e => { 6 | e.currentTarget 7 | .closest('div') 8 | .querySelector('.ease-demo') 9 | .classList.toggle('paused') 10 | }) 11 | }) 12 | 13 | export const toggleIcons = button => { 14 | button 15 | .querySelectorAll('use') 16 | .forEach(icon => { 17 | icon.classList.toggle('hidden') 18 | }) 19 | } 20 | 21 | export const showPlayIcon = button => { 22 | button 23 | .querySelectorAll('use') 24 | .forEach(icon => { 25 | if (icon.getAttribute('href') === '#play-icon') { 26 | icon.classList.remove('hidden') 27 | } else { 28 | icon.classList.add('hidden'); 29 | } 30 | }) 31 | } 32 | 33 | // play buttons 34 | document 35 | .querySelectorAll('.play-button') 36 | .forEach(button => { 37 | button.addEventListener('click', e => { 38 | toggleIcons(e.currentTarget) 39 | }) 40 | }) -------------------------------------------------------------------------------- /docsite/js/scrollspy.js: -------------------------------------------------------------------------------- 1 | let containers = []; 2 | let linkMap = {}; 3 | let matches = new Set(); 4 | const scrollNavLinkSelector = '#scroll-nav li a'; 5 | 6 | // Find out what the IDs are for the parent containers 7 | // =>
8 | for(let link of document.querySelectorAll(scrollNavLinkSelector)) { 9 | const containerId = link.href.replace(`${location.origin}/`, ''); 10 | const container = document.querySelector(containerId); 11 | containers = [...containers, container]; 12 | linkMap[containerId] = document.querySelector(`a[href="${containerId}"]`); 13 | } 14 | 15 | let observer = new IntersectionObserver(entries => { 16 | for(let entry of entries) { 17 | // Get the id of the container 18 | const id = entry.target.id; 19 | // Find it's corresponding link 20 | const link = linkMap[`#` + id]; 21 | // Highlight the link of the intersecting container 22 | // and remove any existing containers 23 | if(entry.isIntersecting) { 24 | link.classList.add('in-view') 25 | for (let match of matches) { 26 | const matchedLink = linkMap[`#${match}`]; 27 | matchedLink.classList.remove('in-view') 28 | matches.delete(id); 29 | } 30 | matches.add(id); 31 | } else { 32 | // Delete entries once they no longer intersect 33 | link.classList.remove('in-view') 34 | matches.delete(id); 35 | } 36 | } 37 | // Set a threshold of 10% of the target's visibility to trigger the 38 | // observer's callback. This will trigger the new section faster and 39 | // help keep multiple sections highlighted. 40 | }, { threshold: .1 }); 41 | 42 | for (let container of containers) { 43 | observer.observe(container); 44 | } -------------------------------------------------------------------------------- /docsite/js/select.js: -------------------------------------------------------------------------------- 1 | const selects = document.querySelectorAll('select') 2 | 3 | selects.forEach(select => { 4 | select.addEventListener('change', e => { 5 | 6 | let value = e.target.value 7 | 8 | let sizes = select 9 | .closest('.relative-sizes-demo') 10 | .querySelector('.sizes-demo') 11 | .children 12 | 13 | for (let i = 0; i < sizes.length; i++) { 14 | let size = sizes[i]; 15 | size.style.fontSize = `var(--font-size-${value})`; 16 | } 17 | }) 18 | }) 19 | 20 | -------------------------------------------------------------------------------- /docsite/js/slider.js: -------------------------------------------------------------------------------- 1 | const sliders = document.querySelectorAll('input[type="range"]') 2 | 3 | const rangeToPercent = slider => { 4 | let percent 5 | let val = slider.value 6 | let max = slider.max 7 | 8 | if (slider.min === '-1' && (val === '-1' || val === '0')) 9 | percent = (val+1) / max * 100 10 | else if (slider.min === '-1' && val === '1') 11 | percent = val / (max-2) * 100 12 | else 13 | percent = val / max * 100 14 | 15 | return `${parseInt(percent)}%` 16 | } 17 | 18 | const highlightProperty = slider => { 19 | if (slider.connectedProperty) 20 | slider.connectedProperty.classList.remove('slider-target') 21 | 22 | let offset = parseInt(slider.value) 23 | 24 | if (slider.min === '1') offset -= 1 25 | if (slider.min === '-1') offset += 1 26 | 27 | slider.connectedProperty = slider.parentElement.parentElement 28 | .querySelectorAll(`code > .property`)[offset] 29 | slider.connectedProperty.classList.add('slider-target') 30 | } 31 | 32 | sliders.forEach(slider => { 33 | slider.style.setProperty('--track-fill', rangeToPercent(slider)) 34 | // todo: wait for prism to tokenize code blocks 35 | // or figure out how to prerender prism blocks 36 | // highlightProperty(slider) 37 | 38 | slider.addEventListener('input', e => { 39 | slider.style.setProperty('--track-fill', rangeToPercent(slider)) 40 | 41 | let value = slider.value 42 | if (value === '-1') value = '00' 43 | 44 | slider 45 | .parentElement.querySelector('.sample-text') 46 | .style[slider.dataset.prop] = `var(--font-${slider.name}-${value})` 47 | 48 | highlightProperty(slider) 49 | }) 50 | }) -------------------------------------------------------------------------------- /docsite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-props", 3 | "author": "Adam Argyle", 4 | "browserslist": [ 5 | "defaults" 6 | ], 7 | "scripts": { 8 | "start": "vite", 9 | "dev": "vite", 10 | "build": "vite build", 11 | "serve": "vite preview" 12 | }, 13 | "devDependencies": { 14 | "postcss-preset-env": "10.1.5", 15 | "vite": "6.2.5" 16 | }, 17 | "dependencies": { 18 | "roving-ux": "^1.0.5" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docsite/postcss.config.js: -------------------------------------------------------------------------------- 1 | const postcssPresetEnv = require('postcss-preset-env') 2 | 3 | module.exports = { 4 | plugins: [ 5 | postcssPresetEnv({ 6 | stage: 0, 7 | autoprefixer: false, 8 | features: { 9 | 'logical-properties-and-values': false, 10 | 'prefers-color-scheme-query': false, 11 | 'gap-properties': false, 12 | 'custom-properties': false, 13 | 'place-properties': false, 14 | 'not-pseudo-class': false, 15 | 'focus-visible-pseudo-class': false, 16 | 'focus-within-pseudo-class': false, 17 | 'color-functional-notation': false 18 | } 19 | }), 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /docsite/public/adaptive-buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/adaptive-buttons.png -------------------------------------------------------------------------------- /docsite/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/apple-touch-icon.png -------------------------------------------------------------------------------- /docsite/public/cards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/cards.png -------------------------------------------------------------------------------- /docsite/public/color-schemes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/color-schemes.png -------------------------------------------------------------------------------- /docsite/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/favicon.ico -------------------------------------------------------------------------------- /docsite/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /docsite/public/hero-layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/hero-layout.png -------------------------------------------------------------------------------- /docsite/public/icon-192-maskable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/icon-192-maskable.png -------------------------------------------------------------------------------- /docsite/public/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/icon-192.png -------------------------------------------------------------------------------- /docsite/public/icon-512-maskable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/icon-512-maskable.png -------------------------------------------------------------------------------- /docsite/public/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/icon-512.png -------------------------------------------------------------------------------- /docsite/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "OpenProps", 3 | "name": "Open Props CSS", 4 | "description": "Supercharged CSS variables", 5 | "scope": "/", 6 | "start_url": "/?source=pwa", 7 | "background_color": "#3B5BDB", 8 | "theme_color": "#5C7CFA", 9 | "display": "standalone", 10 | "icons": [ 11 | { "src": "/favicon.ico", "type": "image/x-icon", "sizes": "32x32" }, 12 | { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" }, 13 | { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }, 14 | { "src": "/icon-192-maskable.png", "type": "image/png", "sizes": "192x192", "purpose": "maskable" }, 15 | { "src": "/icon-512-maskable.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" } 16 | ] 17 | } -------------------------------------------------------------------------------- /docsite/public/normalize-codepen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/normalize-codepen.png -------------------------------------------------------------------------------- /docsite/public/open-props-social.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/open-props-social.jpg -------------------------------------------------------------------------------- /docsite/public/pagination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/pagination.png -------------------------------------------------------------------------------- /docsite/public/pop-animation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/pop-animation.png -------------------------------------------------------------------------------- /docsite/public/theme-switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argyleink/open-props/6dfb2c91712e0b09580e2ef150759788b80eafa6/docsite/public/theme-switch.png -------------------------------------------------------------------------------- /docsite/public/theme-toggle.js: -------------------------------------------------------------------------------- 1 | // theme toggle 2 | const getColorPreference = () => { 3 | if (localStorage.getItem('theme-preference')) 4 | return localStorage.getItem('theme-preference') 5 | else 6 | return window.matchMedia('(prefers-color-scheme: dark)').matches 7 | ? 'dark' 8 | : 'light' 9 | } 10 | 11 | const setPreference = () => { 12 | localStorage.setItem('theme-preference', theme.value) 13 | reflectPreference() 14 | } 15 | 16 | const reflectPreference = () => { 17 | document.firstElementChild.setAttribute('data-theme', theme.value) 18 | document.querySelector('#theme-toggle')?.setAttribute('aria-label', theme.value) 19 | } 20 | 21 | const theme = { 22 | value: getColorPreference(), 23 | } 24 | 25 | // set early so no page flashes 26 | reflectPreference() 27 | 28 | window.onload = () => { 29 | // set on load so screen readers can see latest value on the button 30 | reflectPreference() 31 | 32 | document.querySelector('#theme-toggle').addEventListener('click', e => { 33 | theme.value = theme.value === 'light' 34 | ? 'dark' 35 | : 'light' 36 | 37 | setPreference() 38 | }) 39 | } 40 | 41 | window 42 | .matchMedia('(prefers-color-scheme: dark)') 43 | .addEventListener('change', ({matches:isDark}) => { 44 | theme.value = isDark ? 'dark' : 'light' 45 | setPreference() 46 | }) -------------------------------------------------------------------------------- /docsite/syntax-highlight.css: -------------------------------------------------------------------------------- 1 | :root :not(pre) > code[class*="language-"] { 2 | padding: var(--size-1) var(--size-2); 3 | box-shadow: var(--inner-shadow-0), var(--shadow-1); 4 | color: var(--text-1); 5 | white-space: nowrap; 6 | text-shadow: none; 7 | } 8 | 9 | code.language-bash::before { 10 | content: '$ '; 11 | color: var(--cyan-1); 12 | 13 | [data-theme="light"] & { 14 | color: var(--teal-6); 15 | } 16 | } 17 | 18 | code[class*="language-"], 19 | pre[class*="language-"] { 20 | text-align: start; 21 | white-space: pre; 22 | word-spacing: normal; 23 | word-break: normal; 24 | word-wrap: normal; 25 | line-height: 1.5; 26 | tab-size: 4; 27 | hyphens: none; 28 | } 29 | 30 | pre[class*="language-"] { 31 | padding-inline: var(--size-4); 32 | padding-block: var(--size-3); 33 | margin: var(--size-2) 0; 34 | overflow: auto; 35 | border-radius: var(--radius-conditional-2); 36 | border: var(--border-size-1) solid var(--surface-3); 37 | background: var(--surface-2); 38 | 39 | @media (--lg-n-above) { 40 | padding-inline: var(--size-5); 41 | padding-block: var(--size-4); 42 | } 43 | 44 | [data-theme="light"] & { 45 | background: white; 46 | } 47 | } 48 | 49 | code.language-css { 50 | color: var(--indigo-1); 51 | text-shadow: 52 | 0 0 10px var(--indigo-5), 53 | 0 0 25px var(--indigo-7); 54 | 55 | [data-theme="light"] & { 56 | color: var(--indigo-9); 57 | text-shadow: 0 0 15px var(--indigo-7); 58 | background: white; 59 | } 60 | 61 | @media (--HDcolor) { 62 | text-shadow: 0 0 15px color(display-p3 0 0 1); 63 | } 64 | } 65 | 66 | .token { 67 | &:is(.property, .atrule > *) { 68 | color: var(--text-1); 69 | text-shadow: 0 1px 0 var(--surface-1); 70 | 71 | [data-theme="light"] & { 72 | text-shadow: 0 1px 0 var(--gray-3); 73 | } 74 | } 75 | 76 | &.selector { 77 | color: var(--text-2); 78 | text-shadow: none; 79 | } 80 | 81 | &:is(.string, .attr-value) { 82 | color: var(--teal-0); 83 | text-shadow: 84 | 0 0 10px var(--teal-5), 85 | 0 0 25px var(--teal-7); 86 | 87 | [data-theme="light"] & { 88 | color: var(--purple-9); 89 | text-shadow: 0 0 15px var(--purple-9); 90 | } 91 | 92 | @media (--HDcolor) { 93 | text-shadow: 0 0 15px color(display-p3 0 1 0); 94 | } 95 | } 96 | 97 | &:is(.comment, .punctuation) { 98 | color: var(--gray-5); 99 | text-shadow: none; 100 | 101 | [data-theme="light"] & { 102 | color: var(--gray-6); 103 | } 104 | } 105 | 106 | &.slider-target { 107 | color: initial; 108 | 109 | &::before { 110 | content: '→'; 111 | opacity: 0; 112 | position: absolute; 113 | inset-inline-start: calc(var(--size-4) / 2 - .5ch); 114 | animation: 115 | var(--animation-slide-in-right) forwards, 116 | var(--animation-fade-in) forwards; 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "docsite/dist", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const postcssPresetEnv = require('postcss-preset-env') 2 | const postcssImport = require('postcss-import') 3 | const cssnano = require('cssnano') 4 | const combineSelectors = require('./build/postcss-combine-selectors.cjs') 5 | 6 | const lib = process.env.npm_lifecycle_event 7 | 8 | const inlineMediaQueries = lib === 'lib:media' || lib === 'lib:supports' 9 | // todo: inline MQs for 'lib:all' when it's supported better 10 | 11 | module.exports = { 12 | plugins: [ 13 | postcssImport(), 14 | postcssPresetEnv({ 15 | stage: 0, 16 | autoprefixer: false, 17 | features: { 18 | 'logical-properties-and-values': false, 19 | 'prefers-color-scheme-query': false, 20 | 'gap-properties': false, 21 | 'custom-properties': false, 22 | 'place-properties': false, 23 | 'not-pseudo-class': false, 24 | 'focus-visible-pseudo-class': false, 25 | 'focus-within-pseudo-class': false, 26 | 'color-functional-notation': false, 27 | 'custom-media-queries': {preserve:inlineMediaQueries}, 28 | 'double-position-gradients': false, 29 | } 30 | }), 31 | combineSelectors(), 32 | cssnano({ 33 | preset: 'default' 34 | }), 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ![Open Props Logo](https://user-images.githubusercontent.com/1134620/141246730-7df4cf2a-6249-42ca-a01b-494c3ccddabe.png) 4 | 5 | ## Open Source CSS Variables 6 | 7 | `colors` `gradients` `shadows` `aspect ratios` `typography` 8 | `easings` `animations` `sizes` `borders` `z-indexes` `media-queries` 9 | 10 | [![Tests](https://github.com/argyleink/open-props/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/argyleink/open-props/actions/workflows/tests.yml) 11 | [![npm version](http://img.shields.io/npm/v/open-props.svg)](https://npmjs.org/package/open-props) 12 | ![Discord](https://badgen.net/discord/members/AqA4fU886r) 13 | 14 |
15 | 16 | ### Need help?   👉   [Discord](https://discord.gg/AqA4fU886r) 17 | 18 |
19 | 20 |
21 | 22 | #### CDN ([browse](https://unpkg.com/browse/open-props@latest/)) 23 | - [https://unpkg.com/open-props](https://unpkg.com/open-props) 24 | - [https://unpkg.com/open-props/normalize.min.css](https://unpkg.com/open-props/normalize.min.css) - Normalize (light + dark) [demo](https://codepen.io/argyleink/pen/KKvRORE) 25 | - [https://unpkg.com/open-props/open-props.tokens.json](https://unpkg.com/open-props/open-props.tokens.json) - Design Tokens 26 | - [https://unpkg.com/open-props/open-props.figma-tokens.sync.json](https://unpkg.com/open-props/open-props.figma-tokens.sync.json) - Figma Design Tokens 27 | - [https://unpkg.com/open-props/open-props.style-dictionary-tokens.json](https://unpkg.com/open-props/open-props.style-dictionary-tokens.json) - Style Dictionary Tokens 28 | 29 | #### Bookmarklet 30 | 31 | ```js 32 | javascript: (() => { 33 | const href = "https://unpkg.com/open-props"; 34 | document.head.append(Object.assign(document.createElement("link"),{rel:"stylesheet",href})); 35 | })(); 36 | ``` 37 | 38 | #### CLI 39 | - `npm run gen:op` - runs through `src/` js files and creates the PostCSS files in `src/` 40 | - `npm run gen:nowhere` - creates a version of Open Props without the use of `:where()` 41 | - `npm run gen:shadowdom` - creates a version of Open Props with `:host` as the selector scope 42 | - `npm run gen:prefixed` - creates a version of Open Props with each prop prefixed with `op`, like `--op-font-size-1` 43 | - `npm run bundle` - creates all the various minified bundles of props 44 | - `npm run lib:js` - builds the JS modules for NPM 45 | -------------------------------------------------------------------------------- /src/extra/brand.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | /* --brand: your-brand-color-here; */ 3 | 4 | scrollbar-color: var(--scrollthumb-color) transparent; 5 | accent-color: var(--brand, var(--link)); 6 | caret-color: var(--brand, var(--link)); 7 | color: var(--text-1); 8 | background-color: var(--surface-1); 9 | } 10 | 11 | :where(a[href]) { 12 | color: var(--brand, var(--link)); 13 | 14 | &:where(:visited) { 15 | color: var(--link-visited); 16 | } 17 | } 18 | 19 | :focus-visible { 20 | outline-color: var(--brand, var(--link)); 21 | } 22 | -------------------------------------------------------------------------------- /src/extra/buttons.css: -------------------------------------------------------------------------------- 1 | @import "../props.media.css"; 2 | @import "../props.gray-hsl.css"; 3 | 4 | :where(.btn,button,input:is([type="button"],[type="submit"],[type="reset"])), 5 | :where(input[type="file"])::-webkit-file-upload-button, 6 | :where(input[type="file"])::file-selector-button { 7 | --_accent: initial /* your color */; 8 | --_text: initial /* your text color */; 9 | --_size: initial /* your size */; 10 | 11 | --_bg-light: white; 12 | --_bg-dark: var(--surface-3); 13 | --_bg: var(--_bg-light); 14 | 15 | --_border: var(--surface-3); 16 | 17 | --_highlight-size: 0; 18 | --_highlight-light: hsl(var(--gray-5-hsl) / 25%); 19 | --_highlight-dark: hsl(var(--gray-12-hsl) / 25%); 20 | --_highlight: var(--_highlight-light); 21 | 22 | --_ink-shadow-light: 0 1px 0 var(--gray-3); 23 | --_ink-shadow-dark: 0 1px 0 var(--surface-1); 24 | --_ink-shadow: var(--_ink-shadow-light); 25 | 26 | --_icon-size: var(--size-relative-7); 27 | --_icon-color: var(--_accent, var(--link)); 28 | 29 | font-size: var(--_size); 30 | background: var(--_bg); 31 | color: var(--_text); 32 | border: var(--border-size-2) solid var(--_border); 33 | box-shadow: 34 | var(--shadow-2), 35 | 0 1px var(--surface-3), 36 | 0 0 0 var(--_highlight-size) var(--_highlight) 37 | ; 38 | text-shadow: var(--_ink-shadow); 39 | 40 | display: inline-flex; 41 | justify-content: center; 42 | align-items: center; 43 | text-align: center; 44 | gap: var(--size-2); 45 | 46 | font-weight: var(--font-weight-7); 47 | border-radius: var(--radius-2); 48 | padding-block: .75ch; 49 | padding-inline: var(--size-relative-6); 50 | 51 | user-select: none; 52 | -webkit-tap-highlight-color: transparent; 53 | -webkit-touch-callout: none; 54 | 55 | transition: border-color .5s var(--ease-3); 56 | 57 | @media (--OSdark) { 58 | --_highlight: var(--_highlight-dark); 59 | --_bg: var(--_bg-dark); 60 | --_ink-shadow: var(--_ink-shadow-dark); 61 | } 62 | 63 | @media (--motionOK) { 64 | transition: 65 | border-color .5s var(--ease-3), 66 | box-shadow 145ms var(--ease-4), 67 | outline-offset 145ms var(--ease-4); 68 | } 69 | } 70 | 71 | :where(.btn,button,input:is([type="button"],[type="submit"],[type="reset"])) { 72 | /* disabled */ 73 | &[disabled] { 74 | --_bg: none; 75 | --_text: var(--gray-6); 76 | cursor: not-allowed; 77 | box-shadow: var(--shadow-1); 78 | 79 | @media (--OSdark) { 80 | --_text: var(--gray-5); 81 | } 82 | } 83 | 84 | /* pressing */ 85 | &:where(:not(:active):hover) { 86 | --_highlight-size: var(--size-2); 87 | transition-duration: .25s; 88 | } 89 | 90 | /* icons */ 91 | & > :where(svg) { 92 | flex-shrink: 0; 93 | filter: drop-shadow(var(--_ink-shadow)); 94 | block-size: var(--_icon-size); 95 | inline-size: var(--_icon-size); 96 | } 97 | 98 | & > :where(svg > *) { 99 | stroke: var(--_icon-color); 100 | stroke-width: var(--border-size-2); 101 | } 102 | } 103 | 104 | :where(.btn:is(a)) { 105 | text-decoration: none; 106 | } 107 | 108 | /* adaptive indigo text */ 109 | :where([type="submit"], form button:not([type],[disabled])) { 110 | --_text: var(--_accent, var(--link)); 111 | } 112 | 113 | /* red reset */ 114 | :where([type="reset"]) { 115 | --_text: var(--red-6); 116 | --_border: var(--red-3); 117 | 118 | &:focus-visible { 119 | outline-color: var(--red-6); 120 | } 121 | 122 | @media (--OSdark) { 123 | --_text: var(--red-2); 124 | --_border: var(--surface-3); 125 | } 126 | } 127 | 128 | /* submit, form > button, reset matching hover border color */ 129 | :where([type="submit"], [type="reset"], form button:not([type])):is(:hover, :focus-visible):not([disabled]) { 130 | --_border: currentColor; 131 | } 132 | 133 | /* file input */ 134 | :where(input[type="file"]) { 135 | max-inline-size: 100%; 136 | padding: 0; 137 | cursor: initial; 138 | align-self: flex-start; 139 | border-radius: var(--radius-2); 140 | border: var(--border-size-1) solid var(--surface-2); 141 | box-shadow: var(--inner-shadow-4); 142 | color: var(--text-2); 143 | } 144 | 145 | :where(input[type="file"])::-webkit-file-upload-button, 146 | :where(input[type="file"])::file-selector-button { 147 | margin-inline-end: var(--size-relative-6); 148 | cursor: pointer; 149 | } 150 | 151 | /* special dark theme styles */ 152 | @media (--OSdark) { 153 | :where([type="submit"]), 154 | :where(form button:not([type="button"])), 155 | :where([type="reset"]), 156 | :where([disabled]) { 157 | --_bg: var(--surface-1); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/extra/buttons.dark.css: -------------------------------------------------------------------------------- 1 | @import "../props.media.css"; 2 | @import "../props.gray-hsl.css"; 3 | 4 | :where(.btn,button,input:is([type="button"],[type="submit"],[type="reset"])), 5 | :where(input[type="file"])::-webkit-file-upload-button, 6 | :where(input[type="file"])::file-selector-button { 7 | --_accent: initial /* your color */; 8 | --_text: initial /* your text color */; 9 | --_size: initial /* your size */; 10 | 11 | --_bg: var(--surface-3); 12 | --_border: var(--surface-3); 13 | --_highlight-size: 0; 14 | --_highlight: hsl(var(--gray-12-hsl) / 25%); 15 | --_ink-shadow: 0 1px 0 var(--surface-1); 16 | 17 | --_icon-size: var(--size-relative-7); 18 | --_icon-color: var(--_accent, var(--link)); 19 | 20 | font-size: var(--_size); 21 | background: var(--_bg); 22 | color: var(--_text); 23 | border: var(--border-size-2) solid var(--_border); 24 | box-shadow: 25 | var(--shadow-2), 26 | 0 1px var(--surface-3), 27 | 0 0 0 var(--_highlight-size) var(--_highlight) 28 | ; 29 | text-shadow: var(--_ink-shadow); 30 | 31 | display: inline-flex; 32 | justify-content: center; 33 | align-items: center; 34 | text-align: center; 35 | gap: var(--size-2); 36 | 37 | font-weight: var(--font-weight-7); 38 | border-radius: var(--radius-2); 39 | padding-block: .75ch; 40 | padding-inline: var(--size-relative-6); 41 | 42 | user-select: none; 43 | -webkit-tap-highlight-color: transparent; 44 | -webkit-touch-callout: none; 45 | 46 | transition: border-color .5s var(--ease-3) 3s; 47 | 48 | @media (--motionOK) { 49 | transition: 50 | border-color .5s var(--ease-3) 3s, 51 | box-shadow 145ms var(--ease-4), 52 | outline-offset 145ms var(--ease-4); 53 | } 54 | } 55 | 56 | :where(.btn,button,input:is([type="button"],[type="submit"],[type="reset"])) { 57 | /* disabled */ 58 | &[disabled] { 59 | --_bg: none; 60 | --_text: var(--gray-5); 61 | cursor: not-allowed; 62 | box-shadow: var(--shadow-1); 63 | } 64 | 65 | /* pressing */ 66 | &:where(:not(:active):hover) { 67 | --_highlight-size: var(--size-2); 68 | transition-delay: 0s; 69 | transition-duration: .25s; 70 | } 71 | 72 | /* icons */ 73 | & > :where(svg) { 74 | flex-shrink: 0; 75 | filter: drop-shadow(var(--_ink-shadow)); 76 | block-size: var(--_icon-size); 77 | inline-size: var(--_icon-size); 78 | } 79 | 80 | & > :where(svg > *) { 81 | stroke: var(--_icon-color); 82 | stroke-width: var(--border-size-2); 83 | } 84 | } 85 | 86 | /* adaptive indigo text */ 87 | :where([type="submit"], form button:not([type],[disabled])) { 88 | --_text: var(--_accent, var(--link)); 89 | } 90 | 91 | /* red reset */ 92 | :where([type="reset"]) { 93 | --_text: var(--red-2); 94 | --_border: var(--surface-3); 95 | 96 | &:focus-visible { 97 | outline-color: var(--red-6); 98 | } 99 | } 100 | 101 | /* submit, form > button, reset matching hover border color */ 102 | :where([type="submit"], [type="reset"], form button:not([type])):is(:hover, :focus-visible):not([disabled]) { 103 | --_border: currentColor; 104 | } 105 | 106 | /* file input */ 107 | :where(input[type="file"]) { 108 | max-inline-size: 100%; 109 | padding: 0; 110 | cursor: initial; 111 | align-self: flex-start; 112 | border-radius: var(--radius-2); 113 | border: var(--border-size-1) solid var(--surface-2); 114 | box-shadow: var(--inner-shadow-4); 115 | color: var(--text-2); 116 | } 117 | 118 | :where(input[type="file"])::-webkit-file-upload-button, 119 | :where(input[type="file"])::file-selector-button { 120 | margin-inline-end: var(--size-relative-6); 121 | cursor: pointer; 122 | } 123 | 124 | /* special dark theme styles */ 125 | :where([type="submit"]), 126 | :where(form button:not([type="button"])), 127 | :where([type="reset"]), 128 | :where([disabled]) { 129 | --_bg: var(--surface-1); 130 | } 131 | -------------------------------------------------------------------------------- /src/extra/buttons.light.css: -------------------------------------------------------------------------------- 1 | @import "../props.media.css"; 2 | @import "../props.gray-hsl.css"; 3 | 4 | :where(.btn,button,input:is([type="button"],[type="submit"],[type="reset"])), 5 | :where(input[type="file"])::-webkit-file-upload-button, 6 | :where(input[type="file"])::file-selector-button { 7 | --_accent: initial /* your color */; 8 | --_text: initial /* your text color */; 9 | --_size: initial /* your size */; 10 | 11 | --_bg: white; 12 | --_border: var(--surface-3); 13 | 14 | --_highlight-size: 0; 15 | --_highlight: hsl(var(--gray-5-hsl) / 25%); 16 | 17 | --_ink-shadow: 0 1px 0 var(--gray-3); 18 | 19 | --_icon-size: var(--size-relative-7); 20 | --_icon-color: var(--_accent, var(--link)); 21 | 22 | font-size: var(--_size); 23 | background: var(--_bg); 24 | color: var(--_text); 25 | border: var(--border-size-2) solid var(--_border); 26 | box-shadow: 27 | var(--shadow-2), 28 | 0 1px var(--surface-3), 29 | 0 0 0 var(--_highlight-size) var(--_highlight) 30 | ; 31 | text-shadow: var(--_ink-shadow); 32 | 33 | display: inline-flex; 34 | justify-content: center; 35 | align-items: center; 36 | text-align: center; 37 | gap: var(--size-2); 38 | 39 | font-weight: var(--font-weight-7); 40 | border-radius: var(--radius-2); 41 | padding-block: .75ch; 42 | padding-inline: var(--size-relative-6); 43 | 44 | user-select: none; 45 | -webkit-tap-highlight-color: transparent; 46 | -webkit-touch-callout: none; 47 | 48 | transition: border-color .5s var(--ease-3) 3s; 49 | 50 | @media (--motionOK) { 51 | transition: 52 | border-color .5s var(--ease-3) 3s, 53 | box-shadow 145ms var(--ease-4), 54 | outline-offset 145ms var(--ease-4); 55 | } 56 | } 57 | 58 | :where(.btn,button,input:is([type="button"],[type="submit"],[type="reset"])) { 59 | /* disabled */ 60 | &[disabled] { 61 | --_bg: none; 62 | --_text: var(--gray-6); 63 | cursor: not-allowed; 64 | box-shadow: var(--shadow-1); 65 | } 66 | 67 | /* pressing */ 68 | &:where(:not(:active):hover) { 69 | --_highlight-size: var(--size-2); 70 | transition-delay: 0s; 71 | transition-duration: .25s; 72 | } 73 | 74 | /* icons */ 75 | & > :where(svg) { 76 | flex-shrink: 0; 77 | filter: drop-shadow(var(--_ink-shadow)); 78 | block-size: var(--_icon-size); 79 | inline-size: var(--_icon-size); 80 | } 81 | 82 | & > :where(svg > *) { 83 | stroke: var(--_icon-color); 84 | stroke-width: var(--border-size-2); 85 | } 86 | } 87 | 88 | /* adaptive indigo text */ 89 | :where([type="submit"], form button:not([type],[disabled])) { 90 | --_text: var(--_accent, var(--link)); 91 | } 92 | 93 | /* red reset */ 94 | :where([type="reset"]) { 95 | --_text: var(--red-6); 96 | --_border: var(--red-3); 97 | 98 | &:focus-visible { 99 | outline-color: var(--red-6); 100 | } 101 | } 102 | 103 | /* submit, form > button, reset matching hover border color */ 104 | :where([type="submit"], [type="reset"], form button:not([type])):is(:hover, :focus-visible):not([disabled]) { 105 | --_border: currentColor; 106 | } 107 | 108 | /* file input */ 109 | :where(input[type="file"]) { 110 | max-inline-size: 100%; 111 | padding: 0; 112 | cursor: initial; 113 | align-self: flex-start; 114 | border-radius: var(--radius-2); 115 | border: var(--border-size-1) solid var(--surface-2); 116 | box-shadow: var(--inner-shadow-4); 117 | color: var(--text-2); 118 | } 119 | 120 | :where(input[type="file"])::-webkit-file-upload-button, 121 | :where(input[type="file"])::file-selector-button { 122 | margin-inline-end: var(--size-relative-6); 123 | cursor: pointer; 124 | } 125 | -------------------------------------------------------------------------------- /src/extra/durations.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | 3 | /* Animation duration based on https://design.brainly.com/8adfd5f36/p/091f75-ux-motion */ 4 | --duration-instant: 0ms; /* e.g. text change */ 5 | --duration-quick-1: 80ms; /* e.g. checkbox, radio, hover */ 6 | --duration-quick-2: 120ms; /* e.g. toggle, tab, chip, color, fade */ 7 | --duration-moderate-1: 180ms; /* e.g. dropdown, tooltip */ 8 | --duration-moderate-2: 260ms; /* e.g. modal, toast, dialog, notification */ 9 | --duration-gentle-1: 320ms; /* e.g. bottom sheet, card expand */ 10 | --duration-gentle-2: 420ms; /* e.g. advanced animations */ 11 | 12 | /* 13 | * Calculated animation duration based on https://design.brainly.com/8adfd5f36/p/091f75-ux-motion/t/page-091f75-75547432-5018fa-12 14 | * Demo: https://codepen.io/T3sT3ro/pen/RNwRLWx 15 | * unitless 16 | */ 17 | --animated-element-distance: 0; 18 | --animated-element-width: 0; 19 | --animated-element-height: 0; 20 | 21 | /* Calculated animation duration in milliseconds */ 22 | --duration-calculated: calc(((0.5 * var(--animated-element-distance, 0)) + 23 | (0.35 * var(--animated-element-width, 0)) + 24 | (0.3 * var(--animated-element-height, 0))) * 1ms); 25 | 26 | /* Common time units */ 27 | --minute: 60s; 28 | --hour: calc( 60 * var(--minute)); 29 | --day: calc( 24 * var(--hour)); 30 | --week: calc( 7 * var(--day)); 31 | --fortnight: calc( 14 * var(--day)); 32 | --month: calc( 30 * var(--day)); 33 | --quarter: calc( 13 * var(--week)); 34 | --year: calc(365 * var(--day)); 35 | --leap-year: calc(366 * var(--day)); 36 | --olympiad: calc( 4 * var(--year)); 37 | --decade: calc( 10 * var(--year)); 38 | --generation: calc( 3 * var(--decade)); 39 | --lifetime: calc( 8 * var(--decade)); 40 | 41 | --work-day: calc( 8 * var(--hour)); 42 | --work-week: calc( 5 * var(--day)); 43 | 44 | --blink: .1s; 45 | --flinch: .3s 46 | --sneeze: .5s; 47 | --brief-moment: 15s; 48 | --pause: 10s; 49 | --unhealthy-pause: 30s; 50 | 51 | /* 52 | * https://en.wikipedia.org/wiki/List_of_unusual_units_of_measurement 53 | */ 54 | --moment: 90s; 55 | --kermit: calc(14.4 * var(--minute)); 56 | --microfortnight: 1.2096s; 57 | 58 | /* Approximate astronomical durations */ 59 | --sidereal-day: calc((23 * var(--hour)) + (56 * var(--minute)) + 4.091s); 60 | --iss-orbit: calc(91.5 * var(--minute)); 61 | --lunar-month: calc(29.5 * var(--day)); 62 | --venus-year: calc(225 * var(--day)); 63 | --sol: 88775s; 64 | --mars-year: calc(668.5907 * var(--sol)); 65 | 66 | /* 67 | * 10 Little-Known Units of Time 68 | * https://www.mentalfloss.com/article/60080/10-little-known-units-time 69 | */ 70 | --atom: .15957s; 71 | --ghurry: calc(24 * var(--minute)); 72 | --lustre: calc(5 * var(--year)); 73 | --mileway: calc(20 * var(--minute)); 74 | --nundine: calc(9 * var(--day)); 75 | --nychthemeron: var(--day); 76 | --punct: calc(15 * var(--minute)); 77 | --quadrant: calc(6 * var(--hour)); 78 | --quinzieme: calc(15 * var(--day)); 79 | --scruple: calc(24 * var(--minute)); 80 | 81 | /* 82 | * The Potrzebie System of Weights and Measures 83 | * https://madcoversite.com/mad033-36.html 84 | * https://webmadness.net/resources/The-Potrzebie-system-of-weights-and-measures.pdf 85 | * 86 | * There is an inconsistency in the definitions where 1 wolverton = 0.00001 clarke. 87 | * Calculating fractions of clarkes suggests that a 1 wolverton = 0.00000001 clarke. 88 | */ 89 | --clarke: var(--sidereal-day); 90 | --wood: calc(0.1 * var(--clarke)); 91 | --martin: calc(0.01 * var(--wood)); 92 | --kovac: calc(0.01 * var(--martin)); 93 | --wolverton: calc(0.001 * var(--kovac)); 94 | --mingo: calc(10 * var(--clarke)); 95 | --cowznofski: calc(10 * var(--mingo)); 96 | 97 | /* 98 | * https://en.wikipedia.org/wiki/List_of_humorous_units_of_measurement 99 | */ 100 | --friedman: calc(6 * var(--month)); 101 | --jiffy: 0.01s; 102 | --microcentury: calc((52 * var(--minute)) + 35.7s); 103 | --nanocentury: 3.156s; 104 | --scaramucci: calc(11 * var(--day)); 105 | } 106 | -------------------------------------------------------------------------------- /src/extra/normalize.css: -------------------------------------------------------------------------------- 1 | @import "theme.css"; 2 | @import "brand.css"; 3 | @import "normalize.src.css"; 4 | 5 | @media (--OSdark) { 6 | :where(textarea, select, input:not([type="button"],[type="submit"],[type="reset"])) { 7 | background-color: hsl(210 11% 10%); 8 | } 9 | 10 | :where(dialog) { 11 | background-color: var(--surface-2); 12 | } 13 | 14 | :where(html) { 15 | --shadow-strength: 10%; 16 | --shadow-color: 220 40% 2%; 17 | } 18 | 19 | ::placeholder { 20 | color: var(--gray-6); 21 | } 22 | } -------------------------------------------------------------------------------- /src/extra/normalize.dark.css: -------------------------------------------------------------------------------- 1 | @import "theme.dark.css"; 2 | @import "brand.css"; 3 | @import "normalize.src.css"; 4 | 5 | :where(textarea, select, input:not([type="button"],[type="submit"],[type="reset"])) { 6 | background-color: var(--gray-10); 7 | } 8 | 9 | :where(dialog) { 10 | background-color: var(--surface-2); 11 | } 12 | 13 | :where(html) { 14 | --shadow-strength: 10%; 15 | --shadow-color: 220 40% 2%; 16 | --inner-shadow-highlight: inset 0 -.5px 0 0 #fff1, inset 0 .5px 0 0 #0007; 17 | } 18 | 19 | ::placeholder { 20 | color: var(--gray-6); 21 | opacity: .75; 22 | } -------------------------------------------------------------------------------- /src/extra/normalize.light.css: -------------------------------------------------------------------------------- 1 | @import "theme.light.css"; 2 | @import "brand.css"; 3 | @import "normalize.src.css"; 4 | 5 | :where(html) { 6 | --shadow-color: 220 3% 15%; 7 | --shadow-strength: 1%; 8 | --inner-shadow-highlight: inset 0 -.5px 0 0 #fff, inset 0 .5px 0 0 #0001; 9 | } -------------------------------------------------------------------------------- /src/extra/theme.css: -------------------------------------------------------------------------------- 1 | @import "../props.media.css"; 2 | @import "theme.light.css"; 3 | 4 | @media (--OSdark) { 5 | :where(html) { 6 | color-scheme: dark; 7 | 8 | --link: var(--indigo-3); 9 | --link-visited: var(--purple-3); 10 | 11 | --text-1: var(--gray-1); 12 | --text-2: var(--gray-4); 13 | 14 | --surface-1: var(--gray-9); 15 | --surface-2: var(--gray-8); 16 | --surface-3: var(--gray-7); 17 | --surface-4: var(--gray-6); 18 | 19 | --scrollthumb-color: var(--gray-6); 20 | } 21 | } -------------------------------------------------------------------------------- /src/extra/theme.dark.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | color-scheme: dark; 3 | 4 | --link: var(--indigo-3); 5 | --link-visited: var(--purple-3); 6 | 7 | --text-1: var(--gray-0); 8 | --text-2: var(--gray-4); 9 | 10 | --surface-1: var(--gray-9); 11 | --surface-2: var(--gray-8); 12 | --surface-3: var(--gray-7); 13 | --surface-4: var(--gray-6); 14 | 15 | --scrollthumb-color: var(--gray-6); 16 | 17 | & :where(dialog) { 18 | background-color: var(--surface-2); 19 | } 20 | 21 | & :where(button,.btn) { 22 | --_highlight: var(--_highlight-dark); 23 | --_bg: var(--_bg-dark); 24 | --_ink-shadow: var(--_ink-shadow-dark); 25 | 26 | &:where([type="reset"]) { 27 | --_text: var(--red-2); 28 | --_border: var(--surface-3); 29 | } 30 | } 31 | 32 | & :where(button,.btn,input:is([type="button"],[type="submit"],[type="reset"]))[disabled] { 33 | --_text: var(--gray-5); 34 | } 35 | 36 | & :where(textarea, select, input:not([type="button"],[type="submit"],[type="reset"])) { 37 | background-color: hsl(210deg 11% 10%); 38 | } 39 | 40 | & :where([type="submit"]), 41 | & :where(form button:not([type="button"])), 42 | & :where([type="reset"]), 43 | & :where([disabled]) { 44 | --_bg: var(--surface-1); 45 | } 46 | } -------------------------------------------------------------------------------- /src/extra/theme.dark.switch.css: -------------------------------------------------------------------------------- 1 | @import "../props.media.css"; 2 | 3 | :where( 4 | [data-theme="dark"], 5 | .dark, 6 | .dark-theme 7 | ) { 8 | color-scheme: dark; 9 | 10 | --link: var(--indigo-3); 11 | --link-visited: var(--purple-3); 12 | 13 | --text-1: var(--gray-0); 14 | --text-2: var(--gray-4); 15 | 16 | --surface-1: var(--gray-9); 17 | --surface-2: var(--gray-8); 18 | --surface-3: var(--gray-7); 19 | --surface-4: var(--gray-6); 20 | 21 | --scrollthumb-color: var(--gray-6); 22 | --shadow-strength: 10%; 23 | --shadow-color: 220 40% 2%; 24 | --inner-shadow-highlight: inset 0 -.5px 0 0 #fff1, inset 0 .5px 0 0 #0007; 25 | 26 | & :where(dialog) { 27 | background-color: var(--surface-2); 28 | } 29 | 30 | & :where(button,.btn) { 31 | --_highlight: var(--_highlight-dark); 32 | --_bg: var(--_bg-dark); 33 | --_ink-shadow: var(--_ink-shadow-dark); 34 | 35 | &:where([type="reset"]) { 36 | --_text: var(--red-2); 37 | --_border: var(--surface-3); 38 | } 39 | } 40 | 41 | & :where(button,.btn,input:is([type="button"],[type="submit"],[type="reset"]))[disabled] { 42 | --_text: var(--gray-5); 43 | } 44 | 45 | & :where(textarea, select, input:not([type="button"],[type="submit"],[type="reset"])) { 46 | background-color: hsl(210deg 11% 10%); 47 | } 48 | 49 | & :where([type="submit"]), 50 | & :where(form button:not([type="button"])), 51 | & :where([type="reset"]), 52 | & :where([disabled]) { 53 | --_bg: var(--surface-1); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/extra/theme.light.css: -------------------------------------------------------------------------------- 1 | @import "../props.media.css"; 2 | 3 | :where(html) { 4 | color-scheme: light; 5 | 6 | --link: var(--indigo-7); 7 | --link-visited: var(--purple-7); 8 | 9 | --text-1: var(--gray-12); 10 | --text-2: var(--gray-7); 11 | 12 | --surface-1: var(--gray-0); 13 | --surface-2: var(--gray-2); 14 | --surface-3: var(--gray-3); 15 | --surface-4: var(--gray-4); 16 | 17 | --scrollthumb-color: var(--gray-7); 18 | 19 | @media (--HDcolor) { 20 | @supports (color: color(display-p3 0 0 0)) { 21 | --link: color(display-p3 .1 .39 1); 22 | --link-visited: color(display-p3 .6 .2 1); 23 | } 24 | } 25 | 26 | & :where(dialog) { 27 | background-color: var(--surface-1); 28 | } 29 | 30 | & :where(button,.btn) { 31 | --_highlight: var(--_highlight-light); 32 | --_bg: var(--_bg-light); 33 | --_ink-shadow: var(--_ink-shadow-light); 34 | 35 | & :where([type="reset"]) { 36 | --_text: var(--red-6); 37 | --_border: var(--red-3); 38 | } 39 | } 40 | 41 | & :where(button,.btn,input:is([type="button"],[type="submit"],[type="reset"]))[disabled] { 42 | --_text: var(--gray-6); 43 | } 44 | 45 | & :where(textarea, select, input:not([type="button"],[type="submit"],[type="reset"])) { 46 | background-color: var(--surface-2); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/extra/theme.light.switch.css: -------------------------------------------------------------------------------- 1 | @import "../props.media.css"; 2 | 3 | :where( 4 | [data-theme="light"], 5 | .light, 6 | .light-theme 7 | ) { 8 | color-scheme: light; 9 | 10 | --link: var(--indigo-7); 11 | --link-visited: var(--purple-7); 12 | 13 | --text-1: var(--gray-12); 14 | --text-2: var(--gray-7); 15 | 16 | --surface-1: var(--gray-0); 17 | --surface-2: var(--gray-2); 18 | --surface-3: var(--gray-3); 19 | --surface-4: var(--gray-4); 20 | 21 | --scrollthumb-color: var(--gray-7); 22 | --shadow-color: 220 3% 15%; 23 | --shadow-strength: 1%; 24 | --inner-shadow-highlight: inset 0 -.5px 0 0 #fff, inset 0 .5px 0 0 #0001; 25 | 26 | @media (--HDcolor) { 27 | @supports (color: color(display-p3 0 0 0)) { 28 | --link: color(display-p3 .1 .39 1); 29 | --link-visited: color(display-p3 .6 .2 1); 30 | } 31 | } 32 | 33 | & :where(dialog) { 34 | background-color: var(--surface-1); 35 | } 36 | 37 | & :where(button,.btn) { 38 | --_highlight: var(--_highlight-light); 39 | --_bg: var(--_bg-light); 40 | --_ink-shadow: var(--_ink-shadow-light); 41 | 42 | &:where([type="reset"]) { 43 | --_text: var(--red-6); 44 | --_border: var(--red-3); 45 | } 46 | } 47 | 48 | & :where(button,.btn,input:is([type="button"],[type="submit"],[type="reset"]))[disabled] { 49 | --_text: var(--gray-6); 50 | } 51 | 52 | & :where(textarea, select, input:not([type="button"],[type="submit"],[type="reset"])) { 53 | background-color: var(--surface-2); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/extra/utilities.css: -------------------------------------------------------------------------------- 1 | :is(.visually-hidden, .sr-only) { 2 | inline-size: 0; 3 | block-size: 0; 4 | overflow: hidden; 5 | } 6 | 7 | .border-between-inline > * + * { 8 | border-inline-start-width: var(--border); 9 | } 10 | 11 | .border-between-block > * + * { 12 | border-block-start-width: var(--border); 13 | } 14 | 15 | .gradient-border { 16 | border-width: var(--size-3); 17 | border-image-slice: 1; 18 | border-image-source: var(--conic-gradient-3); 19 | } 20 | 21 | .truncate { 22 | white-space: nowrap; 23 | overflow: hidden; 24 | text-overflow: ellipsis; 25 | } 26 | 27 | .fade-up-and-in { 28 | opacity: 0; 29 | animation: 30 | var(--animation-fade-in) forwards, 31 | var(--animation-slide-in-up) forwards; 32 | animation-delay: .3s, 0s; 33 | animation-duration: .7s, 1s; 34 | } -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import 'props.media.css'; 2 | @import 'props.fonts.css'; 3 | @import 'props.sizes.css'; 4 | @import 'props.easing.css'; 5 | @import 'props.zindex.css'; 6 | @import 'props.shadows.css'; 7 | @import 'props.aspects.css'; 8 | @import 'props.colors.css'; 9 | @import 'props.gradients.css'; 10 | @import 'props.animations.css'; 11 | @import 'props.borders.css'; 12 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Animations from './props.animations.js' 2 | import Sizes from './props.sizes.js' 3 | import Colors from './props.colors.js' 4 | import ColorsHSL from './props.colors-hsl.js' 5 | import Fonts from './props.fonts.js' 6 | import Borders from './props.borders.js' 7 | import Aspects from './props.aspects.js' 8 | import Easings from './props.easing.js' 9 | import Gradients from './props.gradients.js' 10 | import Shadows from './props.shadows.js' 11 | import SVG from './props.svg.js' 12 | import Zindex from './props.zindex.js' 13 | import MaskEdges from './props.masks.edges.js' 14 | import MaskCornerCuts from './props.masks.corner-cuts.js' 15 | 16 | const camelize = text => { 17 | text = text.replace(/[-]+(.)?/g, (_, c) => c 18 | ? c.toUpperCase() 19 | : '') 20 | return text.substr(0, 1).toLowerCase() + text.substr(1) 21 | } 22 | 23 | const mapToObjectNotation = props => { 24 | for (var prop in props) 25 | props[camelize(prop)] = props[prop] 26 | return props 27 | } 28 | 29 | const OpenProps = mapToObjectNotation({ 30 | ...Animations, 31 | ...Sizes, 32 | ...Colors, 33 | ...ColorsHSL, 34 | ...Fonts, 35 | ...Borders, 36 | ...Aspects, 37 | ...Easings, 38 | ...SVG, 39 | ...Gradients, 40 | ...Shadows, 41 | ...Zindex, 42 | ...MaskEdges, 43 | ...MaskCornerCuts, 44 | }) 45 | 46 | export default OpenProps -------------------------------------------------------------------------------- /src/props.animations.css: -------------------------------------------------------------------------------- 1 | @import 'props.media.css'; 2 | 3 | :where(html) { 4 | --animation-fade-in: fade-in .5s var(--ease-3); 5 | --animation-fade-in-bloom: fade-in-bloom 2s var(--ease-3); 6 | --animation-fade-out: fade-out .5s var(--ease-3); 7 | --animation-fade-out-bloom: fade-out-bloom 2s var(--ease-3); 8 | --animation-scale-up: scale-up .5s var(--ease-3); 9 | --animation-scale-down: scale-down .5s var(--ease-3); 10 | --animation-slide-out-up: slide-out-up .5s var(--ease-3); 11 | --animation-slide-out-down: slide-out-down .5s var(--ease-3); 12 | --animation-slide-out-right: slide-out-right .5s var(--ease-3); 13 | --animation-slide-out-left: slide-out-left .5s var(--ease-3); 14 | --animation-slide-in-up: slide-in-up .5s var(--ease-3); 15 | --animation-slide-in-down: slide-in-down .5s var(--ease-3); 16 | --animation-slide-in-right: slide-in-right .5s var(--ease-3); 17 | --animation-slide-in-left: slide-in-left .5s var(--ease-3); 18 | --animation-shake-x: shake-x .75s var(--ease-out-5); 19 | --animation-shake-y: shake-y .75s var(--ease-out-5); 20 | --animation-shake-z: shake-z 1s var(--ease-in-out-3); 21 | --animation-spin: spin 2s linear infinite; 22 | --animation-ping: ping 5s var(--ease-out-3) infinite; 23 | --animation-blink: blink 1s var(--ease-out-3) infinite; 24 | --animation-float: float 3s var(--ease-in-out-3) infinite; 25 | --animation-bounce: bounce 2s var(--ease-squish-2) infinite; 26 | --animation-pulse: pulse 2s var(--ease-out-3) infinite; 27 | } 28 | 29 | @keyframes fade-in { 30 | to { opacity: 1 } 31 | } 32 | @keyframes fade-in-bloom { 33 | 0% { opacity: 0; filter: brightness(1) blur(20px) } 34 | 10% { opacity: 1; filter: brightness(2) blur(10px) } 35 | 100% { opacity: 1; filter: brightness(1) blur(0) } 36 | } 37 | @keyframes fade-out { 38 | to { opacity: 0 } 39 | } 40 | @keyframes fade-out-bloom { 41 | 100% { opacity: 0; filter: brightness(1) blur(20px) } 42 | 10% { opacity: 1; filter: brightness(2) blur(10px) } 43 | 0% { opacity: 1; filter: brightness(1) blur(0) } 44 | } 45 | @keyframes scale-up { 46 | to { transform: scale(1.25) } 47 | } 48 | @keyframes scale-down { 49 | to { transform: scale(.75) } 50 | } 51 | @keyframes slide-out-up { 52 | to { transform: translateY(-100%) } 53 | } 54 | @keyframes slide-out-down { 55 | to { transform: translateY(100%) } 56 | } 57 | @keyframes slide-out-right { 58 | to { transform: translateX(100%) } 59 | } 60 | @keyframes slide-out-left { 61 | to { transform: translateX(-100%) } 62 | } 63 | @keyframes slide-in-up { 64 | from { transform: translateY(100%) } 65 | } 66 | @keyframes slide-in-down { 67 | from { transform: translateY(-100%) } 68 | } 69 | @keyframes slide-in-right { 70 | from { transform: translateX(-100%) } 71 | } 72 | @keyframes slide-in-left { 73 | from { transform: translateX(100%) } 74 | } 75 | @keyframes shake-x { 76 | 0%, 100% { transform: translateX(0%) } 77 | 20% { transform: translateX(-5%) } 78 | 40% { transform: translateX(5%) } 79 | 60% { transform: translateX(-5%) } 80 | 80% { transform: translateX(5%) } 81 | } 82 | @keyframes shake-y { 83 | 0%, 100% { transform: translateY(0%) } 84 | 20% { transform: translateY(-5%) } 85 | 40% { transform: translateY(5%) } 86 | 60% { transform: translateY(-5%) } 87 | 80% { transform: translateY(5%) } 88 | } 89 | @keyframes shake-z { 90 | 0%, 100% { transform: rotate(0deg) } 91 | 20% { transform: rotate(-2deg) } 92 | 40% { transform: rotate(2deg) } 93 | 60% { transform: rotate(-2deg) } 94 | 80% { transform: rotate(2deg) } 95 | } 96 | @keyframes spin { 97 | to { transform: rotate(1turn) } 98 | } 99 | @keyframes ping { 100 | 90%, 100% { 101 | transform: scale(2); 102 | opacity: 0; 103 | } 104 | } 105 | @keyframes blink { 106 | 0%, 100% { 107 | opacity: 1 108 | } 109 | 50% { 110 | opacity: .5 111 | } 112 | } 113 | @keyframes float { 114 | 50% { transform: translateY(-25%) } 115 | } 116 | @keyframes bounce { 117 | 25% { transform: translateY(-20%) } 118 | 40% { transform: translateY(-3%) } 119 | 0%, 60%, 100% { transform: translateY(0) } 120 | } 121 | @keyframes pulse { 122 | 50% { transform: scale(.9,.9) } 123 | } 124 | @media (--OSdark) { 125 | @keyframes fade-in-bloom { 126 | 0% { opacity: 0; filter: brightness(1) blur(20px) } 127 | 10% { opacity: 1; filter: brightness(0.5) blur(10px) } 128 | 100% { opacity: 1; filter: brightness(1) blur(0) } 129 | } 130 | } 131 | @media (--OSdark) { 132 | @keyframes fade-out-bloom { 133 | 100% { opacity: 0; filter: brightness(1) blur(20px) } 134 | 10% { opacity: 1; filter: brightness(0.5) blur(10px) } 135 | 0% { opacity: 1; filter: brightness(1) blur(0) } 136 | } 137 | } -------------------------------------------------------------------------------- /src/props.animations.js: -------------------------------------------------------------------------------- 1 | export default { 2 | "--animation-fade-in": "fade-in .5s var(--ease-3)", 3 | "--animation-fade-in-@": ` 4 | @keyframes fade-in { 5 | to { opacity: 1 } 6 | }`, 7 | "--animation-fade-in-bloom": "fade-in-bloom 2s var(--ease-3)", 8 | "--animation-fade-in-bloom-@": ` 9 | @keyframes fade-in-bloom { 10 | 0% { opacity: 0; filter: brightness(1) blur(20px) } 11 | 10% { opacity: 1; filter: brightness(2) blur(10px) } 12 | 100% { opacity: 1; filter: brightness(1) blur(0) } 13 | }`, 14 | "--animation-fade-in-bloom-@media:dark": ` 15 | @keyframes fade-in-bloom { 16 | 0% { opacity: 0; filter: brightness(1) blur(20px) } 17 | 10% { opacity: 1; filter: brightness(0.5) blur(10px) } 18 | 100% { opacity: 1; filter: brightness(1) blur(0) } 19 | }`, 20 | "--animation-fade-out": "fade-out .5s var(--ease-3)", 21 | "--animation-fade-out-@": ` 22 | @keyframes fade-out { 23 | to { opacity: 0 } 24 | }`, 25 | "--animation-fade-out-bloom": "fade-out-bloom 2s var(--ease-3)", 26 | "--animation-fade-out-bloom-@": ` 27 | @keyframes fade-out-bloom { 28 | 100% { opacity: 0; filter: brightness(1) blur(20px) } 29 | 10% { opacity: 1; filter: brightness(2) blur(10px) } 30 | 0% { opacity: 1; filter: brightness(1) blur(0) } 31 | }`, 32 | "--animation-fade-out-bloom-@media:dark": ` 33 | @keyframes fade-out-bloom { 34 | 100% { opacity: 0; filter: brightness(1) blur(20px) } 35 | 10% { opacity: 1; filter: brightness(0.5) blur(10px) } 36 | 0% { opacity: 1; filter: brightness(1) blur(0) } 37 | }`, 38 | "--animation-scale-up": "scale-up .5s var(--ease-3)", 39 | "--animation-scale-up-@": ` 40 | @keyframes scale-up { 41 | to { transform: scale(1.25) } 42 | }`, 43 | "--animation-scale-down": "scale-down .5s var(--ease-3)", 44 | "--animation-scale-down-@": ` 45 | @keyframes scale-down { 46 | to { transform: scale(.75) } 47 | }`, 48 | "--animation-slide-out-up": "slide-out-up .5s var(--ease-3)", 49 | "--animation-slide-out-up-@": ` 50 | @keyframes slide-out-up { 51 | to { transform: translateY(-100%) } 52 | }`, 53 | "--animation-slide-out-down": "slide-out-down .5s var(--ease-3)", 54 | "--animation-slide-out-down-@": ` 55 | @keyframes slide-out-down { 56 | to { transform: translateY(100%) } 57 | }`, 58 | "--animation-slide-out-right": "slide-out-right .5s var(--ease-3)", 59 | "--animation-slide-out-right-@": ` 60 | @keyframes slide-out-right { 61 | to { transform: translateX(100%) } 62 | }`, 63 | "--animation-slide-out-left": "slide-out-left .5s var(--ease-3)", 64 | "--animation-slide-out-left-@": ` 65 | @keyframes slide-out-left { 66 | to { transform: translateX(-100%) } 67 | }`, 68 | "--animation-slide-in-up": "slide-in-up .5s var(--ease-3)", 69 | "--animation-slide-in-up-@": ` 70 | @keyframes slide-in-up { 71 | from { transform: translateY(100%) } 72 | }`, 73 | "--animation-slide-in-down": "slide-in-down .5s var(--ease-3)", 74 | "--animation-slide-in-down-@": ` 75 | @keyframes slide-in-down { 76 | from { transform: translateY(-100%) } 77 | }`, 78 | "--animation-slide-in-right": "slide-in-right .5s var(--ease-3)", 79 | "--animation-slide-in-right-@": ` 80 | @keyframes slide-in-right { 81 | from { transform: translateX(-100%) } 82 | }`, 83 | "--animation-slide-in-left": "slide-in-left .5s var(--ease-3)", 84 | "--animation-slide-in-left-@": ` 85 | @keyframes slide-in-left { 86 | from { transform: translateX(100%) } 87 | }`, 88 | "--animation-shake-x": "shake-x .75s var(--ease-out-5)", 89 | "--animation-shake-x-@": ` 90 | @keyframes shake-x { 91 | 0%, 100% { transform: translateX(0%) } 92 | 20% { transform: translateX(-5%) } 93 | 40% { transform: translateX(5%) } 94 | 60% { transform: translateX(-5%) } 95 | 80% { transform: translateX(5%) } 96 | }`, 97 | "--animation-shake-y": "shake-y .75s var(--ease-out-5)", 98 | "--animation-shake-y-@": ` 99 | @keyframes shake-y { 100 | 0%, 100% { transform: translateY(0%) } 101 | 20% { transform: translateY(-5%) } 102 | 40% { transform: translateY(5%) } 103 | 60% { transform: translateY(-5%) } 104 | 80% { transform: translateY(5%) } 105 | }`, 106 | "--animation-shake-z": "shake-z 1s var(--ease-in-out-3)", 107 | "--animation-shake-z-@": ` 108 | @keyframes shake-z { 109 | 0%, 100% { transform: rotate(0deg) } 110 | 20% { transform: rotate(-2deg) } 111 | 40% { transform: rotate(2deg) } 112 | 60% { transform: rotate(-2deg) } 113 | 80% { transform: rotate(2deg) } 114 | }`, 115 | "--animation-spin": "spin 2s linear infinite", 116 | "--animation-spin-@": ` 117 | @keyframes spin { 118 | to { transform: rotate(1turn) } 119 | }`, 120 | "--animation-ping": "ping 5s var(--ease-out-3) infinite", 121 | "--animation-ping-@": ` 122 | @keyframes ping { 123 | 90%, 100% { 124 | transform: scale(2); 125 | opacity: 0; 126 | } 127 | }`, 128 | "--animation-blink": "blink 1s var(--ease-out-3) infinite", 129 | "--animation-blink-@": ` 130 | @keyframes blink { 131 | 0%, 100% { 132 | opacity: 1 133 | } 134 | 50% { 135 | opacity: .5 136 | } 137 | }`, 138 | "--animation-float": "float 3s var(--ease-in-out-3) infinite", 139 | "--animation-float-@": ` 140 | @keyframes float { 141 | 50% { transform: translateY(-25%) } 142 | }`, 143 | "--animation-bounce": "bounce 2s var(--ease-squish-2) infinite", 144 | "--animation-bounce-@": ` 145 | @keyframes bounce { 146 | 25% { transform: translateY(-20%) } 147 | 40% { transform: translateY(-3%) } 148 | 0%, 60%, 100% { transform: translateY(0) } 149 | }`, 150 | "--animation-pulse": "pulse 2s var(--ease-out-3) infinite", 151 | "--animation-pulse-@": ` 152 | @keyframes pulse { 153 | 50% { transform: scale(.9,.9) } 154 | }`, 155 | } 156 | -------------------------------------------------------------------------------- /src/props.aspects.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --ratio-square: 1; 3 | --ratio-landscape: 4/3; 4 | --ratio-portrait: 3/4; 5 | --ratio-widescreen: 16/9; 6 | --ratio-ultrawide: 18/5; 7 | --ratio-golden: 1.6180/1; 8 | } 9 | -------------------------------------------------------------------------------- /src/props.aspects.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--ratio-square': '1', 3 | '--ratio-landscape': '4/3', 4 | '--ratio-portrait': '3/4', 5 | '--ratio-widescreen': '16/9', 6 | '--ratio-ultrawide': '18/5', 7 | '--ratio-golden': '1.6180/1', 8 | } 9 | -------------------------------------------------------------------------------- /src/props.blue-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --blue-0-hsl: 205 100% 95%; 3 | --blue-1-hsl: 206 100% 91%; 4 | --blue-2-hsl: 206 100% 82%; 5 | --blue-3-hsl: 206 96% 72%; 6 | --blue-4-hsl: 207 91% 64%; 7 | --blue-5-hsl: 207 86% 57%; 8 | --blue-6-hsl: 208 80% 52%; 9 | --blue-7-hsl: 208 77% 47%; 10 | --blue-8-hsl: 209 77% 43%; 11 | --blue-9-hsl: 209 75% 38%; 12 | --blue-10-hsl: 209 76% 32%; 13 | --blue-11-hsl: 209 75% 27%; 14 | --blue-12-hsl: 209 76% 21%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.blue.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --blue-0: #e7f5ff; 3 | --blue-1: #d0ebff; 4 | --blue-2: #a5d8ff; 5 | --blue-3: #74c0fc; 6 | --blue-4: #4dabf7; 7 | --blue-5: #339af0; 8 | --blue-6: #228be6; 9 | --blue-7: #1c7ed6; 10 | --blue-8: #1971c2; 11 | --blue-9: #1864ab; 12 | --blue-10: #145591; 13 | --blue-11: #114678; 14 | --blue-12: #0d375e; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.borders.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --border-size-1: 1px; 3 | --border-size-2: 2px; 4 | --border-size-3: 5px; 5 | --border-size-4: 10px; 6 | --border-size-5: 25px; 7 | --radius-1: 2px; 8 | --radius-2: 5px; 9 | --radius-3: 1rem; 10 | --radius-4: 2rem; 11 | --radius-5: 4rem; 12 | --radius-6: 8rem; 13 | --radius-drawn-1: 255px 15px 225px 15px / 15px 225px 15px 255px; 14 | --radius-drawn-2: 125px 10px 20px 185px / 25px 205px 205px 25px; 15 | --radius-drawn-3: 15px 255px 15px 225px / 225px 15px 255px 15px; 16 | --radius-drawn-4: 15px 25px 155px 25px / 225px 150px 25px 115px; 17 | --radius-drawn-5: 250px 25px 15px 20px / 15px 80px 105px 115px; 18 | --radius-drawn-6: 28px 100px 20px 15px / 150px 30px 205px 225px; 19 | --radius-round: 1e5px; 20 | --radius-blob-1: 30% 70% 70% 30% / 53% 30% 70% 47%; 21 | --radius-blob-2: 53% 47% 34% 66% / 63% 46% 54% 37%; 22 | --radius-blob-3: 37% 63% 56% 44% / 49% 56% 44% 51%; 23 | --radius-blob-4: 63% 37% 37% 63% / 43% 37% 63% 57%; 24 | --radius-blob-5: 49% 51% 48% 52% / 57% 44% 56% 43%; 25 | --radius-conditional-1: clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-1)); 26 | --radius-conditional-2: clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-2)); 27 | --radius-conditional-3: clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-3)); 28 | --radius-conditional-4: clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-4)); 29 | --radius-conditional-5: clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-5)); 30 | --radius-conditional-6: clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-6)); 31 | } 32 | -------------------------------------------------------------------------------- /src/props.borders.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--border-size-1': '1px', 3 | '--border-size-2': '2px', 4 | '--border-size-3': '5px', 5 | '--border-size-4': '10px', 6 | '--border-size-5': '25px', 7 | 8 | '--radius-1': '2px', 9 | '--radius-2': '5px', 10 | '--radius-3': '1rem', 11 | '--radius-4': '2rem', 12 | '--radius-5': '4rem', 13 | '--radius-6': '8rem', 14 | 15 | '--radius-drawn-1': '255px 15px 225px 15px / 15px 225px 15px 255px', 16 | '--radius-drawn-2': '125px 10px 20px 185px / 25px 205px 205px 25px', 17 | '--radius-drawn-3': '15px 255px 15px 225px / 225px 15px 255px 15px', 18 | '--radius-drawn-4': '15px 25px 155px 25px / 225px 150px 25px 115px', 19 | '--radius-drawn-5': '250px 25px 15px 20px / 15px 80px 105px 115px', 20 | '--radius-drawn-6': '28px 100px 20px 15px / 150px 30px 205px 225px', 21 | 22 | '--radius-round': '1e5px', 23 | '--radius-blob-1': '30% 70% 70% 30% / 53% 30% 70% 47%', 24 | '--radius-blob-2': '53% 47% 34% 66% / 63% 46% 54% 37%', 25 | '--radius-blob-3': '37% 63% 56% 44% / 49% 56% 44% 51%', 26 | '--radius-blob-4': '63% 37% 37% 63% / 43% 37% 63% 57%', 27 | '--radius-blob-5': '49% 51% 48% 52% / 57% 44% 56% 43%', 28 | 29 | '--radius-conditional-1': 'clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-1))', 30 | '--radius-conditional-2': 'clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-2))', 31 | '--radius-conditional-3': 'clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-3))', 32 | '--radius-conditional-4': 'clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-4))', 33 | '--radius-conditional-5': 'clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-5))', 34 | '--radius-conditional-6': 'clamp(0px, calc(100vw - 100%) * 1e5, var(--radius-6))', 35 | } 36 | -------------------------------------------------------------------------------- /src/props.brand-colors.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --brand-facebook: #0866FF; 3 | --brand-youtube: #FF0000; 4 | --brand-twitter: #469CF0; 5 | --brand-whatsapp: #25D366; 6 | --brand-instagram-yellow: #F8D648; 7 | --brand-instagram-red: #E93365; 8 | --brand-instagram-magenta: #D32DBF; 9 | --brand-instagram-blue: #611EF5; 10 | --brand-snapchat: #FFFC00; 11 | --brand-google-blue: #4285F4; 12 | --brand-google-red: #DB4437; 13 | --brand-google-yellow: #F4B400; 14 | --brand-google-green: #0F9D58; 15 | --brand-tiktok-razzmatazz: #FE2C55; 16 | --brand-tiktok-splash: #25F4EE; 17 | --brand-microsoft-red: #F25022; 18 | --brand-microsoft-green: #7FBA00; 19 | --brand-microsoft-blue: #00A4EF; 20 | --brand-microsoft-yellow: #FFB900; 21 | --brand-pinterest: #E60023; 22 | --brand-spotify: #1ED760; 23 | --brand-discord: #5865F2; 24 | --brand-telegram: #2AABEE; 25 | --brand-reddit: #FF4500; 26 | --brand-amazon: #232F3E; 27 | --brand-twitch: #9146FF; 28 | } 29 | -------------------------------------------------------------------------------- /src/props.brand-colors.js: -------------------------------------------------------------------------------- 1 | export default { 2 | // source: https://about.meta.com/brand/resources/facebook/logo/ 3 | '--brand-facebook': '#0866FF', 4 | // source: https://www.youtube.com/intl/ALL_in/howyoutubeworks/resources/brand-resources/#logos-icons-and-colors 5 | '--brand-youtube': '#FF0000', 6 | // source: https://about.twitter.com/content/dam/about-twitter/en/brand-toolkit/downloads/twitter-external-brand-guidelines-01272021.pdf 7 | '--brand-twitter': '#469CF0', 8 | // source: https://about.meta.com/brand/resources/whatsapp/whatsapp-brand/ 9 | '--brand-whatsapp': '#25D366', 10 | // source: https://about.meta.com/brand/resources/instagram/instagram-brand/ 11 | '--brand-instagram-yellow': '#F8D648', 12 | '--brand-instagram-red': '#E93365', 13 | '--brand-instagram-magenta': '#D32DBF', 14 | '--brand-instagram-blue': '#611EF5', 15 | // source: https://snap.com/en-US/brand-guidelines 16 | '--brand-snapchat': '#FFFC00', 17 | // source: https://usbrandcolors.com/google-colors/ 18 | '--brand-google-blue': '#4285F4', 19 | '--brand-google-red': '#DB4437', 20 | '--brand-google-yellow': '#F4B400', 21 | '--brand-google-green': '#0F9D58', 22 | // source: https://tiktokbrandbook.com/d/HhXfjVK1Poj9/brand-guidelines#/basics/color/core-palette 23 | '--brand-tiktok-razzmatazz': '#FE2C55', 24 | '--brand-tiktok-splash': '#25F4EE', 25 | // source: https://cdn-dynmedia-1.microsoft.com/is/content/microsoftcorp/microsoft/mscle/documents/presentations/CELA_ThirdPartyLogoGuidelines_June2021.pdf 26 | '--brand-microsoft-red': '#F25022', 27 | '--brand-microsoft-green': '#7FBA00', 28 | '--brand-microsoft-blue': '#00A4EF', 29 | '--brand-microsoft-yellow': '#FFB900', 30 | // source: https://usbrandcolors.com/pinterest-colors/ 31 | '--brand-pinterest': '#E60023', 32 | // source: https://developer.spotify.com/documentation/design#using-our-colors 33 | '--brand-spotify': '#1ED760', 34 | // source: https://discord.com/branding 35 | '--brand-discord': '#5865F2', 36 | // source: https://telegram.org/tour/screenshots 37 | '--brand-telegram': '#2AABEE', 38 | // source: https://reddit.lingoapp.com/s/Color-R7y72J/?v=22 39 | '--brand-reddit': '#FF4500', 40 | // source: none 41 | '--brand-amazon': '#232F3E', 42 | // source: https://brand.twitch.com/ 43 | '--brand-twitch': '#9146FF', 44 | } 45 | -------------------------------------------------------------------------------- /src/props.brown-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --brown-0-hsl: 36 60% 95%; 3 | --brown-1-hsl: 32 44% 87%; 4 | --brown-2-hsl: 28 40% 80%; 5 | --brown-3-hsl: 28 38% 72%; 6 | --brown-4-hsl: 27 36% 65%; 7 | --brown-5-hsl: 28 34% 57%; 8 | --brown-6-hsl: 28 32% 50%; 9 | --brown-7-hsl: 28 35% 43%; 10 | --brown-8-hsl: 28 38% 37%; 11 | --brown-9-hsl: 27 42% 31%; 12 | --brown-10-hsl: 25 48% 25%; 13 | --brown-11-hsl: 23 58% 19%; 14 | --brown-12-hsl: 22 57% 16%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.brown.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --brown-0: #faf4eb; 3 | --brown-1: #ede0d1; 4 | --brown-2: #e0cab7; 5 | --brown-3: #d3b79e; 6 | --brown-4: #c5a285; 7 | --brown-5: #b78f6d; 8 | --brown-6: #a87c56; 9 | --brown-7: #956b47; 10 | --brown-8: #825b3a; 11 | --brown-9: #6f4b2d; 12 | --brown-10: #5e3a21; 13 | --brown-11: #4e2b15; 14 | --brown-12: #422412; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.camo-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --camo-0-hsl: 66 71% 95%; 3 | --camo-1-hsl: 64 69% 77%; 4 | --camo-2-hsl: 65 69% 59%; 5 | --camo-3-hsl: 65 61% 51%; 6 | --camo-4-hsl: 63 61% 46%; 7 | --camo-5-hsl: 60 62% 41%; 8 | --camo-6-hsl: 59 65% 36%; 9 | --camo-7-hsl: 56 67% 33%; 10 | --camo-8-hsl: 54 70% 29%; 11 | --camo-9-hsl: 54 69% 25%; 12 | --camo-10-hsl: 53 69% 22%; 13 | --camo-11-hsl: 53 69% 18%; 14 | --camo-12-hsl: 52 69% 13%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.camo.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --camo-0: #f9fbe7; 3 | --camo-1: #e8ed9c; 4 | --camo-2: #d2df4e; 5 | --camo-3: #c2ce34; 6 | --camo-4: #b5bb2e; 7 | --camo-5: #a7a827; 8 | --camo-6: #999621; 9 | --camo-7: #8c851c; 10 | --camo-8: #7e7416; 11 | --camo-9: #6d6414; 12 | --camo-10: #5d5411; 13 | --camo-11: #4d460e; 14 | --camo-12: #36300a; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.choco-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --choco-0-hsl: 48 100% 93%; 3 | --choco-1-hsl: 35 91% 86%; 4 | --choco-2-hsl: 30 85% 79%; 5 | --choco-3-hsl: 27 80% 72%; 6 | --choco-4-hsl: 25 75% 65%; 7 | --choco-5-hsl: 25 71% 57%; 8 | --choco-6-hsl: 25 70% 49%; 9 | --choco-7-hsl: 25 75% 42%; 10 | --choco-8-hsl: 25 75% 37%; 11 | --choco-9-hsl: 25 76% 31%; 12 | --choco-10-hsl: 25 71% 26%; 13 | --choco-11-hsl: 25 66% 21%; 14 | --choco-12-hsl: 25 65% 15%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.choco.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --choco-0: #fff8dc; 3 | --choco-1: #fce1bc; 4 | --choco-2: #f7ca9e; 5 | --choco-3: #f1b280; 6 | --choco-4: #e99b62; 7 | --choco-5: #df8545; 8 | --choco-6: #d46e25; 9 | --choco-7: #bd5f1b; 10 | --choco-8: #a45117; 11 | --choco-9: #8a4513; 12 | --choco-10: #703a13; 13 | --choco-11: #572f12; 14 | --choco-12: #3d210d; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.colors-oklch-hues.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --hue-red: 25; 3 | --hue-pink: 350; 4 | --hue-purple: 310; 5 | --hue-violet: 290; 6 | --hue-indigo: 270; 7 | --hue-blue: 240; 8 | --hue-cyan: 210; 9 | --hue-teal: 185; 10 | --hue-green: 145; 11 | --hue-lime: 125; 12 | --hue-yellow: 100; 13 | --hue-orange: 75; 14 | } 15 | -------------------------------------------------------------------------------- /src/props.colors-oklch-hues.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--hue-red': 25, 3 | '--hue-pink': 350, 4 | '--hue-purple': 310, 5 | '--hue-violet': 290, 6 | '--hue-indigo': 270, 7 | '--hue-blue': 240, 8 | '--hue-cyan': 210, 9 | '--hue-teal': 185, 10 | '--hue-green': 145, 11 | '--hue-lime': 125, 12 | '--hue-yellow': 100, 13 | '--hue-orange': 75, 14 | } 15 | -------------------------------------------------------------------------------- /src/props.colors-oklch.css: -------------------------------------------------------------------------------- 1 | :where(*) { 2 | --color-0: oklch(99% .03 var(--color-hue, 0)); 3 | --color-1: oklch(95% .06 var(--color-hue, 0)); 4 | --color-2: oklch(88% .12 var(--color-hue, 0)); 5 | --color-3: oklch(80% .14 var(--color-hue, 0)); 6 | --color-4: oklch(74% .16 var(--color-hue, 0)); 7 | --color-5: oklch(68% .19 var(--color-hue, 0)); 8 | --color-6: oklch(63% .20 var(--color-hue, 0)); 9 | --color-7: oklch(58% .21 var(--color-hue, 0)); 10 | --color-8: oklch(53% .20 var(--color-hue, 0)); 11 | --color-9: oklch(49% .19 var(--color-hue, 0)); 12 | --color-10: oklch(42% .17 var(--color-hue, 0)); 13 | --color-11: oklch(35% .15 var(--color-hue, 0)); 14 | --color-12: oklch(27% .12 var(--color-hue, 0)); 15 | --color-13: oklch(20% .09 var(--color-hue, 0)); 16 | --color-14: oklch(14% .07 var(--color-hue, 0)); 17 | --color-15: oklch(11% .05 var(--color-hue, 0)); 18 | --color-bright: oklch(65% .3 var(--color-hue, 0)); 19 | } 20 | -------------------------------------------------------------------------------- /src/props.colors-oklch.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--color-0': 'oklch(99% .03 var(--color-hue, 0))', 3 | '--color-1': 'oklch(95% .06 var(--color-hue, 0))', 4 | '--color-2': 'oklch(88% .12 var(--color-hue, 0))', 5 | '--color-3': 'oklch(80% .14 var(--color-hue, 0))', 6 | '--color-4': 'oklch(74% .16 var(--color-hue, 0))', 7 | '--color-5': 'oklch(68% .19 var(--color-hue, 0))', 8 | '--color-6': 'oklch(63% .20 var(--color-hue, 0))', 9 | '--color-7': 'oklch(58% .21 var(--color-hue, 0))', 10 | '--color-8': 'oklch(53% .20 var(--color-hue, 0))', 11 | '--color-9': 'oklch(49% .19 var(--color-hue, 0))', 12 | '--color-10': 'oklch(42% .17 var(--color-hue, 0))', 13 | '--color-11': 'oklch(35% .15 var(--color-hue, 0))', 14 | '--color-12': 'oklch(27% .12 var(--color-hue, 0))', 15 | '--color-13': 'oklch(20% .09 var(--color-hue, 0))', 16 | '--color-14': 'oklch(14% .07 var(--color-hue, 0))', 17 | '--color-15': 'oklch(11% .05 var(--color-hue, 0))', 18 | 19 | '--color-bright': 'oklch(65% .3 var(--color-hue, 0))', 20 | } 21 | -------------------------------------------------------------------------------- /src/props.colors.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --gray-0: #f8f9fa; 3 | --gray-1: #f1f3f5; 4 | --gray-2: #e9ecef; 5 | --gray-3: #dee2e6; 6 | --gray-4: #ced4da; 7 | --gray-5: #adb5bd; 8 | --gray-6: #868e96; 9 | --gray-7: #495057; 10 | --gray-8: #343a40; 11 | --gray-9: #212529; 12 | --gray-10: #16191d; 13 | --gray-11: #0d0f12; 14 | --gray-12: #030507; 15 | --stone-0: #f8fafb; 16 | --stone-1: #f2f4f6; 17 | --stone-2: #ebedef; 18 | --stone-3: #e0e4e5; 19 | --stone-4: #d1d6d8; 20 | --stone-5: #b1b6b9; 21 | --stone-6: #979b9d; 22 | --stone-7: #7e8282; 23 | --stone-8: #666968; 24 | --stone-9: #50514f; 25 | --stone-10: #3a3a37; 26 | --stone-11: #252521; 27 | --stone-12: #121210; 28 | --red-0: #fff5f5; 29 | --red-1: #ffe3e3; 30 | --red-2: #ffc9c9; 31 | --red-3: #ffa8a8; 32 | --red-4: #ff8787; 33 | --red-5: #ff6b6b; 34 | --red-6: #fa5252; 35 | --red-7: #f03e3e; 36 | --red-8: #e03131; 37 | --red-9: #c92a2a; 38 | --red-10: #b02525; 39 | --red-11: #962020; 40 | --red-12: #7d1a1a; 41 | --pink-0: #fff0f6; 42 | --pink-1: #ffdeeb; 43 | --pink-2: #fcc2d7; 44 | --pink-3: #faa2c1; 45 | --pink-4: #f783ac; 46 | --pink-5: #f06595; 47 | --pink-6: #e64980; 48 | --pink-7: #d6336c; 49 | --pink-8: #c2255c; 50 | --pink-9: #a61e4d; 51 | --pink-10: #8c1941; 52 | --pink-11: #731536; 53 | --pink-12: #59102a; 54 | --purple-0: #f8f0fc; 55 | --purple-1: #f3d9fa; 56 | --purple-2: #eebefa; 57 | --purple-3: #e599f7; 58 | --purple-4: #da77f2; 59 | --purple-5: #cc5de8; 60 | --purple-6: #be4bdb; 61 | --purple-7: #ae3ec9; 62 | --purple-8: #9c36b5; 63 | --purple-9: #862e9c; 64 | --purple-10: #702682; 65 | --purple-11: #5a1e69; 66 | --purple-12: #44174f; 67 | --violet-0: #f3f0ff; 68 | --violet-1: #e5dbff; 69 | --violet-2: #d0bfff; 70 | --violet-3: #b197fc; 71 | --violet-4: #9775fa; 72 | --violet-5: #845ef7; 73 | --violet-6: #7950f2; 74 | --violet-7: #7048e8; 75 | --violet-8: #6741d9; 76 | --violet-9: #5f3dc4; 77 | --violet-10: #5235ab; 78 | --violet-11: #462d91; 79 | --violet-12: #3a2578; 80 | --indigo-0: #edf2ff; 81 | --indigo-1: #dbe4ff; 82 | --indigo-2: #bac8ff; 83 | --indigo-3: #91a7ff; 84 | --indigo-4: #748ffc; 85 | --indigo-5: #5c7cfa; 86 | --indigo-6: #4c6ef5; 87 | --indigo-7: #4263eb; 88 | --indigo-8: #3b5bdb; 89 | --indigo-9: #364fc7; 90 | --indigo-10: #2f44ad; 91 | --indigo-11: #283a94; 92 | --indigo-12: #21307a; 93 | --blue-0: #e7f5ff; 94 | --blue-1: #d0ebff; 95 | --blue-2: #a5d8ff; 96 | --blue-3: #74c0fc; 97 | --blue-4: #4dabf7; 98 | --blue-5: #339af0; 99 | --blue-6: #228be6; 100 | --blue-7: #1c7ed6; 101 | --blue-8: #1971c2; 102 | --blue-9: #1864ab; 103 | --blue-10: #145591; 104 | --blue-11: #114678; 105 | --blue-12: #0d375e; 106 | --cyan-0: #e3fafc; 107 | --cyan-1: #c5f6fa; 108 | --cyan-2: #99e9f2; 109 | --cyan-3: #66d9e8; 110 | --cyan-4: #3bc9db; 111 | --cyan-5: #22b8cf; 112 | --cyan-6: #15aabf; 113 | --cyan-7: #1098ad; 114 | --cyan-8: #0c8599; 115 | --cyan-9: #0b7285; 116 | --cyan-10: #095c6b; 117 | --cyan-11: #074652; 118 | --cyan-12: #053038; 119 | --teal-0: #e6fcf5; 120 | --teal-1: #c3fae8; 121 | --teal-2: #96f2d7; 122 | --teal-3: #63e6be; 123 | --teal-4: #38d9a9; 124 | --teal-5: #20c997; 125 | --teal-6: #12b886; 126 | --teal-7: #0ca678; 127 | --teal-8: #099268; 128 | --teal-9: #087f5b; 129 | --teal-10: #066649; 130 | --teal-11: #054d37; 131 | --teal-12: #033325; 132 | --green-0: #ebfbee; 133 | --green-1: #d3f9d8; 134 | --green-2: #b2f2bb; 135 | --green-3: #8ce99a; 136 | --green-4: #69db7c; 137 | --green-5: #51cf66; 138 | --green-6: #40c057; 139 | --green-7: #37b24d; 140 | --green-8: #2f9e44; 141 | --green-9: #2b8a3e; 142 | --green-10: #237032; 143 | --green-11: #1b5727; 144 | --green-12: #133d1b; 145 | --lime-0: #f4fce3; 146 | --lime-1: #e9fac8; 147 | --lime-2: #d8f5a2; 148 | --lime-3: #c0eb75; 149 | --lime-4: #a9e34b; 150 | --lime-5: #94d82d; 151 | --lime-6: #82c91e; 152 | --lime-7: #74b816; 153 | --lime-8: #66a80f; 154 | --lime-9: #5c940d; 155 | --lime-10: #4c7a0b; 156 | --lime-11: #3c6109; 157 | --lime-12: #2c4706; 158 | --yellow-0: #fff9db; 159 | --yellow-1: #fff3bf; 160 | --yellow-2: #ffec99; 161 | --yellow-3: #ffe066; 162 | --yellow-4: #ffd43b; 163 | --yellow-5: #fcc419; 164 | --yellow-6: #fab005; 165 | --yellow-7: #f59f00; 166 | --yellow-8: #f08c00; 167 | --yellow-9: #e67700; 168 | --yellow-10: #b35c00; 169 | --yellow-11: #804200; 170 | --yellow-12: #663500; 171 | --orange-0: #fff4e6; 172 | --orange-1: #ffe8cc; 173 | --orange-2: #ffd8a8; 174 | --orange-3: #ffc078; 175 | --orange-4: #ffa94d; 176 | --orange-5: #ff922b; 177 | --orange-6: #fd7e14; 178 | --orange-7: #f76707; 179 | --orange-8: #e8590c; 180 | --orange-9: #d9480f; 181 | --orange-10: #bf400d; 182 | --orange-11: #99330b; 183 | --orange-12: #802b09; 184 | --choco-0: #fff8dc; 185 | --choco-1: #fce1bc; 186 | --choco-2: #f7ca9e; 187 | --choco-3: #f1b280; 188 | --choco-4: #e99b62; 189 | --choco-5: #df8545; 190 | --choco-6: #d46e25; 191 | --choco-7: #bd5f1b; 192 | --choco-8: #a45117; 193 | --choco-9: #8a4513; 194 | --choco-10: #703a13; 195 | --choco-11: #572f12; 196 | --choco-12: #3d210d; 197 | --brown-0: #faf4eb; 198 | --brown-1: #ede0d1; 199 | --brown-2: #e0cab7; 200 | --brown-3: #d3b79e; 201 | --brown-4: #c5a285; 202 | --brown-5: #b78f6d; 203 | --brown-6: #a87c56; 204 | --brown-7: #956b47; 205 | --brown-8: #825b3a; 206 | --brown-9: #6f4b2d; 207 | --brown-10: #5e3a21; 208 | --brown-11: #4e2b15; 209 | --brown-12: #422412; 210 | --sand-0: #f8fafb; 211 | --sand-1: #e6e4dc; 212 | --sand-2: #d5cfbd; 213 | --sand-3: #c2b9a0; 214 | --sand-4: #aea58c; 215 | --sand-5: #9a9178; 216 | --sand-6: #867c65; 217 | --sand-7: #736a53; 218 | --sand-8: #5f5746; 219 | --sand-9: #4b4639; 220 | --sand-10: #38352d; 221 | --sand-11: #252521; 222 | --sand-12: #121210; 223 | --camo-0: #f9fbe7; 224 | --camo-1: #e8ed9c; 225 | --camo-2: #d2df4e; 226 | --camo-3: #c2ce34; 227 | --camo-4: #b5bb2e; 228 | --camo-5: #a7a827; 229 | --camo-6: #999621; 230 | --camo-7: #8c851c; 231 | --camo-8: #7e7416; 232 | --camo-9: #6d6414; 233 | --camo-10: #5d5411; 234 | --camo-11: #4d460e; 235 | --camo-12: #36300a; 236 | --jungle-0: #ecfeb0; 237 | --jungle-1: #def39a; 238 | --jungle-2: #d0e884; 239 | --jungle-3: #c2dd6e; 240 | --jungle-4: #b5d15b; 241 | --jungle-5: #a8c648; 242 | --jungle-6: #9bbb36; 243 | --jungle-7: #8fb024; 244 | --jungle-8: #84a513; 245 | --jungle-9: #7a9908; 246 | --jungle-10: #658006; 247 | --jungle-11: #516605; 248 | --jungle-12: #3d4d04; 249 | } 250 | -------------------------------------------------------------------------------- /src/props.colors.src.js: -------------------------------------------------------------------------------- 1 | // Load `colar` and restructure 2 | // Result: colar.[hueName].[luminosityStep] => hexCode 3 | const colarURL = 4 | "https://raw.githubusercontent.com/fchristant/colar/master/colar/colar.json" 5 | const colar = (await (await fetch(colarURL)).json()).reduce( 6 | (root, { name, color }) => { 7 | let [hueName, luminosityStep] = name.split("-") 8 | 9 | hueName = hueName.toLowerCase() 10 | luminosityStep = parseInt(luminosityStep) 11 | 12 | const hue = root?.[hueName] ?? {} 13 | 14 | return { 15 | ...root, 16 | [hueName]: { ...hue, [luminosityStep]: color.toLowerCase() }, 17 | } 18 | }, 19 | {} 20 | ) 21 | 22 | // Load `open-color` and restructure 23 | // Result: openColor.[hueName].[luminosityStep] => hexCode 24 | const openColor = Object.entries( 25 | (await import("open-color/open-color.js")).default.theme.colors 26 | ) 27 | .filter((group) => typeof group[1] === "object") 28 | .reduce( 29 | (root, [hueName, luminosityStepsObject]) => ({ 30 | ...root, 31 | [hueName]: Object.fromEntries( 32 | Object.entries(luminosityStepsObject).map(([step, color]) => [ 33 | step.replace("00", "").replace("50", "0"), 34 | color, 35 | ]) 36 | ), 37 | }), 38 | {} 39 | ) 40 | 41 | // Combine `open-color` and `colar` palettes 42 | const colors = Object.entries({ 43 | // Extend `openColor.gray` 44 | gray: { 45 | ...openColor.gray, 46 | 10: "#16191d", 47 | 11: "#0d0f12", 48 | 12: "#030507", 49 | }, 50 | // Use `colar.gray` as "stone" 51 | stone: colar.gray, 52 | // Use all other colors in `colar` 53 | ...Object.fromEntries( 54 | Object.entries(colar).filter(([hueName]) => hueName != "gray") 55 | ), 56 | }) 57 | 58 | 59 | const Color = (await import('colorjs.io')).default 60 | 61 | const hexTOhsl = hex => 62 | new Color(hex).to('hsl') 63 | .coords.map(Math.round) 64 | .reduce((acc, coord, index) => { 65 | if (index > 0) 66 | return acc += ' ' + coord + '%' 67 | else 68 | return acc += coord 69 | }, '') 70 | 71 | const capitalizeFirstLetter = string => 72 | string.charAt(0).toUpperCase() + string.slice(1) 73 | 74 | const groupedObject = colors.reduce((root, [color, shades]) => { 75 | let base = `--${color}-` 76 | root += `\n\nexport const ${capitalizeFirstLetter(color)} = {` 77 | 78 | Object.entries(shades).forEach(([num, hex]) => 79 | root += ` 80 | '${base}${num}-hsl': '${hexTOhsl(hex)}',` 81 | // root += ` 82 | // '${base}${num}': '${hex}',` 83 | ) 84 | 85 | root += '\n}' 86 | 87 | return root 88 | }, ``) 89 | 90 | const channels = colors.reduce((root, [color, shades]) => { 91 | let base = `--${color}-` 92 | 93 | Object.entries(shades).forEach(([num, hex]) => 94 | root += ` 95 | '${base}${num}-hsl': '${hexTOhsl(hex)}',` 96 | ) 97 | 98 | return root 99 | }, ``) 100 | 101 | const vars = colors.reduce((root, [color, shades]) => { 102 | let base = `--${color}-` 103 | 104 | Object.entries(shades).forEach(([num, hex]) => 105 | root += ` 106 | '${base}${num}': ${hex}` 107 | ) 108 | 109 | return root 110 | }, ``) 111 | 112 | console.log(groupedObject) 113 | // console.log(vars) 114 | // console.log(channels) 115 | -------------------------------------------------------------------------------- /src/props.cyan-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --cyan-0-hsl: 185 81% 94%; 3 | --cyan-1-hsl: 185 84% 88%; 4 | --cyan-2-hsl: 186 77% 77%; 5 | --cyan-3-hsl: 187 74% 65%; 6 | --cyan-4-hsl: 187 69% 55%; 7 | --cyan-5-hsl: 188 72% 47%; 8 | --cyan-6-hsl: 187 80% 42%; 9 | --cyan-7-hsl: 188 83% 37%; 10 | --cyan-8-hsl: 189 85% 32%; 11 | --cyan-9-hsl: 189 85% 28%; 12 | --cyan-10-hsl: 189 84% 23%; 13 | --cyan-11-hsl: 190 84% 17%; 14 | --cyan-12-hsl: 189 84% 12%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.cyan.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --cyan-0: #e3fafc; 3 | --cyan-1: #c5f6fa; 4 | --cyan-2: #99e9f2; 5 | --cyan-3: #66d9e8; 6 | --cyan-4: #3bc9db; 7 | --cyan-5: #22b8cf; 8 | --cyan-6: #15aabf; 9 | --cyan-7: #1098ad; 10 | --cyan-8: #0c8599; 11 | --cyan-9: #0b7285; 12 | --cyan-10: #095c6b; 13 | --cyan-11: #074652; 14 | --cyan-12: #053038; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.easing.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --ease-1: cubic-bezier(.25, 0, .5, 1); 3 | --ease-2: cubic-bezier(.25, 0, .4, 1); 4 | --ease-3: cubic-bezier(.25, 0, .3, 1); 5 | --ease-4: cubic-bezier(.25, 0, .2, 1); 6 | --ease-5: cubic-bezier(.25, 0, .1, 1); 7 | --ease-in-1: cubic-bezier(.25, 0, 1, 1); 8 | --ease-in-2: cubic-bezier(.50, 0, 1, 1); 9 | --ease-in-3: cubic-bezier(.70, 0, 1, 1); 10 | --ease-in-4: cubic-bezier(.90, 0, 1, 1); 11 | --ease-in-5: cubic-bezier(1, 0, 1, 1); 12 | --ease-out-1: cubic-bezier(0, 0, .75, 1); 13 | --ease-out-2: cubic-bezier(0, 0, .50, 1); 14 | --ease-out-3: cubic-bezier(0, 0, .3, 1); 15 | --ease-out-4: cubic-bezier(0, 0, .1, 1); 16 | --ease-out-5: cubic-bezier(0, 0, 0, 1); 17 | --ease-in-out-1: cubic-bezier(.1, 0, .9, 1); 18 | --ease-in-out-2: cubic-bezier(.3, 0, .7, 1); 19 | --ease-in-out-3: cubic-bezier(.5, 0, .5, 1); 20 | --ease-in-out-4: cubic-bezier(.7, 0, .3, 1); 21 | --ease-in-out-5: cubic-bezier(.9, 0, .1, 1); 22 | --ease-elastic-out-1: cubic-bezier(.5, .75, .75, 1.25); 23 | --ease-elastic-out-2: cubic-bezier(.5, 1, .75, 1.25); 24 | --ease-elastic-out-3: cubic-bezier(.5, 1.25, .75, 1.25); 25 | --ease-elastic-out-4: cubic-bezier(.5, 1.5, .75, 1.25); 26 | --ease-elastic-out-5: cubic-bezier(.5, 1.75, .75, 1.25); 27 | --ease-elastic-in-1: cubic-bezier(.5, -0.25, .75, 1); 28 | --ease-elastic-in-2: cubic-bezier(.5, -0.50, .75, 1); 29 | --ease-elastic-in-3: cubic-bezier(.5, -0.75, .75, 1); 30 | --ease-elastic-in-4: cubic-bezier(.5, -1.00, .75, 1); 31 | --ease-elastic-in-5: cubic-bezier(.5, -1.25, .75, 1); 32 | --ease-elastic-in-out-1: cubic-bezier(.5, -.1, .1, 1.5); 33 | --ease-elastic-in-out-2: cubic-bezier(.5, -.3, .1, 1.5); 34 | --ease-elastic-in-out-3: cubic-bezier(.5, -.5, .1, 1.5); 35 | --ease-elastic-in-out-4: cubic-bezier(.5, -.7, .1, 1.5); 36 | --ease-elastic-in-out-5: cubic-bezier(.5, -.9, .1, 1.5); 37 | --ease-step-1: steps(2); 38 | --ease-step-2: steps(3); 39 | --ease-step-3: steps(4); 40 | --ease-step-4: steps(7); 41 | --ease-step-5: steps(10); 42 | --ease-elastic-1: var(--ease-elastic-out-1); 43 | --ease-elastic-2: var(--ease-elastic-out-2); 44 | --ease-elastic-3: var(--ease-elastic-out-3); 45 | --ease-elastic-4: var(--ease-elastic-out-4); 46 | --ease-elastic-5: var(--ease-elastic-out-5); 47 | --ease-squish-1: var(--ease-elastic-in-out-1); 48 | --ease-squish-2: var(--ease-elastic-in-out-2); 49 | --ease-squish-3: var(--ease-elastic-in-out-3); 50 | --ease-squish-4: var(--ease-elastic-in-out-4); 51 | --ease-squish-5: var(--ease-elastic-in-out-5); 52 | --ease-spring-1: linear( 53 | 0, 0.006, 0.025 2.8%, 0.101 6.1%, 0.539 18.9%, 0.721 25.3%, 0.849 31.5%, 54 | 0.937 38.1%, 0.968 41.8%, 0.991 45.7%, 1.006 50.1%, 1.015 55%, 1.017 63.9%, 55 | 1.001 56 | ); 57 | --ease-spring-2: linear( 58 | 0, 0.007, 0.029 2.2%, 0.118 4.7%, 0.625 14.4%, 0.826 19%, 0.902, 0.962, 59 | 1.008 26.1%, 1.041 28.7%, 1.064 32.1%, 1.07 36%, 1.061 40.5%, 1.015 53.4%, 60 | 0.999 61.6%, 0.995 71.2%, 1 61 | ); 62 | --ease-spring-3: linear( 63 | 0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.723 12.9%, 0.938 16.7%, 1.017, 1.077, 64 | 1.121, 1.149 24.3%, 1.159, 1.163, 1.161, 1.154 29.9%, 1.129 32.8%, 65 | 1.051 39.6%, 1.017 43.1%, 0.991, 0.977 51%, 0.974 53.8%, 0.975 57.1%, 66 | 0.997 69.8%, 1.003 76.9%, 1 67 | ); 68 | --ease-spring-4: linear( 69 | 0, 0.009, 0.037 1.7%, 0.153 3.6%, 0.776 10.3%, 1.001, 1.142 16%, 1.185, 70 | 1.209 19%, 1.215 19.9% 20.8%, 1.199, 1.165 25%, 1.056 30.3%, 1.008 33%, 0.973, 71 | 0.955 39.2%, 0.953 41.1%, 0.957 43.3%, 0.998 53.3%, 1.009 59.1% 63.7%, 72 | 0.998 78.9%, 1 73 | ); 74 | --ease-spring-5: linear( 75 | 0, 0.01, 0.04 1.6%, 0.161 3.3%, 0.816 9.4%, 1.046, 1.189 14.4%, 1.231, 76 | 1.254 17%, 1.259, 1.257 18.6%, 1.236, 1.194 22.3%, 1.057 27%, 0.999 29.4%, 77 | 0.955 32.1%, 0.942, 0.935 34.9%, 0.933, 0.939 38.4%, 1 47.3%, 1.011, 78 | 1.017 52.6%, 1.016 56.4%, 1 65.2%, 0.996 70.2%, 1.001 87.2%, 1 79 | ); 80 | --ease-bounce-1: linear( 81 | 0, 0.004, 0.016, 0.035, 0.063, 0.098, 0.141, 0.191, 0.25, 0.316, 0.391 36.8%, 82 | 0.563, 0.766, 1 58.8%, 0.946, 0.908 69.1%, 0.895, 0.885, 0.879, 0.878, 0.879, 83 | 0.885, 0.895, 0.908 89.7%, 0.946, 1 84 | ); 85 | --ease-bounce-2: linear( 86 | 0, 0.004, 0.016, 0.035, 0.063, 0.098, 0.141 15.1%, 0.25, 0.391, 0.562, 0.765, 87 | 1, 0.892 45.2%, 0.849, 0.815, 0.788, 0.769, 0.757, 0.753, 0.757, 0.769, 0.788, 88 | 0.815, 0.85, 0.892 75.2%, 1 80.2%, 0.973, 0.954, 0.943, 0.939, 0.943, 0.954, 89 | 0.973, 1 90 | ); 91 | --ease-bounce-3: linear( 92 | 0, 0.004, 0.016, 0.035, 0.062, 0.098, 0.141 11.4%, 0.25, 0.39, 0.562, 0.764, 93 | 1 30.3%, 0.847 34.8%, 0.787, 0.737, 0.699, 0.672, 0.655, 0.65, 0.656, 0.672, 94 | 0.699, 0.738, 0.787, 0.847 61.7%, 1 66.2%, 0.946, 0.908, 0.885 74.2%, 0.879, 95 | 0.878, 0.879, 0.885 79.5%, 0.908, 0.946, 1 87.4%, 0.981, 0.968, 0.96, 0.957, 96 | 0.96, 0.968, 0.981, 1 97 | ); 98 | --ease-bounce-4: linear( 99 | 0, 0.004, 0.016 3%, 0.062, 0.141, 0.25, 0.391, 0.562 18.2%, 1 24.3%, 0.81, 100 | 0.676 32.3%, 0.629, 0.595, 0.575, 0.568, 0.575, 0.595, 0.629, 0.676 48.2%, 101 | 0.811, 1 56.2%, 0.918, 0.86, 0.825, 0.814, 0.825, 0.86, 0.918, 1 77.2%, 102 | 0.94 80.6%, 0.925, 0.92, 0.925, 0.94 87.5%, 1 90.9%, 0.974, 0.965, 0.974, 1 103 | ); 104 | --ease-bounce-5: linear( 105 | 0, 0.004, 0.016 2.5%, 0.063, 0.141, 0.25 10.1%, 0.562, 1 20.2%, 0.783, 0.627, 106 | 0.534 30.9%, 0.511, 0.503, 0.511, 0.534 38%, 0.627, 0.782, 1 48.7%, 0.892, 107 | 0.815, 0.769 56.3%, 0.757, 0.753, 0.757, 0.769 61.3%, 0.815, 0.892, 1 68.8%, 108 | 0.908 72.4%, 0.885, 0.878, 0.885, 0.908 79.4%, 1 83%, 0.954 85.5%, 0.943, 109 | 0.939, 0.943, 0.954 90.5%, 1 93%, 0.977, 0.97, 0.977, 1 110 | ); 111 | } 112 | -------------------------------------------------------------------------------- /src/props.easing.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--ease-1': 'cubic-bezier(.25, 0, .5, 1)', 3 | '--ease-2': 'cubic-bezier(.25, 0, .4, 1)', 4 | '--ease-3': 'cubic-bezier(.25, 0, .3, 1)', 5 | '--ease-4': 'cubic-bezier(.25, 0, .2, 1)', 6 | '--ease-5': 'cubic-bezier(.25, 0, .1, 1)', 7 | 8 | '--ease-in-1': 'cubic-bezier(.25, 0, 1, 1)', 9 | '--ease-in-2': 'cubic-bezier(.50, 0, 1, 1)', 10 | '--ease-in-3': 'cubic-bezier(.70, 0, 1, 1)', 11 | '--ease-in-4': 'cubic-bezier(.90, 0, 1, 1)', 12 | '--ease-in-5': 'cubic-bezier(1, 0, 1, 1)', 13 | 14 | '--ease-out-1': 'cubic-bezier(0, 0, .75, 1)', 15 | '--ease-out-2': 'cubic-bezier(0, 0, .50, 1)', 16 | '--ease-out-3': 'cubic-bezier(0, 0, .3, 1)', 17 | '--ease-out-4': 'cubic-bezier(0, 0, .1, 1)', 18 | '--ease-out-5': 'cubic-bezier(0, 0, 0, 1)', 19 | 20 | '--ease-in-out-1': 'cubic-bezier(.1, 0, .9, 1)', 21 | '--ease-in-out-2': 'cubic-bezier(.3, 0, .7, 1)', 22 | '--ease-in-out-3': 'cubic-bezier(.5, 0, .5, 1)', 23 | '--ease-in-out-4': 'cubic-bezier(.7, 0, .3, 1)', 24 | '--ease-in-out-5': 'cubic-bezier(.9, 0, .1, 1)', 25 | 26 | '--ease-elastic-out-1': 'cubic-bezier(.5, .75, .75, 1.25)', 27 | '--ease-elastic-out-2': 'cubic-bezier(.5, 1, .75, 1.25)', 28 | '--ease-elastic-out-3': 'cubic-bezier(.5, 1.25, .75, 1.25)', 29 | '--ease-elastic-out-4': 'cubic-bezier(.5, 1.5, .75, 1.25)', 30 | '--ease-elastic-out-5': 'cubic-bezier(.5, 1.75, .75, 1.25)', 31 | 32 | '--ease-elastic-in-1': 'cubic-bezier(.5, -0.25, .75, 1)', 33 | '--ease-elastic-in-2': 'cubic-bezier(.5, -0.50, .75, 1)', 34 | '--ease-elastic-in-3': 'cubic-bezier(.5, -0.75, .75, 1)', 35 | '--ease-elastic-in-4': 'cubic-bezier(.5, -1.00, .75, 1)', 36 | '--ease-elastic-in-5': 'cubic-bezier(.5, -1.25, .75, 1)', 37 | 38 | '--ease-elastic-in-out-1': 'cubic-bezier(.5, -.1, .1, 1.5)', 39 | '--ease-elastic-in-out-2': 'cubic-bezier(.5, -.3, .1, 1.5)', 40 | '--ease-elastic-in-out-3': 'cubic-bezier(.5, -.5, .1, 1.5)', 41 | '--ease-elastic-in-out-4': 'cubic-bezier(.5, -.7, .1, 1.5)', 42 | '--ease-elastic-in-out-5': 'cubic-bezier(.5, -.9, .1, 1.5)', 43 | 44 | '--ease-step-1': 'steps(2)', 45 | '--ease-step-2': 'steps(3)', 46 | '--ease-step-3': 'steps(4)', 47 | '--ease-step-4': 'steps(7)', 48 | '--ease-step-5': 'steps(10)', 49 | 50 | '--ease-elastic-1': 'var(--ease-elastic-out-1)', 51 | '--ease-elastic-2': 'var(--ease-elastic-out-2)', 52 | '--ease-elastic-3': 'var(--ease-elastic-out-3)', 53 | '--ease-elastic-4': 'var(--ease-elastic-out-4)', 54 | '--ease-elastic-5': 'var(--ease-elastic-out-5)', 55 | 56 | '--ease-squish-1': 'var(--ease-elastic-in-out-1)', 57 | '--ease-squish-2': 'var(--ease-elastic-in-out-2)', 58 | '--ease-squish-3': 'var(--ease-elastic-in-out-3)', 59 | '--ease-squish-4': 'var(--ease-elastic-in-out-4)', 60 | '--ease-squish-5': 'var(--ease-elastic-in-out-5)', 61 | 62 | '--ease-spring-1': `linear( 63 | 0, 0.006, 0.025 2.8%, 0.101 6.1%, 0.539 18.9%, 0.721 25.3%, 0.849 31.5%, 64 | 0.937 38.1%, 0.968 41.8%, 0.991 45.7%, 1.006 50.1%, 1.015 55%, 1.017 63.9%, 65 | 1.001 66 | )`, 67 | '--ease-spring-2': `linear( 68 | 0, 0.007, 0.029 2.2%, 0.118 4.7%, 0.625 14.4%, 0.826 19%, 0.902, 0.962, 69 | 1.008 26.1%, 1.041 28.7%, 1.064 32.1%, 1.07 36%, 1.061 40.5%, 1.015 53.4%, 70 | 0.999 61.6%, 0.995 71.2%, 1 71 | )`, 72 | '--ease-spring-3': `linear( 73 | 0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.723 12.9%, 0.938 16.7%, 1.017, 1.077, 74 | 1.121, 1.149 24.3%, 1.159, 1.163, 1.161, 1.154 29.9%, 1.129 32.8%, 75 | 1.051 39.6%, 1.017 43.1%, 0.991, 0.977 51%, 0.974 53.8%, 0.975 57.1%, 76 | 0.997 69.8%, 1.003 76.9%, 1 77 | )`, 78 | '--ease-spring-4': `linear( 79 | 0, 0.009, 0.037 1.7%, 0.153 3.6%, 0.776 10.3%, 1.001, 1.142 16%, 1.185, 80 | 1.209 19%, 1.215 19.9% 20.8%, 1.199, 1.165 25%, 1.056 30.3%, 1.008 33%, 0.973, 81 | 0.955 39.2%, 0.953 41.1%, 0.957 43.3%, 0.998 53.3%, 1.009 59.1% 63.7%, 82 | 0.998 78.9%, 1 83 | )`, 84 | '--ease-spring-5': `linear( 85 | 0, 0.01, 0.04 1.6%, 0.161 3.3%, 0.816 9.4%, 1.046, 1.189 14.4%, 1.231, 86 | 1.254 17%, 1.259, 1.257 18.6%, 1.236, 1.194 22.3%, 1.057 27%, 0.999 29.4%, 87 | 0.955 32.1%, 0.942, 0.935 34.9%, 0.933, 0.939 38.4%, 1 47.3%, 1.011, 88 | 1.017 52.6%, 1.016 56.4%, 1 65.2%, 0.996 70.2%, 1.001 87.2%, 1 89 | )`, 90 | 91 | '--ease-bounce-1': `linear( 92 | 0, 0.004, 0.016, 0.035, 0.063, 0.098, 0.141, 0.191, 0.25, 0.316, 0.391 36.8%, 93 | 0.563, 0.766, 1 58.8%, 0.946, 0.908 69.1%, 0.895, 0.885, 0.879, 0.878, 0.879, 94 | 0.885, 0.895, 0.908 89.7%, 0.946, 1 95 | )`, 96 | '--ease-bounce-2': `linear( 97 | 0, 0.004, 0.016, 0.035, 0.063, 0.098, 0.141 15.1%, 0.25, 0.391, 0.562, 0.765, 98 | 1, 0.892 45.2%, 0.849, 0.815, 0.788, 0.769, 0.757, 0.753, 0.757, 0.769, 0.788, 99 | 0.815, 0.85, 0.892 75.2%, 1 80.2%, 0.973, 0.954, 0.943, 0.939, 0.943, 0.954, 100 | 0.973, 1 101 | )`, 102 | '--ease-bounce-3': `linear( 103 | 0, 0.004, 0.016, 0.035, 0.062, 0.098, 0.141 11.4%, 0.25, 0.39, 0.562, 0.764, 104 | 1 30.3%, 0.847 34.8%, 0.787, 0.737, 0.699, 0.672, 0.655, 0.65, 0.656, 0.672, 105 | 0.699, 0.738, 0.787, 0.847 61.7%, 1 66.2%, 0.946, 0.908, 0.885 74.2%, 0.879, 106 | 0.878, 0.879, 0.885 79.5%, 0.908, 0.946, 1 87.4%, 0.981, 0.968, 0.96, 0.957, 107 | 0.96, 0.968, 0.981, 1 108 | )`, 109 | '--ease-bounce-4': `linear( 110 | 0, 0.004, 0.016 3%, 0.062, 0.141, 0.25, 0.391, 0.562 18.2%, 1 24.3%, 0.81, 111 | 0.676 32.3%, 0.629, 0.595, 0.575, 0.568, 0.575, 0.595, 0.629, 0.676 48.2%, 112 | 0.811, 1 56.2%, 0.918, 0.86, 0.825, 0.814, 0.825, 0.86, 0.918, 1 77.2%, 113 | 0.94 80.6%, 0.925, 0.92, 0.925, 0.94 87.5%, 1 90.9%, 0.974, 0.965, 0.974, 1 114 | )`, 115 | '--ease-bounce-5': `linear( 116 | 0, 0.004, 0.016 2.5%, 0.063, 0.141, 0.25 10.1%, 0.562, 1 20.2%, 0.783, 0.627, 117 | 0.534 30.9%, 0.511, 0.503, 0.511, 0.534 38%, 0.627, 0.782, 1 48.7%, 0.892, 118 | 0.815, 0.769 56.3%, 0.757, 0.753, 0.757, 0.769 61.3%, 0.815, 0.892, 1 68.8%, 119 | 0.908 72.4%, 0.885, 0.878, 0.885, 0.908 79.4%, 1 83%, 0.954 85.5%, 0.943, 120 | 0.939, 0.943, 0.954 90.5%, 1 93%, 0.977, 0.97, 0.977, 1 121 | )`, 122 | } 123 | -------------------------------------------------------------------------------- /src/props.fonts.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --font-system-ui: system-ui, sans-serif; 3 | --font-transitional: Charter, Bitstream Charter, Sitka Text, Cambria, serif; 4 | --font-old-style: Iowan Old Style, Palatino Linotype, URW Palladio L, P052, serif; 5 | --font-humanist: Seravek, Gill Sans Nova, Ubuntu, Calibri, DejaVu Sans, source-sans-pro, sans-serif; 6 | --font-geometric-humanist: Avenir, Montserrat, Corbel, URW Gothic, source-sans-pro, sans-serif; 7 | --font-classical-humanist: Optima, Candara, Noto Sans, source-sans-pro, sans-serif; 8 | --font-neo-grotesque: Inter, Roboto, Helvetica Neue, Arial Nova, Nimbus Sans, Arial, sans-serif; 9 | --font-monospace-slab-serif: Nimbus Mono PS, Courier New, monospace; 10 | --font-monospace-code: Dank Mono,Operator Mono, Inconsolata, Fira Mono, ui-monospace, SF Mono, Monaco, Droid Sans Mono, Source Code Pro, Cascadia Code, Menlo, Consolas, DejaVu Sans Mono, monospace; 11 | --font-industrial: Bahnschrift, DIN Alternate, Franklin Gothic Medium, Nimbus Sans Narrow, sans-serif-condensed, sans-serif; 12 | --font-rounded-sans: ui-rounded, Hiragino Maru Gothic ProN, Quicksand, Comfortaa, Manjari, Arial Rounded MT, Arial Rounded MT Bold, Calibri, source-sans-pro, sans-serif; 13 | --font-slab-serif: Rockwell, Rockwell Nova, Roboto Slab, DejaVu Serif, Sitka Small, serif; 14 | --font-antique: Superclarendon, Bookman Old Style, URW Bookman, URW Bookman L, Georgia Pro, Georgia, serif; 15 | --font-didone: Didot, Bodoni MT, Noto Serif Display, URW Palladio L, P052, Sylfaen, serif; 16 | --font-handwritten: Segoe Print, Bradley Hand, Chilanka, TSCu_Comic, casual, cursive; 17 | --font-sans: var(--font-system-ui); 18 | --font-serif: ui-serif, serif; 19 | --font-mono: var(--font-monospace-code); 20 | --font-weight-1: 100; 21 | --font-weight-2: 200; 22 | --font-weight-3: 300; 23 | --font-weight-4: 400; 24 | --font-weight-5: 500; 25 | --font-weight-6: 600; 26 | --font-weight-7: 700; 27 | --font-weight-8: 800; 28 | --font-weight-9: 900; 29 | --font-lineheight-00: .95; 30 | --font-lineheight-0: 1.1; 31 | --font-lineheight-1: 1.25; 32 | --font-lineheight-2: 1.375; 33 | --font-lineheight-3: 1.5; 34 | --font-lineheight-4: 1.75; 35 | --font-lineheight-5: 2; 36 | --font-letterspacing-0: -.05em; 37 | --font-letterspacing-1: .025em; 38 | --font-letterspacing-2: .050em; 39 | --font-letterspacing-3: .075em; 40 | --font-letterspacing-4: .150em; 41 | --font-letterspacing-5: .500em; 42 | --font-letterspacing-6: .750em; 43 | --font-letterspacing-7: 1em; 44 | --font-size-00: .5rem; 45 | --font-size-0: .75rem; 46 | --font-size-1: 1rem; 47 | --font-size-2: 1.1rem; 48 | --font-size-3: 1.25rem; 49 | --font-size-4: 1.5rem; 50 | --font-size-5: 2rem; 51 | --font-size-6: 2.5rem; 52 | --font-size-7: 3rem; 53 | --font-size-8: 3.5rem; 54 | --font-size-fluid-0: clamp(.75rem, 2vw, 1rem); 55 | --font-size-fluid-1: clamp(1rem, 4vw, 1.5rem); 56 | --font-size-fluid-2: clamp(1.5rem, 6vw, 2.5rem); 57 | --font-size-fluid-3: clamp(2rem, 9vw, 3.5rem); 58 | } 59 | -------------------------------------------------------------------------------- /src/props.fonts.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--font-system-ui': 'system-ui, sans-serif', 3 | '--font-transitional': 4 | 'Charter, Bitstream Charter, Sitka Text, Cambria, serif', 5 | '--font-old-style': 6 | 'Iowan Old Style, Palatino Linotype, URW Palladio L, P052, serif', 7 | '--font-humanist': 8 | 'Seravek, Gill Sans Nova, Ubuntu, Calibri, DejaVu Sans, source-sans-pro, sans-serif', 9 | '--font-geometric-humanist': 10 | 'Avenir, Montserrat, Corbel, URW Gothic, source-sans-pro, sans-serif', 11 | '--font-classical-humanist': 12 | 'Optima, Candara, Noto Sans, source-sans-pro, sans-serif', 13 | '--font-neo-grotesque': 14 | 'Inter, Roboto, Helvetica Neue, Arial Nova, Nimbus Sans, Arial, sans-serif', 15 | '--font-monospace-slab-serif': 'Nimbus Mono PS, Courier New, monospace', 16 | '--font-monospace-code': 17 | 'Dank Mono,Operator Mono, Inconsolata, Fira Mono, ui-monospace, SF Mono, Monaco, Droid Sans Mono, Source Code Pro, Cascadia Code, Menlo, Consolas, DejaVu Sans Mono, monospace', 18 | '--font-industrial': 19 | 'Bahnschrift, DIN Alternate, Franklin Gothic Medium, Nimbus Sans Narrow, sans-serif-condensed, sans-serif', 20 | '--font-rounded-sans': 21 | 'ui-rounded, Hiragino Maru Gothic ProN, Quicksand, Comfortaa, Manjari, Arial Rounded MT, Arial Rounded MT Bold, Calibri, source-sans-pro, sans-serif', 22 | '--font-slab-serif': 23 | 'Rockwell, Rockwell Nova, Roboto Slab, DejaVu Serif, Sitka Small, serif', 24 | '--font-antique': 25 | 'Superclarendon, Bookman Old Style, URW Bookman, URW Bookman L, Georgia Pro, Georgia, serif', 26 | '--font-didone': 27 | 'Didot, Bodoni MT, Noto Serif Display, URW Palladio L, P052, Sylfaen, serif', 28 | '--font-handwritten': 29 | 'Segoe Print, Bradley Hand, Chilanka, TSCu_Comic, casual, cursive', 30 | '--font-sans': 'var(--font-system-ui)', 31 | '--font-serif': 'ui-serif, serif', 32 | '--font-mono': 'var(--font-monospace-code)', 33 | 34 | '--font-weight-1': '100', 35 | '--font-weight-2': '200', 36 | '--font-weight-3': '300', 37 | '--font-weight-4': '400', 38 | '--font-weight-5': '500', 39 | '--font-weight-6': '600', 40 | '--font-weight-7': '700', 41 | '--font-weight-8': '800', 42 | '--font-weight-9': '900', 43 | 44 | '--font-lineheight-00': '.95', 45 | '--font-lineheight-0': '1.1', 46 | '--font-lineheight-1': '1.25', 47 | '--font-lineheight-2': '1.375', 48 | '--font-lineheight-3': '1.5', 49 | '--font-lineheight-4': '1.75', 50 | '--font-lineheight-5': '2', 51 | 52 | // '--font-relative-lineheight-00': 'calc(1rem + .5ch)', 53 | // '--font-relative-lineheight-0': 'calc(1rem + .75ch)', 54 | // '--font-relative-lineheight-1': 'calc(1rem + 1ch)', 55 | // '--font-relative-lineheight-2': 'calc(1rem + 1.25ch)', 56 | // '--font-relative-lineheight-3': 'calc(1rem + 1.5ch)', 57 | // '--font-relative-lineheight-4': 'calc(1rem + 2ch)', 58 | // '--font-relative-lineheight-5': 'calc(1rem + 2.5ch)', 59 | // '--font-relative-lineheight-6': 'calc(1rem + 3ch)', 60 | 61 | '--font-letterspacing-0': '-.05em', 62 | '--font-letterspacing-1': '.025em', 63 | '--font-letterspacing-2': '.050em', 64 | '--font-letterspacing-3': '.075em', 65 | '--font-letterspacing-4': '.150em', 66 | '--font-letterspacing-5': '.500em', 67 | '--font-letterspacing-6': '.750em', 68 | '--font-letterspacing-7': '1em', 69 | 70 | '--font-size-00': '.5rem', 71 | '--font-size-0': '.75rem', 72 | '--font-size-1': '1rem', 73 | '--font-size-2': '1.1rem', 74 | '--font-size-3': '1.25rem', 75 | '--font-size-4': '1.5rem', 76 | '--font-size-5': '2rem', 77 | '--font-size-6': '2.5rem', 78 | '--font-size-7': '3rem', 79 | '--font-size-8': '3.5rem', 80 | 81 | '--font-size-fluid-0': 'clamp(.75rem, 2vw, 1rem)', 82 | '--font-size-fluid-1': 'clamp(1rem, 4vw, 1.5rem)', 83 | '--font-size-fluid-2': 'clamp(1.5rem, 6vw, 2.5rem)', 84 | '--font-size-fluid-3': 'clamp(2rem, 9vw, 3.5rem)', 85 | }; 86 | -------------------------------------------------------------------------------- /src/props.gradients.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --gradient-space: ; 3 | --gradient-1: linear-gradient(to bottom right var(--gradient-space), #1f005c, #5b0060, #870160, #ac255e, #ca485c, #e16b5c, #f39060, #ffb56b); 4 | --gradient-2: linear-gradient(to bottom right var(--gradient-space), #48005c, #8300e2, #a269ff); 5 | --gradient-3: 6 | radial-gradient( 7 | circle at top right var(--gradient-space), 8 | hsl(180 100% 50%), hsl(180 100% 50% / 0%) 9 | ), 10 | radial-gradient( 11 | circle at bottom left var(--gradient-space), 12 | hsl(328 100% 54%), hsl(328 100% 54% / 0%) 13 | ); 14 | --gradient-4: linear-gradient(to bottom right var(--gradient-space), #00F5A0, #00D9F5); 15 | --gradient-5: conic-gradient(from -270deg at 75% 110% var(--gradient-space), fuchsia, floralwhite); 16 | --gradient-6: conic-gradient(from -90deg at top left var(--gradient-space), black, white); 17 | --gradient-7: linear-gradient(to bottom right var(--gradient-space), #72C6EF, #004E8F); 18 | --gradient-8: conic-gradient(from 90deg at 50% 0% var(--gradient-space), #111, 50%, #222, #111); 19 | --gradient-9: conic-gradient(from .5turn at bottom center var(--gradient-space), lightblue, white); 20 | --gradient-10: conic-gradient(from 90deg at 40% -25% var(--gradient-space), #ffd700, #f79d03, #ee6907, #e6390a, #de0d0d, #d61039, #cf1261, #c71585, #cf1261, #d61039, #de0d0d, #ee6907, #f79d03, #ffd700, #ffd700, #ffd700); 21 | --gradient-11: conic-gradient(at bottom left var(--gradient-space), deeppink, cyan); 22 | --gradient-12: conic-gradient(from 90deg at 25% -10% var(--gradient-space), #ff4500, #d3f340, #7bee85, #afeeee, #7bee85); 23 | --gradient-13: radial-gradient(circle at 50% 200% var(--gradient-space), #000142, #3b0083, #b300c3, #ff059f, #ff4661, #ffad86, #fff3c7); 24 | --gradient-14: conic-gradient(at top right var(--gradient-space), lime, cyan); 25 | --gradient-15: linear-gradient(to bottom right var(--gradient-space), #c7d2fe, #fecaca, #fef3c7); 26 | --gradient-16: radial-gradient(circle at 50% -250% var(--gradient-space), #374151, #111827, #000); 27 | --gradient-17: conic-gradient(from -90deg at 50% -25% var(--gradient-space), blue, blueviolet); 28 | --gradient-18: 29 | linear-gradient(0deg var(--gradient-space), hsla(0 100% 50% / 80%), hsla(0 100% 50% / 0) 75%), 30 | linear-gradient(60deg var(--gradient-space), hsla(60 100% 50% / 80%), hsla(60 100% 50% / 0) 75%), 31 | linear-gradient(120deg var(--gradient-space), hsla(120 100% 50% / 80%), hsla(120 100% 50% / 0) 75%), 32 | linear-gradient(180deg var(--gradient-space), hsla(180 100% 50% / 80%), hsla(180 100% 50% / 0) 75%), 33 | linear-gradient(240deg var(--gradient-space), hsla(240 100% 50% / 80%), hsla(240 100% 50% / 0) 75%), 34 | linear-gradient(300deg var(--gradient-space), hsla(300 100% 50% / 80%), hsla(300 100% 50% / 0) 75%) 35 | ; 36 | --gradient-19: linear-gradient(to bottom right var(--gradient-space), #ffe259, #ffa751); 37 | --gradient-20: conic-gradient(from -135deg at -10% center var(--gradient-space), #ffa500, #ff7715, #ff522a, #ff3f47, #ff5482, #ff69b4); 38 | --gradient-21: conic-gradient(from -90deg at 25% 115% var(--gradient-space), #ff0000, #ff0066, #ff00cc, #cc00ff, #6600ff, #0000ff, #0000ff, #0000ff, #0000ff); 39 | --gradient-22: linear-gradient(to bottom right var(--gradient-space), #acb6e5, #86fde8); 40 | --gradient-23: linear-gradient(to bottom right var(--gradient-space), #536976, #292E49); 41 | --gradient-24: conic-gradient(from .5turn at 0% 0% var(--gradient-space), #00c476, 10%, #82b0ff, 90%, #00c476); 42 | --gradient-25: conic-gradient(at 125% 50% var(--gradient-space), #b78cf7, #ff7c94, #ffcf0d, #ff7c94, #b78cf7); 43 | --gradient-26: linear-gradient(to bottom right var(--gradient-space), #9796f0, #fbc7d4); 44 | --gradient-27: conic-gradient(from .5turn at bottom left var(--gradient-space), deeppink, rebeccapurple); 45 | --gradient-28: conic-gradient(from -90deg at 50% 105% var(--gradient-space), white, orchid); 46 | --gradient-29: 47 | radial-gradient( 48 | circle at top right var(--gradient-space), 49 | hsl(250 100% 85%), hsl(250 100% 85% / 0%) 50 | ), 51 | radial-gradient( 52 | circle at bottom left var(--gradient-space), 53 | hsl(220 90% 75%), hsl(220 90% 75% / 0%) 54 | ); 55 | --gradient-30: radial-gradient( 56 | circle at top right var(--gradient-space), 57 | hsl(150 100% 50%), hsl(150 100% 50% / 0%) 58 | ), 59 | radial-gradient( 60 | circle at bottom left var(--gradient-space), 61 | hsl(150 100% 84%), hsl(150 100% 84% / 0%) 62 | ); 63 | --noise-1: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.005' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); 64 | --noise-2: url("data:image/svg+xml,%3Csvg viewBox='0 0 300 300' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.05' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); 65 | --noise-3: url("data:image/svg+xml,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.25' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); 66 | --noise-4: url("data:image/svg+xml,%3Csvg viewBox='0 0 2056 2056' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); 67 | --noise-5: url("data:image/svg+xml,%3Csvg viewBox='0 0 2056 2056' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); 68 | --noise-filter-1: contrast(300%) brightness(100%); 69 | --noise-filter-2: contrast(200%) brightness(150%); 70 | --noise-filter-3: contrast(200%) brightness(250%); 71 | --noise-filter-4: contrast(200%) brightness(500%); 72 | --noise-filter-5: contrast(200%) brightness(1000%); 73 | } 74 | 75 | @supports (background: linear-gradient(to right in oklab, #000, #fff)) { 76 | :where(html) { 77 | --gradient-space: in oklab; 78 | } 79 | } -------------------------------------------------------------------------------- /src/props.gradients.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--gradient-space': '', 3 | '--gradient-1': 'linear-gradient(to bottom right var(--gradient-space), #1f005c, #5b0060, #870160, #ac255e, #ca485c, #e16b5c, #f39060, #ffb56b)', 4 | '--gradient-2': 'linear-gradient(to bottom right var(--gradient-space), #48005c, #8300e2, #a269ff)', 5 | '--gradient-3': ` 6 | radial-gradient( 7 | circle at top right var(--gradient-space), 8 | hsl(180 100% 50%), hsl(180 100% 50% / 0%) 9 | ), 10 | radial-gradient( 11 | circle at bottom left var(--gradient-space), 12 | hsl(328 100% 54%), hsl(328 100% 54% / 0%) 13 | )`, 14 | '--gradient-4': 'linear-gradient(to bottom right var(--gradient-space), #00F5A0, #00D9F5)', 15 | '--gradient-5': 'conic-gradient(from -270deg at 75% 110% var(--gradient-space), fuchsia, floralwhite)', 16 | '--gradient-6': 'conic-gradient(from -90deg at top left var(--gradient-space), black, white)', 17 | '--gradient-7': 'linear-gradient(to bottom right var(--gradient-space), #72C6EF, #004E8F)', 18 | '--gradient-8': 'conic-gradient(from 90deg at 50% 0% var(--gradient-space), #111, 50%, #222, #111)', 19 | '--gradient-9': 'conic-gradient(from .5turn at bottom center var(--gradient-space), lightblue, white)', 20 | '--gradient-10': 'conic-gradient(from 90deg at 40% -25% var(--gradient-space), #ffd700, #f79d03, #ee6907, #e6390a, #de0d0d, #d61039, #cf1261, #c71585, #cf1261, #d61039, #de0d0d, #ee6907, #f79d03, #ffd700, #ffd700, #ffd700)', 21 | '--gradient-11': 'conic-gradient(at bottom left var(--gradient-space), deeppink, cyan)', 22 | '--gradient-12': 'conic-gradient(from 90deg at 25% -10% var(--gradient-space), #ff4500, #d3f340, #7bee85, #afeeee, #7bee85)', 23 | '--gradient-13': 'radial-gradient(circle at 50% 200% var(--gradient-space), #000142, #3b0083, #b300c3, #ff059f, #ff4661, #ffad86, #fff3c7)', 24 | '--gradient-14': 'conic-gradient(at top right var(--gradient-space), lime, cyan)', 25 | '--gradient-15': 'linear-gradient(to bottom right var(--gradient-space), #c7d2fe, #fecaca, #fef3c7)', 26 | '--gradient-16': 'radial-gradient(circle at 50% -250% var(--gradient-space), #374151, #111827, #000)', 27 | '--gradient-17': 'conic-gradient(from -90deg at 50% -25% var(--gradient-space), blue, blueviolet)', 28 | '--gradient-18': ` 29 | linear-gradient(0deg var(--gradient-space), hsla(0 100% 50% / 80%), hsla(0 100% 50% / 0) 75%), 30 | linear-gradient(60deg var(--gradient-space), hsla(60 100% 50% / 80%), hsla(60 100% 50% / 0) 75%), 31 | linear-gradient(120deg var(--gradient-space), hsla(120 100% 50% / 80%), hsla(120 100% 50% / 0) 75%), 32 | linear-gradient(180deg var(--gradient-space), hsla(180 100% 50% / 80%), hsla(180 100% 50% / 0) 75%), 33 | linear-gradient(240deg var(--gradient-space), hsla(240 100% 50% / 80%), hsla(240 100% 50% / 0) 75%), 34 | linear-gradient(300deg var(--gradient-space), hsla(300 100% 50% / 80%), hsla(300 100% 50% / 0) 75%) 35 | `, 36 | '--gradient-19': 'linear-gradient(to bottom right var(--gradient-space), #ffe259, #ffa751)', 37 | '--gradient-20': 'conic-gradient(from -135deg at -10% center var(--gradient-space), #ffa500, #ff7715, #ff522a, #ff3f47, #ff5482, #ff69b4)', 38 | '--gradient-21': 'conic-gradient(from -90deg at 25% 115% var(--gradient-space), #ff0000, #ff0066, #ff00cc, #cc00ff, #6600ff, #0000ff, #0000ff, #0000ff, #0000ff)', 39 | '--gradient-22': 'linear-gradient(to bottom right var(--gradient-space), #acb6e5, #86fde8)', 40 | '--gradient-23': 'linear-gradient(to bottom right var(--gradient-space), #536976, #292E49)', 41 | '--gradient-24': 'conic-gradient(from .5turn at 0% 0% var(--gradient-space), #00c476, 10%, #82b0ff, 90%, #00c476)', 42 | '--gradient-25': 'conic-gradient(at 125% 50% var(--gradient-space), #b78cf7, #ff7c94, #ffcf0d, #ff7c94, #b78cf7)', 43 | '--gradient-26': 'linear-gradient(to bottom right var(--gradient-space), #9796f0, #fbc7d4)', 44 | '--gradient-27': 'conic-gradient(from .5turn at bottom left var(--gradient-space), deeppink, rebeccapurple)', 45 | '--gradient-28': 'conic-gradient(from -90deg at 50% 105% var(--gradient-space), white, orchid)', 46 | '--gradient-29': ` 47 | radial-gradient( 48 | circle at top right var(--gradient-space), 49 | hsl(250 100% 85%), hsl(250 100% 85% / 0%) 50 | ), 51 | radial-gradient( 52 | circle at bottom left var(--gradient-space), 53 | hsl(220 90% 75%), hsl(220 90% 75% / 0%) 54 | )`, 55 | '--gradient-30': 56 | `radial-gradient( 57 | circle at top right var(--gradient-space), 58 | hsl(150 100% 50%), hsl(150 100% 50% / 0%) 59 | ), 60 | radial-gradient( 61 | circle at bottom left var(--gradient-space), 62 | hsl(150 100% 84%), hsl(150 100% 84% / 0%) 63 | )`, 64 | 65 | '--noise-1': `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.005' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`, 66 | '--noise-2': `url("data:image/svg+xml,%3Csvg viewBox='0 0 300 300' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.05' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`, 67 | '--noise-3': `url("data:image/svg+xml,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.25' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`, 68 | '--noise-4': `url("data:image/svg+xml,%3Csvg viewBox='0 0 2056 2056' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`, 69 | '--noise-5': `url("data:image/svg+xml,%3Csvg viewBox='0 0 2056 2056' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`, 70 | 71 | '--noise-filter-1': 'contrast(300%) brightness(100%)', 72 | '--noise-filter-2': 'contrast(200%) brightness(150%)', 73 | '--noise-filter-3': 'contrast(200%) brightness(250%)', 74 | '--noise-filter-4': 'contrast(200%) brightness(500%)', 75 | '--noise-filter-5': 'contrast(200%) brightness(1000%)', 76 | } 77 | -------------------------------------------------------------------------------- /src/props.gradients.src.js: -------------------------------------------------------------------------------- 1 | // const conicgradients = [ 2 | // { 3 | // gradient: `conic-gradient( 4 | // from 90deg at bottom right, 5 | // cyan, 6 | // rebeccapurple 7 | // )`, 8 | // }, 9 | // { 10 | // gradient: `conic-gradient( 11 | // from .5turn at bottom center, 12 | // lightblue, 13 | // white 14 | // )`, 15 | // }, 16 | // { 17 | // gradient: `conic-gradient( 18 | // from 90deg at 40% -25%, 19 | // #ffd700, #f79d03, #ee6907, #e6390a, #de0d0d, #d61039, #cf1261, #c71585, 20 | // #cf1261, #d61039, #de0d0d, #ee6907, #f79d03, #ffd700, #ffd700, #ffd700 21 | // )`, 22 | // }, 23 | // { 24 | // gradient: `conic-gradient( 25 | // at bottom left, 26 | // deeppink, 27 | // cyan 28 | // )`, 29 | // }, 30 | // { 31 | // gradient: `conic-gradient( 32 | // from 90deg at 25% -10%, 33 | // #ff4500, #d3f340, #7bee85, #afeeee, #7bee85 34 | // )`, 35 | // }, 36 | // { 37 | // gradient: `conic-gradient( 38 | // from -90deg at top left, 39 | // black, 40 | // white 41 | // )`, 42 | // }, 43 | // { 44 | // gradient: `conic-gradient( 45 | // at top right, 46 | // lime, 47 | // cyan 48 | // )`, 49 | // }, 50 | // { 51 | // gradient: `conic-gradient( 52 | // from -.5turn at bottom right, 53 | // deeppink, 54 | // cyan, 55 | // rebeccapurple 56 | // )`, 57 | // }, 58 | // { 59 | // gradient: `conic-gradient( 60 | // at top right, 61 | // slategray, 62 | // white 63 | // )`, 64 | // }, 65 | // { 66 | // gradient: `conic-gradient( 67 | // from .5turn at 50% 110%, 68 | // white, 69 | // orange 70 | // )`, 71 | // }, 72 | // { 73 | // gradient: `conic-gradient( 74 | // from .5turn at center left, 75 | // lime, 76 | // cyan 77 | // )`, 78 | // }, 79 | // { 80 | // gradient: `conic-gradient( 81 | // from -90deg at 50% -25%, 82 | // blue, 83 | // blueviolet 84 | // )`, 85 | // }, 86 | // { 87 | // gradient: `conic-gradient( 88 | // from .5turn at top right, 89 | // darkseagreen, 90 | // darkslategray 91 | // )`, 92 | // }, 93 | // { 94 | // gradient: `conic-gradient( 95 | // from 90deg at 50% 0%, 96 | // #111, 50%, #222, #111 97 | // )`, 98 | // }, 99 | // { 100 | // gradient: `conic-gradient( 101 | // at top right, 102 | // lightcyan, 103 | // lightblue 104 | // )`, 105 | // }, 106 | // { 107 | // gradient: `conic-gradient( 108 | // from -135deg at -10% center, 109 | // #ffa500, #ff7715, #ff522a, #ff3f47, #ff5482, #ff69b4 110 | // )`, 111 | // }, 112 | // { 113 | // gradient: `conic-gradient( 114 | // from -90deg at 50% 105%, 115 | // white, 116 | // orchid 117 | // )`, 118 | // }, 119 | // { 120 | // gradient: `conic-gradient( 121 | // from -90deg at 25% 115%, 122 | // #ff0000, #ff0066, #ff00cc, #cc00ff, #6600ff, 123 | // #0000ff, #0000ff, #0000ff, #0000ff 124 | // )`, 125 | // }, 126 | // { 127 | // gradient: `conic-gradient( 128 | // from -90deg at bottom center, 129 | // papayawhip, 130 | // peachpuff 131 | // )`, 132 | // }, 133 | // { 134 | // gradient: `conic-gradient( 135 | // from -270deg at 50% -5%, 136 | // yellow, 137 | // yellowgreen 138 | // )`, 139 | // }, 140 | // { 141 | // gradient: `conic-gradient( 142 | // from -90deg at 75% -25%, 143 | // sienna, 144 | // purple 145 | // )`, 146 | // }, 147 | // { 148 | // gradient: `conic-gradient( 149 | // from 90deg at 50% 125%, 150 | // #20b2aa, #135da5, #0d0895, #4b0082, 151 | // #4b0082, #0d0895, #135da5, #20b2aa 152 | // )`, 153 | // }, 154 | // { 155 | // gradient: `conic-gradient( 156 | // from -270deg at 110% 50%, 157 | // cadetblue, 158 | // darkgreen 159 | // )`, 160 | // }, 161 | // { 162 | // gradient: `conic-gradient( 163 | // from -270deg at 75% 110%, 164 | // fuchsia, 165 | // floralwhite 166 | // )`, 167 | // }, 168 | // { 169 | // gradient: `conic-gradient( 170 | // from -270deg at 75% 110%, 171 | // midnightblue, 172 | // lawngreen 173 | // )`, 174 | // }, 175 | // { 176 | // gradient: `conic-gradient( 177 | // from .5turn at bottom left, 178 | // deeppink, 179 | // rebeccapurple 180 | // )`, 181 | // }, 182 | // { 183 | // gradient: `conic-gradient( 184 | // from 90deg at 50% 125%, 185 | // #1f005c, #003298, #005ac6, #007fdc, #00a2d3, #00c4ae, 186 | // #00e474, #00ff00, #1f005c, #003298, #005ac6, #007fdc, 187 | // #00a2d3, #00c4ae, #00e474, #00ff00 188 | // )`, 189 | // }, 190 | // { 191 | // gradient: `conic-gradient( 192 | // at 0% 0%, 193 | // snow, 194 | // white 195 | // )`, 196 | // }, 197 | // { 198 | // gradient: `conic-gradient( 199 | // from .5turn at 0% 0%, 200 | // #00c476, 201 | // 10%, 202 | // #82b0ff, 203 | // 90%, 204 | // #00c476 205 | // )`, 206 | // }, 207 | // { 208 | // gradient: `conic-gradient( 209 | // at 125% 50%, 210 | // #b78cf7, #ff7c94, #ffcf0d, #ff7c94, #b78cf7 211 | // )`, 212 | // }, 213 | // ] 214 | 215 | const linearURL = 'https://raw.githubusercontent.com/ghosh/uiGradients/master/gradients.json' 216 | const uigradients = await(await fetch(linearURL)).json() 217 | 218 | const linear = uigradients 219 | .slice(0, 30) 220 | .reduce((root, {colors}, i) => 221 | root += ` 222 | --gradient-${i+1}: linear-gradient(var(--op-gradient-direction),${colors.join(',')});` 223 | , ``) 224 | 225 | // const conic = conicgradients 226 | // // .slice(0, 25) 227 | // .reduce((root, {gradient}, i) => 228 | // root += ` 229 | // --conic-gradient-${i+1}: ${gradient 230 | // .replace(/\s+/g, ' ') 231 | // .trim() 232 | // .replace(' from', 'from') 233 | // .replace(' )', ')') 234 | // };` 235 | // , ``) 236 | 237 | console.log(linear) 238 | // console.log(conic) -------------------------------------------------------------------------------- /src/props.gray-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --gray-0-hsl: 210 17% 98%; 3 | --gray-1-hsl: 210 17% 95%; 4 | --gray-2-hsl: 210 16% 93%; 5 | --gray-3-hsl: 210 14% 89%; 6 | --gray-4-hsl: 210 14% 83%; 7 | --gray-5-hsl: 210 11% 71%; 8 | --gray-6-hsl: 210 7% 56%; 9 | --gray-7-hsl: 210 9% 31%; 10 | --gray-8-hsl: 210 10% 23%; 11 | --gray-9-hsl: 210 11% 15%; 12 | --gray-10-hsl: 214 14% 10%; 13 | --gray-11-hsl: 216 16% 6%; 14 | --gray-12-hsl: 210 40% 2%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.gray-oklch.css: -------------------------------------------------------------------------------- 1 | :where(*) { 2 | --gray-0: oklch(99% var(--gray-chroma, none) var(--gray-hue, none)); 3 | --gray-1: oklch(95% var(--gray-chroma, none) var(--gray-hue, none)); 4 | --gray-2: oklch(88% var(--gray-chroma, none) var(--gray-hue, none)); 5 | --gray-3: oklch(80% var(--gray-chroma, none) var(--gray-hue, none)); 6 | --gray-4: oklch(74% var(--gray-chroma, none) var(--gray-hue, none)); 7 | --gray-5: oklch(68% var(--gray-chroma, none) var(--gray-hue, none)); 8 | --gray-6: oklch(63% var(--gray-chroma, none) var(--gray-hue, none)); 9 | --gray-7: oklch(58% var(--gray-chroma, none) var(--gray-hue, none)); 10 | --gray-8: oklch(53% var(--gray-chroma, none) var(--gray-hue, none)); 11 | --gray-9: oklch(49% var(--gray-chroma, none) var(--gray-hue, none)); 12 | --gray-10: oklch(43% var(--gray-chroma, none) var(--gray-hue, none)); 13 | --gray-11: oklch(37% var(--gray-chroma, none) var(--gray-hue, none)); 14 | --gray-12: oklch(31% var(--gray-chroma, none) var(--gray-hue, none)); 15 | --gray-13: oklch(25% var(--gray-chroma, none) var(--gray-hue, none)); 16 | --gray-14: oklch(18% var(--gray-chroma, none) var(--gray-hue, none)); 17 | --gray-15: oklch(10% var(--gray-chroma, none) var(--gray-hue, none)); 18 | } 19 | -------------------------------------------------------------------------------- /src/props.gray-oklch.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--gray-0': 'oklch(99% var(--gray-chroma, none) var(--gray-hue, none))', 3 | '--gray-1': 'oklch(95% var(--gray-chroma, none) var(--gray-hue, none))', 4 | '--gray-2': 'oklch(88% var(--gray-chroma, none) var(--gray-hue, none))', 5 | '--gray-3': 'oklch(80% var(--gray-chroma, none) var(--gray-hue, none))', 6 | '--gray-4': 'oklch(74% var(--gray-chroma, none) var(--gray-hue, none))', 7 | '--gray-5': 'oklch(68% var(--gray-chroma, none) var(--gray-hue, none))', 8 | '--gray-6': 'oklch(63% var(--gray-chroma, none) var(--gray-hue, none))', 9 | '--gray-7': 'oklch(58% var(--gray-chroma, none) var(--gray-hue, none))', 10 | '--gray-8': 'oklch(53% var(--gray-chroma, none) var(--gray-hue, none))', 11 | '--gray-9': 'oklch(49% var(--gray-chroma, none) var(--gray-hue, none))', 12 | '--gray-10': 'oklch(43% var(--gray-chroma, none) var(--gray-hue, none))', 13 | '--gray-11': 'oklch(37% var(--gray-chroma, none) var(--gray-hue, none))', 14 | '--gray-12': 'oklch(31% var(--gray-chroma, none) var(--gray-hue, none))', 15 | '--gray-13': 'oklch(25% var(--gray-chroma, none) var(--gray-hue, none))', 16 | '--gray-14': 'oklch(18% var(--gray-chroma, none) var(--gray-hue, none))', 17 | '--gray-15': 'oklch(10% var(--gray-chroma, none) var(--gray-hue, none))', 18 | } 19 | -------------------------------------------------------------------------------- /src/props.gray.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --gray-0: #f8f9fa; 3 | --gray-1: #f1f3f5; 4 | --gray-2: #e9ecef; 5 | --gray-3: #dee2e6; 6 | --gray-4: #ced4da; 7 | --gray-5: #adb5bd; 8 | --gray-6: #868e96; 9 | --gray-7: #495057; 10 | --gray-8: #343a40; 11 | --gray-9: #212529; 12 | --gray-10: #16191d; 13 | --gray-11: #0d0f12; 14 | --gray-12: #030507; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.green-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --green-0-hsl: 131 67% 95%; 3 | --green-1-hsl: 128 76% 90%; 4 | --green-2-hsl: 128 71% 82%; 5 | --green-3-hsl: 129 68% 73%; 6 | --green-4-hsl: 130 61% 64%; 7 | --green-5-hsl: 130 57% 56%; 8 | --green-6-hsl: 131 50% 50%; 9 | --green-7-hsl: 131 53% 46%; 10 | --green-8-hsl: 131 54% 40%; 11 | --green-9-hsl: 132 52% 35%; 12 | --green-10-hsl: 132 52% 29%; 13 | --green-11-hsl: 132 53% 22%; 14 | --green-12-hsl: 131 53% 16%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.green.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --green-0: #ebfbee; 3 | --green-1: #d3f9d8; 4 | --green-2: #b2f2bb; 5 | --green-3: #8ce99a; 6 | --green-4: #69db7c; 7 | --green-5: #51cf66; 8 | --green-6: #40c057; 9 | --green-7: #37b24d; 10 | --green-8: #2f9e44; 11 | --green-9: #2b8a3e; 12 | --green-10: #237032; 13 | --green-11: #1b5727; 14 | --green-12: #133d1b; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.highlights.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --highlight-size: 10px; 3 | --highlight-color: hsl(0 0% 0% / 20%); 4 | 5 | --highlight: 6 | 0 0 0 7 | var(--highlight-size) 8 | var(--highlight-color) 9 | ; 10 | 11 | @media (--OSdark) { 12 | --highlight-color: hsl(0 0% 100% / 20%); 13 | } 14 | } -------------------------------------------------------------------------------- /src/props.indigo-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --indigo-0-hsl: 223 100% 96%; 3 | --indigo-1-hsl: 225 100% 93%; 4 | --indigo-2-hsl: 228 100% 86%; 5 | --indigo-3-hsl: 228 100% 78%; 6 | --indigo-4-hsl: 228 96% 72%; 7 | --indigo-5-hsl: 228 94% 67%; 8 | --indigo-6-hsl: 228 89% 63%; 9 | --indigo-7-hsl: 228 81% 59%; 10 | --indigo-8-hsl: 228 69% 55%; 11 | --indigo-9-hsl: 230 57% 50%; 12 | --indigo-10-hsl: 230 57% 43%; 13 | --indigo-11-hsl: 230 57% 37%; 14 | --indigo-12-hsl: 230 57% 30%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.indigo.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --indigo-0: #edf2ff; 3 | --indigo-1: #dbe4ff; 4 | --indigo-2: #bac8ff; 5 | --indigo-3: #91a7ff; 6 | --indigo-4: #748ffc; 7 | --indigo-5: #5c7cfa; 8 | --indigo-6: #4c6ef5; 9 | --indigo-7: #4263eb; 10 | --indigo-8: #3b5bdb; 11 | --indigo-9: #364fc7; 12 | --indigo-10: #2f44ad; 13 | --indigo-11: #283a94; 14 | --indigo-12: #21307a; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.jungle-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --jungle-0-hsl: 74 98% 84%; 3 | --jungle-1-hsl: 74 79% 78%; 4 | --jungle-2-hsl: 74 68% 71%; 5 | --jungle-3-hsl: 75 62% 65%; 6 | --jungle-4-hsl: 74 56% 59%; 7 | --jungle-5-hsl: 74 53% 53%; 8 | --jungle-6-hsl: 74 55% 47%; 9 | --jungle-7-hsl: 74 66% 42%; 10 | --jungle-8-hsl: 74 79% 36%; 11 | --jungle-9-hsl: 73 90% 32%; 12 | --jungle-10-hsl: 73 91% 26%; 13 | --jungle-11-hsl: 73 91% 21%; 14 | --jungle-12-hsl: 73 90% 16%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.jungle.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --jungle-0: #ecfeb0; 3 | --jungle-1: #def39a; 4 | --jungle-2: #d0e884; 5 | --jungle-3: #c2dd6e; 6 | --jungle-4: #b5d15b; 7 | --jungle-5: #a8c648; 8 | --jungle-6: #9bbb36; 9 | --jungle-7: #8fb024; 10 | --jungle-8: #84a513; 11 | --jungle-9: #7a9908; 12 | --jungle-10: #658006; 13 | --jungle-11: #516605; 14 | --jungle-12: #3d4d04; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.layouts.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --grid-cell: [stack] 1fr / [stack] 1fr; 3 | --grid-cell-name: stack; 4 | 5 | --grid-ram: repeat(auto-fit, minmax(min(0, 100%), 1fr)); 6 | --grid-holy-grail: auto 1fr auto / auto 1fr auto; 7 | } 8 | 9 | * { 10 | --grid_adapt_mixin-viewport_context: 100vw; 11 | --grid_adapt_mixin-container_context: 100%; 12 | --grid_adapt_mixin-context: var(--grid_adapt_mixin-viewport_context); 13 | 14 | --grid_adapt_mixin-break_1: 1024px; 15 | --above-break_1-columns: 5; 16 | --grid_adapt_mixin-break_2: 480px; 17 | --above-break_2-columns: 2; 18 | 19 | --grid_adapt_mixin: repeat(auto-fill, 20 | minmax( 21 | clamp( 22 | clamp( 23 | calc(100% / calc(var(--above-break_1-columns) + 1) + 0.1%), 24 | calc(calc(var(--grid_adapt_mixin-break_1) - var(--grid_adapt_mixin-context)) * 1e5), 25 | calc(100% / calc(var(--above-break_2-columns) + 1) + 0.1%) 26 | ), 27 | calc(calc(var(--grid_adapt_mixin-break_2) - var(--grid_adapt_mixin-context)) * 1e5), 28 | 100% 29 | ), 30 | 1fr) 31 | ); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/props.lime-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --lime-0-hsl: 79 81% 94%; 3 | --lime-1-hsl: 80 83% 88%; 4 | --lime-2-hsl: 81 81% 80%; 5 | --lime-3-hsl: 82 75% 69%; 6 | --lime-4-hsl: 83 73% 59%; 7 | --lime-5-hsl: 84 69% 51%; 8 | --lime-6-hsl: 85 74% 45%; 9 | --lime-7-hsl: 85 79% 40%; 10 | --lime-8-hsl: 86 84% 36%; 11 | --lime-9-hsl: 85 84% 32%; 12 | --lime-10-hsl: 85 83% 26%; 13 | --lime-11-hsl: 85 83% 21%; 14 | --lime-12-hsl: 85 84% 15%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.lime.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --lime-0: #f4fce3; 3 | --lime-1: #e9fac8; 4 | --lime-2: #d8f5a2; 5 | --lime-3: #c0eb75; 6 | --lime-4: #a9e34b; 7 | --lime-5: #94d82d; 8 | --lime-6: #82c91e; 9 | --lime-7: #74b816; 10 | --lime-8: #66a80f; 11 | --lime-9: #5c940d; 12 | --lime-10: #4c7a0b; 13 | --lime-11: #3c6109; 14 | --lime-12: #2c4706; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.masks.corner-cuts.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --mask-corner-cut-circles-1: radial-gradient(1rem at 1rem 1rem,#0000 99%,#000) -1rem -1rem; 3 | --mask-corner-cut-circles-2: radial-gradient(2rem at 2rem 2rem,#0000 99%,#000) -2rem -2rem; 4 | --mask-corner-cut-circles-3: radial-gradient(4rem at 4rem 4rem,#0000 99%,#000) -4rem -4rem; 5 | --mask-corner-cut-squares-1: conic-gradient(at calc(2*1rem) calc(2*1rem),#000 75%,#0000 0) -1rem -1rem; 6 | --mask-corner-cut-squares-2: conic-gradient(at calc(2*2rem) calc(2*2rem),#000 75%,#0000 0) -2rem -2rem; 7 | --mask-corner-cut-squares-3: conic-gradient(at calc(2*4rem) calc(2*4rem),#000 75%,#0000 0) -4rem -4rem; 8 | --mask-corner-cut-angles-1: 9 | conic-gradient(from -45deg at 1rem 1rem,#0000 25%,#000 0) 10 | -1rem 0 /100% 51% repeat-x, 11 | conic-gradient(from 135deg at 1rem calc(100% - 1rem),#0000 25%,#000 0) 12 | -1rem 100%/100% 51% repeat-x 13 | ; 14 | --mask-corner-cut-angles-2: 15 | conic-gradient(from -45deg at 2rem 2rem,#0000 25%,#000 0) 16 | -2rem 0 /100% 51% repeat-x, 17 | conic-gradient(from 135deg at 2rem calc(100% - 2rem),#0000 25%,#000 0) 18 | -2rem 100%/100% 51% repeat-x 19 | ; 20 | --mask-corner-cut-angles-3: 21 | conic-gradient(from -45deg at 4rem 4rem,#0000 25%,#000 0) 22 | -4rem 0 /100% 51% repeat-x, 23 | conic-gradient(from 135deg at 4rem calc(100% - 4rem),#0000 25%,#000 0) 24 | -4rem 100%/100% 51% repeat-x 25 | ; 26 | } 27 | -------------------------------------------------------------------------------- /src/props.masks.corner-cuts.js: -------------------------------------------------------------------------------- 1 | // big thanks to Temani Afif: https://twitter.com/ChallengesCss 2 | export default { 3 | '--mask-corner-cut-circles-1': 'radial-gradient(1rem at 1rem 1rem,#0000 99%,#000) -1rem -1rem', 4 | '--mask-corner-cut-circles-2': 'radial-gradient(2rem at 2rem 2rem,#0000 99%,#000) -2rem -2rem', 5 | '--mask-corner-cut-circles-3': 'radial-gradient(4rem at 4rem 4rem,#0000 99%,#000) -4rem -4rem', 6 | '--mask-corner-cut-squares-1': 'conic-gradient(at calc(2*1rem) calc(2*1rem),#000 75%,#0000 0) -1rem -1rem', 7 | '--mask-corner-cut-squares-2': 'conic-gradient(at calc(2*2rem) calc(2*2rem),#000 75%,#0000 0) -2rem -2rem', 8 | '--mask-corner-cut-squares-3': 'conic-gradient(at calc(2*4rem) calc(2*4rem),#000 75%,#0000 0) -4rem -4rem', 9 | '--mask-corner-cut-angles-1': ` 10 | conic-gradient(from -45deg at 1rem 1rem,#0000 25%,#000 0) 11 | -1rem 0 /100% 51% repeat-x, 12 | conic-gradient(from 135deg at 1rem calc(100% - 1rem),#0000 25%,#000 0) 13 | -1rem 100%/100% 51% repeat-x 14 | `, 15 | '--mask-corner-cut-angles-2': ` 16 | conic-gradient(from -45deg at 2rem 2rem,#0000 25%,#000 0) 17 | -2rem 0 /100% 51% repeat-x, 18 | conic-gradient(from 135deg at 2rem calc(100% - 2rem),#0000 25%,#000 0) 19 | -2rem 100%/100% 51% repeat-x 20 | `, 21 | '--mask-corner-cut-angles-3': ` 22 | conic-gradient(from -45deg at 4rem 4rem,#0000 25%,#000 0) 23 | -4rem 0 /100% 51% repeat-x, 24 | conic-gradient(from 135deg at 4rem calc(100% - 4rem),#0000 25%,#000 0) 25 | -4rem 100%/100% 51% repeat-x 26 | `, 27 | } 28 | -------------------------------------------------------------------------------- /src/props.masks.edges.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --mask-edge-scoop-bottom: radial-gradient(20px at 50% 100%,#0000 97%,#000) 50% / calc(1.9 * 20px) 100%; 3 | --mask-edge-scoop-top: radial-gradient(20px at 50% 0,#0000 97%,#000) 50% / calc(1.9 * 20px) 100%; 4 | --mask-edge-scoop-vertical: radial-gradient(20px at 50% 20px,#0000 97%,#000) 50% -20px/ calc(1.9 * 20px) 100%; 5 | --mask-edge-scoop-left: radial-gradient(20px at 0 50%,#0000 97%,#000) 50%/ 100% calc(1.9 * 20px); 6 | --mask-edge-scoop-right: radial-gradient(20px at 100% 50%,#0000 97%,#000) 50%/ 100% calc(1.9 * 20px); 7 | --mask-edge-scoop-horizontal: radial-gradient(20px at 20px 50%,#0000 97%,#000) -20px/ 100% calc(1.9 * 20px); 8 | --mask-edge-scalloped: 9 | radial-gradient(farthest-side,#000 97%,#0000) 0 0 / 20px 20px round, 10 | linear-gradient(#000 0 0) 50%/calc(100% - 20px) calc(100% - 20px) no-repeat 11 | ; 12 | --mask-edge-scalloped-bottom: 13 | linear-gradient(to top,#0000 20px,#000 0), 14 | radial-gradient(20px at top,#000 97%,#0000) bottom / calc(1.9 * 20px) 20px 15 | ; 16 | --mask-edge-scalloped-top: 17 | linear-gradient(to bottom,#0000 20px,#000 0), 18 | radial-gradient(20px at bottom,#000 97%,#0000) top / calc(1.9 * 20px) 20px 19 | ; 20 | --mask-edge-scalloped-vertical: 21 | linear-gradient(0deg,#0000 calc(2 * 20px),#000 0) 0 20px, 22 | radial-gradient(20px,#000 97%,#0000) 50% / calc(1.9 * 20px) calc(2 * 20px) repeat space 23 | ; 24 | --mask-edge-scalloped-left: 25 | linear-gradient(to right,#0000 20px,#000 0), 26 | radial-gradient(20px at right,#000 97%,#0000) left / 20px calc(1.9 * 20px) 27 | ; 28 | --mask-edge-scalloped-right: 29 | linear-gradient(to left,#0000 20px,#000 0), 30 | radial-gradient(20px at left,#000 97%,#0000) right / 20px calc(1.9 * 20px) 31 | ; 32 | --mask-edge-scalloped-horizontal: 33 | linear-gradient(-90deg,#0000 calc(2 * 20px),#000 0) 20px, 34 | radial-gradient(20px,#000 97%,#0000) 50% / calc(2 * 20px) calc(1.9 * 20px) space repeat 35 | ; 36 | --mask-edge-drip-bottom: 37 | radial-gradient(20px at bottom,#0000 97%,#000) 50% calc(100% - 20px) / calc(2 * 20px) 100% repeat-x, 38 | radial-gradient(20px at 25% 50%,#000 97%,#0000) calc(50% - 20px) 99% / calc(4 * 20px) calc(2 * 20px) repeat-x 39 | ; 40 | --mask-edge-drip-top: 41 | radial-gradient(20px at top,#0000 97%,#000) 50% 20px / calc(2 * 20px) 100% repeat-x, 42 | radial-gradient(20px at 25% 50%,#000 97%,#0000) calc(50% - 20px) 1% / calc(4 * 20px) calc(2 * 20px) repeat-x 43 | ; 44 | --mask-edge-drip-vertical: 45 | radial-gradient(20px at top ,#0000 97%,#000) 50% 20px / calc(2 * 20px) 51% repeat-x, 46 | radial-gradient(20px at bottom,#0000 97%,#000) 50% calc(100% - 20px) / calc(2 * 20px) 51% repeat-x, 47 | radial-gradient(20px at 25% 50%,#000 97%,#0000) calc(50% - 20px) 1% / calc(4 * 20px) calc(2 * 20px) repeat-x, 48 | radial-gradient(20px at 25% 50%,#000 97%,#0000) calc(50% - 3*20px) 99% / calc(4 * 20px) calc(2 * 20px) repeat-x 49 | ; 50 | --mask-edge-drip-left: 51 | radial-gradient(20px at left,#0000 97%,#000) 20px 50% / 100% calc(2 * 20px) repeat-y, 52 | radial-gradient(20px at 50% 25%,#000 97%,#0000) 1% calc(50% - 20px) / calc(2 * 20px) calc(4 * 20px) repeat-y 53 | ; 54 | --mask-edge-drip-right: 55 | radial-gradient(20px at right,#0000 97%,#000) calc(100% - 20px) 50% / 100% calc(2 * 20px) repeat-y, 56 | radial-gradient(20px at 50% 25%,#000 97%,#0000) 99% calc(50% - 20px) / calc(2 * 20px) calc(4 * 20px) repeat-y 57 | ; 58 | --mask-edge-drip-horizontal: 59 | radial-gradient(20px at left ,#0000 97%,#000) 20px 50% / 51% calc(2 * 20px) repeat-y, 60 | radial-gradient(20px at right,#0000 97%,#000) calc(100% - 20px) 50% / 51% calc(2 * 20px) repeat-y, 61 | radial-gradient(20px at 50% 25%,#000 97%,#0000) 1% calc(50% - 20px) / calc(2 * 20px) calc(4 * 20px) repeat-y, 62 | radial-gradient(20px at 50% 25%,#000 97%,#0000) 99% calc(50% - 3*20px) / calc(2 * 20px) calc(4 * 20px) repeat-y 63 | ; 64 | --mask-edge-zig-zag-top: conic-gradient(from 135deg at top,#0000,#000 1deg 90deg,#0000 91deg) 50% / 40px 100%; 65 | --mask-edge-zig-zag-bottom: conic-gradient(from -45deg at bottom,#0000,#000 1deg 90deg,#0000 91deg) 50% / 40px 100%; 66 | --mask-edge-zig-zag-left: conic-gradient(from 45deg at left,#0000,#000 1deg 90deg,#0000 91deg) 50% / 100% 40px; 67 | --mask-edge-zig-zag-right: conic-gradient(from -135deg at right,#0000,#000 1deg 90deg,#0000 91deg 180deg) 50% / 100% 40px; 68 | --mask-edge-zig-zag-horizontal: repeating-conic-gradient(from 45deg at 20px 50%,#0000,#000 1deg 90deg,#0000 91deg 180deg) -20px 50% / 100% 40px; 69 | --mask-edge-zig-zag-vertical: repeating-conic-gradient(from 135deg at 50% 20px,#0000,#000 1deg 90deg,#0000 91deg 180deg) 50% -20px / 40px 100%; 70 | } 71 | -------------------------------------------------------------------------------- /src/props.masks.edges.js: -------------------------------------------------------------------------------- 1 | // big thanks to Temani Afif: https://twitter.com/ChallengesCss 2 | // https://github.com/argyleink/open-props/discussions/71 3 | export default { 4 | '--mask-edge-scoop-bottom': 'radial-gradient(20px at 50% 100%,#0000 97%,#000) 50% / calc(1.9 * 20px) 100%', 5 | '--mask-edge-scoop-top': 'radial-gradient(20px at 50% 0,#0000 97%,#000) 50% / calc(1.9 * 20px) 100%', 6 | '--mask-edge-scoop-vertical': 'radial-gradient(20px at 50% 20px,#0000 97%,#000) 50% -20px/ calc(1.9 * 20px) 100%', 7 | '--mask-edge-scoop-left': 'radial-gradient(20px at 0 50%,#0000 97%,#000) 50%/ 100% calc(1.9 * 20px)', 8 | '--mask-edge-scoop-right': 'radial-gradient(20px at 100% 50%,#0000 97%,#000) 50%/ 100% calc(1.9 * 20px)', 9 | '--mask-edge-scoop-horizontal': 'radial-gradient(20px at 20px 50%,#0000 97%,#000) -20px/ 100% calc(1.9 * 20px)', 10 | '--mask-edge-scalloped': ` 11 | radial-gradient(farthest-side,#000 97%,#0000) 0 0 / 20px 20px round, 12 | linear-gradient(#000 0 0) 50%/calc(100% - 20px) calc(100% - 20px) no-repeat 13 | `, 14 | '--mask-edge-scalloped-bottom': ` 15 | linear-gradient(to top,#0000 20px,#000 0), 16 | radial-gradient(20px at top,#000 97%,#0000) bottom / calc(1.9 * 20px) 20px 17 | `, 18 | '--mask-edge-scalloped-top': ` 19 | linear-gradient(to bottom,#0000 20px,#000 0), 20 | radial-gradient(20px at bottom,#000 97%,#0000) top / calc(1.9 * 20px) 20px 21 | `, 22 | '--mask-edge-scalloped-vertical': ` 23 | linear-gradient(0deg,#0000 calc(2 * 20px),#000 0) 0 20px, 24 | radial-gradient(20px,#000 97%,#0000) 50% / calc(1.9 * 20px) calc(2 * 20px) repeat space 25 | `, 26 | '--mask-edge-scalloped-left': ` 27 | linear-gradient(to right,#0000 20px,#000 0), 28 | radial-gradient(20px at right,#000 97%,#0000) left / 20px calc(1.9 * 20px) 29 | `, 30 | '--mask-edge-scalloped-right': ` 31 | linear-gradient(to left,#0000 20px,#000 0), 32 | radial-gradient(20px at left,#000 97%,#0000) right / 20px calc(1.9 * 20px) 33 | `, 34 | '--mask-edge-scalloped-horizontal': ` 35 | linear-gradient(-90deg,#0000 calc(2 * 20px),#000 0) 20px, 36 | radial-gradient(20px,#000 97%,#0000) 50% / calc(2 * 20px) calc(1.9 * 20px) space repeat 37 | `, 38 | '--mask-edge-drip-bottom': ` 39 | radial-gradient(20px at bottom,#0000 97%,#000) 50% calc(100% - 20px) / calc(2 * 20px) 100% repeat-x, 40 | radial-gradient(20px at 25% 50%,#000 97%,#0000) calc(50% - 20px) 99% / calc(4 * 20px) calc(2 * 20px) repeat-x 41 | `, 42 | '--mask-edge-drip-top': ` 43 | radial-gradient(20px at top,#0000 97%,#000) 50% 20px / calc(2 * 20px) 100% repeat-x, 44 | radial-gradient(20px at 25% 50%,#000 97%,#0000) calc(50% - 20px) 1% / calc(4 * 20px) calc(2 * 20px) repeat-x 45 | `, 46 | '--mask-edge-drip-vertical': ` 47 | radial-gradient(20px at top ,#0000 97%,#000) 50% 20px / calc(2 * 20px) 51% repeat-x, 48 | radial-gradient(20px at bottom,#0000 97%,#000) 50% calc(100% - 20px) / calc(2 * 20px) 51% repeat-x, 49 | radial-gradient(20px at 25% 50%,#000 97%,#0000) calc(50% - 20px) 1% / calc(4 * 20px) calc(2 * 20px) repeat-x, 50 | radial-gradient(20px at 25% 50%,#000 97%,#0000) calc(50% - 3*20px) 99% / calc(4 * 20px) calc(2 * 20px) repeat-x 51 | `, 52 | '--mask-edge-drip-left': ` 53 | radial-gradient(20px at left,#0000 97%,#000) 20px 50% / 100% calc(2 * 20px) repeat-y, 54 | radial-gradient(20px at 50% 25%,#000 97%,#0000) 1% calc(50% - 20px) / calc(2 * 20px) calc(4 * 20px) repeat-y 55 | `, 56 | '--mask-edge-drip-right': ` 57 | radial-gradient(20px at right,#0000 97%,#000) calc(100% - 20px) 50% / 100% calc(2 * 20px) repeat-y, 58 | radial-gradient(20px at 50% 25%,#000 97%,#0000) 99% calc(50% - 20px) / calc(2 * 20px) calc(4 * 20px) repeat-y 59 | `, 60 | '--mask-edge-drip-horizontal': ` 61 | radial-gradient(20px at left ,#0000 97%,#000) 20px 50% / 51% calc(2 * 20px) repeat-y, 62 | radial-gradient(20px at right,#0000 97%,#000) calc(100% - 20px) 50% / 51% calc(2 * 20px) repeat-y, 63 | radial-gradient(20px at 50% 25%,#000 97%,#0000) 1% calc(50% - 20px) / calc(2 * 20px) calc(4 * 20px) repeat-y, 64 | radial-gradient(20px at 50% 25%,#000 97%,#0000) 99% calc(50% - 3*20px) / calc(2 * 20px) calc(4 * 20px) repeat-y 65 | `, 66 | '--mask-edge-zig-zag-top': 'conic-gradient(from 135deg at top,#0000,#000 1deg 90deg,#0000 91deg) 50% / 40px 100%', 67 | '--mask-edge-zig-zag-bottom': 'conic-gradient(from -45deg at bottom,#0000,#000 1deg 90deg,#0000 91deg) 50% / 40px 100%', 68 | '--mask-edge-zig-zag-left': 'conic-gradient(from 45deg at left,#0000,#000 1deg 90deg,#0000 91deg) 50% / 100% 40px', 69 | '--mask-edge-zig-zag-right': 'conic-gradient(from -135deg at right,#0000,#000 1deg 90deg,#0000 91deg) 50% / 100% 40px', 70 | '--mask-edge-zig-zag-horizontal': `repeating-conic-gradient(from 45deg at 20px 50%,#0000,#000 1deg 90deg,#0000 91deg 180deg) -20px 50% / 100% 40px`, 71 | '--mask-edge-zig-zag-vertical': `repeating-conic-gradient(from 135deg at 50% 20px,#0000,#000 1deg 90deg,#0000 91deg 180deg) 50% -20px / 40px 100%`, 72 | } 73 | -------------------------------------------------------------------------------- /src/props.media.css: -------------------------------------------------------------------------------- 1 | @custom-media --motionOK (prefers-reduced-motion: no-preference); 2 | @custom-media --motionNotOK (prefers-reduced-motion: reduce); 3 | @custom-media --opacityOK (prefers-reduced-transparency: no-preference); 4 | @custom-media --opacityNotOK (prefers-reduced-transparency: reduce); 5 | @custom-media --useDataOK (prefers-reduced-data: no-preference); 6 | @custom-media --useDataNotOK (prefers-reduced-data: reduce); 7 | 8 | @custom-media --OSdark (prefers-color-scheme: dark); 9 | @custom-media --OSlight (prefers-color-scheme: light); 10 | 11 | @custom-media --highContrast (prefers-contrast: more); 12 | @custom-media --lowContrast (prefers-contrast: less); 13 | 14 | @custom-media --invertedColors (inverted-colors: inverted); 15 | @custom-media --forcedColors (forced-colors: active); 16 | 17 | @custom-media --portrait (orientation: portrait); 18 | @custom-media --landscape (orientation: landscape); 19 | 20 | @custom-media --HDcolor (dynamic-range: high) or (color-gamut: p3); 21 | 22 | @custom-media --touch (hover: none) and (pointer: coarse); 23 | @custom-media --stylus (hover: none) and (pointer: fine); 24 | @custom-media --pointer (hover) and (pointer: coarse); 25 | @custom-media --mouse (hover) and (pointer: fine); 26 | 27 | @custom-media --xxs-only (0px <= width < 240px); 28 | @custom-media --xxs-n-above (width >= 240px); 29 | @custom-media --xxs-n-below (width < 240px); 30 | @custom-media --xxs-phone (--xxs-only) and (--portrait); 31 | 32 | @custom-media --xs-only (240px <= width < 360px); 33 | @custom-media --xs-n-above (width >= 360px); 34 | @custom-media --xs-n-below (width < 360px); 35 | @custom-media --xs-phone (--xs-only) and (--portrait); 36 | 37 | @custom-media --sm-only (360px <= width < 480px); 38 | @custom-media --sm-n-above (width >= 480px); 39 | @custom-media --sm-n-below (width < 480px); 40 | @custom-media --sm-phone (--sm-only) and (--portrait); 41 | 42 | @custom-media --md-only (480px <= width < 768px); 43 | @custom-media --md-n-above (width >= 768px); 44 | @custom-media --md-n-below (width < 768px); 45 | @custom-media --md-phone (--md-only) and (--portrait); 46 | 47 | @custom-media --lg-only (768px <= width < 1024px); 48 | @custom-media --lg-n-above (width >= 1024px); 49 | @custom-media --lg-n-below (width < 1024px); 50 | @custom-media --lg-phone (--lg-only) and (--portrait); 51 | 52 | @custom-media --xl-only (1024px <= width < 1440px); 53 | @custom-media --xl-n-above (width >= 1440px); 54 | @custom-media --xl-n-below (width < 1440px); 55 | 56 | @custom-media --xxl-only (1440px <= width < 1920px); 57 | @custom-media --xxl-n-above (width >= 1920px); 58 | @custom-media --xxl-n-below (width < 1920px); -------------------------------------------------------------------------------- /src/props.media.js: -------------------------------------------------------------------------------- 1 | export const CustomMedia = { 2 | "--motionOK": "(prefers-reduced-motion: no-preference)", 3 | "--motionNotOK": "(prefers-reduced-motion: reduce)", 4 | "--opacityOK": "(prefers-reduced-transparency: no-preference)", 5 | "--opacityNotOK": "(prefers-reduced-transparency: reduce)", 6 | "--useDataOK": "(prefers-reduced-data: no-preference)", 7 | "--useDataNotOK": "(prefers-reduced-data: reduce)", 8 | 9 | "--OSdark": "(prefers-color-scheme: dark)", 10 | "--OSlight": "(prefers-color-scheme: light)", 11 | 12 | "--highContrast": "(prefers-contrast: more)", 13 | "--lowContrast": "(prefers-contrast: less)", 14 | 15 | "--invertedColors": "(inverted-colors: inverted)", 16 | "--forcedColors": "(forced-colors: active)", 17 | 18 | "--portrait": "(orientation: portrait)", 19 | "--landscape": "(orientation: landscape)", 20 | 21 | "--HDcolor": "(dynamic-range: high) or (color-gamut: p3)", 22 | 23 | "--touch": "(hover: none) and (pointer: coarse)", 24 | "--stylus": "(hover: none) and (pointer: fine)", 25 | "--pointer": "(hover) and (pointer: coarse)", 26 | "--mouse": "(hover) and (pointer: fine)", 27 | 28 | "--xxs-only": "(0px <= width < 240px)", 29 | "--xxs-n-above": "(width >= 240px)", 30 | "--xxs-n-below": "(width < 240px)", 31 | "--xxs-phone": "(--xxs-only) and (--portrait)", 32 | 33 | "--xs-only": "(240px <= width < 360px)", 34 | "--xs-n-above": "(width >= 360px)", 35 | "--xs-n-below": "(width < 360px)", 36 | "--xs-phone": "(--xs-only) and (--portrait)", 37 | 38 | "--sm-only": "(360px <= width < 480px)", 39 | "--sm-n-above": "(width >= 480px)", 40 | "--sm-n-below": "(width < 480px)", 41 | "--sm-phone": "(--sm-only) and (--portrait)", 42 | 43 | "--md-only": "(480px <= width < 768px)", 44 | "--md-n-above": "(width >= 768px)", 45 | "--md-n-below": "(width < 768px)", 46 | "--md-phone": "(--md-only) and (--portrait)", 47 | 48 | "--lg-only": "(768px <= width < 1024px)", 49 | "--lg-n-above": "(width >= 1024px)", 50 | "--lg-n-below": "(width < 1024px)", 51 | "--lg-phone": "(--lg-only) and (--portrait)", 52 | 53 | "--xl-only": "(1024px <= width < 1440px)", 54 | "--xl-n-above": "(width >= 1440px)", 55 | "--xl-n-below": "(width < 1440px)", 56 | 57 | "--xxl-only": "(1440px <= width < 1920px)", 58 | "--xxl-n-above": "(width >= 1920px)", 59 | "--xxl-n-below": "(width < 1920px)", 60 | } -------------------------------------------------------------------------------- /src/props.orange-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --orange-0-hsl: 34 100% 95%; 3 | --orange-1-hsl: 33 100% 90%; 4 | --orange-2-hsl: 33 100% 83%; 5 | --orange-3-hsl: 32 100% 74%; 6 | --orange-4-hsl: 31 100% 65%; 7 | --orange-5-hsl: 29 100% 58%; 8 | --orange-6-hsl: 27 98% 54%; 9 | --orange-7-hsl: 24 94% 50%; 10 | --orange-8-hsl: 21 90% 48%; 11 | --orange-9-hsl: 17 87% 45%; 12 | --orange-10-hsl: 17 87% 40%; 13 | --orange-11-hsl: 17 87% 32%; 14 | --orange-12-hsl: 17 87% 27%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.orange.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --orange-0: #fff4e6; 3 | --orange-1: #ffe8cc; 4 | --orange-2: #ffd8a8; 5 | --orange-3: #ffc078; 6 | --orange-4: #ffa94d; 7 | --orange-5: #ff922b; 8 | --orange-6: #fd7e14; 9 | --orange-7: #f76707; 10 | --orange-8: #e8590c; 11 | --orange-9: #d9480f; 12 | --orange-10: #bf400d; 13 | --orange-11: #99330b; 14 | --orange-12: #802b09; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.pink-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --pink-0-hsl: 336 100% 97%; 3 | --pink-1-hsl: 336 100% 94%; 4 | --pink-2-hsl: 338 91% 87%; 5 | --pink-3-hsl: 339 90% 81%; 6 | --pink-4-hsl: 339 88% 74%; 7 | --pink-5-hsl: 339 82% 67%; 8 | --pink-6-hsl: 339 76% 59%; 9 | --pink-7-hsl: 339 67% 52%; 10 | --pink-8-hsl: 339 68% 45%; 11 | --pink-9-hsl: 339 69% 38%; 12 | --pink-10-hsl: 339 70% 32%; 13 | --pink-11-hsl: 339 69% 27%; 14 | --pink-12-hsl: 339 70% 21%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.pink.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --pink-0: #fff0f6; 3 | --pink-1: #ffdeeb; 4 | --pink-2: #fcc2d7; 5 | --pink-3: #faa2c1; 6 | --pink-4: #f783ac; 7 | --pink-5: #f06595; 8 | --pink-6: #e64980; 9 | --pink-7: #d6336c; 10 | --pink-8: #c2255c; 11 | --pink-9: #a61e4d; 12 | --pink-10: #8c1941; 13 | --pink-11: #731536; 14 | --pink-12: #59102a; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.purple-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --purple-0-hsl: 280 67% 96%; 3 | --purple-1-hsl: 287 77% 92%; 4 | --purple-2-hsl: 288 86% 86%; 5 | --purple-3-hsl: 289 85% 78%; 6 | --purple-4-hsl: 288 83% 71%; 7 | --purple-5-hsl: 288 75% 64%; 8 | --purple-6-hsl: 288 67% 58%; 9 | --purple-7-hsl: 288 56% 52%; 10 | --purple-8-hsl: 288 54% 46%; 11 | --purple-9-hsl: 288 54% 40%; 12 | --purple-10-hsl: 288 55% 33%; 13 | --purple-11-hsl: 288 56% 26%; 14 | --purple-12-hsl: 288 55% 20%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.purple.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --purple-0: #f8f0fc; 3 | --purple-1: #f3d9fa; 4 | --purple-2: #eebefa; 5 | --purple-3: #e599f7; 6 | --purple-4: #da77f2; 7 | --purple-5: #cc5de8; 8 | --purple-6: #be4bdb; 9 | --purple-7: #ae3ec9; 10 | --purple-8: #9c36b5; 11 | --purple-9: #862e9c; 12 | --purple-10: #702682; 13 | --purple-11: #5a1e69; 14 | --purple-12: #44174f; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.red-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --red-0-hsl: 0 100% 98%; 3 | --red-1-hsl: 0 100% 95%; 4 | --red-2-hsl: 0 100% 89%; 5 | --red-3-hsl: 0 100% 83%; 6 | --red-4-hsl: 0 100% 76%; 7 | --red-5-hsl: 0 100% 71%; 8 | --red-6-hsl: 0 94% 65%; 9 | --red-7-hsl: 0 86% 59%; 10 | --red-8-hsl: 0 74% 54%; 11 | --red-9-hsl: 0 65% 48%; 12 | --red-10-hsl: 0 65% 42%; 13 | --red-11-hsl: 0 65% 36%; 14 | --red-12-hsl: 0 66% 30%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.red.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --red-0: #fff5f5; 3 | --red-1: #ffe3e3; 4 | --red-2: #ffc9c9; 5 | --red-3: #ffa8a8; 6 | --red-4: #ff8787; 7 | --red-5: #ff6b6b; 8 | --red-6: #fa5252; 9 | --red-7: #f03e3e; 10 | --red-8: #e03131; 11 | --red-9: #c92a2a; 12 | --red-10: #b02525; 13 | --red-11: #962020; 14 | --red-12: #7d1a1a; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.sand-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --sand-0-hsl: 200 27% 98%; 3 | --sand-1-hsl: 48 17% 88%; 4 | --sand-2-hsl: 45 22% 79%; 5 | --sand-3-hsl: 44 22% 69%; 6 | --sand-4-hsl: 44 17% 62%; 7 | --sand-5-hsl: 44 14% 54%; 8 | --sand-6-hsl: 42 14% 46%; 9 | --sand-7-hsl: 43 16% 39%; 10 | --sand-8-hsl: 41 15% 32%; 11 | --sand-9-hsl: 43 14% 26%; 12 | --sand-10-hsl: 44 11% 20%; 13 | --sand-11-hsl: 60 6% 14%; 14 | --sand-12-hsl: 60 6% 7%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.sand.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --sand-0: #f8fafb; 3 | --sand-1: #e6e4dc; 4 | --sand-2: #d5cfbd; 5 | --sand-3: #c2b9a0; 6 | --sand-4: #aea58c; 7 | --sand-5: #9a9178; 8 | --sand-6: #867c65; 9 | --sand-7: #736a53; 10 | --sand-8: #5f5746; 11 | --sand-9: #4b4639; 12 | --sand-10: #38352d; 13 | --sand-11: #252521; 14 | --sand-12: #121210; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.shadows.css: -------------------------------------------------------------------------------- 1 | @import 'props.media.css'; 2 | 3 | :where(html) { 4 | --shadow-color: 220 3% 15%; 5 | --shadow-strength: 1%; 6 | --inner-shadow-highlight: inset 0 -.5px 0 0 #fff, inset 0 .5px 0 0 #0001; 7 | --shadow-1: 0 1px 2px -1px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)); 8 | --shadow-2: 9 | 0 3px 5px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 10 | 0 7px 14px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)); 11 | --shadow-3: 12 | 0 -1px 3px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 13 | 0 1px 2px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 14 | 0 2px 5px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 4%)), 15 | 0 4px 12px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)), 16 | 0 12px 15px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 7%)); 17 | --shadow-4: 18 | 0 -2px 5px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 19 | 0 1px 1px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 20 | 0 2px 2px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 21 | 0 5px 5px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 4%)), 22 | 0 9px 9px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)), 23 | 0 16px 16px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 6%)); 24 | --shadow-5: 25 | 0 -1px 2px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 26 | 0 2px 1px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 27 | 0 5px 5px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 28 | 0 10px 10px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 4%)), 29 | 0 20px 20px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)), 30 | 0 40px 40px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 7%)); 31 | --shadow-6: 32 | 0 -1px 2px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 33 | 0 3px 2px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 34 | 0 7px 5px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 35 | 0 12px 10px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 4%)), 36 | 0 22px 18px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)), 37 | 0 41px 33px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 6%)), 38 | 0 100px 80px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 7%)); 39 | --inner-shadow-0: inset 0 0 0 1px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)); 40 | --inner-shadow-1: inset 0 1px 2px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)), var(--inner-shadow-highlight); 41 | --inner-shadow-2: inset 0 1px 4px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)), var(--inner-shadow-highlight); 42 | --inner-shadow-3: inset 0 2px 8px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)), var(--inner-shadow-highlight); 43 | --inner-shadow-4: inset 0 2px 14px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)), var(--inner-shadow-highlight); 44 | } 45 | 46 | @media (--OSdark) { 47 | :where(html) { 48 | --shadow-color: 220 40% 2%; 49 | --shadow-strength: 25%; 50 | --inner-shadow-highlight: inset 0 -.5px 0 0 #fff1, inset 0 .5px 0 0 #0007; 51 | } 52 | } -------------------------------------------------------------------------------- /src/props.shadows.js: -------------------------------------------------------------------------------- 1 | const Shadows = { 2 | '--shadow-color': '220 3% 15%', 3 | '--shadow-strength': '1%', 4 | 5 | '--shadow-color-@media:dark': '220 40% 2%', 6 | '--shadow-strength-@media:dark': '25%', 7 | 8 | '--inner-shadow-highlight': 'inset 0 -.5px 0 0 #fff, inset 0 .5px 0 0 #0001', 9 | '--inner-shadow-highlight-@media:dark': 'inset 0 -.5px 0 0 #fff1, inset 0 .5px 0 0 #0007', 10 | 11 | '--shadow-1': '0 1px 2px -1px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%))', 12 | '--shadow-2': ` 13 | 0 3px 5px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 14 | 0 7px 14px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%))`, 15 | '--shadow-3': ` 16 | 0 -1px 3px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 17 | 0 1px 2px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 18 | 0 2px 5px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 4%)), 19 | 0 4px 12px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)), 20 | 0 12px 15px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 7%))`, 21 | '--shadow-4': ` 22 | 0 -2px 5px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 23 | 0 1px 1px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 24 | 0 2px 2px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 25 | 0 5px 5px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 4%)), 26 | 0 9px 9px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)), 27 | 0 16px 16px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 6%))`, 28 | '--shadow-5': ` 29 | 0 -1px 2px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 30 | 0 2px 1px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 31 | 0 5px 5px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 32 | 0 10px 10px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 4%)), 33 | 0 20px 20px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)), 34 | 0 40px 40px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 7%))`, 35 | '--shadow-6': ` 36 | 0 -1px 2px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)), 37 | 0 3px 2px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 38 | 0 7px 5px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)), 39 | 0 12px 10px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 4%)), 40 | 0 22px 18px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%)), 41 | 0 41px 33px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 6%)), 42 | 0 100px 80px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 7%))`, 43 | 44 | '--inner-shadow-0': 'inset 0 0 0 1px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%))', 45 | '--inner-shadow-1': 'inset 0 1px 2px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)), var(--inner-shadow-highlight)', 46 | '--inner-shadow-2': 'inset 0 1px 4px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)), var(--inner-shadow-highlight)', 47 | '--inner-shadow-3': 'inset 0 2px 8px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)), var(--inner-shadow-highlight)', 48 | '--inner-shadow-4': 'inset 0 2px 14px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%)), var(--inner-shadow-highlight)', 49 | } 50 | 51 | export default Shadows 52 | 53 | export const StaticShadows = Object.fromEntries( 54 | Object.entries(Shadows) 55 | .map(([key,value]) => { 56 | value = value.replace(/var(--shadow-color)/g, Shadows['--shadow-color']) 57 | value = value.replace(/var(--shadow-strength)/g, Shadows['--shadow-strength']) 58 | return [key, value] 59 | }) 60 | .filter(([key]) => 61 | !['--shadow-color', '--shadow-strength'].includes(key) 62 | ) 63 | ) 64 | -------------------------------------------------------------------------------- /src/props.sizes.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --size-000: -.5rem; 3 | --size-00: -.25rem; 4 | --size-1: .25rem; 5 | --size-2: .5rem; 6 | --size-3: 1rem; 7 | --size-4: 1.25rem; 8 | --size-5: 1.5rem; 9 | --size-6: 1.75rem; 10 | --size-7: 2rem; 11 | --size-8: 3rem; 12 | --size-9: 4rem; 13 | --size-10: 5rem; 14 | --size-11: 7.5rem; 15 | --size-12: 10rem; 16 | --size-13: 15rem; 17 | --size-14: 20rem; 18 | --size-15: 30rem; 19 | --size-px-000: -8px; 20 | --size-px-00: -4px; 21 | --size-px-1: 4px; 22 | --size-px-2: 8px; 23 | --size-px-3: 16px; 24 | --size-px-4: 20px; 25 | --size-px-5: 24px; 26 | --size-px-6: 28px; 27 | --size-px-7: 32px; 28 | --size-px-8: 48px; 29 | --size-px-9: 64px; 30 | --size-px-10: 80px; 31 | --size-px-11: 120px; 32 | --size-px-12: 160px; 33 | --size-px-13: 240px; 34 | --size-px-14: 320px; 35 | --size-px-15: 480px; 36 | --size-fluid-1: clamp(.5rem, 1vw, 1rem); 37 | --size-fluid-2: clamp(1rem, 2vw, 1.5rem); 38 | --size-fluid-3: clamp(1.5rem, 3vw, 2rem); 39 | --size-fluid-4: clamp(2rem, 4vw, 3rem); 40 | --size-fluid-5: clamp(4rem, 5vw, 5rem); 41 | --size-fluid-6: clamp(5rem, 7vw, 7.5rem); 42 | --size-fluid-7: clamp(7.5rem, 10vw, 10rem); 43 | --size-fluid-8: clamp(10rem, 20vw, 15rem); 44 | --size-fluid-9: clamp(15rem, 30vw, 20rem); 45 | --size-fluid-10: clamp(20rem, 40vw, 30rem); 46 | --size-content-1: 20ch; 47 | --size-content-2: 45ch; 48 | --size-content-3: 60ch; 49 | --size-header-1: 20ch; 50 | --size-header-2: 25ch; 51 | --size-header-3: 35ch; 52 | --size-xxs: 240px; 53 | --size-xs: 360px; 54 | --size-sm: 480px; 55 | --size-md: 768px; 56 | --size-lg: 1024px; 57 | --size-xl: 1440px; 58 | --size-xxl: 1920px; 59 | --size-relative-000: -.5ch; 60 | --size-relative-00: -.25ch; 61 | --size-relative-1: .25ch; 62 | --size-relative-2: .5ch; 63 | --size-relative-3: 1ch; 64 | --size-relative-4: 1.25ch; 65 | --size-relative-5: 1.5ch; 66 | --size-relative-6: 1.75ch; 67 | --size-relative-7: 2ch; 68 | --size-relative-8: 3ch; 69 | --size-relative-9: 4ch; 70 | --size-relative-10: 5ch; 71 | --size-relative-11: 7.5ch; 72 | --size-relative-12: 10ch; 73 | --size-relative-13: 15ch; 74 | --size-relative-14: 20ch; 75 | --size-relative-15: 30ch; 76 | } 77 | -------------------------------------------------------------------------------- /src/props.sizes.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--size-000': '-.5rem', 3 | '--size-00': '-.25rem', 4 | '--size-1': '.25rem', 5 | '--size-2': '.5rem', 6 | '--size-3': '1rem', 7 | '--size-4': '1.25rem', 8 | '--size-5': '1.5rem', 9 | '--size-6': '1.75rem', 10 | '--size-7': '2rem', 11 | '--size-8': '3rem', 12 | '--size-9': '4rem', 13 | '--size-10': '5rem', 14 | '--size-11': '7.5rem', 15 | '--size-12': '10rem', 16 | '--size-13': '15rem', 17 | '--size-14': '20rem', 18 | '--size-15': '30rem', 19 | 20 | '--size-px-000': '-8px', 21 | '--size-px-00': '-4px', 22 | '--size-px-1': '4px', 23 | '--size-px-2': '8px', 24 | '--size-px-3': '16px', 25 | '--size-px-4': '20px', 26 | '--size-px-5': '24px', 27 | '--size-px-6': '28px', 28 | '--size-px-7': '32px', 29 | '--size-px-8': '48px', 30 | '--size-px-9': '64px', 31 | '--size-px-10': '80px', 32 | '--size-px-11': '120px', 33 | '--size-px-12': '160px', 34 | '--size-px-13': '240px', 35 | '--size-px-14': '320px', 36 | '--size-px-15': '480px', 37 | 38 | '--size-fluid-1': 'clamp(.5rem, 1vw, 1rem)', 39 | '--size-fluid-2': 'clamp(1rem, 2vw, 1.5rem)', 40 | '--size-fluid-3': 'clamp(1.5rem, 3vw, 2rem)', 41 | '--size-fluid-4': 'clamp(2rem, 4vw, 3rem)', 42 | '--size-fluid-5': 'clamp(4rem, 5vw, 5rem)', 43 | '--size-fluid-6': 'clamp(5rem, 7vw, 7.5rem)', 44 | '--size-fluid-7': 'clamp(7.5rem, 10vw, 10rem)', 45 | '--size-fluid-8': 'clamp(10rem, 20vw, 15rem)', 46 | '--size-fluid-9': 'clamp(15rem, 30vw, 20rem)', 47 | '--size-fluid-10': 'clamp(20rem, 40vw, 30rem)', 48 | 49 | '--size-content-1': '20ch', 50 | '--size-content-2': '45ch', 51 | '--size-content-3': '60ch', 52 | 53 | '--size-header-1': '20ch', 54 | '--size-header-2': '25ch', 55 | '--size-header-3': '35ch', 56 | 57 | '--size-xxs': '240px', 58 | '--size-xs': '360px', 59 | '--size-sm': '480px', 60 | '--size-md': '768px', 61 | '--size-lg': '1024px', 62 | '--size-xl': '1440px', 63 | '--size-xxl': '1920px', 64 | 65 | '--size-relative-000': '-.5ch', 66 | '--size-relative-00': '-.25ch', 67 | '--size-relative-1': '.25ch', 68 | '--size-relative-2': '.5ch', 69 | '--size-relative-3': '1ch', 70 | '--size-relative-4': '1.25ch', 71 | '--size-relative-5': '1.5ch', 72 | '--size-relative-6': '1.75ch', 73 | '--size-relative-7': '2ch', 74 | '--size-relative-8': '3ch', 75 | '--size-relative-9': '4ch', 76 | '--size-relative-10': '5ch', 77 | '--size-relative-11': '7.5ch', 78 | '--size-relative-12': '10ch', 79 | '--size-relative-13': '15ch', 80 | '--size-relative-14': '20ch', 81 | '--size-relative-15': '30ch', 82 | } 83 | -------------------------------------------------------------------------------- /src/props.stone-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --stone-0-hsl: 200 27% 98%; 3 | --stone-1-hsl: 210 18% 96%; 4 | --stone-2-hsl: 210 11% 93%; 5 | --stone-3-hsl: 192 9% 89%; 6 | --stone-4-hsl: 197 8% 83%; 7 | --stone-5-hsl: 202 5% 71%; 8 | --stone-6-hsl: 200 3% 60%; 9 | --stone-7-hsl: 180 2% 50%; 10 | --stone-8-hsl: 160 1% 41%; 11 | --stone-9-hsl: 90 1% 31%; 12 | --stone-10-hsl: 60 3% 22%; 13 | --stone-11-hsl: 60 6% 14%; 14 | --stone-12-hsl: 60 6% 7%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.stone.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --stone-0: #f8fafb; 3 | --stone-1: #f2f4f6; 4 | --stone-2: #ebedef; 5 | --stone-3: #e0e4e5; 6 | --stone-4: #d1d6d8; 7 | --stone-5: #b1b6b9; 8 | --stone-6: #979b9d; 9 | --stone-7: #7e8282; 10 | --stone-8: #666968; 11 | --stone-9: #50514f; 12 | --stone-10: #3a3a37; 13 | --stone-11: #252521; 14 | --stone-12: #121210; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.supports.css: -------------------------------------------------------------------------------- 1 | @custom-media --safariONLY (-apple-pay-button-style: inherit); 2 | @custom-media --firefoxONLY (-moz-appearance: inherit); 3 | @custom-media --firefoxMacONLY (-moz-osx-font-smoothing: inherit); 4 | @custom-media --chromeONLY (-webkit-app-region: inherit) and (not (container-type: none)); 5 | @custom-media --chromiumONLY (-webkit-app-region: inherit) and (container-type: none); 6 | @custom-media --webkitONLY (alt: inherit) and (not (-apple-pay-button-style: inherit)); 7 | 8 | :where(html) { 9 | --isLTR: 1; 10 | --isRTL: -1; 11 | 12 | &:dir(rtl) { 13 | --isLTR: -1; 14 | --isRTL: 1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/props.svg.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --squircle-1: url("data:image/svg+xml,%3Csvg viewbox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d=' M 0, 75 C 0, 18.75 18.75, 0 75, 0 S 150, 18.75 150, 75 131.25, 150 75, 150 0, 131.25 0, 75 ' fill='%23FADB5F' transform='rotate( 0, 100, 100 ) translate( 25 25 )'%3E%3C/path%3E%3C/svg%3E"); 3 | --squircle-2: url("data:image/svg+xml,%3Csvg viewbox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d=' M 0, 75 C 0, 13.500000000000004 13.500000000000004, 0 75, 0 S 150, 13.500000000000004 150, 75 136.5, 150 75, 150 0, 136.5 0, 75 ' fill='%23FADB5F' transform='rotate( 0, 100, 100 ) translate( 25 25 )'%3E%3C/path%3E%3C/svg%3E"); 4 | --squircle-3: url("data:image/svg+xml,%3Csvg viewbox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d=' M 0, 75 C 0, 5.999999999999997 5.999999999999997, 0 75, 0 S 150, 5.999999999999997 150, 75 144, 150 75, 150 0, 144 0, 75 ' fill='%23FADB5F' transform='rotate( 0, 100, 100 ) translate( 25 25 )'%3E%3C/path%3E%3C/svg%3E"); 5 | } 6 | -------------------------------------------------------------------------------- /src/props.svg.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--squircle-1': `url("data:image/svg+xml,%3Csvg viewbox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d=' M 0, 75 C 0, 18.75 18.75, 0 75, 0 S 150, 18.75 150, 75 131.25, 150 75, 150 0, 131.25 0, 75 ' fill='%23FADB5F' transform='rotate( 0, 100, 100 ) translate( 25 25 )'%3E%3C/path%3E%3C/svg%3E")`, 3 | '--squircle-2': `url("data:image/svg+xml,%3Csvg viewbox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d=' M 0, 75 C 0, 13.500000000000004 13.500000000000004, 0 75, 0 S 150, 13.500000000000004 150, 75 136.5, 150 75, 150 0, 136.5 0, 75 ' fill='%23FADB5F' transform='rotate( 0, 100, 100 ) translate( 25 25 )'%3E%3C/path%3E%3C/svg%3E")`, 4 | '--squircle-3': `url("data:image/svg+xml,%3Csvg viewbox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d=' M 0, 75 C 0, 5.999999999999997 5.999999999999997, 0 75, 0 S 150, 5.999999999999997 150, 75 144, 150 75, 150 0, 144 0, 75 ' fill='%23FADB5F' transform='rotate( 0, 100, 100 ) translate( 25 25 )'%3E%3C/path%3E%3C/svg%3E")`, 5 | } 6 | -------------------------------------------------------------------------------- /src/props.teal-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --teal-0-hsl: 161 79% 95%; 3 | --teal-1-hsl: 160 85% 87%; 4 | --teal-2-hsl: 162 78% 77%; 5 | --teal-3-hsl: 162 72% 65%; 6 | --teal-4-hsl: 162 68% 54%; 7 | --teal-5-hsl: 162 73% 46%; 8 | --teal-6-hsl: 162 82% 40%; 9 | --teal-7-hsl: 162 87% 35%; 10 | --teal-8-hsl: 162 88% 30%; 11 | --teal-9-hsl: 162 88% 26%; 12 | --teal-10-hsl: 162 89% 21%; 13 | --teal-11-hsl: 162 88% 16%; 14 | --teal-12-hsl: 163 89% 11%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.teal.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --teal-0: #e6fcf5; 3 | --teal-1: #c3fae8; 4 | --teal-2: #96f2d7; 5 | --teal-3: #63e6be; 6 | --teal-4: #38d9a9; 7 | --teal-5: #20c997; 8 | --teal-6: #12b886; 9 | --teal-7: #0ca678; 10 | --teal-8: #099268; 11 | --teal-9: #087f5b; 12 | --teal-10: #066649; 13 | --teal-11: #054d37; 14 | --teal-12: #033325; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.violet-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --violet-0-hsl: 252 100% 97%; 3 | --violet-1-hsl: 257 100% 93%; 4 | --violet-2-hsl: 256 100% 87%; 5 | --violet-3-hsl: 255 94% 79%; 6 | --violet-4-hsl: 255 93% 72%; 7 | --violet-5-hsl: 255 91% 67%; 8 | --violet-6-hsl: 255 86% 63%; 9 | --violet-7-hsl: 255 78% 60%; 10 | --violet-8-hsl: 255 67% 55%; 11 | --violet-9-hsl: 255 53% 50%; 12 | --violet-10-hsl: 255 53% 44%; 13 | --violet-11-hsl: 255 53% 37%; 14 | --violet-12-hsl: 255 53% 31%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.violet.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --violet-0: #f3f0ff; 3 | --violet-1: #e5dbff; 4 | --violet-2: #d0bfff; 5 | --violet-3: #b197fc; 6 | --violet-4: #9775fa; 7 | --violet-5: #845ef7; 8 | --violet-6: #7950f2; 9 | --violet-7: #7048e8; 10 | --violet-8: #6741d9; 11 | --violet-9: #5f3dc4; 12 | --violet-10: #5235ab; 13 | --violet-11: #462d91; 14 | --violet-12: #3a2578; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.yellow-hsl.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --yellow-0-hsl: 50 100% 93%; 3 | --yellow-1-hsl: 49 100% 87%; 4 | --yellow-2-hsl: 49 100% 80%; 5 | --yellow-3-hsl: 48 100% 70%; 6 | --yellow-4-hsl: 47 100% 62%; 7 | --yellow-5-hsl: 45 97% 54%; 8 | --yellow-6-hsl: 42 96% 50%; 9 | --yellow-7-hsl: 39 100% 48%; 10 | --yellow-8-hsl: 35 100% 47%; 11 | --yellow-9-hsl: 31 100% 45%; 12 | --yellow-10-hsl: 31 100% 35%; 13 | --yellow-11-hsl: 31 100% 25%; 14 | --yellow-12-hsl: 31 100% 20%; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.yellow.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --yellow-0: #fff9db; 3 | --yellow-1: #fff3bf; 4 | --yellow-2: #ffec99; 5 | --yellow-3: #ffe066; 6 | --yellow-4: #ffd43b; 7 | --yellow-5: #fcc419; 8 | --yellow-6: #fab005; 9 | --yellow-7: #f59f00; 10 | --yellow-8: #f08c00; 11 | --yellow-9: #e67700; 12 | --yellow-10: #b35c00; 13 | --yellow-11: #804200; 14 | --yellow-12: #663500; 15 | } 16 | -------------------------------------------------------------------------------- /src/props.zindex.css: -------------------------------------------------------------------------------- 1 | :where(html) { 2 | --layer-1: 1; 3 | --layer-2: 2; 4 | --layer-3: 3; 5 | --layer-4: 4; 6 | --layer-5: 5; 7 | --layer-important: 2147483647; 8 | } 9 | -------------------------------------------------------------------------------- /src/props.zindex.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '--layer-1': 1, 3 | '--layer-2': 2, 4 | '--layer-3': 3, 5 | '--layer-4': 4, 6 | '--layer-5': 5, 7 | '--layer-important': 2147483647, 8 | } 9 | -------------------------------------------------------------------------------- /test/basic.test.cjs: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const fs = require('fs') 3 | const OpenProps = require('../dist/open-props.cjs') 4 | const OPtokens = require('../open-props.tokens.json') 5 | 6 | test('Should have an all included import', t => { 7 | t.is(Object.keys(OpenProps).length, 1736) 8 | }) 9 | 10 | test('Import should have animations', async t => { 11 | t.assert(Object.keys(OpenProps).includes('--animation-fade-in')) 12 | t.assert(OpenProps.animationFadeIn) 13 | t.assert(Object.keys(OpenProps).includes('--animation-fade-in-@')) 14 | }) 15 | 16 | test('Import should have sizes', async t => { 17 | t.assert(Object.keys(OpenProps).includes('--size-5')) 18 | t.assert(OpenProps.size5) 19 | }) 20 | 21 | test('Import should have colors', async t => { 22 | t.assert(Object.keys(OpenProps).includes('--orange-0')) 23 | t.assert(OpenProps.orange0) 24 | }) 25 | 26 | test('JSON Import should have colors', async t => { 27 | t.is(Object.keys(OPtokens).length, 463) 28 | t.assert(Object.keys(OPtokens).includes('--orange-0')) 29 | }) 30 | 31 | test('JSON Import should have types', async t => { 32 | t.assert(OPtokens['--gray-0'].$type, 'color') 33 | }) 34 | 35 | test('Should produce a props bundle', async t => { 36 | t.assert(fs.existsSync('./open-props.min.css')) 37 | }) 38 | 39 | test('Should produce shadow :host props', async t => { 40 | t.assert(fs.existsSync('./open-props.shadow.min.css')) 41 | t.assert(fs.existsSync('./easings.shadow.min.css')) 42 | t.assert(fs.existsSync('./shadows.shadow.min.css')) 43 | }) 44 | 45 | test('Should produce normalize files', async t => { 46 | t.assert(fs.existsSync('./normalize.min.css')) 47 | t.assert(fs.existsSync('./normalize.light.min.css')) 48 | t.assert(fs.existsSync('./normalize.dark.min.css')) 49 | }) 50 | 51 | test('Should produce optional mask props', async t => { 52 | t.assert(fs.existsSync('./masks.edges.min.css')) 53 | t.assert(fs.existsSync('./masks.corner-cuts.min.css')) 54 | }) 55 | 56 | test('Should produce typings files', async t => { 57 | t.assert(fs.existsSync('./dist/open-props.module.d.ts')) 58 | t.assert(fs.existsSync('./src/props.sizes.d.ts')) 59 | }) 60 | 61 | test('References should be valid', async t => { 62 | const formatter = new Intl.ListFormat(); 63 | const defined = new Set(); 64 | const referenced = new Set(); 65 | const referencedBy = new Map(); 66 | 67 | for (const [prop, value] of Object.entries(OpenProps)) { 68 | // Add all defined variables to the defined set 69 | defined.add(prop) 70 | 71 | if (typeof value !== 'string') { 72 | continue; 73 | } 74 | 75 | // Find all references to other variables: var(...) 76 | const matches = value.matchAll(/var\(([^)]+)\)/g); 77 | 78 | if (!matches) { 79 | continue; 80 | } 81 | 82 | // Add all references to the referenced set 83 | // Map all references to the prop that references them 84 | for (const matchArray of matches) { 85 | const reference = matchArray[1]; 86 | 87 | referenced.add(reference); 88 | 89 | if (!prop.startsWith('--')) { 90 | continue; 91 | } 92 | 93 | if (!referencedBy.has(reference)) { 94 | referencedBy.set(reference, new Set()); 95 | } 96 | 97 | referencedBy.get(reference).add(prop); 98 | } 99 | } 100 | 101 | // Check that all referenced variables are defined 102 | for (const reference of referenced) { 103 | const referencing = formatter.format(Array.from(referencedBy.get(reference))); 104 | 105 | t.assert( 106 | defined.has(reference), 107 | `Variable with name ${reference} was referenced by variable ${referencing}, but is not defined` 108 | ); 109 | } 110 | }) -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "declaration": true, 5 | "emitDeclarationOnly": true, 6 | "esModuleInterop": true, 7 | "target": "ESNext", 8 | "module": "ESNext", 9 | "moduleResolution": "NodeNext", 10 | "skipLibCheck": true 11 | }, 12 | "include": ["dist/open-props.module.js", "src/props.*.js"], 13 | "exclude": ["node_modules", "src/*.src.js"] 14 | } 15 | --------------------------------------------------------------------------------