> ## 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

> Cambia el tamaño de un panel mediante arrastre con el puntero o controles de teclado.

## Resumen

`ResizeHandle` gestiona un tamaño numérico y expone un separador que puede recibir el foco. La aplicación aplica ese tamaño al panel; el controlador no cambia automáticamente el tamaño de otro elemento.

**Light**

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

**Dark**

[Ejemplo de 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)

## "Uso"

Usa `edge` para un límite de panel, o `axis="y"` para el cambio de tamaño de altura en línea y `axis="x"` para el cambio de tamaño de anchura en línea. Asigna al controlador un nombre accesible específico y usa `aria-controls` para identificar el panel.

```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>
  );
};
```

El controlador posee su valor. `onValueChange` copia el tamaño más reciente al diseño del panel sin controlar el controlador. `defaultValue` solo establece el tamaño inicial.

## Estado controlado

```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>
  );
};
```

La aplicación posee el valor y puede actualizarlo desde otros controles. Refleje los cambios en tiempo real en `value`; use `onValueCommitted` para guardar el tamaño final. Mantenga `value` y `defaultValue` separados y conserve el mismo modo de propiedad durante toda la vida útil del componente.

## Bordes y espacios entre paneles

`edge="left"`, `"right"`, `"top"` o `"bottom"` determina tanto el eje como la dirección física de aumento. El movimiento hacia la izquierda aumenta un borde izquierdo, el movimiento hacia arriba aumenta un borde superior, y lo contrario se aplica a los bordes derecho e inferior. Este comportamiento se mantiene igual en contenido de derecha a izquierda. Use `edge` o bien `axis` y `direction`.

Con `edge`, la ubicación predeterminada es `"edge"`. Coloque el controlador dentro de un panel con `position: 'relative'` para situarlo a lo largo de ese límite. `placement="inline"` lo mantiene en el flujo normal. Use `placement="gap"` entre paneles hermanos y establezca su ancho o altura mediante `style` cuando el diseño necesite un espacio. Los controladores de espacio no tienen un agarre visible de forma predeterminada.

```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**

[Ejemplo de borde de panel con ResizeHandle (light)](https://storybook.twenty.com/iframe.html?id=ui-layout-resizehandle-panels--documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Ejemplo de borde de panel con 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**

[Ejemplo de espacio de panel de ResizeHandle (light)](https://storybook.twenty.com/iframe.html?id=ui-layout-resizehandle-panels--gap\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Ejemplo de espacio de panel de 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)

La aplicación controla el diseño, el tamaño guardado, el estado contraído y el destino del foco cuando al contraer se elimina el controlador. Use `onActivate` para una acción opcional de contraer.

## Teclado y límites

Para `axis="y"`, Abajo aumenta el tamaño y Arriba lo disminuye. Para `axis="x"`, Derecha aumenta e Izquierda disminuye en contenido de izquierda a derecha; las direcciones se invierten con [DirectionProvider](https://docs.twenty.com/es/ui/primitives/layout/direction-provider.md) con `direction="rtl"`.

Las teclas de flecha usan `step`, cuyo valor predeterminado es `10`. Inicio se mueve a `min` y Fin se mueve a `max`. Se ignoran las teclas pulsadas con Alt, Control o Meta. El arrastre con el puntero usa el movimiento en píxeles y no se ajusta a `step`. Ambas interacciones se mantienen dentro de los límites. Las pulsaciones del puntero no mueven el foco; los usuarios de teclado llegan al controlador con Tab. `disabled` impide cambiar el tamaño y elimina el controlador del orden de tabulación.

La orientación del separador describe el borde divisorio: horizontal para cambiar el tamaño de la altura y vertical para cambiar el tamaño del ancho.

## Direcciones físicas y zoom

Establezca `direction="normal"` o `direction="reverse"` cuando el aumento de tamaño deba seguir una dirección física fija, independientemente de la dirección del texto. Normal aumenta con el movimiento hacia la derecha o hacia abajo. Inverso aumenta con el movimiento hacia la izquierda o hacia arriba. Omita `direction` para conservar el comportamiento de dirección del texto descrito anteriormente.

`scale` acepta un factor de zoom positivo o una función que devuelva uno. El controlador lo toma al presionar el puntero y divide el movimiento del puntero por ese valor. Los pasos del teclado permanecen sin cambios.

## Ciclo de vida del gesto

`onValueChange` informa de valores en tiempo real. `onValueCommitted` informa del valor final después de un arrastre exitoso con el puntero o un cambio efectivo con el teclado. Las teclas Inicio, Fin y de flecha confirman inmediatamente cuando cambian el tamaño.

`onResizeStart` recibe el primer candidato dentro de los límites después de que el puntero supera `dragThreshold`. El umbral predeterminado es `5` con `edge` y `0` en caso contrario, medido en píxeles físicos. `onResizeEnd` recibe `{ cancelled, value }` para un arrastre iniciado. Escape, la cancelación del puntero, la pérdida de captura del puntero y el desmontaje cancelan el gesto sin confirmar; deshabilitar el controlador lo cancela en su siguiente evento de puntero. La cancelación llama a `onValueChange` con el valor inicial, limitado a los límites actuales. `onResizeEnd` recibe ese valor restaurado.

Proporcione `onActivate` para gestionar un clic sin arrastrar, Intro o Espacio. Superar el umbral evita que el siguiente clic del puntero se active, incluso cuando el puntero vuelve a su posición inicial.

Los controladores nativos se ejecutan antes de la interacción del controlador. Llamar a `preventDefault()` en `onPointerDown` o `onKeyDown` omite esa interacción. Evitar `onPointerMove` omite solo esa actualización y mantiene activo el gesto. Evitar `onPointerUp` cancela el arrastre, restaura el valor limitado inicial y omite `onValueCommitted`. La cancelación del puntero y la pérdida de captura siguen finalizando el gesto.

## Controlador personalizado

`ref`, los atributos nativos, `className`, `style` y los controladores de eventos nativos se dirigen al elemento raíz del separador, un `div` de forma predeterminada. El `ref` no se dirige al panel redimensionado ni al tirador visible.

`children` reemplaza el agarre visible y `children={null}` lo oculta; no reemplaza el comportamiento del separador. `render` puede reemplazar el elemento raíz y el `ref` se dirige entonces a ese reemplazo. Los contenedores personalizados deben [reenviar las props y la ref proporcionadas](https://docs.twenty.com/es/ui/primitives/overview#custom-components) para que el foco, la captura del puntero, los controladores de teclado y los atributos de accesibilidad lleguen al mismo elemento.

## "Props"

**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.