component PreferenceSwitcher { outputs { theme(payload: { sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[]) color(payload: { sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[]) language(payload: { sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[]) } props { size: string = "default" color: string = "primary" themeLabel: string = "Theme" colorLabel: string = "Accent color" languageLabel: string = "Language" languages = [ {"label": "English", "shortLabel": "EN", "value": "en"}, {"label": "हिन्दी", "shortLabel": "हि", "value": "hi"}, {"label": "मराठी", "shortLabel": "म", "value": "mr"} ] colors = [ {"label": "Blue", "value": "blue", "hex": "#2563eb"}, {"label": "Cyan", "value": "cyan", "hex": "#0891b2"}, {"label": "Emerald", "value": "emerald", "hex": "#059669"}, {"label": "Violet", "value": "violet", "hex": "#7c3aed"}, {"label": "Rose", "value": "rose", "hex": "#e11d48"}, {"label": "Amber", "value": "amber", "hex": "#d97706"} ] compact: boolean = true class: string = "" } functions { client function choose(type, value) { if (type === "color") window.wrnAccent?.set(value) if (type === "theme") window.wrnTheme?.set(value) output[type]({ value: value }) } } view {
{#if !compact}{themeLabel}{/if}
{themeLabel}
{#if !compact}{colorLabel}{/if}
{colorLabel}
{#each colors as item} {/each}
{#if !compact}{languageLabel}{/if}
{languageLabel} {#each languages as item} {/each}
} style { /* Portal display, accent, and language preferences */ .wrn-preferences { display: inline-flex; align-items: center; gap: 0.25rem; } .wrn-preferences__menu { position: relative; } .wrn-preferences__menu > summary { display: inline-flex; min-width: 2.25rem; min-height: 2.25rem; padding: 0.45rem 0.6rem; align-items: center; justify-content: center; gap: 0.4rem; border: 1px solid transparent; border-radius: 0.6rem; color: var(--wrn-color-muted); cursor: pointer; list-style: none; } .wrn-preferences__menu > summary::-webkit-details-marker { display: none; } .wrn-preferences__menu > summary:hover, .wrn-preferences__menu[open] > summary { color: var(--wrn-color-text); border-color: var(--wrn-color-border); background: var(--wrn-color-surface); } .wrn-preferences__menu > summary > span:first-child { width: 1rem; height: 1rem; } .wrn-preferences__current-language { min-width: 1.25rem; color: var(--wrn-color-text); font-size: 0.625rem; font-weight: 650; letter-spacing: 0.02em; } .wrn-preferences__panel { position: absolute; z-index: 80; top: calc(100% + 0.5rem); right: 0; display: grid; width: max-content; min-width: 11rem; max-width: min(22rem, calc(100vw - 2rem)); max-height: min(28rem, calc(100dvh - 2rem)); overflow-y: auto; padding: 0.75rem; gap: 0.6rem; border: 1px solid var(--wrn-color-border); border-radius: 0.8rem; color: var(--wrn-color-text); background: var(--wrn-color-surface); box-shadow: var(--wrn-shadow-lg, 0 18px 48px rgb(0 0 0 / 0.18)); animation: wrn-component-enter 160ms ease both; } .wrn-preferences__panel > strong { padding-inline: 0.25rem; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; } .wrn-preferences__options { display: grid; grid-template-columns: 1fr 1fr; gap: 0.4rem; } .wrn-preferences__panel button { display: inline-flex; min-height: 2.25rem; padding: 0.5rem 0.65rem; align-items: center; gap: 0.5rem; border-radius: 0.55rem; color: var(--wrn-color-text); background: var(--wrn-color-surface-2); font-size: 0.75rem; font-weight: 500; } .wrn-preferences__panel button:hover { outline: 2px solid color-mix(in srgb, var(--wrn-color-primary) 40%, transparent); } .wrn-preferences__panel button[aria-pressed="true"] { color: var(--wrn-color-primary); background: color-mix(in srgb, var(--wrn-color-primary) 12%, var(--wrn-color-surface)); outline: 1px solid color-mix(in srgb, var(--wrn-color-primary) 55%, transparent); } .wrn-preferences__swatches { display: grid; grid-template-columns: repeat(3, 2rem); gap: 0.5rem; } .wrn-preferences__swatches button { width: 2rem; min-height: 2rem; padding: 0; border: 3px solid var(--wrn-color-surface); border-radius: 999px; background: var(--wrn-preference-swatch); box-shadow: 0 0 0 1px var(--wrn-color-border); } .wrn-preferences__swatches button[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--wrn-color-surface), 0 0 0 4px var(--wrn-color-primary); } .wrn-preferences__panel--language button { width: 100%; background: transparent; } .wrn-preferences__panel--language button span { display: grid; width: 1.65rem; height: 1.65rem; place-items: center; border-radius: 0.45rem; background: var(--wrn-color-surface-2); font-size: 0.65rem; } .wrn-preferences__panel--language button[aria-pressed="true"]::after { width: 0.9rem; height: 0.9rem; margin-left: auto; content: ""; background: currentColor; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m5 12 4 4L19 6'/%3E%3C/svg%3E") center / contain no-repeat; } @media (max-width: 640px) { .wrn-preferences__panel { position: fixed; top: auto; right: 1rem; bottom: 1rem; left: 1rem; width: auto; } } /* 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; } } }