diff --git a/bun.lockb b/bun.lockb index 2454e02..74b89ee 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/packages/components/.gitignore b/packages/components/.gitignore new file mode 100644 index 0000000..9b1ee42 --- /dev/null +++ b/packages/components/.gitignore @@ -0,0 +1,175 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/packages/components/README.md b/packages/components/README.md new file mode 100644 index 0000000..999eaf9 --- /dev/null +++ b/packages/components/README.md @@ -0,0 +1,15 @@ +# mini-strap-components + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run components.scss +``` + +This project was created using `bun init` in bun v1.1.27. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/packages/components/package.json b/packages/components/package.json new file mode 100644 index 0000000..5dcfbc8 --- /dev/null +++ b/packages/components/package.json @@ -0,0 +1,12 @@ +{ + "name": "mini-strap-components", + "module": "src/components.scss", + "type": "module", + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5.0.0" + } +} + diff --git a/packages/components/src/components.scss b/packages/components/src/components.scss new file mode 100644 index 0000000..5cae0db --- /dev/null +++ b/packages/components/src/components.scss @@ -0,0 +1,8 @@ +.btn { + padding: var(--msp-spacing-1); +} + +.btn-primary { + background-color: var(--msp--primary-bg); + color: var(--msp--primary-text); +} diff --git a/packages/components/tsconfig.json b/packages/components/tsconfig.json new file mode 100644 index 0000000..238655f --- /dev/null +++ b/packages/components/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} diff --git a/packages/core/_variables.scss b/packages/core/_variables.scss new file mode 100644 index 0000000..a1850a7 --- /dev/null +++ b/packages/core/_variables.scss @@ -0,0 +1,83 @@ +@use "sass:color"; + +/* Using catppuccin for now, make a theme switcher later */ +@use "./themes/catppuccin/catppuccin"; + +@function getColor($color) { + $ctp-theme: map-get(catppuccin.$palette, "macchiato"); + @return map-get($ctp-theme, $color); +} + +/* +* ╭───────────────────────────────────────────────────────────╮ +* │ Mini-Strap Design Tokens │ +* ╰───────────────────────────────────────────────────────────╯ +* */ + +// ── Structure and convention ──────────────────────────────────────────── + +/* +* +* */ + +/* Taken from Tailwind: https://tailwindcss.com/docs/container#using-the-container */ +$screen-sizes: ( + "sm": 640px, + "md": 768px, + "lg": 1024px, + "xl": 1280px, + "2xl": 1536px, +); + +$spacings: ( + 0 "--prj-spacing-0" 0, + 1 "--prj-spacing-1" 0.25rem, + 2 "--prj-spacing-2" 0.5rem, + 3 "--prj-spacing-3" 1rem, + 4 "--prj-spacing-4" 2rem, + 5 "--prj-spacing-5" 3rem +); + +$border-radius: 0.5rem; + +// Native CSS Variables to allow overridings and usage in external stylesheets +:root { + /* Variables prefixed with prj to avoid collisions */ + + /* Colors are inspired by Material Design: https://m2.material.io/design/color/the-color-system.html */ + --prj-bg: #{getColor("mantle")}; + --prj-bg-transparent: #{color.scale(getColor("mantle"), $alpha: -10%)}; + --prj-shadow: #{getColor("crust")}; + --prj-text: #{getColor("text")}; + + --prj-surface-1: #{getColor("base")}; + --prj-surface-2: #{darken(getColor("surface0"), 2%)}; + --prj-surface-3: #{getColor("surface1")}; + --prj-surface-text: #{getColor("text")}; + + --prj-link-text: #{getColor("teal")}; + + --prj-accent-bg: #{getColor("teal")}; + --prj-accent-text: #{getColor("base")}; + + --prj-primary: #{getColor("teal")}; + --prj-primary-text: #{getColor("base")}; + + --prj-secondary: #{getColor("mauve")}; + --prj-secondary-text: #{getColor("base")}; + + --prj-danger: #{getColor("red")}; + --prj-danger-text: #{getColor("base")}; + + --prj-disabled: #{getColor("red")}; + --prj-disabled-text: rgba(#{getColor("raw")}, 0.5); + + --prj-input: #{getColor("text")}; + --prj-input-text: #{getColor("base")}; + + @each $index, $variable, $value in $spacings { + #{$variable}: #{$value}; + } + + --prj-border-radius: #{$border-radius}; +} diff --git a/packages/core/src/_mixins.scss b/packages/core/src/_mixins.scss index e5abe23..a986741 100644 --- a/packages/core/src/_mixins.scss +++ b/packages/core/src/_mixins.scss @@ -15,3 +15,12 @@ } } } + +@mixin hover-darker() { + transition: filter 0.15s ease-in-out; + filter: brightness(1); + + &:hover { + filter: brightness(0.9); + } +} diff --git a/packages/core/src/_reset.scss b/packages/core/src/_reset.scss new file mode 100644 index 0000000..c4e42f8 --- /dev/null +++ b/packages/core/src/_reset.scss @@ -0,0 +1,187 @@ +/* + * ╭─────────────────────────────────────────────────────────────────╮ + * │ Reset borrowed from https://github.com/kkrishguptaa/reseter.css │ + * ╰─────────────────────────────────────────────────────────────────╯ +*/ + +// ── Global ────────────────────────────────────────────────────────────── + +*, +*::before, +*::after { + box-sizing: inherit; + background-clip: inherit; + padding: 0; + margin: 0; +} + +:where(:root) { + box-sizing: border-box; + background-clip: padding-box; + line-height: 1.5; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, + Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; +} + +:where(main) { + display: block; +} + +:where(h1) { + font-size: 2em; + margin: 0.67em 0; +} + +:where(p + p) { + margin-top: 1rem; +} + +// ── Forms ─────────────────────────────────────────────────────────────── +:where(button, input, optgroup, select, textarea) { + line-height: inherit; + border: 1px solid currentColor; +} + +:where(button) { + overflow: visible; + text-transform: none; +} + +:where(button, [type="button"], [type="reset"], [type="submit"]) { + -webkit-appearance: button; + padding: 1px 6px; + &:not(:disabled) { + cursor: pointer; + } +} + +:where(input) { + overflow: visible; +} + +:where(input, textarea) { + padding: 1px; +} + +:where(fieldset) { + border: 1px solid currentColor; + margin: 0 2px; +} + +:where(legend) { + color: inherit; + display: table; + max-width: 100%; + white-space: normal; +} + +:where(progress) { + display: inline-block; + vertical-align: baseline; +} + +:where(select) { + text-transform: none; +} + +:where(textarea) { + overflow: auto; + vertical-align: top; +} + +:where([type="search"]) { + -webkit-appearance: textfield; + outline-offset: -2px; +} + +:where([type="color"]) { + background: inherit; +} + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +::-webkit-input-placeholder { + color: inherit; + opacity: 0.5; +} + +::-webkit-search-decoration, +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} + +::-moz-focus-inner { + border: 0; +} + +:-moz-focusring { + outline: 1px dotted ButtonText; +} + +:-moz-ui-invalid { + box-shadow: none; +} + +// ── Text ──────────────────────────────────────────────────────────────── + +:where(a) { + background-color: transparent; +} + +:where(abbr[title]) { + text-decoration: underline dotted; +} + +:where(code, kbd, samp, pre) { + font-family: monospace, monospace; + font-size: 1em; +} + +:where(sub, sup) { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +:where(sub) { + bottom: -0.25em; +} + +:where(sup) { + top: -0.5em; +} + +// ── Other ─────────────────────────────────────────────────────────────── + +:where(a) { + background-color: transparent; +} + +:where(abbr[title]) { + text-decoration: underline dotted; +} + +:where(code, kbd, samp, pre) { + font-family: monospace, monospace; + font-size: 1em; +} + +:where(sub, sup) { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +:where(sub) { + bottom: -0.25em; +} + +:where(sup) { + top: -0.5em; +} diff --git a/packages/core/src/_tokens.scss b/packages/core/src/_tokens.scss index 460d536..1d0957b 100644 --- a/packages/core/src/_tokens.scss +++ b/packages/core/src/_tokens.scss @@ -44,44 +44,58 @@ $spacings: ( $border-radius: 0.5rem; +/* Colors are inspired by Material Design: https://m2.material.io/design/color/the-color-system.html */ +$msp-colors: ( + "--msp-color-bg": #{getColor("mantle")}, + "--msp-color-bg-transparent": #{color.scale(getColor("mantle"), $alpha: -10%)}, + "--msp-color-bg-surface-1": #{getColor("base")}, + "--msp-color-bg-surface-2": #{darken(getColor("surface0"), 2%)}, + "--msp-color-bg-surface-3": #{getColor("surface1")}, + + "--msp-color-bg-accent": #{getColor("teal")}, + "--msp-color-bg-primary": #{getColor("teal")}, + "--msp-color-bg-secondary": #{getColor("mauve")}, + "--msp-color-bg-danger": #{getColor("red")}, + "--msp-color-bg-disabled": #{getColor("red")}, + "--msp-color-bg-input": #{getColor("text")}, + "--msp-color-bg-checkbox": #{getColor("teal")}, + "--msp-color-bg-range": #{getColor("surface1")}, + "--msp-color-bg-btn": #{getColor("teal")}, + + "--msp-color-text": #{getColor("text")}, + "--msp-color-text-surface": #{getColor("text")}, + "--msp-color-text-link": #{getColor("teal")}, + "--msp-color-text-accent": #{getColor("base")}, + "--msp-color-text-primary": #{getColor("base")}, + "--msp-color-text-secondary": #{getColor("base")}, + "--msp-color-text-danger": #{getColor("base")}, + "--msp-color-text-disabled": #{color.scale(getColor("text"), $alpha: -30%)}, + "--msp-color-text-input": #{getColor("base")}, + "--msp-color-text-input-disabled": #{color.scale( + getColor("base"), + $alpha: -30% + )}, + "--msp-color-text-checkbox": #{getColor("surface1")}, + "--msp-color-text-range": #{getColor("teal")}, + "--msp-color-text-btn": #{getColor("base")}, + + "--msp-color-shadow": #{getColor("crust")}, + "--msp-color-transparent": transparent, +); + // Native CSS Variables to allow overridings and usage in external stylesheets :root { - /* Variables prefixed with prj to avoid collisions */ - - /* Colors are inspired by Material Design: https://m2.material.io/design/color/the-color-system.html */ - --msp-bg: #{getColor("mantle")}; - --msp-bg-transparent: #{color.scale(getColor("mantle"), $alpha: -10%)}; - --msp-shadow: #{getColor("crust")}; - --msp-text: #{getColor("text")}; - - --msp-surface-1: #{getColor("base")}; - --msp-surface-2: #{darken(getColor("surface0"), 2%)}; - --msp-surface-3: #{getColor("surface1")}; - --msp-surface-text: #{getColor("text")}; - - --msp-link-text: #{getColor("teal")}; - - --msp-accent-bg: #{getColor("teal")}; - --msp-accent-text: #{getColor("base")}; - - --msp-primary: #{getColor("teal")}; - --msp-primary-text: #{getColor("base")}; - - --msp-secondary: #{getColor("mauve")}; - --msp-secondary-text: #{getColor("base")}; - - --msp-danger: #{getColor("red")}; - --msp-danger-text: #{getColor("base")}; - - --msp-disabled: #{getColor("red")}; - --msp-disabled-text: rgba(#{getColor("raw")}, 0.5); - - --msp-input: #{getColor("text")}; - --msp-input-text: #{getColor("base")}; + @each $variable, $value in $msp-colors { + #{$variable}: #{$value}; + } @each $index, $variable, $value in $spacings { #{$variable}: #{$value}; } - --msp-border-radius: #{$border-radius}; + // ── Borders ───────────────────────────────────────────────────────────── + --msp-border-width: 1px; + --msp-border-color: var(--msp-color-bg-transparent); + --msp-border-style: solid; + --msp-border-radius: 0.2rem; } diff --git a/packages/core/src/_utils.scss b/packages/core/src/_utils.scss index 16045d5..82968ee 100644 --- a/packages/core/src/_utils.scss +++ b/packages/core/src/_utils.scss @@ -1,33 +1,33 @@ @use "./tokens" as *; @use "./mixins"; -.position-fixed { +.msp-position-fixed { position: fixed; left: 0; top: 0; z-index: 2; } -.position-sticky { +.msp-position-sticky { position: sticky; left: 0; top: 0; z-index: 2; } -.d-none { +.msp-d-none { display: none; } -.d-block { +.msp-d-block { display: block; } -.d-flex { +.msp-d-flex { display: flex; } -.visually-hidden { +.msp-visually-hidden { height: 0; width: 0; position: absolute; @@ -35,46 +35,46 @@ } @include mixins.responsive using($breakpoint, $size) { - .d-#{$breakpoint}-none { + .msp-d-#{$breakpoint}-none { display: none; } - .d-#{$breakpoint}-block { + .msp-d-#{$breakpoint}-block { display: block; } - .d-#{$breakpoint}-flex { + .msp-d-#{$breakpoint}-flex { display: flex; } } -.flex-eq > * { +.msp-flex-eq > * { flex: 100%; } -.flex-column { +.msp-flex-column { flex-direction: column !important; } -.flex-row { +.msp-flex-row { flex-direction: row !important; } @include mixins.responsive using($breakpoint, $size) { - .flex-#{$breakpoint}-column { + .msp-flex-#{$breakpoint}-column { flex-direction: column !important; } - .flex-#{$breakpoint}-row { + .msp-flex-#{$breakpoint}-row { flex-direction: row !important; } } -.hstack { +.msp-hstack { --prj-gap: var(--prj-spacing-3); display: flex; gap: var(--prj-gap); align-items: center; } -.hstack-reverse { +.msp-hstack-reverse { --prj-gap: var(--prj-spacing-3); display: flex; gap: var(--prj-gap); @@ -82,63 +82,63 @@ flex-direction: row-reverse; } -.vstack { +.msp-vstack { --prj-gap: var(--prj-spacing-3); display: flex; gap: var(--prj-gap); flex-direction: column; } -.vstack-reverse { +.msp-vstack-reverse { --prj-gap: var(--prj-spacing-3); display: flex; flex-direction: column-reverse; } -.flex-grow { +.msp-flex-grow { flex-grow: 1; } -.flex-wrap { +.msp-flex-wrap { flex-wrap: wrap; } -.flex-nowrap { +.msp-flex-nowrap { flex-wrap: nowrap; } @include mixins.responsive using($breakpoint, $size) { - .flex-#{$breakpoint}-wrap { + .msp-flex-#{$breakpoint}-wrap { flex-wrap: wrap; } - .flex-#{$breakpoint}-nowrap { + .msp-flex-#{$breakpoint}-nowrap { flex-wrap: nowrap; } } -.flex-center { +.msp-flex-center { display: flex; justify-content: center; align-items: center; } -.justify-content-center { +.msp-justify-content-center { justify-content: center !important; } -.justify-content-between { +.msp-justify-content-between { justify-content: space-between !important; } -.justify-content-around { +.msp-justify-content-around { justify-content: space-around !important; } -.align-items-center { +.msp-align-items-center { align-items: center !important; } -.grid { +.msp-grid { --prj-gap: var(--prj-spacing-3); --prj-columns: repeat(3, 1fr); --prj-min-col-width: 150px; @@ -152,81 +152,81 @@ } @for $i from 1 through 12 { - .grid-cols-#{$i} { + .msp-grid-cols-#{$i} { @include grid-cols($i); } } @include mixins.responsive-steps(1, 12) using ($breakpoint, $index) { - .grid-#{$breakpoint}-cols-#{$index} { + .msp-grid-#{$breakpoint}-cols-#{$index} { @include grid-cols($index); } } -.list-unstyle { +.msp-list-unstyle { list-style: none; } -.text-justify { +.msp-text-justify { text-align: justify; text-justify: inter-word; } -.text-start { +.msp-text-start { text-align: start; } -.text-center { +.msp-text-center { text-align: center; } -.text-end { +.msp-text-end { text-align: end; } -.align-start { +.msp-align-start { vertical-align: start; } -.align-center { +.msp-align-center { vertical-align: middle; } -.align-end { +.msp-align-end { vertical-align: end; } -.overflow-scroll { +.msp-overflow-scroll { overflow: scroll; } -.overflow-x-scroll { +.msp-overflow-x-scroll { overflow-x: scroll; } -.overflow-y-scroll { +.msp-overflow-y-scroll { overflow-y: scroll; } -.w-auto { +.msp-w-auto { width: auto; } -.h-auto { +.msp-h-auto { height: auto; } @for $i from 0 through 100 { - .w-#{$i} { + .msp-w-#{$i} { width: percentage(calc($i / 100)); } - .h-#{$i} { + .msp-h-#{$i} { height: percentage(calc($i / 100)); } } @include mixins.responsive-steps(0, 100) using ($breakpoint, $index) { - .w-#{$breakpoint}-#{$index} { + .msp-w-#{$breakpoint}-#{$index} { width: percentage(calc($index / 100)); } - .h-#{$breakpoint}-#{$index} { + .msp-h-#{$breakpoint}-#{$index} { height: percentage(calc($index / 100)); } } @@ -236,54 +236,54 @@ $name: "#{$breakpoint}-#{$name}"; } - .m-#{$name} { + .msp-m-#{$name} { margin: $value !important; } - .mx-#{$name} { + .msp-mx-#{$name} { margin-left: $value !important; margin-right: $value !important; } - .my-#{$name} { + .msp-my-#{$name} { margin-top: $value !important; margin-bottom: $value !important; } - .mt-#{$name} { + .msp-mt-#{$name} { margin-top: $value !important; } - .mb-#{$name} { + .msp-mb-#{$name} { margin-bottom: $value !important; } - .ml-#{$name} { + .msp-ml-#{$name} { margin-left: $value !important; } - .mr-#{$name} { + .msp-mr-#{$name} { margin-right: $value !important; } - .p-#{$name} { + .msp-p-#{$name} { padding: $value !important; } - .px-#{$name} { + .msp-px-#{$name} { padding-left: $value !important; padding-right: $value !important; } - .py-#{$name} { + .msp-py-#{$name} { padding-top: $value !important; padding-bottom: $value !important; } - .pt-#{$name} { + .msp-pt-#{$name} { padding-top: $value !important; } - .pb-#{$name} { + .msp-pb-#{$name} { padding-bottom: $value !important; } - .pl-#{$name} { + .msp-pl-#{$name} { padding-left: $value !important; } - .pr-#{$name} { + .msp-pr-#{$name} { padding-right: $value !important; } - .gap-#{$name} { + .msp-gap-#{$name} { --prj-gap: #{$value}; } } @@ -300,30 +300,30 @@ } } -.shadow-0 { +.msp-shadow-0 { box-shadow: none; } -.shadow-1 { +.msp-shadow-1 { box-shadow: 10px 10px 5px 0px var(--prj-shadow); } -.border-radius { +.msp-border-radius { border-radius: var(--prj-border-radius); } -.text-none { +.msp-text-none { text-transform: none; } -.text-capitalize { +.msp-text-capitalize { text-transform: capitalize; } -.text-uppercase { +.msp-text-uppercase { text-transform: uppercase; } -.text-uppercase { +.msp-text-uppercase { text-transform: uppercase; } -.text-lowercase { +.msp-text-lowercase { text-transform: lowercase; } diff --git a/packages/core/src/components/form.scss b/packages/core/src/components/form.scss new file mode 100644 index 0000000..1ad5205 --- /dev/null +++ b/packages/core/src/components/form.scss @@ -0,0 +1,217 @@ +@use "../tokens" as *; +@use "../mixins"; +@use "sass:color"; +@use "sass:string"; + +fieldset:not(.msp-fieldset-border) { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +fieldset.msp-fieldset-border { + padding: var(--msp-spacing-2); + margin: 0; + border-radius: var(--msp-border-radius); + border: var(--msp-border-width) var(--msp-border-style) var(--msp-color-text); +} + +label { + display: inline-block; + margin-bottom: var(--msp-spacing-1); +} + +select, +input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not( + [type="range"] + ) { + display: block; + border-radius: var(--msp-border-radius); + border: var(--msp-border-width) var(--msp-border-style) + var(--msp-border-color); + width: 100%; + background-color: var(--msp-color-bg-input); + color: var(--msp-color-text-input); + + padding: var(--msp-spacing-1); + font-size: 0.8rem; +} + +input[type="checkbox"] + label { + display: inline-block; + margin-bottom: initial; +} + +input[type="checkbox"] { + float: left; + background-color: var(--msp-color-bg-input); + + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + + border-radius: var(--msp-border-radius); + border: var(--msp-border-width) var(--msp-border-style) + var(--msp-border-bg-input); + background-color: var(--msp-color-bg-input); + background-image: var(--msp-form-check-bg-image); + background-repeat: no-repeat; + background-position: center; + background-size: contain; + + $size: 0.75rem; + + width: $size; + height: $size; + + margin-top: 0.425rem; + margin-right: var(--msp-spacing-1); + + &:checked { + background-color: var(--msp-color-bg-checkbox); + border-color: var(--msp-color-bg-checkbox); + + $stroke-color: "%23#{string.slice(map-get($msp-colors, "--msp-color-text-checkbox"), 2, -1)}"; + --msp-form-check-bg-image: url('data:image/svg+xml,'); + } +} + +input[type="radio"] { + float: left; + background-color: var(--msp-color-bg-input); + + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + + border-radius: 50%; + border: var(--msp-border-width) var(--msp-border-style) + var(--msp-border-bg-input); + background-color: var(--msp-color-bg-input); + background-image: var(--msp-form-check-bg-image); + background-repeat: no-repeat; + background-position: center; + background-size: contain; + + $size: 0.75rem; + + width: $size; + height: $size; + + margin-top: 0.425rem; + margin-right: var(--msp-spacing-1); + + &:checked { + background-color: var(--msp-color-bg-checkbox); + border-color: var(--msp-color-bg-checkbox); + + $fill-color: "%23#{string.slice(map-get($msp-colors, "--msp-color-text-checkbox"), 2, -1)}"; + --msp-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='#{$fill-color}'/%3e%3c/svg%3e"); + } +} + +input[type="color"] { + display: block; + border-radius: var(--msp-border-radius); + border: var(--msp-border-width) var(--msp-border-style) + var(--msp-color-bg-input); + padding: var(--msp-spacing-1); + width: 3rem; + height: 2rem; + + background-color: var(--msp-color-bg-input); + + &::-moz-color-swatch { + padding: var(--msp-spacing-1); + border-radius: var(--msp-border-radius); + border: 0; + } +} + +input[type="range"] { + background-color: transparent; + + display: block; + width: 100%; + // color: var(--msp-color-text-input); + + border-color: transparent; + &::-moz-range-thumb { + background-color: var(--msp-color-text-range); + width: 1rem; + height: 1rem; + border-radius: 50%; + border: 0; + } + &::-moz-range-track { + background-color: var(--msp-color-bg-range); + color: transparent; + border-color: transparent; + width: 100%; + height: 0.5rem; + border-radius: var(--msp-border-radius); + } +} + +input:disabled::placeholder, +input::placeholder, +select:disabled, +option:disabled { + opacity: 1; + color: var(--msp-color-text-input-disabled); +} + +input:disabled { + background: var(--msp-color-bg-disabled); +} + +.form-control[type="file"] { + &:not(:disabled):not([readonly]) { + cursor: pointer; + } + + overflow: hidden; + + @include mixins.hover-darker; + + &.form-control::file-selector-button { + background-color: inherit; + padding-right: var(--msp-spacing-2); + margin-right: var(--msp-spacing-2); + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: var(--msp-border-width); + border-radius: 0; + } +} + +.msp-form-text-help { + margin-top: var(--msp-spacing-1); + font-size: 0.875em; + color: var(--msp-color-text-disabled); +} + +[type="submit"]:not(:disabled), +button:not(:disabled) { + cursor: pointer; +} + +button { + display: inline-block; + padding: var(--msp-spacing-1) var(--msp-spacing-2); + background: var(--msp-color-bg-btn); + font-size: 1rem; + color: var(--msp-color-text-btn); + text-align: center; + text-decoration: none; + vertical-align: middle; + cursor: pointer; + border: var(--msp-border-width) var(--msp-border-style) + var(--msp-color-bg-btn); + border-radius: var(--msp-border-radius); + + @include mixins.hover-darker; +} diff --git a/packages/core/src/style.scss b/packages/core/src/style.scss index a1916b2..846c9ab 100644 --- a/packages/core/src/style.scss +++ b/packages/core/src/style.scss @@ -1,14 +1,16 @@ +@use "./reset"; @use "./tokens.scss" as *; @use "./utils.scss"; @use "./animations.scss"; @use "./mixins"; +@use "./components/form"; + // SASS variables are imported without namespace, but try to always use native // CSS variables when possible so they can be overrwritten by custom styles - html { - background-color: var(--msp-bg); - color: var(--msp-text); + background-color: var(--msp-color-bg); + color: var(--msp-color-text); /* Update font size based on screen width, source: https://matthewjamestaylor.com/responsive-font-size */ font-size: calc(15px + 0.390625vw); @@ -23,8 +25,8 @@ body > main { section:not(.clean) { /* outline: 1px solid var(--msp-accent-bg); */ padding: var(--msp-spacing-3); - background-color: var(--msp-surface-1); - box-shadow: 10px 10px 5px 0px var(--msp-shadow); + background-color: var(--msp-color-bg-surface-1); + box-shadow: 10px 10px 5px 0px var(--msp-color-shadow); border-radius: var(--msp-border-radius); } @@ -85,7 +87,7 @@ p:last-child { } a { - color: var(--msp-link-text); + color: var(--msp-color-text-link); } ul { @@ -123,49 +125,3 @@ video.respect-height { li:not(:last-child) { margin-bottom: var(--msp-spacing-1); } - -.btn { - padding: var(--msp-spacing-1); -} - -.btn-primary { - background-color: var(--msp--primary-bg); - color: var(--msp--primary-text); -} - -/* Lightgallery iframe fix */ -.lg-has-iframe { - position: absolute; - top: 0; - left: 0; - .lg-object { - width: 100% !important; - height: 100% !important; - } -} - -.bg-image { - background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), - var(--bg-image); - background-position: center; - background-size: cover; - color: var(--msp-text); - - padding: var(--msp-spacing-3); - - .text { - padding: var(--msp-spacing-2); - background-color: var(--msp-bg-transparent); - - border-radius: var(--msp-border-radius); - } -} - -a { - transition: text-shadow 0.2s; - --anim-shadow-color: var(--msp-accent-bg); - - &:not(.clean):hover { - text-shadow: 1px 1px 8px var(--anim-shadow-color); - } -} diff --git a/packages/website/package.json b/packages/website/package.json index e0e8177..2114401 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -14,6 +14,7 @@ "vite": "^5.4.1" }, "dependencies": { + "handlebars": "^4.7.8", "mini-strap-core": "workspace:*" } } diff --git a/packages/website/src/counter.ts b/packages/website/src/counter.ts deleted file mode 100644 index 09e5afd..0000000 --- a/packages/website/src/counter.ts +++ /dev/null @@ -1,9 +0,0 @@ -export function setupCounter(element: HTMLButtonElement) { - let counter = 0 - const setCounter = (count: number) => { - counter = count - element.innerHTML = `count is ${counter}` - } - element.addEventListener('click', () => setCounter(counter + 1)) - setCounter(0) -} diff --git a/packages/website/src/main.ts b/packages/website/src/main.ts index cc2bd2f..f5095bb 100644 --- a/packages/website/src/main.ts +++ b/packages/website/src/main.ts @@ -1,24 +1,12 @@ import "mini-strap-core"; -import typescriptLogo from "./typescript.svg"; -import viteLogo from "/vite.svg"; -import { setupCounter } from "./counter.ts"; +import render from "./render"; + +import layout from "./templates/form.html"; document.querySelector("#app")!.innerHTML = ` - - - - - - - Vite + TypeScript - - - - - Click on the Vite and TypeScript logos to learn more - + + ${render(layout, { name: "ale" })} + `; - -setupCounter(document.querySelector("#counter")!); diff --git a/packages/website/src/render.ts b/packages/website/src/render.ts new file mode 100644 index 0000000..23684e4 --- /dev/null +++ b/packages/website/src/render.ts @@ -0,0 +1,11 @@ +import Handlebars from "handlebars"; + +export default function (template: string, data: Record) { + const engine = Handlebars.compile(template); + + return engine(data); +} + +export function mapRender(items: string[]) { + return items.join("\n"); +} diff --git a/packages/website/src/templates/form.html b/packages/website/src/templates/form.html new file mode 100644 index 0000000..50fedf6 --- /dev/null +++ b/packages/website/src/templates/form.html @@ -0,0 +1,127 @@ + + + + Email address + + + We'll never share your email with anyone else. + + + + Password + + + + + Check me out + + + + + + Default radio + + + + + + Default range + + + + + + Select + + Open this select menu + One + Two + Three + + + + + Default file input example + + + + + Color picker + + + + Submit + + + + + + + + Disabled fieldset example + + Disabled input + + + + Disabled select menu + + Disabled select + + + + + + + Can't check this + + + + Submit + + diff --git a/packages/website/src/templates/layout.html b/packages/website/src/templates/layout.html new file mode 100644 index 0000000..f0b8800 --- /dev/null +++ b/packages/website/src/templates/layout.html @@ -0,0 +1 @@ +{{name}} diff --git a/packages/website/src/typescript.svg b/packages/website/src/typescript.svg deleted file mode 100644 index d91c910..0000000 --- a/packages/website/src/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/website/src/vite-env.d.ts b/packages/website/src/vite-env.d.ts index 11f02fe..0dc7f4a 100644 --- a/packages/website/src/vite-env.d.ts +++ b/packages/website/src/vite-env.d.ts @@ -1 +1,4 @@ /// + +declare module "*.html"; +declare module "*.md"; diff --git a/packages/website/vite.config.ts b/packages/website/vite.config.ts new file mode 100644 index 0000000..f38a931 --- /dev/null +++ b/packages/website/vite.config.ts @@ -0,0 +1,26 @@ +import { defineConfig } from "vite"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + // Custom plugin to load markdown files + { + name: "markdown-loader", + transform(code, id) { + if (id.slice(-3) === ".md") { + // For .md files, get the raw content + return `export default ${JSON.stringify(code)};`; + } + }, + }, + { + name: "html-loader", + transform(code, id) { + if (id.slice(-5) === ".html") { + // For .md files, get the raw content + return `export default ${JSON.stringify(code)};`; + } + }, + }, + ], +});
- Click on the Vite and TypeScript logos to learn more -