SecretoCho
menu

component 09 / 28WORKING

SC Tag Display

type
Code Component
platform
Framer
last update
read time
6–8 min
license
SecretoCho Design
needs JavaScript

demo · runs with JavaScript

fig 00 · live demo, ported from SC_TagDisplay.tsx

Transforms a comma-separated string into responsive “tag pills” with hover states, borders, spacing, and variable-font axis animation (MONO/CASL/CRSV/slnt/wght) for smooth weight/style transitions; no external libs.

A lightweight tag/chip renderer for Framer. Feed it a comma-separated list and it outputs accessible, responsive pills with configurable padding, gap, border, and colors. If your primary typeface ships a “Variable” face (e.g., Recursive Variable), you can animate axes on hover for a subtle, high-end typographic feel.

  • UI
  • Typography
  • Metadata

Main

Overview

Built With
React, CSS, Framer Code Component API
Layout Support
Fully Responsive (auto-wrap)
Orientation
Inline Tag List
Ideal Use Case
Metadata chips, taxonomy tags, blog/category badges, filters

Tags

  • tags
  • chips
  • badges
  • variable fonts
  • hover
  • typography
  • UI
  • pills

Code comment

/** * SC Tag Display v1 * © SecretoCho Design 2025 (https://secretocho.design) * Renders comma-separated tags as styled pills with optional variable-font axes. * Hover states can morph axes (e.g., wght) without extra libraries. * @framerDisableUnlink */

Dependencies

Technologies
None (no external libraries)
Notes
Variable-font animation requires a variable face in your first family (e.g., “Recursive Variable”).

Complexity

Logic Level
Low (string split + style)
Runtime Cost
Very Low (static DOM, simple hover transitions)
Component Size
~2–3 KB (raw TSX)
Notes
Very large tag counts create many DOM nodes—paginate or truncate if needed.

Guide

Instructions

  1. Set Data to a comma-separated list, e.g. UI, Motion, Generative.
  2. Choose Tag BG, Text, Hover BG; adjust Padding, Gap, and Border.
  3. Enable Variable Font and tune Axes (MONO/CASL/CRSV/slnt/wght).
  4. Toggle Hover Axes to morph typography on hover (e.g., wght: 600 → 700).
  5. Bind to CMS by mapping a text field into Data.

Examples / Presets

  • Minimal

    gap=6, padding=4px 8px, border width=0.

  • Bold hover

    base wght=500 → hover wght=700; subtle bg shift.

  • Neutral UI chips

    BG #F3F3F3, text #111, border #DDD, radius=8.

Mechanics

How it Works

  • Parses data by commas → trims → filters empties → maps into <div> pills.
  • Computes a font stack; if Variable Font is on, first family is coerced to its " Variable" face (e.g., Recursive → Recursive Variable).
  • Builds CSS font-variation-settings strings from Axes; if "wght" is present, CSS font-weight is omitted to avoid conflicts.
  • On hover, swaps background and (optionally) variation settings for smooth axis interpolation.

Performance & Tuning

  • Static layout—no RAF, no listeners.
  • Prefer shorter tag lists for mobile; keep Gap small to reduce line wraps.
  • When animating wght, keep deltas modest (e.g., 500→650) for cleaner interpolation.

Compatibility & Limits

  • Works in modern evergreen browsers.
  • Variable-font axes require a variable face installed/loaded; otherwise fallback to classic font-weight.
  • Right-to-left languages: tags render left-to-right by default; wrap in an RTL container if needed.

Quality

Accessibility

  • Tags are static text by default; if interactive, wrap each in a button/link and provide aria-labels.
  • Ensure color contrast for text vs. background (WCAG AA).

Security & Privacy

  • No dangerouslySetInnerHTML; tags are plain strings.
  • No network calls; no data stored.
  • Be mindful not to inject untrusted CSS tokens into data.

Reference

Props

nametypedefaultdescription
datastring“tag 1, tag 2, tag 3”Comma-separated tags
tagBackgroundColorstring(Color)#F3F3F3Default chip background
tagTextColorstring(Color)#000Chip text color
tagHoverBackgroundColorstring(Color)#E0E0E0BG on hover
fontobject(FontValue)—Family/size/weight/spacing/style
border.colorstring(Color)#CCCBorder color
border.widthnumber1Border width (px)
border.radiusnumber6Corner radius (px)
paddingstring“6px 10px”Chip padding
gapnumber8Gap between chips (px)
variableAxesbooleantrueEnable variable-font axes
axesobject(Axes)see defaultsBase axes (MONO/CASL/CRSV/slnt/wght/cssFontWeight)
variableAxesHoverbooleantrueEnable hover axes morph
hoverAxesobject(Axes)see defaultsHover axes

Notes & Tips

  • If your first font family lacks a variable face, disable Variable Font to avoid mismatches.
  • Keep cssFontWeight in Axes as a fallback when the wght axis isn’t applied.
  • For clickable tags, move hover logic into CSS classes and add focus styles.

Troubleshooting / FAQ

Hover doesn’t change weight.

Your font may not expose a wght axis; use cssFontWeight fallback or choose a variable face.

Text looks jumpy on hover.

Reduce axis deltas; try easing via longer transition durations.

Fonts don’t switch to “Variable”.

Ensure the variable font is loaded and named with the “ Variable” suffix in your stack.

Source

Header comment

SC_TagDisplay.tsx · lines 72–76 · the first doc comment (the header, lines 1–3, holds only Framer’s annotations)
/** * Converts first family in the stack to its "Variable" face if not already. * This mirrors your previous component behavior (great for Recursive etc.). * If your font doesn’t ship a " Variable" face, keep variableAxes=false. */

props [REF]

Key excerpt

Each axis is clamped to its range and joined into one font-variation-settings string; hover swaps in a second string.

SC_TagDisplay.tsx · lines 100–117 · tsx
function clamp(n: number, min: number, max: number): number {    return Math.min(max, Math.max(min, n))}function buildVariationString(a?: Axes): string {    if (!a) return ""    const MONO = clamp(a.MONO ?? 1, 0, 1)    const CASL = clamp(a.CASL ?? 0, 0, 1)    const CRSV = clamp(a.CRSV ?? 0.5, 0, 1)    const slnt = clamp(a.slnt ?? 0, -15, 0)    const wght = clamp(a.wght ?? 600, 300, 1000)    // Order is not critical, but we keep it consistent    return `"MONO" ${MONO}, "CASL" ${CASL}, "CRSV" ${CRSV}, "slnt" ${slnt}, "wght" ${wght}`}function hasWghtAxis(variation: string): boolean {    return /"wght"\s*-?\d+/.test(variation)}

Credits

Credits

Component design & implementation by SecretoCho Design.

license
SecretoCho Design

SecretoCho Design 2025

Disclaimer

Proves

Hiring a design engineer?

I’m open to senior design engineer roles: remote from Belgrade, or relocation with visa sponsorship. Write to me, or read the CV first. Client work stays selective, one project at a time.

sc@secretocho.design

read the CV · LinkedIn