# or
yarn add @zag-js/scroll-area @zag-js/svelte
```

## Anatomy

To set up the scroll area correctly, you'll need to understand its anatomy and
how we name its parts.

> Each part includes a `data-part` attribute to help identify them in the DOM.



## Required style

It's important to note that the scroll area requires the following styles to be
applied to the viewport element to hide the scrollbar:

```css
[data-scope="scroll-area"][data-part="viewport"] {
  /* hide scrollbar */
  scrollbar-width: none;
  &::-webkit-scrollbar {
    display: none;
  }
}
```

## Usage

First, import the scroll area package into your project

```jsx
import * as scrollArea from "@zag-js/scroll-area"
```

The scroll area package exports two key functions:

- `machine` â The state machine logic for the scroll area widget.
- `connect` â The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll also need to provide a unique `id` to the `useMachine` hook. This is
> used to ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
scroll area machine in your project ð¥

```svelte
<script lang="ts">
  import * as scrollArea from "@zag-js/scroll-area"
  import { useMachine, normalizeProps } from "@zag-js/svelte"

  const id = $props.id()
  const service = useMachine(scrollArea.machine, { id })

  const api = $derived(scrollArea.connect(service, normalizeProps))
</script>

<div {...api.getRootProps()}>
  <div {...api.getViewportProps()}>
    <div {...api.getContentProps()}>
      <!-- Your scrollable content here -->
    </div>
  </div>
  <div {...api.getScrollbarProps()}>
    <div {...api.getThumbProps()} />
  </div>
</div>
```

### Scrolling to edges

You can programmatically scroll to any edge of the scroll area using the
`scrollToEdge` method:

```jsx
// Scroll to bottom
api.scrollToEdge({ edge: "bottom" })

// Scroll to top with custom easing
api.scrollToEdge({
  edge: "top",
  duration: 500,
  easing: (t) => t * t,
})
```

### Scrolling to coordinates

Use the `scrollTo` method to scroll to specific coordinates:

```jsx
// Scroll to specific position
api.scrollTo({
  top: 100,
  left: 50,
})

// Scroll with smooth behavior
api.scrollTo({
  top: 200,
  behavior: "smooth",
  duration: 300,
})
```

### Checking scroll position

The API provides several properties to check the current scroll state:

```jsx
// Check if at edges
console.log(api.isAtTop) // boolean
console.log(api.isAtBottom) // boolean
console.log(api.isAtLeft) // boolean
console.log(api.isAtRight) // boolean

// Check for overflow
console.log(api.hasOverflowX) // boolean
console.log(api.hasOverflowY) // boolean

// Get scroll progress (0-1)
const progress = api.getScrollProgress() // { x: number, y: number }
```

### Conditional scrollbar rendering

Only render scrollbars when there's overflow content:

```jsx
{
  api.hasOverflowY && (
    <div {...api.getScrollbarProps({ orientation: "vertical" })}>
      <div {...api.getThumbProps({ orientation: "vertical" })} />
    </div>
  )
}

{
  api.hasOverflowX && (
    <div {...api.getScrollbarProps({ orientation: "horizontal" })}>
      <div {...api.getThumbProps({ orientation: "horizontal" })} />
    </div>
  )
}
```

### Scrollbar state

Get the current state of a scrollbar for styling purposes:

```jsx
const verticalState = api.getScrollbarState({ orientation: "vertical" })
// Returns: { hovering: boolean, scrolling: boolean, hidden: boolean }
```

### Nested scroll areas

Scroll areas can be nested within each other for complex layouts:

```jsx
<div {...api.getRootProps()}>
  <div {...api.getViewportProps()}>
    <div {...api.getContentProps()}>
      {/* Nested scroll area */}
      <ScrollAreaComponent style={{ maxHeight: 200 }}>
        {/* Inner content */}
      </ScrollAreaComponent>
    </div>
  </div>
</div>
```

## Styling guide

Earlier, we mentioned that each scroll area part has a `data-part` attribute
added to them to select and style them in the DOM.

### Scrolling state

When the user is actively scrolling, a `data-scrolling` attribute is set on the
scrollbar elements:

```css
[data-part="scrollbar"][data-scrolling] {
  /* styles when actively scrolling */
}

[data-part="thumb"][data-scrolling] {
  /* styles for thumb when scrolling */
}
```

### Hover state

When hovering over the scroll area or scrollbar, a `data-hover` attribute is
applied:

```css
[data-part="root"][data-hover] {
  /* styles when hovering over scroll area */
}

[data-part="scrollbar"][data-hover] {
  /* styles when hovering over scrollbar */
}
```

### Hidden state

Scrollbars can be automatically hidden when not needed:

```css
[data-part="scrollbar"][data-hidden] {
  /* styles for hidden scrollbar */
  opacity: 0;
  pointer-events: none;
}
```

### Orientation

Different styles can be applied based on scrollbar orientation:

```css
[data-part="scrollbar"][data-orientation="vertical"] {
  /* vertical scrollbar styles */
}

[data-part="scrollbar"][data-orientation="horizontal"] {
  /* horizontal scrollbar styles */
}
```

## Methods and Properties

The scroll area's `api` exposes the following methods and properties:

### Machine Context

The scroll area machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; viewport: string; content: string; scrollbar: string; thumb: string; }>`
Description: The ids of the scroll area elements

**`dir`**
Type: `"ltr" | "rtl"`
Description: The document's text/writing direction.

**`id`**
Type: `string`
Description: The unique identifier of the machine.

**`getRootNode`**
Type: `() => ShadowRoot | Node | Document`
Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.

### Machine API

The scroll area `api` exposes the following methods:

**`isAtTop`**
Type: `boolean`
Description: Whether the scroll area is at the top

**`isAtBottom`**
Type: `boolean`
Description: Whether the scroll area is at the bottom

**`isAtLeft`**
Type: `boolean`
Description: Whether the scroll area is at the left

**`isAtRight`**
Type: `boolean`
Description: Whether the scroll area is at the right

**`hasOverflowX`**
Type: `boolean`
Description: Whether the scroll area has horizontal overflow

**`hasOverflowY`**
Type: `boolean`
Description: Whether the scroll area has vertical overflow

**`getScrollProgress`**
Type: `() => Point`
Description: Get the scroll progress as values between 0 and 1

**`scrollToEdge`**
Type: `(details: ScrollToEdgeDetails) => void`
Description: Scroll to the edge of the scroll area

**`scrollTo`**
Type: `(details: ScrollToDetails) => void`
Description: Scroll to specific coordinates

**`getScrollbarState`**
Type: `(props: ScrollbarProps) => ScrollbarState`
Description: Returns the state of the scrollbar

### Data Attributes

**`Root`**

**`data-scope`**: scroll-area
**`data-part`**: root
**`data-overflow-x`**: Present when the content overflows the x-axis
**`data-overflow-y`**: Present when the content overflows the y-axis

**`Viewport`**

**`data-scope`**: scroll-area
**`data-part`**: viewport
**`data-at-top`**: Present when scrolled to the top edge
**`data-at-bottom`**: Present when scrolled to the bottom edge
**`data-at-left`**: Present when scrolled to the left edge
**`data-at-right`**: Present when scrolled to the right edge
**`data-overflow-x`**: Present when the content overflows the x-axis
**`data-overflow-y`**: Present when the content overflows the y-axis

**`Content`**

**`data-scope`**: scroll-area
**`data-part`**: content
**`data-overflow-x`**: Present when the content overflows the x-axis
**`data-overflow-y`**: Present when the content overflows the y-axis

**`Scrollbar`**

**`data-scope`**: scroll-area
**`data-part`**: scrollbar
**`data-orientation`**: The orientation of the scrollbar
**`data-scrolling`**: Present when scrolling
**`data-hover`**: Present when hovered
**`data-dragging`**: Present when in the dragging state
**`data-overflow-x`**: Present when the content overflows the x-axis
**`data-overflow-y`**: Present when the content overflows the y-axis

**`Thumb`**

**`data-scope`**: scroll-area
**`data-part`**: thumb
**`data-orientation`**: The orientation of the thumb
**`data-hover`**: Present when hovered
**`data-dragging`**: Present when in the dragging state

**`Corner`**

**`data-scope`**: scroll-area
**`data-part`**: corner
**`data-hover`**: Present when hovered
**`data-state`**: "hidden" | "visible"
**`data-overflow-x`**: Present when the content overflows the x-axis
**`data-overflow-y`**: Present when the content overflows the y-axis

### CSS Variables

<CssVarTable name="scroll-area" />
A Segmented control allows users to make a single selection from multiple
exclusive options, providing a visually distinct and intuitive way of
interacting with radio inputs.

## Resources


[Latest version: v1.33.1](https://www.npmjs.com/package/@zag-js/radio-group)
[Logic Visualizer](https://zag-visualizer.vercel.app/segmented-control)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/segmented-control)



**Features**

- Syncs with `disabled` state of fieldset
- Syncs with form `reset` events
- Can programmatically set segmented control value
- Can programmatically focus and blur segmented control items

## Installation

To use segmented control add the radio machine to your project, run the
following command in your command line:

```bash
npm install @zag-js/radio-group @zag-js/svelte