component Badge { outputs { dismiss(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object }) } props { label: string = "Badge" size: string = "md" color: string = "primary" variant: string = "solid" shape: string = "pill" class: string = "" icon: string = "" iconPosition: string = "start" dot: boolean = false dotOnly: boolean = false dotLabel: string = "Status" animated: boolean = false avatarSrc: string = "" avatarAlt: string = "" dismissible: boolean = false dismissLabel: string = "Remove badge" truncate: boolean = false maxWidth: string = "12rem" anchorLabel: string = "" anchorIcon: string = "" placement: string = "inline" anchorLabelText: string = "Badge anchor" } state visible: boolean = true functions { // output.dismiss reaches a parent @dismiss binding; a raw dispatchEvent on // the root does not. The runtime registers parent handlers in a registry // that only the output proxy consults, so the CustomEvent this used to // build bubbled past every binding and was never seen by anyone. client function dismissBadge() { visible = false output.dismiss({ component: "Badge", label: label }) } } view { {#if anchorLabel || anchorIcon} {/if} {#if animated} {/if} {#if avatarSrc} {avatarAlt} {/if} {#if dot || dotOnly} {/if} {#if icon && iconPosition === "start"} {/if} {#if !dotOnly} {label} {/if} {#if icon && iconPosition === "end"} {/if} {#if dismissible} {/if} } style { @keyframes wrn-badge-ping { 75%, 100% { opacity: 0; transform: scale(1.45); } } /* --- Badge --------------------------------------------------------------- */ .wrn-next--badge-root { position: relative; display: inline-flex; width: fit-content; max-width: 100%; vertical-align: middle; } .wrn-next__badge { --wrn-badge-color: var(--wrn-color-primary); position: relative; isolation: isolate; display: inline-flex; min-width: 0; min-height: 1.65rem; align-items: center; justify-content: center; gap: 0.35rem; max-width: var(--wrn-badge-max-width); padding: 0.25rem 0.6rem; color: white; border: 1px solid var(--wrn-badge-color); border-radius: 999px; background: var(--wrn-badge-color); box-shadow: 0 4px 12px color-mix(in srgb, var(--wrn-badge-color) 18%, transparent); font-size: 0.75rem; font-weight: 750; line-height: 1; white-space: nowrap; } .wrn-next__badge[data-size="xs"] { min-height: 1.25rem; padding: 0.15rem 0.4rem; font-size: 0.625rem; } .wrn-next__badge[data-size="sm"] { min-height: 1.45rem; padding: 0.2rem 0.5rem; font-size: 0.6875rem; } .wrn-next__badge[data-size="lg"] { min-height: 2rem; padding: 0.35rem 0.75rem; font-size: 0.825rem; } .wrn-next__badge[data-color="secondary"] { --wrn-badge-color: #737373; } .wrn-next__badge[data-color="success"] { --wrn-badge-color: #0f9f8f; } .wrn-next__badge[data-color="info"] { --wrn-badge-color: #2563eb; } .wrn-next__badge[data-color="danger"] { --wrn-badge-color: #ef3340; } .wrn-next__badge[data-color="warning"] { --wrn-badge-color: #eab308; } .wrn-next__badge[data-color="dark"] { --wrn-badge-color: #27272a; } .wrn-next__badge[data-color="light"] { --wrn-badge-color: #f4f4f5; } .wrn-next__badge[data-color="warning"][data-variant="solid"], .wrn-next__badge[data-color="light"][data-variant="solid"] { color: #18181b; } .wrn-next__badge[data-variant="soft"] { color: var(--wrn-badge-color); border-color: transparent; background: color-mix(in srgb, var(--wrn-badge-color) 15%, var(--wrn-color-surface)); box-shadow: none; } .wrn-next__badge[data-variant="outline"] { color: var(--wrn-badge-color); background: transparent; box-shadow: none; } .wrn-next__badge[data-variant="white"] { color: var(--wrn-color-text); border-color: var(--wrn-color-border); background: var(--wrn-color-surface); box-shadow: 0 4px 12px rgb(0 0 0 / 0.12); } .wrn-next__badge[data-shape="rounded"] { border-radius: 0.4rem; } .wrn-next__badge[data-shape="square"] { border-radius: 0; } .wrn-next__badge-label { min-width: 0; } .wrn-next__badge-label--truncate { overflow: hidden; text-overflow: ellipsis; } .wrn-next__badge-dot { width: 0.42rem; height: 0.42rem; flex: none; border-radius: 999px; background: currentColor; } .wrn-next__badge:has(.wrn-next__badge-dot):not(:has(.wrn-next__badge-label)) { width: 0.7rem; min-width: 0.7rem; height: 0.7rem; min-height: 0.7rem; padding: 0; border: 2px solid var(--wrn-color-bg); } .wrn-next__badge:has(.wrn-next__badge-dot):not(:has(.wrn-next__badge-label)) .wrn-next__badge-dot { width: 100%; height: 100%; } .wrn-next__badge-icon { width: 0.9rem; height: 0.9rem; flex: none; } .wrn-next__badge-avatar { width: 1.25rem; height: 1.25rem; margin-left: -0.35rem; object-fit: cover; border: 1px solid color-mix(in srgb, currentColor 35%, transparent); border-radius: 999px; } .wrn-next__badge-dismiss { display: grid; width: 1.15rem; height: 1.15rem; margin-right: -0.3rem; padding: 0; place-items: center; color: currentColor; border: 0; border-radius: 999px; background: color-mix(in srgb, currentColor 12%, transparent); cursor: pointer; } .wrn-next__badge-dismiss:hover { background: color-mix(in srgb, currentColor 22%, transparent); } .wrn-next__badge-dismiss:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; } .wrn-next__badge-dismiss span { width: 0.75rem; height: 0.75rem; } .wrn-next__badge-anchor { display: inline-flex; min-height: 2.75rem; align-items: center; justify-content: center; gap: 0.5rem; padding: 0.65rem 0.9rem; color: var(--wrn-color-text); border: 1px solid var(--wrn-color-border); border-radius: 0.5rem; background: var(--wrn-color-surface); font: inherit; font-size: 0.875rem; font-weight: 700; } .wrn-next__badge-anchor > [class*="icon-"] { width: 1rem; height: 1rem; } .wrn-next--badge-anchored[data-placement="inline"] { align-items: center; } .wrn-next--badge-anchored[data-placement="inline"] .wrn-next__badge { margin-left: -0.55rem; } .wrn-next--badge-anchored[data-placement="top-right"] .wrn-next__badge { position: absolute; top: -0.55rem; right: -0.75rem; z-index: 2; } .wrn-next__badge-ping { position: absolute; z-index: -1; inset: -0.25rem; border-radius: inherit; background: var(--wrn-badge-color); opacity: 0.5; animation: wrn-badge-ping 1.4s cubic-bezier(0, 0, 0.2, 1) infinite; } @media (prefers-reduced-motion: reduce) { .wrn-next__badge-ping { animation: none; } } /* Shared component foundation. */ .wrn-component { --wrn-component-color: var(--wrn-color-primary); --wrn-component-scale: 1; margin: 0; color: var(--wrn-color-text); font-family: var(--wrn-font-sans, inherit); } .wrn-component--color-primary { --wrn-component-color: var(--wrn-color-primary); } .wrn-component--color-secondary { --wrn-component-color: var(--wrn-color-secondary); } .wrn-component--color-success { --wrn-component-color: var(--wrn-color-success); } .wrn-component--color-warning { --wrn-component-color: var(--wrn-color-warning); } .wrn-component--color-danger { --wrn-component-color: var(--wrn-color-danger); } .wrn-component--color-info { --wrn-component-color: var(--wrn-color-info); } .wrn-component--size-xs { --wrn-component-scale: 0.78; } .wrn-component--size-sm { --wrn-component-scale: 0.88; } .wrn-component--size-default, .wrn-component--size-md { --wrn-component-scale: 1; } .wrn-component--size-lg { --wrn-component-scale: 1.14; } .wrn-component--size-xl { --wrn-component-scale: 1.28; } .wrn-component:not(.wrn-btn) { font-size: calc(1em * var(--wrn-component-scale)); } .wrn-component :is(a, button, input, select, textarea):focus-visible { outline-color: var(--wrn-component-color); } .wrn-component p { margin: 0; color: var(--wrn-color-muted); line-height: 1.6; } } }