Responsive and dark styles

Author responsive and dark email styles with Tailwind variants while keeping baseline content usable and reviewing compatibility findings.

Tailwind is the styling dialect. The compiler generates the classes a template uses, then inlines them into the markup. hover: and dark: variants stay in a <style> block for the clients that honor them, so they are enhancements over a complete baseline.

Keep base content and layout usable without media rules, and pair foreground and background changes for dark styling:

templates/notice.tsx
import { defineTemplate } from "@samva/markup";
import { Email, Section } from "@samva/markup/email";
import { jsonSchema } from "@samva/markup/input-schema";

export default defineTemplate({
  id: "notice",
  schema: jsonSchema<{ message: string }>({
    type: "object",
    properties: { message: { type: "string" } },
    required: ["message"],
    additionalProperties: false,
  }),
  fixtures: { default: { message: "Your plan renews tomorrow." } },
  email: {
    subject: () => "Notice",
    body: (input) => (
      <Email>
        <Section className="bg-white px-8 py-6 text-gray-900 dark:bg-gray-900 dark:text-white">
          <p className="text-base">{input.message}</p>
        </Section>
      </Email>
    ),
  },
});
  • Class names must be literal so the compiler can see them. className={"text-" + size} fails with dynamic-class. Choose between literal lists with input.vip ? "bg-amber-100" : "bg-white".
  • Theme utilities such as bg-card and text-foreground switch in dark mode through the theme's dark block, so they need no dark: class. Use dark: to pick a different value in dark mode.
  • Inspect declared fixtures in light and dark preview, including long and empty content. samva templates snapshot writes both.
  • Compatibility findings describe known constraints of target clients. A browser preview does not emulate every mail client; use inbox tests for client-specific evidence.

Related documentation