-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat(web): Introduce Skeleton component #DS-1625
- Loading branch information
Řehořková Kateřina
committed
Jan 22, 2025
1 parent
fd239fd
commit 080ae06
Showing
7 changed files
with
522 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Skeleton | ||
|
||
## Text | ||
|
||
The `Skeleton--text` class is used to create a text skeleton. | ||
|
||
- Number of lines is defined by number of `Skeleton__item` elements | ||
- Minimum number of lines is 1 | ||
|
||
```html | ||
|
||
<div class="Skeleton Skeleton--text" aria-busy="true" aria-live="polite"> | ||
<div class="Skeleton__item Skeleton__item--text Skeleton__item--small" aria-hidden="true"></div> | ||
<div class="Skeleton__item Skeleton__item--text Skeleton__item--small" aria-hidden="true"></div> | ||
</div> | ||
``` | ||
|
||
## Headline | ||
|
||
The `Skeleton--headline` class is used to create a headline skeleton. | ||
|
||
```html | ||
|
||
<div class="Skeleton Skeleton--headline" aria-busy="true" aria-live="polite"> | ||
<div class="Skeleton__item Skeleton__item--text Skeleton__item--small" aria-hidden="true"></div> | ||
<div class="Skeleton__item Skeleton__item--text Skeleton__item--small" aria-hidden="true"></div> | ||
</div> | ||
``` | ||
|
||
### Text, Headline sizes: | ||
|
||
The Skeleton component supports the following sizes for text and headline skeletons: | ||
|
||
- `Skeleton__item--xsmall` | ||
- `Skeleton__item--small` | ||
- `Skeleton__item--medium` (default) | ||
- `Skeleton__item--large` | ||
- `Skeleton__item--xlarge` | ||
|
||
```html | ||
|
||
<div class="Skeleton__item Skeleton__item--text Skeleton__item--xsmall" aria-hidden="true"></div> | ||
``` | ||
|
||
## Shapes | ||
|
||
Use CSS custom properties to define the width, height, and radius of the shape. | ||
|
||
- The default radius is `--spirit-radius-300` | ||
|
||
```html | ||
--spirit-skeleton-shape-width: number{px}; | ||
--spirit-skeleton-shape-height: number{px}; | ||
--spirit-skeleton-shape-radius: var(--spirit-radius-200); | ||
--spirit-skeleton-shape-tablet-radius: var(--spirit-radius-300); | ||
--spirit-skeleton-shape-desktop-radius: var(--spirit-radius-400); | ||
``` | ||
|
||
```html | ||
|
||
<div class="Skeleton Skeleton--shape" aria-busy="true" aria-live="polite"> | ||
<div | ||
class="Skeleton__item Skeleton__item--shape" | ||
style="--spirit-skeleton-shape-width: 100px; --spirit-skeleton-shape-height: 100px; --spirit-skeleton-shape-radius: var(--spirit-radius-400)" | ||
></div> | ||
</div> | ||
``` | ||
|
||
### Circle | ||
|
||
- For circle there is class `Skeleton__item--circle` | ||
|
||
```html | ||
--spirit-skeleton-shape-width: number{px}; | ||
--spirit-skeleton-shape-height: number{px}; | ||
``` | ||
|
||
```html | ||
|
||
<div class="Skeleton Skeleton--shape" aria-busy="true" aria-live="polite"> | ||
<div | ||
class="Skeleton__item Skeleton__item--shape Skeleton__item--circle" | ||
style="--spirit-skeleton-shape-width: 100px; --spirit-skeleton-shape-height: 100px" | ||
></div> | ||
</div> | ||
``` | ||
|
||
Shape can be used on `img` element as well. | ||
|
||
- `height` and `width` of element should be defined as well | ||
|
||
```html | ||
|
||
<div class="Skeleton Skeleton--shape" aria-busy="true" aria-live="polite"> | ||
<img | ||
src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" | ||
width="100" | ||
height="100" | ||
alt="Loading" | ||
class="Skeleton__item Skeleton__item--shape" | ||
style="--spirit-skeleton-shape-width: 100px; --spirit-skeleton-shape-height: 100px; --spirit-skeleton-shape-radius: var(--spirit-radius-400)" | ||
> | ||
</div> | ||
``` | ||
|
||
|
||
|
||
|
101 changes: 101 additions & 0 deletions
101
packages/web/src/scss/components/Skeleton/_Skeleton.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
@use 'theme'; | ||
@use 'tools'; | ||
@use 'sass:map'; | ||
@use '@tokens' as tokens; | ||
@use '../../tools/breakpoint'; | ||
|
||
.Skeleton { | ||
width: 100%; | ||
cursor: progress; | ||
} | ||
|
||
.Skeleton--text { | ||
@include tools.generate-sizes($class-name: 'Skeleton__item', $sizes: theme.$sizes-body); | ||
} | ||
|
||
.Skeleton--heading { | ||
@include tools.generate-sizes($class-name: 'Skeleton__item', $sizes: theme.$sizes-heading-mobile); | ||
|
||
@include breakpoint.up(map.get(theme.$breakpoints, tablet)) { | ||
@include tools.generate-sizes($class-name: 'Skeleton__item', $sizes: theme.$sizes-heading-tablet); | ||
} | ||
|
||
@include breakpoint.up(map.get(theme.$breakpoints, desktop)) { | ||
@include tools.generate-sizes($class-name: 'Skeleton__item', $sizes: theme.$sizes-heading-desktop); | ||
} | ||
} | ||
|
||
.Skeleton--shape { | ||
display: inline-flex; | ||
overflow: hidden; | ||
} | ||
|
||
.Skeleton__item { | ||
display: block; | ||
width: 100%; | ||
background: theme.$background; | ||
background-size: 400% 400%; | ||
animation: skeleton-loading 2s ease infinite; | ||
|
||
&:not(:last-child) { | ||
margin-bottom: theme.$margin-bottom; | ||
} | ||
} | ||
|
||
.Skeleton__item--text { | ||
height: var(--#{tokens.$css-variable-prefix}skeleton-item-height, #{theme.$typography-default-height}); | ||
border-radius: theme.$typography-border-radius; | ||
|
||
&:last-child:not(:first-child) { | ||
width: 80%; | ||
} | ||
} | ||
|
||
.Skeleton__item--shape { | ||
width: var(--#{tokens.$css-variable-prefix}skeleton-shape-width); | ||
height: var(--#{tokens.$css-variable-prefix}skeleton-shape-height); | ||
object-fit: cover; | ||
border: 1px solid theme.$shape-border-color; | ||
border-radius: var( | ||
--#{tokens.$css-variable-prefix}skeleton-shape-border-radius, | ||
#{theme.$shape-default-border-radius} | ||
); | ||
} | ||
|
||
.Skeleton__item--circle { | ||
border-radius: theme.$border-radius-circle; | ||
} | ||
|
||
$previous-suffix: ''; | ||
$previous-previous-suffix: ''; | ||
|
||
@each $breakpoint-name, $breakpoint-value in theme.$breakpoints { | ||
$suffix: breakpoint.get-modifier(suffix, $breakpoint-name, $breakpoint-value); | ||
$prefix: #{tokens.$css-variable-prefix}skeleton-shape; | ||
|
||
.Skeleton--shape { | ||
--#{$prefix}#{$suffix}-radius: var(--#{tokens.$css-variable-prefix}skeleton-shape#{$suffix}-radius); | ||
} | ||
|
||
@include breakpoint.up($breakpoint-value) { | ||
.Skeleton__item--shape { | ||
--#{$prefix}-border-radius: var( | ||
--#{$prefix}#{$suffix}-radius, | ||
var(--#{$prefix}#{$previous-suffix}-radius, var(--#{$prefix}#{$previous-previous-suffix}-radius)) | ||
); | ||
} | ||
} | ||
|
||
$previous-previous-suffix: $previous-suffix; | ||
$previous-suffix: $suffix; | ||
} | ||
|
||
@keyframes skeleton-loading { | ||
0% { | ||
background-position: 100% 50%; | ||
} | ||
|
||
100% { | ||
background-position: 0 50%; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
@use '@tokens' as tokens; | ||
@use 'sass:map'; | ||
@use 'tools'; | ||
|
||
$margin-bottom: tokens.$space-400; | ||
$background: linear-gradient(94.81deg, #ececec 0%, #fff 48.5%, #ececec 100%); // TODO: update to tokens | ||
$breakpoints: tokens.$breakpoints; | ||
|
||
$typography-border-radius: tokens.$radius-300; | ||
$typography-default-height: tools.get-height(tokens.$body-medium-bold, mobile); | ||
|
||
$border-radius-default: tokens.$radius-300; | ||
$border-radius-square: tokens.$radius-400; | ||
$border-radius-circle: tokens.$radius-full; | ||
|
||
$shape-border-color: tokens.$disabled-border; | ||
$shape-default-border-radius: tokens.$radius-300; | ||
|
||
$sizes-body: ( | ||
xsmall: ( | ||
height: tools.get-height(tokens.$body-xsmall-bold, mobile), | ||
), | ||
small: ( | ||
height: tools.get-height(tokens.$body-small-bold, mobile), | ||
), | ||
medium: ( | ||
height: tools.get-height(tokens.$body-medium-bold, mobile), | ||
), | ||
large: ( | ||
height: tools.get-height(tokens.$body-large-bold, mobile), | ||
), | ||
xlarge: ( | ||
height: tools.get-height(tokens.$body-xlarge-bold, mobile), | ||
), | ||
); | ||
|
||
$sizes-heading-mobile: ( | ||
xsmall: ( | ||
height: tools.get-height(tokens.$heading-xsmall-bold, mobile), | ||
), | ||
small: ( | ||
height: tools.get-height(tokens.$heading-small-bold, mobile), | ||
), | ||
medium: ( | ||
height: tools.get-height(tokens.$heading-medium-bold, mobile), | ||
), | ||
large: ( | ||
height: tools.get-height(tokens.$heading-large-bold, mobile), | ||
), | ||
xlarge: ( | ||
height: tools.get-height(tokens.$heading-xlarge-bold, mobile), | ||
), | ||
); | ||
|
||
$sizes-heading-tablet: ( | ||
xsmall: ( | ||
height: tools.get-height(tokens.$heading-xsmall-bold, tablet), | ||
), | ||
small: ( | ||
height: tools.get-height(tokens.$heading-small-bold, tablet), | ||
), | ||
medium: ( | ||
height: tools.get-height(tokens.$heading-medium-bold, tablet), | ||
), | ||
large: ( | ||
height: tools.get-height(tokens.$heading-large-bold, tablet), | ||
), | ||
xlarge: ( | ||
height: tools.get-height(tokens.$heading-xlarge-bold, tablet), | ||
), | ||
); | ||
|
||
$sizes-heading-desktop: ( | ||
xsmall: ( | ||
height: tools.get-height(tokens.$heading-xsmall-bold, desktop), | ||
), | ||
small: ( | ||
height: tools.get-height(tokens.$heading-small-bold, desktop), | ||
), | ||
medium: ( | ||
height: tools.get-height(tokens.$heading-medium-bold, desktop), | ||
), | ||
large: ( | ||
height: tools.get-height(tokens.$heading-large-bold, desktop), | ||
), | ||
xlarge: ( | ||
height: tools.get-height(tokens.$heading-xlarge-bold, desktop), | ||
), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
@use 'sass:map'; | ||
@use '../../tools/breakpoint'; | ||
@use '../../tools/string' as spirit-string; | ||
@use '@tokens' as tokens; | ||
|
||
@mixin generate-sizes($class-name, $sizes) { | ||
@each $size, $variables in $sizes { | ||
.#{$class-name}--#{$size} { | ||
$component-infix: 'skeleton-item'; | ||
|
||
@each $variable-key, $variable-value in $variables { | ||
--#{tokens.$css-variable-prefix}#{$component-infix}-#{$variable-key}: #{$variable-value}; | ||
} | ||
} | ||
} | ||
} | ||
|
||
@function get-height($token, $device) { | ||
@return map.get($token, $device, font-size) * map.get($token, $device, line-height); | ||
} |
Oops, something went wrong.