Floaty Storybook
The motivation was to have listings that could open overlays, be wrapped in links, or just look pretty and take up some space and provide some information.
Floaties are based on the bootstrap grid, implemented by reusing some scss
mixins. This should provide the option to put items in bootstrap cards or floaty-item-container
s.
SCSS
Snippets
For brevity, only the following mixin is provided.
/*-- scss:functions --*/
@function make-shadow($scale, $color: rgba(0, 0, 0, 0.5)) {
$size: $scale * 1px;
$spread: $scale * 2px;
$shadow: drop-shadow($size $size $spread $color);
@return $shadow;
}
@function make-transform($scale) {
@return scale(100% + $scale) translateY(-$scale);
}
/*-- scss:variables --*/
$floaty-shadow-1: make-shadow(5);
$floaty-shadow-2: make-shadow(8);
$floaty-shadow-3: make-shadow(13);
$floaty-shadow-4: make-shadow(21);
$floaty-shadows : (1:$floaty-shadow-1,
2: $floaty-shadow-2,
3: $floaty-shadow-3,
4: $floaty-shadow-4,
;
)
$floaty-transform-1: make-transform(5%);
$floaty-transform-2: make-transform(8%);
$floaty-transform-3: make-transform(13%);
$floaty-transform-4: make-transform(21%);
$floaty-transforms: (
1: $floaty-transform-1,
2: $floaty-transform-2,
3: $floaty-transform-3,
4: $floaty-transform-4,
;
)
$floaty-border-hover: 3px solid var(--bs-primary) !important;
$floaty-border: 3px solid rgba(0, 0, 0, 0) !important;
$progress-heights : (1: 134px,
2: 89px,
3: 55px,
4: 34px,
5: 21px,
6: 13px,
;
)
/*-- scss:uses --*/
@use "glow.scss";
/* ------------------------------------------------------------------------- */
/*-- scss:mixins --*/
@mixin make-floaty-hover($filter-init, $filter-final, $transform) {
.card {
&.hover,
&:hover {
cursor: pointer;
filter: $filter-final;
/* filter: $filter-init; */
/* background: var(--bs-gray-200); */
border-bottom: $floaty-border-hover;
border-radius: 0px;
.card-img-top {
,
i
iconify-icon {background: rgba(0, 0, 0, 0);
transform: $transform;
filter: none;
}
}
}
}
.floaty-item-container {
transition: background 0.1s;
&.hover,
&:hover {
cursor: pointer;
background: var(--bs-gray-200);
}
}
}
// start snippet make-floaty
@mixin make-floaty {
.floaty-container {
@include make-container();
.floaty-row {
@include make-row();
.floaty-item {
@include make-col();
@include make-container();
.floaty-item-container {
@include make-row();
.floaty-item-img {
@include make-col();
display: flex;
/* i, */
/* iconify-icon { */
/* margin: auto; */
/* } */
}
.floaty-item-title,
.floaty-item-text {
padding-left: map-get($spacers, 1);
padding-right: map-get($spacers, 1);
display: flex;
align-items: center;
}
.floaty-item-title {
@include make-col();
}
.floaty-item-text {
@include make-col();
}
.floaty-item-footer {
@include make-col();
flex-grow: 3;
}
}
.card {
transition: filter 0.1s, transform 0.1s, background 0.1s, border 0.1s;
border: none;
.card-img-top {
display: flex;
,
i
iconify-icon {margin: auto;
}
}
.card-body {
text-align: center;
}
.card-footer {
background: var(--bs-body-bg);
}
}
}
}
}
&.floaty-hover {
@include make-floaty-hover(none, none, none);
.card {
&.hover,
&:hover {
background: var(--bs-gray-200);
}
}
}
@for $k from 1 through 4 {
&.floaty-shadow-#{$k} {
iconify-icon {filter: map-get($floaty-shadows, $k);
}
}
}
/* Under construction floaty. */
&.under-construction {
width: 100%;
border: 1px solid rgba(255, 0, 0, 0.2);
border-left: 5px solid var(--bs-red);
border-radius: 5px;
}
}
// end snippet make-floaty
@mixin make-floaty-size($size-key) {
$progress-height: map-get($progress-heights, $size-key);
$font-size: map-get($font-sizes, $size-key);
.card {
$font-size-svg: calc(4 * $font-size);
border-bottom: $floaty-border;
.card-img-top {
font-size: $font-size-svg;
,
i
iconify-icon {min-height: $font-size-svg;
}
}
.card-body {
/* Because putting header elements in comes with too much bagage. */
.card-title {
font-weight: $font-weight-bold;
font-size: $font-size;
}
.card-text {
font-weight: $font-weight-lighter;
}
}
}
.floaty-item-container {
$font-size-svg: calc(1.25 * $font-size);
font-size: $font-size;
,
i
iconify-icon {font-size: $font-size-svg;
iconify-icon {min-height: $font-size-svg;
}
}
}
&.skills {
.card {
.progress {
height: $font-size;
.progress-bar {
overflow: visible;
padding-left: map-get($spacers, 1);
text-align: left;
font-size: $font-size;
}
}
}
.floaty-item-container {
.progress {
height: 100%;
.progress-bar {
overflow: visible;
padding-left: map-get($spacers, 1);
text-align: left;
font-size: $font-size;
}
}
}
}
&.contacts,
&.links {
$font-size-svg: calc(1.25 * $font-size);
.card {
.card-img-top {
,
i
iconify-icon {min-height: $font-size-svg;
font-size: $font-size-svg;
}
}
}
}
}
@mixin make-bg($bg) {
background: $bg;
padding: 10px;
border-radius: $border-radius-lg;
}
/*
NOTE: It is often necessary to add some padding on top to avoid icon exceeding background.
*/
@mixin make-icon-filter($filter-init, $filter-final, $transform) {
&.floaty-hover {
@include make-floaty-hover($filter-init, $filter-final, $transform );
}
.card {
background: rgba(0, 0, 0, 0);
.card-img-top {
,
i
iconify-icon {transition:
/* filter 0.1s, */
0.1s;
transform /* background 1s; */
filter: $filter-init;
}
}
}
}
@mixin make-floaty-icon-bg($bg) {
.card {
,
i
iconify-icon {@include make-bg($bg);
}
}
@for $k from 1 through 4 {
&.floaty-shadow-#{$k} {
/*
.hover,
.card:hover {
background: $bg;
}
*/
@include make-icon-filter(map-get($floaty-shadows, $k), none, map-get($floaty-transforms, $k));
}
}
}
@mixin make-card-filter($filter, $filter-final, $transform) {
.card {
filter: $filter;
margin: auto;
// Remove the pre-existing shadow.
.card-img-top {
,
i
iconify-icon {filter: none;
}
}
}
&.floaty-hover {
.card.hover,
.card:hover {
background: var(--bs-gray-200);
border-bottom: $floaty-border-hover;
border-radius: 0px;
filter: $filter-final;
transform: $transform;
z-index: 1;
}
}
}
@mixin make-floaty-card-bg($bg) {
.card {
@include make-bg($bg);
}
@for $k from 1 through 4 {
&.floaty-shadow-#{$k} {
@include make-card-filter(map-get($floaty-shadows, $k), none, map-get($floaty-transforms, $k), );
}
}
}
/* ------------------------------------------------------------------------- */
/*-- scss:rules --*/
.floaty {
@include make-floaty();
@for $size-key from 1 through 6 {
&.under-construction.under-construction-#{$size-key},
&.floaty-size-#{$size-key} {
@include make-floaty-size($size-key);
}
}
/* Backgrounds for Icons */
&.floaty-bg-dark {
@include make-floaty-icon-bg($black);
}
&.floaty-bg-light {
@include make-floaty-icon-bg($white);
}
&.floaty-bg {
@include make-floaty-icon-bg($body-color);
}
/* Backgrounds for Cards */
&.floaty-card-bg-dark {
@include make-floaty-card-bg($black);
}
&.floaty-card-bg-light {
@include make-floaty-card-bg($white);
}
&.floaty-card-bg {
@include make-floaty-card-bg($body-color);
}
/* Only for text only cards for now.
* Overwrite `margin` for larger or smaller border.
*
*/
&.glow {
.card {
@include glow(10px);
border: none;
.card-body {
border-radius: 7px;
z-index: 1;
background-color: var(--bs-white);
margin: 5px;
}
}
}
}
.floaty-tooltip {
--bs-tooltip-bg: var(--bs-gray-200);
--bs-tooltip-color: var(--bs-black);
--bs-tooltip-opacity: 0.7;
--bs-tooltip-arrow-height: 1rem;
--bs-tooltip-margin: 1rem;
}
Pure HTML
and CSS
Floaty
To start, the following is a Floaty
implemented using pure HTML
and no pandoc filters. This is to demonstrate what the output of the filters should look like.
The following should:
- have icons layed out in a nice
2 X 2
grid, - have no hover effects or backgrounds/shadows behind icons or cards,
- set the cursor to a pointer to suggest clicking.
<div id="floaty-pure" class="floaty">
<div class="floaty-container">
<div class="floaty-row">
<div class="floaty-item">
<div class="card">
<div class="card-img-top">
<iconify-icon
data-key="impl"
aria-label="Programming Skills"
icon="misc:binary"
title="Programming Skills"
></iconify-icon>
</div>
<div class="card-body">
<text class="">Programming Skills</text>
</div>
</div>
</div>
<div class="floaty-item">
<div class="card">
<div class="card-img-top">
<iconify-icon
data-key="api-and-db"
aria-label="APIs and Databases"
icon="misc:api"
title="APIs and Databases"
></iconify-icon>
</div>
<div class="card-body">
<text class="">APIs and Databases</text>
</div>
</div>
</div>
</div>
<div class="floaty-row">
<div class="floaty-item">
<div class="card">
<div class="card-img-top">
<iconify-icon
data-key="uiux"
aria-label="Dashboards and UIs"
icon="misc:dashboard"
title="Dashboards and UIs"
></iconify-icon>
</div>
<div class="card-body">
<text class="">Dashboards and UIs</text>
</div>
</div>
</div>
<div class="floaty-item">
<div class="card">
<div class="card-img-top">
<iconify-icon
data-key="devops"
aria-label="DevOps Engineering"
icon="misc:devops"
title="DevOps Engineering"
></iconify-icon>
</div>
<div class="card-body">
<text class="">DevOps Engineering</text>
</div>
</div>
</div>
</div>
</div>
</div>
Floaties from Pandoc Filters
Pandoc filters make it easy to configure floaties.
Plain Floaty
With minimal configuration, the following is possible:
- identifier: floaty-plain
container:
size: 1
content:
- image:
iconify:
set: misc
name: quarto
key: quarto
title: Quarto
- image:
iconify:
set: devicon
name: latex
key: latex
title: Latex
- image:
iconify:
set: devicon
name: pulumi
key: pulumi
title: Pulumi
Images With Background and Hover Effect
The following should have icons with
- a background with rounded corners,
- shadows on icons,
- and grow on hover - when hovered, there should be no background.
and cards that
- Have content that do not transform when hovered,
- Have no shadows.
Component wide custom classes are controlled through the container
block of the metadata, for instance $.container.classes
will tell the floaty-container
to implement some classes.
Null blocks are invisible, and to specify these use unique strings as items in $.content
. While null
list items will work, they do not work in metadata.yaml
(which is likely a bug of quarto).
- identifier: floaty-bg-grow-shadow
container:
include_titles: true
size: 1
classes:
- floaty-hover
- floaty-shadow-2
- floaty-bg-light
- py-5
classes_items:
- py-3
classes_rows:
- "py-1"
content:
- image:
iconify:
set: misc
name: quarto
key: quarto
title: Quarto
- empty-1
- image:
iconify:
set: devicon
name: latex
key: latex
title: Latex
- empty-2
- image:
iconify:
set: devicon
name: pulumi
key: pulumi
title: Pulumi
- empty-3
- image:
iconify:
set: logos
name: github-icon
key: github
title: Github
- empty-4
- image:
iconify:
set: devicon
name: git
key: git
title: Git
Cards With Background and Hover Effect
The following should have cards with
- a background with rounded corners,
- and shadows on background,
- no hover effects.
Equal spacing and size of cards may be achieved by adding null
list items to pandoc metadata, e.g. the following should create a diagonal in a 3 X 3
grid
To add full cards, just add floaty-card-bg-light
to $.container.classes
.
- identifier: floaty-bg-card-grow-shadow
container:
include_titles: true
size: 3
classes:
- floaty
- floaty-hover
- floaty-shadow-3
- floaty-card-bg-light
- py-5
classes_items:
- px-1
- py-3
content:
- image:
iconify:
set: devicon
name: neovim
key: neovim
title: Neovim
- empty-1
- image:
iconify:
set: devicon
name: python-wordmark
key: python
title: Python
- empty-2
- image:
iconify:
set: devicon
name: nodejs-wordmark
key: nodejs
title: Nodejs
- empty-3
- image:
iconify:
set: misc
name: mermaid
key: mermaid
title: Mermaidjs
description: |
For making some terrific diagrams. - empty-4
- image:
iconify:
set: logos
name: linode
key: linode
title: Linode
description: |
This is where the servers live.
Bootstrap Icons in a Single Row
The following content:
- should appear in a single row,
- should not have an titles,
- use bootstrap icons, shown in red,
- include an overlay that opens when cards are clicked.
- To enable bootstrap mode, use
bootstrap
as the value of$.mode
. - Settings columns to
0
should put everything into a single row unless more than1000
icons are specified. - To disable titles, set
$.containers.include_titles
tofalse
. - To disable descriptions, set
$.containers.include_descriptions
tofalse
. - To add an overlay, put an overlay object into
$.overlay
.
- identifier: floaty-bootstrap
overlay:
classes:
- overlay-blur
identifier: floaty-bootstrap-overlay
colorize:
color: teal
color_text: black
color_text_hover: white
container:
mode: bootstrap
columns: 0
include_titles: false
size: 5
classes:
- floaty
- floaty-hover
- floaty-shadow-2
- floaty-bg-light
- py-2
classes_rows:
- "py-5"
classes_items:
- px-1
classes_cards:
- text-teal
content:
- image:
bootstrap:
name: filetype-py
title: Python
key: py
- image:
bootstrap:
name: filetype-js
title: Javascript
key: js
- image:
bootstrap:
name: filetype-html
title: HTML
key: html
- image:
bootstrap:
name: filetype-yml
title: YAML
key: yaml
- image:
bootstrap:
name: file-earmark-pdf
title: PDF
key: pdf
- image:
bootstrap:
name: alarm
title: Alaram
key: alarm
Bootstrap Icons in Rows
Items in their own rows using a bootstrap grid.
This can be enabled by setting columns
to a negative value.
- identifier: floaty-rows
container:
size: 6
mode: bootstrap
classes:
- floaty-hover
columns: -1
include_titles: true
include_descriptions: true
content:
- title: Phone
description: (505) 589 - 6914
key: phone
image:
tex:
font_awesome: faPhone
bootstrap:
name: phone
- title: Email
description: adrn.cederberg123@gmail.com
key: email
image:
tex:
font_awesome: faEnvelope
bootstrap:
name: envelope
- title: Location
description: Albuquerque, NM
key: location
image:
tex:
font_awesome: faLocationArrow
bootstrap:
name: compass