format: apply repo prettier (3.8.1) to the folded skills tree

963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
This commit is contained in:
fargo
2026-08-19 14:37:17 -05:00
parent d2eeb64433
commit 1a822493ba
962 changed files with 29594 additions and 27188 deletions
@@ -6,6 +6,7 @@ description: Guidelines and examples for UI motion and animation. Use when desig
# UI Animation
## Core rules
- Animate to clarify cause/effect or add deliberate delight.
- Keep interactions fast (200-300ms; up to 1s only for illustrative motion).
- Never animate keyboard interactions (arrow-key navigation, shortcut responses, tab/focus).
@@ -14,6 +15,7 @@ description: Guidelines and examples for UI motion and animation. Use when desig
- Honor `prefers-reduced-motion` (reduce or disable).
## What to animate
- For movement and spatial change, animate only `transform` and `opacity`.
- For simple state feedback, `color`, `background-color`, and `opacity` transitions are acceptable.
- Never animate layout properties; never use `transition: all`.
@@ -22,30 +24,36 @@ description: Guidelines and examples for UI motion and animation. Use when desig
- Disable transitions during theme switches.
## Spatial and sequencing
- Set `transform-origin` at the trigger point.
- For dialogs/menus, start around `scale(0.85-0.9)`; avoid `scale(0)`.
- Stagger reveals <= 50ms.
## Easing defaults
- Enter and transform-based hover: `cubic-bezier(0.22, 1, 0.36, 1)`.
- Move: `cubic-bezier(0.25, 1, 0.5, 1)`.
- Simple hover colour/background/opacity: `200ms ease`.
- Avoid `ease-in` for UI (feels slow).
## Accessibility
- If `transform` is used, disable it in `prefers-reduced-motion`.
- Disable hover transitions on touch devices via `@media (hover: hover) and (pointer: fine)`.
## Performance
- Pause looping animations off-screen.
- Toggle `will-change` only during heavy motion and only for `transform`/`opacity`.
- Prefer `transform` over positional props in animation libraries.
- Do not animate drag gestures using CSS variables.
## Reference
- Snippets and practical tips: [examples.md](examples.md)
## Workflow
1. Start with the core rules, then pick a reference snippet from [examples.md](examples.md).
2. Keep motion functional; honor `prefers-reduced-motion`.
3. When reviewing, cite file paths and line numbers and propose concrete fixes.
@@ -3,6 +3,7 @@
Snippets and tips for the core rules in `SKILL.md`.
## Table of contents
- [Enter and exit](#enter-and-exit)
- [Spatial rules and stagger](#spatial-rules-and-stagger)
- [Drawer (move easing)](#drawer-move-easing)
@@ -13,29 +14,31 @@ Snippets and tips for the core rules in `SKILL.md`.
- [Practical tips](#practical-tips)
## Enter and exit
```css
/* Toast.module.css */
.toast {
transform: translate3d(0, 6px, 0);
opacity: 0;
transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
opacity 220ms cubic-bezier(0.22, 1, 0.36, 1);
transition:
transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
opacity 220ms cubic-bezier(0.22, 1, 0.36, 1);
}
.toast[data-open="true"] {
.toast[data-open='true'] {
transform: translate3d(0, 0, 0);
opacity: 1;
}
/* Disable transitions during theme switch */
[data-theme-switching="true"] * {
[data-theme-switching='true'] * {
transition: none !important;
}
```
```tsx
// app/components/Panel.tsx
"use client";
import { motion, useReducedMotion } from "framer-motion";
'use client';
import { motion, useReducedMotion } from 'framer-motion';
export function Panel() {
const reduceMotion = useReducedMotion();
@@ -44,25 +47,25 @@ export function Panel() {
<motion.div
whileHover={reduceMotion ? undefined : { scale: 1.02 }}
whileTap={reduceMotion ? undefined : { scale: 0.98 }}
transition={
reduceMotion ? { duration: 0 } : { duration: 0.2, ease: [0.22, 1, 0.36, 1] }
}
transition={reduceMotion ? { duration: 0 } : { duration: 0.2, ease: [0.22, 1, 0.36, 1] }}
/>
);
}
```
## Spatial rules and stagger
```css
/* Menu.module.css */
.menu {
transform-origin: top right;
transform: scale(0.88);
opacity: 0;
transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1),
opacity 200ms cubic-bezier(0.22, 1, 0.36, 1);
transition:
transform 200ms cubic-bezier(0.22, 1, 0.36, 1),
opacity 200ms cubic-bezier(0.22, 1, 0.36, 1);
}
.menu[data-open="true"] {
.menu[data-open='true'] {
transform: scale(1);
opacity: 1;
}
@@ -70,8 +73,12 @@ export function Panel() {
.list > * {
animation: fade-in 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.list > *:nth-child(2) { animation-delay: 50ms; }
.list > *:nth-child(3) { animation-delay: 100ms; }
.list > *:nth-child(2) {
animation-delay: 50ms;
}
.list > *:nth-child(3) {
animation-delay: 100ms;
}
```
```tsx
@@ -81,6 +88,7 @@ const listVariants = {
```
## Drawer (move easing)
```css
.drawer {
transition: transform 240ms cubic-bezier(0.25, 1, 0.5, 1);
@@ -89,19 +97,22 @@ const listVariants = {
```tsx
<motion.aside
initial={{ transform: "translate3d(100%, 0, 0)" }}
animate={{ transform: "translate3d(0, 0, 0)" }}
exit={{ transform: "translate3d(100%, 0, 0)" }}
initial={{ transform: 'translate3d(100%, 0, 0)' }}
animate={{ transform: 'translate3d(0, 0, 0)' }}
exit={{ transform: 'translate3d(100%, 0, 0)' }}
transition={{ duration: 0.24, ease: [0.25, 1, 0.5, 1] }}
/>
```
## Hover transitions
```css
/* Link.module.css */
@media (hover: hover) and (pointer: fine) {
.link {
transition: color 200ms ease, opacity 200ms ease;
transition:
color 200ms ease,
opacity 200ms ease;
}
.link:hover {
opacity: 0.8;
@@ -110,6 +121,7 @@ const listVariants = {
```
## Reduced motion
```css
@media (prefers-reduced-motion: reduce) {
.menu,
@@ -121,8 +133,8 @@ const listVariants = {
```
```tsx
"use client";
import { motion, useReducedMotion } from "framer-motion";
'use client';
import { motion, useReducedMotion } from 'framer-motion';
export function AnimatedCard() {
const reduceMotion = useReducedMotion();
@@ -136,20 +148,30 @@ export function AnimatedCard() {
```
## Origin-aware animations
```css
.popover[data-side="top"] { transform-origin: bottom center; }
.popover[data-side="bottom"] { transform-origin: top center; }
.popover[data-side="left"] { transform-origin: center right; }
.popover[data-side="right"] { transform-origin: center left; }
.popover[data-side='top'] {
transform-origin: bottom center;
}
.popover[data-side='bottom'] {
transform-origin: top center;
}
.popover[data-side='left'] {
transform-origin: center right;
}
.popover[data-side='right'] {
transform-origin: center left;
}
```
## Performance recipes
### Pause looping animations off-screen
```ts
// app/hooks/usePauseOffscreen.ts
"use client";
import { useEffect, useRef } from "react";
'use client';
import { useEffect, useRef } from 'react';
export function usePauseOffscreen<T extends HTMLElement>() {
const ref = useRef<T | null>(null);
@@ -157,7 +179,7 @@ export function usePauseOffscreen<T extends HTMLElement>() {
const el = ref.current;
if (!el) return;
const io = new IntersectionObserver(([entry]) => {
el.style.animationPlayState = entry.isIntersecting ? "running" : "paused";
el.style.animationPlayState = entry.isIntersecting ? 'running' : 'paused';
});
io.observe(el);
return () => io.disconnect();
@@ -167,6 +189,7 @@ export function usePauseOffscreen<T extends HTMLElement>() {
```
### Toggle will-change during animation
```css
.animating {
will-change: transform, opacity;
@@ -174,22 +197,26 @@ export function usePauseOffscreen<T extends HTMLElement>() {
```
### Spring defaults (framer-motion)
```tsx
<motion.div
animate={{ transform: "translate3d(0, 0, 0)" }}
transition={{ type: "spring", stiffness: 500, damping: 40 }}
animate={{ transform: 'translate3d(0, 0, 0)' }}
transition={{ type: 'spring', stiffness: 500, damping: 40 }}
/>
```
## Practical tips
### Record your animations
When something feels off, record the animation and play it back frame by frame.
### Fix shaky 1px shifts
Elements can shift by 1px at the start/end of CSS transforms due to GPU/CPU handoff. Apply `will-change: transform` during the animation (not permanently) to keep compositing on the GPU.
### Scale buttons on press
```css
button:active {
transform: scale(0.97);
@@ -198,6 +225,7 @@ button:active {
```
### Avoid animating from scale(0)
```css
.element {
transform: scale(0.95);
@@ -210,6 +238,7 @@ button:active {
```
### Skip animation on subsequent tooltips
```css
.tooltip {
transition:
@@ -228,7 +257,9 @@ button:active {
```
### Fix hover flicker
Apply the hover effect on a parent, animate the child:
```css
.box:hover .box-inner {
transform: translateY(-20%);