Communitygithub.com

nehakanjamala/personal_website

This skill should be used when the user asks to "add a hover/press effect", "animate a toggle or switch", "build an animated like button", "make a toast/snackbar slide in", "animate a drawer or modal", "animate list reordering or add/remove", "do a shared-element layout transition", or "polish UI feedback". Covers UI motion with Framer Motion (motion/react) and modern CSS.

personal_website とは?

personal_website is a Claude Code agent skill that this skill should be used when the user asks to "add a hover/press effect", "animate a toggle or switch", "build an animated like button", "make a toast/snackbar slide in", "animate a drawer or modal", "animate list reordering or add/remove", "do a shared-element layout transition", or "polish UI feedback". Covers UI motion with Framer Motion (motion/react) and modern CSS.

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/nehakanjamala/personal_website/tree/HEAD/.agents/skills/micro-interaction

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Micro-interactions (UI Motion)

Small, functional motion that makes an interface feel responsive and alive: hover/press/focus feedback, toggles, toasts, drawers, and list/layout animation. The goal is feedback and continuity, not decoration.

When to use

  • Hover/press/focus feedback; toggles, checkboxes, like/heart buttons
  • Toasts/snackbars, drawers, modals, tooltips, accordions (enter/exit)
  • List add/remove/reorder; shared-element ("magic move") layout transitions
  • Loading → success → error state transitions

Principles (apply to all of it)

  • Duration: UI micro-interactions live in 100–250ms. Anything over ~400ms feels laggy for a click response.
  • Animate transform and opacity only — they are GPU-composited (no layout/paint). Avoid animating width/height/top/left; use scale or layout animation instead.
  • Give instant press feedback: scale: 0.96 on tap with a fast spring.
  • Asymmetric timing: enter slightly slower (ease-out), exit faster (ease-in). Things should arrive gracefully and leave promptly.
  • Respect prefers-reduced-motion: gate non-essential motion; keep opacity changes, drop large movement.
  • Easing defaults: ease-out for entrances cubic-bezier(0.16, 1, 0.3, 1); a tasteful overshoot is cubic-bezier(0.34, 1.56, 0.64, 1); standard move cubic-bezier(0.4, 0, 0.2, 1).

Framer Motion (motion/react) essentials

As of v11+, the package is imported as motion/react (the framer-motion name still works).

Gestures and springs

import { motion } from "motion/react";

<motion.button
  whileHover={{ scale: 1.03 }}
  whileTap={{ scale: 0.96 }}
  whileFocus={{ boxShadow: "0 0 0 3px rgba(59,130,246,.5)" }}
  transition={{ type: "spring", stiffness: 400, damping: 30 }}
/>

Spring intuition: higher stiffness = faster; higher damping = less bounce. stiffness: 400, damping: 30 is a snappy UI default. For visible bounce, lower damping (e.g. damping: 12).

Enter / exit with AnimatePresence

Exit animations require AnimatePresence wrapping conditionally-rendered children, each with a stable key.

import { AnimatePresence, motion } from "motion/react";

<AnimatePresence>
  {open && (
    <motion.div
      key="panel"
      initial={{ opacity: 0, y: 8 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: 8 }}
      transition={{ duration: 0.2, ease: [0.16, 1, 0.3, 1] }}
    />
  )}
</AnimatePresence>

For toasts/lists, use mode="popLayout" so removed items don't hold space while exiting.

Layout animation (the superpower)

layout automatically animates any layout change (position/size) using transforms — perfect for reordering, expanding cards, and grid<->list.

<motion.li layout transition={{ type: "spring", stiffness: 500, damping: 40 }} />

Shared-element transition across components: give two elements the same layoutId and Framer Motion animates between them as one mounts and the other unmounts.

{!open && <motion.div layoutId="card" onClick={() => setOpen(true)} />}
<AnimatePresence>
  {open && <motion.div layoutId="card" />} {/* "magic moves" from the source */}
</AnimatePresence>

Gotcha: a plain layout element distorts border-radius and text during scale. Add layout to direct children that should counter-scale, and prefer borderRadius/boxShadow as motion values, or use layout="position" to animate position only.

Pure CSS path (no JS, including discrete properties)

Modern CSS can animate enter/exit and even display toggles without a library.

.toast {
  transition: opacity 0.2s ease, transform 0.2s ease;
  /* allow animating to/from display:none and from initial render */
  transition-behavior: allow-discrete;
}
.toast[hidden] { display: none; }

/* animate FROM these values on first render / when entering */
@starting-style {
  .toast { opacity: 0; transform: translateY(8px); }
}

@starting-style defines the "before-open" values so an element animates in on first appearance; transition-behavior: allow-discrete lets display (and overlay for popovers/dialogs) participate so exit animations run before the element is removed. Baseline in Chrome/Edge/Safari; provide a no-animation fallback for older browsers.

Always include a reduced-motion guard:

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

State, not just decoration

Loading → success → error should be one continuous motion (e.g. a button morphs spinner → checkmark), not a jump cut. Keep the element mounted and animate between states so the eye tracks the same object.

Deliver & verify (standalone HTML)

Packaged helper (scripts/): scripts/seek-shot.sh anim.html 0 1.5 3 freezes the ?t=N harness and screenshots each moment; scripts/contact-sheet.sh sheet.png frame-*.png tiles them for one-glance review. See scripts/README.md.

For a self-contained interaction demo (toggle, like button, toast, drawer) the deliverable is one HTML file that opens directly in a browser. Pure-CSS interactions ship as-is; for a Framer Motion demo, load React + motion from CDN (esm.sh) into one inline module — no build step. One file is the right tier; don't reach for a bundler.

Output contract:

  • One .html file: your markup plus either CSS transitions/@starting-style or an inline <script type="module"> importing motion from CDN.
  • A way to land on the resolved end state for a screenshot — interactions are state-driven, not time-driven, so freeze the state rather than a clock.

Seek harness — pin a deterministic state. A micro-interaction's "frames" are its states (idle / hover / pressed / open). ?state=open applies the target state on load so a screenshot captures it settled:

<script>
  const s = new URLSearchParams(location.search).get("state");
  if (s) document.documentElement.dataset.state = s;   // CSS keys off [data-state="open"]
  // Framer Motion: set the controlled prop from `s` (e.g. const [open]=useState(s==="open"))
  // For a CSS @keyframes loop instead, freeze it: el.style.animationDelay=(-N)+"s"; el.style.animationPlayState="paused";
  window.__ready = true;
</script>

Verify loop — render → set state → screenshot → check: open each meaningful state (?state=idle, ?state=hover, ?state=open), screenshot, and check fidelity (press feedback reads instant, exit runs before unmount) plus artifacts (layout distorting border-radius/text, toast holding space after exit, FOUC, jank). Any headless tool works:

npx playwright screenshot --wait-for-timeout=400 "file://$PWD/demo.html?state=open" open.png

Before you finish:

  1. Opens standalone — no console errors, CDN React/motion (if used) resolves.
  2. The ?state= (or controlled-prop) freeze lands a deterministic, settled state.
  3. Screenshotted across states — idle / active / open — matches the brief, no artifacts.
  4. prefers-reduced-motion honored — large movement dropped, opacity/feedback kept.
  5. Easing is intentional — enter ease-out, exit ease-in, durations in the 100–250ms band.

Quick reference

NeedApproach
Press feedbackwhileTap={{ scale: 0.96 }} spring 400/30
Enter/exitAnimatePresence + initial/animate/exit
Reorder / resizelayout prop (spring)
Magic moveshared layoutId
Toast stackAnimatePresence mode="popLayout"
No-JS enter@starting-style + transition
Animate to display:nonetransition-behavior: allow-discrete
Accessibilityprefers-reduced-motion guard always

Reference files

  • references/framer-motion-recipes.md — variants + stagger, AnimatePresence modes, layout/layoutId magic move, Reorder drag-to-sort, drag constraints, gesture composition, and useReducedMotion.
  • references/css-recipes.md — @starting-style, transition-behavior: allow-discrete, popover/dialog exit animation, keyframe spinners/toggles, @property for animatable custom properties, and prefers-reduced-motion patterns.

Individual skills in this repo

This repo contains 13 individual skills — each has its own dedicated page.

nehakanjamala/personal_website

This skill should be used when the user asks to "fix janky CSS animation", "make animation 60fps", "stop layout thrashing", "animate width/height/top/left smoothly", "convert animation to transform", "animate box-shadow performantly", "animate height auto", "FLIP animation", or "why is my scroll/hover animation choppy".

nehakanjamala/personal_website

This skill should be used when the user asks to "respect prefers-reduced-motion", "honor reduced motion", "make my animations accessible", "fix vestibular / motion-sickness issues", "add a useReducedMotion hook", "gate GSAP / Framer Motion / Lenis for reduced motion", or "meet WCAG 2.3.3 / C39". Provides tiered (not all-or-nothing) reduced-motion patterns in CSS and JS.

nehakanjamala/personal_website

Create, modify, debug, and deploy Apify Actors, and write their input and output schemas. Use when building an Actor from scratch, changing or troubleshooting Actor code, generating or updating .actor schema files, or pushing an Actor to the Apify platform. To wrap an existing non-Actor project, use apify-actorization instead.

nehakanjamala/personal_website

Convert existing projects into Apify Actors - serverless cloud programs. Actorize JavaScript/TypeScript (SDK with Actor.init/exit), Python (async context manager), or any language (CLI wrapper). Use when migrating code to Apify, wrapping CLI tools as Actors, or adding Actor SDK to existing projects.

nehakanjamala/personal_website

Deprecated. Output schema generation moved to the apify-actor-development skill; prefer that skill whenever it is available.

nehakanjamala/personal_website

Design and build an official Apify integration for a company's product - workflow-automation apps (Zapier/n8n-style), AI agent plugins (coding-agent skills+MCP bundles or OpenClaw/Hermes-style harnesses), AI framework packages (LangChain/LlamaIndex-style), or direct application clients via apify-client. Use when planning, creating, or reviewing an integration that exposes Apify Actors, runs, datasets, or key-value stores inside another product.

nehakanjamala/personal_website

Universal AI-powered web scraper for any platform. Scrape data from Instagram, Facebook, TikTok, YouTube, LinkedIn, X/Twitter, Google Maps, Google Search, Google Trends, Reddit, Airbnb, Yelp, and 15+ more platforms. Use for lead generation, brand monitoring, competitor analysis, influencer discovery, trend research, content analytics, audience analysis, review analysis, SEO intelligence, recruitment, or any data extraction task.

nehakanjamala/personal_website

This skill should be used when the user asks to "add a glassmorphism effect", "frosted glass UI", "Apple liquid glass style", "frosted blur card", "translucent glass panel animation", "make a frosted nav bar", "build a glass modal/dialog", "animate a glass card on hover", or "add a refracting liquid-glass hero". Covers frosted translucent panels with backdrop-filter blur, edge/specular highlights, SVG liquid-glass refraction, motion on hover/scroll/enter, and accessible reduced-transparency fallbacks.

nehakanjamala/personal_website

This skill should be used when the user asks to "build a scroll animation", "add ScrollTrigger", "pin a section while scrolling", "scrub an animation to scroll", "create a hero timeline", "do a horizontal scroll section", "split text and animate words", "animate a layout change with GSAP Flip", "sync ScrollTrigger with Lenis", "Lenis smooth scroll jittery", "ScrollTrigger markers drift", "ScrollTrigger pins break with Lenis/Locomotive", or "set up smooth scroll with GSAP pinning". Covers GSAP timelines, ScrollTrigger, SplitText, Flip, and Lenis/Locomotive smooth-scroll sync for code-driven web motion.

nehakanjamala/personal_website

This skill should be used when the user asks to "add a Lottie animation", "play a .lottie or .json animation", "integrate a Bodymovin/After Effects animation on web or mobile", "control Lottie playback / segments", "make a scroll-driven Lottie", "recolor a Lottie at runtime", or "export an AE animation to Lottie". Covers dotLottie/lottie-web integration, playback control, interactivity, theming, and the AE export checklist.

nehakanjamala/personal_website

This skill should be used when the user asks to "animate page or route transitions", "add a page transition or crossfade between views", "animate route changes in Next.js App Router", "use the View Transitions API", "AnimatePresence exit doesn't fire on navigation", or "Framer Motion exit animation not working / exit animation before unmount in Next.js". Covers enter/exit page-transition animation with the View Transitions API and Framer Motion, for Next.js App Router and general SPA routing.

nehakanjamala/personal_website

Scrape web pages using Scrapling with anti-bot bypass (like Cloudflare Turnstile), stealth headless browsing, spiders framework, adaptive scraping, and JavaScript rendering. Use when asked to scrape, crawl, or extract data from websites; web_fetch fails; the site has anti-bot protections; write Python code to scrape/crawl; or write spiders.

nehakanjamala/personal_website

This skill should be used when the user asks to "animate an SVG", "make a line draw itself on", "do a stroke draw-on / signature animation", "morph one shape into another", "move an element along a path", "animate an icon/logo", or "animate an SVG gradient or filter". Covers stroke-dashoffset draw-on, path morphing, motion-along-path, and animated icons/gradients/filters via CSS, SMIL, and GSAP.

関連スキル