From 144b7a2ea83507c98544d14ad9435cc5e51ac071 Mon Sep 17 00:00:00 2001 From: Volpeon Date: Sat, 5 Feb 2022 12:26:35 +0100 Subject: Update --- .stylelintrc.json | 2 +- package.json | 8 +- src/_general.scss | 82 +++++++++++++ src/_vars.scss | 85 ++++++++------ src/index.scss | 47 ++++++-- src/layouts/_card.scss | 38 ++++++ src/layouts/_container.scss | 91 ++++++++++++++ src/mixins/_grid.scss | 88 ++++++++++++++ src/mixins/_typography.scss | 63 ++++++++++ src/objects/_heading.scss | 68 +++++++++++ src/objects/_rule.scss | 120 +++++++++++++++++++ static/script.js | 26 ++++ tpl/index.pug | 281 +------------------------------------------- tpl/layouts/container.pug | 14 +-- tpl/objects/heading.pug | 34 ++++++ tpl/objects/rule.pug | 12 ++ 16 files changed, 724 insertions(+), 335 deletions(-) create mode 100644 src/_general.scss create mode 100644 src/layouts/_card.scss create mode 100644 src/layouts/_container.scss create mode 100644 src/mixins/_grid.scss create mode 100644 src/mixins/_typography.scss create mode 100644 src/objects/_heading.scss create mode 100644 src/objects/_rule.scss create mode 100644 static/script.js create mode 100644 tpl/objects/heading.pug create mode 100644 tpl/objects/rule.pug diff --git a/.stylelintrc.json b/.stylelintrc.json index 63040f7..864ce42 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -58,7 +58,7 @@ }, "overrides": [ { - "files": ["src/style/**/*.scss"], + "files": ["src/**/*.scss"], "customSyntax": "postcss-scss" } ] diff --git a/package.json b/package.json index 2ee3eb8..2d6bba6 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,10 @@ "scripts": { "build": "npm run build:app && npm run build:style && npm run build:assets", "build:assets": "cp -r static/* public/", - "build:app": "pug tpl -p tpl --out public/", - "build:style": "sass --load-path=node_modules src/index.scss >> public/style.css", - "lint:style": "stylelint \"src/style/**/*.scss\"", - "fix:style": "stylelint \"src/style/**/*.scss\" --fix" + "build:app": "pug tpl/index.pug -p tpl --out public/", + "build:style": "sass --load-path=node_modules src/index.scss public/style.css", + "lint:style": "stylelint \"src/**/*.scss\"", + "fix:style": "stylelint \"src/**/*.scss\" --fix" }, "dependencies": { "include-media": "^1.4.9", diff --git a/src/_general.scss b/src/_general.scss new file mode 100644 index 0000000..82b9467 --- /dev/null +++ b/src/_general.scss @@ -0,0 +1,82 @@ +@use 'iro-sass/src/index' as iro; +@use 'mixins/typography'; +@use 'vars'; + +html, +body { + height: 100%; +} + +body { + @include typography.set-font(vars.$font--main, (size: iro.props-get(--dims --font-size --md))); + + margin: 0; + padding: 0; + background-color: iro.props-get(--colors --bg); + color: iro.props-get(--colors --fg); +} + +h1, +h2, +h3, +h4, +h5, +h6 { + @include typography.set-font(vars.$font--main, (size: iro.props-get(--dims --font-size --md), weight: 400)); + + margin: 0; +} + +p { + margin-top: iro.props-get(--dims --paragraph --margin-top); + margin-bottom: 0; + + &:empty { + display: none; + } +} + +ul, +ol { + margin: iro.props-get(--dims --paragraph --margin-top) 0 0; + padding-left: iro.props-get(--dims --list --indent); +} + +:focus { + outline: 0; +} + +:link, +:visited { + color: currentColor; + text-decoration: none; +} + +button { + box-sizing: content-box; + margin: 0; + padding: 0; + border: 0; + background-color: transparent; + color: currentColor; + font: inherit; + letter-spacing: inherit; + text-align: left; + text-transform: inherit; + appearance: none; + + &::-moz-focus-inner { + border: 0; + } +} + +::selection { + background: iro.props-get(--colors --selection --bg); + color: iro.props-get(--colors --selection --fg); +} + +img { + &::selection { + background: iro.props-get(--colors --selection --bg-img); + } +} diff --git a/src/_vars.scss b/src/_vars.scss index 5a6c1d0..d2bdf38 100644 --- a/src/_vars.scss +++ b/src/_vars.scss @@ -1,13 +1,14 @@ @use 'iro-sass/src/index' as iro; +@use 'include-media/dist/include-media' as media; iro.$vars-root-size: 16px; -$breakpoints: ( +media.$breakpoints: ( md: 40rem, sm: 28rem ); -$unit-intervals: ( +media.$unit-intervals: ( 'px': 1, 'em': .01, 'rem': .01, @@ -22,45 +23,15 @@ $font--main: ( ); $font--headline: ( - family: ('IBM Plex Sans', 'Open Sans', 'Segoe UI', 'Droid Sans', Roboto, Oxygen, 'Helvetica Neue', Helvetica, Tahoma, Arial, sans-serif), - line-height: 1.2, - weight: 700, + family: ('IBM Plex Sans', 'Open Sans', 'Segoe UI', 'Droid Sans', Roboto, Oxygen, 'Helvetica Neue', Helvetica, Tahoma, Arial, sans-serif), + line-height: 1.2, + weight: 700, ); $line-height: map-get($font--main, line-height); // -$theme-light: ( - --gray1: hsl(210, 0%, 100%), // 1.11 - --gray2: hsl(210, 0%, 98%), // 1.07 - --gray3: hsl(210, 0%, 95%), // 1 - --gray4: hsl(210, 0%, 90%), // 1.11 - --gray5: hsl(210, 0%, 87%), // 1.2 - --gray6: hsl(210, 0%, 78%), // 1.51 - --gray7: hsl(210, 0%, 69%), // 1.93 - --gray8: hsl(210, 0%, 55%), // 3 - --gray9: hsl(210, 0%, 38%), // 5.53 - --gray10: hsl(210, 0%, 19%), // 11.78 - --gray11: hsl(210, 0%, 0%), // 18.75 -); - -$theme-lighter: ( - --gray1: hsl(210, 0%, 100%), // 1 - --gray2: hsl(210, 0%, 100%), // 1 - --gray3: hsl(210, 0%, 100%), // 1 - --gray4: hsl(210, 0%, 95%), // 1.11 - --gray5: hsl(210, 0%, 92%), // 1.19 - --gray6: hsl(210, 0%, 82%), // 1.52 - --gray7: hsl(210, 0%, 73%), // 1.94 - --gray8: hsl(210, 0%, 58%), // 3.03 - --gray9: hsl(210, 0%, 41%), // 5.48 - --gray10: hsl(210, 0%, 22%), // 11.72 - --gray11: hsl(210, 0%, 0%), // 21 -); - -// - @include iro.fn-execute { $primary-accent-base: hsl(222, 49.8%, 52.4%); $error-accent-base: hsl(352, 49.8%, 52.4%); @@ -119,6 +90,18 @@ $theme-lighter: ( ), --colors: ( + --gray1: hsl(210, 0%, 100%), // 1.11 + --gray2: hsl(210, 0%, 98%), // 1.07 + --gray3: hsl(210, 0%, 95%), // 1 + --gray4: hsl(210, 0%, 90%), // 1.11 + --gray5: hsl(210, 0%, 87%), // 1.2 + --gray6: hsl(210, 0%, 78%), // 1.51 + --gray7: hsl(210, 0%, 69%), // 1.93 + --gray8: hsl(210, 0%, 55%), // 3 + --gray9: hsl(210, 0%, 38%), // 5.53 + --gray10: hsl(210, 0%, 19%), // 11.78 + --gray11: hsl(210, 0%, 0%), // 18.75 + --bg-hi2: iro.props-get(--colors --gray1, null), // Lightest background --bg-hi: iro.props-get(--colors --gray2, null), // Lighter background --bg: iro.props-get(--colors --gray3, null), // Background @@ -183,18 +166,44 @@ $theme-lighter: ( ), ), )); + + @include iro.props-store(( + --colors: ( + --gray1: hsl(210, 0%, 100%), // 1 + --gray2: hsl(210, 0%, 100%), // 1 + --gray3: hsl(210, 0%, 100%), // 1 + --gray4: hsl(210, 0%, 95%), // 1.11 + --gray5: hsl(210, 0%, 92%), // 1.19 + --gray6: hsl(210, 0%, 82%), // 1.52 + --gray7: hsl(210, 0%, 73%), // 1.94 + --gray8: hsl(210, 0%, 58%), // 3.03 + --gray9: hsl(210, 0%, 41%), // 5.48 + --gray10: hsl(210, 0%, 22%), // 11.72 + --gray11: hsl(210, 0%, 0%), // 21 + ) + ), 'light-raised'); } // @include iro.fn-execute { - @include iro.props-store((), 'dark'); + @include iro.fn-execute { + @include iro.props-store(( + --colors: () + ), 'dark'); + } + + @include iro.fn-execute { + @include iro.props-store(( + --colors: () + ), 'dark-raised'); + } } // -@each $breakpoint in map-keys($breakpoints) { - @include media('<=#{$breakpoint}') { +@each $breakpoint in map-keys(media.$breakpoints) { + @include media.media('<=#{$breakpoint}') { @include iro.props-store(( --colors: () ), $breakpoint); diff --git a/src/index.scss b/src/index.scss index dc71caa..292785d 100644 --- a/src/index.scss +++ b/src/index.scss @@ -1,19 +1,48 @@ -@use 'iro-sass/src/props'; - -@import 'include-media/dist/include-media'; +@use 'iro-sass/src/index' as iro; +@use 'include-media/dist/include-media' as media; @import 'vars'; +@import 'general'; + +@import 'layouts/container'; + +@import 'objects/heading'; +@import 'objects/rule'; :root { - @include props.assign; + @include iro.props-assign; - @each $breakpoint in map-keys($breakpoints) { - @include media('<=#{$breakpoint}') { - @include props.assign($breakpoint); + @each $breakpoint in map-keys(media.$breakpoints) { + @include media.media('<=#{$breakpoint}') { + @include iro.props-assign($breakpoint); } } +} + +@include iro.bem-theme('grayscale') { + @include iro.props-assign($root: --colors --grayscale-accent, $prefix: --colors --accent); +} + +@include iro.bem-theme('raised') { + @include iro.props-assign('light-raised'); - @media (prefers-color-scheme: dark) { - @include props.assign('dark'); + @include iro.bem-multi('at-theme' 'grayscale', 'theme' 'grayscale') { + @include iro.props-assign($root: --colors --grayscale-accent, $prefix: --colors --accent); } } + +/*@media (prefers-color-scheme: dark) { + @include iro.props-assign('dark'); + + @include iro.bem-theme('grayscale') { + @include iro.props-assign('dark', $root: --colors --grayscale-accent, $prefix: --colors --accent); + } + + @include iro.bem-theme('raised') { + @include iro.props-assign('dark-raised'); + + @include iro.bem-multi('at-theme' 'grayscale', 'theme' 'grayscale') { + @include iro.props-assign('dark', $root: --colors --grayscale-accent, $prefix: --colors --accent); + } + } +}*/ diff --git a/src/layouts/_card.scss b/src/layouts/_card.scss new file mode 100644 index 0000000..f6b6b03 --- /dev/null +++ b/src/layouts/_card.scss @@ -0,0 +1,38 @@ +@include namespace('card') { + @include store(( + --dims: ( + --pad-x: iro-px-to-rem(11px), + --pad-y: iro-px-to-rem(8px), + --lg: ( + --pad-x: iro-px-to-rem(14px), + --pad-y: iro-px-to-rem(11px), + ) + ) + )); + + @include layout(namespace()) { + display: flex; + align-items: center; + padding: prop(--dims --pad-y) prop(--dims --pad-x); + gap: prop(--dims --pad-x); + line-height: 1.4; + + @include modifier('lg') { + padding: prop(--dims --lg --pad-y) prop(--dims --lg --pad-x); + gap: prop(--dims --lg --pad-x); + } + + @include modifier('flush') { + padding: 0; + } + + @include element('block') { + flex: 0 0 auto; + + @include modifier('main') { + flex-shrink: 1; + width: 100%; + } + } + } +} diff --git a/src/layouts/_container.scss b/src/layouts/_container.scss new file mode 100644 index 0000000..efe5203 --- /dev/null +++ b/src/layouts/_container.scss @@ -0,0 +1,91 @@ +@use 'iro-sass/src/index' as iro; +@use 'include-media/dist/include-media' as media; + +@include iro.props-namespace('container') { + @include iro.props-store(( + --dims: ( + --content-width: iro.fn-px-to-rem(700px), + --sm-content-width: iro.fn-px-to-rem(360px), + --padding-x: 3rem, + --padding-y: 3rem, + --in-page-spacing-y: iro.props-get(--dims --spacing --y --xl, $global: true), + ) + )); + + @include iro.bem-layout(iro.props-namespace()) { + overflow: hidden; + + @include iro.bem-elem('inner') { + margin-top: calc(-1 * iro.props-get(--dims --spacing --y --xl, $global: true)); + margin-bottom: calc(-1 * iro.props-get(--dims --spacing --y --xl, $global: true)); + + &::before, + &::after { + content: ''; + display: block; + width: 0; + height: 0; + } + + &::before { + margin-bottom: iro.props-get(--dims --spacing --y --xl, $global: true); + } + + &::after { + margin-top: iro.props-get(--dims --spacing --y --xl, $global: true); + } + } + + @include iro.bem-modifier('pad-x') { + padding-right: iro.props-get(--dims --padding-x); + padding-left: iro.props-get(--dims --padding-x); + } + + @include iro.bem-modifier('pad-y') { + padding-top: iro.props-get(--dims --padding-y); + padding-bottom: iro.props-get(--dims --padding-y); + } + + @include iro.bem-modifier('narrow') { + max-width: iro.props-get(--dims --content-width); + margin-right: auto; + margin-left: auto; + + @each $breakpoint in map-keys(media.$breakpoints) { + @include media.media('<=#{$breakpoint}') { + @include iro.bem-suffix('#{$breakpoint}-down') { + max-width: iro.props-get(--dims --content-width); + margin-right: auto; + margin-left: auto; + } + } + } + } + + @include iro.bem-modifier('sm-narrow') { + max-width: iro.props-get(--dims --sm-content-width); + margin-right: auto; + margin-left: auto; + + @each $breakpoint in map-keys(media.$breakpoints) { + @include media.media('<=#{$breakpoint}') { + @include iro.bem-suffix('#{$breakpoint}-down') { + max-width: iro.props-get(--dims --sm-content-width); + margin-right: auto; + margin-left: auto; + } + } + } + } + + @include iro.bem-modifier('themed') { + background-color: iro.props-get(--colors --bg, $global: true); + color: iro.props-get(--colors --fg, $global: true); + } + + @include iro.bem-modifier('in-page') { + margin-top: iro.props-get(--dims --in-page-spacing-y); + margin-bottom: iro.props-get(--dims --in-page-spacing-y); + } + } +} diff --git a/src/mixins/_grid.scss b/src/mixins/_grid.scss new file mode 100644 index 0000000..e0a73d9 --- /dev/null +++ b/src/mixins/_grid.scss @@ -0,0 +1,88 @@ +$context-id: 'grid' !default; + +@include iro-context-stack-create($grid-context-id); + +@mixin native-grid { + @supports (display: grid) { + @content; + } +} + +@mixin grid($columns: 12, $h-spacing: 0, $v-spacing: 0, $reverse: false) { + display: flex; + flex-flow: row wrap; + align-items: stretch; + justify-content: flex-start; + margin: (-.5 * $v-spacing) (-.5 * $h-spacing); + + @if $reverse { + flex-direction: row-reverse; + } + + @include iro-context-push($grid-context-id, 'grid', ( + --h-spacing: $h-spacing, + --v-spacing: $v-spacing, + --columns: $columns, + --reverse: $reverse + )); + + @content; + + @include iro-context-pop($grid-context-id); +} + +@mixin grid-col { + @include iro-context-assert-stack-must-contain($grid-context-id, 'grid'); + + $data: nth(iro-context-get($grid-context-id, 'grid'), 2); + $v-spacing: map-get($data, --v-spacing); + $h-spacing: map-get($data, --h-spacing); + + box-sizing: border-box; + flex: 0 0 auto; + margin: .5 * $v-spacing .5 * $h-spacing; + + @include iro-context-push($grid-context-id, 'grid__col'); + + @content; + + @include iro-context-pop($grid-context-id); +} + +@mixin grid-col-span($i) { + @include iro-context-assert-stack-must-contain($grid-context-id, 'grid'); + + $data: nth(iro-context-get($grid-context-id, 'grid'), 2); + $columns: map-get($data, --columns); + $h-spacing: map-get($data, --h-spacing); + + @if $h-spacing != 0 { + width: calc((100% - #{$columns * $h-spacing}) * #{floor($i / $columns * 10000 - 1) / 10000} + #{($i - 1) * $h-spacing}); + // ^^^^^^^^^^ Bugfix for Firefox ^^^^^^^^^^ + } @else { + width: calc(100% * #{floor($i / $columns * 10000 - 1) / 10000}); + } +} + +@mixin grid-col-shift($i) { + @include iro-context-assert-stack-must-contain($grid-context-id, 'grid'); + + $data: nth(iro-context-get($grid-context-id, 'grid'), 2); + $columns: map-get($data, --columns); + $h-spacing: map-get($data, --h-spacing); + $reverse: map-get($data, --reverse); + + $prop: if($reverse, margin-right, margin-left); + + @if $i == 0 { + #{$prop}: 0; + } @else { + @if $h-spacing != 0 { + #{$prop}: calc((100% - #{$columns * $h-spacing}) * #{floor($i / $columns * 10000 - 1) / 10000} + #{$i * $h-spacing + $h-spacing / 2}); + // ^^^^^^^^^^ Bugfix for Firefox ^^^^^^^^^^ + } @else { + #{$prop}: calc(100% * #{floor($i / $columns * 10000 - 1) / 10000}); + // ^^^^^^^^^^ Bugfix for Firefox ^^^^^^^^^^ + } + } +} diff --git a/src/mixins/_typography.scss b/src/mixins/_typography.scss new file mode 100644 index 0000000..31e39f0 --- /dev/null +++ b/src/mixins/_typography.scss @@ -0,0 +1,63 @@ +@function set-font($basis, $values: ()) { + $font: map-merge($basis, $values); + + $map: (font-family: map-get($font, 'family')); + + @if (map-has-key($font, 'size')) { + $map: map-merge( + $map, ( + font-size: map-get($font, 'size') + ) + ); + } + + @if (map-has-key($font, 'weight')) { + $map: map-merge( + $map, ( + font-weight: map-get($font, 'weight') + ) + ); + } + + @if (map-has-key($font, 'style')) { + $map: map-merge( + $map, ( + font-style: map-get($font, 'style') + ) + ); + } + + @if (map-has-key($font, 'line-height')) { + $map: map-merge( + $map, ( + line-height: map-get($font, 'line-height') + ) + ); + } + + @if (map-has-key($font, 'transform')) { + $map: map-merge( + $map, ( + text-transform: map-get($font, 'transform') + ) + ); + } + + @if (map-has-key($font, 'variant-alternates')) { + $map: map-merge( + $map, ( + font-variant-alternates: map-get($font, 'variant-alternates') + ) + ); + } + + @return $map; +} + +@mixin set-font($basis, $values: ()) { + $values: set-font($basis, $values); + + @each $prop, $value in $values { + #{$prop}: $value; + } +} diff --git a/src/objects/_heading.scss b/src/objects/_heading.scss new file mode 100644 index 0000000..a0ce052 --- /dev/null +++ b/src/objects/_heading.scss @@ -0,0 +1,68 @@ +@use 'iro-sass/src/index' as iro; +@use '../vars'; +@use '../mixins/typography'; + +@include iro.props-namespace('heading') { + @include iro.props-store(( + --dims: ( + --in-page-margin: ( + --top: iro.props-get(--dims --spacing --y --lg, $global: true), + --top-sibling: iro.props-get(--dims --spacing --y --md, $global: true), + --bottom: iro.props-get(--dims --spacing --y --sm, $global: true), + ), + ), + --colors: ( + --light: iro.props-get(--colors --fg-hi, $global: true), + --strong: iro.props-get(--colors --fg-lo, $global: true), + ), + )); + + @include iro.bem-object(iro.props-namespace()) { + @include typography.set-font(vars.$font--headline); + + display: block; + margin-top: iro.props-get(--dims --in-page-margin --top); + margin-bottom: 0; + + & + & { + margin-top: iro.props-get(--dims --in-page-margin --top-sibling); + } + + @include iro.bem-modifier('xxl') { + color: iro.props-get(--colors --strong); + font-size: iro.props-get(--dims --font-size --xxxl, $global: true); + } + + @include iro.bem-modifier('xl') { + color: iro.props-get(--colors --strong); + font-size: iro.props-get(--dims --font-size --xxl, $global: true); + } + + @include iro.bem-modifier('lg') { + color: iro.props-get(--colors --strong); + font-size: iro.props-get(--dims --font-size --xl, $global: true); + } + + @include iro.bem-modifier('md') { + color: iro.props-get(--colors --strong); + font-size: iro.props-get(--dims --font-size --lg, $global: true); + } + + @include iro.bem-modifier('sm') { + @include typography.set-font($font--main, (line-height: map-get(vars.$font--headline, line-height))); + + color: iro.props-get(--colors --strong); + font-size: iro.props-get(--dims --font-size --md, $global: true); + font-weight: 500; + } + + @include iro.bem-modifier('xs') { + @include typography.set-font($font--main, (line-height: map-get(vars.$font--headline, line-height))); + + color: iro.props-get(--colors --light); + font-size: iro.props-get(--dims --font-size --xs, $global: true); + font-weight: 500; + text-transform: uppercase; + } + } +} diff --git a/src/objects/_rule.scss b/src/objects/_rule.scss new file mode 100644 index 0000000..74987da --- /dev/null +++ b/src/objects/_rule.scss @@ -0,0 +1,120 @@ +@use 'iro-sass/src/index' as iro; +@use '../vars'; +@use '../mixins/typography'; + +@include iro.props-namespace('rule') { + @include iro.props-store(( + --dims: ( + --margin-y: iro.props-get(--dims --spacing --y --xs, $global: true), + + --strong: ( + --border-width: iro.props-get(--dims --border-width --thick, $global: true), + --label-font-size: iro.props-get(--dims --font-size --md, $global: true), + ), + --medium: ( + --border-width: iro.props-get(--dims --border-width --medium, $global: true), + --label-font-size: iro.props-get(--dims --font-size --sm, $global: true), + ), + --faint: ( + --border-width: iro.props-get(--dims --border-width --thin, $global: true), + --label-font-size: iro.props-get(--dims --font-size --xs, $global: true), + ), + ), + --colors: ( + --strong: ( + --bg: iro.props-get(--colors --fg, $global: true), + --label: iro.props-get(--colors --fg, $global: true), + ), + --medium: ( + --bg: iro.props-get(--colors --obj, $global: true), + --label: iro.props-get(--colors --fg-hi, $global: true), + ), + --faint: ( + --bg: iro.props-get(--colors --obj, $global: true), + --label: iro.props-get(--colors --fg-hi2, $global: true), + ), + ), + )); + + @include iro.bem-object(iro.props-namespace()) { + display: block; + height: iro.props-get(--dims --strong --border-width); + margin-top: iro.props-get(--dims --margin-y); + margin-bottom: iro.props-get(--dims --margin-y); + background-color: iro.props-get(--colors --strong --bg); + + @include iro.bem-modifier('medium') { + height: iro.props-get(--dims --medium --border-width); + background-color: iro.props-get(--colors --medium --bg); + } + + @include iro.bem-modifier('faint') { + height: iro.props-get(--dims --faint --border-width); + background-color: iro.props-get(--colors --faint --bg); + } + + @include iro.bem-modifier('labelled') { + display: flex; + flex-direction: row; + align-items: center; + height: auto; + border-radius: 0; + background-color: transparent; + + &::before, + &::after { + content: ''; + display: block; + flex: 1 1 auto; + width: 100%; + height: 3px; + background-color: iro.props-get(--colors --strong --bg); + } + + &::before { + margin-right: 1em; + } + + &::after { + margin-left: 1em; + } + + @include iro.bem-elem('label') { + flex: 0 0 auto; + color: iro.props-get(--colors --strong --label); + font-size: iro.props-get(--dims --strong --label-font-size); + font-weight: 700; + letter-spacing: .5px; + text-transform: uppercase; + } + + @include iro.bem-modifier('medium') { + &::before, + &::after { + height: 2px; + background-color: iro.props-get(--colors --medium --bg); + } + + @include iro.bem-elem('label') { + color: iro.props-get(--colors --medium --label); + font-size: iro.props-get(--dims --medium --label-font-size); + font-weight: 500; + } + } + + @include iro.bem-modifier('faint') { + &::before, + &::after { + height: 1px; + background-color: iro.props-get(--colors --faint --bg); + } + + @include iro.bem-elem('label') { + color: iro.props-get(--colors --faint --label); + font-size: iro.props-get(--dims --faint --label-font-size); + font-weight: 500; + } + } + } + } +} diff --git a/static/script.js b/static/script.js new file mode 100644 index 0000000..ece93e8 --- /dev/null +++ b/static/script.js @@ -0,0 +1,26 @@ +'use strict'; + +// + +document.querySelectorAll('.is-indeterminate').forEach(el => el.indeterminate = true); + +// + +const enableFocusIndicator = e => { + if (e.key !== 'Tab') { + return; + } + + document.body.classList.add('t-keyboard'); + document.removeEventListener('keydown', enableFocusIndicator); + document.addEventListener('mousedown', disableFocusIndicator); +} + +const disableFocusIndicator = e => { + document.body.classList.remove('t-keyboard'); + + document.removeEventListener('mousedown', disableFocusIndicator); + document.addEventListener('keydown', enableFocusIndicator); +} + +document.addEventListener('keydown', enableFocusIndicator); diff --git a/tpl/index.pug b/tpl/index.pug index 2fb865d..c63e9f1 100644 --- a/tpl/index.pug +++ b/tpl/index.pug @@ -4,19 +4,11 @@ include layouts/container.pug include objects/heading.pug include objects/rule.pug -include objects/button.pug -include objects/icon.pug -include objects/text-input.pug -include objects/field-label.pug -include objects/radio.pug -include objects/checkbox.pug -include objects/switch.pug -include objects/form.pug -include objects/action-button.pug mixin box - +container(padH=true padV=true theme='box' inPage=true) - block + .t-raised + +container(padH=true padV=true inPage=true themed=true) + block doctype html @@ -25,6 +17,8 @@ html meta(charset='utf-8') meta(name='viewport' content='width=device-width, initial-scale=1') title iro-design + link(rel="stylesheet", href="style.css") + script(src="script.js") body(class='t-lighter') +container(padH=true padV=true narrow=true) @@ -64,268 +58,3 @@ html +rule(level='strong')= 'Strong' +rule(level='medium')= 'Medium' +rule(level='faint')= 'Faint' - - //----------------------------------------- - - +h1-heading(level='xl')= 'Button' - +rule(level='medium') - - +box - +a-button(variant='primary')= 'Button' - = ' ' - +a-button(variant='primary' disabled=true)= 'Button' - br - br - +a-button(variant='secondary')= 'Button' - = ' ' - +a-button(variant='secondary' disabled=true)= 'Button' - - +box - +a-button(variant='primary' quiet=true)= 'Button' - = ' ' - +a-button(variant='primary' quiet=true disabled=true)= 'Button' - br - br - +a-button(variant='secondary' quiet=true)= 'Button' - = ' ' - +a-button(variant='secondary' quiet=true disabled=true)= 'Button' - - //----------------------------------------- - - +h1-heading(level='xl')= 'Text input' - +rule(level='medium') - - +box - +text-input(placeholder='Placeholder') - br - br - +text-input(value='Just landed in L.A.') - br - br - +text-input(value='Readonly' readonly=true) - br - br - +text-input(value='Incorrect input' pattern='a+' required=true) - br - br - +text-input(placeholder='Placeholder' disabled=true) - br - br - +text-input(value='Just landed in L.A.' disabled=true) - br - br - +text-input(value='Readonly' readonly=true disabled=true) - br - br - +text-input(value='Incorrect input' pattern='a+' required=true disabled=true) - - //----------------------------------------- - - +h1-heading(level='xl')= 'Field label' - +rule(level='medium') - - +box - +field-label('First name') - +text-input(placeholder='Placeholder') - br - br - +field-label('Password', 'At least 6 characters required') - +text-input(placeholder='Placeholder' type='password') - br - br - +field-label('Password', 'At least 6 characters required')(invalid=true) - +text-input(placeholder='Placeholder' type='password' invalid=true) - br - br - +field-label('First name')(disabled=true) - +text-input(placeholder='Placeholder' disabled=true) - br - br - +field-label('Password', 'At least 6 characters required')(disabled=true) - +text-input(placeholder='Placeholder' type='password' disabled=true) - br - br - +field-label('Password', 'At least 6 characters required')(invalid=true disabled=true) - +text-input(placeholder='Placeholder' type='password' invalid=true disabled=true) - - +box - +field-label('First name')(align='left' labelWidth='100px') - +text-input(placeholder='Placeholder') - br - br - +field-label('Password', 'At least 6 characters required')(align='left' labelWidth='100px') - +text-input(placeholder='Placeholder' type='password') - br - br - +field-label('Password', 'At least 6 characters required')(align='left' labelWidth='100px' invalid=true) - +text-input(placeholder='Placeholder' type='password' invalid=true) - br - br - +field-label('First name')(align='left' labelWidth='100px' disabled=true) - +text-input(placeholder='Placeholder' disabled=true) - br - br - +field-label('Password', 'At least 6 characters required')(align='left' labelWidth='100px' disabled=true) - +text-input(placeholder='Placeholder' type='password' disabled=true) - br - br - +field-label('Password', 'At least 6 characters required')(align='left' labelWidth='100px' invalid=true disabled=true) - +text-input(placeholder='Placeholder' type='password' invalid=true disabled=true) - - +box - +field-label('First name')(align='right' labelWidth='100px') - +text-input(placeholder='Placeholder') - br - br - +field-label('Password', 'At least 6 characters required')(align='right' labelWidth='100px') - +text-input(placeholder='Placeholder' type='password') - br - br - +field-label('Password', 'At least 6 characters required')(align='right' labelWidth='100px' invalid=true) - +text-input(placeholder='Placeholder' type='password' invalid=true) - br - br - +field-label('First name')(align='right' labelWidth='100px' disabled=true) - +text-input(placeholder='Placeholder' disabled=true) - br - br - +field-label('Password', 'At least 6 characters required')(align='right' labelWidth='100px' disabled=true) - +text-input(placeholder='Placeholder' type='password' disabled=true) - br - br - +field-label('Password', 'At least 6 characters required')(align='right' labelWidth='100px' invalid=true disabled=true) - +text-input(placeholder='Placeholder' type='password' invalid=true disabled=true) - - //----------------------------------------- - - +h1-heading(level='xl')= 'Radio' - +rule(level='medium') - - +box - +radio(name="radio-demo-1")= 'Cats' - +radio(name="radio-demo-1")= 'Dogs' - +radio(name="radio-demo-1" checked=true)= 'Foxes' - br - +radio(name="radio-demo-2" disabled=true)= 'Cats' - +radio(name="radio-demo-2" disabled=true)= 'Dogs' - +radio(name="radio-demo-2" checked=true disabled=true)= 'Foxes' - - //----------------------------------------- - - +h1-heading(level='xl')= 'Checkbox' - +rule(level='medium') - - +box - +checkbox(indeterminate=true)= 'Cats' - +checkbox= 'Dogs' - +checkbox(checked=true)= 'Foxes' - br - +checkbox(indeterminate=true disabled=true)= 'Cats' - +checkbox(disabled=true)= 'Dogs' - +checkbox(checked=true disabled=true)= 'Foxes' - - //----------------------------------------- - - +h1-heading(level='xl')= 'Switch' - +rule(level='medium') - - +box - +switch= 'Cats' - +switch= 'Dogs' - +switch(checked=true)= 'Foxes' - br - +switch(disabled=true)= 'Cats' - +switch(disabled=true)= 'Dogs' - +switch(checked=true disabled=true)= 'Foxes' - - //----------------------------------------- - - +h1-heading(level='xl')= 'Form' - +rule(level='medium') - - +box - +form - +form-item('Username') - +text-input(placeholder='Example: Feuerfuchs') - - +form-item('Password', 'At least 6 characters, all characters allowed') - +text-input(placeholder='Example: hunter2' type='password') - - +form-item('Bio') - +text-input(placeholder='Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam...') - - +form-item('Favorite animal') - +radio(name="form-demo-1" checked=true)= 'Foxes' - +radio(name="form-demo-1")= 'Other' - - +form-item('Notification settings') - +switch= 'In-app notifications' - br - +switch= 'Desktop notifications' - br - +switch= 'Email notifications' - - +form-item('') - +checkbox= 'I\'ve read and accept the terms and conditions' - - +form-item('') - +a-button(variant='primary')= 'Register' - - //----------------------------------------- - - +h1-heading(level='xl')= 'Action button' - +rule(level='medium') - - +box - +a-action-button= 'Idle' - = ' ' - +a-action-button(selected=true)= 'Selected' - = ' ' - +a-action-button(disabled=true)= 'Disabled' - = ' ' - +a-action-button(selected=true disabled=true)= 'Selected + disabled' - br - br - +a-action-button(icon='trash')= 'Idle' - = ' ' - +a-action-button(icon='trash' selected=true)= 'Selected' - = ' ' - +a-action-button(icon='trash' disabled=true)= 'Disabled' - = ' ' - +a-action-button(icon='trash' selected=true disabled=true)= 'Selected + disabled' - br - br - +a-action-button(icon='trash') - = ' ' - +a-action-button(icon='trash' selected=true) - = ' ' - +a-action-button(icon='trash' disabled=true) - = ' ' - +a-action-button(icon='trash' selected=true disabled=true) - - +box - +a-action-button(quiet=true )= 'Idle' - = ' ' - +a-action-button(quiet=true selected=true)= 'Selected' - = ' ' - +a-action-button(quiet=true disabled=true)= 'Disabled' - = ' ' - +a-action-button(quiet=true selected=true disabled=true)= 'Selected + disabled' - br - br - +a-action-button(quiet=true icon='trash')= 'Idle' - = ' ' - +a-action-button(quiet=true icon='trash' selected=true)= 'Selected' - = ' ' - +a-action-button(quiet=true icon='trash' disabled=true)= 'Disabled' - = ' ' - +a-action-button(quiet=true icon='trash' selected=true disabled=true)= 'Selected + disabled' - br - br - +a-action-button(quiet=true icon='trash') - = ' ' - +a-action-button(quiet=true icon='trash' selected=true) - = ' ' - +a-action-button(quiet=true icon='trash' disabled=true) - = ' ' - +a-action-button(quiet=true icon='trash' selected=true disabled=true) diff --git a/tpl/layouts/container.pug b/tpl/layouts/container.pug index 75e3b36..9dde2d6 100644 --- a/tpl/layouts/container.pug +++ b/tpl/layouts/container.pug @@ -1,13 +1,13 @@ mixin container - let classes = { - 'l-container': true, - 'l-container--padH': attributes.padH, - 'l-container--padV': attributes.padV, - 'l-container--narrow': attributes.narrow, - 'l-container--smNarrow': attributes.smNarrow, - 'l-container--inPage': attributes.inPage, - 'l-container--themed': !!attributes.theme + 'l-container': true, + 'l-container--pad-h': attributes.padH, + 'l-container--pad-v': attributes.padV, + 'l-container--narrow': attributes.narrow, + 'l-container--sm-narrow': attributes.smNarrow, + 'l-container--in-page': attributes.inPage, + 'l-container--themed': attributes.themed } if (!!attributes.theme) { classes['t-' + attributes.theme] = true diff --git a/tpl/objects/heading.pug b/tpl/objects/heading.pug new file mode 100644 index 0000000..546df43 --- /dev/null +++ b/tpl/objects/heading.pug @@ -0,0 +1,34 @@ +mixin h1-heading + - let classes = ['o-heading', 'o-heading--' + attributes.level] + h1(class=classes) + block + +mixin h2-heading + - let classes = ['o-heading', 'o-heading--' + attributes.level] + h2(class=classes) + block + +mixin h3-heading + - let classes = ['o-heading', 'o-heading--' + attributes.level] + h3(class=classes) + block + +mixin h4-heading + - let classes = ['o-heading', 'o-heading--' + attributes.level] + h4(class=classes) + block + +mixin h5-heading + - let classes = ['o-heading', 'o-heading--' + attributes.level] + h5(class=classes) + block + +mixin h6-heading + - let classes = ['o-heading', 'o-heading--' + attributes.level] + h6(class=classes) + block + +mixin div-heading + - let classes = ['o-heading', 'o-heading--' + attributes.level] + div(class=classes) + block diff --git a/tpl/objects/rule.pug b/tpl/objects/rule.pug new file mode 100644 index 0000000..958ff18 --- /dev/null +++ b/tpl/objects/rule.pug @@ -0,0 +1,12 @@ +mixin rule + - + let classes = { + 'o-rule': true, + 'o-rule--labelled': !!block + } + classes['o-rule--' + attributes.level] = true + + div(class=classes) + if block + .o-rule__label + block -- cgit v1.2.3-70-g09d2