or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

animation-timing.mdborder-utilities.mdbrowser-support.mdcolor-functions.mdform-input-selectors.mdindex.mdlayout-positioning.mdmathematical-utilities.mdshapes-graphics.mdtext-content.mdtypography.md
tile.json

shapes-graphics.mddocs/

Shapes and Graphics

Utilities for creating CSS shapes and graphic elements using pure CSS techniques, particularly the triangle mixin for creating directional arrows and decorative elements.

Capabilities

Triangle Mixin

Generates CSS triangles pointing in specified directions using border manipulation techniques.

/**
 * Generates a triangle pointing in a specified direction
 * @param $direction - Direction: "up", "up-right", "right", "down-right", "down", "down-left", "left", "up-left"
 * @param $width - Width of the triangle (with unit)
 * @param $height - Height of the triangle (with unit)
 * @param $color - Color of the triangle
 */
@mixin triangle($direction, $width, $height, $color);

Usage Examples:

.arrow-up {
  &::before {
    @include triangle("up", 2rem, 1rem, #3498db);
    content: "";
  }
}
// Result:
// .arrow-up::before {
//   border-style: solid;
//   height: 0;
//   width: 0;
//   border-color: transparent transparent #3498db;
//   border-width: 0 1rem 1rem;
//   content: "";
// }

.dropdown-arrow {
  &::after {
    @include triangle("down", 10px, 6px, currentColor);
    content: "";
    margin-left: 8px;
  }
}

.tooltip-pointer {
  &::before {
    @include triangle("left", 8px, 8px, #2c3e50);
    content: "";
    position: absolute;
    right: -8px;
    top: 50%;
    transform: translateY(-50%);
  }
}

Triangle Directions

The triangle mixin supports eight directional orientations:

Basic Directions

// Upward pointing triangle
.triangle-up {
  @include triangle("up", 20px, 15px, #e74c3c);
}

// Downward pointing triangle  
.triangle-down {
  @include triangle("down", 20px, 15px, #27ae60);
}

// Left pointing triangle
.triangle-left {
  @include triangle("left", 15px, 20px, #3498db);
}

// Right pointing triangle
.triangle-right {
  @include triangle("right", 15px, 20px, #9b59b6);
}

Diagonal Directions

// Upper-right diagonal
.triangle-up-right {
  @include triangle("up-right", 20px, 20px, #f39c12);
}

// Lower-right diagonal
.triangle-down-right {
  @include triangle("down-right", 20px, 20px, #e67e22);
}

// Lower-left diagonal
.triangle-down-left {
  @include triangle("down-left", 20px, 20px, #16a085);
}

// Upper-left diagonal
.triangle-up-left {
  @include triangle("up-left", 20px, 20px, #8e44ad);
}

Common UI Patterns

Dropdown Indicators

.dropdown-trigger {
  position: relative;
  padding-right: 24px;
  
  &::after {
    @include triangle("down", 8px, 4px, currentColor);
    content: "";
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    transition: transform 0.2s ease;
  }
  
  &.open::after {
    transform: translateY(-50%) rotate(180deg);
  }
}

.select-arrow {
  position: relative;
  
  &::after {
    @include triangle("down", 12px, 6px, #7f8c8d);
    content: "";
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
  }
}

Breadcrumb Separators

.breadcrumb {
  display: flex;
  align-items: center;
  
  .item {
    &:not(:last-child)::after {
      @include triangle("right", 6px, 10px, #bdc3c7);
      content: "";
      margin: 0 8px;
    }
  }
}

.breadcrumb-chevron {
  .separator {
    @include triangle("right", 8px, 12px, rgba(0, 0, 0, 0.3));
    margin: 0 12px;
  }
}

Tooltip Pointers

.tooltip {
  position: relative;
  
  // Top tooltip
  &.tooltip-top::before {
    @include triangle("down", 12px, 6px, #2c3e50);
    content: "";
    position: absolute;
    bottom: -6px;
    left: 50%;
    transform: translateX(-50%);
  }
  
  // Bottom tooltip
  &.tooltip-bottom::before {
    @include triangle("up", 12px, 6px, #2c3e50);
    content: "";
    position: absolute;
    top: -6px;
    left: 50%;
    transform: translateX(-50%);
  }
  
  // Left tooltip
  &.tooltip-left::before {
    @include triangle("right", 6px, 12px, #2c3e50);
    content: "";
    position: absolute;
    right: -6px;
    top: 50%;
    transform: translateY(-50%);
  }
  
  // Right tooltip
  &.tooltip-right::before {
    @include triangle("left", 6px, 12px, #2c3e50);
    content: "";
    position: absolute;
    left: -6px;
    top: 50%;
    transform: translateY(-50%);
  }
}

Speech Bubbles

.speech-bubble {
  position: relative;
  background: #3498db;
  color: white;
  padding: 12px 16px;
  border-radius: 8px;
  
  // Bottom-left pointer
  &.bottom-left::after {
    @include triangle("down-left", 16px, 16px, #3498db);
    content: "";
    position: absolute;
    bottom: -16px;
    left: 20px;
  }
  
  // Bottom-right pointer
  &.bottom-right::after {
    @include triangle("down-right", 16px, 16px, #3498db);
    content: "";
    position: absolute;
    bottom: -16px;
    right: 20px;
  }
}

Progress Indicators

.step-indicator {
  display: flex;
  align-items: center;
  
  .step {
    flex: 1;
    position: relative;
    background: #ecf0f1;
    height: 4px;
    
    &.completed {
      background: #27ae60;
    }
    
    &:not(:last-child)::after {
      @include triangle("right", 16px, 20px, #ecf0f1);
      content: "";
      position: absolute;
      right: -8px;
      top: 50%;
      transform: translateY(-50%);
      z-index: 1;
    }
    
    &.completed:not(:last-child)::after {
      @include triangle("right", 16px, 20px, #27ae60);
    }
  }
}

Decorative Elements

.banner {
  position: relative;
  background: #e74c3c;
  color: white;
  padding: 20px;
  
  // Decorative corner fold
  &::after {
    @include triangle("down-right", 20px, 20px, rgba(0, 0, 0, 0.2));
    content: "";
    position: absolute;
    top: 0;
    right: 0;
  }
}

.ribbon {
  position: relative;
  background: #f39c12;
  color: white;
  padding: 8px 24px;
  
  // Ribbon tails
  &::before,
  &::after {
    content: "";
    position: absolute;
    top: 100%;
  }
  
  &::before {
    @include triangle("down-left", 12px, 8px, darken(#f39c12, 20%));
    left: 0;
  }
  
  &::after {
    @include triangle("down-right", 12px, 8px, darken(#f39c12, 20%));
    right: 0;
  }
}

Error Handling

The triangle mixin includes comprehensive validation:

// Invalid direction
.invalid-triangle {
  @include triangle("invalid-direction", 10px, 10px, red);
  // Error: Direction must be `up`, `up-right`, `right`, `down-right`, `down`, `down-left`, `left` or `up-left`.
}

// Invalid color
.invalid-color {
  @include triangle("up", 10px, 10px, "not-a-color");
  // Error: `"not-a-color"` is not a valid color for the `$color` argument in the `triangle` mixin.
}