Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.13.2 — 2026-10-04

- **Forms show their labels and the privacy checkbox.** Bricks prints form labels only with "Show labels", and a checkbox's text only from its options. Every BricksSnap form left both out, so on the site the fields had no labels and the required privacy checkbox was missing. This affected contact, hero with form, sign-in and coming-soon layouts. Forms now set `showLabels`, and the checkbox carries its text as an option under a "Privacy" label.
- **Preview** renders forms the same way: no labels without `showLabels`, checkbox texts from the options, honeypot fields hidden.
- **Tests** check every form layout for labels and checkbox options.

## 0.13.1 — 2026-10-01

Fixes found while rebuilding a real club website on a Bricks 2.4.2 site. See the [release notes](docs/RELEASE-0.13.1.md).
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "brickssnap",
"version": "0.13.1",
"version": "0.13.2",
"scripts": {
"dev": "next dev --webpack",
"dev:local": "node scripts/dev-local.mjs",
Expand Down
8 changes: 5 additions & 3 deletions src/lib/kit/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,12 @@ function formHtml(el: BricksElement): string {
const s = el.settings;
const fields = Array.isArray(s.fields) ? s.fields as Array<Record<string, unknown>> : [];
const input = (f: Record<string, unknown>) => {
const label = esc(String(f.label ?? ""));
if (f.type === "checkbox") return `<label class="bsp-check"><input type="checkbox" disabled> <span>${label}</span></label>`;
// Like Bricks: labels only with showLabels, honeypots hidden, checkbox texts from the options.
if (f.isHoneypot) return "";
const label = s.showLabels ? `<label>${esc(String(f.label ?? ""))}</label>` : "";
if (f.type === "checkbox") return `<div class="form-group">${label}${String(f.options ?? "").split("\n").filter(Boolean).map(option => `<label class="bsp-check"><input type="checkbox" disabled> <span>${esc(option)}</span></label>`).join("")}</div>`;
const control = f.type === "textarea" ? `<textarea disabled rows="4"></textarea>` : `<input type="${esc(String(f.type ?? "text"))}" disabled>`;
return `<div class="form-group" style="width:${Number(f.width) > 0 ? `calc(${Number(f.width)}% - 8px)` : "100%"}"><label>${label}</label>${control}</div>`;
return `<div class="form-group" style="width:${Number(f.width) > 0 ? `calc(${Number(f.width)}% - 8px)` : "100%"}">${label}${control}</div>`;
};
return `<form class="brxe-form">${fields.map(input).join("")}<div class="form-group submit-button-wrapper"><button type="button" class="bricks-button">${esc(String(s.submitButtonText ?? "Send"))}</button></div></form>`;
}
Expand Down
6 changes: 5 additions & 1 deletion src/lib/kit/sections/more.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,12 @@ function moreClasses(r: ResolvedKit) {
export function form(ctx: Ctx, fields: Array<{ type: string; label: string; required?: boolean; width?: number }>, submit: string, actions: string[] = ["email"]): KitNode {
const { x } = ctx;
const fieldId = (i: number) => `f${String(i + 1).padStart(5, "0")}`;
// Bricks prints a checkbox's text from its options (one per line); the label becomes its heading.
const checkboxLabel = ctx.c.lang === "de" ? "Datenschutz" : "Privacy";
return node("form", "bs-form", {
fields: fields.map((f, i) => ({ id: fieldId(i), type: f.type, label: f.label, required: !!f.required, ...(f.width ? { width: f.width } : {}) })),
fields: fields.map((f, i) => ({ id: fieldId(i), type: f.type, ...(f.type === "checkbox" ? { label: checkboxLabel, options: f.label } : { label: f.label }), required: !!f.required, ...(f.width ? { width: f.width } : {}) })),
// Without it Bricks renders no labels at all.
showLabels: true,
...(actions.includes("login") ? { loginName: fieldId(0), loginPassword: fieldId(1) } : {}),
submitButtonText: submit,
actions,
Expand Down
21 changes: 21 additions & 0 deletions tests/kit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,24 @@ describe("class CSS as Bricks 2.4 stores and renders it", () => {
expect([...weak]).toEqual([]);
});
});

describe("forms as Bricks renders them", () => {
it("show their labels and give checkboxes the options Bricks prints", () => {
const forms = LAYOUTS.flatMap(layout => generateKitTemplate({ kit: {}, profile: { industry: "kfz", language: "de" }, sections: [layout] }).template.content.filter(el => el.name === "form"));
expect(forms.length).toBeGreaterThanOrEqual(6);
for (const form of forms) {
expect(form.settings.showLabels).toBe(true);
for (const field of form.settings.fields as Array<Record<string, unknown>>) if (field.type === "checkbox") expect(String(field.options ?? "")).toMatch(/Datenschutzerklärung/);
}
});

it("previews labels only when Bricks would show them", () => {
const { template } = generateKitTemplate({ kit: {}, profile: { industry: "kfz", language: "de" }, sections: [{ type: "contact", variant: "split" }] });
const html = renderPreview(template).html;
expect(html).toContain("<label>Name</label>");
expect(html).toContain("<span>Ich stimme der Verarbeitung meiner Daten gemäß Datenschutzerklärung zu.</span>");
const form = template.content.find(el => el.name === "form")!;
const unlabeled = { ...template, content: template.content.map(el => (el === form ? { ...el, settings: { ...el.settings, showLabels: false } } : el)) };
expect(renderPreview(unlabeled).html).not.toContain("<label>Name</label>");
});
});
Loading