feat(badges): per-side header padding configurable via template cfg_json
Adds header_padding_top/right/left alongside existing header_padding_bottom. Removes hardcoded p-2 class — all four sides now set via inline style with 0.5rem default. Template form shows a 2×2 padding grid in Header & Branding. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,10 +47,12 @@ export interface BadgeTemplateCfg {
|
|||||||
header_border_color?: string;
|
header_border_color?: string;
|
||||||
// Thickness of the header bottom border. Any CSS length. Default "2px" when color is set.
|
// Thickness of the header bottom border. Any CSS length. Default "2px" when color is set.
|
||||||
header_border_width?: string;
|
header_border_width?: string;
|
||||||
// Padding below the header image (inside the badge_header div, above the border).
|
// Per-side padding of the badge_header div. Any CSS length. Unset = 0.5rem (Tailwind p-2 default).
|
||||||
// Useful for creating visual space between the image and the body.
|
// Bottom padding creates space between the header image and the border line (e.g. "1.45in").
|
||||||
// Any CSS length: "0.5in", "1rem". Unset = no extra padding.
|
header_padding_top?: string;
|
||||||
|
header_padding_right?: string;
|
||||||
header_padding_bottom?: string;
|
header_padding_bottom?: string;
|
||||||
|
header_padding_left?: string;
|
||||||
|
|
||||||
// Punch-out hole markers: show X overlays at the physical badge clip slot positions.
|
// Punch-out hole markers: show X overlays at the physical badge clip slot positions.
|
||||||
// Slots are pre-perforated on the badge stock — markers guide attendees to push them out.
|
// Slots are pre-perforated on the badge stock — markers guide attendees to push them out.
|
||||||
|
|||||||
@@ -347,17 +347,21 @@ let punch_holes_colors = $derived.by(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Full inline style string for the badge_header div.
|
// Full inline style string for the badge_header div.
|
||||||
// Combines margin-top, optional bottom border (color + width), and optional bottom padding.
|
// All four padding sides are set explicitly so the p-2 class is not needed.
|
||||||
|
// Unset sides default to 0.5rem (Tailwind p-2 equivalent).
|
||||||
// Unset border_color = no border drawn.
|
// Unset border_color = no border drawn.
|
||||||
let header_div_style = $derived.by(() => {
|
let header_div_style = $derived.by(() => {
|
||||||
const parts: string[] = [`margin-top: ${header_margin_top}`];
|
const parts: string[] = [`margin-top: ${header_margin_top}`];
|
||||||
|
const pt = (template_cfg?.header_padding_top ?? '').trim() || '0.5rem';
|
||||||
|
const pr = (template_cfg?.header_padding_right ?? '').trim() || '0.5rem';
|
||||||
|
const pb = (template_cfg?.header_padding_bottom ?? '').trim() || '0.5rem';
|
||||||
|
const pl = (template_cfg?.header_padding_left ?? '').trim() || '0.5rem';
|
||||||
|
parts.push(`padding: ${pt} ${pr} ${pb} ${pl}`);
|
||||||
const color = (template_cfg?.header_border_color ?? '').trim();
|
const color = (template_cfg?.header_border_color ?? '').trim();
|
||||||
if (color) {
|
if (color) {
|
||||||
const width = (template_cfg?.header_border_width ?? '').trim() || '2px';
|
const width = (template_cfg?.header_border_width ?? '').trim() || '2px';
|
||||||
parts.push(`border-bottom: ${width} solid ${color}`);
|
parts.push(`border-bottom: ${width} solid ${color}`);
|
||||||
}
|
}
|
||||||
const pb = (template_cfg?.header_padding_bottom ?? '').trim();
|
|
||||||
if (pb) parts.push(`padding-bottom: ${pb}`);
|
|
||||||
return parts.join('; ');
|
return parts.join('; ');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -748,7 +752,6 @@ const code_to_icon: {
|
|||||||
max-h-[1.10in]
|
max-h-[1.10in]
|
||||||
min-h-[.50in]
|
min-h-[.50in]
|
||||||
max-w-full overflow-hidden
|
max-w-full overflow-hidden
|
||||||
p-2
|
|
||||||
hover:outline-2 hover:outline-gray-500/75 hover:outline-dashed
|
hover:outline-2 hover:outline-gray-500/75 hover:outline-dashed
|
||||||
"
|
"
|
||||||
style={header_div_style}>
|
style={header_div_style}>
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ let cfg_body_text_color = $state('#000000');
|
|||||||
let cfg_bleed = $state('');
|
let cfg_bleed = $state('');
|
||||||
// Header image vertical offset (CSS length). Empty = default 2rem. Negative = shift up.
|
// Header image vertical offset (CSS length). Empty = default 2rem. Negative = shift up.
|
||||||
let cfg_header_margin_top = $state('');
|
let cfg_header_margin_top = $state('');
|
||||||
|
// Header div padding per side (CSS length). Empty = default 0.5rem (Tailwind p-2).
|
||||||
|
let cfg_header_padding_top = $state('');
|
||||||
|
let cfg_header_padding_right = $state('');
|
||||||
|
let cfg_header_padding_bottom = $state('');
|
||||||
|
let cfg_header_padding_left = $state('');
|
||||||
// Punch-out hole markers (left/right/center badge clip slots).
|
// Punch-out hole markers (left/right/center badge clip slots).
|
||||||
let cfg_punch_holes_left = $state(false);
|
let cfg_punch_holes_left = $state(false);
|
||||||
let cfg_punch_holes_right = $state(false);
|
let cfg_punch_holes_right = $state(false);
|
||||||
@@ -81,8 +86,6 @@ let cfg_punch_holes_center_bg = $state('');
|
|||||||
// Header bottom border. Empty color = no border.
|
// Header bottom border. Empty color = no border.
|
||||||
let cfg_header_border_color = $state('');
|
let cfg_header_border_color = $state('');
|
||||||
let cfg_header_border_width = $state('');
|
let cfg_header_border_width = $state('');
|
||||||
// Padding below the header image (above the border line). Empty = no extra padding.
|
|
||||||
let cfg_header_padding_bottom = $state('');
|
|
||||||
// Alignment overrides: 'left' | 'center' | 'right' | 'justify'
|
// Alignment overrides: 'left' | 'center' | 'right' | 'justify'
|
||||||
let cfg_align_name = $state('center');
|
let cfg_align_name = $state('center');
|
||||||
let cfg_align_title = $state('center');
|
let cfg_align_title = $state('center');
|
||||||
@@ -190,7 +193,10 @@ async function load_template(id: string) {
|
|||||||
cfg_punch_holes_center_bg = parsed_cfg?.punch_holes?.center_bg ?? '';
|
cfg_punch_holes_center_bg = parsed_cfg?.punch_holes?.center_bg ?? '';
|
||||||
cfg_header_border_color = parsed_cfg.header_border_color ?? '';
|
cfg_header_border_color = parsed_cfg.header_border_color ?? '';
|
||||||
cfg_header_border_width = parsed_cfg.header_border_width ?? '';
|
cfg_header_border_width = parsed_cfg.header_border_width ?? '';
|
||||||
|
cfg_header_padding_top = parsed_cfg.header_padding_top ?? '';
|
||||||
|
cfg_header_padding_right = parsed_cfg.header_padding_right ?? '';
|
||||||
cfg_header_padding_bottom = parsed_cfg.header_padding_bottom ?? '';
|
cfg_header_padding_bottom = parsed_cfg.header_padding_bottom ?? '';
|
||||||
|
cfg_header_padding_left = parsed_cfg.header_padding_left ?? '';
|
||||||
|
|
||||||
// Alignment overrides (nested under cfg_json.align and cfg_json.qr_alignment)
|
// Alignment overrides (nested under cfg_json.align and cfg_json.qr_alignment)
|
||||||
cfg_align_name = parsed_cfg?.align?.name ?? parsed_cfg.align_name ?? 'center';
|
cfg_align_name = parsed_cfg?.align?.name ?? parsed_cfg.align_name ?? 'center';
|
||||||
@@ -307,12 +313,11 @@ async function handle_submit() {
|
|||||||
delete cfg_obj.header_border_width;
|
delete cfg_obj.header_border_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header padding below image
|
// Header padding — per side; each saved independently, removed when cleared
|
||||||
if (cfg_header_padding_bottom.trim()) {
|
if (cfg_header_padding_top.trim()) { cfg_obj.header_padding_top = cfg_header_padding_top.trim(); } else { delete cfg_obj.header_padding_top; }
|
||||||
cfg_obj.header_padding_bottom = cfg_header_padding_bottom.trim();
|
if (cfg_header_padding_right.trim()) { cfg_obj.header_padding_right = cfg_header_padding_right.trim(); } else { delete cfg_obj.header_padding_right; }
|
||||||
} else {
|
if (cfg_header_padding_bottom.trim()) { cfg_obj.header_padding_bottom = cfg_header_padding_bottom.trim(); } else { delete cfg_obj.header_padding_bottom; }
|
||||||
delete cfg_obj.header_padding_bottom;
|
if (cfg_header_padding_left.trim()) { cfg_obj.header_padding_left = cfg_header_padding_left.trim(); } else { delete cfg_obj.header_padding_left; }
|
||||||
}
|
|
||||||
|
|
||||||
const data_to_save: key_val = {
|
const data_to_save: key_val = {
|
||||||
name,
|
name,
|
||||||
@@ -480,13 +485,29 @@ function toggle_cfg_controls_auth_editable(key: string) {
|
|||||||
<span>Border Thickness</span>
|
<span>Border Thickness</span>
|
||||||
<input type="text" bind:value={cfg_header_border_width} class="input" placeholder="e.g. 2px, 0.5mm (default: 2px)" />
|
<input type="text" bind:value={cfg_header_border_width} class="input" placeholder="e.g. 2px, 0.5mm (default: 2px)" />
|
||||||
</label>
|
</label>
|
||||||
<label class="label">
|
</div>
|
||||||
<span>Padding Below Header Image</span>
|
|
||||||
<input type="text" bind:value={cfg_header_padding_bottom} class="input" placeholder="e.g. 1.45in, 2rem — leave blank for none" />
|
<div class="space-y-1">
|
||||||
<p class="text-xs text-surface-400 italic">
|
<p class="text-sm font-medium">Header Padding</p>
|
||||||
Creates space between the header image and the border line.
|
<p class="text-xs text-surface-400 italic">Per-side padding of the header image container. Any CSS length. Leave blank for default (0.5rem). Bottom padding creates space between the image and the border line.</p>
|
||||||
</p>
|
<div class="grid grid-cols-2 gap-2">
|
||||||
</label>
|
<label class="label">
|
||||||
|
<span>Top</span>
|
||||||
|
<input type="text" bind:value={cfg_header_padding_top} class="input" placeholder="0.5rem" />
|
||||||
|
</label>
|
||||||
|
<label class="label">
|
||||||
|
<span>Right</span>
|
||||||
|
<input type="text" bind:value={cfg_header_padding_right} class="input" placeholder="0.5rem" />
|
||||||
|
</label>
|
||||||
|
<label class="label">
|
||||||
|
<span>Bottom</span>
|
||||||
|
<input type="text" bind:value={cfg_header_padding_bottom} class="input" placeholder="0.5rem" />
|
||||||
|
</label>
|
||||||
|
<label class="label">
|
||||||
|
<span>Left</span>
|
||||||
|
<input type="text" bind:value={cfg_header_padding_left} class="input" placeholder="0.5rem" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label class="label">
|
<label class="label">
|
||||||
|
|||||||
Reference in New Issue
Block a user