[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6D2CQWP3P9YQGAC5682XT4V":3,"skill-same:01M6D2CQWP3P9YQGAC5682XT4V":59},{"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":31,"linkOnly":32,"markdownContent":33,"markdownBody":34,"frontMatter":35,"refName":36,"commitSha":37,"skillDirectory":38,"forksCount":39,"repositoryHtmlUrl":40,"repositoryHomepageUrl":41,"ownerHtmlUrl":42,"ownerBlogUrl":41,"ownerDescription":43,"updatedAt":44,"install":45,"resources":58},"01M6D2CQWP3P9YQGAC5682XT4V","ui-part-empty-states",null,"Empty states that help: first use, no results, cleared, filtered to nothing, no permission and failed to load, each saying why it is empty and offering the one action that fills it. Read before building any view that can be empty.","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-empty-states\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30],"ui","empty","ui part empty states","help","first","why","before building","read","view","results","use","permission","2026-11-10 10:12:30",false,"---\nname: ui-part-empty-states\ndescription: \"Empty states that help: first use, no results, cleared, filtered to nothing, no permission and failed to load, each saying why it is empty and offering the one action that fills it. Read before building any view that can be empty.\"\n---\n\n# Empty states\n\nThe generated empty state is a grey box icon over \"No data\", the same for\nevery reason, or a full-page illustration with a joke and nothing to click.\nWorse, it flashes up while the data is still loading, or stands in for a\nrequest that failed, telling people they have nothing when the server never\nanswered. This skill tells the kinds apart, gives each its words and its one\naction, and puts it in the region it replaces. Principles are in `ui`,\nmeasures in `ui-layout`, words in `writing`.\n\n## 1. Tell the kinds apart\n\n| Kind | When | It says | The action |\n|---|---|---|---|\n| First use | The collection has never had a record | What will appear here, and why it helps | Create the first one; import as a link |\n| No results | A search or filter the user set matched nothing | The query and the filters that are on | Clear filters; a spelling suggestion if the engine has one |\n| Filtered to nothing | A built-in view is empty (Overdue, Assigned to me) | That this is good or neutral news | Usually none; a link to the full list |\n| Cleared | The user finished the work (inbox zero) | Done, and what happens next | None needed |\n| Not yet | The data comes from outside (first event, first sale) | What it is waiting for | The setup step: a snippet, a connection |\n| No permission | Records exist that this user cannot see | Who can grant access | Request access, when it is wired |\n| Failed to load | The request failed | Not an empty state: an error (`frontend-errors`) | Retry |\n| Loading | No answer yet | Nothing: a skeleton (`ui-part-loading`) | None |\n\n## 2. Decide from the data, not from an empty array\n\nAn empty array can mean any row of that table. Decide in one function that\nevery list shares, so they all agree:\n\n```ts\ntype EmptyKind = \"loading\" | \"error\" | \"no-access\" | \"no-results\" | \"cleared\" | \"first-use\";\n\nexport function emptyKind(q: {\n  isPending: boolean; isError: boolean; status?: number;\n  count: number; hasAny: boolean; userFiltered: boolean;\n}): EmptyKind | null {\n  if (q.isPending) return \"loading\";\n  if (q.isError) return q.status === 403 ? \"no-access\" : \"error\";\n  if (q.count > 0) return null;\n  if (q.userFiltered) return \"no-results\";\n  return q.hasAny ? \"cleared\" : \"first-use\";\n}\n```\n\n- The API says whether the unfiltered collection has any record (`hasAny`,\n  or the unfiltered total beside the page). Without it, first use and\n  cleared look the same.\n- `userFiltered` is true when the search or any filter differs from the\n  view's default. An empty built-in view (\"Overdue\") is not a failed\n  search: it takes the cleared wording with the view's name.\n- \"Not yet\" is first use for data that arrives from outside: the same slot,\n  its own words.\n- With TanStack Query, `isPending` means no data yet: a skeleton, never\n  \"No results\".\n\n## 3. The words for each kind\n\nPlain and specific, in the product's own nouns (`writing`); plurals and the\nquoted query through `i18n`, the query escaped because it is user input.\n\n- **First use**: what appears here and why, then the step. \"Invoices you\n  send appear here. Create one, or import them from a spreadsheet.\"\n  [Create invoice] · Import CSV\n- **No results**: echo the query and name the filters that are on. \"No\n  books match 'tolkein'. Did you mean Tolkien?\" (the suggestion only when\n  the search engine returns one). \"Two filters are on: Branch Kemang,\n  Available now.\" [Clear filters]\n- **Filtered to nothing**: the good news is the message. \"Nothing is\n  overdue.\"\n- **Cleared**: \"All caught up. New requests will appear here.\"\n- **Not yet**: \"No events yet. Send the first one with the snippet below;\n  this page updates when it arrives.\" Claim it is listening only when the\n  page really polls or subscribes.\n- **No permission**: \"You don't have access to Payroll. Ask a workspace\n  owner to add you.\" Name the owners when the user may know them; show\n  [Request access] only when the request reaches someone.\n\nA heading of two to six words, a body of one or two sentences, the action a\nverb and an object. No \"Oops\", \"No data\", \"Nothing to see here\",\nexclamation marks, or jokes on errors and permission screens.\n\n## 4. Where it sits, and how big\n\n- In the region it replaces: the table body, the list, the panel, the\n  chart's plot area, the dashboard block. The page header, the toolbar,\n  the search and the filters stay, so people can change what emptied it.\n- Centred in that region as one short block, the text at most 40 to 48ch,\n  48 to 96px of space above and below in a large region.\n- Type: the heading one step above body (16 to 20px, semibold), the body\n  14 to 16px in the muted colour at 4.5:1, 8px between them, 16 to 24px\n  above the action.\n- A table keeps its header row and gets one row spanning every column, 48\n  to 96px tall, so the columns still say what the table holds\n  (`ui-part-tables`).\n- A small block (a dashboard card, a side list): one muted line and a\n  link, \"Nothing due this week · See all tasks\", in the block's own padding.\n\n```html\n\u003Ctbody>\n  \u003Ctr>\n    \u003Ctd colspan=\"6\">\n      \u003Cdiv class=\"empty\">\n        \u003Ch3>No books match 'tolkein'\u003C\u002Fh3>\n        \u003Cp>Two filters are on: Branch Kemang, Available now.\u003C\u002Fp>\n        \u003Cbutton type=\"button\">Clear filters\u003C\u002Fbutton>\n      \u003C\u002Fdiv>\n    \u003C\u002Ftd>\n  \u003C\u002Ftr>\n\u003C\u002Ftbody>\n```\n\n```css\n.empty {\n  display: grid; justify-items: center; gap: var(--s-2);\n  max-width: 44ch; margin-inline: auto; padding-block: var(--s-8);\n  text-align: center;\n}\n.empty p { color: var(--text-muted); }\n.empty button { margin-top: var(--s-3); }\n```\n\n## 5. The action\n\n- One primary action, the one that fills the view, and at most one\n  secondary link (import, a template, the page that explains the feature).\n- A real `button`, or a link when it goes to a create page, and it works: a\n  button that does nothing is worse than none (`ui`, section 8).\n- The page header keeps its own create button; the empty state repeats the\n  same action with the same words, so nothing moves when the first record\n  arrives.\n- No action the user cannot take: without permission to create, say who\n  can (\"Only admins add members\") rather than showing a disabled button.\n- When the action succeeds, the new record replaces the empty state in\n  place, and focus goes to it or to the list's heading.\n\n## 6. Illustration and sample data\n\n- An illustration is optional. When used: small (64 to 120px), from the\n  product's own world in its icon style, or a faded preview of what a\n  filled row will look like, which teaches the layout. Never blobs, people\n  at laptops, 3D shapes, a sad face, or one picture on every empty state.\n- It is decoration: `alt=\"\"` or `aria-hidden=\"true\"`, coloured from the\n  tokens so it holds in the dark theme (`ui-themes`).\n- None in tables, small blocks or search results: the words do it.\n- Sample data only on request (\"Explore with sample data\"), labelled on\n  every record and in a banner above the list, removable in one action, and\n  kept out of counts, reports, exports, billing and anything sent to real\n  people. A template is often the better second action.\n\n## 7. Never empty when it is not\n\n- Loading: a skeleton after about 200ms (`ui-part-loading`), never \"No\n  results\" while the first request is in flight.\n- Refetching after a filter change: keep the previous rows, dimmed, until\n  the new answer arrives (`placeholderData: keepPreviousData` in TanStack\n  Query), so a quick filter does not flash an empty state.\n- Typing a search: judge the settled query (debounced 200 to 300ms), not\n  each keystroke.\n- Failed: an error in the same region with what failed and Retry, keeping\n  the last good data when there is some (`frontend-errors`).\n- The last record deleted: the view becomes cleared or first use, with the\n  undo toast still on screen (`ui-part-notifications`).\n- On a dashboard, only the block that is empty says so; the others carry\n  on.\n\n## 8. Accessibility, phone, themes, motion\n\n- A heading at the level the region's outline needs, the body in a `p`,\n  the action a real control with its words.\n- For a search, the polite status region that says \"24 results\" says \"No\n  results for tolkein\" once the query settles (`role=\"status\"`, in the page\n  before its text changes). A first-use state is not announced: it is\n  content.\n- After Clear filters, focus goes to the search field or the results\n  heading, not to the top of the page.\n- On a phone: the same block with 32 to 48px of padding, under the search\n  bar, the action at least 44px tall.\n- Muted text, illustration and action from tokens in both themes\n  (`ui-themes`); the swap between empty and filled is a fade of 150 to\n  200ms or nothing (`motion-interface`, section 9).\n\n## Check it\n\n- Force every state on every list and block: a fresh account, a search\n  that matches nothing, filters that empty the list, an empty built-in\n  view, a user without access, the endpoint failing (block the request in\n  DevTools, or an MSW handler returning 500), and a throttled network.\n  Each shows its own words; none says \"No results\" before data arrives.\n- Delete the last record, then undo.\n- `preview` at 360, 768 and 1440px, with `login` for screens behind\n  sign-in: the block sits in its region, the toolbar stays, the action is\n  44px on a phone.\n- `ui_check` for generic copy and stock illustrations.\n- A screen reader hears the no-results message once, not per keystroke.\n\n## Avoid\n\n\"No data\" for every kind; an empty state while loading or after a failed\nrequest; the whole page replaced, with the filters that caused it hidden; a\nlarge generic illustration pushing the action out of view; jokes on errors\nor permission screens; a disabled button with no reason; two or three equal\nbuttons; sample data that looks real, cannot be removed or leaks into\nreports; first-use wording on a list that is merely filtered.\n","# Empty states\n\nThe generated empty state is a grey box icon over \"No data\", the same for\nevery reason, or a full-page illustration with a joke and nothing to click.\nWorse, it flashes up while the data is still loading, or stands in for a\nrequest that failed, telling people they have nothing when the server never\nanswered. This skill tells the kinds apart, gives each its words and its one\naction, and puts it in the region it replaces. Principles are in `ui`,\nmeasures in `ui-layout`, words in `writing`.\n\n## 1. Tell the kinds apart\n\n| Kind | When | It says | The action |\n|---|---|---|---|\n| First use | The collection has never had a record | What will appear here, and why it helps | Create the first one; import as a link |\n| No results | A search or filter the user set matched nothing | The query and the filters that are on | Clear filters; a spelling suggestion if the engine has one |\n| Filtered to nothing | A built-in view is empty (Overdue, Assigned to me) | That this is good or neutral news | Usually none; a link to the full list |\n| Cleared | The user finished the work (inbox zero) | Done, and what happens next | None needed |\n| Not yet | The data comes from outside (first event, first sale) | What it is waiting for | The setup step: a snippet, a connection |\n| No permission | Records exist that this user cannot see | Who can grant access | Request access, when it is wired |\n| Failed to load | The request failed | Not an empty state: an error (`frontend-errors`) | Retry |\n| Loading | No answer yet | Nothing: a skeleton (`ui-part-loading`) | None |\n\n## 2. Decide from the data, not from an empty array\n\nAn empty array can mean any row of that table. Decide in one function that\nevery list shares, so they all agree:\n\n```ts\ntype EmptyKind = \"loading\" | \"error\" | \"no-access\" | \"no-results\" | \"cleared\" | \"first-use\";\n\nexport function emptyKind(q: {\n  isPending: boolean; isError: boolean; status?: number;\n  count: number; hasAny: boolean; userFiltered: boolean;\n}): EmptyKind | null {\n  if (q.isPending) return \"loading\";\n  if (q.isError) return q.status === 403 ? \"no-access\" : \"error\";\n  if (q.count > 0) return null;\n  if (q.userFiltered) return \"no-results\";\n  return q.hasAny ? \"cleared\" : \"first-use\";\n}\n```\n\n- The API says whether the unfiltered collection has any record (`hasAny`,\n  or the unfiltered total beside the page). Without it, first use and\n  cleared look the same.\n- `userFiltered` is true when the search or any filter differs from the\n  view's default. An empty built-in view (\"Overdue\") is not a failed\n  search: it takes the cleared wording with the view's name.\n- \"Not yet\" is first use for data that arrives from outside: the same slot,\n  its own words.\n- With TanStack Query, `isPending` means no data yet: a skeleton, never\n  \"No results\".\n\n## 3. The words for each kind\n\nPlain and specific, in the product's own nouns (`writing`); plurals and the\nquoted query through `i18n`, the query escaped because it is user input.\n\n- **First use**: what appears here and why, then the step. \"Invoices you\n  send appear here. Create one, or import them from a spreadsheet.\"\n  [Create invoice] · Import CSV\n- **No results**: echo the query and name the filters that are on. \"No\n  books match 'tolkein'. Did you mean Tolkien?\" (the suggestion only when\n  the search engine returns one). \"Two filters are on: Branch Kemang,\n  Available now.\" [Clear filters]\n- **Filtered to nothing**: the good news is the message. \"Nothing is\n  overdue.\"\n- **Cleared**: \"All caught up. New requests will appear here.\"\n- **Not yet**: \"No events yet. Send the first one with the snippet below;\n  this page updates when it arrives.\" Claim it is listening only when the\n  page really polls or subscribes.\n- **No permission**: \"You don't have access to Payroll. Ask a workspace\n  owner to add you.\" Name the owners when the user may know them; show\n  [Request access] only when the request reaches someone.\n\nA heading of two to six words, a body of one or two sentences, the action a\nverb and an object. No \"Oops\", \"No data\", \"Nothing to see here\",\nexclamation marks, or jokes on errors and permission screens.\n\n## 4. Where it sits, and how big\n\n- In the region it replaces: the table body, the list, the panel, the\n  chart's plot area, the dashboard block. The page header, the toolbar,\n  the search and the filters stay, so people can change what emptied it.\n- Centred in that region as one short block, the text at most 40 to 48ch,\n  48 to 96px of space above and below in a large region.\n- Type: the heading one step above body (16 to 20px, semibold), the body\n  14 to 16px in the muted colour at 4.5:1, 8px between them, 16 to 24px\n  above the action.\n- A table keeps its header row and gets one row spanning every column, 48\n  to 96px tall, so the columns still say what the table holds\n  (`ui-part-tables`).\n- A small block (a dashboard card, a side list): one muted line and a\n  link, \"Nothing due this week · See all tasks\", in the block's own padding.\n\n```html\n\u003Ctbody>\n  \u003Ctr>\n    \u003Ctd colspan=\"6\">\n      \u003Cdiv class=\"empty\">\n        \u003Ch3>No books match 'tolkein'\u003C\u002Fh3>\n        \u003Cp>Two filters are on: Branch Kemang, Available now.\u003C\u002Fp>\n        \u003Cbutton type=\"button\">Clear filters\u003C\u002Fbutton>\n      \u003C\u002Fdiv>\n    \u003C\u002Ftd>\n  \u003C\u002Ftr>\n\u003C\u002Ftbody>\n```\n\n```css\n.empty {\n  display: grid; justify-items: center; gap: var(--s-2);\n  max-width: 44ch; margin-inline: auto; padding-block: var(--s-8);\n  text-align: center;\n}\n.empty p { color: var(--text-muted); }\n.empty button { margin-top: var(--s-3); }\n```\n\n## 5. The action\n\n- One primary action, the one that fills the view, and at most one\n  secondary link (import, a template, the page that explains the feature).\n- A real `button`, or a link when it goes to a create page, and it works: a\n  button that does nothing is worse than none (`ui`, section 8).\n- The page header keeps its own create button; the empty state repeats the\n  same action with the same words, so nothing moves when the first record\n  arrives.\n- No action the user cannot take: without permission to create, say who\n  can (\"Only admins add members\") rather than showing a disabled button.\n- When the action succeeds, the new record replaces the empty state in\n  place, and focus goes to it or to the list's heading.\n\n## 6. Illustration and sample data\n\n- An illustration is optional. When used: small (64 to 120px), from the\n  product's own world in its icon style, or a faded preview of what a\n  filled row will look like, which teaches the layout. Never blobs, people\n  at laptops, 3D shapes, a sad face, or one picture on every empty state.\n- It is decoration: `alt=\"\"` or `aria-hidden=\"true\"`, coloured from the\n  tokens so it holds in the dark theme (`ui-themes`).\n- None in tables, small blocks or search results: the words do it.\n- Sample data only on request (\"Explore with sample data\"), labelled on\n  every record and in a banner above the list, removable in one action, and\n  kept out of counts, reports, exports, billing and anything sent to real\n  people. A template is often the better second action.\n\n## 7. Never empty when it is not\n\n- Loading: a skeleton after about 200ms (`ui-part-loading`), never \"No\n  results\" while the first request is in flight.\n- Refetching after a filter change: keep the previous rows, dimmed, until\n  the new answer arrives (`placeholderData: keepPreviousData` in TanStack\n  Query), so a quick filter does not flash an empty state.\n- Typing a search: judge the settled query (debounced 200 to 300ms), not\n  each keystroke.\n- Failed: an error in the same region with what failed and Retry, keeping\n  the last good data when there is some (`frontend-errors`).\n- The last record deleted: the view becomes cleared or first use, with the\n  undo toast still on screen (`ui-part-notifications`).\n- On a dashboard, only the block that is empty says so; the others carry\n  on.\n\n## 8. Accessibility, phone, themes, motion\n\n- A heading at the level the region's outline needs, the body in a `p`,\n  the action a real control with its words.\n- For a search, the polite status region that says \"24 results\" says \"No\n  results for tolkein\" once the query settles (`role=\"status\"`, in the page\n  before its text changes). A first-use state is not announced: it is\n  content.\n- After Clear filters, focus goes to the search field or the results\n  heading, not to the top of the page.\n- On a phone: the same block with 32 to 48px of padding, under the search\n  bar, the action at least 44px tall.\n- Muted text, illustration and action from tokens in both themes\n  (`ui-themes`); the swap between empty and filled is a fade of 150 to\n  200ms or nothing (`motion-interface`, section 9).\n\n## Check it\n\n- Force every state on every list and block: a fresh account, a search\n  that matches nothing, filters that empty the list, an empty built-in\n  view, a user without access, the endpoint failing (block the request in\n  DevTools, or an MSW handler returning 500), and a throttled network.\n  Each shows its own words; none says \"No results\" before data arrives.\n- Delete the last record, then undo.\n- `preview` at 360, 768 and 1440px, with `login` for screens behind\n  sign-in: the block sits in its region, the toolbar stays, the action is\n  44px on a phone.\n- `ui_check` for generic copy and stock illustrations.\n- A screen reader hears the no-results message once, not per keystroke.\n\n## Avoid\n\n\"No data\" for every kind; an empty state while loading or after a failed\nrequest; the whole page replaced, with the filters that caused it hidden; a\nlarge generic illustration pushing the action out of view; jokes on errors\nor permission screens; a disabled button with no reason; two or three equal\nbuttons; sample data that looks real, cannot be removed or leaks into\nreports; first-use wording on a list that is merely filtered.\n",{"name":5,"description":7},"main","38293fe1b096e6bf3646c7344c38786ed688f464","crates\u002Fenowx-core\u002Fskills\u002Fui-part-empty-states",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":46,"prompt":56,"zipAvailable":57},[47,50,53],{"tool":48,"command":49},"npx","npx skills add enowdev\u002Fenowxcli --skill ui-part-empty-states",{"tool":51,"command":52},"bunx","bunx skills add enowdev\u002Fenowxcli --skill ui-part-empty-states",{"tool":54,"command":55},"pnpm","pnpm dlx skills add enowdev\u002Fenowxcli --skill ui-part-empty-states","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-part-empty-states\u002FSKILL.md",true,[],[60,76,100,114,141,162],{"skillNo":61,"name":62,"nameZh":6,"description":63,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":71,"publishedAt":31},"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",[66],{"categoryNo":67,"categoryName":68,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[72,73,74,75,26],"demo skill","demo","tests","project",{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":90,"publishedAt":31},"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",[82,85],{"categoryNo":83,"categoryName":84,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[78,91,92,20,93,94,26,95,96,97,98,99],"text","emails","drop","document","page","voice","notifications","documentation","translate",{"skillNo":101,"name":19,"nameZh":6,"description":102,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":108,"publishedAt":31},"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",[105],{"categoryNo":106,"categoryName":107,"taxonomyType":88,"taxonomyTypeDesc":89},"01JBSEEDCAT000000000000032","设计师",[19,109,110,111,112,95,113,26,25],"icons","components","SET","responsive","layout",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":118,"categories":119,"keywords":126,"publishedAt":31},"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",[120,123],{"categoryNo":121,"categoryName":122,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":124,"categoryName":125,"taxonomyType":88,"taxonomyTypeDesc":89},"01JBSEEDCAT000000000000030","开发工程师",[19,127,128,129,130,131,132,133,134,26,25,135,95,136,137,138,109,139,140],"ui themes","switching","photos","tokens","drawing","focus","maps","Art","flash","code","Charts","content","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":31},"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":83,"categoryName":84,"taxonomyType":69,"taxonomyTypeDesc":70},{"categoryNo":124,"categoryName":125,"taxonomyType":88,"taxonomyTypeDesc":89},{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},[151,19,152,110,153,154,136,155,156,157,113,130,158,159,160,26,25,95,24,161],"structure","ui structure","pricing","dashboard","Blueprint","article","anatomy","styling","primitives","list","how",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":175,"publishedAt":31},"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",[168,171,174],{"categoryNo":169,"categoryName":170,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":172,"categoryName":173,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":106,"categoryName":107,"taxonomyType":88,"taxonomyTypeDesc":89},[19,176,177,178,179,180,181,182,113,75,183,184,26,185,186,187,188,189,190,191],"vue","stack","ui stack vue","forms","pages","watch","runtime","transitions","fetch","pinia","nuxt","template","server","config","directory","testing"]