Behavior143 / 155
ScrollTargetBehavior
Snap a horizontal strip of cards into alignment.
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>
);
}