summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolpeon <git@volpeon.ink>2025-07-21 22:14:31 +0200
committerVolpeon <git@volpeon.ink>2025-07-21 22:14:31 +0200
commitd61c6362949ecb49d81e608af698a5e0fa4643fe (patch)
tree9ac3c062c717e3b2ca1c972b7ede4695ce9ae115
parentImproved card and card list (diff)
downloadiro-design-d61c6362949ecb49d81e608af698a5e0fa4643fe.tar.gz
iro-design-d61c6362949ecb49d81e608af698a5e0fa4643fe.tar.bz2
iro-design-d61c6362949ecb49d81e608af698a5e0fa4643fe.zip
Improved card
-rw-r--r--src/_config.defaults.scss8
-rw-r--r--src/layouts/_card-list.vars.scss2
-rw-r--r--src/objects/_card.scss106
-rw-r--r--src/objects/_card.vars.scss6
-rw-r--r--tpl/objects/card.pug13
-rw-r--r--tpl/views/card.pug22
6 files changed, 89 insertions, 68 deletions
diff --git a/src/_config.defaults.scss b/src/_config.defaults.scss
index ac20cb9..c328355 100644
--- a/src/_config.defaults.scss
+++ b/src/_config.defaults.scss
@@ -124,6 +124,10 @@ $theme-light: (
124 --bg-l2: --base --50, 124 --bg-l2: --base --50,
125 --bg-l1: --base --100, 125 --bg-l1: --base --100,
126 --bg-base: --base --200, 126 --bg-base: --base --200,
127
128 --box: (
129 --border: --base --200,
130 ),
127 )), 131 )),
128 132
129 --constants: ( 133 --constants: (
@@ -179,6 +183,10 @@ $theme-dark: (
179 --bg-base: --base --50, 183 --bg-base: --base --50,
180 --bg-l1: --base --75, 184 --bg-l1: --base --75,
181 --bg-l2: --base --100, 185 --bg-l2: --base --100,
186
187 --box: (
188 --border: --base --75,
189 ),
182 )), 190 )),
183 191
184 --constants: ( 192 --constants: (
diff --git a/src/layouts/_card-list.vars.scss b/src/layouts/_card-list.vars.scss
index f77bfbf..b489596 100644
--- a/src/layouts/_card-list.vars.scss
+++ b/src/layouts/_card-list.vars.scss
@@ -1,7 +1,7 @@
1@use 'iro-sass/src/props'; 1@use 'iro-sass/src/props';
2@use '../core.vars' as core; 2@use '../core.vars' as core;
3 3
4$row-gap: props.def(--l-card-list--row-gap, props.get(core.$size--200)) !default; 4$row-gap: props.def(--l-card-list--row-gap, props.get(core.$size--50)) !default;
5$quiet--row-gap: props.def(--l-card-list--quiet--row-gap, props.get(core.$size--800)) !default; 5$quiet--row-gap: props.def(--l-card-list--quiet--row-gap, props.get(core.$size--800)) !default;
6 6
7$grid--row-gap: props.def(--l-card-list--grid--row-gap, props.get(core.$size--400)) !default; 7$grid--row-gap: props.def(--l-card-list--grid--row-gap, props.get(core.$size--400)) !default;
diff --git a/src/objects/_card.scss b/src/objects/_card.scss
index aaf46b6..d5d300d 100644
--- a/src/objects/_card.scss
+++ b/src/objects/_card.scss
@@ -15,28 +15,18 @@
15 display: flex; 15 display: flex;
16 flex-direction: column; 16 flex-direction: column;
17 background-color: props.get(vars.$bg-color); 17 background-color: props.get(vars.$bg-color);
18 background-clip: content-box;
19 border: props.get(vars.$border-width) solid transparent; 18 border: props.get(vars.$border-width) solid transparent;
20 border-color: props.get(vars.$border-color); 19 border-color: props.get(vars.$border-color);
21 border-radius: props.get(vars.$rounding); 20 border-radius: props.get(vars.$rounding);
22 transition: transform .2s, border-color .2s; 21 transition: transform .2s, background-color .2s, border-color .2s;
23 22
24 @include bem.multi('&:link, &:visited, &:enabled', 'modifier' 'interactive') { 23 @include bem.multi('&:link, &:visited, &:enabled', 'modifier' 'interactive') {
25 &:hover, 24 &:hover,
26 &:active, 25 &:active,
27 &:focus-visible { 26 &:focus-visible {
28 transform: translateY(props.get(vars.$hover--offset-b)); 27 transform: translateY(props.get(vars.$hover--offset-b));
29 border-color: props.get(vars.$hover--border-color); 28 background-color: props.get(vars.$hover--bg-color);
30 29 border-color: props.get(vars.$hover--border-color);
31 @include bem.elem('body') {
32 @include bem.modifier('hidden') {
33 visibility: visible;
34 opacity: 1;
35 transition:
36 opacity .2s ease,
37 visibility .2s linear;
38 }
39 }
40 } 30 }
41 31
42 &:focus-visible { 32 &:focus-visible {
@@ -60,20 +50,19 @@
60 position: relative; 50 position: relative;
61 display: block; 51 display: block;
62 flex: 0 0 auto; 52 flex: 0 0 auto;
63 inline-size: calc(100% + 2 * props.get(vars.$border-width)); 53 inline-size: 100%;
64 margin: calc(-1 * props.get(vars.$border-width));
65 overflow: hidden; 54 overflow: hidden;
66 object-fit: cover; 55 object-fit: cover;
67 transition: background-color .2s, transform .2s, opacity .2s; 56 transition: background-color .2s, transform .2s, opacity .2s;
68 57
69 &:first-child { 58 &:first-child {
70 border-start-start-radius: props.get(vars.$rounding); 59 border-start-start-radius: calc(props.get(vars.$rounding) - props.get(vars.$border-width));
71 border-start-end-radius: props.get(vars.$rounding); 60 border-start-end-radius: calc(props.get(vars.$rounding) - props.get(vars.$border-width));
72 } 61 }
73 62
74 &:last-child { 63 &:last-child {
75 border-end-start-radius: props.get(vars.$rounding); 64 border-end-start-radius: calc(props.get(vars.$rounding) - props.get(vars.$border-width));
76 border-end-end-radius: props.get(vars.$rounding); 65 border-end-end-radius: calc(props.get(vars.$rounding) - props.get(vars.$border-width));
77 } 66 }
78 67
79 @include bem.next-elem('avatar') { 68 @include bem.next-elem('avatar') {
@@ -106,26 +95,6 @@
106 margin-block: -100em 100em; 95 margin-block: -100em 100em;
107 content: ''; 96 content: '';
108 } 97 }
109
110 @include bem.modifier('hidden') {
111 position: absolute;
112 inset-block-end: calc(-1 * props.get(vars.$border-width));
113 inset-inline: calc(-1 * props.get(vars.$border-width));
114 z-index: 10;
115 visibility: hidden;
116 background-color: props.get(vars.$bg-color);
117 border-end-start-radius: props.get(vars.$rounding);
118 border-end-end-radius: props.get(vars.$rounding);
119 opacity: 0;
120 transition:
121 opacity .2s ease,
122 visibility 0s .2s linear;
123
124 @include bem.next-elem('image') {
125 border-start-start-radius: props.get(vars.$rounding);
126 border-start-end-radius: props.get(vars.$rounding);
127 }
128 }
129 } 98 }
130 99
131 @include bem.elem('content') { 100 @include bem.elem('content') {
@@ -157,19 +126,14 @@
157 &:hover, 126 &:hover,
158 &:active, 127 &:active,
159 &:focus-visible { 128 &:focus-visible {
160 transform: none; 129 transform: none;
130 background-color: transparent;
161 131
162 @include bem.elem('image') { 132 @include bem.elem('image') {
163 background-color: props.get(vars.$quiet--hover--image-color); 133 background-color: props.get(vars.$quiet--hover--image-color);
164 opacity: .75; 134 opacity: .75;
165 transform: translateY(props.get(vars.$hover--offset-b)); 135 transform: translateY(props.get(vars.$hover--offset-b));
166 } 136 }
167
168 @include bem.elem('body') {
169 @include bem.modifier('hidden') {
170 transform: translateY(props.get(vars.$hover--offset-b));
171 }
172 }
173 } 137 }
174 138
175 &:focus-visible { 139 &:focus-visible {
@@ -205,11 +169,6 @@
205 @include bem.elem('body') { 169 @include bem.elem('body') {
206 padding: 0; 170 padding: 0;
207 padding-block-start: props.get(vars.$spacing); 171 padding-block-start: props.get(vars.$spacing);
208
209 @include bem.modifier('hidden') {
210 padding-block: props.get(vars.$pad-b);
211 padding-inline: props.get(vars.$pad-i);
212 }
213 } 172 }
214 173
215 @include bem.elem('footer') { 174 @include bem.elem('footer') {
@@ -217,6 +176,49 @@
217 } 176 }
218 } 177 }
219 178
179 @include bem.modifier('thumbnail') {
180 @include bem.elem('image') {
181 inline-size: calc(100% + 2 * props.get(vars.$border-width));
182 margin: calc(-1 * props.get(vars.$border-width));
183 border-radius: props.get(vars.$rounding);
184 }
185
186 @include bem.elem('body') {
187 position: absolute;
188 inset-block-end: calc(-1 * props.get(vars.$border-width));
189 inset-inline: calc(-1 * props.get(vars.$border-width));
190 z-index: 10;
191 visibility: hidden;
192 background-color: props.get(vars.$bg-color);
193 border-width: 0 props.get(vars.$border-width) props.get(vars.$border-width);
194 border-color: transparent;
195 border-style: solid;
196 border-end-start-radius: calc(props.get(vars.$rounding) - props.get(vars.$border-width));
197 border-end-end-radius: calc(props.get(vars.$rounding) - props.get(vars.$border-width));
198 opacity: 0;
199 transition:
200 border-color .2s ease,
201 opacity .2s ease,
202 visibility 0s .2s linear;
203 }
204
205 @include bem.multi('&:link, &:visited, &:enabled', 'modifier' 'interactive') {
206 &:hover,
207 &:active,
208 &:focus-visible {
209 @include bem.elem('body') {
210 border-color: props.get(vars.$hover--border-color);
211 visibility: visible;
212 opacity: 1;
213 transition:
214 border-color .2s ease,
215 opacity .2s ease,
216 visibility .2s linear;
217 }
218 }
219 }
220 }
221
220 @include bem.modifier('horizontal') { 222 @include bem.modifier('horizontal') {
221 flex-direction: row; 223 flex-direction: row;
222 align-items: center; 224 align-items: center;
diff --git a/src/objects/_card.vars.scss b/src/objects/_card.vars.scss
index ca603be..9810239 100644
--- a/src/objects/_card.vars.scss
+++ b/src/objects/_card.vars.scss
@@ -19,11 +19,11 @@ $key-focus--border-offset: props.def(--o-card--key-focus--border-offset, props.g
19$key-focus--outline-width: props.def(--o-card--key-focus--outline-width, props.get(core.$key-focus--outline-width)) !default; 19$key-focus--outline-width: props.def(--o-card--key-focus--outline-width, props.get(core.$key-focus--outline-width)) !default;
20 20
21$bg-color: props.def(--o-card--bg-color, props.get(core.$theme, --bg-l2), 'color') !default; 21$bg-color: props.def(--o-card--bg-color, props.get(core.$theme, --bg-l2), 'color') !default;
22$border-color: props.def(--o-card--border-color, props.get(core.$theme, --border-mute), 'color') !default; 22$border-color: props.def(--o-card--border-color, props.get(core.$theme, --box, --border), 'color') !default;
23$divider-color: props.def(--o-card--divider-color, props.get(core.$theme, --border-mute), 'color') !default; 23$divider-color: props.def(--o-card--divider-color, props.get(core.$theme, --border-mute), 'color') !default;
24 24
25$hover--border-color: props.def(--o-card--hover--border-color, props.get(core.$theme, --border-strong), 'color') !default; 25$hover--bg-color: props.def(--o-card--hover--bg-color, props.get(core.$theme, --border-mute), 'color') !default;
26$hover--sub-border-color: props.def(--o-card--hover--sub-border-color, props.get(core.$theme, --focus, --outline), 'color') !default; 26$hover--border-color: props.def(--o-card--hover--border-color, props.get(core.$theme, --border), 'color') !default;
27 27
28$key-focus--label-color: props.def(--o-card--key-focus--label-color, props.get(core.$theme, --focus, --text), 'color') !default; 28$key-focus--label-color: props.def(--o-card--key-focus--label-color, props.get(core.$theme, --focus, --text), 'color') !default;
29$key-focus--border-color: props.def(--o-card--key-focus--border-color, props.get(core.$theme, --focus, --border), 'color') !default; 29$key-focus--border-color: props.def(--o-card--key-focus--border-color, props.get(core.$theme, --focus, --border), 'color') !default;
diff --git a/tpl/objects/card.pug b/tpl/objects/card.pug
index acb86eb..1db2fe5 100644
--- a/tpl/objects/card.pug
+++ b/tpl/objects/card.pug
@@ -1,8 +1,9 @@
1mixin card 1mixin card
2 - 2 -
3 let classes = { 3 let classes = {
4 'o-card': true, 4 'o-card': true,
5 'o-card--quiet': !!attributes.quiet, 5 'o-card--quiet': !!attributes.quiet,
6 'o-card--thumbnail': !!attributes.thumbnail,
6 } 7 }
7 8
8 if (attributes.class) { 9 if (attributes.class) {
@@ -38,13 +39,7 @@ mixin card-image
38 block 39 block
39 40
40mixin card-body 41mixin card-body
41 - 42 .o-card__body(style=attributes.style)
42 let classes = {
43 'o-card__body': true,
44 'o-card__body--hidden': attributes.hidden,
45 }
46
47 div(class=classes)(style=attributes.style)
48 block 43 block
49 44
50mixin card-title 45mixin card-title
diff --git a/tpl/views/card.pug b/tpl/views/card.pug
index 3fd0113..8dde279 100644
--- a/tpl/views/card.pug
+++ b/tpl/views/card.pug
@@ -1,5 +1,21 @@
1mixin view-card 1mixin view-card
2 +view('card', 'Card')(wide=true) 2 +view('card', 'Card')(wide=true)
3 .l-card-list
4 +card(href='#' class='l-card-list__card')
5 +card-body
6 strong= 'Lorem ipsum dolor'
7 = 'sit amet'
8 +card(href='#' class='l-card-list__card')
9 +card-body
10 strong= 'Lorem ipsum dolor'
11 = 'sit amet'
12 +card(href='#' class='l-card-list__card')
13 +card-body
14 strong= 'Lorem ipsum dolor'
15 = 'sit amet'
16
17 +divider('faint')(class='u-mb-700')
18
3 .l-card-list.l-card-list--merge 19 .l-card-list.l-card-list--merge
4 +card(href='#' class='l-card-list__card') 20 +card(href='#' class='l-card-list__card')
5 +card-body 21 +card-body
@@ -17,10 +33,10 @@ mixin view-card
17 +divider('faint')(class='u-mb-700') 33 +divider('faint')(class='u-mb-700')
18 34
19 .l-card-list.l-card-list--masonry 35 .l-card-list.l-card-list--masonry
20 +card(href='#' class='l-card-list__card') 36 +card(thumbnail=true href='#' class='l-card-list__card')
21 +card-body(hidden=true)
22 +card-title= 'XS Heading'
23 +card-image(src='Drawing_Half.png' style={ 'aspect-ratio': '21 / 9' }) 37 +card-image(src='Drawing_Half.png' style={ 'aspect-ratio': '21 / 9' })
38 +card-body
39 +card-title= 'XS Heading'
24 40
25 +card(href='#' class='l-card-list__card') 41 +card(href='#' class='l-card-list__card')
26 +card-image(src='Drawing_Half.png' style={ 'aspect-ratio': '21 / 9' }) 42 +card-image(src='Drawing_Half.png' style={ 'aspect-ratio': '21 / 9' })