@nurix/etna 0.19.11 → 0.19.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (494) hide show
  1. package/README.md +6 -4
  2. package/data/harness-index.json +1 -1
  3. package/data/harnesses/code/agents/maintenance.md +1 -1
  4. package/data/harnesses/code/harness.json +1 -1
  5. package/data/harnesses/code/rules/frontend.md +5 -5
  6. package/data/harnesses/code/skills/design/SKILL.md +70 -50
  7. package/data/harnesses/code/skills/design/components/charts.md +76 -0
  8. package/data/harnesses/code/skills/design/components/collections.md +132 -0
  9. package/data/harnesses/code/skills/design/components/feedback.md +47 -0
  10. package/data/harnesses/code/skills/design/components/hooks.md +35 -0
  11. package/data/harnesses/code/skills/design/components/index.md +143 -0
  12. package/data/harnesses/code/skills/design/components/inputs.md +327 -0
  13. package/data/harnesses/code/skills/design/components/layout.md +52 -0
  14. package/data/harnesses/code/skills/design/components/media.md +66 -0
  15. package/data/harnesses/code/skills/design/components/motion.md +82 -0
  16. package/data/harnesses/code/skills/design/components/navigation.md +29 -0
  17. package/data/harnesses/code/skills/design/components/overlays.md +72 -0
  18. package/data/harnesses/code/skills/design/components/setup.md +40 -0
  19. package/data/harnesses/code/skills/design/components/typography.md +46 -0
  20. package/data/harnesses/code/skills/design/components/utils.md +37 -0
  21. package/data/harnesses/code/skills/design/data/blueprints/browse.md +38 -0
  22. package/data/harnesses/code/skills/design/data/blueprints/creation-flow.md +38 -0
  23. package/data/harnesses/code/skills/design/data/blueprints/dashboard.md +38 -0
  24. package/data/harnesses/code/skills/design/data/blueprints/grid.md +38 -0
  25. package/data/harnesses/code/skills/design/data/blueprints/queue.md +38 -0
  26. package/data/harnesses/code/skills/design/data/blueprints/record-detail.md +38 -0
  27. package/data/harnesses/code/skills/design/data/blueprints/settings.md +38 -0
  28. package/data/harnesses/code/skills/design/data/chart-styling/Readme.md +33 -0
  29. package/data/harnesses/code/skills/design/data/chart-styling/carbon-accessible-alert-semantic.md +19 -0
  30. package/data/harnesses/code/skills/design/data/chart-styling/carbon-monochrome-sequential-trend.md +19 -0
  31. package/data/harnesses/code/skills/design/data/chart-styling/datadog-classic-six-aligned.md +19 -0
  32. package/data/harnesses/code/skills/design/data/chart-styling/datawrapper-tiered-gray-hierarchy.md +19 -0
  33. package/data/harnesses/code/skills/design/data/chart-styling/econ-red-rule-horizontal.md +19 -0
  34. package/data/harnesses/code/skills/design/data/chart-styling/financial-diverging-threshold-overlay.md +19 -0
  35. package/data/harnesses/code/skills/design/data/chart-styling/ft-vocabulary-ranked-muted.md +19 -0
  36. package/data/harnesses/code/skills/design/data/chart-styling/grafana-dark-threshold-bands.md +19 -0
  37. package/data/harnesses/code/skills/design/data/chart-styling/material-rounded-explicit-label.md +19 -0
  38. package/data/harnesses/code/skills/design/data/chart-styling/nyt-ghost-grid-direct-label.md +19 -0
  39. package/data/harnesses/code/skills/design/data/chart-styling/plot-currentcolor-inherit.md +19 -0
  40. package/data/harnesses/code/skills/design/data/chart-styling/saas-gradient-glow-area.md +19 -0
  41. package/data/harnesses/code/skills/design/data/chart-styling/shadcn-composable-css-vars.md +19 -0
  42. package/data/harnesses/code/skills/design/data/charts/census.csv +58 -0
  43. package/data/harnesses/code/skills/design/data/checklists/browse.md +21 -0
  44. package/data/harnesses/code/skills/design/data/checklists/creation-flow.md +20 -0
  45. package/data/harnesses/code/skills/design/data/checklists/dashboard.md +21 -0
  46. package/data/harnesses/code/skills/design/data/checklists/grid.md +21 -0
  47. package/data/harnesses/code/skills/design/data/checklists/queue.md +21 -0
  48. package/data/harnesses/code/skills/design/data/checklists/record-detail.md +21 -0
  49. package/data/harnesses/code/skills/design/data/checklists/settings.md +21 -0
  50. package/data/harnesses/code/skills/design/data/chrome/board-column.md +68 -0
  51. package/data/harnesses/code/skills/design/data/chrome/data-table.md +63 -0
  52. package/data/harnesses/code/skills/design/data/chrome/side-panel.md +60 -0
  53. package/data/harnesses/code/skills/design/data/chrome/sidebar.md +78 -0
  54. package/data/harnesses/code/skills/design/data/chrome/stat-cards.md +62 -0
  55. package/data/harnesses/code/skills/design/data/chrome/topbar.md +65 -0
  56. package/data/harnesses/code/skills/design/data/color/accent-presets.md +90 -0
  57. package/data/harnesses/code/skills/design/data/color/aesop-earth-mute.md +91 -0
  58. package/data/harnesses/code/skills/design/data/color/arc-peach-play.md +90 -0
  59. package/data/harnesses/code/skills/design/data/color/attio-hunter-teal.md +90 -0
  60. package/data/harnesses/code/skills/design/data/color/carbon-cyan-signal.md +90 -0
  61. package/data/harnesses/code/skills/design/data/color/clay-parchment.md +90 -0
  62. package/data/harnesses/code/skills/design/data/color/duolingo-feather.md +90 -0
  63. package/data/harnesses/code/skills/design/data/color/geist-mono-signal.md +90 -0
  64. package/data/harnesses/code/skills/design/data/color/linear-graphite-violet.md +90 -0
  65. package/data/harnesses/code/skills/design/data/color/mercury-onyx-cobalt.md +90 -0
  66. package/data/harnesses/code/skills/design/data/color/notion-paper-ink.md +90 -0
  67. package/data/harnesses/code/skills/design/data/color/radix-slate-iris.md +90 -0
  68. package/data/harnesses/code/skills/design/data/color/raycast-void-spectrum.md +90 -0
  69. package/data/harnesses/code/skills/design/data/color/spectrum-celery-fuchsia.md +90 -0
  70. package/data/harnesses/code/skills/design/data/color/stripe-blurple-ruby.md +90 -0
  71. package/data/harnesses/code/skills/design/data/color/superhuman-cod-picton.md +89 -0
  72. package/data/harnesses/code/skills/design/data/corpora/operations-review/companies.csv +15 -0
  73. package/data/harnesses/code/skills/design/data/corpora/operations-review/corpus.md +87 -0
  74. package/data/harnesses/code/skills/design/data/corpora/operations-review/people.csv +25 -0
  75. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/companies.csv +15 -0
  76. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/corpus.md +83 -0
  77. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/people.csv +25 -0
  78. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/companies.csv +15 -0
  79. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/corpus.md +89 -0
  80. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/people.csv +25 -0
  81. package/data/harnesses/code/skills/design/data/elevation/ant-design-directional-shadow.md +19 -0
  82. package/data/harnesses/code/skills/design/data/elevation/apple-liquid-glass-material.md +18 -0
  83. package/data/harnesses/code/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +20 -0
  84. package/data/harnesses/code/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +20 -0
  85. package/data/harnesses/code/skills/design/data/elevation/github-primer-sparing-shadow.md +19 -0
  86. package/data/harnesses/code/skills/design/data/elevation/ibm-carbon-layer-and-border.md +19 -0
  87. package/data/harnesses/code/skills/design/data/elevation/linear-dark-surface-ladder.md +17 -0
  88. package/data/harnesses/code/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +19 -0
  89. package/data/harnesses/code/skills/design/data/elevation/material-3-tonal-elevation.md +21 -0
  90. package/data/harnesses/code/skills/design/data/elevation/neobrutalist-hard-offset.md +19 -0
  91. package/data/harnesses/code/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +18 -0
  92. package/data/harnesses/code/skills/design/data/elevation/notion-warm-minimal-hairline.md +17 -0
  93. package/data/harnesses/code/skills/design/data/elevation/polaris-elevation-inset-bevel.md +21 -0
  94. package/data/harnesses/code/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +19 -0
  95. package/data/harnesses/code/skills/design/data/elevation/shadcn-neutral-derived-radius.md +19 -0
  96. package/data/harnesses/code/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +18 -0
  97. package/data/harnesses/code/skills/design/data/elevation/tailwind-default-utility-scale.md +19 -0
  98. package/data/harnesses/code/skills/design/data/elevation/vercel-geist-shadow-as-border.md +20 -0
  99. package/data/harnesses/code/skills/design/data/gradients/amber-attention-fill.md +16 -0
  100. package/data/harnesses/code/skills/design/data/gradients/cloud-shadow-wash.md +16 -0
  101. package/data/harnesses/code/skills/design/data/gradients/confident-lavender-wash.md +16 -0
  102. package/data/harnesses/code/skills/design/data/gradients/ember-ship-flare.md +18 -0
  103. package/data/harnesses/code/skills/design/data/gradients/full-metal-wash.md +16 -0
  104. package/data/harnesses/code/skills/design/data/gradients/indigo-ruby-cta-band.md +18 -0
  105. package/data/harnesses/code/skills/design/data/gradients/linear-graphite-wash.md +18 -0
  106. package/data/harnesses/code/skills/design/data/gradients/marble-quartz-wash.md +16 -0
  107. package/data/harnesses/code/skills/design/data/gradients/midnight-aurora-panel.md +16 -0
  108. package/data/harnesses/code/skills/design/data/gradients/neutral-volume-fill.md +16 -0
  109. package/data/harnesses/code/skills/design/data/gradients/revenue-uptrend-fill.md +16 -0
  110. package/data/harnesses/code/skills/design/data/gradients/risk-decline-fill.md +16 -0
  111. package/data/harnesses/code/skills/design/data/gradients/signal-blue-develop.md +18 -0
  112. package/data/harnesses/code/skills/design/data/gradients/slate-mist-wash.md +16 -0
  113. package/data/harnesses/code/skills/design/data/gradients/stripe-atmosphere-mesh.md +18 -0
  114. package/data/harnesses/code/skills/design/data/gradients/teal-signal-accent.md +16 -0
  115. package/data/harnesses/code/skills/design/data/gradients/violet-magenta-promo.md +16 -0
  116. package/data/harnesses/code/skills/design/data/iconography.md +199 -0
  117. package/data/harnesses/code/skills/design/data/motion/accordion-expand.md +18 -0
  118. package/data/harnesses/code/skills/design/data/motion/destructive-hold-confirm.md +18 -0
  119. package/data/harnesses/code/skills/design/data/motion/drag-dismiss-momentum.md +18 -0
  120. package/data/harnesses/code/skills/design/data/motion/empty-state-arrive.md +18 -0
  121. package/data/harnesses/code/skills/design/data/motion/hover-lift.md +18 -0
  122. package/data/harnesses/code/skills/design/data/motion/modal-center-arrive.md +18 -0
  123. package/data/harnesses/code/skills/design/data/motion/number-ticker-roll.md +18 -0
  124. package/data/harnesses/code/skills/design/data/motion/onboarding-bounce.md +18 -0
  125. package/data/harnesses/code/skills/design/data/motion/panel-slide.md +18 -0
  126. package/data/harnesses/code/skills/design/data/motion/press-feedback.md +18 -0
  127. package/data/harnesses/code/skills/design/data/motion/progress-linear-loop.md +18 -0
  128. package/data/harnesses/code/skills/design/data/motion/route-crossfade.md +18 -0
  129. package/data/harnesses/code/skills/design/data/motion/rubber-band-overscroll.md +18 -0
  130. package/data/harnesses/code/skills/design/data/motion/skeleton-shimmer.md +18 -0
  131. package/data/harnesses/code/skills/design/data/motion/stagger-arrive.md +18 -0
  132. package/data/harnesses/code/skills/design/data/motion/toast-enter-stack.md +18 -0
  133. package/data/harnesses/code/skills/design/data/motion/tooltip-chain-instant.md +18 -0
  134. package/data/harnesses/code/skills/design/data/motion/trigger-anchored-reveal.md +18 -0
  135. package/data/harnesses/code/skills/design/data/tells.csv +34 -0
  136. package/data/harnesses/code/skills/design/data/typography/anton-work-sans.md +17 -0
  137. package/data/harnesses/code/skills/design/data/typography/archivo-black-archivo.md +17 -0
  138. package/data/harnesses/code/skills/design/data/typography/bitter-karla.md +17 -0
  139. package/data/harnesses/code/skills/design/data/typography/dm-serif-dm-sans.md +17 -0
  140. package/data/harnesses/code/skills/design/data/typography/fraunces-inter.md +17 -0
  141. package/data/harnesses/code/skills/design/data/typography/geist-geist-mono.md +17 -0
  142. package/data/harnesses/code/skills/design/data/typography/hubot-sans-mona-sans.md +17 -0
  143. package/data/harnesses/code/skills/design/data/typography/ibm-plex-sans-operator-single-family.md +17 -0
  144. package/data/harnesses/code/skills/design/data/typography/instrument-serif-instrument-sans.md +17 -0
  145. package/data/harnesses/code/skills/design/data/typography/inter-operator-single-family.md +17 -0
  146. package/data/harnesses/code/skills/design/data/typography/libre-baskerville-libre-franklin.md +17 -0
  147. package/data/harnesses/code/skills/design/data/typography/newsreader-inter.md +17 -0
  148. package/data/harnesses/code/skills/design/data/typography/playfair-display-source-sans.md +17 -0
  149. package/data/harnesses/code/skills/design/data/typography/public-sans-operator-single-family.md +17 -0
  150. package/data/harnesses/code/skills/design/data/typography/sohne-inter-fintech.md +17 -0
  151. package/data/harnesses/code/skills/design/data/typography/source-serif-source-sans.md +17 -0
  152. package/data/harnesses/code/skills/design/data/typography/space-grotesk-work-sans-space-mono.md +17 -0
  153. package/data/harnesses/code/skills/design/data/typography/spectral-manrope.md +17 -0
  154. package/data/harnesses/code/skills/design/data/voices/bright-collaborator.md +29 -0
  155. package/data/harnesses/code/skills/design/data/voices/direct-operator.md +29 -0
  156. package/data/harnesses/code/skills/design/data/voices/earnest-helper.md +29 -0
  157. package/data/harnesses/code/skills/design/data/voices/editorial-composed.md +29 -0
  158. package/data/harnesses/code/skills/design/data/voices/quiet-concierge.md +29 -0
  159. package/data/harnesses/code/skills/design/data/voices/warm-guide.md +29 -0
  160. package/data/harnesses/code/skills/design/design-md/SCHEMA.md +179 -0
  161. package/data/harnesses/code/skills/design/design-md/index.csv +67 -0
  162. package/data/harnesses/code/skills/design/design-md/library/airbnb.md +207 -0
  163. package/data/harnesses/code/skills/design/design-md/library/airtable.md +205 -0
  164. package/data/harnesses/code/skills/design/design-md/library/anthropic-claude.md +203 -0
  165. package/data/harnesses/code/skills/design/design-md/library/apple.md +206 -0
  166. package/data/harnesses/code/skills/design/design-md/library/binance.md +210 -0
  167. package/data/harnesses/code/skills/design/design-md/library/bmw.md +210 -0
  168. package/data/harnesses/code/skills/design/design-md/library/cal.md +209 -0
  169. package/data/harnesses/code/skills/design/design-md/library/clay.md +204 -0
  170. package/data/harnesses/code/skills/design/design-md/library/clickhouse.md +205 -0
  171. package/data/harnesses/code/skills/design/design-md/library/cohere.md +205 -0
  172. package/data/harnesses/code/skills/design/design-md/library/coinbase.md +198 -0
  173. package/data/harnesses/code/skills/design/design-md/library/composio.md +198 -0
  174. package/data/harnesses/code/skills/design/design-md/library/cursor.md +197 -0
  175. package/data/harnesses/code/skills/design/design-md/library/elevenlabs.md +199 -0
  176. package/data/harnesses/code/skills/design/design-md/library/expo.md +200 -0
  177. package/data/harnesses/code/skills/design/design-md/library/figma.md +199 -0
  178. package/data/harnesses/code/skills/design/design-md/library/framer.md +202 -0
  179. package/data/harnesses/code/skills/design/design-md/library/hashicorp.md +205 -0
  180. package/data/harnesses/code/skills/design/design-md/library/ibm.md +205 -0
  181. package/data/harnesses/code/skills/design/design-md/library/intercom.md +204 -0
  182. package/data/harnesses/code/skills/design/design-md/library/kraken.md +200 -0
  183. package/data/harnesses/code/skills/design/design-md/library/linear-app.md +198 -0
  184. package/data/harnesses/code/skills/design/design-md/library/lovable.md +199 -0
  185. package/data/harnesses/code/skills/design/design-md/library/meta.md +204 -0
  186. package/data/harnesses/code/skills/design/design-md/library/minimax.md +204 -0
  187. package/data/harnesses/code/skills/design/design-md/library/mintlify.md +210 -0
  188. package/data/harnesses/code/skills/design/design-md/library/miro.md +209 -0
  189. package/data/harnesses/code/skills/design/design-md/library/mistral-ai.md +201 -0
  190. package/data/harnesses/code/skills/design/design-md/library/mongodb.md +201 -0
  191. package/data/harnesses/code/skills/design/design-md/library/notion.md +204 -0
  192. package/data/harnesses/code/skills/design/design-md/library/nvidia.md +215 -0
  193. package/data/harnesses/code/skills/design/design-md/library/ollama.md +213 -0
  194. package/data/harnesses/code/skills/design/design-md/library/opencode-ai.md +216 -0
  195. package/data/harnesses/code/skills/design/design-md/library/posthog.md +218 -0
  196. package/data/harnesses/code/skills/design/design-md/library/raycast.md +214 -0
  197. package/data/harnesses/code/skills/design/design-md/library/replicate.md +202 -0
  198. package/data/harnesses/code/skills/design/design-md/library/resend.md +203 -0
  199. package/data/harnesses/code/skills/design/design-md/library/revolut.md +203 -0
  200. package/data/harnesses/code/skills/design/design-md/library/runwayml.md +203 -0
  201. package/data/harnesses/code/skills/design/design-md/library/sanity.md +200 -0
  202. package/data/harnesses/code/skills/design/design-md/library/sentry.md +201 -0
  203. package/data/harnesses/code/skills/design/design-md/library/shopify.md +202 -0
  204. package/data/harnesses/code/skills/design/design-md/library/slack.md +202 -0
  205. package/data/harnesses/code/skills/design/design-md/library/spacex.md +206 -0
  206. package/data/harnesses/code/skills/design/design-md/library/spotify.md +206 -0
  207. package/data/harnesses/code/skills/design/design-md/library/stripe.md +196 -0
  208. package/data/harnesses/code/skills/design/design-md/library/supabase.md +196 -0
  209. package/data/harnesses/code/skills/design/design-md/library/superhuman.md +194 -0
  210. package/data/harnesses/code/skills/design/design-md/library/tesla.md +198 -0
  211. package/data/harnesses/code/skills/design/design-md/library/theverge.md +199 -0
  212. package/data/harnesses/code/skills/design/design-md/library/together-ai.md +193 -0
  213. package/data/harnesses/code/skills/design/design-md/library/uber.md +195 -0
  214. package/data/harnesses/code/skills/design/design-md/library/vercel.md +195 -0
  215. package/data/harnesses/code/skills/design/design-md/library/voltagent.md +197 -0
  216. package/data/harnesses/code/skills/design/design-md/library/warp.md +196 -0
  217. package/data/harnesses/code/skills/design/design-md/library/webflow.md +197 -0
  218. package/data/harnesses/code/skills/design/design-md/library/wired.md +197 -0
  219. package/data/harnesses/code/skills/design/design-md/library/wise.md +198 -0
  220. package/data/harnesses/code/skills/design/design-md/library/x-ai.md +199 -0
  221. package/data/harnesses/code/skills/design/design-md/library/zapier.md +198 -0
  222. package/data/harnesses/code/skills/design/design-md/nurix.md +214 -0
  223. package/data/harnesses/code/skills/design/design-md/variants/editorial-luxury.md +184 -0
  224. package/data/harnesses/code/skills/design/design-md/variants/expressive-saas.md +216 -0
  225. package/data/harnesses/code/skills/design/design-md/variants/quiet-premium.md +211 -0
  226. package/data/harnesses/code/skills/design/design-md/variants/terse-dense-operator.md +212 -0
  227. package/data/harnesses/code/skills/design/design-md/variants/warm-approachable.md +216 -0
  228. package/data/harnesses/code/skills/design/references/compose.md +23 -0
  229. package/data/harnesses/code/skills/design/references/content.md +28 -0
  230. package/data/harnesses/code/skills/design/references/emission.md +21 -0
  231. package/data/harnesses/code/skills/design/references/existing-apps.md +27 -0
  232. package/data/harnesses/code/skills/design/references/intake.md +36 -0
  233. package/data/harnesses/code/skills/design/references/object-pass.md +24 -0
  234. package/data/harnesses/code/skills/design/references/ship-gate.md +29 -0
  235. package/data/harnesses/code/skills/design/references/ux-patterns/Readme.md +195 -0
  236. package/data/harnesses/code/skills/design/references/ux-patterns/ai-layer.md +49 -0
  237. package/data/harnesses/code/skills/design/references/ux-patterns/attributes-lifecycle.md +43 -0
  238. package/data/harnesses/code/skills/design/references/ux-patterns/container-choice.md +44 -0
  239. package/data/harnesses/code/skills/design/references/ux-patterns/creation-paths.md +46 -0
  240. package/data/harnesses/code/skills/design/references/ux-patterns/dashboards.md +42 -0
  241. package/data/harnesses/code/skills/design/references/ux-patterns/modes.md +42 -0
  242. package/data/harnesses/code/skills/design/references/ux-patterns/object-model.md +46 -0
  243. package/data/harnesses/code/skills/design/references/ux-patterns/page-archetype.md +48 -0
  244. package/data/harnesses/code/skills/design/references/ux-patterns/promotion-demotion.md +37 -0
  245. package/data/harnesses/code/skills/design/references/ux-patterns/settings.md +42 -0
  246. package/data/harnesses/code/skills/design/references/ux-patterns/standard-pages.md +46 -0
  247. package/data/harnesses/code/skills/design/references/ux-patterns/state-matrix.md +41 -0
  248. package/data/harnesses/code/skills/design/references/ux-patterns/table-mechanics.md +48 -0
  249. package/data/harnesses/code/skills/design/references/ux-patterns/verbs.md +45 -0
  250. package/data/harnesses/code/skills/design/references/ux-patterns/viewer-context.md +40 -0
  251. package/data/harnesses/code/skills/design/scripts/README-validator.md +27 -0
  252. package/data/harnesses/code/skills/design/scripts/select-chart.mjs +596 -0
  253. package/data/harnesses/code/skills/design/scripts/validate-design-md.mjs +1198 -0
  254. package/data/harnesses/discussion/agents/discussion-baseline.md +1 -1
  255. package/data/harnesses/discussion/harness.json +1 -1
  256. package/data/harnesses/etna/agents/maintenance.md +1 -1
  257. package/data/harnesses/etna/harness.json +1 -1
  258. package/data/harnesses/hr/CLAUDE.md +1 -1
  259. package/data/harnesses/hr/harness.json +1 -1
  260. package/package.json +1 -1
  261. package/data/harnesses/code/skills/design/data/catalog/rules.csv +0 -137
  262. package/data/harnesses/code/skills/design/data/combinations/Readme.md +0 -33
  263. package/data/harnesses/code/skills/design/data/combinations/accent-presets.md +0 -113
  264. package/data/harnesses/code/skills/design/data/combinations/charts.csv +0 -33
  265. package/data/harnesses/code/skills/design/data/combinations/fonts-known.json +0 -448
  266. package/data/harnesses/code/skills/design/data/combinations/icons.csv +0 -157
  267. package/data/harnesses/code/skills/design/data/combinations/landing.csv +0 -38
  268. package/data/harnesses/code/skills/design/data/combinations/lucide-names.json +0 -2001
  269. package/data/harnesses/code/skills/design/data/combinations/manifest.json +0 -330
  270. package/data/harnesses/code/skills/design/data/combinations/motion.csv +0 -10
  271. package/data/harnesses/code/skills/design/data/combinations/palettes.csv +0 -92
  272. package/data/harnesses/code/skills/design/data/combinations/product-router.csv +0 -80
  273. package/data/harnesses/code/skills/design/data/combinations/styles.csv +0 -67
  274. package/data/harnesses/code/skills/design/data/combinations/typography.csv +0 -64
  275. package/data/harnesses/code/skills/design/data/design-md/SCHEMA.md +0 -106
  276. package/data/harnesses/code/skills/design/data/design-md/library/airbnb.md +0 -154
  277. package/data/harnesses/code/skills/design/data/design-md/library/airtable.md +0 -151
  278. package/data/harnesses/code/skills/design/data/design-md/library/anthropic-claude.md +0 -139
  279. package/data/harnesses/code/skills/design/data/design-md/library/apple.md +0 -139
  280. package/data/harnesses/code/skills/design/data/design-md/library/binance.md +0 -140
  281. package/data/harnesses/code/skills/design/data/design-md/library/bmw.md +0 -140
  282. package/data/harnesses/code/skills/design/data/design-md/library/cal.md +0 -140
  283. package/data/harnesses/code/skills/design/data/design-md/library/clay.md +0 -139
  284. package/data/harnesses/code/skills/design/data/design-md/library/clickhouse.md +0 -139
  285. package/data/harnesses/code/skills/design/data/design-md/library/cohere.md +0 -147
  286. package/data/harnesses/code/skills/design/data/design-md/library/coinbase.md +0 -156
  287. package/data/harnesses/code/skills/design/data/design-md/library/composio.md +0 -138
  288. package/data/harnesses/code/skills/design/data/design-md/library/cursor.md +0 -138
  289. package/data/harnesses/code/skills/design/data/design-md/library/elevenlabs.md +0 -137
  290. package/data/harnesses/code/skills/design/data/design-md/library/expo.md +0 -148
  291. package/data/harnesses/code/skills/design/data/design-md/library/figma.md +0 -141
  292. package/data/harnesses/code/skills/design/data/design-md/library/framer.md +0 -156
  293. package/data/harnesses/code/skills/design/data/design-md/library/hashicorp.md +0 -140
  294. package/data/harnesses/code/skills/design/data/design-md/library/ibm.md +0 -153
  295. package/data/harnesses/code/skills/design/data/design-md/library/intercom.md +0 -158
  296. package/data/harnesses/code/skills/design/data/design-md/library/kraken.md +0 -156
  297. package/data/harnesses/code/skills/design/data/design-md/library/linear-app.md +0 -122
  298. package/data/harnesses/code/skills/design/data/design-md/library/lovable.md +0 -140
  299. package/data/harnesses/code/skills/design/data/design-md/library/meta.md +0 -139
  300. package/data/harnesses/code/skills/design/data/design-md/library/minimax.md +0 -139
  301. package/data/harnesses/code/skills/design/data/design-md/library/mintlify.md +0 -139
  302. package/data/harnesses/code/skills/design/data/design-md/library/miro.md +0 -153
  303. package/data/harnesses/code/skills/design/data/design-md/library/mistral-ai.md +0 -140
  304. package/data/harnesses/code/skills/design/data/design-md/library/mongodb.md +0 -155
  305. package/data/harnesses/code/skills/design/data/design-md/library/notion.md +0 -140
  306. package/data/harnesses/code/skills/design/data/design-md/library/nvidia.md +0 -141
  307. package/data/harnesses/code/skills/design/data/design-md/library/ollama.md +0 -145
  308. package/data/harnesses/code/skills/design/data/design-md/library/opencode-ai.md +0 -142
  309. package/data/harnesses/code/skills/design/data/design-md/library/posthog.md +0 -152
  310. package/data/harnesses/code/skills/design/data/design-md/library/raycast.md +0 -137
  311. package/data/harnesses/code/skills/design/data/design-md/library/replicate.md +0 -140
  312. package/data/harnesses/code/skills/design/data/design-md/library/resend.md +0 -170
  313. package/data/harnesses/code/skills/design/data/design-md/library/revolut.md +0 -145
  314. package/data/harnesses/code/skills/design/data/design-md/library/runwayml.md +0 -137
  315. package/data/harnesses/code/skills/design/data/design-md/library/sanity.md +0 -168
  316. package/data/harnesses/code/skills/design/data/design-md/library/sentry.md +0 -163
  317. package/data/harnesses/code/skills/design/data/design-md/library/shopify.md +0 -147
  318. package/data/harnesses/code/skills/design/data/design-md/library/slack.md +0 -158
  319. package/data/harnesses/code/skills/design/data/design-md/library/spacex.md +0 -171
  320. package/data/harnesses/code/skills/design/data/design-md/library/spotify.md +0 -166
  321. package/data/harnesses/code/skills/design/data/design-md/library/stripe.md +0 -160
  322. package/data/harnesses/code/skills/design/data/design-md/library/supabase.md +0 -173
  323. package/data/harnesses/code/skills/design/data/design-md/library/superhuman.md +0 -145
  324. package/data/harnesses/code/skills/design/data/design-md/library/tesla.md +0 -153
  325. package/data/harnesses/code/skills/design/data/design-md/library/theverge.md +0 -167
  326. package/data/harnesses/code/skills/design/data/design-md/library/together-ai.md +0 -140
  327. package/data/harnesses/code/skills/design/data/design-md/library/uber.md +0 -140
  328. package/data/harnesses/code/skills/design/data/design-md/library/vercel.md +0 -140
  329. package/data/harnesses/code/skills/design/data/design-md/library/voltagent.md +0 -130
  330. package/data/harnesses/code/skills/design/data/design-md/library/warp.md +0 -140
  331. package/data/harnesses/code/skills/design/data/design-md/library/webflow.md +0 -140
  332. package/data/harnesses/code/skills/design/data/design-md/library/wired.md +0 -139
  333. package/data/harnesses/code/skills/design/data/design-md/library/wise.md +0 -137
  334. package/data/harnesses/code/skills/design/data/design-md/library/x-ai.md +0 -138
  335. package/data/harnesses/code/skills/design/data/design-md/library/zapier.md +0 -158
  336. package/data/harnesses/code/skills/design/data/design-md/nurix.md +0 -138
  337. package/data/harnesses/code/skills/design/data/design-tokens/SCHEMA.md +0 -695
  338. package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.resolver.json +0 -20
  339. package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.tokens.json +0 -1272
  340. package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.resolver.json +0 -20
  341. package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.tokens.json +0 -1268
  342. package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.resolver.json +0 -20
  343. package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.tokens.json +0 -1273
  344. package/data/harnesses/code/skills/design/data/design-tokens/apple/design.resolver.json +0 -20
  345. package/data/harnesses/code/skills/design/data/design-tokens/apple/design.tokens.json +0 -1262
  346. package/data/harnesses/code/skills/design/data/design-tokens/binance/design.resolver.json +0 -20
  347. package/data/harnesses/code/skills/design/data/design-tokens/binance/design.tokens.json +0 -1257
  348. package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.resolver.json +0 -20
  349. package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.tokens.json +0 -1270
  350. package/data/harnesses/code/skills/design/data/design-tokens/cal/design.resolver.json +0 -20
  351. package/data/harnesses/code/skills/design/data/design-tokens/cal/design.tokens.json +0 -1270
  352. package/data/harnesses/code/skills/design/data/design-tokens/clay/design.resolver.json +0 -20
  353. package/data/harnesses/code/skills/design/data/design-tokens/clay/design.tokens.json +0 -1261
  354. package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.resolver.json +0 -20
  355. package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.tokens.json +0 -1268
  356. package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.resolver.json +0 -20
  357. package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.tokens.json +0 -1281
  358. package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.resolver.json +0 -20
  359. package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.tokens.json +0 -1262
  360. package/data/harnesses/code/skills/design/data/design-tokens/composio/design.resolver.json +0 -20
  361. package/data/harnesses/code/skills/design/data/design-tokens/composio/design.tokens.json +0 -1271
  362. package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.resolver.json +0 -20
  363. package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.tokens.json +0 -1276
  364. package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.resolver.json +0 -20
  365. package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.tokens.json +0 -1293
  366. package/data/harnesses/code/skills/design/data/design-tokens/expo/design.resolver.json +0 -20
  367. package/data/harnesses/code/skills/design/data/design-tokens/expo/design.tokens.json +0 -1270
  368. package/data/harnesses/code/skills/design/data/design-tokens/figma/design.resolver.json +0 -20
  369. package/data/harnesses/code/skills/design/data/design-tokens/figma/design.tokens.json +0 -1276
  370. package/data/harnesses/code/skills/design/data/design-tokens/framer/design.resolver.json +0 -20
  371. package/data/harnesses/code/skills/design/data/design-tokens/framer/design.tokens.json +0 -1267
  372. package/data/harnesses/code/skills/design/data/design-tokens/goldens.json +0 -251
  373. package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.resolver.json +0 -20
  374. package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.tokens.json +0 -1273
  375. package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.resolver.json +0 -20
  376. package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.tokens.json +0 -1286
  377. package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.resolver.json +0 -20
  378. package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.tokens.json +0 -1290
  379. package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.resolver.json +0 -20
  380. package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.tokens.json +0 -1270
  381. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.resolver.json +0 -23
  382. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.dark.json +0 -599
  383. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.json +0 -1272
  384. package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.resolver.json +0 -20
  385. package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.tokens.json +0 -1267
  386. package/data/harnesses/code/skills/design/data/design-tokens/meta/design.resolver.json +0 -20
  387. package/data/harnesses/code/skills/design/data/design-tokens/meta/design.tokens.json +0 -1289
  388. package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.resolver.json +0 -20
  389. package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.tokens.json +0 -1258
  390. package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.resolver.json +0 -20
  391. package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.tokens.json +0 -1284
  392. package/data/harnesses/code/skills/design/data/design-tokens/miro/design.resolver.json +0 -20
  393. package/data/harnesses/code/skills/design/data/design-tokens/miro/design.tokens.json +0 -1291
  394. package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.resolver.json +0 -20
  395. package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.tokens.json +0 -1263
  396. package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.resolver.json +0 -20
  397. package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.tokens.json +0 -1270
  398. package/data/harnesses/code/skills/design/data/design-tokens/notion/design.resolver.json +0 -20
  399. package/data/harnesses/code/skills/design/data/design-tokens/notion/design.tokens.json +0 -1261
  400. package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.resolver.json +0 -20
  401. package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.tokens.json +0 -1209
  402. package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.resolver.json +0 -20
  403. package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.tokens.json +0 -1265
  404. package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.resolver.json +0 -20
  405. package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.tokens.json +0 -1253
  406. package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.resolver.json +0 -20
  407. package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.tokens.json +0 -1268
  408. package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.resolver.json +0 -20
  409. package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.tokens.json +0 -1261
  410. package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.resolver.json +0 -20
  411. package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.tokens.json +0 -1263
  412. package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.resolver.json +0 -20
  413. package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.tokens.json +0 -1266
  414. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.resolver.json +0 -23
  415. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.dark.json +0 -623
  416. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.json +0 -1276
  417. package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.resolver.json +0 -20
  418. package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.tokens.json +0 -1264
  419. package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.resolver.json +0 -20
  420. package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.tokens.json +0 -1268
  421. package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.resolver.json +0 -20
  422. package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.tokens.json +0 -1270
  423. package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.resolver.json +0 -20
  424. package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.tokens.json +0 -1288
  425. package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.resolver.json +0 -20
  426. package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.tokens.json +0 -1272
  427. package/data/harnesses/code/skills/design/data/design-tokens/slack/design.resolver.json +0 -20
  428. package/data/harnesses/code/skills/design/data/design-tokens/slack/design.tokens.json +0 -1265
  429. package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.resolver.json +0 -20
  430. package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.tokens.json +0 -1287
  431. package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.resolver.json +0 -20
  432. package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.tokens.json +0 -1286
  433. package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.resolver.json +0 -20
  434. package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.tokens.json +0 -1285
  435. package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.resolver.json +0 -20
  436. package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.tokens.json +0 -1287
  437. package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.resolver.json +0 -20
  438. package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.tokens.json +0 -1278
  439. package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.resolver.json +0 -20
  440. package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.tokens.json +0 -1269
  441. package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.resolver.json +0 -20
  442. package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.tokens.json +0 -1285
  443. package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.resolver.json +0 -20
  444. package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.tokens.json +0 -1303
  445. package/data/harnesses/code/skills/design/data/design-tokens/uber/design.resolver.json +0 -20
  446. package/data/harnesses/code/skills/design/data/design-tokens/uber/design.tokens.json +0 -1274
  447. package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.resolver.json +0 -20
  448. package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.tokens.json +0 -1296
  449. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.resolver.json +0 -23
  450. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.dark.json +0 -612
  451. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.json +0 -1282
  452. package/data/harnesses/code/skills/design/data/design-tokens/warp/design.resolver.json +0 -20
  453. package/data/harnesses/code/skills/design/data/design-tokens/warp/design.tokens.json +0 -1287
  454. package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.resolver.json +0 -20
  455. package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.tokens.json +0 -1268
  456. package/data/harnesses/code/skills/design/data/design-tokens/wired/design.resolver.json +0 -20
  457. package/data/harnesses/code/skills/design/data/design-tokens/wired/design.tokens.json +0 -1276
  458. package/data/harnesses/code/skills/design/data/design-tokens/wise/design.resolver.json +0 -20
  459. package/data/harnesses/code/skills/design/data/design-tokens/wise/design.tokens.json +0 -1273
  460. package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.resolver.json +0 -20
  461. package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.tokens.json +0 -1296
  462. package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.resolver.json +0 -20
  463. package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.tokens.json +0 -1286
  464. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/command-center.tsx +0 -249
  465. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/create-edit.tsx +0 -249
  466. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/dashboard.tsx +0 -225
  467. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/entity-detail.tsx +0 -249
  468. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/list-detail.tsx +0 -224
  469. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/log-stream.tsx +0 -249
  470. package/data/harnesses/code/skills/design/data/operator-pack/fixtures.md +0 -88
  471. package/data/harnesses/code/skills/design/data/operator-pack/surface-catalog.md +0 -132
  472. package/data/harnesses/code/skills/design/data/operator-pack/trust-rubric.md +0 -76
  473. package/data/harnesses/code/skills/design/references/create.md +0 -173
  474. package/data/harnesses/code/skills/design/references/diagnosis.md +0 -108
  475. package/data/harnesses/code/skills/design/references/hard-rules.md +0 -177
  476. package/data/harnesses/code/skills/design/references/improve.md +0 -116
  477. package/data/harnesses/code/skills/design/references/interaction.md +0 -77
  478. package/data/harnesses/code/skills/design/references/introspect.md +0 -100
  479. package/data/harnesses/code/skills/design/references/lifecycle.md +0 -73
  480. package/data/harnesses/code/skills/design/references/personality.md +0 -575
  481. package/data/harnesses/code/skills/design/references/structure.md +0 -159
  482. package/data/harnesses/code/skills/design/scripts/convert-design-md.mjs +0 -1312
  483. package/data/harnesses/code/skills/design/scripts/derive-personality.mjs +0 -1498
  484. package/data/harnesses/code/skills/design/scripts/generate-fixtures.mjs +0 -551
  485. package/data/harnesses/code/skills/design/scripts/lib/checks.mjs +0 -1092
  486. package/data/harnesses/code/skills/design/scripts/lib/golden.mjs +0 -26
  487. package/data/harnesses/code/skills/design/scripts/lib/vocabulary.mjs +0 -65
  488. package/data/harnesses/code/skills/design/scripts/phase-gate.mjs +0 -538
  489. package/data/harnesses/code/skills/design/scripts/preship-sweep.mjs +0 -312
  490. package/data/harnesses/code/skills/design/scripts/render-rung.mjs +0 -890
  491. package/data/harnesses/code/skills/design/scripts/scaffold.mjs +0 -769
  492. package/data/harnesses/code/skills/design/scripts/self-integrity.mjs +0 -675
  493. package/data/harnesses/code/skills/design/scripts/snapshot-goldens.mjs +0 -164
  494. package/data/harnesses/code/skills/design/scripts/validate-combinations.mjs +0 -439
@@ -1,225 +0,0 @@
1
- // skills/design/data/operator-pack/exemplars/dashboard.tsx — reference render — imitate the ambition and the composition; the project's tokens supply the look.
2
- // Surface: brand-forward (delight-allowing)
3
- import { useMemo, useState, type ReactNode } from "react";
4
- import { Activity, ArrowDown, ArrowUp, ArrowUpRight, ChevronsUpDown, CircleAlert, Clock, Database, Plug, RefreshCw, TriangleAlert } from "lucide-react";
5
- import { Alert, AlertDescription, AlertTitle } from "@nurix/components/alert";
6
- import { Badge } from "@nurix/components/badge";
7
- import { Button } from "@nurix/components/button";
8
- import { EmptyState } from "@nurix/components/empty-state";
9
- import { Skeleton } from "@nurix/components/skeleton";
10
- import { BarGraph, type BarGraphData } from "@nurix/components/bar-graph";
11
- import { LineGraph, type LineGraphData } from "@nurix/components/line-graph";
12
- import {
13
- Statistics, StatisticsActions, StatisticsCaption, StatisticsDescription, StatisticsFooter,
14
- StatisticsHeader, StatisticsHeading, StatisticsIcon, StatisticsMetric,
15
- StatisticsSparkline, StatisticsTitle, StatisticsTrend, StatisticsUnit, StatisticsValue,
16
- } from "@nurix/components/statistics";
17
-
18
- type SurfaceStatus = "loading" | "ready" | "empty" | "error";
19
- type SortKey = "records" | "errorRate";
20
- type SortDir = "asc" | "desc";
21
- type Health = "healthy" | "elevated" | "failing";
22
- interface KpiDatum { key: string; label: string; value: string; unit?: string; trend: number; invertTrend?: boolean; spark: number[]; chart: string; stale?: boolean }
23
- interface ConnectorRow { id: string; name: string; kind: string; records: number; errorRate: number; health: Health }
24
- export interface OperationsDashboardProps {
25
- status?: SurfaceStatus; degraded?: boolean; kpis?: KpiDatum[]; connectors?: ConnectorRow[];
26
- lastUpdated?: string; onRefresh?: () => void; onRetry?: () => void; onConnectSource?: () => void;
27
- }
28
- const TIMEFRAMES = [{ key: "24h", label: "24h" }, { key: "7d", label: "7d" }, { key: "30d", label: "30d" }] as const;
29
- const HEALTH: Record<Health, { label: string; className: string; icon: ReactNode }> = {
30
- healthy: { label: "Healthy", className: "text-success", icon: <Activity className="size-4" aria-hidden /> },
31
- elevated: { label: "Elevated", className: "text-warning", icon: <TriangleAlert className="size-4" aria-hidden /> },
32
- failing: { label: "Failing", className: "text-destructive", icon: <CircleAlert className="size-4" aria-hidden /> },
33
- };
34
- // Signed percentage for a KPI trend chip.
35
- const formatPct = (n: number) => `${n > 0 ? "+" : ""}${n.toFixed(1)}%`;
36
- // KPI stat card: headline value, trend, and a per-metric sparkline on a raised (elevation.md) panel; the degraded metric shows a cached marker instead.
37
- function KpiCard({ kpi }: { kpi: KpiDatum }) {
38
- return (
39
- <Statistics variant="card" size="md" className="gap-3 bg-surface-raised shadow-md">
40
- <StatisticsHeader>
41
- <StatisticsHeading><StatisticsTitle size="sm">{kpi.label}</StatisticsTitle></StatisticsHeading>
42
- <StatisticsActions>{kpi.stale ? <Badge variant="outline" className="gap-1 text-warning"><Clock className="size-3" aria-hidden /> Cached</Badge> : <StatisticsIcon variant="primary" tone="soft" size="sm"><Activity className="size-4" aria-hidden /></StatisticsIcon>}</StatisticsActions>
43
- </StatisticsHeader>
44
- <StatisticsMetric>
45
- <StatisticsValue className="tabular-nums">{kpi.value}{/* mock */}</StatisticsValue>
46
- {kpi.unit ? <StatisticsUnit>{kpi.unit}</StatisticsUnit> : null}
47
- {kpi.trend !== 0 ? <StatisticsTrend value={kpi.trend} invert={kpi.invertTrend} pill format={formatPct} /> : null}
48
- </StatisticsMetric>
49
- <StatisticsFooter>{kpi.stale ? <StatisticsCaption className="text-warning">Last cached at 14:12</StatisticsCaption> : <StatisticsSparkline data={kpi.spark} color={kpi.chart} height={28} className="w-full" />}</StatisticsFooter>
50
- </Statistics>
51
- );
52
- }
53
- // The focal hero: the one display-step metric this surface exists to answer, on an elevation.lg raised panel with an optional wash tint, its trend read through the chart tokens.
54
- function ThroughputHero({ total, trend }: { total: string; trend: LineGraphData }) {
55
- return (
56
- <section aria-labelledby="hero-heading" className="flex flex-col gap-4 rounded-xl bg-surface-raised p-6 shadow-lg lg:flex-row lg:items-center lg:justify-between" style={{ backgroundImage: "var(--wash-surface, transparent)" }}>
57
- <div className="flex flex-col gap-1">
58
- <h2 id="hero-heading" className="text-small font-medium text-muted-foreground">Records ingested today</h2>
59
- <div className="flex items-baseline gap-3"><span className="text-display tabular-nums text-foreground">{total}{/* mock */}</span><span className="inline-flex items-center gap-1 text-success"><ArrowUp className="size-4" aria-hidden /><span className="tabular-nums">6.4%</span></span></div>
60
- <p className="text-body text-muted-foreground">Across every connector, versus the same window yesterday.</p>
61
- </div>
62
- <div className="min-w-0 lg:w-1/2"><LineGraph data={trend} height="sm" filled colors={["var(--chart-1)", "var(--chart-2)"]} /></div>
63
- </section>
64
- );
65
- }
66
- // One sortable, right-aligned numeric column header carrying its aria-sort state and a keyboard-native toggle.
67
- function SortHeader({ label, sortKey, active, dir, onSort }: { label: string; sortKey: SortKey; active: boolean; dir: SortDir; onSort: (k: SortKey) => void }) {
68
- const ariaSort: "none" | "ascending" | "descending" = active ? (dir === "asc" ? "ascending" : "descending") : "none";
69
- return (
70
- <th scope="col" aria-sort={ariaSort} className="py-2 pr-4 text-right font-medium">
71
- <button type="button" onClick={() => onSort(sortKey)} aria-label={`Sort by ${label}`} className="inline-flex items-center gap-1 rounded text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
72
- {label}{active ? (dir === "asc" ? <ArrowUp className="size-3" aria-hidden /> : <ArrowDown className="size-3" aria-hidden />) : <ChevronsUpDown className="size-3" aria-hidden />}
73
- </button>
74
- </th>
75
- );
76
- }
77
- // The connectors breakdown: a bounded top-volume table on a raised (elevation.md) panel, sortable numeric columns, per-row health.
78
- function ConnectorsTile({ connectors }: { connectors: ConnectorRow[] }) {
79
- const [sortKey, setSortKey] = useState<SortKey>("records");
80
- const [sortDir, setSortDir] = useState<SortDir>("desc");
81
- const rows = useMemo(() => [...connectors].sort((a, b) => (sortDir === "asc" ? a[sortKey] - b[sortKey] : b[sortKey] - a[sortKey])), [connectors, sortKey, sortDir]);
82
- const onSort = (k: SortKey) => k === sortKey ? setSortDir((d) => (d === "asc" ? "desc" : "asc")) : (setSortKey(k), setSortDir("desc"));
83
- return (
84
- <Statistics variant="outline" className="gap-4 bg-surface-raised shadow-md">
85
- <StatisticsHeader>
86
- <StatisticsHeading><StatisticsTitle size="sm">Connectors by volume</StatisticsTitle><StatisticsDescription>Top sources in the selected range.</StatisticsDescription></StatisticsHeading>
87
- </StatisticsHeader>
88
- <div className="overflow-x-auto">
89
- <table className="w-full text-small">
90
- <thead>
91
- <tr className="border-b border-border text-left text-caption text-muted-foreground">
92
- <th scope="col" className="py-2 pr-4 font-medium">Connector</th>
93
- <SortHeader label="Records" sortKey="records" active={sortKey === "records"} dir={sortDir} onSort={onSort} />
94
- <SortHeader label="Error rate" sortKey="errorRate" active={sortKey === "errorRate"} dir={sortDir} onSort={onSort} />
95
- <th scope="col" className="whitespace-nowrap py-2 pl-2 font-medium">Health</th>
96
- </tr>
97
- </thead>
98
- <tbody>
99
- {rows.map((c) => (
100
- <tr key={c.id} className="border-b border-border last:border-0">
101
- <td className="py-2 pr-4"><div className="flex items-center gap-2"><Database className="size-4 shrink-0 text-muted-foreground" aria-hidden /><span className="truncate font-medium text-foreground">{c.name}</span><span className="shrink-0 font-mono text-muted-foreground">{c.kind}</span></div></td>
102
- <td className="py-2 pr-4 text-right tabular-nums">{c.records.toLocaleString()}</td>
103
- <td className="py-2 pr-4 text-right tabular-nums">{c.errorRate.toFixed(2)}%</td>
104
- <td className="py-2 pl-2"><span className={`inline-flex items-center gap-1 whitespace-nowrap ${HEALTH[c.health].className}`}>{HEALTH[c.health].icon}{HEALTH[c.health].label}</span></td>
105
- </tr>
106
- ))}
107
- </tbody>
108
- </table>
109
- </div>
110
- </Statistics>
111
- );
112
- }
113
- // The ingest-health strip: per-day request outcome, its status roles wired through the BarGraph map; the graph and tally fill the card.
114
- function HealthStripTile({ days }: { days: BarGraphData[] }) {
115
- const tally = days.reduce((acc, d) => { const s = d.bar[0]?.status ?? "empty"; acc[s] = (acc[s] ?? 0) + 1; return acc; }, {} as Record<string, number>);
116
- return (
117
- <Statistics variant="outline" className="gap-4 bg-surface-raised shadow-md">
118
- <StatisticsHeader>
119
- <StatisticsHeading><StatisticsTitle size="sm">Ingest health</StatisticsTitle><StatisticsDescription>Daily request outcome over the last twelve days.</StatisticsDescription></StatisticsHeading>
120
- <StatisticsActions><a href="/incidents" className="inline-flex items-center gap-1 text-caption text-primary">Incidents <ArrowUpRight className="size-4" aria-hidden /></a></StatisticsActions>
121
- </StatisticsHeader>
122
- <div className="flex-1"><BarGraph data={days} height="lg" roundedCorners="all" colors={{ success: "var(--success)", degraded: "var(--warning)", error: "var(--destructive)", info: "var(--primary)", empty: "var(--muted-foreground)" }} /></div>
123
- <StatisticsFooter>
124
- <StatisticsCaption className="flex flex-wrap items-center gap-3 tabular-nums">
125
- <span className="text-success">{tally.success ?? 0} healthy</span><span className="text-warning">{tally.degraded ?? 0} degraded</span><span className="text-destructive">{tally.error ?? 0} errored</span><span>across {days.length} days</span>
126
- </StatisticsCaption>
127
- </StatisticsFooter>
128
- </Statistics>
129
- );
130
- }
131
- // Loading skeleton mirroring the real shape: a hero band, four KPI cards, then two breakdown tiles.
132
- function DashboardSkeleton() {
133
- return (
134
- <div className="flex flex-col gap-6" aria-hidden>
135
- <Skeleton className="h-28 w-full rounded-xl" />
136
- <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">{[0, 1, 2, 3].map((i) => <div key={i} className="flex flex-col gap-3 rounded-lg border border-border p-4"><Skeleton className="h-4 w-24" /><Skeleton className="h-8 w-32" /><Skeleton className="h-7 w-full" /></div>)}</div>
137
- <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">{[0, 1].map((i) => <div key={i} className="flex flex-col gap-4 rounded-lg border border-border p-4"><Skeleton className="h-4 w-40" /><Skeleton className="h-16 w-full" /><Skeleton className="h-4 w-3/4" /></div>)}</div>
138
- </div>
139
- );
140
- }
141
- // Ingestion-operations overview: a read-mostly hero + KPI + breakdown dashboard with every lifecycle state reachable via the status prop.
142
- export function OperationsDashboard(props: OperationsDashboardProps) {
143
- const { status = "ready", degraded = false, lastUpdated = "14:32:08", onRefresh, onRetry, onConnectSource } = props;
144
- const kpis = props.kpis ?? DEFAULT_KPIS;
145
- const connectors = props.connectors ?? DEFAULT_CONNECTORS;
146
- const [timeframe, setTimeframe] = useState<string>("24h");
147
- return (
148
- <main className="flex min-h-[100dvh] flex-col bg-background font-sans text-foreground" data-density-step="looser">
149
- <header className="flex flex-col gap-2 border-b border-border px-6 py-4">
150
- <div className="flex flex-wrap items-center justify-between gap-4">
151
- <div className="flex flex-col gap-1">
152
- <h1 className="text-h1 text-foreground">Ingestion operations</h1>
153
- <p className="text-small text-muted-foreground">Cross-connector health for the data platform.</p>
154
- </div>
155
- <div className="flex items-center gap-2">
156
- <div className="flex items-center gap-2" role="group" aria-label="Time range">
157
- {TIMEFRAMES.map((tf) => <Button key={tf.key} size="sm" variant={tf.key === timeframe ? "secondary" : "ghost"} aria-pressed={tf.key === timeframe} onClick={() => setTimeframe(tf.key)}>{tf.label}</Button>)}
158
- </div>
159
- <Button size="sm" variant="secondary" onClick={onRefresh}><RefreshCw className="size-4" aria-hidden /> Refresh</Button>
160
- </div>
161
- </div>
162
- <p role="status" aria-live="polite" className="text-caption text-muted-foreground">{status === "loading" ? "Loading ingestion overview…" : status === "error" ? "Overview failed to load."
163
- : <>Updated <span className="font-mono">{lastUpdated}</span>{degraded ? " · latency source stale" : ""}</>}</p>
164
- </header>
165
- <div className="flex flex-col gap-6 px-6 py-6">
166
- {status === "loading" ? <DashboardSkeleton /> : null}
167
- {status === "error" ? (
168
- <Alert variant="destructive" role="alert">
169
- <TriangleAlert className="size-4" aria-hidden /><AlertTitle>Overview failed to load</AlertTitle>
170
- <AlertDescription>The metrics service did not answer within the request timeout, usually a transient gateway hiccup. Retry now, or check the metrics service status if it keeps failing.
171
- <span className="mt-3 block"><Button size="sm" variant="secondary" onClick={onRetry}><RefreshCw className="size-4" aria-hidden /> Retry</Button></span></AlertDescription>
172
- </Alert>
173
- ) : null}
174
- {status === "empty" ? (
175
- <EmptyState icon={<Plug className="size-6 text-muted-foreground" aria-hidden />} title="No connectors yet"
176
- description="Connect a data source to start ingesting records. Throughput, failure rates, and latency appear here once the first batch runs."
177
- action={<Button size="sm" onClick={onConnectSource}><Plug className="size-4" aria-hidden /> Connect a source</Button>} />
178
- ) : null}
179
- {status === "ready" ? (
180
- <>
181
- {degraded ? (
182
- <Alert role="status"><Clock className="size-4" aria-hidden /><AlertTitle>Latency source unreachable</AlertTitle>
183
- <AlertDescription>The p95 processing panel is showing the last cached value from 14:12. Every other panel is live.</AlertDescription></Alert>
184
- ) : null}
185
- <ThroughputHero total="1,284,930" trend={THROUGHPUT_TREND} />
186
- <section className="flex flex-col gap-3" aria-labelledby="kpi-heading">
187
- <h2 id="kpi-heading" className="text-small font-medium text-muted-foreground">Today at a glance</h2>
188
- <div className="motion-stagger grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">{kpis.map((kpi) => <KpiCard key={kpi.key} kpi={kpi} />)}</div>
189
- </section>
190
- <section className="flex flex-col gap-3" aria-labelledby="breakdown-heading">
191
- <h2 id="breakdown-heading" className="text-small font-medium text-muted-foreground">Breakdowns</h2>
192
- <div className="grid grid-cols-1 gap-4 lg:grid-cols-2"><HealthStripTile days={INGEST_HEALTH} /><ConnectorsTile connectors={connectors} /></div>
193
- </section>
194
- </>
195
- ) : null}
196
- </div>
197
- </main>
198
- );
199
- }
200
-
201
- // exemplar fixture data — seeded, domain-shaped
202
- export const FIXTURE_SEED = 6820;
203
- const DEFAULT_KPIS: KpiDatum[] = [
204
- { key: "throughput", label: "Records ingested", value: "1,284,930", unit: "today", trend: 6.4, spark: [820, 910, 880, 1020, 1180, 1240, 1284], chart: "var(--chart-1)" },
205
- { key: "failures", label: "Batch failure rate", value: "0.42", unit: "%", trend: 1.8, invertTrend: true, spark: [0.3, 0.28, 0.35, 0.31, 0.4, 0.44, 0.42], chart: "var(--chart-5)" },
206
- { key: "latency", label: "p95 processing", value: "312", unit: "ms", trend: -4.1, spark: [360, 352, 341, 338, 330, 318, 312], chart: "var(--chart-2)", stale: true },
207
- { key: "connectors", label: "Active connectors", value: "18", unit: "of 21", trend: 0, spark: [17, 17, 18, 18, 18, 17, 18], chart: "var(--chart-3)" },
208
- ];
209
- const THROUGHPUT_TREND: LineGraphData = {
210
- labels: ["08:00", "09:00", "10:00", "11:00", "12:00", "13:00", "14:00"],
211
- series: [{ name: "Ingested", values: [820, 910, 880, 1020, 1180, 1240, 1284] }, { name: "Queued", values: [140, 120, 210, 90, 160, 130, 118] }],
212
- };
213
- const INGEST_HEALTH: BarGraphData[] = ["Jun 23", "Jun 24", "Jun 25", "Jun 26", "Jun 27", "Jun 28", "Jun 29", "Jun 30", "Jul 01", "Jul 02", "Jul 03", "Jul 04"].map((day, i) => {
214
- const status = i === 6 ? "error" : i === 3 || i === 9 ? "degraded" : "success";
215
- const value = status === "success" ? "100.0% healthy" : status === "degraded" ? "97.4% degraded" : "91.2% errored";
216
- return { day, bar: [{ status, height: 100 }], card: [{ status, value }], events: [] };
217
- });
218
- const DEFAULT_CONNECTORS: ConnectorRow[] = [
219
- { id: "cn_stripe_events", name: "Stripe billing events", kind: "webhook", records: 486210, errorRate: 0.08, health: "healthy" },
220
- { id: "cn_salesforce_crm", name: "Salesforce CRM accounts and opportunities", kind: "rest", records: 312440, errorRate: 0.31, health: "healthy" },
221
- { id: "cn_postgres_orders", name: "Postgres orders replica", kind: "cdc", records: 274900, errorRate: 1.94, health: "elevated" },
222
- { id: "cn_segment_web", name: "Segment web analytics", kind: "stream", records: 158030, errorRate: 0.12, health: "healthy" },
223
- { id: "cn_zendesk_tickets", name: "Zendesk support tickets", kind: "rest", records: 42110, errorRate: 6.71, health: "failing" },
224
- { id: "cn_s3_archive", name: "S3 nightly archive export", kind: "batch", records: 11240, errorRate: 0, health: "healthy" },
225
- ];
@@ -1,249 +0,0 @@
1
- // skills/design/data/operator-pack/exemplars/entity-detail.tsx — reference render — imitate the ambition and the composition; the project's tokens supply the look.
2
- // Surface: brand-forward (delight-allowing)
3
- import { useEffect, useState } from "react";
4
- import { Button } from "@nurix/components/button";
5
- import { Badge } from "@nurix/components/badge";
6
- import { Card, CardContent } from "@nurix/components/card";
7
- import { Skeleton } from "@nurix/components/skeleton";
8
- import { EmptyState } from "@nurix/components/empty-state";
9
- import { Alert, AlertTitle, AlertDescription } from "@nurix/components/alert";
10
- import { Label } from "@nurix/components/label";
11
- import { Kbd } from "@nurix/components/kbd";
12
- import { Input } from "@nurix/components/input";
13
- import { Tabs, TabsList, TabsTrigger, TabsContent } from "@nurix/components/tabs";
14
- import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, SheetFooter, SheetClose } from "@nurix/components/sheet";
15
- import { Table, defineColumn, type ColumnDefinition } from "@nurix/components/table";
16
- import { ArrowRight, Boxes, CircleCheck, CircleX, Pencil, RefreshCw, Rocket, ScrollText, TriangleAlert } from "lucide-react";
17
- // A deployment-console service: a long-lived entity with many attributes, related instances, and deployment history (entity-detail).
18
- type ServiceHealth = "healthy" | "degraded" | "down";
19
- type SaveState = "idle" | "saving" | "saved" | "conflict";
20
- type LoadStatus = "ready" | "loading" | "error";
21
- export interface Service {
22
- id: string; name: string; slug: string; environment: string; health: ServiceHealth; owner: string; runtime: string; region: string; replicas: number; lastDeployedAt: string;
23
- }
24
- export interface Instance { id: string; region: string; version: string; status: string; cpuPercent: number; startedAt: string }
25
- export interface Deployment { id: string; version: string; actor: string; status: "succeeded" | "failed" | "rolled_back"; at: string }
26
- export interface ActivityEvent { id: string; at: string; actor: string; summary: string; ref: string }
27
- export interface ServiceMetric { label: string; value: string; unit: string; note: string; tone: string }
28
- export interface ConfigPatch { replicas: number }
29
- export interface EntityDetailProps {
30
- service: Service | null; instances: Instance[]; deployments: Deployment[]; activity?: ActivityEvent[]; metrics?: ServiceMetric[];
31
- status?: LoadStatus; metricsStale?: boolean; errorDetail?: string; saveState?: SaveState; onRetry?: () => void; onDeploy?: () => void; onSaveConfig?: (patch: ConfigPatch) => void;
32
- }
33
- const HEALTH_META: Record<ServiceHealth, { label: string; cls: string; Icon: typeof CircleCheck }> = { healthy: { label: "Healthy", cls: "text-success", Icon: CircleCheck }, degraded: { label: "Degraded", cls: "text-warning", Icon: TriangleAlert }, down: { label: "Down", cls: "text-destructive", Icon: CircleX } };
34
- const DEPLOY_LABEL: Record<Deployment["status"], string> = { succeeded: "Deployed", failed: "Deploy failed", rolled_back: "Rolled back" };
35
- const INSTANCE_STATUS = [{ value: "running", label: "Running" }, { value: "starting", label: "Starting" }, { value: "unknown", label: "Unknown" }];
36
- const instanceColumns: ColumnDefinition<Instance>[] = [
37
- defineColumn<Instance>({ slug: "id", label: "Instance", type: "text", cell: (r) => <span className="font-mono tabular-nums">{r.id}</span> }),
38
- defineColumn<Instance>({ slug: "region", label: "Region", type: "text" }),
39
- defineColumn<Instance>({ slug: "version", label: "Version", type: "text", cell: (r) => <span className="font-mono">{r.version}</span> }),
40
- defineColumn<Instance>({ slug: "status", label: "Status", type: "enum", component: "status", metadata: { options: INSTANCE_STATUS } }),
41
- defineColumn<Instance>({ slug: "cpuPercent", label: "CPU", type: "number", metadata: { suffix: "%" } }),
42
- defineColumn<Instance>({ slug: "startedAt", label: "Started", type: "date", metadata: { relativeFormat: true } }),
43
- ];
44
- // Loading shell mirrors the header identity, tab bar, and metrics strip, never a centered spinner.
45
- function DetailSkeleton() {
46
- return (
47
- <div className="min-h-[100dvh] bg-background p-6 font-sans">
48
- <div className="flex items-center gap-3"><Skeleton className="h-10 w-10 rounded-md" /><div className="flex flex-col gap-2"><Skeleton className="h-5 w-48" /><Skeleton className="h-4 w-32" /></div></div>
49
- <div className="mt-6 flex gap-2"><Skeleton className="h-8 w-24" /><Skeleton className="h-8 w-24" /><Skeleton className="h-8 w-24" /></div>
50
- <div className="mt-6 grid grid-cols-2 gap-4 xl:grid-cols-4">{[0, 1, 2, 3].map((i) => <Skeleton key={i} className="h-20 w-full" />)}</div><div className="mt-6"><Skeleton className="h-40 w-full" /></div>
51
- </div>
52
- );
53
- }
54
- // Entity load failure states what happened, why, and the recovery path. Never a dead end.
55
- function DetailError({ detail, onRetry }: { detail?: string; onRetry?: () => void }) {
56
- return (
57
- <div className="flex min-h-[100dvh] items-center justify-center bg-background p-6 font-sans">
58
- <Alert variant="destructive" className="max-w-md">
59
- <CircleX className="h-4 w-4" /><AlertTitle>Could not load this service</AlertTitle>
60
- <AlertDescription>{detail ?? "The deployment API did not respond."} Retry the request, or open the platform status page if it keeps failing.</AlertDescription>
61
- <div className="mt-3"><Button size="sm" onClick={onRetry}><RefreshCw className="h-4 w-4" /> Retry</Button></div>
62
- </Alert>
63
- </div>
64
- );
65
- }
66
- // Config edit opens beside the work on the overlay ladder; the save path narrates saving, saved, and the concurrent-edit conflict.
67
- function EditConfigSheet({ service, open, onOpenChange, saveState, onSave }: { service: Service; open: boolean; onOpenChange: (v: boolean) => void; saveState: SaveState; onSave?: (patch: ConfigPatch) => void }) {
68
- const [replicas, setReplicas] = useState(String(service.replicas));
69
- const [replicaError, setReplicaError] = useState<string | null>(null);
70
- const saving = saveState === "saving";
71
- return (
72
- <Sheet open={open} onOpenChange={onOpenChange}>
73
- <SheetContent side="right" className="bg-surface-overlay shadow-overlay">
74
- <SheetHeader>
75
- <SheetTitle className="text-h3">Edit configuration</SheetTitle><SheetDescription className="text-small">Changes apply on the next deploy of {service.slug}.</SheetDescription>
76
- </SheetHeader>
77
- <SheetBody className="flex flex-col gap-4">
78
- {saveState === "conflict" && (
79
- <Alert variant="destructive">
80
- <TriangleAlert className="h-4 w-4" /><AlertTitle>Configuration changed elsewhere</AlertTitle><AlertDescription>Another operator saved this service while you were editing. Reload to see their values before saving yours.</AlertDescription>
81
- </Alert>
82
- )}
83
- <div className="flex flex-col gap-2">
84
- <Label htmlFor="replicas">Desired replicas</Label>
85
- <Input id="replicas" inputMode="numeric" value={replicas} aria-invalid={!!replicaError} onChange={(e) => setReplicas(e.target.value)}
86
- onBlur={() => { const n = Number(replicas); setReplicaError(!Number.isInteger(n) || n < 1 ? "Enter a whole number of one or more." : null); }} />
87
- {replicaError && <p className="text-small text-destructive">{replicaError}</p>}
88
- </div>
89
- <p role="status" aria-live="polite" className="min-h-4 text-small text-muted-foreground">{saveState === "saving" && "Saving configuration…"}{saveState === "saved" && "Configuration saved."}</p>
90
- </SheetBody>
91
- <SheetFooter>
92
- <SheetClose asChild><Button variant="secondary" size="sm">Cancel</Button></SheetClose><Button size="sm" disabled={saving || !!replicaError} onClick={() => onSave?.({ replicas: Number(replicas) })}>{saving && <RefreshCw className="h-4 w-4" />} Save changes</Button>
93
- </SheetFooter>
94
- </SheetContent>
95
- </Sheet>
96
- );
97
- }
98
- // Service entity-detail: a raised identity header (its brand-forward region), a furnished overview (metrics strip, config, activity preview, instance summary), tabbed related views, edit in a side panel.
99
- export function EntityDetail(props: EntityDetailProps) {
100
- const { service, instances, deployments, status = "ready", metricsStale = false, errorDetail, saveState = "idle", onRetry, onDeploy, onSaveConfig } = props;
101
- const metrics = props.metrics ?? SERVICE_METRICS;
102
- const activity = props.activity ?? RECENT_ACTIVITY;
103
- const [tab, setTab] = useState("overview");
104
- const [editOpen, setEditOpen] = useState(false);
105
- const byStatus = instances.reduce((acc, i) => { acc[i.status] = (acc[i.status] ?? 0) + 1; return acc; }, {} as Record<string, number>);
106
- const regions = [...new Set(instances.map((i) => i.region))];
107
- // Keyboard parity for the Edit affordance: press E to open the config panel.
108
- useEffect(() => {
109
- function onKey(e: KeyboardEvent) {
110
- const el = e.target as HTMLElement | null;
111
- if (el && (el.tagName === "INPUT" || el.tagName === "TEXTAREA")) return;
112
- if (e.key === "e" && !editOpen) { e.preventDefault(); setEditOpen(true); }
113
- }
114
- window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey);
115
- }, [editOpen]);
116
- if (status === "loading") return <DetailSkeleton />;
117
- if (status === "error" || !service) return <DetailError detail={errorDetail} onRetry={onRetry} />;
118
- const health = HEALTH_META[service.health];
119
- const attributes: { label: string; value: string; mono?: boolean; num?: boolean }[] = [
120
- { label: "Environment", value: service.environment }, { label: "Runtime", value: service.runtime, mono: true }, { label: "Region", value: service.region, mono: true }, { label: "Owner", value: service.owner },
121
- { label: "Desired replicas", value: String(service.replicas), num: true }, { label: "Last deployed", value: new Date(service.lastDeployedAt).toLocaleString(), num: true },
122
- ];
123
- return (
124
- <div className="min-h-[100dvh] bg-background font-sans text-foreground">
125
- <header className="flex flex-wrap items-start justify-between gap-4 border-b border-border bg-surface-raised p-6 shadow-sm">
126
- <div className="flex items-start gap-3">
127
- <span className="grid h-10 w-10 place-items-center rounded-md bg-muted text-muted-foreground"><Boxes className="h-5 w-5" /></span>
128
- <div>
129
- <div className="flex items-center gap-2"><h1 className="text-h1">{service.name}</h1><Badge variant="outline" className={`gap-1 ${health.cls}`}><health.Icon className="h-3.5 w-3.5" /> {health.label}</Badge></div>
130
- <p className="mt-1 text-small text-muted-foreground">{service.slug} · {service.environment}</p>
131
- </div>
132
- </div>
133
- <div className="flex items-center gap-2">
134
- <Button variant="secondary" size="sm" onClick={() => setEditOpen(true)}><Pencil className="h-4 w-4" /> Edit config <Kbd className="ml-1">E</Kbd></Button><Button size="sm" onClick={onDeploy}><Rocket className="h-4 w-4" /> Deploy</Button>
135
- </div>
136
- </header>
137
- <div className="p-6">
138
- {metricsStale && (
139
- <Alert className="mb-4">
140
- <TriangleAlert className="h-4 w-4 text-warning" /><AlertTitle>Live health signals unavailable</AlertTitle><AlertDescription>The health collector is unreachable, so instance status and the figures below reflect the last cached snapshot and may be stale.</AlertDescription>
141
- </Alert>
142
- )}
143
- <Tabs value={tab} onValueChange={setTab}>
144
- <TabsList><TabsTrigger value="overview">Overview</TabsTrigger><TabsTrigger value="instances">Instances</TabsTrigger><TabsTrigger value="activity">Activity</TabsTrigger></TabsList>
145
- <TabsContent value="overview">
146
- <div className="mt-4 flex flex-col gap-6">
147
- <section aria-labelledby="ov-health">
148
- <h2 id="ov-health" className="mb-3 text-h3">Service health <span className="text-caption font-normal text-muted-foreground">sample data</span></h2>
149
- <div className="grid grid-cols-2 gap-4 xl:grid-cols-4">{/* mock: fixture-supplied readings, not authoritative production statistics */}
150
- {metrics.map((m) => (
151
- <Card key={m.label} className="flex flex-col gap-1 p-4"><span className="text-caption text-muted-foreground">{m.label}</span>
152
- <span className="flex items-baseline gap-1"><span className="text-h2 tabular-nums">{m.value}</span><span className="text-caption text-muted-foreground">{m.unit}</span></span><span className={`text-caption ${m.tone}`}>{m.note}</span>
153
- </Card>
154
- ))}
155
- </div>
156
- </section>
157
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
158
- <section aria-labelledby="ov-config">
159
- <h2 id="ov-config" className="mb-3 text-h3">Configuration</h2>
160
- <Card><CardContent className="p-0"><dl className="divide-y divide-border">
161
- {attributes.map((a) => (
162
- <div key={a.label} className="flex items-center justify-between gap-4 px-4 py-3 text-small"><dt className="text-muted-foreground">{a.label}</dt><dd className={`${a.mono ? "font-mono" : ""} ${a.num ? "tabular-nums" : ""}`}>{a.value}</dd></div>
163
- ))}
164
- </dl></CardContent></Card>
165
- </section>
166
- <div className="flex flex-col gap-6">
167
- <section aria-labelledby="ov-activity">
168
- <div className="mb-3 flex items-center justify-between"><h2 id="ov-activity" className="text-h3">Recent activity</h2><Button variant="ghost" size="sm" onClick={() => setTab("activity")}>All activity <ArrowRight className="h-4 w-4" /></Button></div>
169
- <Card><CardContent className="p-0"><ol className="divide-y divide-border">
170
- {activity.map((ev) => (
171
- <li key={ev.id} className="flex items-baseline gap-3 px-4 py-2 text-small">
172
- <time className="shrink-0 font-mono tabular-nums text-muted-foreground">{ev.at}</time><span className="min-w-0 flex-1 truncate">{ev.summary} <span className="text-muted-foreground">by {ev.actor}</span></span><span className="shrink-0 font-mono text-muted-foreground">{ev.ref}</span>
173
- </li>
174
- ))}
175
- </ol></CardContent></Card>
176
- </section>
177
- <section aria-labelledby="ov-instances">
178
- <div className="mb-3 flex items-center justify-between"><h2 id="ov-instances" className="text-h3">Instances</h2><Button variant="ghost" size="sm" onClick={() => setTab("instances")}>All instances <ArrowRight className="h-4 w-4" /></Button></div>
179
- <Card><CardContent className="flex flex-wrap items-center gap-x-6 gap-y-2 p-4 text-small">
180
- <span className="flex items-center gap-1.5 text-success"><CircleCheck className="h-4 w-4" /><span className="tabular-nums">{byStatus.running ?? 0}</span> running</span><span className="flex items-center gap-1.5 text-warning"><RefreshCw className="h-4 w-4" /><span className="tabular-nums">{byStatus.starting ?? 0}</span> starting</span><span className="flex items-center gap-1.5 text-destructive"><CircleX className="h-4 w-4" /><span className="tabular-nums">{byStatus.unknown ?? 0}</span> unknown</span><span className="text-muted-foreground">across {regions.length} regions (<span className="font-mono">{regions.join(", ")}</span>)</span>
181
- </CardContent></Card>
182
- </section>
183
- </div>
184
- </div>
185
- </div>
186
- </TabsContent>
187
- <TabsContent value="instances">
188
- <div className="mt-4">
189
- {instances.length === 0
190
- ? <EmptyState icon={<Boxes className="h-10 w-10 text-muted-foreground" />} title="No running instances" description="This service has no instances in this environment yet. Deploy a build to bring the first one online." action={<Button size="sm" onClick={onDeploy}><Rocket className="h-4 w-4" /> Deploy</Button>} />
191
- : <Table data={instances} columns={instanceColumns} tableConfig={{ header: true, density: "compact" }} />}
192
- </div>
193
- </TabsContent>
194
- <TabsContent value="activity">
195
- <div className="mt-4">
196
- {deployments.length === 0 ? (
197
- <EmptyState icon={<ScrollText className="h-10 w-10 text-muted-foreground" />} title="No deployments recorded" description="Deployment history for this service appears here once the first build ships." />
198
- ) : (
199
- <ol className="flex flex-col">
200
- {deployments.map((d) => (
201
- <li key={d.id} className="flex items-center gap-3 border-b border-border py-3 text-small last:border-0">
202
- {d.status === "succeeded" ? <CircleCheck className="h-4 w-4 text-success" /> : <CircleX className="h-4 w-4 text-destructive" />}<span className="font-mono">{d.version}</span><span className="text-muted-foreground">{DEPLOY_LABEL[d.status]} by {d.actor}</span><time className="ml-auto font-mono tabular-nums text-muted-foreground">{new Date(d.at).toLocaleString()}</time>
203
- </li>
204
- ))}
205
- </ol>
206
- )}
207
- </div>
208
- </TabsContent>
209
- </Tabs>
210
- </div>
211
- <EditConfigSheet service={service} open={editOpen} onOpenChange={setEditOpen} saveState={saveState} onSave={onSaveConfig} />
212
- </div>
213
- );
214
- }
215
- // exemplar fixture data — seeded, domain-shaped
216
- export const FIXTURE_SEED = 7314;
217
- export const service: Service = {
218
- id: "svc_0e9c1a7b", name: "checkout-api", slug: "checkout-api", environment: "production", health: "degraded", owner: "payments-platform", runtime: "node20", region: "iad", replicas: 6, lastDeployedAt: "2026-07-03T14:22:00Z",
219
- };
220
- export const instances: Instance[] = [
221
- { id: "checkout-api-7f4b21", region: "iad", version: "2026.7.3-a19f", status: "running", cpuPercent: 34, startedAt: "2026-07-03T14:23:00Z" },
222
- { id: "checkout-api-9c02de", region: "iad", version: "2026.7.3-a19f", status: "running", cpuPercent: 51, startedAt: "2026-07-03T14:23:00Z" },
223
- { id: "checkout-api-b73a10", region: "sfo", version: "2026.7.3-a19f", status: "running", cpuPercent: 47, startedAt: "2026-07-03T14:24:00Z" },
224
- { id: "checkout-api-1de8ff", region: "sfo", version: "2026.6.28-c4e2-hotfix-billing-migration", status: "starting", cpuPercent: 0, startedAt: "2026-07-04T02:11:00Z" },
225
- { id: "checkout-api-0000aa", region: "fra", version: "2026.6.28-c4e2", status: "unknown", cpuPercent: 0, startedAt: "2026-07-02T09:05:00Z" },
226
- { id: "checkout-api-55b9c1", region: "fra", version: "2026.7.3-a19f", status: "running", cpuPercent: 62, startedAt: "2026-07-03T14:25:00Z" },
227
- ];
228
- export const deployments: Deployment[] = [
229
- { id: "dep_5a1", version: "2026.7.3-a19f", actor: "m.okonkwo", status: "succeeded", at: "2026-07-03T14:22:00Z" },
230
- { id: "dep_4f7", version: "2026.7.1-77b0", actor: "priya.nair", status: "rolled_back", at: "2026-07-01T18:40:00Z" },
231
- { id: "dep_4e2", version: "2026.6.28-c4e2", actor: "s.delacroix", status: "failed", at: "2026-06-28T22:05:00Z" },
232
- { id: "dep_4b0", version: "2026.6.20-11ad", actor: "m.okonkwo", status: "succeeded", at: "2026-06-20T10:33:00Z" },
233
- ];
234
- export const RECENT_ACTIVITY: ActivityEvent[] = [
235
- { id: "act-91", at: "07-03 14:22", actor: "m.okonkwo", summary: "Deployed 2026.7.3-a19f to production", ref: "dep_5a1" },
236
- { id: "act-90", at: "07-03 11:05", actor: "autoscaler", summary: "Scaled replicas 4 to 6 on sustained queue depth", ref: "evt_88c2" },
237
- { id: "act-89", at: "07-02 16:48", actor: "s.delacroix", summary: "Config change: LOG_LEVEL info to warn", ref: "cfg_7719" },
238
- { id: "act-88", at: "07-02 09:14", actor: "monitor", summary: "Alert fired: p95 latency above 250 ms for 12 minutes", ref: "alr_5520" },
239
- { id: "act-87", at: "07-01 18:40", actor: "priya.nair", summary: "Rolled back 2026.7.1-77b0 after elevated 5xx", ref: "dep_4f7" },
240
- { id: "act-86", at: "07-01 07:03", actor: "health-collector", summary: "Instance checkout-api-0000aa marked unknown after 3 failed probes", ref: "evt_4411" },
241
- ];
242
- export const SERVICE_METRICS: ServiceMetric[] = [
243
- { label: "Uptime, 30 days", value: "99.92", unit: "%", note: "target 99.90", tone: "text-success" },
244
- { label: "Error rate", value: "1.84", unit: "%", note: "elevated last hour", tone: "text-warning" },
245
- { label: "Throughput", value: "412", unit: "req/s", note: "peak 590 today", tone: "text-muted-foreground" },
246
- { label: "p95 latency", value: "268", unit: "ms", note: "SLO 250 ms", tone: "text-warning" },
247
- ];
248
- export const emptyInstances: Instance[] = [];
249
- export const emptyDeployments: Deployment[] = [];