Skip to component content
Layout019 / 155

ViewThatFits

Select a compact or expanded composition at container breakpoints.

Example
12 projects
Projects12 projects · sorted by date
12 projects
Projects12 projects · sorted by date
Source
ViewThatFits.tsxtsx
import { useState } from "react";
import { Badge, Grid, HStack, Picker, Text, ViewFrame, ViewThatFits, VStack } from "@/ohmygui";

const variants = [
  <Badge key="compact">12 projects</Badge>,
  <HStack key="expanded" gap="sm" align="center">
    <Badge variant="accent">Projects</Badge>
    <Text>12 projects · sorted by date</Text>
  </HStack>,
];

export default function Example() {
  const [mode, setMode] = useState<"container" | "viewport">("container");
  const [threshold, setThreshold] = useState("360");

  return (
    <VStack gap="md" align="stretch">
      <Grid columns="auto" minColumnWidth={180} gap="sm">
        <Picker label="Measure against" value={mode} onChange={(event) => setMode(event.currentTarget.value as typeof mode)} items={[{ value: "container", label: "Each container" }, { value: "viewport", label: "Browser viewport" }]} />
        <Picker label="Expansion threshold" value={threshold} onChange={(event) => setThreshold(event.currentTarget.value)} items={[{ value: "320", label: "320 px" }, { value: "360", label: "360 px" }, { value: "480", label: "480 px" }]} />
      </Grid>
      <Text variant="metadata" color="muted">{mode === "container" ? "The wider frame expands independently; the narrow frame stays compact." : "Both frames follow the browser width. Resize the page to cross the threshold."}</Text>
      <HStack gap="md" align="start" wrap>
        {[{ label: "Narrow · 260 px", width: 260 }, { label: "Wide · 440 px", width: 440 }].map(({ label, width }) => (
          <VStack key={label} gap="xs" align="stretch">
            <Text variant="metadata" color="muted">{label}</Text>
            <ViewFrame width={width} max="100%">
              <ViewThatFits breakpointPolicy={{ mode, thresholds: [threshold] }} variants={variants} />
            </ViewFrame>
          </VStack>
        ))}
      </HStack>
    </VStack>
  );
}