ui(badges): layout & fit-text tweaks; improve template form controls; remove badge modals from event settings; add documentation for passcode security

This commit is contained in:
Scott Idem
2026-04-10 11:44:22 -04:00
parent c9e2284758
commit e542c55500
5 changed files with 499 additions and 155 deletions

View File

@@ -19,7 +19,7 @@
* Props:
* min — minimum font size in px (default: 16)
* max — maximum font size in px (default: 80)
* manual_size — when set, disables auto-scaling and applies this font size directly
* manual_size — when set, caps the binary search at this size (overflow-safe preferred max)
* disabled — when true, neither auto-scaling nor manual_size is applied
* height — explicit CSS height for the wrapper div (e.g. "1.5in", "3rem")
* width — explicit CSS width for the wrapper div (rarely needed; usually inherits)
@@ -37,7 +37,7 @@
* {attendee_name}
* </Element_fit_text>
*
* Example — manual override (disables auto-scale, applies fixed size):
* Example — manual cap (prefers this size, scales down if it doesn't fit):
* <Element_fit_text min={20} max={80} manual_size={font_size_name}>
* {attendee_name}
* </Element_fit_text>
@@ -49,7 +49,12 @@ import type { Snippet } from 'svelte';
interface Props {
min?: number;
max?: number;
/** When set, disables auto-scaling and applies this size directly via inline style. */
/**
* When set, caps the binary search at this size (overflow-safe preferred max).
* If the text fits at manual_size → renders at exactly manual_size.
* If manual_size is too large for the container → scales down to what fits.
* Reset to null to restore full auto-scaling.
*/
manual_size?: number | null;
/** When true, neither auto-scaling nor manual_size is applied. */
disabled?: boolean;
@@ -78,16 +83,32 @@ let {
children
}: Props = $props();
// Pass null to the action when auto-scaling should be suppressed
// Always run the action unless explicitly disabled.
// When manual_size is set, use it as the max for the binary search — the action
// still runs so the text can never overflow the container. This means manual_size
// is "no larger than X, but still container-safe":
// manual_size fits → renders at exactly manual_size (same as before)
// manual_size too big → action scales down to what fits (prevents clipping)
// manual_size=null → auto-scales up to max as normal
// Using min=1 in manual mode: the user may intentionally want sizes below the
// auto-scale minimum (e.g. a very long name that only reads well at 22px).
// The controls' own FONT_SIZE_MIN prevents comically small values.
//
// WHY NOT inline style: if we set font-size via style attr AND the action sets it
// via node.style.fontSize, the last writer wins — causing unpredictable results.
// Letting the action own font-size entirely avoids this race.
let action_params = $derived(
disabled || manual_size != null ? null : { min, max }
disabled
? null
: {
min: manual_size != null ? 1 : min,
max: manual_size != null ? manual_size : max
}
);
// Compose the final inline style.
// Priority: manual_size → height/width → extra_style (caller's additional styles)
// Compose the final inline style — font-size is NOT here; the action owns it.
let computed_style = $derived(() => {
const parts: string[] = [];
if (manual_size != null) parts.push(`font-size: ${manual_size}px`);
if (height) parts.push(`height: ${height}`);
if (width) parts.push(`width: ${width}`);
if (extra_style) parts.push(extra_style);