acederberg.io
  • Home
  • Projects
    • Projects
    • Blog
    • Nvim Configuration
    • Blog and Demo Automation
    • Captura
  • Resume
  • Posts
  • Kaggle
  • Leetcode
  1. Projects
  2. Blog
  3. Components and Filters
  4. Floaty
  5. Demo: Overview
  • Projects
    • Blog
      • About the Blog
      • Subprojects
        • Resume
        • Building A Custom Iconset for Kubernetes
        • Leetcode Problems
      • Technical Details
        • Blog ReadMe
        • Docker and Quarto
        • How is the Blog Deployed?
        • Static Quarto Websites in Kubernetes
      • Components and Filters
        • IFrames
          • Demo
          • Docs: Pandoc Filter
        • Overlay
          • Demo
          • Docs: Pandoc Filter
          • Docs: Javascript
        • Floaty
          • Demo: Overview
          • Demo: Skills
          • Demo: Contacts
          • Demo: Links
          • Demo: Under Construction
          • Docs: Pandoc Filter
          • Docs: Javascript
        • Resume
          • Demo
          • Docs: Pandoc Filter
    • Nvim Configuration
      • Nvim Configuration
      • Gallery
    • Blog and Demo Automation
      • Automation
      • Github Actions in Automation
    • Captura
      • What is Captura?
      • Things I Plan to Build Using Captura

On this page

  • Pure HTML and CSS Floaty
  • Floaties from Pandoc Filters
    • Plain Floaty
    • Images With Background and Hover Effect
    • Cards With Background and Hover Effect
    • Bootstrap Icons in a Single Row
    • Bootstrap Icons in Rows
  1. Projects
  2. Blog
  3. Components and Filters
  4. Floaty
  5. Demo: Overview

Floaty Storybook

Author

Adrian Cederberg

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-containers.

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, */
          transform 0.1s;
        /* 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.
Current Size
Programming Skills
APIs and Databases
Dashboards and UIs
DevOps Engineering
HTML Code
  <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:

Filter Configuration: Minimal Configuration
  - 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

  1. a background with rounded corners,
  2. shadows on icons,
  3. and grow on hover - when hovered, there should be no background.

and cards that

  1. Have content that do not transform when hovered,
  2. Have no shadows.
Quarto
empty
Latex
empty
Pulumi
empty
Github
empty
Git
Filter Configuration: Null Blocks and Custom Classes

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

  1. a background with rounded corners,
  2. and shadows on background,
  3. no hover effects.
Neovim
empty
Python
empty
Nodejs
empty
Mermaidjs
empty
Linode

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

Filter Configuration: Adding Full Cards.

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:

  1. should appear in a single row,
  2. should not have an titles,
  3. use bootstrap icons, shown in red,
  4. include an overlay that opens when cards are clicked.

Python

Javascript

HTML

YAML

PDF

Alarm

Filter Configuration: Bootstrap Mode, Overlays, Disabling Titles and Descriptions, and Single Rows.
  • To enable bootstrap mode, use bootstrap as the value of $.mode.
  • Settings columns to 0 should put everything into a single row unless more than 1000 icons are specified.
  • To disable titles, set $.containers.include_titles to false.
  • To disable descriptions, set $.containers.include_descriptions to false.
  • 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.

Phone
(505) 589 - 6914
Email
adrn.cederberg123@gmail.com
Location
Albuquerque, NM

This can be enabled by setting columns to a negative value.

Filter Configuration: Table Like Layout using Grids.
  - 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
Docs: Javascript
Demo: Skills