Skip to component content
Behavior143 / 155

ScrollTargetBehavior

Snap a horizontal strip of cards into alignment.

Example
Planned3 projects
In progress2 projects
Review4 projects
Published12 projects
Source
ScrollTargetBehavior.tsxtsx
import { useState } from "react";
import { Grid, GroupBox, Picker, ScrollTargetBehavior, Text, ViewFrame, VStack } from "@/ohmygui";

export default function Example() {
  const [snap, setSnap] = useState<"mandatory" | "proximity" | "none">("mandatory");
  const [align, setAlign] = useState<"start" | "center" | "end">("start");

  return (
    <VStack gap="md" align="stretch">
      <Grid columns="auto" minColumnWidth={180} gap="sm">
        <Picker label="Snap strength" value={snap} onChange={(event) => setSnap(event.currentTarget.value as typeof snap)} items={["none", "proximity", "mandatory"].map((value) => ({ value, label: value }))} />
        <Picker label="Target alignment" value={align} onChange={(event) => setAlign(event.currentTarget.value as typeof align)} items={["start", "center", "end"].map((value) => ({ value, label: value }))} />
      </Grid>
      <ScrollTargetBehavior snap={snap} align={align} tabIndex={0} aria-label="Project stages">
        {[
          { name: "Planned", detail: "3 projects" },
          { name: "In progress", detail: "2 projects" },
          { name: "Review", detail: "4 projects" },
          { name: "Published", detail: "12 projects" },
        ].map(({ name, detail }) => (
          <ViewFrame key={name} width={180} height={120}>
            <GroupBox title={name}><Text>{detail}</Text></GroupBox>
          </ViewFrame>
        ))}
      </ScrollTargetBehavior>
    </VStack>
  );
}