Skip to content
Conduit

skill

delete-icon-motion

Upgrade a static Delete button into a polished semantic sweep-into-bin motion for React, Vue, and Web Components.

youwenjiujiu/delete-icon-motioncommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/youwenjiujiu/delete-icon-motion itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 23, 2026

delete-icon-motion

Generate and integrate a polished semantic Delete button motion — the trash lid lifts and hovers level, a broom winds up and sweeps the "Delete" label away letter-by-letter, debris arcs into the open bin mouth, the returning stroke reveals "Done", and the lid drops shut with a settle bounce. The loop is seam-free.

License: Apache-2.0 Agent Skills

No Figma. No Lottie. No runtime dependency in the Web Component core. Pure CSS keyframes + SVG in a Shadow DOM custom element.

→ Open the interactive demo

What it does

delete-icon-motion is an Agent Skill for upgrading an existing static Delete button into a full delete narrative. It can:

  • replace the button's visual with the animated control while preserving the real <button>, its click handler, focus behavior, and accessible name;
  • integrate into React, Next.js, Vue, or Nuxt via thin wrappers, or any other frontend via the framework-neutral Web Component;
  • play once per activation (restart()), firing motion-complete when the real delete should run;
  • re-brand through attributes only — accent, label, result-label, duration — no CSS surgery;
  • respect prefers-reduced-motion by holding the resting sealed-bin icon;
  • stay SSR-safe (the ES module registers the element only in a browser).

The skill is intentionally Delete-only. Home, Search, and unrelated icon meanings are outside its scope.

Quick start

Claude Code

git clone https://github.com/youwenjiujiu/delete-icon-motion.git ~/.claude/skills/delete-motion

Then ask naturally — "give this delete button the delete motion" — or invoke /delete-motion.

Codex

git clone https://github.com/youwenjiujiu/delete-icon-motion.git ~/.agents/skills/delete-icon-motion
$delete-icon-motion Upgrade the static Delete button in this React app.

Direct integration

Web Component (any framework)

import "./icon-motion/web-component/icon-motion.js";
<button type="button" aria-label="Delete" id="del"
        style="position:relative;width:202px;height:62px">
  <icon-motion id="delMotion" accent="#CC0033" label="Delete" result-label="Done"
    autoplay="false" loop="false" presentation="inline" aria-hidden="true"
    style="position:absolute;inset:0;overflow:visible"></icon-motion>
</button>
<script>
  del.addEventListener("click", () => delMotion.restart());
  delMotion.addEventListener("motion-complete", () => {/* real delete */});
</script>

React

import { useRef } from "react";
import { IconMotion } from "./icon-motion/react/IconMotion.js";

export function DeleteButton({ onDelete }) {
  const motion = useRef(null);
  return (
    <button type="button" aria-label="Delete"
      onClick={() => motion.current?.restart()}
      style={{ position: "relative", width: 202, height: 62 }}>
      <IconMotion ref={motion} accent="#CC0033" label="Delete" result-label="Done"
        autoplay={false} loop={false} presentation="inline" aria-hidden="true"
        onMotionComplete={onDelete}
        style={{ position: "absolute", inset: 0, overflow: "visible" }} />
    </button>
  );
}

Vue 3

<script setup>
import { ref } from "vue";
import { IconMotion } from "./icon-motion/vue/IconMotion.js";
const motion = ref(null);
const emit = defineEmits(["delete"]);
</script>

<template>
  <button type="button" aria-label="Delete" @click="motion?.restart()">
    <IconMotion ref="motion" accent="#CC0033" label="Delete" result-label="Done"
      :autoplay="false" :loop="false" presentation="inline" aria-hidden="true"
      @motion-complete="emit('delete')" />
  </button>
</template>

Runtime API

KindNames
Attributesaccent light background bar foreground muted shadow label result-label duration autoplay loop paused presentation
Methodsplay() pause() restart() seek(ms) setProgress(0..1)
Eventsmotion-ready motion-play motion-pause motion-seek motion-loop motion-complete

Booleans must be set explicitly when false: autoplay="false". The control's design aspect is 300 : 92 (≈ 202 × 62 px slot). duration rescales the whole timeline (default 4180 ms) — every beat is percentage-based, so rescaling is safe.

"Done" shows during 72–93 % of the timeline. A non-looping run intentionally ends back at the resting "Delete" state (the loop is seam-free); to hold on "Done", call setProgress(0.8); pause() inside motion-complete.

Motion design notes

  • Anticipation → stroke → follow-through: the broom winds back before the sweep, accelerates through the text, and lifts to the bin mouth to empty the debris.
  • Contact-coupled erase: the label starts disappearing exactly when the broom foot reaches its last letter, and the erase edge tracks the foot — no independent timelines.
  • Seam-free loop: surface tint, both labels, lid, and broom all resolve to the 0 % pose by 100 %.
  • Do not edit the keyframes' transform-origin values. They are pre-converted for transform-box: fill-box (bounding-box-relative): broom pivot 17px 58px, lid pivot 12.6px 10.2px. The lid's closed pose carries a constant +7° corrective rotation compensating the artwork's own tilt.

License

Apache-2.0

↑↓ navigate openesc close