Skip to main content

Visual Templates

SchemaForms Data ships with 20+ ready-made visual templates. You can use one as-is, override CSS variables, or register a completely new theme.

Available templates

IDStyleNavigation
modernoCard, normal spacingWizard
minimalistaFlat, relaxed spacingWizard
cardCard, normalWizard
bannerBordered, tabsTabs
acampamentoGlassmorphism, labelled iconsWizard
acampamento_imersivoImmersive glassmorphismWizard
corporativoBordered, formalWizard
festivalVibrant glassmorphismWizard
webinarCompact cardTabs
retiroRelaxed cardWizard
conferenciaProfessional cardWizard
socialFriendly cardWizard
workshopBordered, verticalVertical
galaElegant glassmorphismWizard
acaoCompact cardWizard
podcastModern cardWizard
classicoClassic cardWizard
comunitarioRelaxed cardWizard
noturnoDark glassmorphismWizard

Applying a template

Pass the template ID to FormRenderer:

<FormRenderer schema={schema} template="acampamento" onComplete={handler} />

Or use TemplateProvider directly to wrap a component:

import { TemplateProvider } from "@schema-forms-data/templates";

<TemplateProvider templateId="noturno">
<FormRenderer schema={schema} onComplete={handler} />
</TemplateProvider>;

CSS Variables

Each template injects the following CSS variables on the form wrapper:

VariableDescription
--t-primaryPrimary colour (buttons, accents)
--t-primary-hoverPrimary colour on hover
--t-accentAccent colour
--t-bgForm background colour
--t-surfaceCard/container background colour
--t-textMain text colour
--t-text-mutedSecondary text colour (labels, hints)
--t-borderBorder colour
--t-errorError colour

Registering a custom template

import { registerTemplate } from "@schema-forms-data/templates";
import type { FormTemplateConfig } from "@schema-forms-data/core";

// Call once at application startup
registerTemplate({
id: "my-brand",
displayName: "My Brand",
colors: {
primary: "#7c3aed",
primaryHover: "#6d28d9",
accent: "#a78bfa",
background: "#faf5ff",
surface: "#ffffff",
text: "#1e1b4b",
textMuted: "#6b7280",
border: "#ddd6fe",
error: "#dc2626",
},
layout: {
stepNavigation: "wizard",
containerStyle: "card",
spacing: "normal",
roundness: "lg",
showProgressBar: true,
showStepIndicators: true,
stepIndicatorVariant: "numbers",
stepIndicatorPosition: "top-center",
},
typography: {
fontFamily: '"Nunito", sans-serif',
stepTitleClass: "text-2xl font-bold",
stepDescClass: "text-base text-muted",
labelClass: "text-sm font-medium",
},
wrapperClass: "my-brand-wrapper",
});

Then use it in any FormRenderer:

<FormRenderer schema={schema} template="my-brand" onComplete={handler} />

Querying available templates

import {
getAllTemplates,
getTemplateConfig,
} from "@schema-forms-data/templates";

// List all templates
const all = getAllTemplates();
// [{ id: 'moderno', displayName: 'Moderno', ... }, ...]

// Get a specific template (with fallback to 'moderno')
const config = getTemplateConfig("corporativo");

Using the template context in a component

import { useTemplate } from "@schema-forms-data/templates";

function StyledButton() {
const template = useTemplate();

return (
<button
style={{
backgroundColor: template.colors.primary,
color: "#fff",
borderRadius: "8px",
}}
>
Next
</button>
);
}

FormTemplateConfig (complete type)

interface FormTemplateConfig {
id: string;
displayName: string;
colors: FormTemplateColors;
layout: FormTemplateLayout;
typography?: FormTemplateTypography;
wrapperClass?: string;
}

interface FormTemplateColors {
primary: string;
primaryHover: string;
accent: string;
background: string;
surface: string;
text: string;
textMuted: string;
border: string;
error: string;
}

interface FormTemplateLayout {
stepNavigation: "wizard" | "tabs" | "vertical";
containerStyle: "card" | "glassmorphism" | "flat" | "bordered";
spacing: "compact" | "normal" | "relaxed";
roundness: string;
showProgressBar: boolean;
showStepIndicators: boolean;
stepIndicatorVariant?: "numbers" | "icons" | "icons-labeled";
stepIndicatorPosition?: "top-center" | "top-left";
stepIndicatorOrientation?: "horizontal" | "vertical";
eventTitleStyle?: "bar" | "inline" | "hidden";
}

Template in the builder

The BuilderWrapper also accepts a template prop so the canvas preview matches what the end user will see:

<BuilderWrapper template="my-brand" schema={schema} onSave={handleSave}>
<Canvas />
</BuilderWrapper>

| card | Card, normal | Wizard | | banner | Bordas, tabs | Tabs | | acampamento | Glassmorphism, ícones com label | Wizard | | acampamento_imersivo | Glassmorphism imersivo | Wizard | | corporativo | Bordas, formal | Wizard | | festival | Glassmorphism vibrante | Wizard | | webinar | Card compacto | Tabs | | retiro | Card relaxado | Wizard | | conferencia | Card profissional | Wizard | | social | Card amigável | Wizard | | workshop | Bordas, vertical | Vertical | | gala | Glassmorphism elegante | Wizard | | acao | Card compacto | Wizard | | podcast | Card moderno | Wizard | | classico | Card clássico | Wizard | | comunitario | Card relaxado | Wizard | | noturno | Glassmorphism escuro | Wizard |

Aplicar um template

Passe o ID do template para o FormRenderer:

<FormRenderer schema={schema} template="acampamento" onComplete={handler} />

Ou use o TemplateProvider diretamente para envolver um componente:

import { TemplateProvider } from "@schema-forms-data/templates";

<TemplateProvider templateId="noturno">
<FormRenderer schema={schema} onComplete={handler} />
</TemplateProvider>;

CSS Variables

Cada template injeta as seguintes variáveis CSS no wrapper do formulário:

VariávelDescrição
--t-primaryCor primária (botões, acentos)
--t-primary-hoverCor primária ao hover
--t-accentCor de destaque
--t-bgCor de fundo do formulário
--t-surfaceCor de fundo dos cards/containers
--t-textCor do texto principal
--t-text-mutedCor do texto secundário (labels, hints)
--t-borderCor das bordas
--t-errorCor de erros

Registrar um template customizado

import { registerTemplate } from "@schema-forms-data/templates";
import type { FormTemplateConfig } from "@schema-forms-data/core";

// Chamar uma vez no início da aplicação
registerTemplate({
id: "minha-marca",
displayName: "Minha Marca",
colors: {
primary: "#7c3aed",
primaryHover: "#6d28d9",
accent: "#a78bfa",
background: "#faf5ff",
surface: "#ffffff",
text: "#1e1b4b",
textMuted: "#6b7280",
border: "#ddd6fe",
error: "#dc2626",
},
layout: {
stepNavigation: "wizard",
containerStyle: "card",
spacing: "normal",
roundness: "lg",
showProgressBar: true,
showStepIndicators: true,
stepIndicatorVariant: "numbers",
stepIndicatorPosition: "top-center",
},
typography: {
fontFamily: '"Nunito", sans-serif',
stepTitleClass: "text-2xl font-bold",
stepDescClass: "text-base text-muted",
labelClass: "text-sm font-medium",
},
wrapperClass: "minha-marca-wrapper",
});

Depois use em qualquer FormRenderer:

<FormRenderer schema={schema} template="minha-marca" onComplete={handler} />

Consultar templates disponíveis

import {
getAllTemplates,
getTemplateConfig,
} from "@schema-forms-data/templates";

// Listar todos os templates
const todos = getAllTemplates();
// [{ id: 'moderno', displayName: 'Moderno', ... }, ...]

// Buscar um template específico (com fallback para 'moderno')
const config = getTemplateConfig("corporativo");

Usar o contexto de template num componente

import { useTemplate } from "@schema-forms-data/templates";

function BotaoEstilizado() {
const template = useTemplate();

return (
<button
style={{
backgroundColor: template.colors.primary,
color: "#fff",
borderRadius: "8px",
}}
>
Avançar
</button>
);
}

FormTemplateConfig (tipo completo)

interface FormTemplateConfig {
id: string;
displayName: string;
colors: FormTemplateColors;
layout: FormTemplateLayout;
typography?: FormTemplateTypography;
wrapperClass?: string;
}

interface FormTemplateColors {
primary: string;
primaryHover: string;
accent: string;
background: string;
surface: string;
text: string;
textMuted: string;
border: string;
error: string;
}

interface FormTemplateLayout {
stepNavigation: "wizard" | "tabs" | "vertical";
containerStyle: "card" | "glassmorphism" | "flat" | "bordered";
spacing: "compact" | "normal" | "relaxed";
roundness: string;
showProgressBar: boolean;
showStepIndicators: boolean;
stepIndicatorVariant?: "numbers" | "icons" | "icons-labeled";
stepIndicatorPosition?: "top-center" | "top-left";
stepIndicatorOrientation?: "horizontal" | "vertical";
eventTitleStyle?: "bar" | "inline" | "hidden";
}
// Depois use o template registrado:
<FormRenderer schema={schema} templateKey="brand" onComplete={handler} />

Custom Field Components

For deeper customization, you can swap out individual field renderers:

import { registerFieldRenderer } from "@schema-forms-data/renderer";
import { FieldType } from "@schema-forms-data/core";

// Replace the default TEXT renderer with your own
registerFieldRenderer(FieldType.TEXT, ({ field, value, onChange, error }) => (
<div className="my-text-field">
<label>{field.label}</label>
<input
value={value ?? ""}
onChange={(e) => onChange(e.target.value)}
className={error ? "error" : ""}
/>
{error && <span className="error-msg">{error}</span>}
</div>
));

Template in the Builder

The BuilderProvider also accepts a templateKey prop, so the canvas preview matches what the end user will see:

<BuilderProvider templateKey="brand" ...>
<Canvas />
</BuilderProvider>