From 339554cf4535343e502d3199c7873a058661d742 Mon Sep 17 00:00:00 2001 From: SandObserver <260779319+SandObserver@users.noreply.github.com> Date: Tue, 20 Oct 2026 17:45:43 -0400 Subject: [PATCH] Feature: choose the icon colour style from a drop-down Replace the icon colour's Dark, White, Auto and Clear swatches with a Style drop-down that also offers Color. The colour swatches and HSB sliders show only under Color, and choosing Color again restores the colour a style replaced, or Blue the first time. Shorten the Auto label to one word. Group the badge and wallpaper swatches at the row end with one gap and one size, and drop the styles for the removed swatches. --- e2e/control-names.spec.js | 29 +++++++++------ e2e/reflow.spec.js | 6 ++-- ui/admin/index.html | 4 +-- ui/css/admin.css | 21 ++--------- ui/i18n/de.json | 3 +- ui/i18n/en.json | 3 +- ui/i18n/es.json | 3 +- ui/i18n/fa.json | 3 +- ui/i18n/fr.json | 3 +- ui/i18n/zh-Hans.json | 3 +- ui/js/admin-app-form.js | 2 +- ui/js/admin-color-control.js | 64 ++++++++++++++++++++++++++++------ ui/js/admin-list.js | 2 +- ui/js/admin-settings.js | 2 +- ui/js/admin-widget-form.js | 2 +- ui/js/admin.js | 8 ++--- ui/js/widget-config-form.js | 2 +- ui/test/i18n-coverage.test.mjs | 2 ++ 18 files changed, 103 insertions(+), 59 deletions(-) diff --git a/e2e/control-names.spec.js b/e2e/control-names.spec.js index d331cb54..28ac8fa7 100644 --- a/e2e/control-names.spec.js +++ b/e2e/control-names.spec.js @@ -88,24 +88,33 @@ test('Settings group titles are headings', async ({ page }) => { await expect(page.locator('#sec-general').getByRole('heading', { level: 2, name: 'Sprache' })).toBeVisible(); }); -test('the selected colour swatch is announced as pressed', async ({ page }) => { +test('the icon colour Style is a named drop-down', async ({ page }) => { await openDashboardList(page); await rowByName(page, 'Alpha') .getByRole('button', { name: /^Bearbeiten/ }) .click(); + const style = page.getByRole('button', { name: /^Stil/ }); + await expect(style).toHaveAccessibleName('Stil Dunkel'); + const pick = async v => { + await style.click(); + await page.locator(`#icon-col-style-list [data-val="${v}"]`).click(); + }; const swatch = v => page.locator(`#icon-color-slot .cc-swatch[data-v="${v}"]`); - await expect(swatch('dark')).toHaveAttribute('aria-pressed', 'true'); - await expect(swatch('light')).toHaveAttribute('aria-pressed', 'false'); - await swatch('light').click(); - await expect(swatch('light')).toHaveAttribute('aria-pressed', 'true'); - await expect(swatch('dark')).toHaveAttribute('aria-pressed', 'false'); - await swatch('custom').click(); - await expect(swatch('custom')).toHaveAttribute('aria-expanded', 'true'); - await expect(swatch('custom')).toHaveAttribute('aria-pressed', 'true'); + await expect(swatch('red')).toBeHidden(); + await pick('color'); + await expect(style).toHaveAccessibleName('Stil Farbe'); + await expect(swatch('blue')).toHaveAttribute('aria-pressed', 'true'); await swatch('red').click(); await expect(swatch('red')).toHaveAttribute('aria-pressed', 'true'); + await expect(swatch('blue')).toHaveAttribute('aria-pressed', 'false'); await expect(swatch('custom')).toHaveAttribute('aria-pressed', 'false'); - await expect(swatch('custom')).toHaveAttribute('aria-expanded', 'true'); + await pick('light'); + await expect(swatch('red')).toBeHidden(); + await pick('color'); + await expect(swatch('red')).toHaveAttribute('aria-pressed', 'true'); + await swatch('custom').click(); + await expect(swatch('custom')).toHaveAttribute('aria-pressed', 'true'); + await expect(swatch('red')).toHaveAttribute('aria-pressed', 'false'); }); test('the Test result is announced', async ({ page }) => { diff --git a/e2e/reflow.spec.js b/e2e/reflow.spec.js index be08028b..b24b4f5a 100644 --- a/e2e/reflow.spec.js +++ b/e2e/reflow.spec.js @@ -71,7 +71,8 @@ test.describe('on a touch screen', () => { await page.setViewportSize({ width: 320, height: 700 }); await page.goto('/admin/#dashboard'); await page.locator('#al [data-act="edit"]').first().click(); - await page.locator('#icon-color-slot .cc-swatch[data-v="custom"]').click(); + await page.locator('#icon-col-style-btn').click(); + await page.locator('#icon-col-style-list [data-val="color"]').click(); const picker = page.locator('#icon-color-slot'); await picker.locator('.cc-hues').waitFor({ state: 'visible' }); await animationsDone(page); @@ -104,7 +105,8 @@ test('the colour sliders share one length', async ({ page, request }) => { await page.setViewportSize({ width: 1280, height: 900 }); await openDashboardList(page); await page.locator('#al [data-act="edit"]').first().click(); - await page.locator('#icon-color-slot .cc-swatch[data-v="custom"]').click(); + await page.locator('#icon-col-style-btn').click(); + await page.locator('#icon-col-style-list [data-val="color"]').click(); const sliders = page.locator('#icon-color-slot .hsb-range'); await expect(sliders).toHaveCount(3); await animationsDone(page); diff --git a/ui/admin/index.html b/ui/admin/index.html index cc9e837a..ea8cb997 100644 --- a/ui/admin/index.html +++ b/ui/admin/index.html @@ -11,7 +11,7 @@ - + @@ -302,6 +302,6 @@

General

- + diff --git a/ui/css/admin.css b/ui/css/admin.css index 08b2ac4d..3a3a8870 100644 --- a/ui/css/admin.css +++ b/ui/css/admin.css @@ -1,10 +1,5 @@ /* admin.css v33 */ :root{ - /* The two plate previews in the colour control. Fixed in both themes: each - shows the plate it selects, not the theme the page is in. */ - --cc-plate-dark:#1C1C1E; - --cc-plate-light:#F2F2F7; - /* Surfaces and borders, darkest first, from the system greys. */ --bg-outer:var(--sy-gray6); --sb:#141517; @@ -353,9 +348,7 @@ button.rnm{font-family:inherit;color:inherit;background:none;border:0;padding:0; /* ── Color control: swatch row + HSB sliders + code (PSD Icon/Label/Activity) ── */ .cc-row{padding-top:13px;padding-bottom:13px} -/* Grid, not a wrapping flex row. space-between spreads whatever wraps to the - far edges. */ -.cc-sw{display:grid;grid-template-columns:repeat(auto-fit,26px);gap:10px;margin-inline-start:auto;flex:2;max-width:none;justify-content:space-between} +.cc-sw{display:flex;flex-wrap:wrap;gap:10px;justify-content:flex-end;margin-inline-start:auto;flex:0 1 auto} .cc-swatch{width:26px;height:26px;border-radius:50%;cursor:pointer;border:none;padding:0;outline:2px solid transparent;outline-offset:2px;transition:outline-color var(--t);flex-shrink:0} .cc-swatch.on{outline-color:var(--swatch-ring)} @media (forced-colors: active){ @@ -424,12 +417,6 @@ input::placeholder,textarea::placeholder{color:var(--dm-strong)} .dash-load-fail{padding:32px;text-align:center;color:var(--dm);font-size:14px} .dash-load-fail .retry-btn{padding:8px 20px;border-radius:16px;background:var(--btn-fill);border:0;color:var(--tx);cursor:pointer;font-size:14px;font-family:inherit} .wcf-add-label{color:var(--ac2)} -.cc-kw-auto{background:linear-gradient(135deg,var(--cc-plate-dark) 50%,var(--cc-plate-light) 50%);box-shadow:inset 0 0 0 .5px var(--separator)} -.cc-kw-light,.cc-kw-dark{box-shadow:inset 0 0 0 1px var(--separator)} -.cc-kw-clear{background:repeating-conic-gradient(var(--sy-gray2) 0 25%,var(--sy-gray4) 0 50%) 50% 50%/8px 8px;box-shadow:inset 0 0 0 1px var(--separator)} -html[data-theme="light"] .cc-kw-clear{background-image:repeating-conic-gradient(var(--sy-gray4) 0 25%,#fff 0 50%)} -.cc-hues .cc-sw{grid-template-columns:repeat(auto-fill,22px);gap:8px;justify-content:end} -.cc-hues .cc-swatch{width:22px;height:22px} /* App form: icon source row, poll, value list */ .icon-src-row{gap:12px} .icon-prev{box-shadow:inset 0 0 0 1px var(--separator);width:34px;height:34px;border-radius:9px;display:flex;align-items:center;justify-content:center;color:var(--on-tint);font-size:13px;font-weight:600;flex-shrink:0;overflow:hidden} @@ -736,10 +723,6 @@ a:focus-visible,button:focus-visible,[role="button"]:focus-visible{outline:2px s .adm-range { height:44px; padding-block:19px; background-clip:content-box; border-radius:3px / 22px; } .hsb-range { height:44px; padding-block:19px; background-clip:content-box; border-radius:3px / 22px; } .cc-swatch { width:34px; height:34px; } - .cc-sw { grid-template-columns:repeat(auto-fit,34px); } - .cc-kw-clear { background-size:10px 10px; } - .cc-hues .cc-sw { grid-template-columns:repeat(7,34px); } - .cc-hues .cc-swatch { width:34px; height:34px; } } /* ─────────────── Mobile: phone settings + bottom tab bar ─────────────── @@ -758,7 +741,7 @@ html.is-mobile .sec{padding-block:16px calc(132px + env(safe-area-inset-bottom)) html.is-mobile .sec-title{font-size:var(--fs-large-title);line-height:var(--lh-large-title);letter-spacing:var(--tr-large-title)} html.is-mobile .cc-row{flex-wrap:wrap;row-gap:10px} html.is-mobile .cc-row .rl{flex:0 0 100%} -html.is-mobile .cc-sw{flex:1 1 100%;grid-template-columns:repeat(7,auto);column-gap:0;justify-content:space-between} +html.is-mobile .cc-sw{display:grid;flex:1 1 100%;grid-template-columns:repeat(7,auto);column-gap:0;justify-content:space-between} html.is-mobile .sec-hdr{padding:10px 0 10px;flex-wrap:wrap;row-gap:6px} html.is-mobile .sec-title{order:1;flex-basis:100%;min-width:0;overflow-wrap:break-word} html.is-mobile .sec-hdr-actions{margin-inline-start:auto} diff --git a/ui/i18n/de.json b/ui/i18n/de.json index 33af4c79..864451ce 100644 --- a/ui/i18n/de.json +++ b/ui/i18n/de.json @@ -538,9 +538,10 @@ "hidden": "Ausgeblendet" }, "color": { + "style": "Stil", "dark": "Dunkel", "light": "Weiß", - "auto": "Automatisch (Dunkel oder Weiß)", + "auto": "Automatisch", "clear": "Klar", "system": "System", "accent": "Akzent", diff --git a/ui/i18n/en.json b/ui/i18n/en.json index a75df991..55a82535 100644 --- a/ui/i18n/en.json +++ b/ui/i18n/en.json @@ -538,9 +538,10 @@ "hidden": "Hidden" }, "color": { + "style": "Style", "dark": "Dark", "light": "White", - "auto": "Auto (Dark or White)", + "auto": "Auto", "clear": "Clear", "system": "System", "accent": "Accent", diff --git a/ui/i18n/es.json b/ui/i18n/es.json index 0080c981..b752d08d 100644 --- a/ui/i18n/es.json +++ b/ui/i18n/es.json @@ -550,9 +550,10 @@ "hidden": "Oculto" }, "color": { + "style": "Estilo", "dark": "Oscuro", "light": "Blanco", - "auto": "Automático (oscuro o blanco)", + "auto": "Automático", "clear": "Transparente", "system": "Sistema", "accent": "Acento", diff --git a/ui/i18n/fa.json b/ui/i18n/fa.json index 86d35bd7..5447effa 100644 --- a/ui/i18n/fa.json +++ b/ui/i18n/fa.json @@ -538,9 +538,10 @@ "hidden": "پنهان" }, "color": { + "style": "سبک", "dark": "تیره", "light": "سفید", - "auto": "خودکار (تیره یا سفید)", + "auto": "خودکار", "clear": "شفاف", "system": "سیستم", "accent": "رنگ اصلی", diff --git a/ui/i18n/fr.json b/ui/i18n/fr.json index 13106d20..552dedb0 100644 --- a/ui/i18n/fr.json +++ b/ui/i18n/fr.json @@ -550,9 +550,10 @@ "hidden": "Masqué" }, "color": { + "style": "Style", "dark": "Sombre", "light": "Blanc", - "auto": "Automatique (sombre ou blanc)", + "auto": "Automatique", "clear": "Transparent", "system": "Système", "accent": "Accent", diff --git a/ui/i18n/zh-Hans.json b/ui/i18n/zh-Hans.json index 147bf20a..d6c8ce98 100644 --- a/ui/i18n/zh-Hans.json +++ b/ui/i18n/zh-Hans.json @@ -526,9 +526,10 @@ "hidden": "已隐藏" }, "color": { + "style": "样式", "dark": "深色", "light": "白色", - "auto": "自动(深色或白色)", + "auto": "自动", "clear": "透明", "system": "系统", "accent": "强调色", diff --git a/ui/js/admin-app-form.js b/ui/js/admin-app-form.js index 1f51ea1c..b1f0bcca 100644 --- a/ui/js/admin-app-form.js +++ b/ui/js/admin-app-form.js @@ -34,7 +34,7 @@ import { } from '/js/admin-shared.js?v=1c01be9a'; import { createListbox } from '/js/listbox.js?v=f814170f'; import { MAX_LABELS } from '/js/badge-logic.js?v=5c72bd4c'; -import { renderColorControl, BADGE_DEFAULT } from '/js/admin-color-control.js?v=ef504f96'; +import { renderColorControl, BADGE_DEFAULT } from '/js/admin-color-control.js?v=4083ea3b'; import { badgeErrorAdvice, TONE } from '/js/admin-error.js?v=b0881957'; import { fluidHoverClear, fluidHoverKb } from '/js/fluid-hover.js?v=cb886e86'; import { iconSvg } from '/js/icon-set.js?v=628341d4'; diff --git a/ui/js/admin-color-control.js b/ui/js/admin-color-control.js index 87c16bd3..cd548108 100644 --- a/ui/js/admin-color-control.js +++ b/ui/js/admin-color-control.js @@ -3,6 +3,7 @@ import { t } from '/js/i18n.js?v=ed7c5565'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; import { qa, q } from '/js/utils.js?v=705ca896'; import { iconSvg } from '/js/icon-set.js?v=628341d4'; +import { createListbox } from '/js/listbox.js?v=f814170f'; import { HUE_NAMES, ROLE_NAMES, TILE_KEYWORDS, pageTheme, tileColor } from '/js/palette.js?v=3fb8ae43'; const CC_SWATCHES = ['#1c1c1e', '#8e8e93', '#f2f2f7', '#ff393c', '#ffcd00', '#35c759', '#0289ff', '#cb30df']; @@ -147,9 +148,11 @@ export function renderColorControl( container, { value = '#0289ff', idPrefix, onChange, variant, swatchColors = CC_SWATCHES, label = t('common.color') } = {}, ) { - const top = variant === 'tile' ? TILE_KEYWORDS : variant === 'badge' ? ROLE_NAMES : []; + const styled = variant === 'tile'; + const styles = styled ? TILE_KEYWORDS : []; + const top = variant === 'badge' ? ROLE_NAMES : []; const hues = variant ? HUE_NAMES : []; - const isKw = v => typeof v === 'string' && (top.includes(v) || hues.includes(v)); + const isKw = v => typeof v === 'string' && (styles.includes(v) || top.includes(v) || hues.includes(v)); const kwName = v => t(COLOR_KEYS[v]); const init = _hexToHsv(isKw(value) ? _swatchFill(value) || '#0289ff' : value) || { h: 212, s: 99, v: 100 }; const kwSwatch = v => @@ -160,13 +163,18 @@ export function renderColorControl( const wrap = document.createElement('div'); const slider = (name, cls, id, max, val, lo, hi) => html`
${name}
${raw(lo)}${raw(hi)}
`; - const hueRow = hues.length - ? html`
${t('color.system')}
${hues.map(kwSwatch)}
` - : ''; + const hueRow = !hues.length + ? '' + : styled + ? html`
${label}
${hues.map(kwSwatch)}${rainbow}
` + : html`
${t('color.system')}
${hues.map(kwSwatch)}
`; + const topRow = styled + ? html`
${t('color.style')}
` + : html`
${label}
${swatches}
`; setHtml( wrap, html` -
${label}
${swatches}
+ ${topRow}
${hueRow} ${slider(t('appearance.hue'), 'hsb-range hsb-hue', `${idPrefix}-h`, 360, init.h, _ccIco.hueLo, _ccIco.hueHi)} @@ -179,7 +187,7 @@ export function renderColorControl( 'unsafe-inline'. A swatch paints itself from its own value. */ for (const b of wrap.querySelectorAll('.cc-swatch[data-v]')) { const v = b.getAttribute('data-v') || ''; - const fill = v[0] === '#' ? v : v === 'auto' || v === 'clear' ? '' : _swatchFill(v); + const fill = v[0] === '#' ? v : _swatchFill(v); if (fill) /** @type {HTMLElement} */ (b).style.background = fill; } const rows = /** @type {HTMLElement[]} */ ([...wrap.children]); @@ -196,6 +204,33 @@ export function renderColorControl( container.appendChild(hidden); let mode = isKw(value) ? value : 'color'; let showTune = hues.includes(mode); + /* The colour a Style other than Color replaced, so choosing Color brings it back. */ + let resume = null; + const styleOf = () => (styles.includes(mode) ? mode : 'color'); + const styleBox = styled + ? createListbox({ + id: `${idPrefix}-style`, + label: t('color.style'), + options: [...styles, 'color'].map(v => ({ value: v, label: v === 'color' ? label : kwName(v) })), + value: styleOf(), + onChange: next => { + if (next !== 'color') { + if (!styles.includes(mode)) resume = { mode, hex: curHex(), pristine }; + mode = next; + showTune = false; + commit(); + return; + } + if (styles.includes(mode)) { + mode = resume?.mode ?? 'blue'; + setSliders(resume?.hex ?? _swatchFill('blue')); + } + showTune = true; + commit(resume?.pristine); + }, + }) + : null; + if (styleBox) rows[0].appendChild(styleBox.el); /* The first paint restores stored state, so it must not animate. */ let _painted = false; /* The value as it was stored. The sliders are integers, so reading a colour @@ -235,13 +270,15 @@ export function renderColorControl( b.classList.toggle('on', on); }); const rb = q('.cc-rainbow', container); - if (rb) rb.classList.toggle('on', showTune && (mode === 'color' || hues.includes(mode))); + if (rb) + rb.classList.toggle('on', styled ? mode === 'color' : showTune && (mode === 'color' || hues.includes(mode))); const sw = qa('.cc-swatch', container); const preset = sw.some(b => b !== rb && b.classList.contains('on')); sw.forEach(b => b.setAttribute('aria-pressed', String(b === rb ? mode === 'color' && !preset : b.classList.contains('on'))), ); - rb?.setAttribute('aria-expanded', String(showTune)); + if (!styled) rb?.setAttribute('aria-expanded', String(showTune)); + styleBox?.setValue(styleOf()); reveal(tune, showTune, !_painted); if (!codeRv.closest('.editing')) { codeRv.textContent = mode === 'color' ? hex : kwName(mode); @@ -250,8 +287,8 @@ export function renderColorControl( hidden.value = mode === 'color' ? (pristine ?? hex) : mode; _painted = true; } - const commit = () => { - pristine = null; + const commit = (keep = null) => { + pristine = keep; paint(); onChange?.(hidden.value); }; @@ -265,6 +302,11 @@ export function renderColorControl( qa('.cc-swatch', container).forEach(b => b.addEventListener('click', () => { const v = b.dataset.v || ''; + if (v === 'custom' && styled) { + mode = 'color'; + commit(); + return; + } if (v === 'custom') { showTune = !(showTune && (mode === 'color' || hues.includes(mode))); if (showTune && !hues.includes(mode)) mode = 'color'; diff --git a/ui/js/admin-list.js b/ui/js/admin-list.js index 8bf320dd..00aff25f 100644 --- a/ui/js/admin-list.js +++ b/ui/js/admin-list.js @@ -19,7 +19,7 @@ import { paintIcon } from '/js/admin-shared.js?v=1c01be9a'; import { clr, el, focusFirst, initial, qa, setUserText } from '/js/utils.js?v=705ca896'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; import { t } from '/js/i18n.js?v=ed7c5565'; -import { sizeLabel } from '/js/admin-widget-form.js?v=b76d944f'; +import { sizeLabel } from '/js/admin-widget-form.js?v=1cb745cf'; import { widgetGlyph } from '/js/widget-glyphs.js?v=b383b7c8'; import { iconSvg } from '/js/icon-set.js?v=628341d4'; diff --git a/ui/js/admin-settings.js b/ui/js/admin-settings.js index 965e7426..7fbea010 100644 --- a/ui/js/admin-settings.js +++ b/ui/js/admin-settings.js @@ -14,7 +14,7 @@ import { confirmText, promptModal } from '/js/modal.js?v=6b0320bd'; import { el, inp, setUserText } from '/js/utils.js?v=705ca896'; import { formatNumber } from '/js/format-number.js?v=abcd4ae4'; import { serialWrites } from '/js/admin-save-logic.js?v=5613a9fa'; -import { renderColorControl } from '/js/admin-color-control.js?v=ef504f96'; +import { renderColorControl } from '/js/admin-color-control.js?v=4083ea3b'; import { BACKDROP } from '/js/background.js?v=25428bf2'; import { ALLOWED_HOSTS_MAX, diff --git a/ui/js/admin-widget-form.js b/ui/js/admin-widget-form.js index e96ddaf7..e1d45f90 100644 --- a/ui/js/admin-widget-form.js +++ b/ui/js/admin-widget-form.js @@ -1,7 +1,7 @@ import { state } from '/js/admin-state.js?v=af772a1b'; import { PE_SVG, initInlineEdit, swapContent } from '/js/admin-shared.js?v=1c01be9a'; import { createListbox } from '/js/listbox.js?v=f814170f'; -import { renderWidgetConfigForm } from '/js/widget-config-form.js?v=355b495e'; +import { renderWidgetConfigForm } from '/js/widget-config-form.js?v=1807c371'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; import { sizesForView, widgetConfigMode, rejectionLines, carriesTypedValues } from '/js/admin-logic.js?v=1cca36f5'; import { t } from '/js/i18n.js?v=ed7c5565'; diff --git a/ui/js/admin.js b/ui/js/admin.js index 29c6bea5..e2664fee 100644 --- a/ui/js/admin.js +++ b/ui/js/admin.js @@ -1,7 +1,7 @@ -import { buildAppForm, buildFolderForm, captureActLabels, serializeKvRows } from '/js/admin-app-form.js?v=622c5ce8'; +import { buildAppForm, buildFolderForm, captureActLabels, serializeKvRows } from '/js/admin-app-form.js?v=f0da79cf'; import { checkAuth, requireLogin, wirePasswordStrength } from '/js/admin-auth.js?v=5246ff39'; import { recoveryShown } from '/js/config-recovery.js?v=85138697'; -import { focusRow, initList, render, syncFilterUI } from '/js/admin-list.js?v=61d89772'; +import { focusRow, initList, render, syncFilterUI } from '/js/admin-list.js?v=411d6f37'; import { resolveAdminSection } from '/js/admin-logic.js?v=1cca36f5'; import { afterImport, @@ -23,7 +23,7 @@ import { showBgFields, showWallpaperFile, wireUnsplashKey, -} from '/js/admin-settings.js?v=de5b1723'; +} from '/js/admin-settings.js?v=4b374391'; import { apiGet, apiPost, @@ -39,7 +39,7 @@ import { withheldText, } from '/js/admin-shared.js?v=1c01be9a'; import { collapsedFolders, filter, state } from '/js/admin-state.js?v=af772a1b'; -import { buildWidgetForm } from '/js/admin-widget-form.js?v=b76d944f'; +import { buildWidgetForm } from '/js/admin-widget-form.js?v=1cb745cf'; import { initFluidHover } from '/js/fluid-hover.js?v=cb886e86'; import { formatNumber } from '/js/format-number.js?v=abcd4ae4'; import { initGlideSelect, syncGlideSelect } from '/js/glide-select.js?v=8b39e9d0'; diff --git a/ui/js/widget-config-form.js b/ui/js/widget-config-form.js index a420a6bf..f405f060 100644 --- a/ui/js/widget-config-form.js +++ b/ui/js/widget-config-form.js @@ -5,7 +5,7 @@ import { t } from '/js/i18n.js?v=ed7c5565'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; import { reveal, wireInlineEdit } from '/js/admin-shared.js?v=1c01be9a'; import { createListbox } from '/js/listbox.js?v=f814170f'; -import { renderColorControl } from '/js/admin-color-control.js?v=ef504f96'; +import { renderColorControl } from '/js/admin-color-control.js?v=4083ea3b'; import { seedCarried, applyOptionSet, diff --git a/ui/test/i18n-coverage.test.mjs b/ui/test/i18n-coverage.test.mjs index 4da56d6a..924a2d10 100644 --- a/ui/test/i18n-coverage.test.mjs +++ b/ui/test/i18n-coverage.test.mjs @@ -78,6 +78,8 @@ const SAME_ON_PURPOSE = { 'color.orange', 'color.cyan', 'color.indigo', + /* "Style" is the French word too. */ + 'color.style', /* Info and the version line are written the same way in French. */ 'general.logInfo', /* "Image" is the French word too. */