summaryrefslogtreecommitdiffstats
path: root/src/objects
diff options
context:
space:
mode:
authorVolpeon <git@volpeon.ink>2024-10-18 18:08:24 +0200
committerVolpeon <git@volpeon.ink>2024-10-18 18:08:24 +0200
commit365c56edcc36b5b92902bac01ce44b43d01e8685 (patch)
tree644611792591a76e605068d0c9e230fad6a633e7 /src/objects
parentRevamped variable management (diff)
downloadiro-design-365c56edcc36b5b92902bac01ce44b43d01e8685.tar.gz
iro-design-365c56edcc36b5b92902bac01ce44b43d01e8685.tar.bz2
iro-design-365c56edcc36b5b92902bac01ce44b43d01e8685.zip
Refactoring
Diffstat (limited to 'src/objects')
-rw-r--r--src/objects/_action-button.scss179
-rw-r--r--src/objects/_action-button.vars.scss185
-rw-r--r--src/objects/_alert.scss43
-rw-r--r--src/objects/_alert.vars.scss0
-rw-r--r--src/objects/_avatar.scss165
-rw-r--r--src/objects/_backdrop.scss26
-rw-r--r--src/objects/_badge.scss300
-rw-r--r--src/objects/_button.scss301
-rw-r--r--src/objects/_card.scss170
-rw-r--r--src/objects/_checkbox.scss261
-rw-r--r--src/objects/_divider.scss203
-rw-r--r--src/objects/_emoji.scss73
-rw-r--r--src/objects/_field-label.scss86
-rw-r--r--src/objects/_heading.scss116
-rw-r--r--src/objects/_icon.scss26
-rw-r--r--src/objects/_lightbox.scss313
-rw-r--r--src/objects/_menu.scss137
-rw-r--r--src/objects/_palette.scss62
-rw-r--r--src/objects/_popover.scss51
-rw-r--r--src/objects/_radio.scss185
-rw-r--r--src/objects/_side-nav.scss122
-rw-r--r--src/objects/_status-indicator.scss39
-rw-r--r--src/objects/_switch.scss222
-rw-r--r--src/objects/_table.scss168
-rw-r--r--src/objects/_text-field.scss213
25 files changed, 3646 insertions, 0 deletions
diff --git a/src/objects/_action-button.scss b/src/objects/_action-button.scss
new file mode 100644
index 0000000..0a65b8d
--- /dev/null
+++ b/src/objects/_action-button.scss
@@ -0,0 +1,179 @@
1@use 'sass:list';
2@use 'sass:map';
3@use 'sass:meta';
4@use 'iro-sass/src/iro-sass' as iro;
5@use '../props';
6
7@forward 'action-button.vars';
8@use 'action-button.vars' as vars;
9
10@mixin -apply-theme($theme, $key: ()) {
11 color: props.get($theme, list.join($key, --disabled --label)...);
12 background-color: props.get($theme, list.join($key, --disabled --bg)...);
13 border-color: props.get($theme, list.join($key, --disabled --border)...);
14
15 &::after {
16 outline-color: props.get($theme, list.join($key, --key-focus --border)...);
17 box-shadow:
18 0
19 0
20 0
21 calc(props.get(vars.$key-focus--border-width) + props.get(vars.$key-focus--outline-width))
22 props.get($theme, list.join($key, --key-focus --outline-width)...);
23 }
24
25 &:link,
26 &:visited,
27 &:enabled {
28 color: props.get($theme, list.join($key, --label)...);
29 background-color: props.get($theme, list.join($key, --bg)...);
30 border-color: props.get($theme, list.join($key, --border)...);
31
32 &:hover,
33 &:focus-visible {
34 color: props.get($theme, list.join($key, --hover --label)...);
35 background-color: props.get($theme, list.join($key, --hover --bg)...);
36 border-color: props.get($theme, list.join($key, --hover --border)...);
37 }
38
39 &:active {
40 color: props.get($theme, list.join($key, --active --label)...);
41 background-color: props.get($theme, list.join($key, --active --bg)...);
42 border-color: props.get($theme, list.join($key, --active --border)...);
43 }
44 }
45
46 @include iro.bem-modifier('quiet') {
47 color: props.get($theme, list.join($key, --quiet --disabled --label)...);
48 background-color: transparent;
49 border-color: transparent;
50
51 &:link,
52 &:visited,
53 &:enabled {
54 color: props.get($theme, list.join($key, --quiet --label)...);
55 background-color: transparent;
56 border-color: transparent;
57
58 &:hover,
59 &:focus-visible {
60 color: props.get($theme, list.join($key, --quiet --hover --label)...);
61 background-color: props.get($theme, list.join($key, --quiet --hover --bg)...);
62 border-color: transparent;
63 }
64
65 &:active {
66 color: props.get($theme, list.join($key, --quiet --active --label)...);
67 background-color: props.get($theme, list.join($key, --quiet --active --bg)...);
68 border-color: transparent;
69 }
70 }
71 }
72
73 @include iro.bem-is('selected') {
74 color: props.get($theme, list.join($key, --selected --disabled --label)...);
75 background-color: props.get($theme, list.join($key, --selected --disabled --bg)...);
76 border-color: props.get($theme, list.join($key, --selected --disabled --border)...);
77
78 &:link,
79 &:visited,
80 &:enabled {
81 color: props.get($theme, list.join($key, --selected --label)...);
82 background-color: props.get($theme, list.join($key, --selected --bg)...);
83 border-color: props.get($theme, list.join($key, --selected --border)...);
84
85 &:hover,
86 &:focus-visible {
87 color: props.get($theme, list.join($key, --selected --hover --label)...);
88 background-color: props.get($theme, list.join($key, --selected --hover --bg)...);
89 border-color: props.get($theme, list.join($key, --selected --hover --border)...);
90 }
91
92 &:active {
93 color: props.get($theme, list.join($key, --selected --active --label)...);
94 background-color: props.get($theme, list.join($key, --selected --active --bg)...);
95 border-color: props.get($theme, list.join($key, --selected --active --border)...);
96 }
97 }
98 }
99}
100
101@mixin styles {
102 @include props.materialize(meta.module-variables('vars'));
103
104 @include iro.bem-object('action-button') {
105 position: relative;
106 display: inline-block;
107 padding-block: props.get(vars.$pad-b);
108 padding-inline: props.get(vars.$pad-i);
109 line-height: props.get(vars.$line-height);
110 text-align: center;
111 text-decoration: none;
112 text-overflow: ellipsis;
113 white-space: nowrap;
114 border: props.get(vars.$border-width) solid transparent;
115 border-radius: props.get(vars.$rounding);
116
117 &::after {
118 position: absolute;
119 inset: calc(-1 * props.get(vars.$border-width) - props.get(vars.$key-focus--border-offset));
120 z-index: 1;
121 display: none;
122 pointer-events: none;
123 content: '';
124 border-radius: calc(props.get(vars.$rounding) + props.get(vars.$key-focus--border-offset));
125 outline: transparent solid props.get(vars.$key-focus--border-width);
126 }
127
128 &:link,
129 &:visited,
130 &:enabled {
131 &:focus-visible {
132 &::after {
133 display: block;
134 }
135 }
136 }
137
138 @include -apply-theme(vars.$default-theme);
139
140 @each $theme in map.keys(props.get(vars.$static-themes)) {
141 @include iro.bem-modifier($theme) {
142 @include -apply-theme(vars.$static-themes, $theme);
143 }
144 }
145
146 @include iro.bem-modifier('pill') {
147 padding-inline: props.get(vars.$pad-i-pill);
148 border-radius: 100em;
149
150 &::after {
151 border-radius: 100em;
152 }
153 }
154
155 @each $mod, $pad-i, $pad-i-pill, $pad-b, $font-size in vars.$fixed-sizes {
156 @include iro.bem-modifier($mod) {
157 padding-block: props.get($pad-i);
158 padding-inline: props.get($pad-i);
159 font-size: props.get($font-size);
160
161 @include iro.bem-modifier('pill') {
162 padding-inline: props.get($pad-i-pill);
163 }
164 }
165 }
166
167 @include iro.bem-modifier('icon') {
168 inline-size: calc(1em * props.get(vars.$line-height) + 2 * props.get(vars.$pad-b));
169 padding-inline: 0;
170
171 @each $mod, $pad-i, $pad-i-pill, $pad-b, $font-size in vars.$fixed-sizes {
172 @include iro.bem-modifier($mod) {
173 inline-size: calc(1em * props.get(vars.$line-height) + 2 * props.get($pad-b));
174 padding-inline: 0;
175 }
176 }
177 }
178 }
179}
diff --git a/src/objects/_action-button.vars.scss b/src/objects/_action-button.vars.scss
new file mode 100644
index 0000000..16d9e7f
--- /dev/null
+++ b/src/objects/_action-button.vars.scss
@@ -0,0 +1,185 @@
1@use 'sass:map';
2@use '../props';
3@use '../vars';
4
5$line-height: props.def(--o-action-button--line-height, 1.4) !default;
6$pad-i: props.def(--o-action-button--pad-i, props.get(vars.$size--150)) !default;
7$pad-i-pill: props.def(--o-action-button--pad-i-pill, props.get(vars.$size--200)) !default;
8$pad-b: props.def(--o-action-button--pad-b, props.get(vars.$size--85)) !default;
9$border-width: props.def(--o-action-button--border-width, props.get(vars.$border-width--thin)) !default;
10$rounding: props.def(--o-action-button--rounding, props.get(vars.$rounding)) !default;
11$font-size: props.def(--o-action-button--font-size, props.get(vars.$font-size--100)) !default;
12
13$pad-i--sm: props.def(--o-action-button--pad-i, props.get(vars.$size--100), 'sm') !default;
14$pad-i-pill--sm: props.def(--o-action-button--pad-i-pill, props.get(vars.$size--150), 'sm') !default;
15$pad-b--sm: props.def(--o-action-button--pad-b, props.get(vars.$size--40), 'sm') !default;
16$font-size--sm: props.def(--o-action-button--font-size, props.get(vars.$font-size--75), 'sm') !default;
17
18$pad-i--lg: props.def(--o-action-button--pad-i, props.get(vars.$size--175), 'lg') !default;
19$pad-i-pill--lg: props.def(--o-action-button--pad-i-pill, props.get(vars.$size--225), 'lg') !default;
20$pad-b--lg: props.def(--o-action-button--pad-b, props.get(vars.$size--115), 'lg') !default;
21$font-size--lg: props.def(--o-action-button--font-size, props.get(vars.$font-size--150), 'lg') !default;
22
23$pad-i--xl: props.def(--o-action-button--pad-i, props.get(vars.$size--225), 'xl') !default;
24$pad-i-pill--xl: props.def(--o-action-button--pad-i-pill, props.get(vars.$size--300), 'xl') !default;
25$pad-b--xl: props.def(--o-action-button--pad-b, props.get(vars.$size--150), 'xl') !default;
26$font-size--xl: props.def(--o-action-button--font-size, props.get(vars.$font-size--200), 'xl') !default;
27
28$key-focus--border-width: props.def(--o-action-button--key-focus--border-width, props.get(vars.$key-focus--border-width)) !default;
29$key-focus--border-offset: props.def(--o-action-button--key-focus--border-offset, props.get(vars.$key-focus--border-offset)) !default;
30$key-focus--outline-width: props.def(--o-action-button--key-focus--outline-width, props.get(vars.$key-focus--outline-width)) !default;
31
32$fixed-sizes: (
33 'sm' $pad-i--sm $pad-i-pill--sm $pad-b--sm $font-size--sm,
34 'lg' $pad-i--lg $pad-i-pill--lg $pad-b--lg $font-size--lg,
35 'xl' $pad-i--xl $pad-i-pill--xl $pad-b--xl $font-size--xl,
36) !default;
37
38$default-theme: props.def(--o-action-button, (
39 --bg-color: props.get(vars.$theme, --base, --75),
40 --label-color: props.get(vars.$theme, --text),
41 --border-color: props.get(vars.$theme, --border-strong),
42
43 --hover: (
44 --bg-color: props.get(vars.$theme, --border-mute),
45 --label-color: props.get(vars.$theme, --heading),
46 --border-color: props.get(vars.$theme, --text-mute-more),
47 ),
48
49 --active: (
50 --bg-color: props.get(vars.$theme, --border),
51 --label-color: props.get(vars.$theme, --heading),
52 --border-color: props.get(vars.$theme, --text-mute),
53 ),
54
55 --disabled: (
56 --bg-color: props.get(vars.$theme, --bg-l1),
57 --label-color: props.get(vars.$theme, --border-strong),
58 --border-color: props.get(vars.$theme, --border),
59 ),
60
61 --key-focus: (
62 --border-color: props.get(vars.$theme, --focus, --border),
63 --outline-color: props.get(vars.$theme, --focus, --outline),
64 ),
65
66 --selected: (
67 --bg-color: props.get(vars.$theme, --text-mute),
68 --label-color: props.get(vars.$theme, --base, --50),
69 --border-color: props.get(vars.$theme, --text-mute),
70
71 --hover: (
72 --bg-color: props.get(vars.$theme, --text),
73 --label-color: props.get(vars.$theme, --base, --50),
74 --border-color: props.get(vars.$theme, --text),
75 ),
76
77 --active: (
78 --bg-color: props.get(vars.$theme, --heading),
79 --label-color: props.get(vars.$theme, --base, --50),
80 --border-color: props.get(vars.$theme, --heading),
81 ),
82
83 --disabled: (
84 --bg-color: props.get(vars.$theme, --border-mute),
85 --label-color: props.get(vars.$theme, --border-strong),
86 --border-color: props.get(vars.$theme, --border-mute),
87 ),
88 ),
89
90 --quiet: (
91 --label-color: props.get(vars.$theme, --text),
92
93 --hover: (
94 --bg-color: props.get(vars.$theme, --border-mute),
95 --label-color: props.get(vars.$theme, --heading),
96 ),
97
98 --active: (
99 --bg-color: props.get(vars.$theme, --border),
100 --label-color: props.get(vars.$theme, --heading),
101 ),
102
103 --disabled: (
104 --label-color: props.get(vars.$theme, --border-strong),
105 ),
106 ),
107)) !default;
108
109$static-themes: props.def(--o-action-button);
110@each $theme in map.keys(props.get(vars.$transparent-colors)) {
111 $button-theme: #{$theme}-static;
112
113 $static-themes: props.merge($static-themes, (
114 $button-theme: (
115 --bg-color: props.get(vars.$transparent-colors, $theme, --100),
116 --label-color: props.get(vars.$transparent-colors, $theme, --900),
117 --border-color: props.get(vars.$transparent-colors, $theme, --400),
118
119 --hover: (
120 --bg-color: props.get(vars.$transparent-colors, $theme, --300),
121 --label-color: props.get(vars.$transparent-colors, $theme, --900),
122 --border-color: props.get(vars.$transparent-colors, $theme, --500),
123 ),
124
125 --active: (
126 --bg-color: props.get(vars.$transparent-colors, $theme, --400),
127 --label-color: props.get(vars.$transparent-colors, $theme, --900),
128 --border-color: props.get(vars.$transparent-colors, $theme, --600),
129 ),
130
131 --disabled: (
132 --bg-color: props.get(vars.$transparent-colors, $theme, --100),
133 --label-color: props.get(vars.$transparent-colors, $theme, --500),
134 --border-color: props.get(vars.$transparent-colors, $theme, --300),
135 ),
136
137 --key-focus: (
138 --border-color: props.get(vars.$transparent-colors, $theme, --900),
139 --outline-color: props.get(vars.$transparent-colors, $theme, --300),
140 ),
141
142 --selected: (
143 --bg-color: props.get(vars.$transparent-colors, $theme, --800),
144 --label-color: props.get(vars.$transparent-colors, $theme, --text),
145 --border-color: props.get(vars.$transparent-colors, $theme, --100),
146
147 --hover: (
148 --bg-color: props.get(vars.$transparent-colors, $theme, --900),
149 --label-color: props.get(vars.$transparent-colors, $theme, --text),
150 --border-color: props.get(vars.$transparent-colors, $theme, --100),
151 ),
152
153 --active: (
154 --bg-color: props.get(vars.$transparent-colors, $theme, --900),
155 --label-color: props.get(vars.$transparent-colors, $theme, --text),
156 --border-color: props.get(vars.$transparent-colors, $theme, --100),
157 ),
158
159 --disabled: (
160 --bg-color: props.get(vars.$transparent-colors, $theme, --200),
161 --label-color: props.get(vars.$transparent-colors, $theme, --500),
162 --border-color: props.get(vars.$transparent-colors, $theme, --100),
163 ),
164 ),
165
166 --quiet: (
167 --label-color: props.get(vars.$transparent-colors, $theme, --900),
168
169 --hover: (
170 --bg-color: props.get(vars.$transparent-colors, $theme, --300),
171 --label-color: props.get(vars.$transparent-colors, $theme, --900),
172 ),
173
174 --active: (
175 --bg-color: props.get(vars.$transparent-colors, $theme, --400),
176 --label-color: props.get(vars.$transparent-colors, $theme, --900),
177 ),
178
179 --disabled: (
180 --label-color: props.get(vars.$transparent-colors, $theme, --500),
181 ),
182 ),
183 )
184 ));
185}
diff --git a/src/objects/_alert.scss b/src/objects/_alert.scss
new file mode 100644
index 0000000..774b443
--- /dev/null
+++ b/src/objects/_alert.scss
@@ -0,0 +1,43 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4$themes: 'accent' 'positive' 'negative' 'warning' !default;
5
6@include iro.props-namespace('alert') {
7 @include iro.props-store((
8 --dims: (
9 --border: fn.global-dim(--border --medium),
10 --pad-i: fn.global-dim(--size --250),
11 --pad-b: fn.global-dim(--size --200),
12 --rounding: fn.global-dim(--rounding),
13 ),
14 --colors: (
15 --bg: fn.global-color(--bg-l2),
16 --border: fn.global-color(--text-mute-more),
17 ),
18 ));
19
20 @each $theme in $themes {
21 @include iro.props-store((
22 --colors: (
23 --#{$theme}: (
24 --border: fn.global-color(--#{$theme} --700),
25 ),
26 ),
27 ));
28 }
29
30 @include iro.bem-object(iro.props-namespace()) {
31 padding-block: fn.dim(--pad-b);
32 padding-inline: fn.dim(--pad-i);
33 background-color: fn.color(--bg);
34 border: fn.dim(--border) solid fn.color(--border);
35 border-radius: fn.dim(--rounding);
36
37 @each $theme in $themes {
38 @include iro.bem-modifier($theme) {
39 border-color: fn.color(--#{$theme} --border);
40 }
41 }
42 }
43}
diff --git a/src/objects/_alert.vars.scss b/src/objects/_alert.vars.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/objects/_alert.vars.scss
diff --git a/src/objects/_avatar.scss b/src/objects/_avatar.scss
new file mode 100644
index 0000000..d9c1105
--- /dev/null
+++ b/src/objects/_avatar.scss
@@ -0,0 +1,165 @@
1@use 'sass:list';
2@use 'iro-sass/src/iro-sass' as iro;
3@use '../functions' as fn;
4
5$sizes: 'xs' 'sm' 'lg' 'xl' 'xxl' 'xxxl';
6
7@mixin status($size: ()) {
8 @include iro.bem-elem('status') {
9 inline-size: fn.dim(list.join($size, --indicator-size));
10 block-size: fn.dim(list.join($size, --indicator-size));
11
12 @include iro.bem-next-elem('content') {
13 mask-image: radial-gradient(circle calc(.5 * fn.dim(list.join($size, --indicator-size)) + fn.dim(--indicator-spacing)) at
14 calc(100% - .5 * fn.dim(list.join($size, --indicator-size)))
15 calc(100% - .5 * fn.dim(list.join($size, --indicator-size))),
16 transparent 95%,
17 #fff);
18 }
19 }
20}
21
22@include iro.props-namespace('avatar') {
23 @include iro.props-store((
24 --dims: (
25 --size: fn.global-dim(--size --500),
26 --font-size: fn.global-dim(--font-size --100),
27 --indicator-size: fn.global-dim(--size --150),
28 --indicator-spacing: fn.global-dim(--size --40),
29 --rounding: 25%,
30
31 --xxxl: (
32 --size: fn.global-dim(--size --1600),
33 --font-size: fn.global-dim(--font-size --800),
34 --indicator-size: fn.global-dim(--size --400),
35 ),
36 --xxl: (
37 --size: fn.global-dim(--size --1200),
38 --font-size: fn.global-dim(--font-size --600),
39 --indicator-size: fn.global-dim(--size --300),
40 ),
41 --xl: (
42 --size: fn.global-dim(--size --800),
43 --font-size: fn.global-dim(--font-size --300),
44 --indicator-size: fn.global-dim(--size --225),
45 ),
46 --lg: (
47 --size: fn.global-dim(--size --650),
48 --font-size: fn.global-dim(--font-size --200),
49 --indicator-size: fn.global-dim(--size --175),
50 ),
51 --sm: (
52 --size: fn.global-dim(--size --375),
53 --font-size: fn.global-dim(--font-size --75),
54 --indicator-size: fn.global-dim(--size --125),
55 ),
56 --xs: (
57 --size: fn.global-dim(--size --250),
58 --font-size: fn.global-dim(--font-size --50),
59 --indicator-size: fn.global-dim(--size --100),
60 ),
61
62 --key-focus: (
63 --border: fn.global-dim(--key-focus --border),
64 --border-offset: fn.global-dim(--key-focus --border-offset),
65 --outline: fn.global-dim(--key-focus --outline),
66 ),
67 ),
68 --colors: (
69 --h: 354,
70 --s: 44%,
71 --l: 45%,
72
73 --key-focus: (
74 --border: fn.global-color(--focus --border),
75 --outline: fn.global-color(--focus --outline),
76 ),
77 ),
78 ));
79
80 @include iro.bem-object(iro.props-namespace()) {
81 position: relative;
82 display: inline-block;
83 font-size: fn.dim(--font-size);
84 font-style: normal;
85 vertical-align: .05em;
86 border-radius: fn.dim(--rounding);
87
88 &::after {
89 position: absolute;
90 inset: calc(-1 * fn.dim(--key-focus --border-offset));
91 z-index: 1;
92 display: none;
93 pointer-events: none;
94 content: '';
95 border: fn.dim(--key-focus --border-offset) solid transparent;
96 border-radius: fn.dim(--rounding);
97 outline: fn.color(--key-focus --border) solid fn.dim(--key-focus --border);
98 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(--key-focus --outline);
99 }
100
101 @include iro.bem-elem('status') {
102 position: absolute;
103 inset-block-end: 0;
104 inset-inline-end: 0;
105 }
106
107 @include status;
108
109 @include iro.bem-elem('content') {
110 display: block;
111 inline-size: fn.dim(--size);
112 block-size: fn.dim(--size);
113 line-height: fn.dim(--size);
114 text-align: center;
115 object-fit: cover;
116 object-position: center center;
117 border-radius: fn.dim(--rounding);
118 }
119
120 @include iro.bem-modifier('circle') {
121 border-radius: 100%;
122
123 &::after {
124 border-radius: 100%;
125 }
126
127 @include iro.bem-elem('content') {
128 border-radius: 100%;
129 }
130 }
131
132 @include iro.bem-modifier('placeholder') {
133 @include iro.bem-elem('content') {
134 background-color: hsl(0, 0%, fn.color(--l));
135 }
136 }
137
138 @include iro.bem-modifier('colored') {
139 @include iro.bem-elem('content') {
140 color: #fff;
141 background-color: hsl(fn.color(--h), fn.color(--s), fn.color(--l));
142 }
143 }
144
145 @each $size in $sizes {
146 @include iro.bem-modifier($size) {
147 font-size: fn.dim(--#{$size} --font-size);
148
149 @include status(--#{$size});
150
151 @include iro.bem-elem('content') {
152 inline-size: fn.dim(--#{$size} --size);
153 block-size: fn.dim(--#{$size} --size);
154 line-height: fn.dim(--#{$size} --size);
155 }
156 }
157 }
158
159 &:focus-visible {
160 &::after {
161 display: block;
162 }
163 }
164 }
165}
diff --git a/src/objects/_backdrop.scss b/src/objects/_backdrop.scss
new file mode 100644
index 0000000..9e0cc1e
--- /dev/null
+++ b/src/objects/_backdrop.scss
@@ -0,0 +1,26 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@include iro.props-namespace('backdrop') {
5 @include iro.props-store((
6 --dims: (
7 --z-index: 10000,
8 --blur: 2em,
9 ),
10 --colors: (
11 --bg: rgba(#000, .75),
12 ),
13 ));
14
15 @include iro.bem-object(iro.props-namespace()) {
16 position: fixed;
17 inset: 0;
18 z-index: fn.dim(--z-index);
19 box-sizing: border-box;
20 display: flex;
21 flex-direction: column;
22 overflow: auto;
23 background-color: fn.color(--bg);
24 backdrop-filter: blur(fn.dim(--blur));
25 }
26}
diff --git a/src/objects/_badge.scss b/src/objects/_badge.scss
new file mode 100644
index 0000000..72d85ff
--- /dev/null
+++ b/src/objects/_badge.scss
@@ -0,0 +1,300 @@
1@use 'sass:string';
2@use 'iro-sass/src/iro-sass' as iro;
3@use '../functions' as fn;
4
5$sizes: 'sm' 'lg' 'xl' !default;
6$themes: 'accent' 'positive' 'negative' 'warning' !default;
7$static-themes: 'black' 'white' !default;
8
9@mixin theme($theme) {
10 color: fn.color(--#{$theme} --label);
11 background-color: fn.color(--#{$theme} --bg);
12
13 &:link,
14 &:visited,
15 &:enabled {
16 &:hover,
17 &:focus-visible {
18 color: fn.color(--#{$theme} --hover --label);
19 background-color: fn.color(--#{$theme} --hover --bg);
20 }
21
22 &:active {
23 color: fn.color(--#{$theme} --active --label);
24 background-color: fn.color(--#{$theme} --active --bg);
25 }
26 }
27
28 @include iro.bem-modifier('quiet') {
29 color: fn.color(--#{$theme}-quiet --label);
30 background-color: fn.color(--#{$theme}-quiet --bg);
31
32 &:link,
33 &:visited,
34 &:enabled {
35 &:hover,
36 &:focus-visible {
37 color: fn.color(--#{$theme}-quiet --hover --label);
38 background-color: fn.color(--#{$theme}-quiet --hover --bg);
39 }
40
41 &:active {
42 color: fn.color(--#{$theme}-quiet --active --label);
43 background-color: fn.color(--#{$theme}-quiet --active --bg);
44 }
45 }
46 }
47
48 @if string.slice($theme, 1, 7) == 'static-' {
49 &::after {
50 outline: fn.color(--#{$theme} --key-focus --border) solid fn.dim(--key-focus --border);
51 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(--#{$theme} --key-focus --outline);
52 }
53 }
54}
55
56@include iro.props-namespace('badge') {
57 @include iro.props-store((
58 --dims: (
59 --pad-b: fn.global-dim(--size --50),
60 --pad-i: fn.global-dim(--size --100),
61 --pad-i-pill: fn.global-dim(--size --150),
62 --pad-i-label: fn.global-dim(--size --50),
63 --rounding: fn.global-dim(--rounding),
64 --font-size: fn.global-dim(--font-size --75),
65
66 --sm: (
67 --pad-b: fn.global-dim(--size --25),
68 --pad-i: fn.global-dim(--size --75),
69 --pad-i-pill: fn.global-dim(--size --125),
70 --pad-i-label: fn.global-dim(--size --25),
71 --font-size: fn.global-dim(--font-size --50),
72 ),
73 --lg: (
74 --pad-b: fn.global-dim(--size --75),
75 --pad-i: fn.global-dim(--size --125),
76 --pad-i-pill: fn.global-dim(--size --175),
77 --pad-i-label: fn.global-dim(--size --50),
78 --font-size: fn.global-dim(--font-size --100),
79 ),
80 --xl: (
81 --pad-b: fn.global-dim(--size --100),
82 --pad-i: fn.global-dim(--size --150),
83 --pad-i-pill: fn.global-dim(--size --225),
84 --pad-i-label: fn.global-dim(--size --75),
85 --font-size: fn.global-dim(--font-size --150),
86 ),
87
88 --key-focus: (
89 --border: fn.global-dim(--key-focus --border),
90 --border-offset: fn.global-dim(--key-focus --border-offset),
91 --outline: fn.global-dim(--key-focus --outline),
92 ),
93 ),
94 --colors: (
95 --bg: fn.global-color(--text-mute),
96 --label: fn.global-color(--bg-l2),
97 --hover: (
98 --bg: fn.global-color(--text),
99 ),
100 --active: (
101 --bg: fn.global-color(--heading),
102 ),
103 --key-focus: (
104 --label: fn.global-color(--focus --text),
105 --border: fn.global-color(--focus --border),
106 --outline: fn.global-color(--focus --outline),
107 ),
108
109 --quiet: (
110 --bg: fn.global-color(--border-mute),
111 --label: fn.global-color(--heading),
112 --hover: (
113 --bg: fn.global-color(--border),
114 ),
115 --active: (
116 --bg: fn.global-color(--border-strong),
117 ),
118 ),
119 ),
120 ));
121
122 @each $theme in $themes {
123 @include iro.props-store((
124 --colors: (
125 --#{$theme}: (
126 --bg: fn.global-color(--#{$theme}-static --900),
127 --label: fn.global-color(--#{$theme}-static --900-text),
128 --hover: (
129 --bg: fn.global-color(--#{$theme}-static --1000),
130 --label: fn.global-color(--#{$theme}-static --1000-text),
131 ),
132 --active: (
133 --bg: fn.global-color(--#{$theme}-static --1100),
134 --label: fn.global-color(--#{$theme}-static --1000-text),
135 ),
136 ),
137
138 --#{$theme}-quiet: (
139 --bg: fn.global-color(--#{$theme} --200),
140 --label: fn.global-color(--#{$theme} --1100),
141 --hover: (
142 --bg: fn.global-color(--#{$theme} --300),
143 --label: fn.global-color(--#{$theme} --1200),
144 ),
145 --active: (
146 --bg: fn.global-color(--#{$theme} --400),
147 --label: fn.global-color(--#{$theme} --1300),
148 ),
149 )
150 ),
151 ));
152 }
153
154 @each $theme in $static-themes {
155 @include iro.props-store((
156 --colors: (
157 --static-#{$theme}: (
158 --bg: fn.global-color(--#{$theme}-transparent --800),
159 --label: fn.global-color(--#{$theme}-transparent --text),
160 --hover: (
161 --bg: fn.global-color(--#{$theme}-transparent --900),
162 --label: fn.global-color(--#{$theme}-transparent --text),
163 ),
164 --active: (
165 --bg: fn.global-color(--#{$theme}-transparent --900),
166 --label: fn.global-color(--#{$theme}-transparent --text),
167 ),
168 --key-focus: (
169 --bg: fn.global-color(--#{$theme}-transparent --100),
170 --label: fn.global-color(--#{$theme}-transparent --900),
171 --border: fn.global-color(--#{$theme}-transparent --900),
172 --outline: fn.global-color(--#{$theme}-transparent --300),
173 ),
174 ),
175
176 --static-#{$theme}-quiet: (
177 --bg: fn.global-color(--#{$theme}-transparent --200),
178 --label: fn.global-color(--#{$theme}-transparent --900),
179 --hover: (
180 --bg: fn.global-color(--#{$theme}-transparent --300),
181 --label: fn.global-color(--#{$theme}-transparent --900),
182 ),
183 --active: (
184 --bg: fn.global-color(--#{$theme}-transparent --400),
185 --label: fn.global-color(--#{$theme}-transparent --900),
186 ),
187 )
188 )
189 ));
190 }
191
192 @include iro.bem-object(iro.props-namespace()) {
193 position: relative;
194 display: inline-block;
195 padding-block: fn.dim(--pad-b);
196 padding-inline: fn.dim(--pad-i);
197 font-size: fn.dim(--font-size);
198 line-height: fn.global-dim(--font --standard --line-height);
199 color: fn.color(--label);
200 text-align: center;
201 text-decoration: none;
202 background-color: fn.color(--bg);
203 background-clip: padding-box;
204 border-radius: fn.dim(--rounding);
205
206 &::after {
207 position: absolute;
208 inset: calc(-1 * fn.dim(--key-focus --border-offset));
209 z-index: 1;
210 display: none;
211 pointer-events: none;
212 content: '';
213 border-radius: calc(fn.dim(--rounding) + fn.dim(--key-focus --border-offset));
214 outline: fn.color(--key-focus --border) solid fn.dim(--key-focus --border);
215 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(--key-focus --outline);
216 }
217
218 &:link,
219 &:visited,
220 &:enabled {
221 &:hover,
222 &:focus-visible {
223 background-color: fn.color(--hover --bg);
224 }
225
226 &:active {
227 background-color: fn.color(--active --bg);
228 }
229 }
230
231 @include iro.bem-elem('label') {
232 margin-inline: fn.dim(--pad-i-label);
233 }
234
235 @include iro.bem-modifier('quiet') {
236 color: fn.color(--quiet --label);
237 background-color: fn.color(--quiet --bg);
238
239 &:link,
240 &:visited,
241 &:enabled {
242 &:hover,
243 &:focus-visible {
244 background-color: fn.color(--quiet --hover --bg);
245 }
246
247 &:active {
248 background-color: fn.color(--quiet --active --bg);
249 }
250 }
251 }
252
253 @each $theme in $themes {
254 @include iro.bem-modifier($theme) {
255 @include theme($theme);
256 }
257 }
258
259 &:link,
260 &:visited,
261 &:enabled {
262 &:focus-visible {
263 &::after {
264 display: block;
265 }
266 }
267 }
268
269 @each $theme in $static-themes {
270 @include iro.bem-modifier(static-#{$theme}) {
271 @include theme(static-#{$theme});
272 }
273 }
274
275 @include iro.bem-modifier('pill') {
276 padding-inline: fn.dim(--pad-i-pill);
277 border-radius: 10em;
278
279 &::after {
280 border-radius: 10em;
281 }
282 }
283
284 @each $size in $sizes {
285 @include iro.bem-modifier($size) {
286 padding-block: fn.dim(--#{$size} --pad-b);
287 padding-inline: fn.dim(--#{$size} --pad-i);
288 font-size: fn.dim(--#{$size} --font-size);
289
290 @include iro.bem-elem('label') {
291 margin-inline: fn.dim(--#{$size} --pad-i-label);
292 }
293
294 @include iro.bem-modifier('pill') {
295 padding-inline: fn.dim(--#{$size} --pad-i-pill);
296 }
297 }
298 }
299 }
300}
diff --git a/src/objects/_button.scss b/src/objects/_button.scss
new file mode 100644
index 0000000..097bc21
--- /dev/null
+++ b/src/objects/_button.scss
@@ -0,0 +1,301 @@
1@use 'sass:list';
2@use 'iro-sass/src/iro-sass' as iro;
3@use '../functions' as fn;
4
5$sizes: 'sm' 'lg' 'xl' !default;
6$themes: 'accent' 'negative' !default;
7$static-themes: 'black' 'white' !default;
8
9@mixin theme($theme: ()) {
10 &:link,
11 &:visited,
12 &:enabled {
13 color: fn.color(list.join($theme, --label));
14 background-color: fn.color(list.join($theme, --bg));
15 border-color: transparent;
16 }
17
18 @include iro.bem-modifier('outline') {
19 &:link,
20 &:visited,
21 &:enabled {
22 color: fn.color(list.join($theme, --outline-label));
23 background-color: transparent;
24 border-color: fn.color(list.join($theme, --outline-border));
25 }
26 }
27
28 &:link,
29 &:visited,
30 &:enabled {
31 &:hover,
32 &:focus-visible {
33 color: fn.color(list.join($theme, --hover --label));
34 background-color: fn.color(list.join($theme, --hover --bg));
35 border-color: transparent;
36 }
37
38 &:active {
39 color: fn.color(list.join($theme, --active --label));
40 background-color: fn.color(list.join($theme, --active --bg));
41 border-color: transparent;
42 }
43 }
44}
45
46@mixin static-theme($theme: ()) {
47 color: fn.color(list.join($theme, --disabled --label));
48 background-color: fn.color(list.join($theme, --disabled --bg));
49 border-color: transparent;
50
51 &::after {
52 outline: fn.color(list.join($theme, --key-focus --border)) solid fn.dim(--key-focus --border);
53 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(list.join($theme, --key-focus --outline));
54 }
55
56 @include iro.bem-modifier('outline') {
57 background-color: transparent;
58 border-color: fn.color(list.join($theme, --disabled --outline-border));
59 }
60
61 @include theme($theme);
62
63 @include iro.bem-modifier('primary') {
64 @include theme(list.join($theme, --primary));
65 }
66}
67
68@include iro.props-namespace('button') {
69 @include iro.props-store((
70 --dims: (
71 --line-height: 1.4,
72 --pad-i: fn.global-dim(--size --200),
73 --pad-i-label: fn.global-dim(--size --75),
74 --pad-b: fn.global-dim(--size --65),
75 --border: fn.global-dim(--border --medium),
76 --rounding: 10em,
77 --font-size: fn.global-dim(--font-size --100),
78
79 --sm: (
80 --pad-i: fn.global-dim(--size --150),
81 --pad-i-label: fn.global-dim(--size --50),
82 --pad-b: fn.global-dim(--size --25),
83 --font-size: fn.global-dim(--font-size --75),
84 ),
85 --lg: (
86 --pad-i: fn.global-dim(--size --250),
87 --pad-i-label: fn.global-dim(--size --100),
88 --pad-b: fn.global-dim(--size --100),
89 --font-size: fn.global-dim(--font-size --150),
90 ),
91 --xl: (
92 --pad-i: fn.global-dim(--size --300),
93 --pad-i-label: fn.global-dim(--size --150),
94 --pad-b: fn.global-dim(--size --150),
95 --font-size: fn.global-dim(--font-size --200),
96 ),
97
98 --key-focus: (
99 --border: fn.global-dim(--key-focus --border),
100 --border-offset: fn.global-dim(--key-focus --border-offset),
101 --outline: fn.global-dim(--key-focus --outline),
102 ),
103 ),
104 --colors: (
105 --bg: fn.global-color(--border-mute),
106 --label: fn.global-color(--text),
107 --outline-border: fn.global-color(--border),
108 --outline-label: fn.global-color(--text),
109
110 --hover: (
111 --bg: fn.global-color(--border),
112 --label: fn.global-color(--heading),
113 ),
114 --active: (
115 --bg: fn.global-color(--border-strong),
116 --label: fn.global-color(--heading),
117 ),
118 --disabled: (
119 --bg: fn.global-color(--border-mute),
120 --outline-border: fn.global-color(--border),
121 --label: fn.global-color(--text-disabled),
122 ),
123 --key-focus: (
124 --label: fn.global-color(--focus --text),
125 --border: fn.global-color(--focus --border),
126 --outline: fn.global-color(--focus --outline),
127 ),
128
129 --primary: (
130 --bg: fn.global-color(--base --800),
131 --label: fn.global-color(--base --800-text),
132 --outline-border: fn.global-color(--base --800),
133 --outline-label: fn.global-color(--text),
134
135 --hover: (
136 --bg: fn.global-color(--base --900),
137 --label: fn.global-color(--base --900-text),
138 ),
139 --active: (
140 --bg: fn.global-color(--base --900),
141 --label: fn.global-color(--base --900-text),
142 ),
143 ),
144 ),
145 ));
146
147 @each $theme in $themes {
148 @include iro.props-store((
149 --colors: (
150 --#{$theme}: (
151 --bg: fn.global-color(--#{$theme}-static --900),
152 --label: fn.global-color(--#{$theme}-static --900-text),
153 --outline-border: fn.global-color(--#{$theme} --900),
154 --outline-label: fn.global-color(--#{$theme} --1000),
155
156 --hover: (
157 --bg: fn.global-color(--#{$theme}-static --1000),
158 --label: fn.global-color(--#{$theme}-static --1000-text),
159 ),
160 --active: (
161 --bg: fn.global-color(--#{$theme}-static --1100),
162 --label: fn.global-color(--#{$theme}-static --1100-text),
163 ),
164 ),
165 ),
166 ));
167 }
168
169 @each $theme in $static-themes {
170 @include iro.props-store((
171 --colors: (
172 --static-#{$theme}: (
173 --bg: fn.global-color(--#{$theme}-transparent --200),
174 --label: fn.global-color(--#{$theme}-transparent --900),
175 --outline-border: fn.global-color(--#{$theme}-transparent --300),
176 --outline-label: fn.global-color(--#{$theme}-transparent --900),
177
178 --hover: (
179 --bg: fn.global-color(--#{$theme}-transparent --300),
180 --label: fn.global-color(--#{$theme}-transparent --900),
181 ),
182 --active: (
183 --bg: fn.global-color(--#{$theme}-transparent --400),
184 --label: fn.global-color(--#{$theme}-transparent --900),
185 ),
186 --disabled: (
187 --bg: fn.global-color(--#{$theme}-transparent --200),
188 --outline-border: fn.global-color(--#{$theme}-transparent --300),
189 --label: fn.global-color(--#{$theme}-transparent --500),
190 ),
191 --key-focus: (
192 --bg: fn.global-color(--#{$theme}-transparent --100),
193 --label: fn.global-color(--#{$theme}-transparent --900),
194 --border: fn.global-color(--#{$theme}-transparent --900),
195 --outline: fn.global-color(--#{$theme}-transparent --300),
196 ),
197
198 --primary: (
199 --bg: fn.global-color(--#{$theme}-transparent --800),
200 --label: fn.global-color(--#{$theme}-transparent --text),
201 --outline-border: fn.global-color(--#{$theme}-transparent --800),
202 --outline-label: fn.global-color(--#{$theme}-transparent --900),
203
204 --hover: (
205 --bg: fn.global-color(--#{$theme}-transparent --900),
206 --label: fn.global-color(--#{$theme}-transparent --text),
207 ),
208 --active: (
209 --bg: fn.global-color(--#{$theme}-transparent --900),
210 --label: fn.global-color(--#{$theme}-transparent --text),
211 ),
212 ),
213 ),
214 ),
215 ));
216 }
217
218 @include iro.bem-object(iro.props-namespace()) {
219 position: relative;
220 display: inline-block;
221 padding-block: fn.dim(--pad-b);
222 padding-inline: fn.dim(--pad-i);
223 font-size: fn.dim(--font-size);
224 font-weight: 500;
225 line-height: fn.dim(--line-height);
226 color: fn.color(--disabled --label);
227 text-align: center;
228 text-decoration: none;
229 background-color: fn.color(--disabled --bg);
230 border: fn.dim(--border) solid transparent;
231 border-color: fn.color(--disabled --bg);
232 border-radius: fn.dim(--rounding);
233
234 &::after {
235 position: absolute;
236 inset: calc(-1 * fn.dim(--border) - fn.dim(--key-focus --border-offset));
237 z-index: 1;
238 display: none;
239 pointer-events: none;
240 content: '';
241 border-radius: calc(fn.dim(--rounding) + fn.dim(--key-focus --border-offset));
242 outline: fn.color(--key-focus --border) solid fn.dim(--key-focus --border);
243 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(--key-focus --outline);
244 }
245
246 &:link,
247 &:visited,
248 &:enabled {
249 &:focus-visible {
250 &::after {
251 display: block;
252 }
253 }
254 }
255
256 @include iro.bem-elem('label') {
257 margin-inline: fn.dim(--pad-i-label);
258 }
259
260 @include iro.bem-modifier('block') {
261 display: block;
262 }
263
264 @include iro.bem-modifier('outline') {
265 background-color: transparent;
266 border-color: fn.color(--disabled --outline-border);
267 }
268
269 @each $size in $sizes {
270 @include iro.bem-modifier($size) {
271 padding-block: fn.dim(--#{$size} --pad-b);
272 padding-inline: fn.dim(--#{$size} --pad-i);
273 font-size: fn.dim(--#{$size} --font-size);
274
275 @include iro.bem-elem('label') {
276 margin-inline: fn.dim(--#{$size} --pad-i-label);
277 }
278 }
279 }
280
281 @include static-theme;
282
283 @each $theme in $themes {
284 @include iro.bem-modifier($theme) {
285 @include theme(--#{$theme});
286 }
287 }
288
289 @each $theme in $static-themes {
290 @include iro.bem-modifier(static-#{$theme}) {
291 @include static-theme(--static-#{$theme});
292 }
293 }
294
295 @include iro.bem-modifier('round') {
296 inline-size: calc(1em * fn.dim(--line-height) + 2 * fn.dim(--pad-b));
297 padding-inline: 0;
298 border-radius: 100em;
299 }
300 }
301}
diff --git a/src/objects/_card.scss b/src/objects/_card.scss
new file mode 100644
index 0000000..cc9afc9
--- /dev/null
+++ b/src/objects/_card.scss
@@ -0,0 +1,170 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@include iro.props-namespace('card') {
5 @include iro.props-store((
6 --dims: (
7 --divider: fn.global-dim(--border --thin),
8 --pad-i: fn.global-dim(--size --300),
9 --pad-b: fn.global-dim(--size --250),
10 --spacing: fn.global-dim(--size --200),
11 --rounding: fn.global-dim(--rounding),
12
13 --hover: (
14 --offset-b: calc(-1 * fn.global-dim(--size --65)),
15 ),
16
17 --key-focus: (
18 --border: fn.global-dim(--key-focus --border),
19 --border-offset: fn.global-dim(--key-focus --border-offset),
20 --outline: fn.global-dim(--key-focus --outline),
21 ),
22 ),
23 --colors: (
24 --bg: fn.global-color(--bg-l2),
25 --divider: fn.global-color(--border-mute),
26
27 --key-focus: (
28 --label: fn.global-color(--focus --text),
29 --border: fn.global-color(--focus --border),
30 --outline: fn.global-color(--focus --outline),
31 ),
32
33 --quiet: (
34 --image: fn.global-color(--bg-base),
35
36 --hover: (
37 --image: fn.global-color(--border),
38 ),
39 )
40 ),
41 ));
42
43 @include iro.bem-object(iro.props-namespace()) {
44 display: block;
45 margin: calc(-1 * fn.dim(--key-focus --border));
46 background-color: fn.color(--bg);
47 background-clip: content-box;
48 border: fn.dim(--key-focus --border-offset) solid transparent;
49 border-radius: calc(fn.dim(--rounding) + fn.dim(--key-focus --border-offset));
50 transition: transform .2s;
51
52 @include iro.bem-multi('&:link, &:visited, &:enabled', 'modifier' 'interactive') {
53 &:hover,
54 &:active,
55 &:focus-visible {
56 transform: translateY(fn.dim(--hover --offset-b));
57 }
58
59 &:focus-visible {
60 outline: fn.color(--key-focus --border) solid fn.dim(--key-focus --border);
61 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(--key-focus --outline);
62 }
63 }
64
65 @include iro.bem-elem('avatar') {
66 margin-block-start: fn.dim(--pad-b);
67 margin-inline-start: fn.dim(--pad-i);
68 }
69
70 @include iro.bem-elem('image') {
71 display: block;
72 inline-size: 100%;
73 object-fit: cover;
74 transition: transform .2s, opacity .2s;
75
76 &:first-child {
77 border-start-start-radius: fn.dim(--rounding);
78 border-start-end-radius: fn.dim(--rounding);
79 }
80
81 &:last-child {
82 border-end-start-radius: fn.dim(--rounding);
83 border-end-end-radius: fn.dim(--rounding);
84 }
85
86 @include iro.bem-next-elem('avatar') {
87 margin-block-start: calc(-.7 * fn.foreign-dim(--avatar, --xl --size));
88 }
89 }
90
91 @include iro.bem-elem('body') {
92 padding-block: fn.dim(--pad-b);
93 padding-inline: fn.dim(--pad-i);
94
95 &::before {
96 display: block;
97 margin-block: -100em 100em;
98 content: '';
99 }
100 }
101
102 @include iro.bem-elem('content') {
103 margin-block-start: fn.dim(--spacing);
104 }
105
106 @include iro.bem-elem('footer') {
107 padding-block: 0 fn.dim(--pad-b);
108 padding-inline: fn.dim(--pad-i);
109 margin-block-start: calc(-1 * fn.dim(--pad-b));
110
111 &::before {
112 display: block;
113 block-size: fn.dim(--divider);
114 margin-block: fn.dim(--spacing);
115 content: '';
116 background-color: fn.color(--divider);
117 }
118 }
119
120 @include iro.bem-modifier('quiet') {
121 position: relative;
122 background-color: transparent;
123 border: 0;
124
125 @include iro.bem-multi('&:link, &:visited, &:enabled', 'modifier' 'interactive') {
126 &:hover,
127 &:active,
128 &:focus-visible {
129 transform: none;
130
131 @include iro.bem-elem('image') {
132 background-color: fn.color(--quiet --hover --image);
133 opacity: .75;
134 transform: translateY(fn.dim(--hover --offset-b));
135 }
136 }
137
138 &:focus-visible {
139 outline: none;
140 box-shadow: none;
141
142 @include iro.bem-elem('image') {
143 background-color: fn.color(--quiet --hover --image);
144 outline: fn.color(--key-focus --border) solid fn.dim(--key-focus --border);
145 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(--key-focus --outline);
146 opacity: 1;
147 }
148 }
149 }
150
151 @include iro.bem-elem('image') {
152 position: relative;
153 margin: calc(-1 * fn.dim(--key-focus --border));
154 background-color: fn.color(--quiet --image);
155 background-clip: padding-box;
156 border: fn.dim(--key-focus --border-offset) solid transparent;
157 border-radius: calc(fn.dim(--rounding) + fn.dim(--key-focus --border-offset));
158 }
159
160 @include iro.bem-elem('body') {
161 padding: 0;
162 padding-block-start: fn.dim(--spacing);
163 }
164
165 @include iro.bem-elem('footer') {
166 padding-inline: 0;
167 }
168 }
169 }
170}
diff --git a/src/objects/_checkbox.scss b/src/objects/_checkbox.scss
new file mode 100644
index 0000000..8d82cd5
--- /dev/null
+++ b/src/objects/_checkbox.scss
@@ -0,0 +1,261 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@include iro.props-namespace('checkbox') {
5 @include iro.props-store((
6 --dims: (
7 --size: fn.global-dim(--size --175),
8 --label-gap: fn.global-dim(--size --125),
9 --border: fn.global-dim(--border --medium),
10 --pad-i: fn.global-dim(--size --65),
11 --pad-b: fn.global-dim(--size --65),
12 --rounding: fn.global-dim(--rounding),
13 --spacing-sibling: fn.global-dim(--size --300),
14
15 --key-focus: (
16 --border: fn.global-dim(--key-focus --border),
17 --border-offset: fn.global-dim(--key-focus --border-offset),
18 --outline: fn.global-dim(--key-focus --outline),
19 ),
20 ),
21 --colors: (
22 --box-border: fn.global-color(--text-mute-more),
23 --box-bg: fn.global-color(--base --75),
24
25 --hover: (
26 --label: fn.global-color(--heading),
27 --box-border: fn.global-color(--text-mute),
28 ),
29 --accent: (
30 --box-border: fn.global-color(--accent --900),
31
32 --hover: (
33 --box-border: fn.global-color(--accent --1000),
34 ),
35 ),
36 --disabled: (
37 --label: fn.global-color(--text-disabled),
38 --box-border: fn.global-color(--border-strong),
39 --box-bg: fn.global-color(--base --75),
40 ),
41 --key-focus: (
42 --label: fn.global-color(--focus --text),
43 --border: fn.global-color(--focus --border),
44 --outline: fn.global-color(--focus --outline),
45 ),
46 ),
47 ));
48
49 @include iro.bem-object(iro.props-namespace()) {
50 position: relative;
51 display: inline-block;
52 padding-block: fn.dim(--pad-b);
53 padding-inline: fn.dim(--pad-i);
54 margin-inline:
55 calc(-1 * fn.dim(--pad-i) - fn.dim(--key-focus --border-offset))
56 calc(fn.dim(--spacing-sibling) - fn.dim(--pad-b) - fn.dim(--key-focus --border-offset));
57
58 @include iro.bem-elem('box') {
59 position: relative;
60 display: inline-block;
61 flex: 0 0 auto;
62 inline-size: fn.dim(--size);
63 block-size: fn.dim(--size);
64 margin-block-start: calc(.5em * fn.global-dim(--font --standard --line-height) - .5 * fn.dim(--size) - fn.dim(--key-focus --border-offset));
65 vertical-align: top;
66 background-color: fn.color(--box-border);
67 background-clip: padding-box;
68 border: fn.dim(--key-focus --border-offset) solid transparent;
69 border-radius: calc(fn.dim(--border) + fn.dim(--key-focus --border-offset));
70
71 &::before,
72 &::after {
73 position: absolute;
74 display: block;
75 content: '';
76 }
77
78 &::before {
79 inset-block-start: fn.dim(--border);
80 inset-inline-start: fn.dim(--border);
81 z-index: 2;
82 inline-size: calc(fn.dim(--size) - 2 * fn.dim(--border));
83 block-size: calc(fn.dim(--size) - 2 * fn.dim(--border));
84 background-color: fn.color(--box-bg);
85 transition: transform .2s ease;
86 }
87
88 &::after {
89 inset-block-start: calc(.5 * fn.dim(--size) - 1px);
90 inset-inline-start: calc(1.5 * fn.dim(--border));
91 z-index: 3;
92 box-sizing: border-box;
93 inline-size: calc(fn.dim(--size) - 3 * fn.dim(--border));
94 block-size: 0;
95 border-color: fn.color(--box-bg);
96 border-style: solid;
97 border-radius: 2px;
98 transition: transform .2s ease;
99 transform: scale(0);
100 border-block-width: 0 2px;
101 border-inline-width: 0 2px;
102 }
103 }
104
105 @include iro.bem-elem('check-icon') {
106 position: absolute;
107 inset-block-start: calc(1 * fn.dim(--border));
108 inset-inline-start: calc(1 * fn.dim(--border));
109 z-index: 2;
110 display: block;
111 inline-size: calc(100% - 2 * fn.dim(--border));
112 block-size: calc(100% - 2 * fn.dim(--border));
113 margin: 0;
114 color: fn.color(--box-bg);
115 stroke-width: iro.fn-px-to-rem(3px);
116 transition: transform .2s ease;
117 transform: scale(0);
118 transform-origin: 40% 90%;
119 }
120
121 @include iro.bem-elem('label') {
122 margin-inline-start: calc(fn.dim(--label-gap) - fn.dim(--key-focus --border-offset));
123 }
124
125 @include iro.bem-elem('native') {
126 position: absolute;
127 inset-block-start: 0;
128 inset-inline-start: 0;
129 z-index: -1;
130 inline-size: 100%;
131 block-size: 100%;
132 padding: 0;
133 margin: 0;
134 overflow: hidden;
135 appearance: none;
136 border-radius: fn.dim(--rounding);
137
138 &:hover,
139 &:focus-visible {
140 @include iro.bem-sibling-elem('label') {
141 color: fn.color(--hover --label);
142 }
143
144 @include iro.bem-sibling-elem('box') {
145 background-color: fn.color(--hover --box-border);
146 }
147 }
148
149 &:checked {
150 @include iro.bem-sibling-elem('box') {
151 &::before {
152 transform: scale(0);
153 }
154
155 @include iro.bem-elem('check-icon') {
156 transform: scale(1);
157 }
158 }
159 }
160
161 &:indeterminate {
162 @include iro.bem-sibling-elem('box') {
163 &::before {
164 transform: scale(0);
165 }
166
167 &::after {
168 transform: scale(1);
169 }
170
171 @include iro.bem-elem('check-icon') {
172 transform: scale(0);
173 }
174 }
175 }
176
177 &:disabled {
178 @include iro.bem-sibling-elem('label') {
179 color: fn.color(--disabled --label);
180 }
181
182 @include iro.bem-sibling-elem('box') {
183 background-color: fn.color(--disabled --box-border);
184
185 &::before {
186 background-color: fn.color(--disabled --box-bg);
187 }
188 }
189 }
190
191 &:focus-visible {
192 @include iro.bem-sibling-elem('label') {
193 color: fn.color(--key-focus --label);
194 }
195
196 @include iro.bem-sibling-elem('box') {
197 outline: fn.color(--key-focus --border) solid fn.dim(--key-focus --border);
198 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(--key-focus --outline);
199 }
200 }
201 }
202
203 @include iro.bem-modifier('standalone') {
204 @include iro.bem-elem('box') {
205 margin-block-start: 0;
206 }
207 }
208
209 @include iro.bem-modifier('accent') {
210 @include iro.bem-elem('native') {
211 &:checked {
212 @include iro.bem-sibling-elem('box') {
213 background-color: fn.color(--accent --box-border);
214 }
215
216 &:hover,
217 &:focus-visible {
218 @include iro.bem-sibling-elem('box') {
219 background-color: fn.color(--accent --hover --box-border);
220 }
221 }
222 }
223
224 &:indeterminate {
225 @include iro.bem-sibling-elem('box') {
226 background-color: fn.color(--accent --box-border);
227 }
228
229 &:hover,
230 &:focus-visible {
231 @include iro.bem-sibling-elem('box') {
232 background-color: fn.color(--accent --hover --box-border);
233 }
234 }
235 }
236
237 &:disabled {
238 @include iro.bem-sibling-elem('box') {
239 background-color: fn.color(--disabled --box-border);
240
241 &::before {
242 background-color: fn.color(--disabled --box-bg);
243 }
244 }
245
246 &:checked {
247 @include iro.bem-sibling-elem('box') {
248 background-color: fn.color(--disabled --box-border);
249 }
250 }
251
252 &:indeterminate {
253 @include iro.bem-sibling-elem('box') {
254 background-color: fn.color(--disabled --box-border);
255 }
256 }
257 }
258 }
259 }
260 }
261}
diff --git a/src/objects/_divider.scss b/src/objects/_divider.scss
new file mode 100644
index 0000000..7d96206
--- /dev/null
+++ b/src/objects/_divider.scss
@@ -0,0 +1,203 @@
1@use 'sass:map';
2@use 'iro-sass/src/iro-sass' as iro;
3@use '../functions' as fn;
4@use '../config';
5
6$static-themes: 'black' 'white' !default;
7
8@include iro.props-namespace('divider') {
9 @include iro.props-store((
10 --dims: (
11 --margin-b: fn.global-dim(--size --85),
12
13 --strong: (
14 --border: fn.global-dim(--border --thick),
15 --label-font-size: fn.global-dim(--font-size --100),
16 ),
17 --medium: (
18 --border: fn.global-dim(--border --medium),
19 --label-font-size: fn.global-dim(--font-size --75),
20 ),
21 --faint: (
22 --border: fn.global-dim(--border --thin),
23 --label-font-size: fn.global-dim(--font-size --50),
24 ),
25 ),
26 --colors: (
27 --strong: (
28 --bg: fn.global-color(--text),
29 --label: fn.global-color(--text),
30 ),
31 --medium: (
32 --bg: fn.global-color(--border),
33 --label: fn.global-color(--text-mute),
34 ),
35 --faint: (
36 --bg: fn.global-color(--border),
37 --label: fn.global-color(--text-mute-more),
38 ),
39 ),
40 ));
41
42 @each $color in map.keys(map.get(config.$themes, config.$theme-default, --palettes)) {
43 @if $color != '--base' {
44 @include iro.props-store((
45 --colors: (
46 $color: (
47 --bg: fn.global-color($color --800),
48 --label: fn.global-color($color --1000),
49 )
50 ),
51 ));
52 }
53 }
54
55 @each $theme in $static-themes {
56 @include iro.props-store((
57 --colors: (
58 --static-#{$theme}: (
59 --strong: (
60 --bg: fn.global-color(--#{$theme}-transparent --800),
61 --label: fn.global-color(--#{$theme}-transparent --900),
62 ),
63 --medium: (
64 --bg: fn.global-color(--#{$theme}-transparent --300),
65 --label: fn.global-color(--#{$theme}-transparent --500),
66 ),
67 --faint: (
68 --bg: fn.global-color(--#{$theme}-transparent --300),
69 --label: fn.global-color(--#{$theme}-transparent --500),
70 ),
71 )
72 ),
73 ));
74 }
75
76 @include iro.bem-object(iro.props-namespace()) {
77 display: flex;
78 flex: 0 0 auto;
79 flex-direction: row;
80 align-items: center;
81 block-size: 1em;
82 margin-block: fn.dim(--margin-b);
83 font-size: fn.dim(--strong --label-font-size);
84 font-weight: 700;
85 line-height: 1;
86 color: fn.color(--strong --label);
87 text-transform: uppercase;
88 letter-spacing: .5px;
89
90 &::before,
91 &::after {
92 flex: 1 1 auto;
93 inline-size: 100%;
94 block-size: fn.dim(--strong --border);
95 content: '';
96 background-color: fn.color(--strong --bg);
97 }
98
99 &::before {
100 display: block;
101 }
102
103 @include iro.bem-elem('label') {
104 flex: 0 0 auto;
105 }
106
107 @include iro.bem-modifier('vertical') {
108 align-self: stretch;
109 inline-size: 1px;
110 block-size: auto;
111 margin-block: 0;
112 background-color: fn.color(--faint --bg);
113
114 &::before,
115 &::after {
116 display: none;
117 }
118 }
119
120 @include iro.bem-modifier('medium') {
121 font-size: fn.dim(--medium --label-font-size);
122 font-weight: 500;
123 color: fn.color(--medium --label);
124
125 &::before,
126 &::after {
127 block-size: fn.dim(--medium --border);
128 background-color: fn.color(--medium --bg);
129 }
130 }
131
132 @include iro.bem-modifier('faint') {
133 font-size: fn.dim(--faint --label-font-size);
134 font-weight: 500;
135 color: fn.color(--faint --label);
136
137 &::before,
138 &::after {
139 block-size: fn.dim(--faint --border);
140 background-color: fn.color(--faint --bg);
141 }
142 }
143
144 @include iro.bem-modifier('labelled') {
145 &::before {
146 margin-inline-end: 1em;
147 }
148
149 &::after {
150 display: block;
151 margin-inline-start: 1em;
152 }
153 }
154
155 @each $color in 'blue' 'purple' 'red' 'green' 'yellow' {
156 @include iro.bem-modifier($color) {
157 &::before,
158 &::after {
159 background-color: fn.color(--#{$color} --bg);
160 }
161
162 @include iro.bem-elem('label') {
163 color: fn.color(--#{$color} --label);
164 }
165 }
166 }
167
168 @each $theme in $static-themes {
169 @include iro.bem-modifier(static-#{$theme}) {
170 &::before,
171 &::after {
172 background-color: fn.color(--static-#{$theme} --strong --bg);
173 }
174
175 @include iro.bem-elem('label') {
176 color: fn.color(--static-#{$theme} --strong --label);
177 }
178
179 @include iro.bem-modifier('medium') {
180 &::before,
181 &::after {
182 background-color: fn.color(--static-#{$theme} --medium --bg);
183 }
184
185 @include iro.bem-elem('label') {
186 color: fn.color(--static-#{$theme} --medium --label);
187 }
188 }
189
190 @include iro.bem-modifier('faint') {
191 &::before,
192 &::after {
193 background-color: fn.color(--static-#{$theme} --faint --bg);
194 }
195
196 @include iro.bem-elem('label') {
197 color: fn.color(--static-#{$theme} --faint --label);
198 }
199 }
200 }
201 }
202 }
203}
diff --git a/src/objects/_emoji.scss b/src/objects/_emoji.scss
new file mode 100644
index 0000000..41c614c
--- /dev/null
+++ b/src/objects/_emoji.scss
@@ -0,0 +1,73 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3@use 'sass:math';
4
5@use 'icon';
6
7@include iro.props-namespace('emoji') {
8 @include iro.props-store((
9 --dims: (
10 --size: calc(1 / 14 * 18em),
11 --pad: .3em,
12 --rounding: fn.global-dim(--rounding),
13 --zoom: 3,
14 --valign: -.25em,
15
16 --125: (
17 --size: calc(1 / 14 * 23em),
18 --valign: -.45em,
19 ),
20
21 --150: (
22 --size: calc(1 / 14 * 28em),
23 --valign: -.65em,
24 ),
25
26 --200: (
27 --size: calc(1 / 14 * 38em),
28 --valign: -1em,
29 )
30 ),
31 --colors: (
32 --bg: fn.global-color(--border-mute),
33 )
34 ));
35
36 @include iro.bem-object(iro.props-namespace()) {
37 position: relative;
38 display: inline-block;
39 inline-size: calc(fn.dim(--size));
40 block-size: calc(fn.dim(--size));
41 padding: calc(fn.dim(--pad));
42 margin: calc(-1 * fn.dim(--pad));
43 vertical-align: fn.dim(--valign);
44 object-fit: contain;
45
46 @include iro.bem-modifier('icon') {
47 margin: calc(-1 * fn.dim(--pad) - .5 * (fn.dim(--size) - fn.foreign-dim(--icon, --size)));
48 vertical-align: fn.foreign-dim(--icon, --valign);
49 }
50
51 @each $size in '125' '150' '200' {
52 @include iro.bem-modifier($size) {
53 inline-size: fn.dim(--#{$size} --size);
54 block-size: fn.dim(--#{$size} --size);
55 vertical-align: fn.dim(--#{$size} --valign);
56
57 @include iro.bem-modifier('icon') {
58 margin: calc(-1 * fn.dim(--pad) - .5 * (fn.dim(--#{$size} --size) - fn.foreign-dim(--icon, --size)));
59 }
60 }
61 }
62
63 @include iro.bem-modifier('zoomable') {
64 border-radius: calc(fn.dim(--rounding) / fn.dim(--zoom));
65 transition: transform .2s ease, background-color .2s ease;
66
67 &:hover {
68 background-color: fn.color(--bg);
69 transform: scale(fn.dim(--zoom));
70 }
71 }
72 }
73}
diff --git a/src/objects/_field-label.scss b/src/objects/_field-label.scss
new file mode 100644
index 0000000..ba3841a
--- /dev/null
+++ b/src/objects/_field-label.scss
@@ -0,0 +1,86 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@include iro.props-namespace('field-label') {
5 @include iro.props-store((
6 --dims: (
7 --spacing-i: fn.global-dim(--size --150),
8 --spacing-b: fn.global-dim(--size --85),
9 --label-font-size: fn.global-dim(--font-size --75),
10 --hint-font-size: fn.global-dim(--font-size --75),
11 ),
12 --colors: (
13 --label: fn.global-color(--text-mute),
14 --hint: fn.global-color(--text-mute),
15 --error-hint: fn.global-color(--negative --900),
16 --disabled: fn.global-color(--text-disabled),
17 ),
18 ));
19
20 @include iro.bem-object(iro.props-namespace()) {
21 display: block;
22
23 @include iro.bem-elem('label') {
24 display: block;
25 flex: 0 0 auto;
26 padding-inline-end: fn.dim(--spacing-i);
27 font-size: fn.dim(--label-font-size);
28 font-weight: 400;
29 line-height: 1.3;
30 color: fn.color(--label);
31
32 @include iro.bem-next-elem('content') {
33 margin-block-start: fn.dim(--spacing-b);
34 }
35 }
36
37 @include iro.bem-elem('content') {
38 display: block;
39 flex: 1 1 auto;
40 }
41
42 @include iro.bem-elem('hint') {
43 display: block;
44 margin-block-start: fn.dim(--spacing-b);
45 font-size: fn.dim(--hint-font-size);
46 color: fn.color(--hint);
47 }
48
49 @include iro.bem-is('invalid') {
50 @include iro.bem-elem('hint') {
51 color: fn.color(--error-hint);
52 }
53 }
54
55 @include iro.bem-is('disabled') {
56 @include iro.bem-elem('label', 'hint') {
57 color: fn.color(--disabled);
58 }
59 }
60
61 @include iro.bem-modifier('align-start', 'align-end') {
62 display: flex;
63 align-items: baseline;
64
65 @include iro.bem-elem('label') {
66 display: inline-block;
67
68 @include iro.bem-next-elem('content') {
69 margin-block-start: 0;
70 }
71 }
72 }
73
74 @include iro.bem-modifier('align-start') {
75 @include iro.bem-elem('label') {
76 text-align: start;
77 }
78 }
79
80 @include iro.bem-modifier('align-end') {
81 @include iro.bem-elem('label') {
82 text-align: end;
83 }
84 }
85 }
86}
diff --git a/src/objects/_heading.scss b/src/objects/_heading.scss
new file mode 100644
index 0000000..7fbafea
--- /dev/null
+++ b/src/objects/_heading.scss
@@ -0,0 +1,116 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3@use '../mixins' as mx;
4@use '../config';
5@use 'include-media/dist/include-media' as media;
6
7$sizes: 'xxl' 'xl' 'lg' 'md' 'sm' 'xs';
8
9@include iro.props-namespace('heading') {
10 @include iro.props-store((
11 --dims: (
12 --offset: -.02em,
13 ),
14 --colors: (
15 --bg: fn.global-color(--base --50),
16 ),
17 ));
18
19 @include iro.bem-object(iro.props-namespace()) {
20 @include mx.set-font(--headline);
21
22 display: block;
23 margin-block-start: fn.global-dim(--heading --margin-bs);
24 text-transform: none;
25 letter-spacing: normal;
26 transform: translateX(fn.dim(--offset));
27
28 & + & {
29 margin-block-start: fn.global-dim(--heading --margin-bs-sibling);
30 }
31
32 @include iro.bem-elem('highlight') {
33 background-image: linear-gradient(to top,
34 transparent .05em,
35 fn.color(--bg) .05em,
36 fn.color(--bg) .5em,
37 transparent .5em);
38 }
39
40 @include iro.bem-modifier('xxl') {
41 @include mx.heading-strong(--xxl);
42 }
43
44 @include iro.bem-modifier('xl') {
45 @include mx.heading-strong(--xl);
46 }
47
48 @include iro.bem-modifier('lg') {
49 @include mx.heading-medium(--lg);
50 }
51
52 @include iro.bem-modifier('md') {
53 @include mx.heading-medium(--md);
54 }
55
56 @include iro.bem-modifier('sm') {
57 @include mx.heading-faint(--sm);
58 }
59
60 @include iro.bem-modifier('xs') {
61 @include mx.heading-faint(--xs);
62 }
63
64 @include iro.bem-modifier('display') {
65 @include mx.set-font(--headline);
66
67 @include iro.bem-modifier('xxl') {
68 @include mx.heading-strong(--display --xxl);
69
70 @include media.media('<=md') {
71 @include mx.heading-strong(--display-sm --xxl);
72 }
73 }
74
75 @include iro.bem-modifier('xl') {
76 @include mx.heading-strong(--display --xl);
77
78 @include media.media('<=md') {
79 @include mx.heading-strong(--display-sm --xl);
80 }
81 }
82
83 @include iro.bem-modifier('lg') {
84 @include mx.heading-strong(--display --lg);
85
86 @include media.media('<=md') {
87 @include mx.heading-strong(--display-sm --lg);
88 }
89 }
90
91 @include iro.bem-modifier('md') {
92 @include mx.heading-strong(--display --md);
93
94 @include media.media('<=md') {
95 @include mx.heading-strong(--display-sm --md);
96 }
97 }
98
99 @include iro.bem-modifier('sm') {
100 @include mx.heading-medium(--display --sm);
101
102 @include media.media('<=md') {
103 @include mx.heading-medium(--display-sm --sm);
104 }
105 }
106
107 @include iro.bem-modifier('xs') {
108 @include mx.heading-faint(--display --xs);
109
110 @include media.media('<=md') {
111 @include mx.heading-faint(--display-sm --xs);
112 }
113 }
114 }
115 }
116}
diff --git a/src/objects/_icon.scss b/src/objects/_icon.scss
new file mode 100644
index 0000000..7cbb7db
--- /dev/null
+++ b/src/objects/_icon.scss
@@ -0,0 +1,26 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@include iro.props-namespace('icon') {
5 @include iro.props-store((
6 --dims: (
7 --stroke: 1.5px,
8 --size: calc(1 / 14 * 16em),
9 --valign: -.2em,
10 )
11 ));
12
13 @include iro.bem-object(iro.props-namespace()) {
14 display: inline;
15 inline-size: fn.dim(--size);
16 block-size: fn.dim(--size);
17 vertical-align: fn.dim(--valign);
18 stroke-linecap: round;
19 stroke-linejoin: round;
20 stroke-width: fn.dim(--stroke);
21
22 @include iro.bem-modifier('block') {
23 display: block;
24 }
25 }
26}
diff --git a/src/objects/_lightbox.scss b/src/objects/_lightbox.scss
new file mode 100644
index 0000000..edbc62a
--- /dev/null
+++ b/src/objects/_lightbox.scss
@@ -0,0 +1,313 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@use 'action-button';
5
6$static-themes: 'black' 'white' !default;
7
8@include iro.props-namespace('lightbox') {
9 @include iro.props-store((
10 --dims: (
11 --pad: fn.global-dim(--size --150),
12
13 --thumbnail: (
14 --size: fn.global-dim(--size --700),
15 --rounding: fn.global-dim(--rounding),
16 --spacing: fn.global-dim(--size --100),
17 --border: fn.global-dim(--border --thin),
18
19 --selected: (
20 --border: fn.global-dim(--border --medium),
21 ),
22
23 --key-focus: (
24 --border: fn.global-dim(--key-focus --border),
25 --border-offset: fn.global-dim(--key-focus --border-offset),
26 --outline: fn.global-dim(--key-focus --outline),
27 ),
28 ),
29
30 --close-button: (
31 --font-size: fn.global-dim(--font-size --200),
32 ),
33
34 --nav-button: (
35 --width: fn.global-dim(--size --2000),
36 --height: fn.global-dim(--size --3800),
37 --font-size: fn.global-dim(--font-size --200),
38 ),
39 ),
40 --colors: (
41 --thumbnail: (
42 --border: fn.global-color(--border-strong),
43
44 --hover: (
45 --border: fn.global-color(--text-mute-more),
46 ),
47
48 --selected: (
49 --border: fn.global-color(--heading),
50 ),
51
52 --key-focus: (
53 --border: fn.global-color(--focus --border),
54 --outline: fn.global-color(--focus --outline),
55 ),
56 ),
57 ),
58 ));
59
60 @each $theme in $static-themes {
61 @include iro.props-store((
62 --colors: (
63 --static-#{$theme}: (
64 --text: fn.global-color(--white-transparent --800),
65 --thumbnail: (
66 --border: fn.global-color(--white-transparent --400),
67
68 --hover: (
69 --border: fn.global-color(--white-transparent --500),
70 ),
71
72 --selected: (
73 --border: fn.global-color(--white-transparent --900),
74 ),
75
76 --key-focus: (
77 --border: fn.global-color(--#{$theme}-transparent --900),
78 --outline: fn.global-color(--#{$theme}-transparent --300),
79 ),
80 ),
81 )
82 )
83 ));
84 }
85
86 @include iro.props-store((
87 --dims: (
88 --thumbnail: (
89 --size: fn.global-dim(--size --600),
90 ),
91 --nav-button: (
92 --width: fn.global-dim(--size --2500),
93 --height: fn.global-dim(--size --2500),
94 ),
95 ),
96 ), 'md');
97
98 @include iro.bem-object(iro.props-namespace()) {
99 box-sizing: border-box;
100 display: grid;
101 flex: 1 1 auto;
102 grid-template-areas:
103 'header header header'
104 'prev content next'
105 'thumbnails thumbnails thumbnails'
106 'footer footer footer';
107 grid-template-rows: auto minmax(0, 1fr) auto auto;
108 grid-template-columns: auto minmax(0, 1fr) auto;
109 min-block-size: 0;
110
111 @include iro.bem-elem('header') {
112 display: flex;
113 grid-area: header;
114 align-items: flex-start;
115 padding-block-start: fn.dim(--pad);
116 padding-inline: fn.dim(--pad);
117 }
118
119 @include iro.bem-elem('img') {
120 box-sizing: border-box;
121 display: none;
122 grid-area: content;
123 place-self: center;
124 max-inline-size: 100%;
125 max-block-size: 100%;
126 padding: fn.dim(--pad);
127
128 @include iro.bem-sibling-elem('img') {
129 @include iro.bem-modifier('default') {
130 display: block;
131
132 @include iro.bem-next-elem('nav-btn') {
133 display: block;
134
135 @include iro.bem-next-elem('nav-btn') {
136 display: block;
137 }
138 }
139 }
140 }
141
142 @include iro.bem-multi('&:target', 'is' 'visible') {
143 display: block;
144
145 @include iro.bem-next-elem('nav-btn') {
146 display: block;
147
148 @include iro.bem-next-elem('nav-btn') {
149 display: block;
150 }
151 }
152
153 @include iro.bem-sibling-elem('img') {
154 @include iro.bem-modifier('default') {
155 display: none;
156
157 @include iro.bem-next-elem('nav-btn') {
158 display: none;
159
160 @include iro.bem-next-elem('nav-btn') {
161 display: none;
162 }
163 }
164 }
165 }
166 }
167 }
168
169 @include iro.bem-elem('thumbnails') {
170 display: flex;
171 grid-area: thumbnails;
172 gap: fn.dim(--thumbnail --spacing);
173 padding: fn.dim(--pad);
174 margin-block-start: calc(-1 * fn.dim(--pad));
175 overflow: auto;
176 }
177
178 @include iro.bem-elem('footer') {
179 display: flex;
180 grid-area: footer;
181 align-items: flex-start;
182 padding-block: 0 fn.dim(--pad);
183 padding-inline: fn.dim(--pad);
184 }
185
186 @include iro.bem-elem('thumbnail') {
187 position: relative;
188 flex: 0 0 auto;
189 inline-size: fn.dim(--thumbnail --size);
190 block-size: fn.dim(--thumbnail --size);
191 overflow: hidden;
192 border-radius: fn.dim(--thumbnail --rounding);
193 outline: fn.dim(--thumbnail --border) solid fn.color(--thumbnail --border);
194 outline-offset: calc(-1 * fn.dim(--thumbnail --border));
195 opacity: .75;
196
197 &:hover,
198 &:active,
199 &:focus-visible {
200 outline-color: fn.color(--thumbnail --hover --border);
201 opacity: 1;
202 }
203
204 @include iro.bem-is('selected') {
205 $focus-border-offset: calc(-1 * fn.dim(--thumbnail --selected --border));
206
207 margin: $focus-border-offset;
208 border: fn.dim(--thumbnail --selected --border) solid fn.color(--thumbnail --selected --border);
209 border-radius: calc(fn.dim(--thumbnail --rounding) - $focus-border-offset);
210 outline: none;
211 opacity: 1;
212 }
213
214 &:focus-visible {
215 $focus-border-offset: calc(-1 * fn.dim(--thumbnail --key-focus --border-offset));
216
217 margin: $focus-border-offset;
218 border: fn.dim(--thumbnail --key-focus --border-offset) solid transparent;
219 border-radius: calc(fn.dim(--thumbnail --rounding) - $focus-border-offset);
220 outline: fn.dim(--thumbnail --key-focus --border) solid fn.color(--thumbnail --key-focus --border);
221 outline-offset: 0;
222 box-shadow: 0 0 0 calc(fn.dim(--thumbnail --key-focus --outline) + fn.dim(--thumbnail --key-focus --border)) fn.color(--thumbnail --key-focus --outline);
223 }
224 }
225
226 @include iro.bem-elem('thumbnail-img') {
227 position: absolute;
228 inset-block-start: 0;
229 inset-inline-start: 0;
230 display: block;
231 inline-size: 100%;
232 block-size: 100%;
233 object-fit: cover;
234 object-position: center center;
235 }
236
237 @include iro.bem-elem('thumbnail-icon') {
238 position: absolute;
239 inset-block-start: 50%;
240 inset-inline-start: 50%;
241 transform: translate(-50%, -50%);
242 }
243
244 @include iro.bem-elem('close-btn') {
245 flex: 0 0 auto;
246 margin-block-start: calc(-.5 * fn.dim(--pad));
247 margin-inline: auto calc(-.5 * fn.dim(--pad));
248 font-size: fn.dim(--close-button --font-size);
249 }
250
251 @include iro.bem-elem('nav-btn') {
252 position: relative;
253 display: none;
254 align-self: center;
255 overflow: visible;
256 font-size: fn.dim(--nav-button --font-size);
257
258 &::before {
259 position: absolute;
260 inset-block-start: 50%;
261 display: block;
262 inline-size: fn.dim(--nav-button --width);
263 block-size: fn.dim(--nav-button --height);
264 content: '';
265 transform: translateY(-50%);
266 }
267
268 @include iro.bem-modifier('prev') {
269 grid-area: prev;
270 margin-inline: calc(.5 * fn.dim(--pad)) calc(-1 * fn.dim(--pad));
271
272 &::before {
273 inset-inline-start: 0;
274 }
275 }
276
277 @include iro.bem-modifier('next') {
278 grid-area: next;
279 margin-inline: calc(-1 * fn.dim(--pad)) calc(.5 * fn.dim(--pad));
280
281 &::before {
282 inset-inline-end: 0;
283 }
284 }
285 }
286
287 @each $theme in $static-themes {
288 @include iro.bem-modifier(static-#{$theme}) {
289 color: fn.color(--static-#{$theme} --text);
290
291 @include iro.bem-elem('thumbnail') {
292 outline-color: fn.color(--static-#{$theme} --thumbnail --border);
293
294 &:hover,
295 &:active,
296 &:focus-visible {
297 outline-color: fn.color(--static-#{$theme} --thumbnail --hover --border);
298 }
299
300 @include iro.bem-is('selected') {
301 border-color: fn.color(--static-#{$theme} --thumbnail --selected --border);
302 }
303
304 &:focus-visible {
305 border-color: transparent;
306 outline-color: fn.color(--static-#{$theme} --thumbnail --key-focus --border);
307 box-shadow: 0 0 0 calc(fn.dim(--thumbnail --key-focus --outline) + fn.dim(--thumbnail --key-focus --border)) fn.color(--static-#{$theme} --thumbnail --key-focus --outline);
308 }
309 }
310 }
311 }
312 }
313}
diff --git a/src/objects/_menu.scss b/src/objects/_menu.scss
new file mode 100644
index 0000000..12e9755
--- /dev/null
+++ b/src/objects/_menu.scss
@@ -0,0 +1,137 @@
1/* stylelint-disable length-zero-no-unit */
2
3@use 'iro-sass/src/iro-sass' as iro;
4@use '../functions' as fn;
5
6@use './icon';
7
8@include iro.props-namespace('menu') {
9 @include iro.props-store((
10 --dims: (
11 --spacing: 0em,
12 --header: (
13 --font-size: fn.global-dim(--font-size --50),
14 ),
15 --separator: fn.global-dim(--size --100),
16 --item: (
17 --pad-i: fn.global-dim(--size --150),
18 --pad-b: fn.global-dim(--size --100),
19 --rounding: 0em,
20
21 --key-focus: (
22 --border: fn.global-dim(--key-focus --border),
23 --border-offset: fn.global-dim(--key-focus --border-offset),
24 --outline: fn.global-dim(--key-focus --outline),
25 ),
26 ),
27 ),
28 --colors: (
29 --separator: fn.global-color(--border),
30 --header: (
31 --label: fn.global-color(--heading),
32 ),
33 --item: (
34 --hover: (
35 --bg: fn.global-color(--border-mute),
36 --label: fn.global-color(--heading),
37 ),
38 --active: (
39 --bg: fn.global-color(--border),
40 --label: fn.global-color(--heading),
41 ),
42 --disabled: (
43 --label: fn.global-color(--text-disabled),
44 ),
45 --key-focus: (
46 --border: fn.global-color(--focus --border),
47 --outline: fn.global-color(--focus --outline),
48 ),
49 ),
50 ),
51 ));
52
53 @include iro.bem-object(iro.props-namespace()) {
54 display: flex;
55 flex-direction: column;
56 gap: fn.dim(--spacing);
57
58 @include iro.bem-elem('header') {
59 padding-block: fn.dim(--item --pad-b);
60 padding-inline: fn.dim(--item --pad-i);
61 font-size: fn.dim(--header --font-size);
62 font-weight: 500;
63 color: fn.color(--header --label);
64 text-transform: uppercase;
65 letter-spacing: .5px;
66
67 @include iro.bem-next-twin-elem {
68 margin-block-start: calc(fn.dim(--separator) + fn.dim(--spacing));
69 }
70 }
71
72 @include iro.bem-elem('item') {
73 padding-block: fn.dim(--item --pad-b);
74 padding-inline: fn.dim(--item --pad-i);
75 margin: calc(-1 * fn.dim(--item --key-focus --outline));
76 color: fn.color(--item --disabled --label);
77 background-clip: padding-box;
78 border: fn.dim(--item --key-focus --outline) solid transparent;
79 border-radius: calc(fn.dim(--item --rounding) + fn.dim(--item --key-focus --outline));
80
81 &:link,
82 &:visited,
83 &:enabled {
84 color: currentColor;
85
86 @include iro.bem-multi('&:hover, &:focus-visible', 'is' 'selected') {
87 color: fn.color(--item --hover --label);
88 background-color: fn.color(--item --hover --bg);
89 }
90
91 &:active {
92 color: fn.color(--item --active --label);
93 background-color: fn.color(--item --active --bg);
94 }
95
96 &:focus-visible {
97 outline: fn.color(--item --key-focus --border) solid fn.dim(--item --key-focus --border);
98 box-shadow: 0 0 0 calc(fn.dim(--item --key-focus --border) + fn.dim(--item --key-focus --outline)) fn.color(--item --key-focus --outline);
99 }
100 }
101
102 @include iro.bem-next-elem('header') {
103 margin-block-start: calc(fn.dim(--separator) + fn.dim(--spacing));
104 }
105 }
106
107 @include iro.bem-elem('header') {
108 &:link,
109 &:visited,
110 &:enabled {
111 color: fn.color(--header --label);
112 }
113 }
114
115 @include iro.bem-elem('separator') {
116 block-size: 1px;
117 margin-block: fn.dim(--separator);
118 margin-inline: fn.dim(--item --pad-i);
119 background-color: fn.color(--separator);
120 }
121
122 @include iro.bem-elem('slot') {
123 padding-block: fn.dim(--item --pad-b);
124 padding-inline: fn.dim(--item --pad-i);
125 }
126
127 @include iro.bem-elem('icon-slot') {
128 display: flex;
129 justify-content: center;
130 inline-size: fn.foreign-dim(--icon, --size);
131 }
132
133 @include iro.bem-modifier('pull') {
134 margin: calc(-1 * fn.dim(--item --pad-i));
135 }
136 }
137}
diff --git a/src/objects/_palette.scss b/src/objects/_palette.scss
new file mode 100644
index 0000000..8291750
--- /dev/null
+++ b/src/objects/_palette.scss
@@ -0,0 +1,62 @@
1@use 'sass:map';
2@use 'sass:list';
3@use 'sass:string';
4@use 'iro-sass/src/iro-sass' as iro;
5@use '../functions' as fn;
6@use '../config';
7
8@include iro.props-namespace('palette') {
9 @include iro.bem-object(iro.props-namespace()) {
10 display: flex;
11 block-size: 3em;
12
13 @include iro.bem-elem('item') {
14 flex: 1 1 auto;
15
16 $palette: map.get(config.$themes, config.$theme-default, --palettes, --base);
17 $contrasts: map.get(config.$themes, config.$theme-default, --contrasts, list.nth($palette, 2));
18
19 @for $i from 1 through list.length($contrasts) {
20 $key: list.nth(map.keys($contrasts), $i);
21
22 &:nth-child(#{$i}) {
23 background-color: fn.global-color(--base $key);
24 }
25 }
26 }
27
28 @each $palette-name, $palette in map.get(config.$themes, config.$theme-default, --palettes) {
29 $contrasts: map.get(config.$themes, config.$theme-default, --contrasts, list.nth($palette, 2));
30
31 @include iro.bem-modifier(string.slice($palette-name, 3)) {
32 @include iro.bem-elem('item') {
33 @for $i from 1 through list.length($contrasts) {
34 $key: list.nth(map.keys($contrasts), $i);
35
36 &:nth-child(#{$i}) {
37 background-color: fn.global-color($palette-name $key);
38 }
39 }
40 }
41 }
42 }
43
44 @include iro.bem-modifier('static') {
45 @each $palette-name, $palette in map.get(config.$static-colors, --palettes) {
46 $contrasts: map.get(config.$static-colors, --contrasts);
47
48 @include iro.bem-modifier(string.slice($palette-name, 3)) {
49 @include iro.bem-elem('item') {
50 @for $i from 1 through list.length($contrasts) {
51 $key: list.nth(map.keys($contrasts), $i);
52
53 &:nth-child(#{$i}) {
54 background-color: fn.global-color(#{$palette-name}-static $key);
55 }
56 }
57 }
58 }
59 }
60 }
61 }
62}
diff --git a/src/objects/_popover.scss b/src/objects/_popover.scss
new file mode 100644
index 0000000..13550eb
--- /dev/null
+++ b/src/objects/_popover.scss
@@ -0,0 +1,51 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@include iro.props-namespace('popover') {
5 @include iro.props-store((
6 --dims: (
7 --z-index: 10000,
8 --pad-i: 0,
9 --pad-b: fn.global-dim(--size --85),
10 --separator: fn.global-dim(--size --85),
11 --rounding: fn.global-dim(--rounding),
12 --border: fn.global-dim(--border --thin),
13 ),
14 --colors: (
15 --bg: fn.global-color(--bg-l2),
16 --border: fn.global-color(--border),
17 --filter: drop-shadow(
18 fn.global-dim(--shadow --x)
19 fn.global-dim(--shadow --y)
20 fn.global-dim(--shadow --blur)
21 fn.global-color(--shadow)
22 ),
23 ),
24 ));
25
26 @include iro.bem-object(iro.props-namespace()) {
27 position: absolute;
28 inset-block-start: 0;
29 inset-inline-start: 0;
30 z-index: fn.dim(--z-index);
31 padding-block: fn.dim(--pad-b);
32 padding-inline: fn.dim(--pad-i);
33 background-color: fn.color(--bg);
34 filter: fn.color(--filter);
35 border: fn.dim(--border) solid fn.color(--border);
36 border-radius: fn.dim(--rounding);
37 transform: translate(var(--x), var(--y));
38
39 @include iro.bem-modifier('up-left') {
40 transform: translate(var(--x), calc(var(--y) - 100%));
41 }
42
43 @include iro.bem-modifier('up-right') {
44 transform: translate(calc(var(--x) - 100%), calc(var(--y) - 100%));
45 }
46
47 @include iro.bem-modifier('down-right') {
48 transform: translate(calc(var(--x) - 100%), var(--y));
49 }
50 }
51}
diff --git a/src/objects/_radio.scss b/src/objects/_radio.scss
new file mode 100644
index 0000000..ad3e8d4
--- /dev/null
+++ b/src/objects/_radio.scss
@@ -0,0 +1,185 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@include iro.props-namespace('radio') {
5 @include iro.props-store((
6 --dims: (
7 --diameter: fn.global-dim(--size --200),
8 --label-gap: fn.global-dim(--size --125),
9 --border: fn.global-dim(--border --medium),
10 --pad-i: fn.global-dim(--size --65),
11 --pad-b: fn.global-dim(--size --65),
12 --rounding: fn.global-dim(--rounding),
13 --spacing-sibling: fn.global-dim(--size --300),
14
15 --key-focus: (
16 --border: fn.global-dim(--key-focus --border),
17 --border-offset: fn.global-dim(--key-focus --border-offset),
18 --outline: fn.global-dim(--key-focus --outline),
19 ),
20 ),
21 --colors: (
22 --circle-border: fn.global-color(--text-mute-more),
23 --circle-bg: fn.global-color(--base --75),
24
25 --hover: (
26 --label: fn.global-color(--heading),
27 --circle-border: fn.global-color(--text-mute),
28 ),
29 --accent: (
30 --circle-border: fn.global-color(--accent --900),
31
32 --hover: (
33 --circle-border: fn.global-color(--accent --1000),
34 ),
35 ),
36 --disabled: (
37 --label: fn.global-color(--text-disabled),
38 --circle-border: fn.global-color(--border-strong),
39 --circle-bg: fn.global-color(--base --75),
40 ),
41 --key-focus: (
42 --label: fn.global-color(--focus --text),
43 --border: fn.global-color(--focus --border),
44 --outline: fn.global-color(--focus --outline),
45 ),
46 ),
47 ));
48
49 @include iro.bem-object(iro.props-namespace()) {
50 position: relative;
51 display: inline-block;
52 padding-block: fn.dim(--pad-b);
53 padding-inline: fn.dim(--pad-i);
54 margin-inline:
55 calc(-1 * fn.dim(--pad-i) - fn.dim(--key-focus --border-offset))
56 calc(fn.dim(--spacing-sibling) - fn.dim(--pad-i) - fn.dim(--key-focus --border-offset));
57
58 @include iro.bem-elem('circle') {
59 display: inline-block;
60 flex: 0 0 auto;
61 inline-size: fn.dim(--diameter);
62 block-size: fn.dim(--diameter);
63 margin-block-start: calc(.5em * fn.global-dim(--font --standard --line-height) - .5 * fn.dim(--diameter) - fn.dim(--key-focus --border-offset));
64 vertical-align: top;
65 background-color: fn.color(--circle-border);
66 background-clip: padding-box;
67 border: fn.dim(--key-focus --border-offset) solid transparent;
68 border-radius: 2em;
69
70 &::after {
71 position: relative;
72 inset-block-start: fn.dim(--border);
73 inset-inline-start: fn.dim(--border);
74 display: block;
75 inline-size: calc(fn.dim(--diameter) - 2 * fn.dim(--border));
76 block-size: calc(fn.dim(--diameter) - 2 * fn.dim(--border));
77 content: '';
78 background-color: fn.color(--circle-bg);
79 border-radius: fn.dim(--diameter);
80 transition: transform .2s ease;
81 }
82 }
83
84 @include iro.bem-elem('label') {
85 margin-inline-start: calc(fn.dim(--label-gap) - fn.dim(--key-focus --border-offset));
86 }
87
88 @include iro.bem-elem('native') {
89 position: absolute;
90 inset-block-start: 0;
91 inset-inline-start: 0;
92 z-index: -1;
93 inline-size: 100%;
94 block-size: 100%;
95 padding: 0;
96 margin: 0;
97 overflow: hidden;
98 appearance: none;
99 border-radius: fn.dim(--rounding);
100
101 &:hover,
102 &:focus-visible {
103 @include iro.bem-sibling-elem('label') {
104 color: fn.color(--hover --label);
105 }
106
107 @include iro.bem-sibling-elem('circle') {
108 background-color: fn.color(--hover --circle-border);
109 }
110 }
111
112 &:checked {
113 @include iro.bem-sibling-elem('circle') {
114 &::after {
115 transform: scale(.44);
116 }
117 }
118 }
119
120 &:disabled {
121 @include iro.bem-sibling-elem('label') {
122 color: fn.color(--disabled --label);
123 }
124
125 @include iro.bem-sibling-elem('circle') {
126 background-color: fn.color(--disabled --circle-border);
127
128 &::after {
129 background-color: fn.color(--disabled --circle-bg);
130 }
131 }
132 }
133
134 &:focus-visible {
135 @include iro.bem-sibling-elem('label') {
136 color: fn.color(--key-focus --label);
137 }
138
139 @include iro.bem-sibling-elem('circle') {
140 outline: fn.color(--key-focus --border) solid fn.dim(--key-focus --border);
141 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(--key-focus --outline);
142 }
143 }
144 }
145
146 @include iro.bem-modifier('standalone') {
147 @include iro.bem-elem('circle') {
148 margin-block-start: 0;
149 }
150 }
151
152 @include iro.bem-modifier('accent') {
153 @include iro.bem-elem('native') {
154 &:checked {
155 @include iro.bem-sibling-elem('circle') {
156 background-color: fn.color(--accent --circle-border);
157 }
158
159 &:hover,
160 &:focus-visible {
161 @include iro.bem-sibling-elem('circle') {
162 background-color: fn.color(--accent --hover --circle-border);
163 }
164 }
165 }
166
167 &:disabled {
168 @include iro.bem-sibling-elem('circle') {
169 background-color: fn.color(--disabled --circle-border);
170
171 &::after {
172 background-color: fn.color(--disabled --circle-bg);
173 }
174 }
175
176 &:checked {
177 @include iro.bem-sibling-elem('circle') {
178 background-color: fn.color(--disabled --circle-border);
179 }
180 }
181 }
182 }
183 }
184 }
185}
diff --git a/src/objects/_side-nav.scss b/src/objects/_side-nav.scss
new file mode 100644
index 0000000..237b5aa
--- /dev/null
+++ b/src/objects/_side-nav.scss
@@ -0,0 +1,122 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@use './icon';
5
6@include iro.props-namespace('side-nav') {
7 @include iro.props-store((
8 --dims: (
9 --spacing: fn.global-dim(--size --50),
10 --header: (
11 --font-size: fn.global-dim(--font-size --50),
12 ),
13 --separator: fn.global-dim(--size --200),
14 --item: (
15 --pad-i: fn.global-dim(--size --150),
16 --pad-b: fn.global-dim(--size --100),
17 --rounding: fn.global-dim(--rounding),
18
19 --key-focus: (
20 --border: fn.global-dim(--key-focus --border),
21 --border-offset: fn.global-dim(--key-focus --border-offset),
22 --outline: fn.global-dim(--key-focus --outline),
23 ),
24 ),
25 ),
26 --colors: (
27 --header: (
28 --label: fn.global-color(--text-mute-more),
29 ),
30 --item: (
31 --hover: (
32 --bg: fn.global-color(--border-mute),
33 --label: fn.global-color(--heading),
34 ),
35 --active: (
36 --bg: fn.global-color(--border),
37 --label: fn.global-color(--heading),
38 ),
39 --disabled: (
40 --label: fn.global-color(--text-disabled),
41 ),
42 --key-focus: (
43 --border: fn.global-color(--focus --border),
44 --outline: fn.global-color(--focus --outline),
45 ),
46 ),
47 ),
48 ));
49
50 @include iro.bem-object(iro.props-namespace()) {
51 display: flex;
52 flex-direction: column;
53 gap: fn.dim(--spacing);
54
55 @include iro.bem-elem('header') {
56 padding-block: fn.dim(--item --pad-b);
57 padding-inline: fn.dim(--item --pad-i);
58 font-size: fn.dim(--header --font-size);
59 font-weight: 500;
60 color: fn.color(--header --label);
61 text-transform: uppercase;
62 letter-spacing: .5px;
63
64 @include iro.bem-next-twin-elem {
65 margin-block-start: calc(fn.dim(--separator) + fn.dim(--spacing));
66 }
67 }
68
69 @include iro.bem-elem('item') {
70 padding-block: fn.dim(--item --pad-b);
71 padding-inline: fn.dim(--item --pad-i);
72 margin: calc(-1 * fn.dim(--item --key-focus --border-offset));
73 color: fn.color(--item --disabled --label);
74 background-clip: padding-box;
75 border: fn.dim(--item --key-focus --border-offset) solid transparent;
76 border-radius: calc(fn.dim(--item --rounding) + fn.dim(--item --key-focus --border-offset));
77
78 &:link,
79 &:visited,
80 &:enabled {
81 color: currentColor;
82
83 @include iro.bem-multi('&:hover, &:focus-visible', 'is' 'selected') {
84 color: fn.color(--item --hover --label);
85 background-color: fn.color(--item --hover --bg);
86 }
87
88 &:active {
89 color: fn.color(--item --active --label);
90 background-color: fn.color(--item --active --bg);
91 }
92
93 &:focus-visible {
94 outline: fn.color(--item --key-focus --border) solid fn.dim(--item --key-focus --border);
95 box-shadow: 0 0 0 calc(fn.dim(--item --key-focus --border) + fn.dim(--item --key-focus --outline)) fn.color(--item --key-focus --outline);
96 }
97 }
98
99 @include iro.bem-next-elem('header') {
100 margin-block-start: calc(fn.dim(--separator) + fn.dim(--spacing));
101 }
102 }
103
104 @include iro.bem-elem('header') {
105 &:link,
106 &:visited,
107 &:enabled {
108 color: fn.color(--header --label);
109 }
110 }
111
112 @include iro.bem-elem('separator') {
113 block-size: fn.dim(--separator);
114 }
115
116 @include iro.bem-elem('icon-slot') {
117 display: flex;
118 justify-content: center;
119 inline-size: fn.foreign-dim(--icon, --size);
120 }
121 }
122}
diff --git a/src/objects/_status-indicator.scss b/src/objects/_status-indicator.scss
new file mode 100644
index 0000000..ce1794a
--- /dev/null
+++ b/src/objects/_status-indicator.scss
@@ -0,0 +1,39 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4$themes: 'accent' 'positive' 'negative' 'warning' !default;
5
6@include iro.props-namespace('status-indicator') {
7 @include iro.props-store((
8 --dims: (
9 --size: fn.global-dim(--size --125),
10 ),
11 --colors: (
12 --default: fn.global-color(--border-strong),
13 --primary: fn.global-color(--text),
14 ),
15 ));
16
17 @each $theme in $themes {
18 @include iro.props-store((
19 --colors: (
20 --#{$theme}: fn.global-color(--#{$theme} --700),
21 ),
22 ));
23 }
24
25 @include iro.bem-object(iro.props-namespace()) {
26 display: inline-block;
27 inline-size: fn.dim(--size);
28 block-size: fn.dim(--size);
29 vertical-align: middle;
30 background-color: fn.color(--default);
31 border-radius: 10em;
32
33 @each $theme in $themes {
34 @include iro.bem-is($theme) {
35 background-color: fn.color(--#{$theme});
36 }
37 }
38 }
39}
diff --git a/src/objects/_switch.scss b/src/objects/_switch.scss
new file mode 100644
index 0000000..fa903b1
--- /dev/null
+++ b/src/objects/_switch.scss
@@ -0,0 +1,222 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@include iro.props-namespace('switch') {
5 @include iro.props-store((
6 --dims: (
7 --width: fn.global-dim(--size --350),
8 --height: fn.global-dim(--size --200),
9 --label-gap: fn.global-dim(--size --125),
10 --border: fn.global-dim(--border --medium),
11 --pad-i: fn.global-dim(--size --65),
12 --pad-b: fn.global-dim(--size --65),
13 --rounding: fn.global-dim(--rounding),
14 --spacing-sibling: fn.global-dim(--size --300),
15
16 --key-focus: (
17 --border: fn.global-dim(--key-focus --border),
18 --border-offset: fn.global-dim(--key-focus --border-offset),
19 --outline: fn.global-dim(--key-focus --outline),
20 ),
21 ),
22 --colors: (
23 --track-bg: fn.global-color(--border),
24 --handle-border: fn.global-color(--text-mute-more),
25 --handle-bg: fn.global-color(--base --50),
26
27 --hover: (
28 --label: fn.global-color(--heading),
29 --handle-border: fn.global-color(--text-mute),
30 ),
31 --accent: (
32 --handle-border: fn.global-color(--accent --900),
33
34 --hover: (
35 --handle-border: fn.global-color(--accent --1000),
36 ),
37 ),
38 --disabled: (
39 --label: fn.global-color(--text-disabled),
40 --track-bg: fn.global-color(--border),
41 --handle-border: fn.global-color(--border-strong),
42 --handle-bg: fn.global-color(--base --50),
43 ),
44 --key-focus: (
45 --label: fn.global-color(--focus --text),
46 --border: fn.global-color(--focus --border),
47 --outline: fn.global-color(--focus --outline),
48 ),
49 ),
50 ));
51
52 @include iro.bem-object(iro.props-namespace()) {
53 position: relative;
54 display: inline-block;
55 padding-block: fn.dim(--pad-b);
56 padding-inline: fn.dim(--pad-i);
57 margin-inline:
58 calc(-1 * fn.dim(--pad-i) - fn.dim(--key-focus --border-offset))
59 calc(fn.dim(--spacing-sibling) - fn.dim(--pad-i) - fn.dim(--key-focus --border-offset));
60
61 @include iro.bem-elem('indicator') {
62 display: inline-block;
63 flex: 0 0 auto;
64 inline-size: fn.dim(--width);
65 block-size: fn.dim(--height);
66 margin-block-start: calc(.5em * fn.global-dim(--font --standard --line-height) - .5 * fn.dim(--height) - fn.dim(--key-focus --border-offset));
67 vertical-align: top;
68 background-color: fn.color(--track-bg);
69 background-clip: padding-box;
70 border: fn.dim(--key-focus --border-offset) solid transparent;
71 border-radius: 2em;
72 transition: background-color .2s ease;
73
74 &::after {
75 display: block;
76 inline-size: calc(fn.dim(--height) - 2 * fn.dim(--border));
77 block-size: calc(fn.dim(--height) - 2 * fn.dim(--border));
78 content: '';
79 background-color: fn.color(--handle-bg);
80 border: fn.dim(--border) solid fn.color(--handle-border);
81 border-radius: fn.dim(--width);
82 transition: transform .2s ease;
83 }
84 }
85
86 @include iro.bem-elem('label') {
87 margin-inline-start: fn.dim(--label-gap);
88 }
89
90 @include iro.bem-elem('native') {
91 position: absolute;
92 inset-block-start: 0;
93 inset-inline-start: 0;
94 z-index: -1;
95 inline-size: 100%;
96 block-size: 100%;
97 padding: 0;
98 margin: 0;
99 overflow: hidden;
100 appearance: none;
101 border-radius: fn.dim(--rounding);
102
103 &:hover,
104 &:focus-visible {
105 @include iro.bem-sibling-elem('label') {
106 color: fn.color(--hover --label);
107 }
108
109 @include iro.bem-sibling-elem('indicator') {
110 &::after {
111 border-color: fn.color(--hover --handle-border);
112 }
113 }
114 }
115
116 &:checked {
117 @include iro.bem-sibling-elem('indicator') {
118 background-color: fn.color(--handle-border);
119
120 &::after {
121 border-color: fn.color(--handle-border);
122 transform: translate(calc(fn.dim(--width) - fn.dim(--height) + .5px), 0);
123 }
124 }
125
126 &:hover,
127 &:focus-visible {
128 @include iro.bem-sibling-elem('indicator') {
129 background-color: fn.color(--hover --handle-border);
130
131 &::after {
132 border-color: fn.color(--hover --handle-border);
133 }
134 }
135 }
136 }
137
138 &:disabled {
139 @include iro.bem-sibling-elem('label') {
140 color: fn.color(--disabled --label);
141 }
142
143 @include iro.bem-sibling-elem('indicator') {
144 background-color: fn.color(--disabled --track-bg);
145
146 &::after {
147 background-color: fn.color(--disabled --handle-bg);
148 border-color: fn.color(--disabled --handle-border);
149 }
150 }
151
152 &:checked {
153 @include iro.bem-sibling-elem('indicator') {
154 background-color: fn.color(--disabled --handle-border);
155
156 &::after {
157 border-color: fn.color(--disabled --handle-border);
158 }
159 }
160 }
161 }
162
163 &:focus-visible {
164 @include iro.bem-sibling-elem('label') {
165 color: fn.color(--key-focus --label);
166 }
167
168 @include iro.bem-sibling-elem('indicator') {
169 outline: fn.color(--key-focus --border) solid fn.dim(--key-focus --border);
170 box-shadow: 0 0 0 calc(fn.dim(--key-focus --border) + fn.dim(--key-focus --outline)) fn.color(--key-focus --outline);
171 }
172 }
173 }
174
175 @include iro.bem-modifier('standalone') {
176 @include iro.bem-elem('indicator') {
177 margin-block-start: 0;
178 }
179 }
180
181 @include iro.bem-modifier('accent') {
182 @include iro.bem-elem('native') {
183 &:checked {
184 @include iro.bem-sibling-elem('indicator') {
185 background-color: fn.color(--accent --handle-border);
186
187 &::after {
188 border-color: fn.color(--accent --handle-border);
189 }
190 }
191
192 &:hover,
193 &:focus-visible {
194 @include iro.bem-sibling-elem('indicator') {
195 background-color: fn.color(--accent --hover --handle-border);
196
197 &::after {
198 border-color: fn.color(--accent --hover --handle-border);
199 }
200 }
201 }
202 }
203
204 &:disabled {
205 @include iro.bem-sibling-elem('label') {
206 color: fn.color(--disabled --label);
207 }
208
209 &:checked {
210 @include iro.bem-sibling-elem('indicator') {
211 background-color: fn.color(--disabled --handle-border);
212
213 &::after {
214 border-color: fn.color(--disabled --handle-border);
215 }
216 }
217 }
218 }
219 }
220 }
221 }
222}
diff --git a/src/objects/_table.scss b/src/objects/_table.scss
new file mode 100644
index 0000000..5b16d66
--- /dev/null
+++ b/src/objects/_table.scss
@@ -0,0 +1,168 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3@use '../mixins' as mx;
4
5@include iro.props-namespace('table') {
6 @include iro.props-store((
7 --dims: (
8 --pad-i: fn.global-dim(--size --175),
9 --pad-b: fn.global-dim(--size --125),
10 --rounding: fn.global-dim(--rounding),
11 --border: fn.global-dim(--border --thin),
12
13 --sm: (
14 --pad-b: fn.global-dim(--size --75),
15 )
16 ),
17 --colors: (
18 --border: fn.global-color(--border),
19 --heading: fn.global-color(--heading),
20 --hover: fn.global-color(--border-mute),
21 --active: fn.global-color(--border),
22 --box: (
23 --bg: fn.global-color(--base --50),
24 --hover: fn.global-color(--bg-base),
25 --active: fn.global-color(--border-mute),
26 )
27 )
28 ));
29
30 @include iro.bem-object(iro.props-namespace()) {
31 border-spacing: 0;
32 border-collapse: separate;
33
34 @include iro.bem-modifier('fixed') {
35 table-layout: fixed;
36 }
37
38 @include iro.bem-elem('head-cell') {
39 @include mx.set-font(--standard, (
40 --line-height: null,
41 --size: fn.global-dim(--font-size --50),
42 --weight: bold,
43 --transform: uppercase,
44 --spacing: .5px
45 ));
46 padding-block: fn.dim(--pad-b);
47
48 padding-inline: fn.dim(--pad-i);
49 color: fn.color(--heading);
50 text-align: start;
51 }
52
53 @include iro.bem-elem('cell') {
54 padding-block: fn.dim(--pad-b);
55 padding-inline: fn.dim(--pad-i);
56 border-color: fn.color(--border);
57 border-style: solid;
58 border-width: 0;
59 border-block-start-width: fn.dim(--border);
60
61 @include iro.bem-modifier('divider') {
62 border-inline-end-width: fn.dim(--border);
63 }
64 }
65
66 @include iro.bem-elem('row') {
67 &:last-child {
68 @include iro.bem-elem('cell') {
69 border-block-end-width: fn.dim(--border);
70 }
71 }
72 }
73
74 @include iro.bem-modifier('flush') {
75 @include iro.bem-elem('head-cell', 'cell') {
76 &:first-child {
77 padding-inline-start: 0;
78 }
79
80 &:last-child {
81 padding-inline-end: 0;
82 }
83 }
84 }
85
86 @include iro.bem-modifier('box') {
87 @include iro.bem-elem('cell') {
88 background-color: fn.color(--box --bg);
89
90 &:first-child {
91 border-inline-start-width: fn.dim(--border);
92 }
93
94 &:last-child {
95 border-inline-end-width: fn.dim(--border);
96 }
97 }
98
99 @include iro.bem-elem('row') {
100 &:first-child {
101 @include iro.bem-elem('cell') {
102 &:first-child {
103 border-start-start-radius: fn.dim(--rounding);
104 }
105
106 &:last-child {
107 border-start-end-radius: fn.dim(--rounding);
108 }
109 }
110 }
111
112 &:last-child {
113 @include iro.bem-elem('cell') {
114 &:first-child {
115 border-end-start-radius: fn.dim(--rounding);
116 }
117
118 &:last-child {
119 border-end-end-radius: fn.dim(--rounding);
120 }
121 }
122 }
123 }
124 }
125
126 @include iro.bem-modifier('interactive') {
127 @include iro.bem-elem('row') {
128 @include iro.bem-elem('cell') {
129 cursor: pointer;
130 }
131
132 &:hover {
133 @include iro.bem-elem('cell') {
134 background-color: fn.color(--hover);
135 }
136 }
137
138 &:active {
139 @include iro.bem-elem('cell') {
140 background-color: fn.color(--active);
141 }
142 }
143 }
144
145 @include iro.bem-modifier('box') {
146 @include iro.bem-elem('row') {
147 &:hover {
148 @include iro.bem-elem('cell') {
149 background-color: fn.color(--box --hover);
150 }
151 }
152
153 &:active {
154 @include iro.bem-elem('cell') {
155 background-color: fn.color(--box --active);
156 }
157 }
158 }
159 }
160 }
161
162 @include iro.bem-modifier('sm') {
163 @include iro.bem-elem('head-cell', 'cell') {
164 padding-block: fn.dim(--sm --pad-b);
165 }
166 }
167 }
168}
diff --git a/src/objects/_text-field.scss b/src/objects/_text-field.scss
new file mode 100644
index 0000000..cfb5a6d
--- /dev/null
+++ b/src/objects/_text-field.scss
@@ -0,0 +1,213 @@
1@use 'iro-sass/src/iro-sass' as iro;
2@use '../functions' as fn;
3
4@mixin invalid {
5 $focus-border-offset: calc(fn.dim(--border) - fn.dim(--focus --border));
6
7 @include iro.bem-sibling-elem('bg') {
8 inset-block: $focus-border-offset;
9 inset-inline: $focus-border-offset;
10 border: fn.dim(--focus --border) solid fn.color(--error --border);
11 border-radius: calc(fn.dim(--rounding) - $focus-border-offset);
12 }
13
14 &:hover {
15 @include iro.bem-sibling-elem('bg') {
16 border-color: fn.color(--error --hover --border);
17 }
18 }
19
20 &:focus {
21 @include iro.bem-sibling-elem('bg') {
22 border-color: fn.color(--error --focus --border);
23 }
24 }
25}
26
27@mixin keyboard-focus {
28 @include iro.bem-sibling-elem('bg') {
29 border-color: fn.color(--key-focus --border);
30 outline: fn.color(--key-focus --outline) solid fn.dim(--key-focus --border);
31 //outline-offset: fn.dim(--focus --border);
32 }
33}
34
35@include iro.props-namespace('text-field') {
36 @include iro.props-store((
37 --dims: (
38 --line-height: 1.4,
39 --pad-i: fn.global-dim(--size --125),
40 --pad-b: fn.global-dim(--size --125),
41 --border: fn.global-dim(--border --thin),
42 --rounding: fn.global-dim(--rounding),
43
44 --extended: (
45 --pad: fn.global-dim(--size --50),
46 ),
47
48 --focus: (
49 --border: fn.global-dim(--border --medium),
50 ),
51
52 --key-focus: (
53 --border: fn.global-dim(--key-focus --outline),
54 ),
55 ),
56 --colors: (
57 --bg: fn.global-color(--base --50),
58 --placeholder: fn.global-color(--text-mute-more),
59 --text: fn.global-color(--text),
60 --border: fn.global-color(--border-strong),
61
62 --hover: (
63 --border: fn.global-color(--text-mute-more),
64 ),
65 --focus: (
66 --border: fn.global-color(--focus --border),
67 ),
68 --key-focus: (
69 --border: fn.global-color(--focus --border),
70 --outline: fn.global-color(--focus --outline),
71 ),
72 --error: (
73 --border: fn.global-color(--negative --700),
74
75 --hover: (
76 --border: fn.global-color(--negative --900),
77 ),
78 --focus: (
79 --border: fn.global-color(--negative --900),
80 ),
81 ),
82 --disabled: (
83 --bg: fn.global-color(--border-mute),
84 --placeholder: fn.global-color(--text-disabled),
85 --text: fn.global-color(--text-disabled),
86 --border: fn.global-color(--border-mute),
87 ),
88 ),
89 ));
90
91 @include iro.bem-object(iro.props-namespace()) {
92 $focus-border-offset: calc(fn.dim(--border) - fn.dim(--focus --border));
93
94 position: relative;
95 min-inline-size: 0;
96 background-color: fn.color(--bg);
97 border-radius: fn.dim(--rounding);
98
99 @include iro.bem-elem('bg') {
100 position: absolute;
101 inset-block: 0;
102 inset-inline: 0;
103 display: block;
104 pointer-events: none;
105 border: fn.dim(--border) solid fn.color(--border);
106 border-radius: fn.dim(--rounding);
107 }
108
109 @include iro.bem-elem('native') {
110 box-sizing: border-box;
111 inline-size: 100%;
112 padding-block: calc(fn.dim(--pad-b) - .5em * (fn.dim(--line-height) - 1));
113 padding-inline: fn.dim(--pad-i);
114 font: inherit;
115 line-height: fn.dim(--line-height);
116 color: fn.color(--text);
117 appearance: none;
118 resize: none;
119 background-color: transparent;
120 border: 1px solid transparent;
121
122 &::placeholder {
123 font-style: italic;
124 color: fn.color(--placeholder);
125 opacity: 1;
126 }
127
128 &:hover {
129 @include iro.bem-sibling-elem('bg') {
130 border-color: fn.color(--hover --border);
131 }
132 }
133
134 &:focus {
135 outline: 0;
136
137 @include iro.bem-sibling-elem('bg') {
138 inset-block: $focus-border-offset;
139 inset-inline: $focus-border-offset;
140 border: fn.dim(--focus --border) solid fn.color(--focus --border);
141 border-radius: calc(fn.dim(--rounding) - $focus-border-offset);
142 }
143 }
144
145 &:invalid {
146 @include invalid;
147 }
148
149 &:focus-visible,
150 &:invalid:focus-visible {
151 @include keyboard-focus;
152 }
153 }
154
155 @include iro.bem-modifier('extended') {
156 padding: fn.dim(--extended --pad);
157
158 @include iro.bem-multi('&', 'elem' 'bg') {
159 border-radius: calc(fn.dim(--rounding) + fn.dim(--extended --pad));
160 }
161
162 @include iro.bem-elem('native') {
163 &:focus {
164 @include iro.bem-sibling-elem('bg') {
165 border-radius: calc(fn.dim(--rounding) + fn.dim(--extended --pad) - $focus-border-offset);
166 }
167 }
168 }
169 }
170
171 @include iro.bem-is('invalid') {
172 @include iro.bem-elem('native') {
173 @include invalid;
174
175 &:focus-visible {
176 @include keyboard-focus;
177 }
178 }
179 }
180
181 @include iro.bem-is('disabled') {
182 background-color: fn.color(--disabled --bg);
183
184 @include iro.bem-elem('native') {
185 color: fn.color(--disabled --text);
186
187 &::placeholder {
188 color: fn.color(--disabled --placeholder);
189 }
190 }
191
192 @include iro.bem-elem('bg') {
193 border-color: fn.color(--disabled --border);
194 }
195
196 @include iro.bem-is('invalid') {
197 @include iro.bem-elem('native') {
198 @include iro.bem-sibling-elem('bg') {
199 border-color: fn.color(--disabled --border);
200 }
201 }
202 }
203
204 @include iro.bem-elem('native') {
205 &:invalid {
206 @include iro.bem-sibling-elem('bg') {
207 border-color: fn.color(--disabled --border);
208 }
209 }
210 }
211 }
212 }
213}