> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ResizeHandle

> Изменяйте размер панели перетаскиванием указателем или с помощью элементов управления с клавиатуры.

## Обзор

`ResizeHandle` управляет числовым размером и предоставляет фокусируемый разделитель. Приложение применяет этот размер к панели; маркер не изменяет размер другого элемента автоматически.

**Light**

[Пример ResizeHandle (light)](https://storybook.twenty.com/iframe.html?id=ui-layout-resizehandle--display\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Пример ResizeHandle (dark)](https://storybook.twenty.com/iframe.html?id=ui-layout-resizehandle--display\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-layout-resizehandle--display)

## Использование

Используйте `edge` для границы панели или `axis="y"` для изменения высоты во встроенном режиме и `axis="x"` для изменения ширины во встроенном режиме. Задайте маркеру конкретное доступное имя и используйте `aria-controls` для указания панели.

```tsx theme={null}
import { useId, useState } from 'react';
import { ResizeHandle } from 'twenty-ui/primitives/layout';
import { Card } from 'twenty-ui/primitives/surfaces';
import { Text } from 'twenty-ui/primitives/typography';

export const ResizableNotes = () => {
  const panelId = useId();
  const [height, setHeight] = useState(150);

  return (
    <Card.Root style={{ width: 300, maxWidth: '100%' }}>
      <Text
        id={panelId}
        style={{
          height,
          overflow: 'auto',
          padding: 16,
          boxSizing: 'border-box',
        }}
      >
        <Text
          style={{
            color: 'var(--t-font-color-primary)',
            fontWeight: 'var(--t-font-weight-medium)',
          }}
        >
          Record notes
        </Text>
        <Text style={{ marginTop: 8, lineHeight: 1.5 }}>
          Follow up with Morgan about the proposal. Share the revised timeline
          before Friday.
        </Text>
      </Text>
      <Text style={{ padding: 4 }}>
        <ResizeHandle
          axis="y"
          defaultValue={150}
          onValueChange={setHeight}
          min={50}
          max={500}
          aria-label="Resize notes height"
          aria-controls={panelId}
        />
      </Text>
    </Card.Root>
  );
};
```

Ползунок самостоятельно хранит своё значение. `onValueChange` копирует последний размер в компоновку панелей, не управляя ползунком. `defaultValue` задаёт только начальный размер.

## Управляемое состояние

```tsx theme={null}
import { useId, useState } from 'react';
import { ResizeHandle } from 'twenty-ui/primitives/layout';
import { Card } from 'twenty-ui/primitives/surfaces';
import { Text } from 'twenty-ui/primitives/typography';

export const ResizableNotes = () => {
  const panelId = useId();
  const [height, setHeight] = useState(150);

  return (
    <Card.Root style={{ width: 300, maxWidth: '100%' }}>
      <Text
        id={panelId}
        style={{
          height,
          overflow: 'auto',
          padding: 16,
          boxSizing: 'border-box',
        }}
      >
        <Text
          style={{
            color: 'var(--t-font-color-primary)',
            fontWeight: 'var(--t-font-weight-medium)',
          }}
        >
          Record notes
        </Text>
        <Text style={{ marginTop: 8, lineHeight: 1.5 }}>
          Follow up with Morgan about the proposal. Share the revised timeline
          before Friday.
        </Text>
      </Text>
      <Text style={{ padding: 4 }}>
        <ResizeHandle
          axis="y"
          value={height}
          onValueChange={setHeight}
          min={50}
          max={500}
          aria-label="Resize notes height"
          aria-controls={panelId}
        />
      </Text>
    </Card.Root>
  );
};
```

Приложение владеет значением и может обновлять его с помощью других элементов управления. Отражайте текущие изменения в `value`; используйте `onValueCommitted`, чтобы сохранить окончательный размер. Не смешивайте `value` и `defaultValue` и сохраняйте один и тот же режим владения на протяжении всего жизненного цикла компонента.

## Края и промежутки панелей

`edge="left"`, `"right"`, `"top"` или `"bottom"` определяет как ось, так и физическое направление увеличения. Движение влево увеличивает левый край, движение вверх увеличивает верхний край; для правого и нижнего краёв действует обратное правило. Это поведение не меняется в содержимом с направлением справа налево. Используйте либо `edge`, либо `axis` и `direction`.

При использовании `edge` по умолчанию применяется размещение `"edge"`. Поместите ползунок внутрь панели с `position: 'relative'`, чтобы расположить его вдоль этой границы. `placement="inline"` сохраняет его в обычном потоке. Используйте `placement="gap"` между соседними панелями и задайте его ширину или высоту через `style`, если компоновке нужен промежуток. По умолчанию ползунки промежутков не имеют видимой ручки.

```tsx theme={null}
import { useId, useState } from 'react';
import { ResizeHandle } from 'twenty-ui/primitives/layout';
import { Card } from 'twenty-ui/primitives/surfaces';
import { Text } from 'twenty-ui/primitives/typography';

export const ResizableDetails = ({
  saveWidth,
}: {
  saveWidth: (value: number) => void;
}) => {
  const detailsId = useId();
  const [width, setWidth] = useState(380);

  return (
    <div style={{ display: 'flex', height: 200 }}>
      <Card.Root style={{ flex: 1 }}>
        <Text>Activity</Text>
      </Card.Root>
      <ResizeHandle
        edge="left"
        placement="gap"
        value={width}
        onValueChange={setWidth}
        onValueCommitted={saveWidth}
        min={280}
        max={800}
        style={{ width: 12 }}
        aria-label="Resize details"
        aria-controls={detailsId}
      />
      <Card.Root id={detailsId} style={{ width }}>
        <Text>Details</Text>
      </Card.Root>
    </div>
  );
};
```

**Light**

[Пример края панели ResizeHandle (light)](https://storybook.twenty.com/iframe.html?id=ui-layout-resizehandle-panels--documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Пример края панели ResizeHandle (dark)](https://storybook.twenty.com/iframe.html?id=ui-layout-resizehandle-panels--documentation\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-layout-resizehandle-panels--documentation)

**Light**

[Пример промежутка панели ResizeHandle (light)](https://storybook.twenty.com/iframe.html?id=ui-layout-resizehandle-panels--gap\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Пример промежутка панели ResizeHandle (dark)](https://storybook.twenty.com/iframe.html?id=ui-layout-resizehandle-panels--gap\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-layout-resizehandle-panels--gap)

Приложение управляет макетом, сохранённым размером, состоянием сворачивания и местом назначения фокуса, когда при сворачивании удаляется ручка. Используйте `onActivate` для необязательного действия сворачивания.

## Клавиатура и границы

Для `axis="y"` клавиша «Вниз» увеличивает размер, а «Вверх» уменьшает его. Для `axis="x"` Right увеличивает, а Left уменьшает в содержимом с направлением слева направо; направления меняются на противоположные при использовании [DirectionProvider](https://docs.twenty.com/ru/ui/primitives/layout/direction-provider.md) с `direction="rtl"`.

Клавиши со стрелками используют `step`, значение которого по умолчанию — `10`. Home перемещает к `min`, а End — к `max`. Нажатия клавиш с Alt, Control или Meta игнорируются. Перетаскивание указателем использует перемещение в пикселях и не привязано к `step`. Оба взаимодействия не выходят за границы. Нажатия указателем не перемещают фокус; пользователи клавиатуры достигают ручки с помощью Tab. `disabled` предотвращает изменение размера и исключает маркер из порядка навигации по клавише Tab.

Ориентация разделителя описывает разделяющую границу: горизонтальная для изменения высоты и вертикальная для изменения ширины.

## Физические направления и масштабирование

Задайте `direction="normal"` или `direction="reverse"`, когда увеличение размера должно следовать фиксированному физическому направлению независимо от направления текста. Normal увеличивает размер при движении вправо или вниз. Reverse увеличивает размер при движении влево или вверх. Не указывайте `direction`, чтобы сохранить описанное выше поведение, зависящее от направления текста.

`scale` принимает положительный коэффициент масштабирования или функцию, которая его возвращает. Ручка считывает его при нажатии указателя и делит перемещение указателя на это значение. Шаги клавиатуры остаются без изменений.

## Жизненный цикл жеста

`onValueChange` сообщает текущие значения. `onValueCommitted` сообщает окончательное значение после успешного перетаскивания указателем или результативного изменения с клавиатуры. Клавиши Home, End и стрелки немедленно фиксируют значение, когда изменяют размер.

`onResizeStart` получает первого ограниченного кандидата после того, как указатель превысит `dragThreshold`. Порог по умолчанию равен `5` при использовании `edge` и `0` в остальных случаях; он измеряется в физических пикселях. `onResizeEnd` получает `{ cancelled, value }` для начатого перетаскивания. Escape, отмена указателя, потеря захвата указателя и размонтирование отменяют жест без фиксации; отключение ручки отменяет его при следующем событии указателя. При отмене вызывается `onValueChange` с начальным значением, ограниченным текущими границами. `onResizeEnd` получает это восстановленное значение.

Передайте `onActivate` для обработки щелчка без перетаскивания, Enter или Space. Превышение порога предотвращает активацию последующего щелчка указателем, даже если указатель возвращается в начальное положение.

Нативные обработчики выполняются до взаимодействия с маркером. Вызов `preventDefault()` в `onPointerDown` или `onKeyDown` пропускает это взаимодействие. Предотвращение `onPointerMove` пропускает только это обновление и сохраняет жест активным. Предотвращение `onPointerUp` отменяет перетаскивание, восстанавливает исходное ограниченное значение и пропускает `onValueCommitted`. Отмена указателя и потеря захвата по-прежнему завершают жест.

## Пользовательский маркер

`ref`, нативные атрибуты, `className`, `style` и нативные обработчики событий относятся к корневому элементу разделителя, по умолчанию к `div`. Ref не относится к изменяемой по размеру панели или видимому захвату.

`children` заменяет видимый захват, а `children={null}` скрывает его; это не заменяет поведение разделителя. `render` может заменить корневой элемент, и тогда ref относится к этой замене. Пользовательские обёртки должны [передавать предоставленные props и ref](https://docs.twenty.com/ru/ui/primitives/overview#custom-components), чтобы фокус, захват указателя, обработчики клавиатуры и атрибуты доступности достигали того же элемента.

## Свойства

**axis** `"x" | "y"` (default: y without edge)

Pointer movement axis without `edge`: `y` for height or `x` for width.

**defaultValue** `number | (readonly string[] & number)` (default: 150)

Initial size when the handle owns its state.

**direction** `"normal" | "reverse"`

Physical increasing direction. Omit to follow the horizontal text direction; use `normal` or `reverse` for a fixed physical edge.

**disabled** `boolean` (default: false)

Disables resizing and removes the handle from the tab order.

**dragThreshold** `number` (default: 5 with edge; 0 otherwise)

Physical pointer distance required before resizing starts. Movement below the threshold remains a click. Defaults to 5 with `edge` and 0 otherwise.

**edge** `"bottom" | "left" | "right" | "top"`

Physical panel edge. Determines the movement axis and increasing direction, independently of text direction.

**max** `number` (default: 500)

Maximum allowed size.

**min** `number` (default: 50)

Minimum allowed size.

**onActivate** `(() =\> void)`

Called for a click without dragging, Enter, or Space.

**onResizeEnd** `((details: \{ cancelled: boolean; value: number; \}) =\> void)`

Called after a started drag ends, with its final value and whether it was cancelled. Cancellation restores the starting value within the current bounds.

**onResizeStart** `((value: number) =\> void)`

Called once with the first bounded drag value after the threshold is crossed.

**onValueChange** `((value: number) =\> void)`

Called with the bounded size during pointer or keyboard interaction and with the restored value on cancellation.

**onValueCommitted** `((value: number) =\> void)`

Called with the final size after a successful drag or an effective keyboard size change. Cancellation does not commit.

**placement** `"edge" | "gap" | "inline"` (default: edge with edge; inline otherwise)

Layout mode: `inline` stays in normal flow, `edge` positions the handle on the panel edge, and `gap` sits between panels. Defaults to `edge` when `edge` is set and `inline` otherwise.

**render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, \{\}\>`

Allows you to replace the component's HTML element
with a different tag, or compose it with another component.

Accepts a `ReactElement` or a function that returns the element to render.

**scale** `number | (() =\> number)` (default: 1)

Pointer scale or resolver sampled at pointer down. Movement is divided by this positive scale; keyboard steps are unchanged.

**step** `number` (default: 10)

Keyboard arrow increment. Pointer movement uses the pixel delta.

**value** `number`

Current controlled size. Update it in `onValueChange` and apply it to the element being resized.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.