[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6D2DQ9BCSNN7HS1SWG3FG8G":3,"skill-same:01M6D2DQ9BCSNN7HS1SWG3FG8G":61},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":33,"linkOnly":34,"markdownContent":35,"markdownBody":36,"frontMatter":37,"refName":38,"commitSha":39,"skillDirectory":40,"forksCount":41,"repositoryHtmlUrl":42,"repositoryHomepageUrl":43,"ownerHtmlUrl":44,"ownerBlogUrl":43,"ownerDescription":45,"updatedAt":46,"install":47,"resources":60},"01M6D2DQ9BCSNN7HS1SWG3FG8G","ui-part-loading",null,"Loading and progress: what to show for each length of wait, loading per block rather than per page, skeletons shaped like the content, keeping old data during a refresh, busy buttons, optimistic updates, spinners and progress bars, streaming, screen reader announcements, and no layout shift. Read before building any state where the interface waits for data or work.","enowdev\u002Fenowxcli","enowdev","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F179420349?v=4","01M6D1MVX2KC0X3Z9NESE7P22K","Enow Dev.","01M6D1MW1FMZGBDKWAJY4GQX81",67,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-part-loading\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32],"ui","ui part loading","state","streaming","content","data","page","work","reader","before building","read","refresh","show","layout","2026-11-10 10:12:30",false,"---\nname: ui-part-loading\ndescription: \"Loading and progress: what to show for each length of wait, loading per block rather than per page, skeletons shaped like the content, keeping old data during a refresh, busy buttons, optimistic updates, spinners and progress bars, streaming, screen reader announcements, and no layout shift. Read before building any state where the interface waits for data or work.\"\n---\n\n# Progress and loading\n\nThe generated version: a full-page spinner for every request, grey bars in\na layout the data never fills, content that jumps when it lands, a\nprogress bar that eases to 90% and waits, and a Save button that can be\npressed five times while it saves. A loading state answers three\nquestions: is something happening, what, and for how long. The principles\nare in the `ui` skill, the measures in `ui-layout`, the motion in\n`motion-interface` (section 11).\n\n## 1. Choose by the wait\n\n| The wait | Show |\n|---|---|\n| Under about 200 to 300ms | nothing: a spinner that flashes is worse than none |\n| The first load of a region of content | a skeleton shaped like the content, appearing after about 200ms |\n| 300ms to 2 or 3s, for an action or a small widget | the control's own busy state, or an inline spinner with text |\n| Past about 3s | progress with a label saying what is happening; a bar with numbers when progress is known |\n| Past about 10s | say it is still working, and offer to carry on while it runs in the background and notify when done (`backend-jobs`) |\n\n- About 0.1s feels instant, 1s keeps the train of thought, 10s is as long\n  as attention holds (Nielsen's limits). Aim for most actions under 1s.\n- Once an indicator shows, keep it at least about 400ms so it does not\n  flicker (the `spin-delay` hook does the delay and the minimum).\n\n## 2. Per block, not per page\n\n- Each part of a screen loads its own data and shows its own skeleton, so\n  the fast parts appear first and one slow query blanks nothing else. The\n  frame (navigation, headers, the page title and its actions) renders at\n  once.\n- Never a full-page spinner or overlay for a small update, and never a\n  blank page with a centred logo while an app boots: render the frame on\n  the server, or put the shell's HTML in `index.html`.\n- Stream what is ready: a `\u003CSuspense>` boundary with a skeleton around each\n  slow block in React (`loading.tsx` for a route in Next.js), promises\n  streamed from a SvelteKit `load` and shown with `{#await}`, `server:defer`\n  islands with a fallback in Astro.\n\n## 3. Skeletons\n\n- A skeleton only where it matches the layout that will load: the same\n  blocks at the same sizes. Text lines at the text's line height, the last\n  one shorter; images at their aspect ratio; avatars as circles; table rows\n  at the row height. The content then takes its place without a jump.\n- For regions of content on their first load: a list, a card grid, a detail\n  panel, a chart's frame. Not for a button, a count, a single number or a\n  select: those show an inline spinner or keep their old value.\n- As many as usually arrive: a page of rows, or three when the list usually\n  holds three.\n- `--surface-2` on `--surface`, low contrast, the content's radius; static,\n  or a slow shimmer (1.5 to 2s a sweep) that stops under reduced motion.\n- A skeleton appears only after about 200ms, so fast loads do not flash.\n- `aria-hidden=\"true\"` on the skeleton; the region carries\n  `aria-busy=\"true\"` and a visually hidden status (\"Loading invoices\").\n\n## 4. Refreshing, filtering and saving\n\n- Refreshing data stays on screen while the new copy loads (stale while\n  revalidate); a small spinner in the block's header says it is updating.\n  A new filter or page dims the old rows slightly and keeps them until the\n  new ones replace them (`ui-part-pagination`).\n  - TanStack Query: `placeholderData: keepPreviousData`; `isPending` means\n    nothing yet (the skeleton), `isFetching` means refreshing (the small\n    spinner). SWR: `keepPreviousData: true`. React's `useTransition` keeps\n    the current screen while the next one renders.\n- Buttons show their own loading state: a 16px spinner and the verb in\n  progress (\"Saving…\"), the width kept (a `min-width`, or the spinner laid\n  over the label), `aria-disabled=\"true\"` so a second press does nothing\n  while focus stays on the button (setting `disabled` on a focused button\n  drops its focus in some browsers). Then the result (\"Saved\") or the error\n  beside it.\n- Optimistic updates for quick actions that almost always succeed (star,\n  mark as read, reorder, rename, add a comment): the change shows at once,\n  the request runs behind it, and a failure puts it back and says so with a\n  retry. React 19's `useOptimistic`, TanStack Query's `onMutate` with a\n  rollback in `onError`, SWR's `optimisticData`. Not for payments, sending,\n  or deleting what cannot be restored.\n- Long work the user started (an export, an import) becomes a status they\n  can leave: a row with its progress, and a notification when it is done\n  (`ui-part-notifications`).\n\n## 5. Spinners and progress bars\n\n- A spinner with text saying what is loading: one small arc turning (0.8\n  to 1s a turn, linear), 16px in a control, 20 to 24px in a region. Not\n  bouncing dots, not the logo spinning.\n- A progress bar with numbers for long tasks: \"312 of 1,240 rows\", \"45%\",\n  and time left only when it can be estimated honestly. `\u003Cprogress\n  value=\"312\" max=\"1240\">` with a visible label, or `role=\"progressbar\"`\n  with `aria-valuenow`, `aria-valuemin`, `aria-valuemax`, `aria-valuetext`\n  and a name. 4 to 8px tall, the numbers in text beside it.\n- Unknown length: an indeterminate bar or a spinner, with the current step\n  in words (\"Matching payments, step 2 of 3\").\n- No fake progress: a bar that eases to 90% and waits is a lie; an\n  indeterminate bar is honest.\n- A Cancel button on anything long the user started.\n\n## 6. Screen readers and layout\n\n- `aria-busy=\"true\"` on the region while it loads, removed when it is done.\n- A polite status (`role=\"status\"`, in the page before its text changes)\n  says it started when the wait is long enough to notice, and says the\n  outcome once (\"24 invoices loaded\", or the error). Milestones at most\n  (every 25%), never every percent.\n- Focus stays where it was; arriving content never takes it.\n- No layout shift when content arrives: the skeleton or a `min-height`\n  holds the space, images have their dimensions (`ui-part-images`). CLS\n  stays under 0.1 (`frontend-performance`).\n\n## 7. Phones, themes and motion\n\n- On a phone the same per-block loading; a sticky action button shows its\n  busy state in place.\n- Themes: skeleton, shimmer and progress track from tokens in both themes;\n  on dark the shimmer is a slightly lighter step, not a white sweep\n  (`ui-themes`).\n- Motion: spinners and shimmers are the only loops, and they end when the\n  loading does; under reduced motion the shimmer is static\n  (`motion-interface`, section 11; `motion-comfort`).\n\n## 8. A sketch\n\n```css\n\u002F* Hidden for the first 200ms, so a fast load never flashes. *\u002F\n.skeleton { animation: wait-then-show 0s 200ms backwards; }\n@keyframes wait-then-show { from { visibility: hidden; } }\n\n.bone {\n  position: relative;\n  overflow: hidden;\n  background: var(--surface-2);\n  border-radius: var(--radius-sm);\n}\n@media (prefers-reduced-motion: no-preference) {\n  .bone::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: linear-gradient(90deg, transparent, var(--shine), transparent);\n    transform: translateX(-100%);\n    animation: shimmer 1.8s linear infinite;\n  }\n}\n@keyframes shimmer { to { transform: translateX(100%); } }\n```\n\n```tsx\nconst { data, isPending, isFetching, isError, refetch } = useQuery({\n  queryKey: [\"invoices\", filters],\n  queryFn: () => fetchInvoices(filters),\n  placeholderData: keepPreviousData,\n});\n\nreturn (\n  \u003Csection aria-labelledby=\"invoices-title\" aria-busy={isFetching}>\n    \u003Cheader className=\"block-head\">\n      \u003Ch2 id=\"invoices-title\">Invoices\u003C\u002Fh2>\n      {isFetching && !isPending && \u003CSpinner label=\"Updating invoices\" \u002F>}\n    \u003C\u002Fheader>\n    {isPending ? (\n      \u003CInvoiceRowsSkeleton rows={25} \u002F>\n    ) : isError ? (\n      \u003CBlockError message=\"The invoices did not load.\" onRetry={refetch} \u002F>\n    ) : (\n      \u003CInvoiceTable rows={data.items} dimmed={isFetching} \u002F>\n    )}\n  \u003C\u002Fsection>\n);\n```\n\n## Check it\n\n- DevTools, network throttled to Slow 4G: each block shows its own\n  skeleton, the frame is there at once, nothing jumps when content lands.\n  Unthrottled: nothing flashes.\n- `preview` with `motion: true`: layout shift while loading over 0.05 is\n  reported with the elements that moved; anything repeating forever is\n  listed (a spinner left turning after the data arrived).\n- Press a saving button twice quickly: one request. Tab to it while it\n  saves: focus stays.\n- A screen reader hears that loading started and how it ended, once each.\n- Go offline in DevTools: the failed block shows its error and a retry;\n  the rest of the screen still works.\n\n## Avoid\n\nA full-page spinner for a small update; skeletons shaped like a layout the\ndata never fills; content that jumps when it arrives; spinners that flash\nfor 100ms; a spinner with no words; a progress bar that eases to 90% and\nwaits; a bright, fast shimmer; blanking the old data on every refetch; a\nbutton that can be pressed again while it saves; the logo spinning on a\nboot screen; a loading state that never ends when the request fails.\n","# Progress and loading\n\nThe generated version: a full-page spinner for every request, grey bars in\na layout the data never fills, content that jumps when it lands, a\nprogress bar that eases to 90% and waits, and a Save button that can be\npressed five times while it saves. A loading state answers three\nquestions: is something happening, what, and for how long. The principles\nare in the `ui` skill, the measures in `ui-layout`, the motion in\n`motion-interface` (section 11).\n\n## 1. Choose by the wait\n\n| The wait | Show |\n|---|---|\n| Under about 200 to 300ms | nothing: a spinner that flashes is worse than none |\n| The first load of a region of content | a skeleton shaped like the content, appearing after about 200ms |\n| 300ms to 2 or 3s, for an action or a small widget | the control's own busy state, or an inline spinner with text |\n| Past about 3s | progress with a label saying what is happening; a bar with numbers when progress is known |\n| Past about 10s | say it is still working, and offer to carry on while it runs in the background and notify when done (`backend-jobs`) |\n\n- About 0.1s feels instant, 1s keeps the train of thought, 10s is as long\n  as attention holds (Nielsen's limits). Aim for most actions under 1s.\n- Once an indicator shows, keep it at least about 400ms so it does not\n  flicker (the `spin-delay` hook does the delay and the minimum).\n\n## 2. Per block, not per page\n\n- Each part of a screen loads its own data and shows its own skeleton, so\n  the fast parts appear first and one slow query blanks nothing else. The\n  frame (navigation, headers, the page title and its actions) renders at\n  once.\n- Never a full-page spinner or overlay for a small update, and never a\n  blank page with a centred logo while an app boots: render the frame on\n  the server, or put the shell's HTML in `index.html`.\n- Stream what is ready: a `\u003CSuspense>` boundary with a skeleton around each\n  slow block in React (`loading.tsx` for a route in Next.js), promises\n  streamed from a SvelteKit `load` and shown with `{#await}`, `server:defer`\n  islands with a fallback in Astro.\n\n## 3. Skeletons\n\n- A skeleton only where it matches the layout that will load: the same\n  blocks at the same sizes. Text lines at the text's line height, the last\n  one shorter; images at their aspect ratio; avatars as circles; table rows\n  at the row height. The content then takes its place without a jump.\n- For regions of content on their first load: a list, a card grid, a detail\n  panel, a chart's frame. Not for a button, a count, a single number or a\n  select: those show an inline spinner or keep their old value.\n- As many as usually arrive: a page of rows, or three when the list usually\n  holds three.\n- `--surface-2` on `--surface`, low contrast, the content's radius; static,\n  or a slow shimmer (1.5 to 2s a sweep) that stops under reduced motion.\n- A skeleton appears only after about 200ms, so fast loads do not flash.\n- `aria-hidden=\"true\"` on the skeleton; the region carries\n  `aria-busy=\"true\"` and a visually hidden status (\"Loading invoices\").\n\n## 4. Refreshing, filtering and saving\n\n- Refreshing data stays on screen while the new copy loads (stale while\n  revalidate); a small spinner in the block's header says it is updating.\n  A new filter or page dims the old rows slightly and keeps them until the\n  new ones replace them (`ui-part-pagination`).\n  - TanStack Query: `placeholderData: keepPreviousData`; `isPending` means\n    nothing yet (the skeleton), `isFetching` means refreshing (the small\n    spinner). SWR: `keepPreviousData: true`. React's `useTransition` keeps\n    the current screen while the next one renders.\n- Buttons show their own loading state: a 16px spinner and the verb in\n  progress (\"Saving…\"), the width kept (a `min-width`, or the spinner laid\n  over the label), `aria-disabled=\"true\"` so a second press does nothing\n  while focus stays on the button (setting `disabled` on a focused button\n  drops its focus in some browsers). Then the result (\"Saved\") or the error\n  beside it.\n- Optimistic updates for quick actions that almost always succeed (star,\n  mark as read, reorder, rename, add a comment): the change shows at once,\n  the request runs behind it, and a failure puts it back and says so with a\n  retry. React 19's `useOptimistic`, TanStack Query's `onMutate` with a\n  rollback in `onError`, SWR's `optimisticData`. Not for payments, sending,\n  or deleting what cannot be restored.\n- Long work the user started (an export, an import) becomes a status they\n  can leave: a row with its progress, and a notification when it is done\n  (`ui-part-notifications`).\n\n## 5. Spinners and progress bars\n\n- A spinner with text saying what is loading: one small arc turning (0.8\n  to 1s a turn, linear), 16px in a control, 20 to 24px in a region. Not\n  bouncing dots, not the logo spinning.\n- A progress bar with numbers for long tasks: \"312 of 1,240 rows\", \"45%\",\n  and time left only when it can be estimated honestly. `\u003Cprogress\n  value=\"312\" max=\"1240\">` with a visible label, or `role=\"progressbar\"`\n  with `aria-valuenow`, `aria-valuemin`, `aria-valuemax`, `aria-valuetext`\n  and a name. 4 to 8px tall, the numbers in text beside it.\n- Unknown length: an indeterminate bar or a spinner, with the current step\n  in words (\"Matching payments, step 2 of 3\").\n- No fake progress: a bar that eases to 90% and waits is a lie; an\n  indeterminate bar is honest.\n- A Cancel button on anything long the user started.\n\n## 6. Screen readers and layout\n\n- `aria-busy=\"true\"` on the region while it loads, removed when it is done.\n- A polite status (`role=\"status\"`, in the page before its text changes)\n  says it started when the wait is long enough to notice, and says the\n  outcome once (\"24 invoices loaded\", or the error). Milestones at most\n  (every 25%), never every percent.\n- Focus stays where it was; arriving content never takes it.\n- No layout shift when content arrives: the skeleton or a `min-height`\n  holds the space, images have their dimensions (`ui-part-images`). CLS\n  stays under 0.1 (`frontend-performance`).\n\n## 7. Phones, themes and motion\n\n- On a phone the same per-block loading; a sticky action button shows its\n  busy state in place.\n- Themes: skeleton, shimmer and progress track from tokens in both themes;\n  on dark the shimmer is a slightly lighter step, not a white sweep\n  (`ui-themes`).\n- Motion: spinners and shimmers are the only loops, and they end when the\n  loading does; under reduced motion the shimmer is static\n  (`motion-interface`, section 11; `motion-comfort`).\n\n## 8. A sketch\n\n```css\n\u002F* Hidden for the first 200ms, so a fast load never flashes. *\u002F\n.skeleton { animation: wait-then-show 0s 200ms backwards; }\n@keyframes wait-then-show { from { visibility: hidden; } }\n\n.bone {\n  position: relative;\n  overflow: hidden;\n  background: var(--surface-2);\n  border-radius: var(--radius-sm);\n}\n@media (prefers-reduced-motion: no-preference) {\n  .bone::after {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: linear-gradient(90deg, transparent, var(--shine), transparent);\n    transform: translateX(-100%);\n    animation: shimmer 1.8s linear infinite;\n  }\n}\n@keyframes shimmer { to { transform: translateX(100%); } }\n```\n\n```tsx\nconst { data, isPending, isFetching, isError, refetch } = useQuery({\n  queryKey: [\"invoices\", filters],\n  queryFn: () => fetchInvoices(filters),\n  placeholderData: keepPreviousData,\n});\n\nreturn (\n  \u003Csection aria-labelledby=\"invoices-title\" aria-busy={isFetching}>\n    \u003Cheader className=\"block-head\">\n      \u003Ch2 id=\"invoices-title\">Invoices\u003C\u002Fh2>\n      {isFetching && !isPending && \u003CSpinner label=\"Updating invoices\" \u002F>}\n    \u003C\u002Fheader>\n    {isPending ? (\n      \u003CInvoiceRowsSkeleton rows={25} \u002F>\n    ) : isError ? (\n      \u003CBlockError message=\"The invoices did not load.\" onRetry={refetch} \u002F>\n    ) : (\n      \u003CInvoiceTable rows={data.items} dimmed={isFetching} \u002F>\n    )}\n  \u003C\u002Fsection>\n);\n```\n\n## Check it\n\n- DevTools, network throttled to Slow 4G: each block shows its own\n  skeleton, the frame is there at once, nothing jumps when content lands.\n  Unthrottled: nothing flashes.\n- `preview` with `motion: true`: layout shift while loading over 0.05 is\n  reported with the elements that moved; anything repeating forever is\n  listed (a spinner left turning after the data arrived).\n- Press a saving button twice quickly: one request. Tab to it while it\n  saves: focus stays.\n- A screen reader hears that loading started and how it ended, once each.\n- Go offline in DevTools: the failed block shows its error and a retry;\n  the rest of the screen still works.\n\n## Avoid\n\nA full-page spinner for a small update; skeletons shaped like a layout the\ndata never fills; content that jumps when it arrives; spinners that flash\nfor 100ms; a spinner with no words; a progress bar that eases to 90% and\nwaits; a bright, fast shimmer; blanking the old data on every refetch; a\nbutton that can be pressed again while it saves; the logo spinning on a\nboot screen; a loading state that never ends when the request fails.\n",{"name":5,"description":7},"main","38293fe1b096e6bf3646c7344c38786ed688f464","crates\u002Fenowx-core\u002Fskills\u002Fui-part-loading",21,"https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli","https:\u002F\u002Fenowx.ai","https:\u002F\u002Fgithub.com\u002Fenowdev","Pretending to be a Developer","2026-10-06 02:05:35",{"source":8,"skillName":5,"commands":48,"prompt":58,"zipAvailable":59},[49,52,55],{"tool":50,"command":51},"npx","npx skills add enowdev\u002Fenowxcli --skill ui-part-loading",{"tool":53,"command":54},"bunx","bunx skills add enowdev\u002Fenowxcli --skill ui-part-loading",{"tool":56,"command":57},"pnpm","pnpm dlx skills add enowdev\u002Fenowxcli --skill ui-part-loading","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-part-loading\u002FSKILL.md",true,[],[62,78,102,115,141,163],{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":73,"publishedAt":33},"01M6D2HQYSQD9N7MTNDT4A7CBM","demo-skill","Project-scope demo skill for tests.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fworkspace\u002F.agents\u002Fskills\u002Fdemo-skill\u002FSKILL.md",[68],{"categoryNo":69,"categoryName":70,"taxonomyType":71,"taxonomyTypeDesc":72},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[74,75,76,77,29],"demo skill","demo","tests","project",{"skillNo":79,"name":80,"nameZh":6,"description":81,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":92,"publishedAt":33},"01M6D2HM0GCPM0TM2HPG9HHR2R","writing","Writing words people read: the specific thing instead of claims, words to drop, sentences, interface copy (buttons, labels, errors, empty states, confirmations), page copy, notifications and emails, alt text and link text, numbers and dates, words that translate well, documentation and voice. Read before writing a page's copy, an interface's text or a document.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fwriting\u002FSKILL.md",[84,87],{"categoryNo":85,"categoryName":86,"taxonomyType":71,"taxonomyTypeDesc":72},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":88,"categoryName":89,"taxonomyType":90,"taxonomyTypeDesc":91},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[80,93,94,95,96,97,29,25,98,99,100,101],"text","emails","empty","drop","document","voice","notifications","documentation","translate",{"skillNo":103,"name":19,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":105,"categories":106,"keywords":110,"publishedAt":33},"01M6D2HG07YS49NM196Q0R3AZ8","Designing or restyling an interface: direction, layout, type, colour, icons, components, states, responsive behaviour. Read before building a page, a screen or a set of components.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui\u002FSKILL.md",[107],{"categoryNo":108,"categoryName":109,"taxonomyType":90,"taxonomyTypeDesc":91},"01JBSEEDCAT000000000000032","设计师",[19,111,112,113,114,25,32,29,28],"icons","components","SET","responsive",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":127,"publishedAt":33},"01M6D2HB59HZHWG1RYZDV4SJ91","ui-themes","Light and dark themes, and colour that holds in both: tokens with a value per theme, and what each kind of content needs to stay visible (icons, SVG drawings and line art, logos, photos, screenshots, charts, code, maps, borders, shadows, focus, form controls), switching without a flash, and checking both. Read before building a second theme or a theme toggle, and before any drawing, logo or chart on a page that has two themes.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-themes\u002FSKILL.md",[121,124],{"categoryNo":122,"categoryName":123,"taxonomyType":71,"taxonomyTypeDesc":72},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":125,"categoryName":126,"taxonomyType":90,"taxonomyTypeDesc":91},"01JBSEEDCAT000000000000030","开发工程师",[19,128,129,130,131,132,133,134,135,29,28,136,25,137,138,23,111,139,140],"ui themes","switching","photos","tokens","drawing","focus","maps","Art","flash","code","Charts","screenshots","logo",{"skillNo":142,"name":143,"nameZh":6,"description":144,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":145,"categories":146,"keywords":150,"publishedAt":33},"01M6D2H5R5KRAE524C8QX0T7Q0","ui-structure","Structure before styling: the blueprint written before any interface code (the screen's job, the regions its kind of page needs, their order and why, the layout skeleton in numbers, the components and their states), the anatomy and order of a homepage, a dashboard, a list, a detail page, settings, a form, sign-in, pricing, docs, an article and a checkout, and how to turn the blueprint into code (tokens, layout primitives, components, sections, page). Read first, before building or rebuilding any page or screen.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-structure\u002FSKILL.md",[147,148,149],{"categoryNo":85,"categoryName":86,"taxonomyType":71,"taxonomyTypeDesc":72},{"categoryNo":125,"categoryName":126,"taxonomyType":90,"taxonomyTypeDesc":91},{"categoryNo":88,"categoryName":89,"taxonomyType":90,"taxonomyTypeDesc":91},[151,19,152,112,153,154,137,155,156,157,32,131,158,159,160,29,28,25,161,162],"structure","ui structure","pricing","dashboard","Blueprint","article","anatomy","styling","primitives","list","why","how",{"skillNo":164,"name":165,"nameZh":6,"description":166,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":167,"categories":168,"keywords":176,"publishedAt":33},"01M6D2H0ZZBJG77MBGPZHA6MWD","ui-stack-vue","Building interfaces in Vue 3 and Nuxt: project layout, script setup with typed defineProps, defineEmits and defineModel, attribute fallthrough, slots and scoped slots, template refs, ref, reactive and computed, watch versus watchEffect, composables and VueUse, provide and inject, Pinia, keyed v-for, transitions, Nuxt 4 (app directory, pages, layouts, useFetch and useAsyncData keys, $fetch in handlers, server routes, runtime config, useSeoMeta, NuxtImg, middleware), VeeValidate forms, Reka UI and Nuxt UI, testing, vue-tsc, and the traps. Read when the project uses Vue or Nuxt.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-stack-vue\u002FSKILL.md",[169,172,175],{"categoryNo":170,"categoryName":171,"taxonomyType":71,"taxonomyTypeDesc":72},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":173,"categoryName":174,"taxonomyType":71,"taxonomyTypeDesc":72},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":108,"categoryName":109,"taxonomyType":90,"taxonomyTypeDesc":91},[19,177,178,179,180,181,182,183,32,77,184,185,29,186,187,188,189,190,191,192],"vue","stack","ui stack vue","forms","pages","watch","runtime","transitions","fetch","pinia","nuxt","template","server","config","directory","testing"]