Skip to main content

Ribbon

Info:Feedback
89

A corner ribbon: a diagonal banner pinned to a container's corner for a short label, in any tone.

corner banner flag new sale beta featured decoration callout

Live demo

live · @xtyle/astro

Ribbon

Four corners

A ribbon pins to any corner of its container and clips to the edges, so it reads as a folded banner. The container just needs position: relative — the ribbon clips itself, rounded corners included, so it never forces overflow: hidden on your card.

Beta top-left
New top-right
Free bottom-left
Sale bottom-right

Three sizes

New sm
New md
New lg

Solid and soft

Solid accent
Solid success
Solid warn
Solid danger
Solid info
Solid neutral
Soft accent
Soft success
Soft warn
Soft danger
Soft info
Soft neutral

Every tone

tone spans the full roster: the accent variants, the status roles, and the named hues, each resolved off the derived theme.

Accents

accent accent
accent-2 accent-2
accent-3 accent-3
accent-4 accent-4
neutral neutral

Statuses

success success
info info
warn warn
danger danger

Named hues

red red
orange orange
yellow yellow
green green
blue blue
purple purple
brown brown
pink pink
cyan cyan
gray gray
white white
black black

Color escape hatch

color paints the band any raw value past the tone set, for a per-campaign palette. Pair it with textColor so the label stays legible on the custom fill.

Featured --purple
Hot #f59e0b
Mixed color-mix

Ribbon is the diagonal corner banner for a short call-out on a card, a tile, or an image: New, Beta, Sale, Featured. tone skins it across the six semantic roles (plus the accent variants and named hues), variant picks a solid fill or a soft tint, corner chooses which of the four corners it hugs, and size steps the band from sm to lg.

A color / textColor pair is the escape hatch for a band background and text past the tone set. It fills its container as a clipping overlay, so the band's overhang is trimmed to the container's edges and the ribbon reads as a real folded banner rather than a floating strip; the container just needs position: relative (the ribbon clips itself to the container's box, rounded corners included). It ships as a first-class element that self-styles in its own shadow root, so a shadow-DOM consumer with no global stylesheet gets it for free, and the .xtyle-ribbon utility class stays available for global-CSS pages. Ribbon is decoration, not a control: the overlay is pointer-events: none, and its short label is rendered as visible text, so it reads to assistive tech in the container's reading order. Keep the label short; the band is a fixed width per size and a longer label clips.

When to use

How this component composes with the rest of the set.

Reach for Ribbon when a call-out should hug a corner and read as a folded banner (a Sale flash on a product tile); reach for Badge when the label sits inline with content, and Dot when a bare color-coded status is enough.
Give the container position: relative and the ribbon does the rest: it pins to the corner and clips the band's ends to the container's edges, rounded corners included. It never needs the container to set overflow: hidden, so a card with an escaping dropdown or focus ring keeps it.
Keep the label short (a word or two); the band is a fixed width per size, and a longer label is clipped rather than wrapped.
Use soft for a quieter call-out that tints rather than shouts; color + textColor for a per-campaign palette wider than the tone set.

Props

7 props, straight from the manifest.

PropTypeDefaultBindingsDescription
tone FullTone
accent neutral danger success warn info accent-2 accent-3 accent-4 red orange yellow green blue purple brown pink cyan gray white black
accent
html svelte astro
Semantic color role (or named hue) driving the ribbon color.
corner RibbonCorner
top-right top-left bottom-right bottom-left
top-right
html svelte astro
Which corner of the container the ribbon hugs.
size RibbonSize
sm md lg
md
html svelte astro
Band width and type size.
variant RibbonVariant
solid soft
solid
html svelte astro
Fill style: a `solid` tone fill or a `soft` tinted band.
color string
html svelte astro
Escape hatch: paint the band background any raw color, past the tone set. Sets `--rb-bg` and wins over `tone`. Pair it with `textColor` so the label stays legible on a custom fill.
textColor string
html svelte astro
The label color to pair with a custom `color` fill (sets `--rb-fg`). Set both together so a raw-color ribbon keeps its text readable; on a tone it is unneeded.
label string
html svelte astro
The ribbon's text: a short call-out like `New` or `Sale`.

Appearance

Variants

solid

.xtyle-ribbon

A solid tone fill with on-tone text (the default).

soft

.xtyle-ribbon--soft

A soft tinted band with tone-colored text.

accent

.xtyle-ribbon--accent

accent-toned ribbon.

neutral

.xtyle-ribbon--neutral

neutral-toned ribbon.

danger

.xtyle-ribbon--danger

danger-toned ribbon.

success

.xtyle-ribbon--success

success-toned ribbon.

warn

.xtyle-ribbon--warn

warn-toned ribbon.

info

.xtyle-ribbon--info

info-toned ribbon.

accent-2

.xtyle-ribbon--accent-2

accent-2-toned ribbon.

accent-3

.xtyle-ribbon--accent-3

accent-3-toned ribbon.

accent-4

.xtyle-ribbon--accent-4

accent-4-toned ribbon.

red

.xtyle-ribbon--red

red-toned ribbon.

orange

.xtyle-ribbon--orange

orange-toned ribbon.

yellow

.xtyle-ribbon--yellow

yellow-toned ribbon.

green

.xtyle-ribbon--green

green-toned ribbon.

blue

.xtyle-ribbon--blue

blue-toned ribbon.

purple

.xtyle-ribbon--purple

purple-toned ribbon.

brown

.xtyle-ribbon--brown

brown-toned ribbon.

pink

.xtyle-ribbon--pink

pink-toned ribbon.

cyan

.xtyle-ribbon--cyan

cyan-toned ribbon.

gray

.xtyle-ribbon--gray

gray-toned ribbon.

white

.xtyle-ribbon--white

white-toned ribbon.

black

.xtyle-ribbon--black

black-toned ribbon.

Sizes

sm

.xtyle-ribbon--sm

Compact.

md

default
.xtyle-ribbon

Default.

lg

.xtyle-ribbon--lg

Large.

States

top-right

.xtyle-ribbon--top-right

Pinned to the top-right corner (default).

top-left

.xtyle-ribbon--top-left

Pinned to the top-left corner.

bottom-right

.xtyle-ribbon--bottom-right

Pinned to the bottom-right corner.

bottom-left

.xtyle-ribbon--bottom-left

Pinned to the bottom-left corner.

Anatomy

The named parts that make up the component, with their selectors.

ribbon

.xtyle-ribbon

The clip layer: an absolutely-positioned overlay that fills the container and trims the band's overhang.

band

.xtyle-ribbon__band

The diagonal banner itself: the rotated strip carrying the label, filled with the resolved tone.

--accent --accent-fg --weight-semibold --elevation-2

Tokens & coverage

What the component consumes, checked live against what the algorithm produces.

Success:fully covered 89/89 consumed tokens produced default register: 299 tokens

Live coverage check against the xtyle-default register (derive(xtyleDefault, { anchors })coverComponent(manifest, register)). Every token this component consumes must be a key the algorithm produces.

--accent --accent-2 --accent-2-bg --accent-2-fg --accent-2-text --accent-3 --accent-3-bg --accent-3-fg --accent-3-text --accent-4 --accent-4-bg --accent-4-fg --accent-4-text --accent-bg --accent-fg --accent-text --black --black-bg --black-fg --black-text --blue --blue-bg --blue-fg --blue-text --brown --brown-bg --brown-fg --brown-text --cyan --cyan-bg --cyan-fg --cyan-text --danger --danger-bg --danger-fg --danger-text --elevation-2 --gray --gray-bg --gray-fg --gray-text --green --green-bg --green-fg --green-text --info --info-bg --info-fg --info-text --neutral --neutral-bg --neutral-fg --neutral-text --orange --orange-bg --orange-fg --orange-text --pink --pink-bg --pink-fg --pink-text --purple --purple-bg --purple-fg --purple-text --red --red-bg --red-fg --red-text --success --success-bg --success-fg --success-text --text-lg --text-sm --text-xs --warn --warn-bg --warn-fg --warn-text --weight-semibold --white --white-bg --white-fg --white-text --yellow --yellow-bg --yellow-fg --yellow-text

Accessibility

The label is rendered as visible text, so it reads to assistive tech in the container's normal reading order rather than resting on color or position alone.
Ribbon is decoration, not a control: the overlay is pointer-events: none, so it never intercepts clicks meant for the content beneath, and a clickable call-out belongs in a real link or button instead.
The color escape hatch bypasses the derived contrast the tones guarantee, so pair it with textColor to keep the label legible on a custom fill.

Code

Corners, tones, and variants

A ribbon pinned to each corner, in solid and soft fills across the semantic tones.

<div style="position: relative; width: 16rem; height: 9rem; border-radius: var(--radius-lg); background: var(--bg-1);">
	<xtyle-ribbon tone="accent" label="New"></xtyle-ribbon>
	<!-- …card content… -->
</div>

<div style="position: relative;">
	<xtyle-ribbon tone="danger" corner="top-left" label="Sale"></xtyle-ribbon>
</div>

<div style="position: relative;">
	<xtyle-ribbon tone="success" variant="soft" corner="bottom-right" label="Beta"></xtyle-ribbon>
</div>
<script lang="ts">
	import { Ribbon } from "@xtyle/svelte";
</script>

<!-- the container only needs position: relative; the ribbon clips itself -->
<div style="position: relative;">
	<Ribbon tone="accent" label="New" />
	<!-- …card content… -->
</div>

<div style="position: relative;">
	<Ribbon tone="danger" corner="top-left" label="Sale" />
</div>

<div style="position: relative;">
	<Ribbon tone="success" variant="soft" corner="bottom-right" label="Beta" />
</div>
---
import Ribbon from "@xtyle/astro/Ribbon.astro";
---

<!-- the container only needs position: relative; the ribbon clips itself -->
<div style="position: relative;">
	<Ribbon tone="accent" label="New" />
	<!-- …card content… -->
</div>

<div style="position: relative;">
	<Ribbon tone="danger" corner="top-left" label="Sale" />
</div>

<div style="position: relative;">
	<Ribbon tone="success" variant="soft" corner="bottom-right" label="Beta" />
</div>