component 09 / 28WORKING
SC Tag Display
- type
- Code Component
- platform
- Framer
- last update
- read time
- 6–8 min
- license
- SecretoCho Design
demo · runs with JavaScript
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
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
- Set Data to a comma-separated list, e.g. UI, Motion, Generative.
- Choose Tag BG, Text, Hover BG; adjust Padding, Gap, and Border.
- Enable Variable Font and tune Axes (MONO/CASL/CRSV/slnt/wght).
- Toggle Hover Axes to morph typography on hover (e.g., wght: 600 → 700).
- 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
| name | type | default | description |
|---|---|---|---|
data | string | “tag 1, tag 2, tag 3” | Comma-separated tags |
tagBackgroundColor | string(Color) | #F3F3F3 | Default chip background |
tagTextColor | string(Color) | #000 | Chip text color |
tagHoverBackgroundColor | string(Color) | #E0E0E0 | BG on hover |
font | object(FontValue) | — | Family/size/weight/spacing/style |
border.color | string(Color) | #CCC | Border color |
border.width | number | 1 | Border width (px) |
border.radius | number | 6 | Corner radius (px) |
padding | string | “6px 10px” | Chip padding |
gap | number | 8 | Gap between chips (px) |
variableAxes | boolean | true | Enable variable-font axes |
axes | object(Axes) | see defaults | Base axes (MONO/CASL/CRSV/slnt/wght/cssFontWeight) |
variableAxesHover | boolean | true | Enable hover axes morph |
hoverAxes | object(Axes) | see defaults | Hover 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
/** * 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. */Key excerpt
Each axis is clamped to its range and joined into one font-variation-settings string; hover swaps in a second string.
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
Provided “as is.” Validate accessibility, licensing for fonts, and performance in your project before shipping.
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