From 32e9550ca2d280e2efd11e9d1cb6e5720db9001b Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Mon, 2 Mar 2026 16:53:32 -0500 Subject: [PATCH] =?UTF-8?q?feat(badges):=20layout=20CSS=20system=20?= =?UTF-8?q?=E2=80=94=20data-layout=20attribute,=20@page=20injection,=20sty?= =?UTF-8?q?le=5Fhref?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two compiled layout CSS files in src/lib/ae_events/badges/css/: - badge_layout_epson_4x5_fanfold.css — 4"×5" per side, Epson ColorWorks C3500 fanfold duplex; preferred for general conference use (ISHLT, demos) - badge_layout_zebra_zc10l_pvc.css — 3.5"×5.5" PVC card, Zebra ZC10L, single-sided (pair with duplex=0 on template) Rules scoped under [data-layout="..."] on the wrapper — beats Tailwind utility class specificity without !important. Vite hot-reloads these in dev. Badge component: add data-layout attribute from template.layout field; import both layout CSS files (falls back to Tailwind 4"×6" defaults if layout unset). Print page svelte:head: inject @page paper-size rule per layout code (@page cannot use attribute selectors so it must be dynamic). Also wire style_href as a for per-event external client branding CSS. db_events.ts Badge_template interface: add style_href and duplex fields. MODULE doc: update layout codes table with badge_4x5_fanfold entry. Co-Authored-By: Claude Sonnet 4.6 --- .../MODULE__AE_Events_Badge_Templates.md | 20 +++++---- .../css/badge_layout_epson_4x5_fanfold.css | 42 +++++++++++++++++++ .../css/badge_layout_zebra_zc10l_pvc.css | 29 +++++++++++++ src/lib/ae_events/db_events.ts | 2 + .../[badge_id]/ae_comp__badge_obj_view.svelte | 7 ++++ .../badges/[badge_id]/print/+page.svelte | 37 ++++++++++++++++ 6 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 src/lib/ae_events/badges/css/badge_layout_epson_4x5_fanfold.css create mode 100644 src/lib/ae_events/badges/css/badge_layout_zebra_zc10l_pvc.css diff --git a/documentation/MODULE__AE_Events_Badge_Templates.md b/documentation/MODULE__AE_Events_Badge_Templates.md index 6d7bea23..0589caf8 100644 --- a/documentation/MODULE__AE_Events_Badge_Templates.md +++ b/documentation/MODULE__AE_Events_Badge_Templates.md @@ -176,15 +176,19 @@ to avoid bleeding into the rest of the app. The classes used in The `layout` field encodes physical badge stock dimensions. Standard codes to use: -| Code | Dimensions | Description | -|---|---|---| -| `badge_3.5x5.5_pvc` | 3.5" × 5.5" (88.9 × 139.7mm) | PVC card, Zebra ZC10L | -| `badge_4x6_fanfold` | 4" × 6" (101.6 × 152.4mm) | Fanfold paper badge | -| `badge_4x6_fanfold_tickets` | 4" × 6" + tear-offs | Fanfold with ticket stubs | +| Code | Dimensions | CSS file | Description | +| --- | --- | --- | --- | +| `badge_4x5_fanfold` | 4" × 5" (101.6 × 127mm) | `badge_layout_epson_4x5_fanfold.css` | Epson ColorWorks C3500 / ExpoBadge fanfold — preferred for general conference use (ISHLT, demos) | +| `badge_3.5x5.5_pvc` | 3.5" × 5.5" (88.9 × 139.7mm) | `badge_layout_zebra_zc10l_pvc.css` | PVC card, Zebra ZC10L — single-sided, set `duplex=0` | +| `badge_4x6_fanfold` | 4" × 6" (101.6 × 152.4mm) | *(none — Tailwind defaults)* | Generic fanfold fallback; dimensions match the hardcoded Tailwind values | +| `badge_4x6_fanfold_tickets` | 4" × 6" + tear-offs | *(pending)* | Fanfold with ticket stubs | -The current badge component is hard-coded to `w-[4in]` / `min-h-[6.0in]`. These -dimensions will need to be made template-driven once the `layout` field is wired up. -For now, override via print CSS in the `style_href` stylesheet. +Layout CSS files live in `src/lib/ae_events/badges/css/` and are imported by +`ae_comp__badge_obj_view.svelte`. Rules are scoped under `[data-layout="..."]` on the +wrapper so multiple layouts can coexist in the bundle without conflict. + +`@page` paper size rules are injected per-layout from `print/+page.svelte ` +(attribute selectors cannot scope `@page` rules, so they're handled dynamically). --- diff --git a/src/lib/ae_events/badges/css/badge_layout_epson_4x5_fanfold.css b/src/lib/ae_events/badges/css/badge_layout_epson_4x5_fanfold.css new file mode 100644 index 00000000..e086784b --- /dev/null +++ b/src/lib/ae_events/badges/css/badge_layout_epson_4x5_fanfold.css @@ -0,0 +1,42 @@ +/* ============================================================================= + Badge Layout: Epson ColorWorks C3500/C4000 / ExpoBadge 4" × 5" Fanfold (Duplex) + layout code: badge_4x5_fanfold + Badge stock: 4in wide × 5in per side, double-sided, continuous fanfold + Used for: ISHLT, general conference use, preferred demo layout + + Print behavior: + Front (5") and back (5") render stacked on screen. When printed, the browser + sends a 4" × 10" strip to the Epson ColorWorks driver. @page size is injected + dynamically by print/+page.svelte based on the layout field. + + CSS scope: + All rules scoped under [data-layout="badge_4x5_fanfold"] to avoid conflicts + with other layouts rendered on the same page. These override the Tailwind + utility classes (w-[4in], min-h-[6.0in], etc.) that are hardcoded on the + badge sections — attribute + class selectors win over single class selectors. + ============================================================================= */ + +/* --- Badge front --- */ + +[data-layout="badge_4x5_fanfold"] .badge_front { + width: 4in; + min-height: 5in; + max-height: 5in; +} + +/* Body area: 5in total − ~1in header − ~0.5in footer = ~3.5in for content */ +[data-layout="badge_4x5_fanfold"] .badge_body { + max-height: 3.5in; +} + +/* --- Badge back --- */ + +[data-layout="badge_4x5_fanfold"] .badge_back { + width: 4in; + min-height: 5in; + max-height: 5in; +} + +[data-layout="badge_4x5_fanfold"] .badge_back_content { + max-height: 4.5in; +} diff --git a/src/lib/ae_events/badges/css/badge_layout_zebra_zc10l_pvc.css b/src/lib/ae_events/badges/css/badge_layout_zebra_zc10l_pvc.css new file mode 100644 index 00000000..3bd1c2c3 --- /dev/null +++ b/src/lib/ae_events/badges/css/badge_layout_zebra_zc10l_pvc.css @@ -0,0 +1,29 @@ +/* ============================================================================= + Badge Layout: Zebra ZC10L — PVC Card 3.5" × 5.5" + layout code: badge_3.5x5.5_pvc + Badge stock: 3.5in × 5.5in PVC card (CR80 portrait equivalent) + Used for: Axonius NYC (April 2026), single-sided events + + Print behavior: + Single-sided only. Set duplex=0 on the template — the badge_back section + will not render at all. @page size (3.5in × 5.5in) is injected dynamically + by print/+page.svelte based on the layout field. + + CSS scope: + All rules scoped under [data-layout="badge_3.5x5.5_pvc"] to avoid conflicts. + These override the hardcoded Tailwind utility classes on the badge sections. + ============================================================================= */ + +/* --- Badge front --- */ + +[data-layout="badge_3.5x5.5_pvc"] .badge_front { + width: 3.5in; + min-height: 5.5in; + max-height: 5.5in; +} + +/* Body area: 5.5in total − ~1in header − ~0.5in footer = ~4in for content. + Same as the current Tailwind default — no body override needed. */ + +/* No .badge_back rules — duplex=0 on the template means the back section + is not rendered at all (see show_badge_back in ae_comp__badge_obj_view.svelte). */ diff --git a/src/lib/ae_events/db_events.ts b/src/lib/ae_events/db_events.ts index 769a8d2b..ec9688ac 100644 --- a/src/lib/ae_events/db_events.ts +++ b/src/lib/ae_events/db_events.ts @@ -251,6 +251,8 @@ export interface Badge_template { layout?: null | string; style_filename?: null | string; + style_href?: null | string; + duplex?: null | number | boolean; enable?: null | boolean; hide?: null | boolean; diff --git a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte index cb459e83..f56c1a58 100644 --- a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte +++ b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte @@ -33,6 +33,12 @@ log_lvl = 0 }: Props = $props(); + // Badge layout CSS — compiled in, hot-reloads in dev. + // Each file scopes rules under [data-layout="..."] on the wrapper section. + // @page rules (paper size) are injected per-template in print/+page.svelte. + import '$lib/ae_events/badges/css/badge_layout_epson_4x5_fanfold.css'; + import '$lib/ae_events/badges/css/badge_layout_zebra_zc10l_pvc.css'; + // *** Import Svelte specific import { browser } from '$app/environment'; import { goto } from '$app/navigation'; @@ -561,6 +567,7 @@ onkeypress={() => {