Skip to component content
Layout016 / 155

ScrollViewReader

Move to a chosen child inside a scrollable collection.

Example

Note 1 · Prepare field kit

Note 2 · Review cover

Note 3 · Print test page

Note 4 · Update plant index

Note 5 · Pack samples

Note 6 · Share preview

Source
ScrollViewReader.tsxtsx
import { useState } from "react";
import {
  Button,
  Grid,
  HStack,
  Padding,
  Picker,
  ScrollView,
  ScrollViewReader,
  Text,
  VStack,
  ViewFrame,
} from "@/ohmygui";

const notes = ["Prepare field kit", "Review cover", "Print test page", "Update plant index", "Pack samples", "Share preview"];

export default function Example() {
  const [target, setTarget] = useState<string>();
  const [behavior, setBehavior] = useState<ScrollBehavior>("smooth");
  const [block, setBlock] = useState<ScrollLogicalPosition>("center");
  const [inline, setInline] = useState<ScrollLogicalPosition>("nearest");
  return (
    <VStack gap="md" align="stretch">
      <Grid columns="auto" minColumnWidth={180} gap="sm">
        <Picker label="Scroll behavior" value={behavior} onChange={(event) => setBehavior(event.currentTarget.value as ScrollBehavior)} items={["smooth", "instant", "auto"].map((value) => ({ value, label: value }))} />
        <Picker label="Vertical alignment" value={block} onChange={(event) => setBlock(event.currentTarget.value as ScrollLogicalPosition)} items={["start", "center", "end", "nearest"].map((value) => ({ value, label: value }))} />
        <Picker label="Horizontal alignment" value={inline} onChange={(event) => setInline(event.currentTarget.value as ScrollLogicalPosition)} items={["start", "center", "end", "nearest"].map((value) => ({ value, label: value }))} />
      </Grid>
      <HStack gap="sm" wrap>
        <Button onClick={() => setTarget("reader-note-3")}>Jump to note 3</Button>
        <Button onClick={() => setTarget("reader-note-6")}>Jump to note 6</Button>
      </HStack>
      <ScrollView axis="both" maxWidth={440} maxHeight={180} aria-label="Six field notes with horizontal overflow">
        <ScrollViewReader targetId={target} behavior={behavior} block={block} inline={inline}>
          <ViewFrame width={560}>
            <VStack gap="xs" align="stretch">
              {notes.map((note, index) => (
                <Padding key={note} id={"reader-note-" + (index + 1)} padding="sm">
                  <HStack justify="between" gap="lg"><Text as="p">Note {index + 1} · {note}</Text><Text variant="metadata" color="muted">Field journal</Text></HStack>
                </Padding>
              ))}
            </VStack>
          </ViewFrame>
        </ScrollViewReader>
      </ScrollView>
    </VStack>
  );
}