chore(badges): hex-only body_text_color + form color picker; renderer default black

This commit is contained in:
Scott Idem
2026-04-08 14:19:48 -04:00
parent 0aa32a5293
commit d5b2b557f3
3 changed files with 40 additions and 27 deletions

View File

@@ -296,28 +296,17 @@ let qr_back_justify = $derived.by(() => {
});
// Body text color: can be a Tailwind `text-*` class or a hex value like `#112233`.
let body_text_color_class = $derived.by(() => {
const cfg = template_cfg || {};
const raw = cfg?.body_text_color ?? cfg?.text_color ?? '';
if (!raw || typeof raw !== 'string') return '';
const v = raw.trim();
if (v.startsWith('text-')) return v;
// Map simple color names to Tailwind where reasonable (e.g., 'white' -> 'text-white')
if (/^[a-zA-Z]+$/.test(v)) {
const pick = v.toLowerCase();
const allowed = ['white','black','gray','red','blue','green','yellow','indigo','purple','pink'];
if (allowed.includes(pick)) return `text-${pick}`;
}
return '';
});
// Prefer an explicit hex fallback stored as `body_text_color_hex` in `cfg_json`.
// The `body_text_color` key may still contain a Tailwind class for styling
// when the compiled CSS includes it; the hex ensures correct rendering when
// classes are purged at build-time.
let body_text_color_style = $derived.by(() => {
const cfg = template_cfg || {};
const raw = cfg?.body_text_color ?? cfg?.text_color ?? '';
if (!raw || typeof raw !== 'string') return '';
if (!raw || typeof raw !== 'string') return 'color: #000000;';
const v = raw.trim();
if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(v)) return `color: ${v};`;
return '';
return 'color: #000000;';
});
/**
@@ -686,7 +675,7 @@ const code_to_icon: {
items-center
justify-end overflow-clip
p-0 px-8 pb-1
{body_text_color_class || 'text-white'}
text-black
gap-0
"
style="{body_text_color_style}">

View File

@@ -57,8 +57,8 @@ let cfg_show_qr_back = $state(true);
let cfg_hide_title = $state(false);
let cfg_hide_affiliations = $state(false);
let cfg_hide_location = $state(false);
// Body text color: Tailwind class (e.g. 'text-black') or hex (e.g. '#000000')
let cfg_body_text_color = $state('text-black');
// Body text color (hex)
let cfg_body_text_color = $state('#000000');
// Alignment overrides: 'left' | 'center' | 'right' | 'justify'
let cfg_align_name = $state('center');
let cfg_align_title = $state('center');
@@ -128,8 +128,13 @@ async function load_template(id: string) {
cfg_hide_affiliations = parsed_cfg.hasOwnProperty('hide_affiliations') ? !!parsed_cfg.hide_affiliations : false;
cfg_hide_location = parsed_cfg.hasOwnProperty('hide_location') ? !!parsed_cfg.hide_location : false;
// Body text color
cfg_body_text_color = parsed_cfg.body_text_color ?? parsed_cfg.text_color ?? 'text-white';
// Body text color (hex-only). Prefer explicit hex keys.
const _hex_candidate = parsed_cfg.body_text_color_hex ?? parsed_cfg.body_text_color ?? parsed_cfg.text_color ?? '';
if (typeof _hex_candidate === 'string' && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(_hex_candidate.trim())) {
cfg_body_text_color = _hex_candidate.trim();
} else {
cfg_body_text_color = '#000000';
}
// Alignment overrides (nested under cfg_json.align and cfg_json.qr_alignment)
cfg_align_name = parsed_cfg?.align?.name ?? parsed_cfg.align_name ?? 'center';
@@ -190,8 +195,14 @@ async function handle_submit() {
cfg_obj.qr_alignment.front = cfg_qr_alignment_front;
cfg_obj.qr_alignment.back = cfg_qr_alignment_back;
// Body text color (Tailwind class or hex)
cfg_obj.body_text_color = cfg_body_text_color;
// Body text color (hex-only)
if (typeof cfg_body_text_color === 'string' && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(cfg_body_text_color.trim())) {
cfg_obj.body_text_color = cfg_body_text_color.trim();
} else {
// Remove any stale color keys to avoid keeping invalid values
if ((cfg_obj as any)?.body_text_color) delete (cfg_obj as any).body_text_color;
if ((cfg_obj as any)?.body_text_color_hex) delete (cfg_obj as any).body_text_color_hex;
}
const data_to_save: key_val = {
name,
@@ -432,8 +443,14 @@ function handle_cancel() {
</select>
</label>
<label class="label">
<span>Body Text Color (Tailwind class or #hex)</span>
<input type="text" bind:value={cfg_body_text_color} class="input" placeholder="text-black or #000000" />
<span>Body Text Color (hex)</span>
<div class="flex items-center gap-2">
<input type="color" bind:value={cfg_body_text_color} class="w-10 h-8 p-0" />
<input type="text" bind:value={cfg_body_text_color} class="input w-32" placeholder="#rrggbb" />
</div>
<p class="text-xs text-surface-400 italic">
Pick a hex color (e.g. #112233). The renderer will use this inline color.
</p>
</label>
</div>
<p class="text-xs text-surface-400 italic">

View File

@@ -1,4 +1,11 @@
import type { Config } from 'tailwindcss';
// Tailwind's shipped `Config` type may not include the `safelist` option
// depending on the installed types/version. Extend it locally so we can
// use `safelist` without TypeScript errors.
type ConfigWithSafelist = Config & {
safelist?: Array<string | { pattern: RegExp }>;
};
import { skeleton } from '@skeletonlabs/skeleton';
import forms from '@tailwindcss/forms';
import typography from '@tailwindcss/typography';
@@ -40,6 +47,6 @@ const config = {
}
})
]
} satisfies Config;
} satisfies ConfigWithSafelist;
export default config;