Skip to content
Back to skills

Dialkit

ASecurity

Add DialKit floating control panel for tuning animations and visual properties. Use when the user explicitly asks for DialKit, live dials, sliders, spring controls, or runtime visual tuning.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 16, 2026
developmentjavascriptjavashellbashreactvuenextjsnodespringgit

Works with

  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 16, 2026

npx -y skills add tommylower/cortex --skill dialkit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dialkit?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dialkit
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tommylower-dialkit/badge)](https://www.skillsdirectory.com/skills/tommylower-dialkit)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dialkit
description: Add DialKit floating control panel for tuning animations and visual properties. Use when the user explicitly asks for DialKit, live dials, sliders, spring controls, or runtime visual tuning.
author: Josh Puckett (https://github.com/joshpuckett/dialkit)
---

# DialKit

DialKit is a development-only floating control panel for React: sliders,
toggles, color pickers, spring and easing editors, and a timeline, wired to
live UI values. Verified against **dialkit 2.0.2** (2026-09-22).

If `../dev-overlays.md` exists, read the shared dev-overlay rules there first.

## Install

Install as dev dependencies, with the repo's own package manager:

```bash
npm install -D dialkit motion     # or: bun add -d dialkit motion
```

`motion` is a peer dependency (`>=11.0.0`). Non-React peers (`solid-js`,
`svelte`, `vue`, `motion-v`) are declared but only matter for those subpath
entries; npm will not ask for them in a React project.

## Setup (Next.js App Router)

Two files, so neither the panel's JavaScript nor its stylesheet reaches a
production bundle. A static `import "dialkit/styles.css"` is **not** removed by
a `NODE_ENV` guard, so it has to live behind the dynamic import.

`components/dev-tools-panel.tsx` — the dynamic half:

```tsx
"use client";

import "dialkit/styles.css";
import { DialRoot } from "dialkit";

export default function DevToolsPanel() {
  return <DialRoot position="bottom-right" theme="light" />;
}
```

`components/dev-tools.tsx` — the guard:

```tsx
"use client";

import dynamic from "next/dynamic";

const DevToolsPanel = dynamic(() => import("@/components/dev-tools-panel"), {
  ssr: false,
});

export function DevTools() {
  if (process.env.NODE_ENV !== "development") return null;
  return <DevToolsPanel />;
}
```

Mount `<DevTools />` as a sibling of `{children}` in the app shell. The chunk is
still emitted by `next build`; no prerendered page references it, so a visitor
never downloads it.

### `DialRoot` props

`position` (`top-right` | `top-left` | `bottom-right` | `bottom-left`),
`defaultOpen`, `mode` (`popover` | `inline`), `theme` (`light` | `dark` |
`system`), `productionEnabled` (default false), `onOpenChange`.

## Usage

```tsx
import { useDialKit } from "dialkit";

const params = useDialKit("Card", {
  blur: [24, 0, 100],
  opacity: [0.8, 0, 1],
  scale: 1.18,
  color: "#ff5500",
  visible: true,
  spring: { type: "spring", visualDuration: 0.3, bounce: 0.2 },
});
```

`useDialKit(name, config, options?)` returns the resolved values.
`useDialKitController(name, config, options?)` returns a controller when you
need to write values back. `useDialTimeline` + `<DialTimeline />` (export
`dialkit/timeline`) drive a scrubbable timeline; `DialStore` (`dialkit/store`)
is the imperative store. Other frameworks: `createDialKit` from
`dialkit/solid`, `dialkit/svelte`, or `useDialKit` from `dialkit/vue`. A
framework-free build lives at `dialkit/vanilla`.

## Config types

- `[default, min, max, step?]` → slider
- `number` → auto-range slider
- `boolean` → toggle
- `"#hex"` → color picker
- `"text"` → text input
- `{ type: "select", ... }` → dropdown
- `{ type: "spring", ... }` → spring editor
- `{ type: "easing", ... }` → easing editor
- `{ type: "action" }` → button trigger
- `{ type: "image", ... }` → image picker
- `{ nested: ... }` → collapsible folder

Also available as standalone components: `Slider`, `Toggle`, `Folder`,
`ButtonGroup`, `SpringControl`, `TransitionControl`, `TextControl`,
`SelectControl`, `ColorControl`, `ImageControl`, `DialPad`, `PresetManager`,
`ShortcutsMenu`.

## Scoping dials to one component (token-driven codebases)

In a codebase where components style themselves through token variables
(`px-(--space-inset)`, `rounded-card`, `bg-paper-light`), dialling the tokens at
`:root` repaints the whole site — one slider, everything moves. That is almost
never what the operator wants.

Scope instead by rebinding the variables on the component's own root:

1. Stamp each component root with `data-dial="<id>"` (inert: no import, no hook,
   no bundle weight). A generator script can do this and emit a registry of
   which token variables each component actually consumes — that set is its
   knobs.
2. Give the panel a `select` of components plus the selected one's knobs.
3. Write one `<style>` element: `[data-dial="path-card"] { --space-inset: 2rem }`.
   CSS custom properties inherit, so the rebinding reaches that subtree only.

This keeps `useDialKit` out of product files entirely, so there is no hook code
to strip afterwards. Two limits worth stating up front: a descendant that reads
the same variable moves with its parent, and the trick cannot separate two uses
of one role inside a single component (a `sand` border and a `sand` rule move
together) — that needs a real prop.

For colors, prefer a **role swap** (`--color-sand: var(--color-slate-light)`)
over a free color picker: it keeps the palette closed and sidesteps hex literals
in files a tokens-only gate scans.

## Notes

- Use during polish: animation, spring, spacing, shadow, and color tuning.
- After tuning, hardcode the final values as defaults.
- Dial config can stay for future passes as long as it remains dev-only.
- A tokens-only prebuild gate will reject a raw hex in a dial config. Keep color
  dials out of gated files, or grandfather the file.
- Works alongside Agentation and Interface Kit in `DevTools.tsx`.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.