Options using union

Options using union of literal

Union of Literals

When you create a union of literal values, Val Studio automatically displays it as a dropdown in the editor. This is perfect for fields with a fixed set of options.

Basic Dropdown

Create a dropdown by using `s.union()` with multiple `s.literal()` values:

const buttonSchema = s.object({
  label: s.string(),
  variant: s.union(
    s.literal("primary"),
    s.literal("secondary"),
    s.literal("tertiary")
  ),
  size: s.union(
    s.literal("small"),
    s.literal("medium"),
    s.literal("large")
  ),
});

export default c.define("/content/button.val.ts", buttonSchema, {
  label: "Click me",
  variant: "primary",
  size: "medium",
});

Type Safety

Literal unions provide complete type safety. TypeScript knows exactly which values are valid:

import { t } from "@/val.config";

type ButtonVariant = t.inferSchema<typeof buttonSchema>["variant"];
// Type: "primary" | "secondary" | "tertiary"

function Button({ variant }: { variant: ButtonVariant }) {
  // TypeScript ensures variant is one of the three values
  const className = {
    primary: "bg-blue-500",
    secondary: "bg-gray-500",
    tertiary: "bg-white",
  }[variant];
  
  return <button className={className}>Click me</button>;
}

Common Use Cases

Dropdowns are ideal for:

  • Button variants and sizes

  • Color themes or styles

  • Alignment options (left, center, right)

  • Status values (draft, published, archived)

  • Priority levels (low, medium, high)

Example: Card Component

Here's a complete example of a card component with multiple dropdown options:

const cardSchema = s.object({
  title: s.string(),
  description: s.richtext(),
  variant: s.union(
    s.literal("default"),
    s.literal("bordered"),
    s.literal("elevated")
  ),
  alignment: s.union(
    s.literal("left"),
    s.literal("center"),
    s.literal("right")
  ),
  padding: s.union(
    s.literal("none"),
    s.literal("small"),
    s.literal("medium"),
    s.literal("large")
  ),
});

export default c.define("/content/card.val.ts", cardSchema, {
  title: "Welcome Card",
  description: [
    { tag: "p", children: ["This is a card component"] },
  ],
  variant: "elevated",
  alignment: "center",
  padding: "medium",
});