Curves

PreviousNext

A tone-curve editor with draggable points and per-channel splines.

<script setup lang="ts">
import type { CurvePoint } from '@/components/ui/curves'
import { ref } from 'vue'
import { Curves } from '@/components/ui/curves'

const points = ref<CurvePoint[]>([
  { x: 0, y: 0 },
  { x: 0.25, y: 0.7 },
  { x: 0.5, y: 0.4 },
  { x: 1, y: 1 },
])
</script>

<template>
  <Curves v-model="points" class="max-w-xs" />
</template>

Installation

pnpm dlx hui-kit@latest add curves

Usage

<script setup lang="ts">
import { ref } from 'vue'
import { Curves, type CurvePoint } from '@/components/ui/curves'

const points = ref<CurvePoint[]>([
  { x: 0, y: 0 },
  { x: 0.5, y: 0.5 },
  { x: 1, y: 1 },
])
</script>

<template>
  <Curves v-model="points" class="max-w-xs" />
</template>

v-model holds the points of the currently active channel as normalized { x, y } pairs in 0..1. The component keeps a separate curve per channel (RGB, R, G, B); switching tabs emits that channel's points.

Interactions

  • Click near the curve inserts a point at that spot and starts dragging it.
  • Drag moves a point; interior points are constrained between their neighbors so the curve stays a function of x, and the endpoints keep their positions on the left and right edges.
  • Double-click removes an interior point (endpoints are pinned).
  • Backspace / Delete removes the focused point from the keyboard.
  • Reset returns the active channel to the straight identity line.

The spline through the points is a monotone cubic (Fritsch–Carlson), so the curve never overshoots between samples.

Channels

Each channel has an accent color resolved from semantic theme tokens — foreground for RGB, destructive for R, and chart tokens for G/B — so the editor adapts to any theme.