diff --git a/apps/web/src/components/branding/branding-form.tsx b/apps/web/src/components/branding/branding-form.tsx index e22a2d2..aefddf6 100644 --- a/apps/web/src/components/branding/branding-form.tsx +++ b/apps/web/src/components/branding/branding-form.tsx @@ -5,6 +5,7 @@ import { Button, Card, Field, Input, Textarea } from "@msk-forms/ui"; import { useRouter } from "next/navigation"; import { useState } from "react"; +import { CssPreview } from "@/components/branding/css-preview"; import type { Dictionary } from "@/i18n"; type BrandingDict = Dictionary["branding"]; @@ -12,6 +13,21 @@ type BrandingDict = Dictionary["branding"]; const DEFAULT_ACCENT = "#5eb131"; const HEX = /^#[0-9a-fA-F]{6}$/; +/** + * Beginner-friendly starter rules. Each targets `.msk-form` or a CSS variable + * so it behaves identically in the preview and on the live page (the two + * documented, stable hooks). `key` maps to a localized label. + */ +const CSS_SNIPPETS: { key: keyof BrandingDict["snip"]; css: string }[] = [ + { key: "rounded", css: ".msk-form {\n --radius: 1.25rem;\n}" }, + { + key: "tint", + css: ".msk-form {\n background: hsl(var(--primary) / 0.05);\n padding: 1.5rem;\n border-radius: 1rem;\n}", + }, + { key: "text", css: ".msk-form {\n font-size: 1.05rem;\n}" }, + { key: "heading", css: ".msk-form h1 {\n color: hsl(var(--primary));\n font-weight: 800;\n}" }, +]; + export function BrandingForm({ guildId, initial, @@ -58,6 +74,11 @@ export function BrandingForm({ } } + function addSnippet(snippet: string) { + setCss((prev) => (prev.trim() ? `${prev.trimEnd()}\n\n${snippet}` : snippet)); + setSaved(false); + } + const swatch = HEX.test(color.trim()) ? color.trim() : DEFAULT_ACCENT; return ( @@ -101,17 +122,51 @@ export function BrandingForm({ {canCss ? ( - `; + }, [css, accentColor, dark, labels]); + + return ( +