Curve Editor

Draggable cubic Bézier handles with keyboard and bounded exact coordinate editing.

Edit an easing curve

Expand to edit the curve and its exact coordinates.

ease-in-out

X1 Y1 X2 Y2 ease-in-out

Code

<link
  rel="component"
  href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
  rel="component"
  href="@threadlabs/looma/components/ui-text/ui-text.html"
>
<link
  rel="component"
  href="@threadlabs/looma/components/ui-disclosure/ui-disclosure.html"
>
<link
  rel="component"
  href="@threadlabs/looma/components/ui-curve-editor/ui-curve-editor.html"
>

<ui-stack
  gap="s"
>
  <ui-text
    variant="code"
  >ease-in-out</ui-text>
  <ui-disclosure
    summary="Edit easing curve"
  >
    <ui-curve-editor
      label="Easing curve"
      value="ease-in-out"
      size="sm"
    ></ui-curve-editor>
  </ui-disclosure>
</ui-stack>
<script setup>
  import { UiCurveEditor, UiDisclosure, UiStack, UiText } from "@threadlabs/looma";
</script>

<template>
  <UiStack
    gap="s"
  >
    <UiText
      variant="code"
    >ease-in-out</UiText>
    <UiDisclosure
      summary="Edit easing curve"
    >
      <UiCurveEditor
        label="Easing curve"
        value="ease-in-out"
        size="sm"
      />
    </UiDisclosure>
  </UiStack>
</template>
import { UiCurveEditor, UiDisclosure, UiStack, UiText } from "@threadlabs/looma";

export default function Example() {
  return <UiStack
    gap="s"
  >
    <UiText
      variant="code"
    >ease-in-out</UiText>
    <UiDisclosure
      summary="Edit easing curve"
    >
      <UiCurveEditor
        label="Easing curve"
        value="ease-in-out"
        size="sm"
      />
    </UiDisclosure>
  </UiStack>;
}
/** @jsxImportSource preact */
import { UiCurveEditor, UiDisclosure, UiStack, UiText } from "@threadlabs/looma";

export default function Example() {
  return <UiStack
    gap="s"
  >
    <UiText
      variant="code"
    >ease-in-out</UiText>
    <UiDisclosure
      summary="Edit easing curve"
    >
      <UiCurveEditor
        label="Easing curve"
        value="ease-in-out"
        size="sm"
      />
    </UiDisclosure>
  </UiStack>;
}
<script>
  import { UiCurveEditor, UiDisclosure, UiStack, UiText } from "@threadlabs/looma";
</script>

<UiStack
  gap="s"
>
  <UiText
    variant="code"
  >ease-in-out</UiText>
  <UiDisclosure
    summary="Edit easing curve"
  >
    <UiCurveEditor
      label="Easing curve"
      value="ease-in-out"
      size="sm"
    />
  </UiDisclosure>
</UiStack>
import { Component } from "@angular/core";
import { UiCurveEditor, UiDisclosure, UiStack, UiText } from "@threadlabs/looma";

@Component({
  selector: "example-view",
  standalone: true,
  imports: [UiStack, UiText, UiDisclosure, UiCurveEditor],
  template: `
    <div
      ui-stack
      [gap]="'s'"
    >
      <ng-template
        ui-text
        [variant]="'code'"
      >ease-in-out</ng-template>
      <div
        ui-disclosure
        [summary]="'Edit easing curve'"
      >
        <span
          ui-curve-editor
          [label]="'Easing curve'"
          [value]="'ease-in-out'"
          [size]="'sm'"
        ></span>
      </div>
    </div>
  `,
})
export default class Example {}

Exact and visual editing

Draggable cubic Bézier handles with keyboard and bounded exact coordinate editing.

X1 Y1 X2 Y2 cubic-bezier(0.25, 0.1, 0.25, 1)

Code

<link
  rel="component"
  href="@threadlabs/looma/components/ui-curve-editor/ui-curve-editor.html"
>

<ui-curve-editor
  label="Fellowship office motion"
  value="cubic-bezier(0.25, 0.1, 0.25, 1)"
></ui-curve-editor>
<script setup>
  import { UiCurveEditor } from "@threadlabs/looma";
</script>

<template>
  <UiCurveEditor
    label="Fellowship office motion"
    value="cubic-bezier(0.25, 0.1, 0.25, 1)"
  />
</template>
import { UiCurveEditor } from "@threadlabs/looma";

export default function Example() {
  return <UiCurveEditor
    label="Fellowship office motion"
    value="cubic-bezier(0.25, 0.1, 0.25, 1)"
  />;
}
/** @jsxImportSource preact */
import { UiCurveEditor } from "@threadlabs/looma";

export default function Example() {
  return <UiCurveEditor
    label="Fellowship office motion"
    value="cubic-bezier(0.25, 0.1, 0.25, 1)"
  />;
}
<script>
  import { UiCurveEditor } from "@threadlabs/looma";
</script>

<UiCurveEditor
  label="Fellowship office motion"
  value="cubic-bezier(0.25, 0.1, 0.25, 1)"
/>
import { Component } from "@angular/core";
import { UiCurveEditor } from "@threadlabs/looma";

@Component({
  selector: "example-view",
  standalone: true,
  imports: [UiCurveEditor],
  template: `
    <span
      ui-curve-editor
      [label]="'Fellowship office motion'"
      [value]="'cubic-bezier(0.25, 0.1, 0.25, 1)'"
    ></span>
  `,
})
export default class Example {}

API

Package: @threadlabs/looma · Native root: span

Attributes

NameDescriptionPropertyTypeDefaultAllowed values
disabledPrevents typing, stepping and pointer or keyboard changes while keeping the value visible.disabledbooleanfalse—
labelAccessible name for the editing control.labelstringValue—
sizeShared field and button height.sizekeywordmdsm, md, lg
valueCSS cubic-bezier or a standard easing keyword. X stays within 0–1; Y is bounded to -1–2 for a limited overshoot.valuestringcubic-bezier(0.25, 0.1, 0.25, 1)—

Framework props

NameTypeDefaultAllowed values
disabledbooleanfalse—
labelstringValue—
size"sm" | "md" | "lg"mdsm, md, lg
valuestringcubic-bezier(0.25, 0.1, 0.25, 1)—

Events

NameDetailDescription
cancelobject
  • value: string (required)
Emitted with the declared detail payload.
changeobject
  • value: string (required)
Emitted when a toggleable control changes checked state.
inputobject
  • value: string (required)
Emitted with the declared detail payload.

Slots

No slots.

Design tokens

Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.

Component tokens

No component tokens.

Shared tokens

TokenFallback
--ui-accent-solid—
--ui-border-width—
--ui-control-border—
--ui-control-focusvar(--ui-accent-solid)
--ui-control-min-block-size—
--ui-control-surfacevar(--ui-surface)
--ui-field-radiusvar(--ui-radius-md)
--ui-focus-width—
--ui-font-monomonospace
--ui-font-size-sm—
--ui-radius-md—
--ui-shadow-xs—
--ui-space-1—
--ui-space-2—
--ui-space-3—
--ui-space-4—
--ui-surface—
--ui-surface-raised—
--ui-text-primary—