agentleFS
build-dezineerbuild-dezineer/skills-nuxt4-tw-webapp/skills/dashboard-motion/SKILL.md

dashboard-motion

Skill0 starsChanged 45 days agoApache-2.0View on GitHub

The webapp motion toolkit: count-up numbers through `useCounter` (already wired into MetricCard) and the `.stagger-children` CSS utility for card-grid and table-row entrances. Dependency-free and reduced-motion safe. Use when building dashboard, analytics or list screens.

The file

We split this skill into the rules it gives an agent

10 rules. About 0 are common, 1 is distinctive, and 9 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 9

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Put the class on the PARENT of a card grid, table <tbody>, or list — every direct child animates in with an increasing delay automatically.

    line 44
  2. Very specific:

    Do NOT wire per-item animation-delay by hand, and do NOT add a template ref per row to stagger manually — that's exactly the kind of …

    line 62
  3. Very specific:

    Do NOT add gsap, lenis, split-type, @vueuse/motion, swiper, three, or @tresjs/* to package.json — this is a data tool, not a marketing site.

    line 96
  4. Very specific:

    Do NOT use ScrollTrigger/scroll-pinning, parallax, a marquee/ticker, a custom cursor, or a full-page GSAP timeline — all of that is …

    line 98
  5. Very specific:

    Do NOT build a custom entrance animation per component — use .stagger-children.

    line 100
  6. Very specific:

    Do NOT render a metric value as a static string — see metric-card/SKILL.md's count-up rule.

    line 101
  7. Very specific:

    Never reimplement useCounter or hand-roll a count-up loop — import it.

    line 105
  8. Very specific:

    Use .stagger-children on the parent, never per-item delays.

    line 106
  9. Very specific:

    No motion library dependency beyond what's already in package.json (@vueuse/core).

    line 107
  10. Distinctive:

    No scroll-driven, pinned, or parallax effects anywhere in webapp code.

    line 108

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Dashboard Motion Skill

When to use

Any webapp screen with numbers to count up (metric cards, KPIs) or a list/grid of cards/rows that should animate in on load (a metric row, a table body, a card grid). This is the ENTIRE motion toolkit for webapp screens — there is no GSAP, ScrollTrigger, Lenis, or scroll-driven animation here. A data-dense tool is not a scroll narrative; motion is a small, tasteful enhancement, not a centerpiece.

Never call context.selector(). It only exists on a scoped context and is undefined on gsap.matchMedia() / gsap.context(fn), where calling it throws. Query through the section’s template ref instead: sectionRef.value?.querySelectorAll('.item') ?? []. Guard your refs before animating. sectionRef.value can be null when onMounted runs; a tween with no targets fails silently and the section never animates. Start motion setup with if (!sectionRef.value) return.

Use the pre-built primitives — do NOT reimplement them

~/composables/useDashboardMotion.ts already exists in the scaffold, fully implemented and guarded. Do not hand-roll a count-up loop, a requestAnimationFrame tween, or your own IntersectionObserver-based reveal — import what's there:

import { useCounter } from '~/composables/useDashboardMotion'

In practice you rarely call this directly — MetricCard.vue already wires it in internally (see the metric-card skill). Only reach for useCounter yourself if you're building a one-off numeric display outside of MetricCard.

Entrance stagger — .stagger-children

Put the class on the PARENT of a card grid, table <tbody>, or list — every direct child animates in with an increasing delay automatically. One class is the whole API:

<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 stagger-children">
  <MetricCard ... />
  <MetricCard ... />
  <MetricCard ... />
  <MetricCard ... />
</div>
<tbody class="stagger-children">
  <tr v-for="row in rows" :key="row.id">...</tr>
</tbody>

Do NOT wire per-item animation-delay by hand, and do NOT add a template ref per row to stagger manually — that's exactly the kind of per-item wiring .stagger-children exists to replace. It caps automatically at 10 children (later ones share the last delay) so long lists don't get a multi-second entrance.

Count-up numbers

MetricCard's value prop already counts up to itself on mount — pass the formatted string you want ("$48.2k", "18.4%", "24") and it animates automatically (see the metric-card skill). If you need a standalone counter outside MetricCard:

<script setup lang="ts">
import { ref } from 'vue'
import { useCounter } from '~/composables/useDashboardMotion'

const valueEl = ref<HTMLElement | null>(null)
useCounter(() => valueEl.value, 12847, { formatter: (v) => Math.round(v).toLocaleString() })
</script>

<template>
  <p ref="valueEl" class="text-2xl font-bold tabular-nums">0</p>
</template>

Reduced motion

Both primitives already handle prefers-reduced-motion — useCounter writes the final formatted value immediately with no animation, and .stagger-children's keyframe is neutralized by the global reduced-motion rule in main.css. You never need to check prefers-reduced-motion yourself in webapp code.

Do NOT

  • Do NOT add gsap, lenis, split-type, @vueuse/motion, swiper, three, or @tresjs/* to package.json — this is a data tool, not a marketing site. None of these belong here.
  • Do NOT use ScrollTrigger/scroll-pinning, parallax, a marquee/ticker, a custom cursor, or a full-page GSAP timeline — all of that is website-skill territory, not webapp.
  • Do NOT build a custom entrance animation per component — use .stagger-children.
  • Do NOT render a metric value as a static string — see metric-card/SKILL.md's count-up rule.

Non-negotiables

  1. Never reimplement useCounter or hand-roll a count-up loop — import it.
  2. Use .stagger-children on the parent, never per-item delays.
  3. No motion library dependency beyond what's already in package.json (@vueuse/core).
  4. No scroll-driven, pinned, or parallax effects anywhere in webapp code.

Colour & polish

  • .stagger-children on card grids and table bodies.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.