diff --git a/.github/workflows/check-skills.yml b/.github/workflows/check-skills.yml new file mode 100644 index 0000000000..2087151a6c --- /dev/null +++ b/.github/workflows/check-skills.yml @@ -0,0 +1,85 @@ +# check-skills.yml — Intent skill PR checks. +# +# Originally scaffolded by `intent maintainer setup`, then converted to a +# self-contained, in-repo workflow so it: +# - runs only on PRs that touch the sources the skills are built from, +# - uses this repo's own pnpm/Node toolchain (no external reusable workflows), +# - runs the lockfile-pinned @tanstack/intent (ui-components devDependency). +# +# Two things happen on a PR: +# 1. validate — hard gate: fails the PR on malformed/invented-API skills. +# 2. review drift — non-blocking: flags skills whose cited sources changed in +# THIS PR, surfaced as a GitHub review reminder so the author +# can update the skill in the same PR (the actionable moment). +# +# NOTE: `intent maintainer setup` may regenerate this file. If it does, re-apply +# the paths filter and the PR-only scope. + +name: Check Skills + +on: + pull_request: + paths: + # Skills are grounded in these source trees (see `sources:` in _artifacts/skill_tree.yaml), + # so only run the skill checks when something that can affect them changes. + - "packages/ui-components/**" # component source + the skills/ files themselves + - "docs/ux/**" # UX docs the skills cite as sources + - "_artifacts/**" # planning records the gate validates + - ".github/workflows/check-skills.yml" # the workflow itself + workflow_dispatch: {} + +permissions: {} + +env: + NODE_VERSION: "22.22.2" + +jobs: + validate: + name: Validate Intent skills + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write # the non-blocking drift step posts a review reminder + steps: + - name: Checkout Repo + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 # drift review diffs this PR against its base branch + + - name: Setup Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install pnpm + uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0 + with: + package_json_file: package.json + + # Installs the lockfile-pinned @tanstack/intent (declared in + # packages/ui-components/package.json devDependencies) so the version is a + # single source of truth, bumped like any other dep — no magic version + # string in this workflow. + - name: Install Dependencies + run: pnpm install --frozen-lockfile + + # Hard gate. Structural + type validation of every SKILL.md and reference + # file; type-checks each code fence against the real component types and + # fails the PR on malformed frontmatter, broken links, or invented APIs. + # + # Scope: `validate` only ever reads packages/ui-components/skills — an + # intrinsic allowlist, so this gate needs no path-ignore maintenance as the + # monorepo grows. + - name: Validate skills + run: pnpm --filter @cloudoperators/juno-ui-components exec intent validate skills --github-summary + + # Non-blocking. Compares this PR against its base branch to flag skills + # whose cited sources (components / UX docs) changed but whose guidance has + # not been re-reviewed, and surfaces them as a GitHub review reminder. Runs + # here — at PR time, not release — so the author can update the skill in the + # same change. Never fails the PR (`continue-on-error`): soft drift is a + # heads-up, not a correctness error (that's what `validate` is for). + - name: Review skill drift (non-blocking) + continue-on-error: true + run: pnpm --filter @cloudoperators/juno-ui-components exec intent review --base "origin/${{ github.base_ref }}" --github-review --package-label "juno-ui-components" + diff --git a/.intent/review-state.json b/.intent/review-state.json new file mode 100644 index 0000000000..6acb1016d9 --- /dev/null +++ b/.intent/review-state.json @@ -0,0 +1,608 @@ +{ + "schemaVersion": 1, + "baseline": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "items": { + "skill:packages/ui-components/skills/accessibility/SKILL.md": { + "fingerprint": "6b8538342ed4a0eba8fbd5392437c0eceb05fad9a73c314646c15aa06975f348", + "snapshot": { + "docs/ux/accessibility.md": "d32ca231d6bce546856ea22b163597761e992d0f5b99fd457ea5c9e18314cea2", + "docs/ux/interaction-guidelines.md": "66b73ba90831440363a4cfdcc68100c4921088351648bd2f37caab6f27b5287f", + "packages/ui-components/skills/accessibility/SKILL.md": "9007d48fb7408e8dce8aa02f35a16232bfc0938c489bdc476cd33f1916639374", + "packages/ui-components/skills/accessibility/references/announcing-dynamic-content.md": "fe1bbaf9ccd43375655b9acc26b9478e7d22912d45d18ae7581e3da2c656a77c", + "packages/ui-components/skills/accessibility/references/semantic-foundations.md": "75f32c9d567a1ceee425e392f57b463be5b5da2559d8d0cf382b38a2bece0c84", + "packages/ui-components/src/components/Button/Button.component.tsx": "38a2b7989136a075ed8ca485ef51b4d5a4d77c9b6aa7cf0677b24e6e4bace0cb", + "packages/ui-components/src/components/Button/Button.stories.tsx": "79411b76c2ca6d59071e0258d5a60cb3e80533bb9f80f69063665fa8eeba31e1", + "packages/ui-components/src/components/CheckboxGroup/CheckboxGroup.component.tsx": "b71a206d9e9c63e8f1f4d553986f9db2e638c0e2cd61dd936b98336480314ace", + "packages/ui-components/src/components/Icon/Icon.component.tsx": "dc53e11e26f8194ed1c484f6a3d6a9c36b92f9419ae82694f4c141837b097a73", + "packages/ui-components/src/components/Modal/Modal.component.tsx": "1fa2b62d6497d3a48e7c28c3b5f47e5e4c3e09f468f727e4f47fecacd5433f8a", + "packages/ui-components/src/components/RadioGroup/RadioGroup.component.tsx": "86386e0365c2fb6863dd1dfad691a8ef08e259eac046124d3f4deb6e4fb5fde8", + "packages/ui-components/src/components/Status/Status.component.tsx": "b3aa376ca63d06c1c4b32c5cea881b692f9b335b58f01a9de732dd0d82400280", + "packages/ui-components/src/components/TextInput/TextInput.component.tsx": "cae8a354728da5d209476388f34528f0452f487bc206b6b713631d57bf3893c8" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/accessibility/SKILL.md, packages/ui-components/skills/accessibility/references/announcing-dynamic-content.md, packages/ui-components/skills/accessibility/references/semantic-foundations.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/actions/SKILL.md": { + "fingerprint": "38359da6824dff9674f3995b6dc608b7823dd30368972f057c24b875f13f7642", + "snapshot": { + "docs/ux/interaction-guidelines.md": "66b73ba90831440363a4cfdcc68100c4921088351648bd2f37caab6f27b5287f", + "docs/ux/page-level-actions.md": "704cd20150b542055a14c69648ecaccdd610a62e465c0aa039d31e4a9210db65", + "docs/ux/ux-writing-content-design.md": "de593155ba62395401f765f19d77ec65284f20a7bda4f123c63e61f0058f9973", + "packages/ui-components/skills/actions/SKILL.md": "1a1b9dc10bc207a19b55414fc1e7269c9062cb0db4865396ce52659bb88b50cf", + "packages/ui-components/skills/actions/references/label-wording.md": "f4d438fc006d69b34d98351f6ace7cf904cf2eee2802516fe6e8c8d43fde5e94", + "packages/ui-components/skills/actions/references/page-level-actions.md": "19f2f6880c3bf86377825424514e823e94a5baa1934e70e2e3025433a3cb6660", + "packages/ui-components/src/components/Button/Button.component.tsx": "38a2b7989136a075ed8ca485ef51b4d5a4d77c9b6aa7cf0677b24e6e4bace0cb", + "packages/ui-components/src/components/Button/Button.stories.tsx": "79411b76c2ca6d59071e0258d5a60cb3e80533bb9f80f69063665fa8eeba31e1", + "packages/ui-components/src/components/ButtonRow/ButtonRow.component.tsx": "f7306fca6077260cc1bae71f0b82df1af698527beb86fa72c92385e2a908f0ec", + "packages/ui-components/src/components/ButtonRow/ButtonRow.stories.tsx": "0efbdbd99d9a6800c5581ef3a0b12c9499c7976c7e094a02a9ff50f57c472adb", + "packages/ui-components/src/components/SortButton/SortButton.component.tsx": "d4da4cd64ebb23678c0affd9cebe6c95425ab78dcb186faeeeb70709a0e49e09", + "packages/ui-components/src/components/SortButton/SortButton.stories.tsx": "94f144e28fbdf6b8325addfaa37e95c287378f0b9e7ce0863a3eb4daf4bae16e", + "packages/ui-components/src/components/ThemeToggle/ThemeToggle.component.tsx": "f82828bc1dd1f1063b8219e8d0a5ccd6118722cb1a280e92cdbb48e38f08d892", + "packages/ui-components/src/components/ThemeToggle/ThemeToggle.stories.tsx": "ae655c412700aca1b585bfe97f1bdba180f2045c6e70734ce232370f5d8c9b14" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/actions/SKILL.md, packages/ui-components/skills/actions/references/label-wording.md, packages/ui-components/skills/actions/references/page-level-actions.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/app-foundations/SKILL.md": { + "fingerprint": "62c6d221c36e32025f55fe6d21fbfeaf08e05efba618ec74468f5d924c59ec0f", + "snapshot": { + "docs/ux/core-concepts.md": "706e80d691d4d5b3765f8db35982afda0165eb2fc398427121beda6ebd1cf4ca", + "docs/ux/embedded-application-layout.md": "3e6029d290752f29f14f175f63668dd829081d39e7a4f3ba54bcfb59a42b86e5", + "docs/ux/foundations.md": "c67bf3c3ec66d3171807e2e476384050001ff4d19064736499641a2cb0298b4d", + "docs/ux/getting-started-with-juno-ui-components.md": "74f9bb51a1a9f573c0a3d5d539c07482451632d126a1ce620cf7c6a2e80281bc", + "docs/ux/the-appshell.md": "6d790437907488a9106d8a88a04fd98e789dfda0f78b2d304f8a2ed9223fe9f8", + "packages/ui-components/skills/app-foundations/SKILL.md": "4d5d71137a9497a93ac5c91779c488e70bbc9aadf4eebb7524a703afdb08f9df", + "packages/ui-components/skills/app-foundations/references/portals.md": "56e586430c6ef998e196374f109bc6049a902caebbbec237b5ac1f13e8134b21", + "packages/ui-components/skills/app-foundations/references/providers-standalone.md": "52b9f35f95e30944685a28b72acc272be8e8fe57ba432d70c9fb67dd04b3adfc", + "packages/ui-components/src/components/AppShellProvider/AppShellProvider.component.tsx": "702fde8555aab675df467c87c4bfa8fc68053f1bdbc741802ff7ca7a008ba29d", + "packages/ui-components/src/components/AppShellProvider/AppShellProvider.stories.tsx": "daad3c6718177660121a835b550c2b294fe141012bf8b90a0bb096d0036ad9a0", + "packages/ui-components/src/components/PortalProvider/PortalProvider.component.tsx": "87f56c421f5511edf2910a7b678d823446bd84c28a6fcf0d09e43de46a5f7599", + "packages/ui-components/src/components/PortalProvider/PortalProvider.stories.tsx": "aba8638017a100cd2a5369a983d50574fcc70d3148171326560691dc3638aa5f", + "packages/ui-components/src/components/ShadowRoot/ShadowRoot.component.tsx": "df1e7432ef6c7656cbf3edb01362b207e0a6a06223742e489379fd5acf3c977c", + "packages/ui-components/src/components/ShadowRoot/ShadowRoot.stories.tsx": "2440718f3733b8449e153d79bb78e3d151610cae20ed0f61d8d793e4a2f8ad75", + "packages/ui-components/src/components/StyleProvider/StyleProvider.component.tsx": "36b9f2c49958770facb25cd40b1b2d9ee8dcc2733905894c200a06c329fe083a", + "packages/ui-components/src/components/StyleProvider/StyleProvider.stories.tsx": "0c11234442547e0afe5e6f0651279412f6fc6016840811c79d2d407c4d63598f" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/app-foundations/SKILL.md, packages/ui-components/skills/app-foundations/references/portals.md, packages/ui-components/skills/app-foundations/references/providers-standalone.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/data-display/SKILL.md": { + "fingerprint": "1bfd3bcd0a84a204770635ff9cfc2a3b0bbf66eaaba0ac5150d83c7c3a486f40", + "snapshot": { + "docs/ux/datagrid.md": "a2c243bf5be35cd456d1ebe1f85df166a3816db628f3270e76a76fb59493bd99", + "docs/ux/ux-writing-content-design.md": "de593155ba62395401f765f19d77ec65284f20a7bda4f123c63e61f0058f9973", + "packages/ui-components/skills/data-display/SKILL.md": "2a63b585d63f1b3e2b536a58a327c09873802effd71ad9330a267d69fd2fe84b", + "packages/ui-components/skills/data-display/references/codeblock-footer.md": "f8a413ca6c6852a8ac7cc5383de2842005311d60c971774ad828ca68e661a371", + "packages/ui-components/skills/data-display/references/description-list-layout.md": "352a66ad7ef089005b3a7d556fb5fa3a05f5c3f1f6caa8af487de030aa9f6f10", + "packages/ui-components/skills/data-display/references/icon-names.md": "c8fabb014c8200dba59f67f78031eb38a471fbd90ecf83592ba45e3440b6993e", + "packages/ui-components/src/components/Card/Card.component.tsx": "cba8445f1487c9cc60da6fd3a23e502a02d9bfad55ed908d4d630477ed0f62f2", + "packages/ui-components/src/components/Card/Card.stories.tsx": "c4f2139d9d2eb284421569de861827f0b5e5bef3b617c090dd8c04cebfd99ed1", + "packages/ui-components/src/components/Code/Code.component.tsx": "286e9f1b35ce7ebf35b3144023a124d68a2c58897d185261a961687648c9b516", + "packages/ui-components/src/components/Code/Code.stories.tsx": "18a46640fd3b69c271f2dc2bfba80b89417e4356e23772446837a58e08d703b6", + "packages/ui-components/src/components/CodeBlock/CodeBlock.component.tsx": "ebe90a94b60a67522329ef96f50517d00c7a688ae3a7ba25863c13de7067167d", + "packages/ui-components/src/components/CodeBlock/CodeBlock.stories.tsx": "323641768dab48d79a47caa3fa23ef0c7895a2aab2e9f9f3f4a03584f9863d98", + "packages/ui-components/src/components/CodeBlockFooter/CodeBlockFooter.component.tsx": "709894ea3f153bd17e1eb4e8307f4e18bac10bed84275b7bf236db2eff7d7ca9", + "packages/ui-components/src/components/CodeBlockFooter/CodeBlockFooter.stories.tsx": "175232e2f63d71ddbcac4b2ee679e5f984545851ee7dbb13c72db0af3217416a", + "packages/ui-components/src/components/DescriptionDefinition/DescriptionDefinition.component.tsx": "dd9fda56b50787bf59bcf2693f49cc36eb430de14ef9cd955f114a38c8ca1418", + "packages/ui-components/src/components/DescriptionList/DescriptionList.component.tsx": "0425b65632b98d481153900372ae36e95e09a5a646633f384f11e0f1c5b2932c", + "packages/ui-components/src/components/DescriptionList/DescriptionList.stories.tsx": "5d146d62bd9ebabfdfd641896fb4c8e10108abfe386fb1d1fa7bdd0890460490", + "packages/ui-components/src/components/DescriptionTerm/DescriptionTerm.component.tsx": "34fe197e89faf29da187f6cc158494dc6251f2b051f8c72931977bdb7bb8f1d8", + "packages/ui-components/src/components/FormattedText/FormattedText.component.tsx": "e33f109666da6dae669a2b99a982d794bab1b0c34cc40be8b3fdd2da80e7955b", + "packages/ui-components/src/components/FormattedText/FormattedText.stories.tsx": "eb5a6cb7fcdb5577809a431d98540cbbb95b00baff3363efccb283ac5ee871d4", + "packages/ui-components/src/components/Icon/Icon.component.tsx": "dc53e11e26f8194ed1c484f6a3d6a9c36b92f9419ae82694f4c141837b097a73", + "packages/ui-components/src/components/JsonViewer/JsonViewer.component.tsx": "4301664c16c531bc195aca63eeae549dba503ae9b229e7753529cfed7946e880", + "packages/ui-components/src/components/JsonViewer/JsonViewer.stories.tsx": "ed2f8793f05916ac2610cd7ebca7af147acb07b7b79f06bdedb49679a75d4bbf" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/data-display/SKILL.md, packages/ui-components/skills/data-display/references/codeblock-footer.md, packages/ui-components/skills/data-display/references/description-list-layout.md, packages/ui-components/skills/data-display/references/icon-names.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/datagrid/SKILL.md": { + "fingerprint": "f3306ebf0cfc3533074a9ed985a37cde53d19639fb2c2bff26e3b1b3aa177302", + "snapshot": { + "docs/ux/datagrid.md": "a2c243bf5be35cd456d1ebe1f85df166a3816db628f3270e76a76fb59493bd99", + "packages/ui-components/skills/datagrid/SKILL.md": "ba68af16ab4410f056b21086ba579e54f48ee97c46b200838a2d6af465e8fb32", + "packages/ui-components/skills/datagrid/references/bulk-selection.md": "6377b498d8ed1fc8839733de7704bcf2e79ba3537fe3188a7715708862ef896c", + "packages/ui-components/skills/datagrid/references/toolbar-zones.md": "891568497004fbd36620c964a63d00912769f5dcc0b6d15fd0dd2c40ef62b578", + "packages/ui-components/src/components/DataGrid/DataGrid.component.tsx": "6fbf8b63ca291d4fcae42bd59efde3e945b1148c198a6d6c1a4bc8bb64199904", + "packages/ui-components/src/components/DataGrid/DataGrid.stories.tsx": "db2003baceb27c32a0b63b71db7f9890f0830b24aa5beea896eb5a95b44a3e78" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/datagrid/SKILL.md, packages/ui-components/skills/datagrid/references/bulk-selection.md, packages/ui-components/skills/datagrid/references/toolbar-zones.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/feedback/SKILL.md": { + "fingerprint": "98c61bdf15c46421d15071ad180935a3aa3b555c38fcbc6a29ea7a9d513ffd4c", + "snapshot": { + "docs/ux/error-handling-loading-empty-states.md": "5ae642327fa1ab41d3f9a009f6211eb0e619d97905ae71d4edace31133d2ed35", + "docs/ux/messages-and-notifications.md": "5c30443667d09df95428b766b030aab1da3ad75d5b3d0b56b720a01ce040cfe8", + "docs/ux/semantic-variants.md": "9f94e59cf933270a72621785624d086d0130ec6dca6904fb5b72c2b0ec28efc4", + "docs/ux/transient-states-and-progress.md": "f5f71d81d91869abaec5394dbafe10bd7cfced7e81a1c45f3fb0b8a8f5674f20", + "packages/ui-components/skills/feedback/SKILL.md": "93ee2bc11f31f251ceb14601c14458d19d742e27729c39d8f69fbf21f8bb3357", + "packages/ui-components/skills/feedback/references/notifications.md": "e2b179d37754bc96a4a6902ea8742e08f30f41e3edf2653fcb1f04dcd5f3e201", + "packages/ui-components/skills/feedback/references/semantic-variants.md": "01a0a5d99a46c3e4ccf750f9e52f79f289e49c8da06fdb796294a92d5c8a5b02", + "packages/ui-components/src/components/Badge/Badge.component.tsx": "524f7cb642ab7cb3be0d5b20bf74eabd13b878973dd6df106ee5f079671c86dc", + "packages/ui-components/src/components/LoadingIndicator/LoadingIndicator.component.tsx": "2437c378bd007718fee2eff5a1fc5e85515d401289e3b31531be939ac7bf656a", + "packages/ui-components/src/components/Message/Message.component.tsx": "c7a594561fd75df7840f5d7b819dce410c54c51a71f8ec8501dfb925a64d01f9", + "packages/ui-components/src/components/Message/Message.stories.ts": "cce9d461b84d3c684ba64fd9b80fa187be88ba796e1fbc8ad0aed66ae9b8b655", + "packages/ui-components/src/components/NotificationManager/NotificationManager.component.tsx": "501bc8ef00f6ea14483ba523c3825bd800bed6a4ac33b404f1660a57fd9248c1", + "packages/ui-components/src/components/NotificationManager/NotificationManager.stories.tsx": "1558baf9a908f609a3e388cb91bdf11fa7953f98cd4483bc2c0efc02a2ecff5b", + "packages/ui-components/src/components/NotificationManager/NotificationManager.types.ts": "0abc0dd2e801587a2d940a18192d076cddb2bc08afb8e9b6abae635ebc5ae898", + "packages/ui-components/src/components/Pill/Pill.component.tsx": "fe0c12916f371707d52db5516fdb6b90d13bb67ceec13fd572b11762efa13711", + "packages/ui-components/src/components/ProgressBar/ProgressBar.component.tsx": "d187e7a0e7609cce86b25798d6d5d5496818bb5fcd74970afa01feb7dbdf0aa2", + "packages/ui-components/src/components/Spinner/Spinner.component.tsx": "0225200b2342b21c876bd2f3ec14c0eff6bc6aa5ccbd5e15ffb6bd2f9c082ac9", + "packages/ui-components/src/components/Status/Status.component.tsx": "b3aa376ca63d06c1c4b32c5cea881b692f9b335b58f01a9de732dd0d82400280", + "packages/ui-components/src/components/Status/Status.stories.tsx": "1b9657f07b0803c7543cf547a3b447977ec1545395bf820cb277b8901b2ee85a", + "packages/ui-components/src/components/Toast/Toast.component.tsx": "b6c34273713c8cbacc119205df2a6998d55bbf139a75d71450f90b204fda65f6", + "packages/ui-components/src/components/Toast/Toast.stories.tsx": "ab4e0bffa7049896c5b01983fe893fc2e83172be75285df12949705746d90ee4" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/feedback/SKILL.md, packages/ui-components/skills/feedback/references/notifications.md, packages/ui-components/skills/feedback/references/semantic-variants.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/forms/SKILL.md": { + "fingerprint": "620ba42723bf5eb0563405670996ffcaf01bd39d6b98b9163511efaef3588d26", + "snapshot": { + "docs/ux/authentication-and-access.md": "bc27551217fe8e74930491ab83fe3eb2e23cb0096da1327715f647889e61a606", + "docs/ux/forms.md": "48567f6a8297ea8ca36ead9cf4afb3f2cd534c1127d08ae126356f311ec23aa0", + "docs/ux/semantic-variants.md": "9f94e59cf933270a72621785624d086d0130ec6dca6904fb5b72c2b0ec28efc4", + "docs/ux/sign-in.md": "7c79a772de5f7e2330b2dba00db407b68b0978f7a4a289c214620fbe10387659", + "packages/ui-components/skills/forms/SKILL.md": "f8f36ee50be28bc7ee0821f2f1b13a3b3d127efb1d1f9129facafd468f2209d2", + "packages/ui-components/skills/forms/references/secret-and-date.md": "66e9aa6f3572465e4db0c1b31c9d7e6cad77430582480673fd2321a9d529a39c", + "packages/ui-components/skills/forms/references/selects.md": "27b1f9500ea4755674c9785f0bd4928007b86a0c69a63185d97395b7ca715e0a", + "packages/ui-components/skills/forms/references/sign-in.md": "a35a5d7febfd03290cbb8fb7cb0cc80d51a4264861b9f79443c06813c21d5345", + "packages/ui-components/skills/forms/references/validation.md": "bd2d8c4c6648056902475a716d9055c3b91abb189ae8ad8b921f35bb8aad88fc", + "packages/ui-components/src/components/Checkbox/Checkbox.component.tsx": "eb943dad61f124ef8515b08396fb97ea19bc7d4b1ba8dc4efd24433f92e2b96a", + "packages/ui-components/src/components/CheckboxGroup/CheckboxGroup.component.tsx": "b71a206d9e9c63e8f1f4d553986f9db2e638c0e2cd61dd936b98336480314ace", + "packages/ui-components/src/components/ComboBox/ComboBox.component.tsx": "d6d38b4ad34b216c06e555073d0441a39642d588e7569a45f2b3a87338cfb834", + "packages/ui-components/src/components/ComboBoxOption/ComboBoxOption.component.tsx": "a6d15add75ee150dee64878a1163c7e30ebd63fadaf728106b1e1674f087de90", + "packages/ui-components/src/components/DateTimePicker/DateTimePicker.component.tsx": "e0bfa5dd438236e97b69ba11daca3836136d3aa1d948dfe794f8ec947216d029", + "packages/ui-components/src/components/Form/Form.component.tsx": "ea9e036cd12d9f3fa863229470f65990c3861e5d526cf13735c92a9e12527a71", + "packages/ui-components/src/components/FormHint/FormHint.component.tsx": "4ae03e7c014c55224f142c7073250419483221308668a95236a9a34f83baeeb5", + "packages/ui-components/src/components/FormRow/FormRow.component.tsx": "bb8b4d88832a657d59cf88148c5ac8f444be996ebe740fab784e7eff8fadf15b", + "packages/ui-components/src/components/FormSection/FormSection.component.tsx": "72765126599417212d6830152147d88540da38460ebeab99af75bb99fe385045", + "packages/ui-components/src/components/InputGroup/InputGroup.component.tsx": "a60f62834176ae3a2b4926b06db88b7c5bf6222781a0287c051a52072c9cdba7", + "packages/ui-components/src/components/InputGroup/InputGroup.stories.tsx": "2d8d3ef7c3ee4f4c26b8e686de56d7d0a02aeb68b9683a963a92d0d54f8c2579", + "packages/ui-components/src/components/Label/Label.component.tsx": "1191d7d1e40778388913167dc5a0779fc0d9d928f42e58b152b8d5c870b83c10", + "packages/ui-components/src/components/NativeSelect/NativeSelect.component.tsx": "453ea8bb59c2d604136f6c18c74a99146dc33ad331335e9a1ccc17397f8d2903", + "packages/ui-components/src/components/NativeSelectOption/NativeSelectOption.component.tsx": "3a9654b83ca6b78856070974362acd45895fae68b00d871c4e16a112ec4894bb", + "packages/ui-components/src/components/NativeSelectOptionGroup/NativeSelectOptionGroup.component.tsx": "931066fe9125c1003a50bb1ea6706d43bf788a3daa92c19575893f0aa28e0dde", + "packages/ui-components/src/components/Radio/Radio.component.tsx": "840c24c0cc9785285f08d9266935db2e82b386e76340eae953806e796a71f87a", + "packages/ui-components/src/components/RadioGroup/RadioGroup.component.tsx": "86386e0365c2fb6863dd1dfad691a8ef08e259eac046124d3f4deb6e4fb5fde8", + "packages/ui-components/src/components/RadioGroup/RadioGroup.stories.tsx": "ae92ee3c899274ff8d2dbb8ba79acd5ee96d3fb521cdfc5f99ad69cb27d67158", + "packages/ui-components/src/components/SearchInput/SearchInput.component.tsx": "828b4ce57b12d38fad735209993c386edbda5b7b1a9f3b2e8c1a66165f45d72a", + "packages/ui-components/src/components/SecretText/SecretText.component.tsx": "a4cf80d86d7af38a90fd840abb9f3a7b695137a101a811e7b6fe1c32f9475fd6", + "packages/ui-components/src/components/Select/Select.component.tsx": "7112feb2fda76a658739d5352400aa4160c1b4f49e15cb0e8e64210dd253385c", + "packages/ui-components/src/components/Select/Select.stories.tsx": "b21567094b03f62361ab1dc7301a736cf800397e652800ef2b90f21810b9fcc3", + "packages/ui-components/src/components/SelectDivider/SelectDivider.component.tsx": "426d5310c02ebd8093d115738ca0bc26d836a2152c1cd0cb27c86a3b20164be4", + "packages/ui-components/src/components/SelectOption/SelectOption.component.tsx": "d60db7a86501291f6a7451515ba397e359e977d81e727a9c4cc7bcc5598ef6b3", + "packages/ui-components/src/components/SignInForm/SignInForm.component.tsx": "c0feaf6df3805e2fcc6c6be97835b0723ce981345f95e2ccef57f7cc4b75f82a", + "packages/ui-components/src/components/SignInForm/SignInForm.stories.tsx": "b26513a50a92368c8037aafb39b106cf296bf7475878c8bce3a9865435c38ea6", + "packages/ui-components/src/components/Switch/Switch.component.tsx": "314cc633a540b7948218467506d0ad37011258d95c1f1d7fbd9ab000f39a99fc", + "packages/ui-components/src/components/TextInput/TextInput.component.tsx": "cae8a354728da5d209476388f34528f0452f487bc206b6b713631d57bf3893c8", + "packages/ui-components/src/components/TextInput/TextInput.stories.tsx": "3c5cb9b54285b801097e9c503083dd40e41e9a9477b8af447ea6e2c2776f2dd3", + "packages/ui-components/src/components/Textarea/Textarea.component.tsx": "1ce90cf4d17a101aef2ce234f3122bcf177aedc8646912a413c1d7f33187a6d3", + "packages/ui-components/src/components/ToggleButton/ToggleButton.component.tsx": "838ddd8377ed67cd7fd1a6cfa7a090d16bd1d6e6d66c844a340704c9acd582c2" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/forms/SKILL.md, packages/ui-components/skills/forms/references/secret-and-date.md, packages/ui-components/skills/forms/references/selects.md, packages/ui-components/skills/forms/references/sign-in.md, packages/ui-components/skills/forms/references/validation.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/interaction-patterns/SKILL.md": { + "fingerprint": "3e583478c29662621a17e2a4fadc9a898e064fd32910fe3ac50322a369c9d7e6", + "snapshot": { + "docs/ux/inline-adding-editing-and-deleting.md": "38431cabf2e676c658843e731426c01164a6c068c0b99836fb9dcbf01a3a06db", + "docs/ux/interaction-guidelines.md": "66b73ba90831440363a4cfdcc68100c4921088351648bd2f37caab6f27b5287f", + "docs/ux/page-and-user-flow.md": "992f3953ed2c74b6aa1a9cf5229c1ea749834fb5e76560708fad956e440b2e0a", + "docs/ux/ui-for-unauthorized-users.md": "1822a7af9e431fb2d51aee27ca995c224005b7f747e57ff71d1f9f70b780e19e", + "docs/ux/wizard.md": "28c493b06c05440b2ff230477bf8e36e032df99677c7ad54855750c8e9e069ab", + "packages/ui-components/skills/interaction-patterns/SKILL.md": "b92ce7e1832fb2ec06caee672848a4f0d340f7cc27ad9b20bc804997f8d4bad1", + "packages/ui-components/skills/interaction-patterns/references/authorization-ui.md": "c7b7018625fcdbef8d07b593208744f38a5c471f1482281a1fe819da67936ba5", + "packages/ui-components/skills/interaction-patterns/references/inline-crud.md": "8da7f2c99bbeb72f33ca17d72ebda3fa9bd38265843f3cfab4d5d3c666ade66a", + "packages/ui-components/skills/interaction-patterns/references/wizard.md": "c60139aaa51c145462c5ae3470d77cb349a78a78a6522d573ecf9199158c0ad9", + "packages/ui-components/src/components/Button/Button.component.tsx": "38a2b7989136a075ed8ca485ef51b4d5a4d77c9b6aa7cf0677b24e6e4bace0cb", + "packages/ui-components/src/components/Button/Button.stories.tsx": "79411b76c2ca6d59071e0258d5a60cb3e80533bb9f80f69063665fa8eeba31e1", + "packages/ui-components/src/components/Modal/Modal.component.tsx": "1fa2b62d6497d3a48e7c28c3b5f47e5e4c3e09f468f727e4f47fecacd5433f8a", + "packages/ui-components/src/components/Modal/Modal.stories.tsx": "adad76347e3c27b33c132ab9bf8463acd3fa100746ab670a92e419e1837bdaad", + "packages/ui-components/src/components/ModalFooter/ModalFooter.component.tsx": "9e71267af1af65af685bea53d46f117e76ebf1b60ab0b9450647880987329226", + "packages/ui-components/src/components/TextInput/TextInput.component.tsx": "cae8a354728da5d209476388f34528f0452f487bc206b6b713631d57bf3893c8", + "packages/ui-components/src/components/Tooltip/Tooltip.component.tsx": "6473f419ee752041c61d0d8a5875ba10a95750c8b75a81c06c04a76a9c2b16e0" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/interaction-patterns/SKILL.md, packages/ui-components/skills/interaction-patterns/references/authorization-ui.md, packages/ui-components/skills/interaction-patterns/references/inline-crud.md, packages/ui-components/skills/interaction-patterns/references/wizard.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/layout/SKILL.md": { + "fingerprint": "bc8d33bcb41c8588cb0eec1b96f13e0146b53b329b86045ac8f9bde3e90bb643", + "snapshot": { + "docs/ux/box.md": "448217525d318b044e3cb79c24a735c6ec69260a7eadec00ae9b859147095c54", + "docs/ux/embedded-application-layout.md": "3e6029d290752f29f14f175f63668dd829081d39e7a4f3ba54bcfb59a42b86e5", + "docs/ux/juno-layout.md": "ca091146d6412ca4491664187a406f8fc00a26ed9e7220dbf6a91b031a240569", + "docs/ux/layout-fundamentals.md": "95867815b08b51ac790cce9da352bca552c2207ec66ae02be0e73d7dc6ee5ff2", + "docs/ux/page-content-area.md": "923a248c8c5b81c5197058444eae0da3ed09818c14b48185acc4ee7578a789d9", + "docs/ux/page-footer.md": "ae4ae88d01d4a67d5f212938af875e1a0f08f5d64c4689ffb44a2fcacdb3ac29", + "docs/ux/page-header.md": "036cab8c408f3f0ff9f69b1155c25703e4c10ee79cc7a271d954bdde1cb8098f", + "docs/ux/page-layout-elements.md": "c5b95aa042858da3833d249437327eaea75760caa0d8499761b91150df5632dc", + "docs/ux/the-appshell.md": "6d790437907488a9106d8a88a04fd98e789dfda0f78b2d304f8a2ed9223fe9f8", + "packages/ui-components/skills/layout/SKILL.md": "9db62d998ce1d27ae1801e2f58d112beac9c8062df5f8e0cc984f248fb3de8e0", + "packages/ui-components/skills/layout/references/box-patterns.md": "a4cab726012a4c9ec56b8b349a53ab34a8057aa0fee16d561ab377104e44e8d3", + "packages/ui-components/skills/layout/references/grid-and-stack.md": "ad645de1ab9d1c596daa998b10a5054edfdb2f22e421f5d66c714fe5d5ab592a", + "packages/ui-components/skills/layout/references/manual-layout.md": "d4d77981f9e228b25c5c795342444b3fe082328bc767d951ae4da5102bc6f4d9", + "packages/ui-components/skills/layout/references/page-footer.md": "4b70f85686d19f5d25dea1adf6454aecda8fe31d65a0e6faee118cf62e7c6ca1", + "packages/ui-components/src/components/AppBody/AppBody.component.tsx": "775427fbbea0f92f5261fa18592742fdd9ec54608796227b33b9aad59c313b05", + "packages/ui-components/src/components/AppShell/AppShell.component.tsx": "10c6a77de4c3c0c3981dcd0427461f950b668d17227ad57e0360db1a7e0e82e2", + "packages/ui-components/src/components/AppShell/AppShell.stories.tsx": "ec5fbc3423a0f93f5f1db9940110d6e17fef0c7ea8495dd140ed10d98ee7765f", + "packages/ui-components/src/components/AppShellProvider/AppShellProvider.component.tsx": "702fde8555aab675df467c87c4bfa8fc68053f1bdbc741802ff7ca7a008ba29d", + "packages/ui-components/src/components/Box/Box.component.tsx": "d3f1285de707d847a1bb3a221b2b5259ba9d534e2d43513bff160c32d177326c", + "packages/ui-components/src/components/Container/Container.component.tsx": "730441879e45bce08a18bf27324a19b7d36801b2164078c9c911cf73fd0666c7", + "packages/ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.component.tsx": "90163b1d91adc6fc7cd9f9b711723e0a4a6604accc57050111a582322adb1025", + "packages/ui-components/src/components/ContentContainer/ContentContainer.component.tsx": "052864bf9b260c264da5deb32cd81d9a1baeb71d1d180e21f1ff924994d7eac6", + "packages/ui-components/src/components/ContentHeading/ContentHeading.component.tsx": "f2724c8bfd8ce2db6659463bb40654147c4b86f4f1002f94c7d0a788a36c4d16", + "packages/ui-components/src/components/Divider/Divider.component.tsx": "864a232db72804613fe791a744e78d354df9a3ba8cfa4dd01b5875984a6095ef", + "packages/ui-components/src/components/Grid/Grid.component.tsx": "3058fac661a3c5a917fe6b1d259f1ed15cad80cfd643a8f372d8bfdd8f6311a8", + "packages/ui-components/src/components/GridColumn/GridColumn.component.tsx": "e119123d671096b3c9ed5f491573574d64438854a09e2bdb3849b0aa91fec6cf", + "packages/ui-components/src/components/GridRow/GridRow.component.tsx": "b3f38c228144600df4e64a6d49b9bcae5eeae37fabeb38f728ae7a4e93e7c52e", + "packages/ui-components/src/components/HeaderContainer/HeaderContainer.component.tsx": "b4b2e406d6368ddf751c7eb11a84e2e54dac584acb357b9e92ffb8ddd87447f6", + "packages/ui-components/src/components/IntroBox/IntroBox.component.tsx": "0e0c6ceba7b1311c103f2ad2f4c19ebe129ef9b6a505c36a772a4c76db2cce47", + "packages/ui-components/src/components/MainContainer/MainContainer.component.tsx": "d109c53845b29fa7bcdcfb2e995e5e4935c75d3bc06e2e58c6445f1af183525f", + "packages/ui-components/src/components/MainContainerInner/MainContainerInner.component.tsx": "a33f1440d83f724d66fff70def7e91bddb7852d8122b667695284040f32189b3", + "packages/ui-components/src/components/PageFooter/PageFooter.component.tsx": "b4efaa0574659fc3170984900a04f27820c8c4024b277ace9ba43ecf995efa12", + "packages/ui-components/src/components/PageFooter/PageFooter.stories.tsx": "2ea5ac1a7b4dcff0c28e728fc28926af9e490cb0d79f2b9ee969b54a40504ee6", + "packages/ui-components/src/components/PageHeader/PageHeader.component.tsx": "a98785becfc6a806570d38a6a4f18bfd0636b76dd9702a78cab6ca3e8cae6d7b", + "packages/ui-components/src/components/Stack/Stack.component.tsx": "963eabb8a291a63314b906cfce332c05211fb521cee477af2c139fbbbceba3a2" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/layout/SKILL.md, packages/ui-components/skills/layout/references/box-patterns.md, packages/ui-components/skills/layout/references/grid-and-stack.md, packages/ui-components/skills/layout/references/manual-layout.md, packages/ui-components/skills/layout/references/page-footer.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/navigation/SKILL.md": { + "fingerprint": "7aa0b1e52022071c751569cc25efbd52ffc11be96363daa7ef227a391a174ba8", + "snapshot": { + "docs/ux/navigation-fundamentals.md": "e0ace4c0c1291b6983fcca9296c0bbc24f7c2c8709f4169a28be7da86f99c69f", + "docs/ux/navigation-side-navigation.md": "830600d0766221d1cc0fc9c89b324717e1fbdc336625bb63a0d97ee339bbdcaf", + "docs/ux/navigation.md": "783b1d3237531502492bf0c9af68b381257171772853c96dd681c41aa0583836", + "docs/ux/page-and-user-flow.md": "992f3953ed2c74b6aa1a9cf5229c1ea749834fb5e76560708fad956e440b2e0a", + "packages/ui-components/skills/navigation/SKILL.md": "bb5182f5ec535f3863f20dbb0bdf124356486aefa610fc7f3cfe15b529fd1051", + "packages/ui-components/skills/navigation/references/legacy-tabs.md": "26b3046e02bc27ce69c6266d57bf568f6f6cc7f434599359be68723d3bec3bdb", + "packages/ui-components/skills/navigation/references/pagination.md": "2f57b4424fd3da133620478fcd7c4edd29975d504b32f03f967777eb44d57a9d", + "packages/ui-components/skills/navigation/references/second-level-bars.md": "c9da9af7be0532d557fca4b04eb8dbcf419e7e4c509475e3bcb2e2fc841411af", + "packages/ui-components/src/components/Breadcrumb/Breadcrumb.component.tsx": "bf9ca6d22962a52bb30be47a37b05f703b88b07b62f52b015bffc743629d203b", + "packages/ui-components/src/components/BreadcrumbItem/BreadcrumbItem.component.tsx": "5c9552521ce63d2d63381ccebd5d707df9d4d72c39dc778f12c0ba670b274fea", + "packages/ui-components/src/components/Navigation/Navigation.component.tsx": "fa439180c6daa3ac29f5a01bf336f75e037610d92a6993ff8c1ade51305fc7e0", + "packages/ui-components/src/components/NavigationItem/NavigationItem.component.tsx": "f7b50d3cb20a77ec132f26e852564065b9a3d14baddacbb8d2d8e1e5b2b195b7", + "packages/ui-components/src/components/Pagination/Pagination.component.tsx": "f5babcb2696a2daccea4cda8e3e8f05fc3989bbcb96fc790afbcc6cd4555174a", + "packages/ui-components/src/components/SideNavigation/SideNavigation.component.tsx": "583bf0e7874fdd9bbb223db3d657bac13fc5b6053522883f6a4748e429d882c7", + "packages/ui-components/src/components/SideNavigation/SideNavigation.stories.tsx": "ebaa6753eb96e5674a7133fb473bd0918d8a9b57727f644d0589b8a5b4a19731", + "packages/ui-components/src/components/SideNavigationGroup/SideNavigationGroup.component.tsx": "a15b357528255fb93fc95f96fb2aee72592a04898a5b20836762a97b97e818d3", + "packages/ui-components/src/components/SideNavigationItem/SideNavigationItem.component.tsx": "a895c0f2939f3013ddbd6af49a679c44f05001fff54de293fcccb1dbcddbb2fc", + "packages/ui-components/src/components/SideNavigationList/SideNavigationList.component.tsx": "618928c7ba37de8ae71a1d1b5c4e3a2f2233769e243314f7329404f83eecdb7c", + "packages/ui-components/src/components/TabBar/TabBar.component.tsx": "28ac3c001318f9fcf7654529385171017fa2c7fd8101f69aa45300e54ebb49c9", + "packages/ui-components/src/components/TabBarItem/TabBarItem.component.tsx": "0ae587b3897cbcfb9f48114536e01719489a7435a91789e80d0f2833e72cc36a", + "packages/ui-components/src/components/Tabs/Tabs.component.tsx": "e99281dfad18e6c0764854c358ea09190cb58e128c871fe6ce65105c10dab398", + "packages/ui-components/src/components/TopNavigation/TopNavigation.component.tsx": "f0951e0a048d02fa509a080f6b2d7fac22a41bf2097309d6c41598605fc373af", + "packages/ui-components/src/components/TopNavigationItem/TopNavigationItem.component.tsx": "3d34ae8bece0cda5a1fe61f65fa4d4f2c0567715266e91e416de6d9f233d107d" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/navigation/SKILL.md, packages/ui-components/skills/navigation/references/legacy-tabs.md, packages/ui-components/skills/navigation/references/pagination.md, packages/ui-components/skills/navigation/references/second-level-bars.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/overlays/SKILL.md": { + "fingerprint": "df48a6b54e1950773ce42136e19e8b16716650ba8569a0154adb32c092a03571", + "snapshot": { + "docs/ux/interaction-guidelines.md": "66b73ba90831440363a4cfdcc68100c4921088351648bd2f37caab6f27b5287f", + "docs/ux/modals.md": "e57ab3f6e68b08d490a3b4f948a1880ffee48ba838ed70f18d5ccd38b239b8ca", + "docs/ux/popup-and-overflow-menus.md": "3a33ef9ab5afee91e21075ec2b2ac05d0dae981af75e55122780f7571dd57b45", + "packages/ui-components/skills/overlays/SKILL.md": "c26f8297f1bfdddfbf437df518f925f08d1b2bbc1f92bb0bf7d0fe2947e5d54c", + "packages/ui-components/skills/overlays/references/modal-patterns.md": "e615258d2f4eb9c07fbc33031f9e2055cdffd8825b62357ffc992694401a9607", + "packages/ui-components/skills/overlays/references/popup-menu-composition.md": "75a012039d83dbfa6351141688b124f03f34f0a9ea70b6e8a856c59678ba600a", + "packages/ui-components/skills/overlays/references/tooltip-modes.md": "a0d9cfc44d8c2e8e545f6ab06ad428e77498acf9bd6fc50900a59ebeaa4700f2", + "packages/ui-components/src/components/Modal/Modal.component.tsx": "1fa2b62d6497d3a48e7c28c3b5f47e5e4c3e09f468f727e4f47fecacd5433f8a", + "packages/ui-components/src/components/Modal/Modal.stories.tsx": "adad76347e3c27b33c132ab9bf8463acd3fa100746ab670a92e419e1837bdaad", + "packages/ui-components/src/components/ModalFooter/ModalFooter.component.tsx": "9e71267af1af65af685bea53d46f117e76ebf1b60ab0b9450647880987329226", + "packages/ui-components/src/components/Panel/Panel.component.tsx": "b0d50930dec9a6fb76368ae12822cdc503dcb68f37470bde15d40fdc8d8d4fac", + "packages/ui-components/src/components/Panel/Panel.stories.tsx": "bf8b032a6f9a6e14b632f0b9fc855faf93cbd339a101abb3af77eaccc234b866", + "packages/ui-components/src/components/PanelBody/PanelBody.component.tsx": "d1c399d5d9d2f6b0e7a42dee7b39881d2fd15b6d2e6b1052d747d417f2c914ec", + "packages/ui-components/src/components/PanelFooter/PanelFooter.component.tsx": "8a916a05328ed85f7c29d1b38fc969c8aaf3da42f6983534017e1536b9267dcb", + "packages/ui-components/src/components/PopupMenu/PopupMenu.component.tsx": "1f393465aed7aed1e9c09e89946237dd205c1a91508be5c0ea650cf0c623c319", + "packages/ui-components/src/components/PopupMenu/PopupMenu.stories.tsx": "e16ac76f152378acd04d88ef51d971a6c3dc2a24b17b4013e947335304cca73e", + "packages/ui-components/src/components/PortalProvider/PortalProvider.component.tsx": "87f56c421f5511edf2910a7b678d823446bd84c28a6fcf0d09e43de46a5f7599", + "packages/ui-components/src/components/Tooltip/Tooltip.component.tsx": "6473f419ee752041c61d0d8a5875ba10a95750c8b75a81c06c04a76a9c2b16e0", + "packages/ui-components/src/components/Tooltip/Tooltip.stories.tsx": "b7e00f30902cdc3b1dbe1ae5e68b78a0effb39a483a1a8bb4514dc1d83713fd1", + "packages/ui-components/src/components/TooltipContent/TooltipContent.component.tsx": "b2cf09e5688afe8d218709baab6e7b8b165d93ababbd09c21c7bf565793fa06f", + "packages/ui-components/src/components/TooltipTrigger/TooltipTrigger.component.tsx": "9eafa46b8ef6c6b46ac93068f61ac8ffc2ca0d99886e2a66ff9663c6e6ffc9d1" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/overlays/SKILL.md, packages/ui-components/skills/overlays/references/modal-patterns.md, packages/ui-components/skills/overlays/references/popup-menu-composition.md, packages/ui-components/skills/overlays/references/tooltip-modes.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "skill:packages/ui-components/skills/ux-writing/SKILL.md": { + "fingerprint": "f12b58024679a3ae6bce17848bc46b46ae787d4101da7a87b88ec431988d897c", + "snapshot": { + "docs/ux/application-design-guidelines.md": "490452676000dbd53834b5a4f826341415a202c22740e81551b5465d2024eca4", + "docs/ux/ux-writing-content-design.md": "de593155ba62395401f765f19d77ec65284f20a7bda4f123c63e61f0058f9973", + "packages/ui-components/skills/ux-writing/SKILL.md": "f494a4154eb9bcdae28cfb73b78ca0c2cba9998a479ba29a8cb833d3bd4e7422", + "packages/ui-components/skills/ux-writing/references/empty-values.md": "7c77d8a6d9f9ab84ee41d614efd9529c22fd47fad9f579ff1dc428ca3f9d2b2c", + "packages/ui-components/skills/ux-writing/references/title-case.md": "620872e3ece8e4b63eadda9a3feb006e6f835e5ef7863228113a3947b793d32d", + "packages/ui-components/src/components/Button/Button.component.tsx": "38a2b7989136a075ed8ca485ef51b4d5a4d77c9b6aa7cf0677b24e6e4bace0cb", + "packages/ui-components/src/components/Button/Button.stories.tsx": "79411b76c2ca6d59071e0258d5a60cb3e80533bb9f80f69063665fa8eeba31e1", + "packages/ui-components/src/components/Message/Message.component.tsx": "c7a594561fd75df7840f5d7b819dce410c54c51a71f8ec8501dfb925a64d01f9", + "packages/ui-components/src/components/Modal/Modal.component.tsx": "1fa2b62d6497d3a48e7c28c3b5f47e5e4c3e09f468f727e4f47fecacd5433f8a", + "packages/ui-components/src/components/Status/Status.component.tsx": "b3aa376ca63d06c1c4b32c5cea881b692f9b335b58f01a9de732dd0d82400280" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: packages/ui-components/skills/ux-writing/SKILL.md, packages/ui-components/skills/ux-writing/references/empty-values.md, packages/ui-components/skills/ux-writing/references/title-case.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "planning:_artifacts": { + "fingerprint": "3a65da61781856d311ed49db09ae6bbd5e1612108b0e701d4eb4459b1ca4e015", + "snapshot": { + "_artifacts/domain_map.yaml": "443c2366350f9d94e319790417e8730ebc1a41889f90ac42176f51aa0f7971d9", + "_artifacts/skill_spec.md": "6802376c23cafdf0a0e939cb1ef9f55e2a0ea2cabf873a9291494c9b8d1b8dfd", + "_artifacts/skill_tree.yaml": "ee77addcb6024b6d57543a2f40cb3357f68358c1af1637e0405d58d53029dad1", + "docs/ux/accessibility.md": "d32ca231d6bce546856ea22b163597761e992d0f5b99fd457ea5c9e18314cea2", + "docs/ux/application-design-guidelines.md": "490452676000dbd53834b5a4f826341415a202c22740e81551b5465d2024eca4", + "docs/ux/authentication-and-access.md": "bc27551217fe8e74930491ab83fe3eb2e23cb0096da1327715f647889e61a606", + "docs/ux/box.md": "448217525d318b044e3cb79c24a735c6ec69260a7eadec00ae9b859147095c54", + "docs/ux/core-concepts.md": "706e80d691d4d5b3765f8db35982afda0165eb2fc398427121beda6ebd1cf4ca", + "docs/ux/datagrid.md": "a2c243bf5be35cd456d1ebe1f85df166a3816db628f3270e76a76fb59493bd99", + "docs/ux/embedded-application-layout.md": "3e6029d290752f29f14f175f63668dd829081d39e7a4f3ba54bcfb59a42b86e5", + "docs/ux/error-handling-loading-empty-states.md": "5ae642327fa1ab41d3f9a009f6211eb0e619d97905ae71d4edace31133d2ed35", + "docs/ux/forms.md": "48567f6a8297ea8ca36ead9cf4afb3f2cd534c1127d08ae126356f311ec23aa0", + "docs/ux/foundations.md": "c67bf3c3ec66d3171807e2e476384050001ff4d19064736499641a2cb0298b4d", + "docs/ux/getting-started-with-juno-ui-components.md": "74f9bb51a1a9f573c0a3d5d539c07482451632d126a1ce620cf7c6a2e80281bc", + "docs/ux/inline-adding-editing-and-deleting.md": "38431cabf2e676c658843e731426c01164a6c068c0b99836fb9dcbf01a3a06db", + "docs/ux/interaction-guidelines.md": "66b73ba90831440363a4cfdcc68100c4921088351648bd2f37caab6f27b5287f", + "docs/ux/juno-layout.md": "ca091146d6412ca4491664187a406f8fc00a26ed9e7220dbf6a91b031a240569", + "docs/ux/layout-fundamentals.md": "95867815b08b51ac790cce9da352bca552c2207ec66ae02be0e73d7dc6ee5ff2", + "docs/ux/messages-and-notifications.md": "5c30443667d09df95428b766b030aab1da3ad75d5b3d0b56b720a01ce040cfe8", + "docs/ux/modals.md": "e57ab3f6e68b08d490a3b4f948a1880ffee48ba838ed70f18d5ccd38b239b8ca", + "docs/ux/navigation-fundamentals.md": "e0ace4c0c1291b6983fcca9296c0bbc24f7c2c8709f4169a28be7da86f99c69f", + "docs/ux/navigation-side-navigation.md": "830600d0766221d1cc0fc9c89b324717e1fbdc336625bb63a0d97ee339bbdcaf", + "docs/ux/navigation.md": "783b1d3237531502492bf0c9af68b381257171772853c96dd681c41aa0583836", + "docs/ux/page-and-user-flow.md": "992f3953ed2c74b6aa1a9cf5229c1ea749834fb5e76560708fad956e440b2e0a", + "docs/ux/page-content-area.md": "923a248c8c5b81c5197058444eae0da3ed09818c14b48185acc4ee7578a789d9", + "docs/ux/page-footer.md": "ae4ae88d01d4a67d5f212938af875e1a0f08f5d64c4689ffb44a2fcacdb3ac29", + "docs/ux/page-header.md": "036cab8c408f3f0ff9f69b1155c25703e4c10ee79cc7a271d954bdde1cb8098f", + "docs/ux/page-layout-elements.md": "c5b95aa042858da3833d249437327eaea75760caa0d8499761b91150df5632dc", + "docs/ux/page-level-actions.md": "704cd20150b542055a14c69648ecaccdd610a62e465c0aa039d31e4a9210db65", + "docs/ux/popup-and-overflow-menus.md": "3a33ef9ab5afee91e21075ec2b2ac05d0dae981af75e55122780f7571dd57b45", + "docs/ux/semantic-variants.md": "9f94e59cf933270a72621785624d086d0130ec6dca6904fb5b72c2b0ec28efc4", + "docs/ux/sign-in.md": "7c79a772de5f7e2330b2dba00db407b68b0978f7a4a289c214620fbe10387659", + "docs/ux/the-appshell.md": "6d790437907488a9106d8a88a04fd98e789dfda0f78b2d304f8a2ed9223fe9f8", + "docs/ux/transient-states-and-progress.md": "f5f71d81d91869abaec5394dbafe10bd7cfced7e81a1c45f3fb0b8a8f5674f20", + "docs/ux/ui-for-unauthorized-users.md": "1822a7af9e431fb2d51aee27ca995c224005b7f747e57ff71d1f9f70b780e19e", + "docs/ux/ux-writing-content-design.md": "de593155ba62395401f765f19d77ec65284f20a7bda4f123c63e61f0058f9973", + "docs/ux/wizard.md": "28c493b06c05440b2ff230477bf8e36e032df99677c7ad54855750c8e9e069ab", + "packages/ui-components/skills/accessibility/SKILL.md": "9007d48fb7408e8dce8aa02f35a16232bfc0938c489bdc476cd33f1916639374", + "packages/ui-components/skills/accessibility/references/announcing-dynamic-content.md": "fe1bbaf9ccd43375655b9acc26b9478e7d22912d45d18ae7581e3da2c656a77c", + "packages/ui-components/skills/accessibility/references/semantic-foundations.md": "75f32c9d567a1ceee425e392f57b463be5b5da2559d8d0cf382b38a2bece0c84", + "packages/ui-components/skills/actions/SKILL.md": "1a1b9dc10bc207a19b55414fc1e7269c9062cb0db4865396ce52659bb88b50cf", + "packages/ui-components/skills/actions/references/label-wording.md": "f4d438fc006d69b34d98351f6ace7cf904cf2eee2802516fe6e8c8d43fde5e94", + "packages/ui-components/skills/actions/references/page-level-actions.md": "19f2f6880c3bf86377825424514e823e94a5baa1934e70e2e3025433a3cb6660", + "packages/ui-components/skills/app-foundations/SKILL.md": "4d5d71137a9497a93ac5c91779c488e70bbc9aadf4eebb7524a703afdb08f9df", + "packages/ui-components/skills/app-foundations/references/portals.md": "56e586430c6ef998e196374f109bc6049a902caebbbec237b5ac1f13e8134b21", + "packages/ui-components/skills/app-foundations/references/providers-standalone.md": "52b9f35f95e30944685a28b72acc272be8e8fe57ba432d70c9fb67dd04b3adfc", + "packages/ui-components/skills/data-display/SKILL.md": "2a63b585d63f1b3e2b536a58a327c09873802effd71ad9330a267d69fd2fe84b", + "packages/ui-components/skills/data-display/references/codeblock-footer.md": "f8a413ca6c6852a8ac7cc5383de2842005311d60c971774ad828ca68e661a371", + "packages/ui-components/skills/data-display/references/description-list-layout.md": "352a66ad7ef089005b3a7d556fb5fa3a05f5c3f1f6caa8af487de030aa9f6f10", + "packages/ui-components/skills/data-display/references/icon-names.md": "c8fabb014c8200dba59f67f78031eb38a471fbd90ecf83592ba45e3440b6993e", + "packages/ui-components/skills/datagrid/SKILL.md": "ba68af16ab4410f056b21086ba579e54f48ee97c46b200838a2d6af465e8fb32", + "packages/ui-components/skills/datagrid/references/bulk-selection.md": "6377b498d8ed1fc8839733de7704bcf2e79ba3537fe3188a7715708862ef896c", + "packages/ui-components/skills/datagrid/references/toolbar-zones.md": "891568497004fbd36620c964a63d00912769f5dcc0b6d15fd0dd2c40ef62b578", + "packages/ui-components/skills/feedback/SKILL.md": "93ee2bc11f31f251ceb14601c14458d19d742e27729c39d8f69fbf21f8bb3357", + "packages/ui-components/skills/feedback/references/notifications.md": "e2b179d37754bc96a4a6902ea8742e08f30f41e3edf2653fcb1f04dcd5f3e201", + "packages/ui-components/skills/feedback/references/semantic-variants.md": "01a0a5d99a46c3e4ccf750f9e52f79f289e49c8da06fdb796294a92d5c8a5b02", + "packages/ui-components/skills/forms/SKILL.md": "f8f36ee50be28bc7ee0821f2f1b13a3b3d127efb1d1f9129facafd468f2209d2", + "packages/ui-components/skills/forms/references/secret-and-date.md": "66e9aa6f3572465e4db0c1b31c9d7e6cad77430582480673fd2321a9d529a39c", + "packages/ui-components/skills/forms/references/selects.md": "27b1f9500ea4755674c9785f0bd4928007b86a0c69a63185d97395b7ca715e0a", + "packages/ui-components/skills/forms/references/sign-in.md": "a35a5d7febfd03290cbb8fb7cb0cc80d51a4264861b9f79443c06813c21d5345", + "packages/ui-components/skills/forms/references/validation.md": "bd2d8c4c6648056902475a716d9055c3b91abb189ae8ad8b921f35bb8aad88fc", + "packages/ui-components/skills/interaction-patterns/SKILL.md": "b92ce7e1832fb2ec06caee672848a4f0d340f7cc27ad9b20bc804997f8d4bad1", + "packages/ui-components/skills/interaction-patterns/references/authorization-ui.md": "c7b7018625fcdbef8d07b593208744f38a5c471f1482281a1fe819da67936ba5", + "packages/ui-components/skills/interaction-patterns/references/inline-crud.md": "8da7f2c99bbeb72f33ca17d72ebda3fa9bd38265843f3cfab4d5d3c666ade66a", + "packages/ui-components/skills/interaction-patterns/references/wizard.md": "c60139aaa51c145462c5ae3470d77cb349a78a78a6522d573ecf9199158c0ad9", + "packages/ui-components/skills/layout/SKILL.md": "9db62d998ce1d27ae1801e2f58d112beac9c8062df5f8e0cc984f248fb3de8e0", + "packages/ui-components/skills/layout/references/box-patterns.md": "a4cab726012a4c9ec56b8b349a53ab34a8057aa0fee16d561ab377104e44e8d3", + "packages/ui-components/skills/layout/references/grid-and-stack.md": "ad645de1ab9d1c596daa998b10a5054edfdb2f22e421f5d66c714fe5d5ab592a", + "packages/ui-components/skills/layout/references/manual-layout.md": "d4d77981f9e228b25c5c795342444b3fe082328bc767d951ae4da5102bc6f4d9", + "packages/ui-components/skills/layout/references/page-footer.md": "4b70f85686d19f5d25dea1adf6454aecda8fe31d65a0e6faee118cf62e7c6ca1", + "packages/ui-components/skills/navigation/SKILL.md": "bb5182f5ec535f3863f20dbb0bdf124356486aefa610fc7f3cfe15b529fd1051", + "packages/ui-components/skills/navigation/references/legacy-tabs.md": "26b3046e02bc27ce69c6266d57bf568f6f6cc7f434599359be68723d3bec3bdb", + "packages/ui-components/skills/navigation/references/pagination.md": "2f57b4424fd3da133620478fcd7c4edd29975d504b32f03f967777eb44d57a9d", + "packages/ui-components/skills/navigation/references/second-level-bars.md": "c9da9af7be0532d557fca4b04eb8dbcf419e7e4c509475e3bcb2e2fc841411af", + "packages/ui-components/skills/overlays/SKILL.md": "c26f8297f1bfdddfbf437df518f925f08d1b2bbc1f92bb0bf7d0fe2947e5d54c", + "packages/ui-components/skills/overlays/references/modal-patterns.md": "e615258d2f4eb9c07fbc33031f9e2055cdffd8825b62357ffc992694401a9607", + "packages/ui-components/skills/overlays/references/popup-menu-composition.md": "75a012039d83dbfa6351141688b124f03f34f0a9ea70b6e8a856c59678ba600a", + "packages/ui-components/skills/overlays/references/tooltip-modes.md": "a0d9cfc44d8c2e8e545f6ab06ad428e77498acf9bd6fc50900a59ebeaa4700f2", + "packages/ui-components/skills/ux-writing/SKILL.md": "f494a4154eb9bcdae28cfb73b78ca0c2cba9998a479ba29a8cb833d3bd4e7422", + "packages/ui-components/skills/ux-writing/references/empty-values.md": "7c77d8a6d9f9ab84ee41d614efd9529c22fd47fad9f579ff1dc428ca3f9d2b2c", + "packages/ui-components/skills/ux-writing/references/title-case.md": "620872e3ece8e4b63eadda9a3feb006e6f835e5ef7863228113a3947b793d32d", + "packages/ui-components/src/components/AppBody/AppBody.component.tsx": "775427fbbea0f92f5261fa18592742fdd9ec54608796227b33b9aad59c313b05", + "packages/ui-components/src/components/AppShell/AppShell.component.tsx": "10c6a77de4c3c0c3981dcd0427461f950b668d17227ad57e0360db1a7e0e82e2", + "packages/ui-components/src/components/AppShell/AppShell.stories.tsx": "ec5fbc3423a0f93f5f1db9940110d6e17fef0c7ea8495dd140ed10d98ee7765f", + "packages/ui-components/src/components/AppShellProvider/AppShellProvider.component.tsx": "702fde8555aab675df467c87c4bfa8fc68053f1bdbc741802ff7ca7a008ba29d", + "packages/ui-components/src/components/AppShellProvider/AppShellProvider.stories.tsx": "daad3c6718177660121a835b550c2b294fe141012bf8b90a0bb096d0036ad9a0", + "packages/ui-components/src/components/Badge/Badge.component.tsx": "524f7cb642ab7cb3be0d5b20bf74eabd13b878973dd6df106ee5f079671c86dc", + "packages/ui-components/src/components/Box/Box.component.tsx": "d3f1285de707d847a1bb3a221b2b5259ba9d534e2d43513bff160c32d177326c", + "packages/ui-components/src/components/Breadcrumb/Breadcrumb.component.tsx": "bf9ca6d22962a52bb30be47a37b05f703b88b07b62f52b015bffc743629d203b", + "packages/ui-components/src/components/BreadcrumbItem/BreadcrumbItem.component.tsx": "5c9552521ce63d2d63381ccebd5d707df9d4d72c39dc778f12c0ba670b274fea", + "packages/ui-components/src/components/Button/Button.component.tsx": "38a2b7989136a075ed8ca485ef51b4d5a4d77c9b6aa7cf0677b24e6e4bace0cb", + "packages/ui-components/src/components/Button/Button.stories.tsx": "79411b76c2ca6d59071e0258d5a60cb3e80533bb9f80f69063665fa8eeba31e1", + "packages/ui-components/src/components/ButtonRow/ButtonRow.component.tsx": "f7306fca6077260cc1bae71f0b82df1af698527beb86fa72c92385e2a908f0ec", + "packages/ui-components/src/components/ButtonRow/ButtonRow.stories.tsx": "0efbdbd99d9a6800c5581ef3a0b12c9499c7976c7e094a02a9ff50f57c472adb", + "packages/ui-components/src/components/Card/Card.component.tsx": "cba8445f1487c9cc60da6fd3a23e502a02d9bfad55ed908d4d630477ed0f62f2", + "packages/ui-components/src/components/Card/Card.stories.tsx": "c4f2139d9d2eb284421569de861827f0b5e5bef3b617c090dd8c04cebfd99ed1", + "packages/ui-components/src/components/Checkbox/Checkbox.component.tsx": "eb943dad61f124ef8515b08396fb97ea19bc7d4b1ba8dc4efd24433f92e2b96a", + "packages/ui-components/src/components/CheckboxGroup/CheckboxGroup.component.tsx": "b71a206d9e9c63e8f1f4d553986f9db2e638c0e2cd61dd936b98336480314ace", + "packages/ui-components/src/components/Code/Code.component.tsx": "286e9f1b35ce7ebf35b3144023a124d68a2c58897d185261a961687648c9b516", + "packages/ui-components/src/components/Code/Code.stories.tsx": "18a46640fd3b69c271f2dc2bfba80b89417e4356e23772446837a58e08d703b6", + "packages/ui-components/src/components/CodeBlock/CodeBlock.component.tsx": "ebe90a94b60a67522329ef96f50517d00c7a688ae3a7ba25863c13de7067167d", + "packages/ui-components/src/components/CodeBlock/CodeBlock.stories.tsx": "323641768dab48d79a47caa3fa23ef0c7895a2aab2e9f9f3f4a03584f9863d98", + "packages/ui-components/src/components/CodeBlockFooter/CodeBlockFooter.component.tsx": "709894ea3f153bd17e1eb4e8307f4e18bac10bed84275b7bf236db2eff7d7ca9", + "packages/ui-components/src/components/CodeBlockFooter/CodeBlockFooter.stories.tsx": "175232e2f63d71ddbcac4b2ee679e5f984545851ee7dbb13c72db0af3217416a", + "packages/ui-components/src/components/ComboBox/ComboBox.component.tsx": "d6d38b4ad34b216c06e555073d0441a39642d588e7569a45f2b3a87338cfb834", + "packages/ui-components/src/components/ComboBoxOption/ComboBoxOption.component.tsx": "a6d15add75ee150dee64878a1163c7e30ebd63fadaf728106b1e1674f087de90", + "packages/ui-components/src/components/Container/Container.component.tsx": "730441879e45bce08a18bf27324a19b7d36801b2164078c9c911cf73fd0666c7", + "packages/ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.component.tsx": "90163b1d91adc6fc7cd9f9b711723e0a4a6604accc57050111a582322adb1025", + "packages/ui-components/src/components/ContentContainer/ContentContainer.component.tsx": "052864bf9b260c264da5deb32cd81d9a1baeb71d1d180e21f1ff924994d7eac6", + "packages/ui-components/src/components/ContentHeading/ContentHeading.component.tsx": "f2724c8bfd8ce2db6659463bb40654147c4b86f4f1002f94c7d0a788a36c4d16", + "packages/ui-components/src/components/DataGrid/DataGrid.component.tsx": "6fbf8b63ca291d4fcae42bd59efde3e945b1148c198a6d6c1a4bc8bb64199904", + "packages/ui-components/src/components/DataGrid/DataGrid.stories.tsx": "db2003baceb27c32a0b63b71db7f9890f0830b24aa5beea896eb5a95b44a3e78", + "packages/ui-components/src/components/DateTimePicker/DateTimePicker.component.tsx": "e0bfa5dd438236e97b69ba11daca3836136d3aa1d948dfe794f8ec947216d029", + "packages/ui-components/src/components/DescriptionDefinition/DescriptionDefinition.component.tsx": "dd9fda56b50787bf59bcf2693f49cc36eb430de14ef9cd955f114a38c8ca1418", + "packages/ui-components/src/components/DescriptionList/DescriptionList.component.tsx": "0425b65632b98d481153900372ae36e95e09a5a646633f384f11e0f1c5b2932c", + "packages/ui-components/src/components/DescriptionList/DescriptionList.stories.tsx": "5d146d62bd9ebabfdfd641896fb4c8e10108abfe386fb1d1fa7bdd0890460490", + "packages/ui-components/src/components/DescriptionTerm/DescriptionTerm.component.tsx": "34fe197e89faf29da187f6cc158494dc6251f2b051f8c72931977bdb7bb8f1d8", + "packages/ui-components/src/components/Divider/Divider.component.tsx": "864a232db72804613fe791a744e78d354df9a3ba8cfa4dd01b5875984a6095ef", + "packages/ui-components/src/components/Form/Form.component.tsx": "ea9e036cd12d9f3fa863229470f65990c3861e5d526cf13735c92a9e12527a71", + "packages/ui-components/src/components/FormHint/FormHint.component.tsx": "4ae03e7c014c55224f142c7073250419483221308668a95236a9a34f83baeeb5", + "packages/ui-components/src/components/FormRow/FormRow.component.tsx": "bb8b4d88832a657d59cf88148c5ac8f444be996ebe740fab784e7eff8fadf15b", + "packages/ui-components/src/components/FormSection/FormSection.component.tsx": "72765126599417212d6830152147d88540da38460ebeab99af75bb99fe385045", + "packages/ui-components/src/components/FormattedText/FormattedText.component.tsx": "e33f109666da6dae669a2b99a982d794bab1b0c34cc40be8b3fdd2da80e7955b", + "packages/ui-components/src/components/FormattedText/FormattedText.stories.tsx": "eb5a6cb7fcdb5577809a431d98540cbbb95b00baff3363efccb283ac5ee871d4", + "packages/ui-components/src/components/Grid/Grid.component.tsx": "3058fac661a3c5a917fe6b1d259f1ed15cad80cfd643a8f372d8bfdd8f6311a8", + "packages/ui-components/src/components/GridColumn/GridColumn.component.tsx": "e119123d671096b3c9ed5f491573574d64438854a09e2bdb3849b0aa91fec6cf", + "packages/ui-components/src/components/GridRow/GridRow.component.tsx": "b3f38c228144600df4e64a6d49b9bcae5eeae37fabeb38f728ae7a4e93e7c52e", + "packages/ui-components/src/components/HeaderContainer/HeaderContainer.component.tsx": "b4b2e406d6368ddf751c7eb11a84e2e54dac584acb357b9e92ffb8ddd87447f6", + "packages/ui-components/src/components/Icon/Icon.component.tsx": "dc53e11e26f8194ed1c484f6a3d6a9c36b92f9419ae82694f4c141837b097a73", + "packages/ui-components/src/components/InputGroup/InputGroup.component.tsx": "a60f62834176ae3a2b4926b06db88b7c5bf6222781a0287c051a52072c9cdba7", + "packages/ui-components/src/components/InputGroup/InputGroup.stories.tsx": "2d8d3ef7c3ee4f4c26b8e686de56d7d0a02aeb68b9683a963a92d0d54f8c2579", + "packages/ui-components/src/components/IntroBox/IntroBox.component.tsx": "0e0c6ceba7b1311c103f2ad2f4c19ebe129ef9b6a505c36a772a4c76db2cce47", + "packages/ui-components/src/components/JsonViewer/JsonViewer.component.tsx": "4301664c16c531bc195aca63eeae549dba503ae9b229e7753529cfed7946e880", + "packages/ui-components/src/components/JsonViewer/JsonViewer.stories.tsx": "ed2f8793f05916ac2610cd7ebca7af147acb07b7b79f06bdedb49679a75d4bbf", + "packages/ui-components/src/components/Label/Label.component.tsx": "1191d7d1e40778388913167dc5a0779fc0d9d928f42e58b152b8d5c870b83c10", + "packages/ui-components/src/components/LoadingIndicator/LoadingIndicator.component.tsx": "2437c378bd007718fee2eff5a1fc5e85515d401289e3b31531be939ac7bf656a", + "packages/ui-components/src/components/MainContainer/MainContainer.component.tsx": "d109c53845b29fa7bcdcfb2e995e5e4935c75d3bc06e2e58c6445f1af183525f", + "packages/ui-components/src/components/MainContainerInner/MainContainerInner.component.tsx": "a33f1440d83f724d66fff70def7e91bddb7852d8122b667695284040f32189b3", + "packages/ui-components/src/components/Message/Message.component.tsx": "c7a594561fd75df7840f5d7b819dce410c54c51a71f8ec8501dfb925a64d01f9", + "packages/ui-components/src/components/Message/Message.stories.ts": "cce9d461b84d3c684ba64fd9b80fa187be88ba796e1fbc8ad0aed66ae9b8b655", + "packages/ui-components/src/components/Modal/Modal.component.tsx": "1fa2b62d6497d3a48e7c28c3b5f47e5e4c3e09f468f727e4f47fecacd5433f8a", + "packages/ui-components/src/components/Modal/Modal.stories.tsx": "adad76347e3c27b33c132ab9bf8463acd3fa100746ab670a92e419e1837bdaad", + "packages/ui-components/src/components/ModalFooter/ModalFooter.component.tsx": "9e71267af1af65af685bea53d46f117e76ebf1b60ab0b9450647880987329226", + "packages/ui-components/src/components/NativeSelect/NativeSelect.component.tsx": "453ea8bb59c2d604136f6c18c74a99146dc33ad331335e9a1ccc17397f8d2903", + "packages/ui-components/src/components/NativeSelectOption/NativeSelectOption.component.tsx": "3a9654b83ca6b78856070974362acd45895fae68b00d871c4e16a112ec4894bb", + "packages/ui-components/src/components/NativeSelectOptionGroup/NativeSelectOptionGroup.component.tsx": "931066fe9125c1003a50bb1ea6706d43bf788a3daa92c19575893f0aa28e0dde", + "packages/ui-components/src/components/Navigation/Navigation.component.tsx": "fa439180c6daa3ac29f5a01bf336f75e037610d92a6993ff8c1ade51305fc7e0", + "packages/ui-components/src/components/NavigationItem/NavigationItem.component.tsx": "f7b50d3cb20a77ec132f26e852564065b9a3d14baddacbb8d2d8e1e5b2b195b7", + "packages/ui-components/src/components/NotificationManager/NotificationManager.component.tsx": "501bc8ef00f6ea14483ba523c3825bd800bed6a4ac33b404f1660a57fd9248c1", + "packages/ui-components/src/components/NotificationManager/NotificationManager.stories.tsx": "1558baf9a908f609a3e388cb91bdf11fa7953f98cd4483bc2c0efc02a2ecff5b", + "packages/ui-components/src/components/NotificationManager/NotificationManager.types.ts": "0abc0dd2e801587a2d940a18192d076cddb2bc08afb8e9b6abae635ebc5ae898", + "packages/ui-components/src/components/PageFooter/PageFooter.component.tsx": "b4efaa0574659fc3170984900a04f27820c8c4024b277ace9ba43ecf995efa12", + "packages/ui-components/src/components/PageFooter/PageFooter.stories.tsx": "2ea5ac1a7b4dcff0c28e728fc28926af9e490cb0d79f2b9ee969b54a40504ee6", + "packages/ui-components/src/components/PageHeader/PageHeader.component.tsx": "a98785becfc6a806570d38a6a4f18bfd0636b76dd9702a78cab6ca3e8cae6d7b", + "packages/ui-components/src/components/Pagination/Pagination.component.tsx": "f5babcb2696a2daccea4cda8e3e8f05fc3989bbcb96fc790afbcc6cd4555174a", + "packages/ui-components/src/components/Panel/Panel.component.tsx": "b0d50930dec9a6fb76368ae12822cdc503dcb68f37470bde15d40fdc8d8d4fac", + "packages/ui-components/src/components/Panel/Panel.stories.tsx": "bf8b032a6f9a6e14b632f0b9fc855faf93cbd339a101abb3af77eaccc234b866", + "packages/ui-components/src/components/PanelBody/PanelBody.component.tsx": "d1c399d5d9d2f6b0e7a42dee7b39881d2fd15b6d2e6b1052d747d417f2c914ec", + "packages/ui-components/src/components/PanelFooter/PanelFooter.component.tsx": "8a916a05328ed85f7c29d1b38fc969c8aaf3da42f6983534017e1536b9267dcb", + "packages/ui-components/src/components/Pill/Pill.component.tsx": "fe0c12916f371707d52db5516fdb6b90d13bb67ceec13fd572b11762efa13711", + "packages/ui-components/src/components/PopupMenu/PopupMenu.component.tsx": "1f393465aed7aed1e9c09e89946237dd205c1a91508be5c0ea650cf0c623c319", + "packages/ui-components/src/components/PopupMenu/PopupMenu.stories.tsx": "e16ac76f152378acd04d88ef51d971a6c3dc2a24b17b4013e947335304cca73e", + "packages/ui-components/src/components/PortalProvider/PortalProvider.component.tsx": "87f56c421f5511edf2910a7b678d823446bd84c28a6fcf0d09e43de46a5f7599", + "packages/ui-components/src/components/PortalProvider/PortalProvider.stories.tsx": "aba8638017a100cd2a5369a983d50574fcc70d3148171326560691dc3638aa5f", + "packages/ui-components/src/components/ProgressBar/ProgressBar.component.tsx": "d187e7a0e7609cce86b25798d6d5d5496818bb5fcd74970afa01feb7dbdf0aa2", + "packages/ui-components/src/components/Radio/Radio.component.tsx": "840c24c0cc9785285f08d9266935db2e82b386e76340eae953806e796a71f87a", + "packages/ui-components/src/components/RadioGroup/RadioGroup.component.tsx": "86386e0365c2fb6863dd1dfad691a8ef08e259eac046124d3f4deb6e4fb5fde8", + "packages/ui-components/src/components/RadioGroup/RadioGroup.stories.tsx": "ae92ee3c899274ff8d2dbb8ba79acd5ee96d3fb521cdfc5f99ad69cb27d67158", + "packages/ui-components/src/components/SearchInput/SearchInput.component.tsx": "828b4ce57b12d38fad735209993c386edbda5b7b1a9f3b2e8c1a66165f45d72a", + "packages/ui-components/src/components/SecretText/SecretText.component.tsx": "a4cf80d86d7af38a90fd840abb9f3a7b695137a101a811e7b6fe1c32f9475fd6", + "packages/ui-components/src/components/Select/Select.component.tsx": "7112feb2fda76a658739d5352400aa4160c1b4f49e15cb0e8e64210dd253385c", + "packages/ui-components/src/components/Select/Select.stories.tsx": "b21567094b03f62361ab1dc7301a736cf800397e652800ef2b90f21810b9fcc3", + "packages/ui-components/src/components/SelectDivider/SelectDivider.component.tsx": "426d5310c02ebd8093d115738ca0bc26d836a2152c1cd0cb27c86a3b20164be4", + "packages/ui-components/src/components/SelectOption/SelectOption.component.tsx": "d60db7a86501291f6a7451515ba397e359e977d81e727a9c4cc7bcc5598ef6b3", + "packages/ui-components/src/components/ShadowRoot/ShadowRoot.component.tsx": "df1e7432ef6c7656cbf3edb01362b207e0a6a06223742e489379fd5acf3c977c", + "packages/ui-components/src/components/ShadowRoot/ShadowRoot.stories.tsx": "2440718f3733b8449e153d79bb78e3d151610cae20ed0f61d8d793e4a2f8ad75", + "packages/ui-components/src/components/SideNavigation/SideNavigation.component.tsx": "583bf0e7874fdd9bbb223db3d657bac13fc5b6053522883f6a4748e429d882c7", + "packages/ui-components/src/components/SideNavigation/SideNavigation.stories.tsx": "ebaa6753eb96e5674a7133fb473bd0918d8a9b57727f644d0589b8a5b4a19731", + "packages/ui-components/src/components/SideNavigationGroup/SideNavigationGroup.component.tsx": "a15b357528255fb93fc95f96fb2aee72592a04898a5b20836762a97b97e818d3", + "packages/ui-components/src/components/SideNavigationItem/SideNavigationItem.component.tsx": "a895c0f2939f3013ddbd6af49a679c44f05001fff54de293fcccb1dbcddbb2fc", + "packages/ui-components/src/components/SideNavigationList/SideNavigationList.component.tsx": "618928c7ba37de8ae71a1d1b5c4e3a2f2233769e243314f7329404f83eecdb7c", + "packages/ui-components/src/components/SignInForm/SignInForm.component.tsx": "c0feaf6df3805e2fcc6c6be97835b0723ce981345f95e2ccef57f7cc4b75f82a", + "packages/ui-components/src/components/SignInForm/SignInForm.stories.tsx": "b26513a50a92368c8037aafb39b106cf296bf7475878c8bce3a9865435c38ea6", + "packages/ui-components/src/components/SortButton/SortButton.component.tsx": "d4da4cd64ebb23678c0affd9cebe6c95425ab78dcb186faeeeb70709a0e49e09", + "packages/ui-components/src/components/SortButton/SortButton.stories.tsx": "94f144e28fbdf6b8325addfaa37e95c287378f0b9e7ce0863a3eb4daf4bae16e", + "packages/ui-components/src/components/Spinner/Spinner.component.tsx": "0225200b2342b21c876bd2f3ec14c0eff6bc6aa5ccbd5e15ffb6bd2f9c082ac9", + "packages/ui-components/src/components/Stack/Stack.component.tsx": "963eabb8a291a63314b906cfce332c05211fb521cee477af2c139fbbbceba3a2", + "packages/ui-components/src/components/Status/Status.component.tsx": "b3aa376ca63d06c1c4b32c5cea881b692f9b335b58f01a9de732dd0d82400280", + "packages/ui-components/src/components/Status/Status.stories.tsx": "1b9657f07b0803c7543cf547a3b447977ec1545395bf820cb277b8901b2ee85a", + "packages/ui-components/src/components/StyleProvider/StyleProvider.component.tsx": "36b9f2c49958770facb25cd40b1b2d9ee8dcc2733905894c200a06c329fe083a", + "packages/ui-components/src/components/StyleProvider/StyleProvider.stories.tsx": "0c11234442547e0afe5e6f0651279412f6fc6016840811c79d2d407c4d63598f", + "packages/ui-components/src/components/Switch/Switch.component.tsx": "314cc633a540b7948218467506d0ad37011258d95c1f1d7fbd9ab000f39a99fc", + "packages/ui-components/src/components/TabBar/TabBar.component.tsx": "28ac3c001318f9fcf7654529385171017fa2c7fd8101f69aa45300e54ebb49c9", + "packages/ui-components/src/components/TabBarItem/TabBarItem.component.tsx": "0ae587b3897cbcfb9f48114536e01719489a7435a91789e80d0f2833e72cc36a", + "packages/ui-components/src/components/Tabs/Tabs.component.tsx": "e99281dfad18e6c0764854c358ea09190cb58e128c871fe6ce65105c10dab398", + "packages/ui-components/src/components/TextInput/TextInput.component.tsx": "cae8a354728da5d209476388f34528f0452f487bc206b6b713631d57bf3893c8", + "packages/ui-components/src/components/TextInput/TextInput.stories.tsx": "3c5cb9b54285b801097e9c503083dd40e41e9a9477b8af447ea6e2c2776f2dd3", + "packages/ui-components/src/components/Textarea/Textarea.component.tsx": "1ce90cf4d17a101aef2ce234f3122bcf177aedc8646912a413c1d7f33187a6d3", + "packages/ui-components/src/components/ThemeToggle/ThemeToggle.component.tsx": "f82828bc1dd1f1063b8219e8d0a5ccd6118722cb1a280e92cdbb48e38f08d892", + "packages/ui-components/src/components/ThemeToggle/ThemeToggle.stories.tsx": "ae655c412700aca1b585bfe97f1bdba180f2045c6e70734ce232370f5d8c9b14", + "packages/ui-components/src/components/Toast/Toast.component.tsx": "b6c34273713c8cbacc119205df2a6998d55bbf139a75d71450f90b204fda65f6", + "packages/ui-components/src/components/Toast/Toast.stories.tsx": "ab4e0bffa7049896c5b01983fe893fc2e83172be75285df12949705746d90ee4", + "packages/ui-components/src/components/ToggleButton/ToggleButton.component.tsx": "838ddd8377ed67cd7fd1a6cfa7a090d16bd1d6e6d66c844a340704c9acd582c2", + "packages/ui-components/src/components/Tooltip/Tooltip.component.tsx": "6473f419ee752041c61d0d8a5875ba10a95750c8b75a81c06c04a76a9c2b16e0", + "packages/ui-components/src/components/Tooltip/Tooltip.stories.tsx": "b7e00f30902cdc3b1dbe1ae5e68b78a0effb39a483a1a8bb4514dc1d83713fd1", + "packages/ui-components/src/components/TooltipContent/TooltipContent.component.tsx": "b2cf09e5688afe8d218709baab6e7b8b165d93ababbd09c21c7bf565793fa06f", + "packages/ui-components/src/components/TooltipTrigger/TooltipTrigger.component.tsx": "9eafa46b8ef6c6b46ac93068f61ac8ffc2ca0d99886e2a66ff9663c6e6ffc9d1", + "packages/ui-components/src/components/TopNavigation/TopNavigation.component.tsx": "f0951e0a048d02fa509a080f6b2d7fac22a41bf2097309d6c41598605fc373af", + "packages/ui-components/src/components/TopNavigationItem/TopNavigationItem.component.tsx": "3d34ae8bece0cda5a1fe61f65fa4d4f2c0567715266e91e416de6d9f233d107d" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: _artifacts/domain_map.yaml, _artifacts/skill_spec.md, _artifacts/skill_tree.yaml, packages/ui-components/skills/accessibility/SKILL.md, packages/ui-components/skills/accessibility/references/announcing-dynamic-content.md, packages/ui-components/skills/accessibility/references/semantic-foundations.md, packages/ui-components/skills/actions/SKILL.md, packages/ui-components/skills/actions/references/label-wording.md, packages/ui-components/skills/actions/references/page-level-actions.md, packages/ui-components/skills/app-foundations/SKILL.md, packages/ui-components/skills/app-foundations/references/portals.md, packages/ui-components/skills/app-foundations/references/providers-standalone.md, packages/ui-components/skills/data-display/SKILL.md, packages/ui-components/skills/data-display/references/codeblock-footer.md, packages/ui-components/skills/data-display/references/description-list-layout.md, packages/ui-components/skills/data-display/references/icon-names.md, packages/ui-components/skills/datagrid/SKILL.md, packages/ui-components/skills/datagrid/references/bulk-selection.md, packages/ui-components/skills/datagrid/references/toolbar-zones.md, packages/ui-components/skills/feedback/SKILL.md, packages/ui-components/skills/feedback/references/notifications.md, packages/ui-components/skills/feedback/references/semantic-variants.md, packages/ui-components/skills/forms/SKILL.md, packages/ui-components/skills/forms/references/secret-and-date.md, packages/ui-components/skills/forms/references/selects.md, packages/ui-components/skills/forms/references/sign-in.md, packages/ui-components/skills/forms/references/validation.md, packages/ui-components/skills/interaction-patterns/SKILL.md, packages/ui-components/skills/interaction-patterns/references/authorization-ui.md, packages/ui-components/skills/interaction-patterns/references/inline-crud.md, packages/ui-components/skills/interaction-patterns/references/wizard.md, packages/ui-components/skills/layout/SKILL.md, packages/ui-components/skills/layout/references/box-patterns.md, packages/ui-components/skills/layout/references/grid-and-stack.md, packages/ui-components/skills/layout/references/manual-layout.md, packages/ui-components/skills/layout/references/page-footer.md, packages/ui-components/skills/navigation/SKILL.md, packages/ui-components/skills/navigation/references/legacy-tabs.md, packages/ui-components/skills/navigation/references/pagination.md, packages/ui-components/skills/navigation/references/second-level-bars.md, packages/ui-components/skills/overlays/SKILL.md, packages/ui-components/skills/overlays/references/modal-patterns.md, packages/ui-components/skills/overlays/references/popup-menu-composition.md, packages/ui-components/skills/overlays/references/tooltip-modes.md, packages/ui-components/skills/ux-writing/SKILL.md, packages/ui-components/skills/ux-writing/references/empty-values.md, packages/ui-components/skills/ux-writing/references/title-case.md at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + }, + "source:.github/workflows/release.yaml": { + "fingerprint": "92e83ebdadb89c4b11c57501c21b9d52bf9e7ee9e99305f1188f34d420ad07f0", + "snapshot": { + ".github/workflows/release.yaml": "b95796f4cafb0866dc51b4881bffcdd5fc35161e4092827ed403f2f2f7a16a0e" + }, + "head": "68c0861d4d507908e4d7316d0558fbd440f4cd50", + "outcome": "updated", + "reason": "Initial authored batch: 12 skills grounded in ui-components 9.6.0 source + docs/ux; intent validate passes 12/12 (every code fence type-checked against real component APIs).", + "evidence": [ + "Changed: .github/workflows/release.yaml at 68c0861d4d507908e4d7316d0558fbd440f4cd50" + ] + } + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..1c2bb467bf --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,13 @@ + + +## Library Skill Maintenance + +Use the repository’s installed Intent. If it is unavailable, report the missing dependency instead of downloading a replacement. +Before substantial library source, documentation, examples, tests, or skill work, run `pnpm exec intent meta generate-skill` and follow the packaged maintainer procedure. +Use the current request and repository evidence. For initial skills, propose a useful batch and reuse any scope already agreed with the maintainer. +Before handing off a skill batch or library change, run `pnpm exec intent maintainer review --json`. Follow the maintainer procedure to update affected guidance, run task checks, and record completed review outcomes. Report an evidence-backed no-op or missing evidence explicitly. +Create and incrementally maintain domain_map.yaml, skill_spec.md, and skill_tree.yaml in the established artifact location for every skill batch. Preserve prior tasks, maintainer decisions, and remaining work. +Keep maintainer decisions and changes in the repository; do not require the user to repeat the procedure in later sessions. +Use intent maintainer setup to initialize missing records, maintainer add to register skills, maintainer status to identify work, and maintainer sync to update generated metadata. Finish with intent maintainer check. + + diff --git a/_artifacts/domain_map.yaml b/_artifacts/domain_map.yaml new file mode 100644 index 0000000000..c4721eba75 --- /dev/null +++ b/_artifacts/domain_map.yaml @@ -0,0 +1,288 @@ +library: + name: juno +domains: [] +skills: + [ + { + name: datagrid, + slug: datagrid, + domain: data-display, + description: "Use when building data tables with the Juno DataGrid: rendering + rows and columns, adding sorting, filtering via DataGridToolbar, bulk + row selection, pagination, and empty/loading/error states.", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Render rows and columns and control column widths", + "Make a row clickable to open a detail view", + "Add a toolbar for filters, search, and bulk actions", + "Render the required empty, loading, and error states with Status", + "Implement tri-state bulk row selection" + ], + covers: [ DataGrid, DataGridRow, DataGridCell, DataGridHeadCell, DataGridToolbar, Status, Checkbox, SearchInput ] + }, + { + name: layout, + slug: layout, + domain: layout, + description: "Teaches developers to assemble a UX-compliant Juno page: the + mandatory AppShellProvider wrapper plus the AppShell page frame + (header, content area, footer) that the UX guidelines require on every + page, when to drop to the manual AppBody/MainContainer primitives, how + embedded mode changes the frame for micro-frontends, and how to lay + out the content area with the Grid, Stack, Container, Box, IntroBox, + and Divider primitives.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Wrap the app in AppShellProvider and scaffold AppShell", + "Add side and/or top navigation to the shell", + "Customize the Page Header and Page Footer", + "Structure the content area with ContentHeading and ContentAreaToolbar", + "Arrange blocks with Stack and lay out a responsive Grid", + "Set content apart with Box, IntroBox, and Divider", + "Run embedded mode for micro-frontends", + "Drop to manual layout without AppShell when needed" + ], + covers: [ AppShell, AppShellProvider, AppBody, Container, ContentContainer, MainContainer, MainContainerInner, HeaderContainer, PageHeader, PageFooter, ContentHeading, ContentAreaToolbar, Grid, GridRow, GridColumn, Stack, Box, IntroBox, Divider ] + }, + { + name: forms, + slug: forms, + domain: forms, + description: "Teaches developers to compose the Juno form primitives into + accessible, UX-compliant forms: picking the right input for the data, + labelling and hinting fields the Juno way (the `label` prop, not a + standalone Label), driving validation state through invalid/valid plus + errortext/successtext, choosing when to validate, and the sign-in + form's deliberately different (no-validation) rules the library does + not enforce for you.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Label every field with the label prop", + "Pick the right input type for the data", + "Communicate expectations with helptext", + "Show validation state via invalid/valid + errortext/successtext", + "Group radios and checkboxes", + "Choose Switch vs. Checkbox", + "Join an input and a button with InputGroup", + "Handle submit, cancel, and submission feedback", + "Build a sign-in form with SignInForm" + ], + covers: [ Form, FormRow, FormSection, Label, TextInput, Textarea, SearchInput, SecretText, Checkbox, CheckboxGroup, Radio, RadioGroup, Switch, ToggleButton, Select, SelectOption, SelectDivider, NativeSelect, NativeSelectOption, NativeSelectOptionGroup, ComboBox, ComboBoxOption, InputGroup, DateTimePicker, SignInForm ] + }, + { + name: navigation, + slug: navigation, + domain: navigation, + description: 'Teaches developers to pick the right Juno navigation primitive for + each level of an app — SideNavigation for top-level, + TopNavigation/TabBar for second-level, Breadcrumb for the path back, + Tabs for in-page content, Pagination for paged lists — and to wire the + active-item and controlled-expansion state the components leave to the + app, following the UX rules on depth, icon placement, and the + "navigation vs. filtering" distinction. + + ', + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Set up the primary left SideNavigation", + "Group related top-level items and nest up to three levels", + "Expand the group containing the active route (controlled)", + "Add a second-level navigation (TopNavigation/TabBar) above content", + "Give the user a path back with a Breadcrumb", + "Page through a list with Pagination", + "Render in-page tabbed content (noting Tabs is deprecated)" + ], + covers: [ SideNavigation, SideNavigationGroup, SideNavigationItem, SideNavigationList, TopNavigation, TopNavigationItem, Breadcrumb, BreadcrumbItem, Tabs, Tab, TabList, TabPanel, TabBar, TabBarItem, MainTabs, Pagination ] + }, + { + name: feedback, + slug: feedback, + domain: feedback, + description: "Teaches developers to choose and compose the Juno feedback + primitives — Message, Toast + NotificationManager, Status, Spinner, + LoadingIndicator, ProgressBar, Badge, and Pill — into UX-compliant + feedback, including the Message-vs-Notification decision, the + semantic-variant rules, the required non-blocking scoping of + loading/error states, and the copy and dismissal conventions the + components leave to the consumer.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Show an inline Message for a condition in the view", + "Fire a transient notification with toast()", + "Render page/section empty, loading, and error states with Status", + "Indicate busy state at the right scale (Spinner/LoadingIndicator)", + "Show quantifiable progress with ProgressBar", + "Label entity state with Badge and filter chips with Pill" + ], + covers: [ Message, Toast, NotificationManager, Status, Spinner, LoadingIndicator, ProgressBar, Badge, Pill ] + }, + { + name: overlays, + slug: overlays, + domain: overlays, + description: "Teaches developers to build Juno overlays — Modal/ModalFooter, + Panel/PanelBody/PanelFooter, Tooltip/TooltipTrigger/TooltipContent, + and PopupMenu — so they are triggered by user action, render into the + PortalProvider, confirm destructive actions at the correct severity, + and order menu items by the UX rules the components do not enforce on + their own.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Confirm a destructive action at the right severity with Modal", + "Replace the footer with a custom ModalFooter", + "Slide in a Panel for a form or detail drawer", + "Add a Tooltip", + "Build an overflow menu with PopupMenu" + ], + covers: [ Modal, ModalFooter, Panel, PanelBody, PanelFooter, Tooltip, TooltipTrigger, TooltipContent, PopupMenu, PortalProvider ] + }, + { + name: data-display, + slug: data-display, + domain: data-display, + description: "Teaches developers to pick and compose the Juno content-display + primitives (Card, DescriptionList with + DescriptionTerm/DescriptionDefinition, Code, CodeBlock with + CodeBlockFooter, JsonViewer, FormattedText, Icon) with their real + props, including the detail-view term/definition pattern, the + inline-vs-block code distinction, and the UX writing rules for titles, + empty values, and accessible interactive icons that the components do + not enforce on their own.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Group content in a Card", + "Show an item's properties in a DescriptionList", + "Choose inline Code vs. a CodeBlock", + "Render structured JSON with JsonViewer", + "Add a custom action to a CodeBlock footer", + "Style rich prose with FormattedText", + "Render an Icon as glyph, link, or button" + ], + covers: [ Card, DescriptionList, DescriptionTerm, DescriptionDefinition, Code, CodeBlock, CodeBlockFooter, JsonViewer, FormattedText, Icon ] + }, + { + name: actions, + slug: actions, + domain: actions, + description: "Teaches developers to pick the correct Juno Button variant and + placement for an action, group actions consistently with ButtonRow, + give async actions in-progress feedback, and apply the SortButton and + ThemeToggle correctly — enforcing the UX rules (one primary action per + page, destructive = primary-danger, title-case infinitive labels, + disable vs hide) that the components do not enforce on their own.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Choose a Button variant and size", + "Add an icon or make an icon-only button", + "Show progress during an async action", + "Render a link that looks like a button", + "Group actions with ButtonRow", + "Wire a SortButton for a sortable column", + "Place a ThemeToggle" + ], + covers: [ Button, ButtonRow, SortButton, ThemeToggle ] + }, + { + name: app-foundations, + slug: app-foundations, + domain: foundations, + description: "Teaches developers to bootstrap a Juno application correctly: + wrapping the app in a single AppShellProvider (which composes + StyleProvider + PortalProvider, optionally inside a ShadowRoot), + loading the component CSS where the chosen style/shadow mode requires + it, selecting a theme, and adjusting the setup for standalone vs. + Shadow-DOM-encapsulated vs. host-embedded deployment — the invisible + plumbing that, if omitted, makes components silently fail to style or + portal.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Wrap the app in AppShellProvider (StyleProvider + PortalProvider)", + "Load the component CSS for the chosen style/shadow mode", + "Choose a theme", + "Decide where styles live: Shadow DOM vs. document", + "Run embedded inside a host shell", + "Render overlays through the portal" + ], + covers: [ AppShellProvider, StyleProvider, PortalProvider, ShadowRoot ] + }, + { + name: accessibility, + slug: accessibility, + domain: accessibility, + description: "Teaches developers to build accessible Juno UIs by preferring + semantic Juno primitives (Button, TextInput, CheckboxGroup, + RadioGroup, Modal, Status) that already carry the correct roles, + labels, and focus behaviour, and by filling the gaps the components do + not enforce — accessible names for icon-only controls, grouped-input + labelling, non-color status signals, and aria-live announcement of + application-driven dynamic content.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Use the semantic component instead of a styled div", + "Give every icon-only control an accessible name", + "Label inputs with the component's own label prop", + "Group related inputs under one labelled group", + "Keep keyboard operation and the focus ring intact", + "Let Modal manage focus and give it an accessible name", + "Signal status with more than color and announce it" + ], + covers: [ Button, Icon, TextInput, Checkbox, CheckboxGroup, RadioGroup, Modal, Status, Message, Label ] + }, + { + name: ux-writing, + slug: ux-writing, + domain: content-design, + description: "Teaches developers to write and label Juno UI text that follows + the project's UX Writing and Content Design guidelines — active + impersonal voice, title case, concise verb-based button labels, + professional non-alarmist error copy, and the project-specific + empty-value conventions (render \"- -\", fall back to the ID for + name-like fields) — grounded in the real Button, Status, Message, + Modal, and DescriptionList component props so the examples + type-check.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Use active, impersonal voice", + "Apply title case to titles, headings, and labels", + "Write button labels as short verbs", + "Keep terminology consistent", + "Write professional, non-alarmist error copy", + "Render missing values as '- -' with the ID fall-back" + ], + covers: [ Button, Status, Message, Modal, ContentHeading, DescriptionList, DescriptionTerm, DescriptionDefinition, DataGridHeadCell ] + }, + { + name: interaction-patterns, + slug: interaction-patterns, + domain: interaction, + description: "Teaches developers to choose and implement Juno's interaction + patterns correctly — confirmation of destructive actions, the + disable/hide/error decision for unauthorized controls, inline + add/edit/delete, multi-step wizards, and the standard page-and-user + flow — grounded in the UX guidelines so apps stay predictable and + consistent instead of each screen inventing its own affordances.\n", + packages: [ "@cloudoperators/juno-ui-components" ], + tasks: + [ + "Confirm consequential and destructive actions — and only those", + "Give every action feedback", + "Decide disabled vs hidden vs always-functional for unauthorized controls", + "Add, edit, and delete items inline in a list", + "Break long, sequential tasks into a wizard", + "Lay out the overall sign-in → home → list → detail page flow" + ], + covers: [ Button, ButtonRow, Modal, ModalFooter, Tooltip, TooltipTrigger, TooltipContent, TextInput, Message, Icon ] + } + ] +gaps: [] diff --git a/_artifacts/skill_spec.md b/_artifacts/skill_spec.md new file mode 100644 index 0000000000..5fb0459977 --- /dev/null +++ b/_artifacts/skill_spec.md @@ -0,0 +1,91 @@ +# juno skill spec + +The human-readable coverage and decision record for Juno's Intent skills. One entry per authored +skill: what it covers, the consequential decisions baked into its guidance, the source evidence it +was verified against, and any remaining work. Keep this history as the library changes. + +## Assessed scope + +Initial batch: the UI building blocks of `@cloudoperators/juno-ui-components` (105 components), +grouped into domain skills, plus four UX-guideline skills (accessibility, ux-writing, +interaction-patterns, app-foundations) that are not tied to a single component cluster. Skills are +grounded in the component source (`packages/ui-components/src/components/**`), their Storybook +stories, and the UX documentation (`docs/ux/**`). Target library version: **9.6.0**. + +Structural check: `intent validate packages/ui-components/skills` → **12/12 pass** (every code fence +is type-checked against the real component types). No cross-package skills; each package owns its +own. + +## Coverage and batch history + +### Batch 1 — initial component + UX skill set (ui-components 9.6.0) + +- **datagrid** (`data-display`) — composing DataGrid grid primitives into a UX-compliant table. + Decisions: empty/loading/error states are **required** and must use `Status` in a column-spanning + cell; the tri-state select-all bulk-selection model is owned by the consumer (the library does not + enforce it); cell count must equal `columns` unless `colSpan` is used. + +- **layout** (`layout`) — the mandatory `AppShellProvider` wrapper + `AppShell` page frame (header, + content, footer). Decisions: `AppShell` is the default; dropping to manual + `AppBody`/`MainContainer` primitives is the documented escape hatch; embedded mode changes the + frame for micro-frontends. + +- **forms** (`forms`) — composing form inputs. Decisions: label via each input's `label` prop, **not** + a standalone `Label` (which is not a public barrel export); validation runs through + `invalid`/`valid` + `errortext`/`successtext`; `Switch` fires a button change event with no + `.checked`, so state is derived from the `on` prop; `SignInForm` deliberately skips field + validation. + +- **navigation** (`navigation`) — picking the right primitive per level (SideNavigation top-level, + TopNavigation/TabBar second-level, Breadcrumb, Pagination). Decisions: nesting capped at three + levels; `Tabs`/`TabList`/`TabPanel`/`MainTabs` are **deprecated** and quarantined into a reference + marked "maintaining existing code only" — `TabBar` is the current choice; filter tabs must not be + misused as navigation. + +- **feedback** (`feedback`) — Message vs. Toast decision, `Status` for page/section states, + Spinner/LoadingIndicator/ProgressBar, Badge/Pill. Decisions: loading/error states must be + non-blocking and scoped, not full-page; semantic-variant rules; copy and dismissal left to the + consumer. + +- **overlays** (`overlays`) — Modal/ModalFooter, Panel, Tooltip, PopupMenu + PortalProvider. + Decisions: overlays are user-triggered and render into the portal; destructive actions confirm at + the correct severity; `usePopupMenuContext` is internal (not a barrel export) — closing from + custom content uses a `PopupMenuItem`. + +- **data-display** (`data-display`) — Card, DescriptionList, Code/CodeBlock, JsonViewer, + FormattedText, Icon. Decisions: term/definition pattern for detail views; inline-vs-block code + distinction; interactive icons need accessible names. + +- **actions** (`actions`) — Button variants/placement, ButtonRow, SortButton, ThemeToggle. + Decisions: one primary action per page; destructive = `primary-danger`; title-case infinitive + labels; disable-vs-hide rules the components do not enforce. + +- **app-foundations** (`foundations`) — provider bootstrapping. Decisions: a single + `AppShellProvider` composes `StyleProvider` + `PortalProvider` (optionally inside `ShadowRoot`); + CSS must be loaded for the chosen style/shadow mode; omitting the plumbing makes components + silently fail to style or portal. + +- **accessibility** (`accessibility`) — accessible UIs via semantic Juno primitives plus the gaps + they do not cover: accessible names for icon-only controls, grouped-input labelling, non-color + status signals, aria-live announcement of app-driven dynamic content. + +- **ux-writing** (`content-design`) — UX Writing / Content Design rules: active impersonal voice, + title case, verb-based button labels, non-alarmist error copy, and the empty-value conventions + (`- -`, ID fall-back for name-like fields). Grounded in real Button/Status/Message/Modal props so + examples type-check. + +- **interaction-patterns** (`interaction`) — confirmation of destructive actions, the + disable/hide/error decision for unauthorized controls, inline add/edit/delete, multi-step wizards, + and the standard page/user flow. Note: the wizard step-indicator and Modal wizard variant are + still in design/development, so the skill composes the behavior from `Modal`/`Button` in the + meantime. + +Checks: structural validation passed for all 12. Representative task checks and a fresh-session +consumer check are not yet run — treat them as unverified for this batch. + +## Remaining work + +- Author representative executable task checks per skill (task-quality), and run a fresh-session + consumer check for the highest-traffic skills (datagrid, forms, feedback). +- Confirm the per-skill `covers` lists are intentional (some incidentally list wrapper components + such as `AppShellProvider`/`DataGrid` that appear only in setup examples). diff --git a/_artifacts/skill_tree.yaml b/_artifacts/skill_tree.yaml new file mode 100644 index 0000000000..141a42c223 --- /dev/null +++ b/_artifacts/skill_tree.yaml @@ -0,0 +1,545 @@ +library: + name: juno +generated_from: + domain_map: _artifacts/domain_map.yaml + skill_spec: _artifacts/skill_spec.md +skills: + [ + { + name: datagrid, + slug: datagrid, + domain: data-display, + package: packages/ui-components, + path: skills/datagrid/SKILL.md, + description: "Use when building data tables with the Juno DataGrid in + @cloudoperators/juno-ui-components: rendering rows and columns, + controlling column widths, adding a toolbar for filtering and search, + row click and bulk selection, and rendering empty, loading, and error + states inside the grid. For form inputs used inside filters, see the + forms skill; for the Status component's other uses, see the feedback + skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/DataGrid/DataGrid.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/DataGrid/DataGrid.stories.tsx, + cloudoperators/juno:docs/ux/datagrid.md + ], + requires: [], + references: [ references/bulk-selection.md, references/toolbar-zones.md ], + purpose: "Teaches developers to compose the Juno DataGrid primitives (DataGrid, + DataGridRow, DataGridCell, DataGridHeadCell, DataGridToolbar) into an + accessible, UX-compliant data table, including the required + Status-based empty/loading/error pattern and the tri-state + bulk-selection model that the component library does not enforce on + its own.\n" + }, + { + name: layout, + slug: layout, + domain: layout, + package: packages/ui-components, + path: skills/layout/SKILL.md, + description: "Use when building the overall page structure of a Juno app with + @cloudoperators/juno-ui-components: wrapping the app in + AppShellProvider, scaffolding the shell with AppShell (page header, + side/top navigation, content area, page footer), running in embedded + mode for micro-frontends, and arranging content inside the content + area with ContentHeading, ContentAreaToolbar, Grid/GridRow/GridColumn, + Stack, Container, Box, IntroBox, and Divider. For the data table that + usually fills a list page, see the datagrid skill; for the navigation + items themselves, see the navigation skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/AppShellProvider/AppShellProvider.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/AppShell/AppShell.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/AppShell/AppShell.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/AppBody/AppBody.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Container/Container.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/ContentContainer/ContentContainer.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/MainContainer/MainContainer.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/MainContainerInner/MainContainerInner.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/HeaderContainer/HeaderContainer.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/PageHeader/PageHeader.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/PageFooter/PageFooter.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/PageFooter/PageFooter.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/ContentHeading/ContentHeading.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Grid/Grid.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/GridRow/GridRow.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/GridColumn/GridColumn.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Stack/Stack.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Box/Box.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/IntroBox/IntroBox.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Divider/Divider.component.tsx, + cloudoperators/juno:docs/ux/juno-layout.md, + cloudoperators/juno:docs/ux/the-appshell.md, + cloudoperators/juno:docs/ux/layout-fundamentals.md, + cloudoperators/juno:docs/ux/page-header.md, + cloudoperators/juno:docs/ux/page-content-area.md, + cloudoperators/juno:docs/ux/page-footer.md, + cloudoperators/juno:docs/ux/page-layout-elements.md, + cloudoperators/juno:docs/ux/embedded-application-layout.md, + cloudoperators/juno:docs/ux/box.md + ], + requires: [], + references: [ references/box-patterns.md, references/grid-and-stack.md, references/manual-layout.md, references/page-footer.md ], + purpose: "Teaches developers to assemble a UX-compliant Juno page: the mandatory + AppShellProvider wrapper plus the AppShell page frame (header, content + area, footer) that the UX guidelines require on every page, when to + drop to the manual AppBody/MainContainer primitives, how embedded mode + changes the frame for micro-frontends, and how to lay out the content + area with the Grid, Stack, Container, Box, IntroBox, and Divider + primitives.\n" + }, + { + name: forms, + slug: forms, + domain: forms, + package: packages/ui-components, + path: skills/forms/SKILL.md, + description: "Use when building forms with Juno inputs in + @cloudoperators/juno-ui-components: text fields, textareas, selects, + native selects, combo boxes, checkboxes, radios, switches, toggle + buttons, secret/date fields, grouping with Form/FormRow/FormSection, + labels and hints, validation state and timing + (helptext/errortext/successtext, invalid/valid), and the dedicated + SignInForm. For a data table and its filter toolbar, see the datagrid + skill; for Status-based page states, see the feedback skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/Form/Form.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/FormRow/FormRow.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/FormSection/FormSection.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/FormHint/FormHint.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Label/Label.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/TextInput/TextInput.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/TextInput/TextInput.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/Textarea/Textarea.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/SearchInput/SearchInput.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/SecretText/SecretText.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Checkbox/Checkbox.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/CheckboxGroup/CheckboxGroup.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Radio/Radio.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/RadioGroup/RadioGroup.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/RadioGroup/RadioGroup.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/Switch/Switch.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/ToggleButton/ToggleButton.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Select/Select.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Select/Select.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/SelectOption/SelectOption.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/SelectDivider/SelectDivider.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/NativeSelect/NativeSelect.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/NativeSelectOption/NativeSelectOption.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/NativeSelectOptionGroup/NativeSelectOptionGroup.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/ComboBox/ComboBox.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/ComboBoxOption/ComboBoxOption.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/InputGroup/InputGroup.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/InputGroup/InputGroup.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/DateTimePicker/DateTimePicker.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/SignInForm/SignInForm.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/SignInForm/SignInForm.stories.tsx, + cloudoperators/juno:docs/ux/forms.md, + cloudoperators/juno:docs/ux/sign-in.md, + cloudoperators/juno:docs/ux/authentication-and-access.md, + cloudoperators/juno:docs/ux/semantic-variants.md + ], + requires: [], + references: [ references/secret-and-date.md, references/selects.md, references/sign-in.md, references/validation.md ], + purpose: "Teaches developers to compose the Juno form primitives into + accessible, UX-compliant forms: picking the right input for the data, + labelling and hinting fields the Juno way (the `label` prop, not a + standalone Label), driving validation state through invalid/valid plus + errortext/successtext, choosing when to validate, and the sign-in + form's deliberately different (no-validation) rules the library does + not enforce for you.\n" + }, + { + name: navigation, + slug: navigation, + domain: navigation, + package: packages/ui-components, + path: skills/navigation/SKILL.md, + description: "Use when building navigation in a Juno app with + @cloudoperators/juno-ui-components: the primary left SideNavigation + (flat items, groups, nested children up to three levels, active + + controlled expansion), a horizontal TopNavigation or TabBar as a + second-level navigation above content, a Breadcrumb trail back to list + views, in-page tabbed content (deprecated Tabs/TabList/TabPanel and + MainTabs), and Pagination for paged lists. For the DataGrid that fills + a list view, see the datagrid skill; for the AppShell that frames the + whole layout, see the fundamentals skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/SideNavigation/SideNavigation.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/SideNavigation/SideNavigation.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/SideNavigationGroup/SideNavigationGroup.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/SideNavigationItem/SideNavigationItem.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/SideNavigationList/SideNavigationList.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/TopNavigation/TopNavigation.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/TopNavigationItem/TopNavigationItem.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Navigation/Navigation.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/NavigationItem/NavigationItem.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Breadcrumb/Breadcrumb.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/BreadcrumbItem/BreadcrumbItem.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/TabBar/TabBar.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/TabBarItem/TabBarItem.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Tabs/Tabs.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Pagination/Pagination.component.tsx, + cloudoperators/juno:docs/ux/navigation-fundamentals.md, + cloudoperators/juno:docs/ux/navigation-side-navigation.md, + cloudoperators/juno:docs/ux/navigation.md, + cloudoperators/juno:docs/ux/page-and-user-flow.md + ], + requires: [], + references: [ references/legacy-tabs.md, references/pagination.md, references/second-level-bars.md ], + purpose: 'Teaches developers to pick the right Juno navigation primitive for + each level of an app — SideNavigation for top-level, + TopNavigation/TabBar for second-level, Breadcrumb for the path back, + Tabs for in-page content, Pagination for paged lists — and to wire the + active-item and controlled-expansion state the components leave to the + app, following the UX rules on depth, icon placement, and the + "navigation vs. filtering" distinction. + + ' + }, + { + name: feedback, + slug: feedback, + domain: feedback, + package: packages/ui-components, + path: skills/feedback/SKILL.md, + description: "Use when surfacing feedback in a Juno app with + @cloudoperators/juno-ui-components: a static inline Message vs a + transient Toast notification fired through NotificationManager and the + toast() API, the Status component for page/section empty, loading, + error and no-matches states, Spinner / LoadingIndicator / ProgressBar + for progress, and Badge / Pill for inline status labels and filter + chips. Covers which component to reach for, the semantic variant to + pick, and the message copy and dismissal rules the library does not + enforce. For Status inside a DataGrid, see the datagrid skill; for + form field validation, see the forms skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/Message/Message.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Message/Message.stories.ts, + cloudoperators/juno:packages/ui-components/src/components/Toast/Toast.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Toast/Toast.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/NotificationManager/NotificationManager.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/NotificationManager/NotificationManager.types.ts, + cloudoperators/juno:packages/ui-components/src/components/NotificationManager/NotificationManager.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/Status/Status.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Status/Status.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/Spinner/Spinner.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/LoadingIndicator/LoadingIndicator.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/ProgressBar/ProgressBar.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Badge/Badge.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Pill/Pill.component.tsx, + cloudoperators/juno:docs/ux/messages-and-notifications.md, + cloudoperators/juno:docs/ux/error-handling-loading-empty-states.md, + cloudoperators/juno:docs/ux/transient-states-and-progress.md, + cloudoperators/juno:docs/ux/semantic-variants.md + ], + requires: [], + references: [ references/notifications.md, references/semantic-variants.md ], + purpose: "Teaches developers to choose and compose the Juno feedback primitives + — Message, Toast + NotificationManager, Status, Spinner, + LoadingIndicator, ProgressBar, Badge, and Pill — into UX-compliant + feedback, including the Message-vs-Notification decision, the + semantic-variant rules, the required non-blocking scoping of + loading/error states, and the copy and dismissal conventions the + components leave to the consumer.\n" + }, + { + name: overlays, + slug: overlays, + domain: overlays, + package: packages/ui-components, + path: skills/overlays/SKILL.md, + description: "Use when building overlay UI in a Juno app with + @cloudoperators/juno-ui-components: Modal dialogs with built-in or + custom ModalFooter actions and destructive-action confirmation + (checkbox / typed phrase), slide-in Panels with PanelBody and + PanelFooter, Tooltips (TooltipTrigger + TooltipContent, hover vs. + click, semantic variants), and PopupMenu overflow menus with sections + and dividers. Also covers the PortalProvider these overlays render + into. For the Button variants used in footers see the forms/actions + material; for Status-based empty states inside tables see the datagrid + skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/Modal/Modal.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Modal/Modal.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/ModalFooter/ModalFooter.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Panel/Panel.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Panel/Panel.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/PanelBody/PanelBody.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/PanelFooter/PanelFooter.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Tooltip/Tooltip.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Tooltip/Tooltip.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/TooltipTrigger/TooltipTrigger.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/TooltipContent/TooltipContent.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/PopupMenu/PopupMenu.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/PopupMenu/PopupMenu.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/PortalProvider/PortalProvider.component.tsx, + cloudoperators/juno:docs/ux/modals.md, + cloudoperators/juno:docs/ux/popup-and-overflow-menus.md, + cloudoperators/juno:docs/ux/interaction-guidelines.md + ], + requires: [], + references: [ references/modal-patterns.md, references/popup-menu-composition.md, references/tooltip-modes.md ], + purpose: "Teaches developers to build Juno overlays — Modal/ModalFooter, + Panel/PanelBody/PanelFooter, Tooltip/TooltipTrigger/TooltipContent, + and PopupMenu — so they are triggered by user action, render into the + PortalProvider, confirm destructive actions at the correct severity, + and order menu items by the UX rules the components do not enforce on + their own.\n" + }, + { + name: data-display, + slug: data-display, + domain: data-display, + package: packages/ui-components, + path: skills/data-display/SKILL.md, + description: "Use when displaying non-tabular content in a Juno app built with + @cloudoperators/juno-ui-components: grouping information in a Card, + rendering an item's properties as a term/definition DescriptionList, + showing inline code with Code or a copyable multi-line block with + CodeBlock and CodeBlockFooter, rendering structured JSON with the + collapsible JsonViewer, styling rich HTML prose with FormattedText, + and placing an Icon as a glyph, link, or button. For tabular lists of + items use the datagrid skill; for status badges and the empty/error + pattern see the feedback skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/Card/Card.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Card/Card.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/DescriptionList/DescriptionList.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/DescriptionList/DescriptionList.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/DescriptionTerm/DescriptionTerm.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/DescriptionDefinition/DescriptionDefinition.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Code/Code.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Code/Code.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/CodeBlock/CodeBlock.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/CodeBlock/CodeBlock.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/CodeBlockFooter/CodeBlockFooter.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/CodeBlockFooter/CodeBlockFooter.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/JsonViewer/JsonViewer.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/JsonViewer/JsonViewer.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/FormattedText/FormattedText.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/FormattedText/FormattedText.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/Icon/Icon.component.tsx, + cloudoperators/juno:docs/ux/datagrid.md, + cloudoperators/juno:docs/ux/ux-writing-content-design.md + ], + requires: [], + references: [ references/codeblock-footer.md, references/description-list-layout.md, references/icon-names.md ], + purpose: "Teaches developers to pick and compose the Juno content-display + primitives (Card, DescriptionList with + DescriptionTerm/DescriptionDefinition, Code, CodeBlock with + CodeBlockFooter, JsonViewer, FormattedText, Icon) with their real + props, including the detail-view term/definition pattern, the + inline-vs-block code distinction, and the UX writing rules for titles, + empty values, and accessible interactive icons that the components do + not enforce on their own.\n" + }, + { + name: actions, + slug: actions, + domain: actions, + package: packages/ui-components, + path: skills/actions/SKILL.md, + description: "Use when adding actions to a Juno UI built with + @cloudoperators/juno-ui-components: choosing a Button variant + (default, primary, primary-danger, subdued) and size, showing an + in-progress button during async work, grouping buttons with ButtonRow + in dialogs and forms, wiring a SortButton for a sortable column, and + placing a ThemeToggle. Covers which action is primary vs secondary vs + destructive, button label wording (title case, infinitive verbs), and + when to disable vs hide an action. For page-level toolbar slot layout + and the overflow menu, read the page-level-actions reference; for + actions scoped to a DataGrid, see the datagrid skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/Button/Button.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Button/Button.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/ButtonRow/ButtonRow.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/ButtonRow/ButtonRow.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/SortButton/SortButton.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/SortButton/SortButton.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/ThemeToggle/ThemeToggle.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/ThemeToggle/ThemeToggle.stories.tsx, + cloudoperators/juno:docs/ux/page-level-actions.md, + cloudoperators/juno:docs/ux/interaction-guidelines.md, + cloudoperators/juno:docs/ux/ux-writing-content-design.md + ], + requires: [], + references: [ references/label-wording.md, references/page-level-actions.md ], + purpose: "Teaches developers to pick the correct Juno Button variant and + placement for an action, group actions consistently with ButtonRow, + give async actions in-progress feedback, and apply the SortButton and + ThemeToggle correctly — enforcing the UX rules (one primary action per + page, destructive = primary-danger, title-case infinitive labels, + disable vs hide) that the components do not enforce on their own.\n" + }, + { + name: app-foundations, + slug: app-foundations, + domain: foundations, + package: packages/ui-components, + path: skills/app-foundations/SKILL.md, + description: "Use when bootstrapping a Juno app or plugin with + @cloudoperators/juno-ui-components: wiring the required provider so + components render at all, loading the library CSS and your own styles, + choosing or switching the dark/light theme, encapsulating styles in a + Shadow DOM, and running the app embedded inside a host shell. Covers + AppShellProvider (the recommended entry point) plus the primitives it + composes — StyleProvider, PortalProvider, and ShadowRoot — and when to + drop down to them. For the page layout container (header/nav/footer + slots) see the AppShell layout skill; this skill is about the + providers that must wrap it.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/AppShellProvider/AppShellProvider.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/AppShellProvider/AppShellProvider.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/StyleProvider/StyleProvider.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/StyleProvider/StyleProvider.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/PortalProvider/PortalProvider.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/PortalProvider/PortalProvider.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/ShadowRoot/ShadowRoot.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/ShadowRoot/ShadowRoot.stories.tsx, + cloudoperators/juno:docs/ux/the-appshell.md, + cloudoperators/juno:docs/ux/getting-started-with-juno-ui-components.md, + cloudoperators/juno:docs/ux/core-concepts.md, + cloudoperators/juno:docs/ux/foundations.md, + cloudoperators/juno:docs/ux/embedded-application-layout.md + ], + requires: [], + references: [ references/portals.md, references/providers-standalone.md ], + purpose: "Teaches developers to bootstrap a Juno application correctly: wrapping + the app in a single AppShellProvider (which composes StyleProvider + + PortalProvider, optionally inside a ShadowRoot), loading the component + CSS where the chosen style/shadow mode requires it, selecting a theme, + and adjusting the setup for standalone vs. Shadow-DOM-encapsulated vs. + host-embedded deployment — the invisible plumbing that, if omitted, + makes components silently fail to style or portal.\n" + }, + { + name: accessibility, + slug: accessibility, + domain: accessibility, + package: packages/ui-components, + path: skills/accessibility/SKILL.md, + description: "Use when ensuring a Juno UI built with + @cloudoperators/juno-ui-components is accessible: choosing semantic + HTML over div/span for actions and navigation, giving every input and + icon-only button an accessible name, grouping related inputs, wiring + help and error text, keeping keyboard navigation and visible focus + intact, trapping and returning focus in modals, avoiding color-only + signals, and announcing dynamic content (loading, success, errors) to + screen readers. For the DataGrid empty/loading/error pattern see the + datagrid skill; for form validation wiring see the forms skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/Button/Button.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Button/Button.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/Icon/Icon.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/TextInput/TextInput.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/CheckboxGroup/CheckboxGroup.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/RadioGroup/RadioGroup.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Modal/Modal.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Status/Status.component.tsx, + cloudoperators/juno:docs/ux/accessibility.md, + cloudoperators/juno:docs/ux/interaction-guidelines.md + ], + requires: [], + references: [ references/announcing-dynamic-content.md, references/semantic-foundations.md ], + purpose: "Teaches developers to build accessible Juno UIs by preferring semantic + Juno primitives (Button, TextInput, CheckboxGroup, RadioGroup, Modal, + Status) that already carry the correct roles, labels, and focus + behaviour, and by filling the gaps the components do not enforce — + accessible names for icon-only controls, grouped-input labelling, + non-color status signals, and aria-live announcement of + application-driven dynamic content.\n" + }, + { + name: ux-writing, + slug: ux-writing, + domain: content-design, + package: packages/ui-components, + path: skills/ux-writing/SKILL.md, + description: 'Use when writing any user-facing text in a Juno UI built with + @cloudoperators/juno-ui-components: button and confirm-action labels, + Modal titles and copy, Status/Message titles and bodies, headings and + DataGrid column headers, error and empty-state wording, and rendering + missing or unknown field values. Covers active-voice phrasing, + title-case rules, the "no please/thanks", "no exclamation marks", + "Sign in not Log in" rules, and the "- -" / fall-back-to-ID + conventions, so copy stays consistent across the app. For the DataGrid + empty/loading/error structure itself see the datagrid skill; this + skill governs the words that go in it. + + ', + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/Button/Button.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Button/Button.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/Status/Status.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Message/Message.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Modal/Modal.component.tsx, + cloudoperators/juno:docs/ux/ux-writing-content-design.md, + cloudoperators/juno:docs/ux/application-design-guidelines.md + ], + requires: [], + references: [ references/empty-values.md, references/title-case.md ], + purpose: "Teaches developers to write and label Juno UI text that follows the + project's UX Writing and Content Design guidelines — active impersonal + voice, title case, concise verb-based button labels, professional + non-alarmist error copy, and the project-specific empty-value + conventions (render \"- -\", fall back to the ID for name-like fields) + — grounded in the real Button, Status, Message, Modal, and + DescriptionList component props so the examples type-check.\n" + }, + { + name: interaction-patterns, + slug: interaction-patterns, + domain: interaction, + package: packages/ui-components, + path: skills/interaction-patterns/SKILL.md, + description: "Use when designing interaction flows in a Juno app built with + @cloudoperators/juno-ui-components: confirming consequential or + destructive actions with a Modal, deciding whether to disable, hide, + or always-render a control the user may not be authorized for, + adding/editing/deleting items inline in a list, breaking a long task + into a multi-step wizard, and laying out the overall sign-in → home → + scope → list → detail page flow. This is a UX-guidelines skill: it + tells you which pattern to reach for and wires real Juno components + (Button, Modal, Tooltip, Icon, TextInput, Message) into each. For the + Modal API itself see the overlays skill; for form validation see the + forms skill; for the DataGrid list view see the datagrid skill.\n", + sources: + [ + cloudoperators/juno:packages/ui-components/src/components/Button/Button.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Button/Button.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/Modal/Modal.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Modal/Modal.stories.tsx, + cloudoperators/juno:packages/ui-components/src/components/ModalFooter/ModalFooter.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/Tooltip/Tooltip.component.tsx, + cloudoperators/juno:packages/ui-components/src/components/TextInput/TextInput.component.tsx, + cloudoperators/juno:docs/ux/interaction-guidelines.md, + cloudoperators/juno:docs/ux/inline-adding-editing-and-deleting.md, + cloudoperators/juno:docs/ux/wizard.md, + cloudoperators/juno:docs/ux/ui-for-unauthorized-users.md, + cloudoperators/juno:docs/ux/page-and-user-flow.md + ], + requires: [], + references: [ references/authorization-ui.md, references/inline-crud.md, references/wizard.md ], + purpose: "Teaches developers to choose and implement Juno's interaction patterns + correctly — confirmation of destructive actions, the + disable/hide/error decision for unauthorized controls, inline + add/edit/delete, multi-step wizards, and the standard page-and-user + flow — grounded in the UX guidelines so apps stay predictable and + consistent instead of each screen inventing its own affordances.\n" + } + ] +distribution: + mode: none diff --git a/apps/doop/src/components/violations/ViolationsList.tsx b/apps/doop/src/components/violations/ViolationsList.tsx index 32e9750435..1ad0c190ef 100644 --- a/apps/doop/src/components/violations/ViolationsList.tsx +++ b/apps/doop/src/components/violations/ViolationsList.tsx @@ -21,7 +21,7 @@ const ViolationsList = () => {
No violations found
) : ( <> - + diff --git a/apps/greenhouse/src/components/admin/ClusterDetail/Overview/Details.tsx b/apps/greenhouse/src/components/admin/ClusterDetail/Overview/Details.tsx index 0afcf6238d..0cbb70f085 100644 --- a/apps/greenhouse/src/components/admin/ClusterDetail/Overview/Details.tsx +++ b/apps/greenhouse/src/components/admin/ClusterDetail/Overview/Details.tsx @@ -45,7 +45,7 @@ const NodeStatus: React.FC<{ nodes: NodesStatus }> = ({ nodes }) => { export const Details: React.FC = ({ clusters }) => ( Details - + Name {clusters.metadata?.name ?? NO_VALUE_DEFAULT} diff --git a/apps/greenhouse/src/components/admin/ClusterDetail/Overview/PluginInstances.tsx b/apps/greenhouse/src/components/admin/ClusterDetail/Overview/PluginInstances.tsx index 8a34aa33c9..49cdf4500a 100644 --- a/apps/greenhouse/src/components/admin/ClusterDetail/Overview/PluginInstances.tsx +++ b/apps/greenhouse/src/components/admin/ClusterDetail/Overview/PluginInstances.tsx @@ -114,7 +114,7 @@ export const PluginInstances = () => { {`(${ready} ready, ${notReady} not ready)`} - + diff --git a/apps/greenhouse/src/components/admin/Clusters/ClustersGrid/index.tsx b/apps/greenhouse/src/components/admin/Clusters/ClustersGrid/index.tsx index 63d0a8dc0f..59de31e913 100644 --- a/apps/greenhouse/src/components/admin/Clusters/ClustersGrid/index.tsx +++ b/apps/greenhouse/src/components/admin/Clusters/ClustersGrid/index.tsx @@ -17,7 +17,7 @@ const COLUMN_SPAN = 9 export const ClustersDataGrid = () => { const { filterSettings } = useLoaderData({ from: "/admin/clusters/" }) return ( - + diff --git a/apps/greenhouse/src/components/admin/ExposedServices/ExposedServicesDataGrid/index.tsx b/apps/greenhouse/src/components/admin/ExposedServices/ExposedServicesDataGrid/index.tsx index 5397cbf152..fc6edab18f 100644 --- a/apps/greenhouse/src/components/admin/ExposedServices/ExposedServicesDataGrid/index.tsx +++ b/apps/greenhouse/src/components/admin/ExposedServices/ExposedServicesDataGrid/index.tsx @@ -17,7 +17,7 @@ const COLUMN_SPAN = 4 export const ExposedServicesDataGrid = () => { const { filterSettings } = useLoaderData({ from: "/admin/exposed-services" }) return ( - + Name Cluster diff --git a/apps/greenhouse/src/components/admin/PluginInstanceDetail/Overview/Details.tsx b/apps/greenhouse/src/components/admin/PluginInstanceDetail/Overview/Details.tsx index a55a6b44b3..a036bc9a69 100644 --- a/apps/greenhouse/src/components/admin/PluginInstanceDetail/Overview/Details.tsx +++ b/apps/greenhouse/src/components/admin/PluginInstanceDetail/Overview/Details.tsx @@ -34,7 +34,7 @@ export const Details: React.FC = ({ plugin }) => { Details - + Name {plugin.metadata?.name} @@ -64,7 +64,7 @@ export const Details: React.FC = ({ plugin }) => { {plugin.metadata?.labels?.[SUPPORT_GROUP_LABEL] ?? NO_VALUE_DEFAULT} - + Cluster {plugin.spec?.clusterName ?? NO_VALUE_DEFAULT} diff --git a/apps/greenhouse/src/components/admin/PluginPresetDetail/Overview/Details.tsx b/apps/greenhouse/src/components/admin/PluginPresetDetail/Overview/Details.tsx index 73b11439a3..7c779f3988 100644 --- a/apps/greenhouse/src/components/admin/PluginPresetDetail/Overview/Details.tsx +++ b/apps/greenhouse/src/components/admin/PluginPresetDetail/Overview/Details.tsx @@ -23,7 +23,7 @@ interface DetailsProps { export const Details: React.FC = ({ pluginPreset }) => ( Details - + Name {pluginPreset.metadata?.name} diff --git a/apps/greenhouse/src/components/admin/PluginPresetDetail/Overview/PluginInstances.tsx b/apps/greenhouse/src/components/admin/PluginPresetDetail/Overview/PluginInstances.tsx index ac299b1791..fd69bde65e 100644 --- a/apps/greenhouse/src/components/admin/PluginPresetDetail/Overview/PluginInstances.tsx +++ b/apps/greenhouse/src/components/admin/PluginPresetDetail/Overview/PluginInstances.tsx @@ -111,7 +111,7 @@ export const PluginInstances = () => { {`(${ready} ready, ${notReady} not ready)`} - + diff --git a/apps/greenhouse/src/components/admin/PluginPresets/PluginPresetsDataGrid/index.tsx b/apps/greenhouse/src/components/admin/PluginPresets/PluginPresetsDataGrid/index.tsx index bf0d50fef6..a3d5d45975 100644 --- a/apps/greenhouse/src/components/admin/PluginPresets/PluginPresetsDataGrid/index.tsx +++ b/apps/greenhouse/src/components/admin/PluginPresets/PluginPresetsDataGrid/index.tsx @@ -16,7 +16,7 @@ const COLUMN_SPAN = 8 export const PluginPresetsDataGrid = () => { const { filterSettings } = useLoaderData({ from: "/admin/plugin-presets/" }) return ( - + diff --git a/apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/RemediationHistoryPanel/index.tsx b/apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/RemediationHistoryPanel/index.tsx index 9bcd58e299..c08c1d5cad 100644 --- a/apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/RemediationHistoryPanel/index.tsx +++ b/apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/RemediationHistoryPanel/index.tsx @@ -282,7 +282,7 @@ export const RemediationHistoryPanel = ({ fallbackRender={getErrorDataRowComponent({ colspan: COLUMN_SPAN })} resetKeys={[remediationsPromise]} > - + Type Expiration Date diff --git a/apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/index.tsx b/apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/index.tsx index 8e8c35fc34..bc12cb2870 100644 --- a/apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/index.tsx +++ b/apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/index.tsx @@ -86,7 +86,7 @@ const VulnerabilitiesTabContent = ({ }} /> - + @@ -176,7 +176,7 @@ const RemediatedVulnerabilitiesTabContent = ({ />
- + diff --git a/apps/heureka/src/components/Service/ImageVersionDetails/ImageVersionIssuesList/index.tsx b/apps/heureka/src/components/Service/ImageVersionDetails/ImageVersionIssuesList/index.tsx index 1e7f080196..b8f6c96ca9 100644 --- a/apps/heureka/src/components/Service/ImageVersionDetails/ImageVersionIssuesList/index.tsx +++ b/apps/heureka/src/components/Service/ImageVersionDetails/ImageVersionIssuesList/index.tsx @@ -31,7 +31,7 @@ export const ImageVersionIssuesList = ({ issuesPromise, service, image }: ImageV Vulnerabilities - + diff --git a/apps/heureka/src/components/Services/ServicesList/index.tsx b/apps/heureka/src/components/Services/ServicesList/index.tsx index c0b53bf294..e3873524cf 100644 --- a/apps/heureka/src/components/Services/ServicesList/index.tsx +++ b/apps/heureka/src/components/Services/ServicesList/index.tsx @@ -47,7 +47,7 @@ export const ServicesList = () => { return (
- + Service diff --git a/apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/VulnerabilityDetailsPanel/index.tsx b/apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/VulnerabilityDetailsPanel/index.tsx index 64377844ce..a3bcb94087 100644 --- a/apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/VulnerabilityDetailsPanel/index.tsx +++ b/apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/VulnerabilityDetailsPanel/index.tsx @@ -98,7 +98,7 @@ export const VulnerabilityPanel = () => { {vulnerability && vulnerabilityDetailsPromise && servicesPromise && ( Loading...
}> - + Support Groups diff --git a/apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/index.tsx b/apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/index.tsx index 7988c94407..6e28c5d000 100644 --- a/apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/index.tsx +++ b/apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/index.tsx @@ -47,7 +47,7 @@ export const VulnerabilitiesList = () => { return (
- + diff --git a/apps/heureka/src/components/common/ServiceImages/index.tsx b/apps/heureka/src/components/common/ServiceImages/index.tsx index dd2907ce62..e9e10a987e 100644 --- a/apps/heureka/src/components/common/ServiceImages/index.tsx +++ b/apps/heureka/src/components/common/ServiceImages/index.tsx @@ -63,7 +63,7 @@ export const ServiceImages = ({ )}
- + Image Repository Versions diff --git a/apps/supernova/src/components/alerts/AlertDetail.tsx b/apps/supernova/src/components/alerts/AlertDetail.tsx index af02b5427c..76bdcdc496 100644 --- a/apps/supernova/src/components/alerts/AlertDetail.tsx +++ b/apps/supernova/src/components/alerts/AlertDetail.tsx @@ -96,7 +96,7 @@ const AlertDetail = () => { ) ) : ( <> - + Status diff --git a/apps/supernova/src/components/alerts/AlertSilences.tsx b/apps/supernova/src/components/alerts/AlertSilences.tsx index 991c1c1c30..76046e042d 100644 --- a/apps/supernova/src/components/alerts/AlertSilences.tsx +++ b/apps/supernova/src/components/alerts/AlertSilences.tsx @@ -63,7 +63,7 @@ const AlertSilences = ({ alert }: any) => { {alert.status.inhibitedBy.length > 0 && ( <>

Inhibited by

- + Alert diff --git a/apps/supernova/src/components/alerts/AlertsList.tsx b/apps/supernova/src/components/alerts/AlertsList.tsx index 259ef40fca..f01aa4fc67 100644 --- a/apps/supernova/src/components/alerts/AlertsList.tsx +++ b/apps/supernova/src/components/alerts/AlertsList.tsx @@ -41,7 +41,7 @@ const AlertsList = () => { }) return ( - + diff --git a/apps/supernova/src/components/alerts/shared/AlertSilencesList.tsx b/apps/supernova/src/components/alerts/shared/AlertSilencesList.tsx index 30c3995ba5..f1fc415f6e 100644 --- a/apps/supernova/src/components/alerts/shared/AlertSilencesList.tsx +++ b/apps/supernova/src/components/alerts/shared/AlertSilencesList.tsx @@ -42,7 +42,7 @@ const AlertSilencesList = ({ alert }: any) => { {silenceList.length > 0 && ( <>

Silences

- + Status Silence start diff --git a/apps/supernova/src/components/silences/SilencesList.tsx b/apps/supernova/src/components/silences/SilencesList.tsx index 12f6d4765a..36fbe52168 100644 --- a/apps/supernova/src/components/silences/SilencesList.tsx +++ b/apps/supernova/src/components/silences/SilencesList.tsx @@ -162,7 +162,7 @@ const SilencesList = () => { /> - + <> Time intervall diff --git a/packages/ui-components/docs/intent-skills.md b/packages/ui-components/docs/intent-skills.md new file mode 100644 index 0000000000..bf08af8842 --- /dev/null +++ b/packages/ui-components/docs/intent-skills.md @@ -0,0 +1,646 @@ +# Shipping Knowledge with TanStack Intent + +> [!NOTE] +> This document describes the design for distributing Juno's maintainer knowledge (component usage, UX guidelines, patterns) to consumer projects via [TanStack Intent](https://tanstack.com/intent/latest). It is the reference for both maintainers authoring skills and teams consuming them. + +## Table of Contents + +- [The Problem](#the-problem) +- [What Is TanStack Intent?](#what-is-tanstack-intent) +- [How It Works End-to-End](#how-it-works-end-to-end) +- [Consumer-Side Flow (How the AI Uses Skills)](#consumer-side-flow-how-the-ai-uses-skills) +- [Where the Skills Actually Live in the Chain](#where-the-skills-actually-live-in-the-chain) +- [Skill Architecture](#skill-architecture) +- [Maintainer Setup](#maintainer-setup) +- [Consumer Setup](#consumer-setup) +- [Consumer: Controlling Which Skills Load](#consumer-controlling-which-skills-load) +- [CLAUDE.md Fallback (Hybrid Approach)](#claudemd-fallback-hybrid-approach) +- [CI Integration](#ci-integration) +- [Documentation Surfaces](#documentation-surfaces) +- [Rollout Phases](#rollout-phases) +- [Design Decisions Reference](#design-decisions-reference) +- [Out of Scope](#out-of-scope) + +--- + +## The Problem + +As the Frontend Engineering team, we maintain knowledge on the **maintainer side**: + +- `packages/ui-components` — 105 components with Storybook documentation +- `docs/ux` — 42 markdown files of UX guidelines, patterns, and best practices + +We want to ship that knowledge to the **consumer side** so that every team member — and the AI assistants they use — produces consistent code that follows our guidelines: + +- **Aurora** (`@cobaltcore-dev/aurora`) — external consumer that bundles Juno components +- **Greenhouse core** (`apps/greenhouse`) — the shell/host application +- **Greenhouse plugins** (`apps/doop`, `apps/supernova`, `apps/heureka`) — micro-frontends +- **External plugins** — new apps built from a template, later integrated into Greenhouse + +The goal is **both** active guidance for critical patterns (AppShell wrapping, provider setup, accessibility) and passive knowledge for reference (UX writing, component APIs). + +--- + +## What Is TanStack Intent? + +TanStack Intent is a CLI for library maintainers to **generate, validate, and ship Agent Skills alongside their npm packages**. Skills are markdown documents (`SKILL.md`) that teach AI coding agents how to use a library correctly. + +Key properties: + +- **Versioned with code** — skills ship inside the npm tarball, so consumers get guidance matching their installed version. +- **Discoverable** — consumers run `intent list` to see available skills; AI agents run `intent load` to pull guidance into context. +- **Trust-gated** — consumers explicitly allowlist which packages' skills are surfaced via `package.json#intent.skills`. +- **Open standard** — compatible with the Agent Skills standard, so it works across Claude Code, Cursor, and other AI tools. + +> [!NOTE] +> TanStack Intent is alpha-stage (`@tanstack/intent@0.5.x` at time of writing). Expect the CLI surface to evolve. + +--- + +## How It Works End-to-End + +``` +┌───────────────────────────────────────────────────────────────────────────┐ +│ MAINTAINER SIDE (Frontend Engineering team) │ +│ │ +│ @cloudoperators/juno-ui-components (npm package) │ +│ └── skills/ │ +│ ├── fundamentals/SKILL.md ← AppShell, providers, theming, core │ +│ ├── datagrid/SKILL.md ← DataGrid patterns │ +│ ├── forms/SKILL.md ← Form inputs, validation │ +│ └── feedback/SKILL.md ← Messages, toasts, loading states │ +│ │ +│ Skills reference: docs/ux/*.md + *.stories.tsx │ +│ │ +│ Published to npm ──► skills ship inside the package tarball │ +└───────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌───────────────────────────────────────────────────────────────────────────┐ +│ CONSUMER SIDE (e.g. a Greenhouse plugin developer) │ +│ │ +│ my-greenhouse-plugin/ │ +│ ├── package.json │ +│ │ "dependencies": { │ +│ │ "@cloudoperators/juno-ui-components": "^9" │ +│ │ }, │ +│ │ "intent": { │ +│ │ "skills": ["@cloudoperators/juno-ui-components"] ← allowlist │ +│ │ } │ +│ │ │ +│ ├── node_modules/@cloudoperators/juno-ui-components/ │ +│ │ └── skills/ ← skills land HERE, installed with the package │ +│ │ │ +│ └── AGENTS.md (and/or CLAUDE.md) │ +│ └── block with discovery instructions │ +└───────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌───────────────────────────────────────────────────────────────────────────┐ +│ AI TOOL (Claude Code, Cursor, …) │ +│ │ +│ 1. Reads AGENTS.md / CLAUDE.md ──► sees Intent instructions │ +│ 2. Runs: npx @tanstack/intent list │ +│ 3. Sees available skills from allowlisted packages │ +│ 4. Working on a table? npx @tanstack/intent load #datagrid │ +│ 5. SKILL.md content is injected into the AI's context window │ +│ 6. AI applies the guidance while helping the developer write code │ +└───────────────────────────────────────────────────────────────────────────┘ +``` + +**Key insight:** The AI does not know skills exist by magic. The mechanism is _context injection_ — a discovery file points the AI at Intent, the `intent load` command extracts `SKILL.md` content, and that content becomes part of the AI's working context, exactly as if the developer had pasted it in by hand, but automated and versioned with the package. + +--- + +## Consumer-Side Flow (How the AI Uses Skills) + +Here is a concrete end-to-end example of what happens when a developer works with an Intent-aware AI assistant. + +**Scenario:** A developer on the Aurora team asks Claude Code: + +> _"Add a table showing all images with filtering and pagination."_ + +### Step 1 — AI discovers that skills exist + +The AI reads the project's `AGENTS.md`, which contains a block auto-generated by `intent install`: + +```markdown + + +This project uses TanStack Intent for AI guidance. Before editing code: + +- Run `npx @tanstack/intent list` to see available skills +- Run `npx @tanstack/intent load #` to load relevant guidance + +``` + +### Step 2 — AI lists available skills + +```bash +$ npx @tanstack/intent list + +@cloudoperators/juno-ui-components (9.1.0) + ★ #fundamentals [load first] AppShell setup, providers, theming, core patterns + #datagrid DataGrid components, sorting, filtering, pagination + #forms Form inputs, validation, submit patterns + #feedback Messages, toasts, loading states + ... +``` + +### Step 3 — AI loads the relevant skill + +The AI recognizes "table with filtering and pagination" and loads the DataGrid skill: + +```bash +$ npx @tanstack/intent load @cloudoperators/juno-ui-components#datagrid +``` + +The full `SKILL.md` content streams into the AI's context: + +```markdown +# DataGrid Skill + +## Core Components + +- `DataGrid` - Container for tabular data +- `DataGridRow` - Individual row +- `DataGridCell` - Cell within a row +- `DataGridHeadCell` - Header cell with sorting support +- `DataGridToolbar` - Toolbar for filters and actions + +## Required Patterns + +### Always wrap filters in DataGridToolbar + +✅ Do: + + + +... + +❌ Don't: place filters outside the toolbar structure + +### Empty state handling + +Always provide an empty state using the Status component: + + +## References + +- Full UX guidelines: docs/ux/datagrid.md +- Storybook examples: https://cloudoperators.github.io/juno/?path=/docs/... +``` + +### Step 4 — AI applies the guidance + +When Claude Code writes the code, it now: + +- uses `DataGridToolbar` for the filter UI, +- adds sortable `DataGridHeadCell` columns, +- includes an empty state with the `Status` component, +- follows the pagination pattern from the skill. + +### How different tools consume Intent + +| AI Tool | How it uses Intent | +| ---------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| **Claude Code** | Reads `CLAUDE.md` → follows instructions to run `intent load` → skill content enters the conversation context. | +| **Cursor** | Reads `.cursorrules` or `AGENTS.md` → same `intent load` flow. | +| **GitHub Copilot** | Can read `AGENTS.md` if configured; less reliable at running CLI commands. | +| **Native Intent support** (future) | Tools may integrate Intent directly, auto-loading skills based on the file being edited. | + +--- + +## Where the Skills Actually Live in the Chain + +A key property of this model: **skills are a development-time artifact, not a distribution one.** They +ship inside the Juno package, land in a consumer's `node_modules` where the AI can read them while a +developer writes code, and then stop there — they never propagate into the consumer's own built +bundle or published package. + +Worked example using [Aurora](https://github.com/cobaltcore-dev/aurora-dashboard/tree/main/packages/aurora), +which consumes Juno and publishes its own package: + +``` +@cloudoperators/juno-ui-components (npm) + └── skills/ ← skills ship HERE, inside Juno's tarball (~75 KB compressed) + │ + ▼ pnpm install (Aurora lists juno as a devDependency) +Aurora dev's node_modules/@cloudoperators/juno-ui-components/skills/ + │ ← skills sit here during DEVELOPMENT + │ `intent list` / `intent load` read them from here + │ + ▼ pnpm build → dist/ (vite + tsup; SKILL.md is never `import`-ed by app code) +Aurora's dist/ ← NO skills. Only Aurora's own compiled client/server output + │ (the Juno components Aurora actually imports are bundled in; + │ the markdown skills are left behind) + │ + ▼ npm publish (Aurora's package.json has files: ["dist"]) +Aurora's published tarball ← NO skills + │ + ▼ installed by Aurora's own consumers +Downstream app ← sees nothing of Juno's skills +``` + +### Why the skills never leak downstream + +Two independent mechanisms guarantee it, each sufficient on its own: + +1. **Bundlers only include what is `import`-ed.** `SKILL.md` files are plain markdown that no + application code imports, so Vite/tsup never pull them into `dist/`. They add **zero bytes** to + any built output. (This is the same reason skills do not affect Juno's own runtime bundle: the + skills are a small fraction of the package on disk — roughly the size of the compiled CSS — but + 0% of what executes, since nothing imports them.) +2. **The `files` allowlist scopes the published tarball.** Aurora publishes `files: ["dist"]`, and + the skills live in `node_modules/@cloudoperators/juno-ui-components/skills/`, not in `dist/`. So + they are outside Aurora's publish set regardless of bundling. + +### Implications + +- A developer building against Juno (Aurora, a Greenhouse plugin, a new app from the template) gets + Juno's skills **while developing**. Their AI assistant loads them from `node_modules`. +- That consumer's **own** downstream users see nothing of Juno's skills — which is the desired + behavior. +- If a consumer wants to ship guidance to **its** users, it authors **its own** skills and adds its + `skills/` directory to its **own** `files` array. This is exactly the plan for Aurora-specific + skills (tRPC patterns, the slot system, OpenStack integration) described under + [Consumer Setup → Aurora](#aurora). + +> [!NOTE] +> A consumer only sees the skills once it depends on a **published Juno version that contains them**. +> For example, Aurora currently pins `@cloudoperators/juno-ui-components` at an older version as a +> devDependency; it will not see the skills until it bumps to a release that ships them (or installs +> a local tarball built with the skills for testing). + +--- + +## Skill Architecture + +### Location + +Skills live at the **package root** in a visible `skills/` directory, matching TanStack Intent's documented convention and versioning together with the package: + +``` +packages/ui-components/ +└── skills/ + ├── fundamentals/SKILL.md + ├── datagrid/SKILL.md + ├── forms/SKILL.md + ├── feedback/SKILL.md + ├── layout/SKILL.md + ├── navigation/SKILL.md + ├── modals/SKILL.md + ├── accessibility/SKILL.md + ├── ux-writing/SKILL.md + └── migrations/SKILL.md +``` + +### The 10 skills + +The architecture is **hybrid**: one foundational skill that is always relevant, plus domain skills loaded on demand. + +| Skill | Purpose | Priority | +| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| `#fundamentals` | AppShellProvider, theming, CSS imports, provider nesting order, embedded patterns, routing (TanStack Router), state management (Zustand slices), semantic variants, accessibility basics, error/loading/empty states | **Phase 1** | +| `#datagrid` | DataGrid components, sorting, filtering, pagination, bulk actions, empty states | **Phase 1** | +| `#forms` | Form inputs, validation timing, `FormRow`/`FormSection`, conditional fields, submit feedback | **Phase 1** | +| `#feedback` | `Message`, `Toast`, `NotificationManager`, `Status`, loading states | **Phase 1** | +| `#layout` | `AppShell`, `Container`, `Stack`, `Grid`, page structure | Phase 2 | +| `#navigation` | `SideNavigation`, `TopNavigation`, `Breadcrumb`, `Tabs` | Phase 2 | +| `#modals` | `Modal`, `Panel`, confirmation dialogs, destructive-action severity | Phase 2 | +| `#accessibility` | ARIA patterns, keyboard navigation, focus management | Phase 2 | +| `#ux-writing` | Content guidelines, title case, button labels, empty values (`- -`) | Phase 2 | +| `#migrations` | Deprecated components and upgrade paths | Phase 2 | + +Skill names are **short** — the package scope (`@cloudoperators/juno-ui-components#datagrid`) already provides the origin context. + +### Content conventions + +- **Tiered** — core guidance (the 80% case) upfront; advanced sections at the end that the AI can skip for simple tasks. +- **Summarize + reference** — skills contain condensed, actionable guidance and link to the full `docs/ux/*.md` for deep dives, so the UX docs remain the single source of truth. +- **Source references** — each skill references the relevant UX docs (the "why" and the rules) and Storybook stories (`*.stories.tsx`, the "how to use"). Component source is implementation detail skills do not need to reference. + +### Discovery experience + +`intent list` presents skills **hierarchically**: `#fundamentals` is marked _load first_; domain skills are marked _load as needed_. + +--- + +## Maintainer Setup + +- **Ownership:** The **Frontend Engineering team** owns and maintains all skills centrally, ensuring a consistent voice. PR review enforces quality. +- **Versioning:** **Loose coupling.** Skills are updated when patterns or APIs change meaningfully — not on every release. `intent stale` surfaces drift; maintainers decide whether guidance needs updating. + +Typical maintainer workflow: + +```bash +# One-time, from the ui-components package +npx @tanstack/intent maintainer setup + +# Create or register a skill +npx @tanstack/intent maintainer add datagrid --package @cloudoperators/juno-ui-components + +# Ongoing: find skills affected by recent changes +npx @tanstack/intent maintainer review + +# Before release: align metadata and verify structure +npx @tanstack/intent maintainer sync +npx @tanstack/intent maintainer check +``` + +> [!NOTE] +> `maintainer add` creates the skeleton and registers the skill, but the maintainer writes the task coverage, source-backed guidance, and consequential decisions — the command does not infer them. + +--- + +## Consumer Setup + +Consumers **opt in explicitly** by allowlisting the package and running `intent install`. + +### Existing Greenhouse apps (doop, supernova, heureka) — configured retroactively + +Each app's `package.json`: + +```json +{ + "intent": { + "skills": ["@cloudoperators/juno-ui-components"] + } +} +``` + +Then run `npx @tanstack/intent install` to generate the `AGENTS.md` discovery block. Even internal apps benefit — any team member working on any app gets the same guidance. + +### New plugin template — working integration out of the box + +The "start from scratch" template ships with Intent ready to use: + +1. `package.json#intent.skills` pointing at `@cloudoperators/juno-ui-components`. +2. `AGENTS.md` with the Intent skill-discovery block. +3. `CLAUDE.md` with critical fundamentals inline **plus** instructions to load domain skills (see below). + +New plugin developers get AI assistance immediately, with no extra setup — the template is the happy path. + +### Aurora + +Aurora bundles Juno components (as a dev dependency) and has its **own patterns** that Juno skills do not cover. Aurora therefore ships **its own Aurora-specific skills**, living in the Aurora package: + +- tRPC procedure patterns (`publicProcedure`, `protectedProcedure`, `projectScopedProcedure`, …) +- the slot system (`logo`, `sideNavBanner`, `pageFooter`, …) +- route `staticData` conventions for breadcrumbs +- OpenStack / BFF integration patterns + +Each package owns its own skills; there are **no cross-package skill references**. + +--- + +## Consumer: Controlling Which Skills Load + +Once a consumer has Intent set up, there are **two different layers** that decide "which skills +load," and it is worth separating them because they answer different concerns. + +### Layer 1 — Which skills are _available_ (the allowlist, in `package.json`) + +A one-time policy decision per consumer project, controlled by `intent.skills` (allowlist) and +`intent.exclude` (blocklist). It governs what `intent list` / `intent load` will surface at all. + +```jsonc +// consumer app's package.json +{ + "intent": { + "skills": [ + /* allowlist — what is permitted */ + ], + "exclude": [ + /* blocklist — removed AFTER the allowlist resolves */ + ], + }, +} +``` + +`intent.skills` entry forms, most → least permissive: + +| Entry | Meaning | +| ----------------------------------------------- | --------------------------------------------------------------------- | +| `["*"]` | All discovered packages' skills (emits an "acknowledged risk" notice) | +| `"@cloudoperators/juno-ui-components"` | **All** skills from that package | +| `"@cloudoperators/*"` | All skills from any package in that scope | +| `"@cloudoperators/juno-ui-components#datagrid"` | **Only** that one skill | +| `[]` | Nothing | + +`intent.exclude` removes entries _after_ the allowlist resolves — the surgical "all except" tool, +and it accepts patterns: + +```jsonc +{ + "intent": { + "skills": ["@cloudoperators/juno-ui-components"], // allow all juno skills… + "exclude": [ + "@cloudoperators/juno-ui-components#ux-writing", // …except these, + "@cloudoperators/juno-ui-components#experimental-*", // and anything experimental + ], + }, +} +``` + +So "which skills should be available" comes down to picking the right granularity: + +- **Want everything:** `"skills": ["@cloudoperators/juno-ui-components"]` +- **Want only a few:** list them individually — `"...#datagrid"`, `"...#forms"` +- **Want all-but-some:** allow the package, then `exclude` the unwanted ones + +Ways to set it: + +- **Interactive (recommended first time):** `npx @tanstack/intent install` walks through + "Enable all / Choose packages or scopes / Choose individual skills" and writes both the + `intent.skills` block and the `AGENTS.md` discovery guidance. +- **Change your mind later:** `npx @tanstack/intent install --review` reopens the picker. +- **Quick blocklist tweaks:** `npx @tanstack/intent exclude add ` / + `exclude remove ` / `exclude list`. +- **Preview without writing:** add `--dry-run`. + +### Layer 2 — Which skills _actually load_ into the AI, per task + +Even with all 12 skills allowed, the AI does not dump them all into context. Loading is +**on-demand and task-driven**: + +1. The AI reads the `AGENTS.md` / `CLAUDE.md` block, which instructs it to run `intent list`, then + `intent load #` for the relevant skill before editing. +2. The AI matches each skill's **`description`** (its "Use when…" activation text) against what the + developer asked, and loads only the matching skills. This is why the skills are authored with + precise, non-overlapping descriptions and explicit cross-references ("for form inputs, see the + forms skill"). +3. `intent install --map` can harden this by writing an explicit **task → skill mapping** into the + agent config (e.g. "building a table → `#datagrid`"), making selection deterministic rather than + left to the model's judgment. + +### The two levers, summarized + +| Lever | Scope | Where | Granularity | +| ------------------------------------- | --------------------------------------- | -------------------------------- | ----------------- | +| **Allowlist / exclude** | _Policy_ — what is permitted at all | `package.json#intent` | Coarse, set once | +| **Activation descriptions + `--map`** | _Routing_ — what loads for a given task | skill frontmatter / agent config | Fine, per request | + +### Recommended default + +For a Greenhouse plugin or Aurora, allow the whole package and let per-task activation handle the +rest: + +```jsonc +{ "intent": { "skills": ["@cloudoperators/juno-ui-components"] } } +``` + +Reach for individual `#skill` entries or `exclude` only when a team deliberately wants to suppress +something — e.g. a design-system team that handles `ux-writing` out of band and does not want the AI +touching copy. + +--- + +## CLAUDE.md Fallback (Hybrid Approach) + +Not every AI tool natively runs the Intent CLI. For maximum compatibility, `CLAUDE.md` uses a **hybrid** strategy: critical fundamentals inline (work immediately) + instructions to load domain skills via Intent (full content without duplication). + +````markdown +# Juno UI Development Guidelines + +## Critical: Always Follow These Rules + +### Provider Setup (MUST DO) + +Always wrap your app with AppShellProvider: + +```tsx + + + +``` + +### CSS Import (MUST DO) + +```tsx +import "@cloudoperators/juno-ui-components/juno-ui-components.css" +``` + +## Loading Additional Guidance + +For component-specific guidance, load Intent skills: + +```bash +# List available skills +npx @tanstack/intent list + +# Load a specific skill +npx @tanstack/intent load @cloudoperators/juno-ui-components#datagrid +npx @tanstack/intent load @cloudoperators/juno-ui-components#forms +npx @tanstack/intent load @cloudoperators/juno-ui-components#feedback +``` + +Load the relevant skill before working on: + +- Data tables → #datagrid +- Form inputs → #forms +- Notifications → #feedback +```` + +This means: + +- **Critical fundamentals work immediately** — they are inline in `CLAUDE.md`. +- **Domain guidance loads on demand** — via Intent. +- **It degrades gracefully** — even if the AI never runs the CLI, the basics are present. + +--- + +## CI Integration + +The pipeline uses the **full workflow**: validation + staleness + PR comments. + +```yaml +- name: Validate Intent skills + run: npx @tanstack/intent maintainer check # fails build on malformed skills + +- name: Check skill freshness + run: npx @tanstack/intent stale # surfaces drift + +- name: Review skill impact + run: npx @tanstack/intent maintainer review --json > review.json + # + a custom action posts a PR comment when changed files + # (e.g. DataGrid.stories.tsx) affect a skill's referenced sources +``` + +- `maintainer check` **fails the build** on structural problems (bad frontmatter, missing sections, unregistered skills). +- `stale` and `review` **inform** — they flag when a referenced source file changed so a reviewer can decide whether the skill needs updating. This pairs with the loose-coupling versioning policy. + +--- + +## Documentation Surfaces + +Skills are documented in three places so teams can find them wherever they look: + +| Surface | Content | +| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| `packages/ui-components/README.md` | Intent quick-start section | +| `packages/ui-components/docs/intent-skills.md` (this file) | Full setup guide + skill catalog | +| Storybook | An "Intent Skills" page showing available skills and how to use them, alongside component docs | + +--- + +## Rollout Phases + +**Phase 1 — initial rollout (highest-usage domains first):** + +1. Set up the `skills/` directory structure in `ui-components`. +2. Author `#fundamentals`, `#datagrid`, `#forms`, `#feedback`. +3. Add the CI validation workflow. +4. Update the `ui-components` README. +5. Configure the Greenhouse apps retroactively. +6. Update the plugin template with the Intent integration. + +**Phase 2 — expansion:** + +1. Author the remaining domain skills (`#layout`, `#navigation`, `#modals`, `#accessibility`, `#ux-writing`). +2. Author the `#migrations` skill. +3. Add the Storybook documentation page. +4. Author Aurora-specific skills (separate effort, in the Aurora package). + +--- + +## Design Decisions Reference + +| # | Decision | Choice | +| --- | ------------------------- | ---------------------------------------------------------------------------------------- | +| 1 | Primary goal | Both — active guidance for critical patterns + passive reference knowledge | +| 2 | Skill granularity | Hybrid — one foundational skill + domain skills on demand | +| 3 | Authoring location | Colocated with source (ships in the npm package) | +| 4 | Consumer adoption | Opt-in explicit (`package.json#intent.skills` + `intent install`) | +| 5 | Rollout scope | All projects simultaneously; each adopts when ready | +| 6 | Foundational skill scope | Setup + patterns + critical UX | +| 7 | Domain skills | All 8 (layout, navigation, datagrid, forms, modals, feedback, accessibility, ux-writing) | +| 8 | Source references | UX docs + Storybook stories | +| 9 | Versioning | Loose coupling (`intent stale` flags drift; maintainers decide) | +| 10 | Plugin template | Intent + CLAUDE.md working integration | +| 11 | Skill file location | `skills/` at package root | +| 12 | UX docs integration | Summarize + reference | +| 13 | CI integration | Full workflow (validation + staleness + PR comments) | +| 14 | Consumer documentation | README + dedicated doc + Storybook | +| 15 | Aurora skills | Yes — Aurora-specific skills in the Aurora package | +| 16 | CLAUDE.md strategy | Hybrid — fundamentals inline + Intent instructions | +| 17 | Authoring responsibility | Frontend Engineering team (centralized) | +| 18 | Content depth | Tiered — core upfront, advanced at the end | +| 19 | Greenhouse apps migration | Yes, retroactively | +| 20 | Discovery experience | Hierarchical (fundamentals load-first) | +| 21 | External plugin template | Working integration | +| 22 | Naming convention | Short names | +| 23 | Cross-package references | No — each package owns its own skills | +| 24 | Deprecation handling | Separate `#migrations` skill | +| 25 | Initial rollout order | Most-used domains first | + +--- + +## Out of Scope + +Decided against, for clarity: + +- **Cross-package skill references** — each package owns its own skills. +- **Skills inside component source directories** — they live at the package root. +- **Duplicating full UX docs content in skills** — skills summarize and link. +- **Auto-failing CI on staleness warnings** — staleness informs; only structural validation fails the build. diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json index ecb005134f..64f872acee 100644 --- a/packages/ui-components/package.json +++ b/packages/ui-components/package.json @@ -12,7 +12,19 @@ "./theme.css": "./build/theme.css" }, "files": [ - "build/*" + "build/*", + "skills/datagrid", + "skills/layout", + "skills/forms", + "skills/navigation", + "skills/feedback", + "skills/overlays", + "skills/data-display", + "skills/actions", + "skills/app-foundations", + "skills/accessibility", + "skills/ux-writing", + "skills/interaction-patterns" ], "author": "UI-Team", "repository": "https://github.com/cloudoperators/juno/tree/main/packages/juno-ui-components", @@ -29,6 +41,7 @@ "@storybook/addon-docs": "10.6.1", "@storybook/addon-links": "10.6.1", "@storybook/react-vite": "10.6.1", + "@tanstack/intent": "0.5.5", "@tailwindcss/vite": "4.3.3", "@testing-library/jest-dom": "7.0.1", "@testing-library/react": "16.3.3", @@ -71,5 +84,8 @@ "test-vitest:watch": "vitest", "clean": "rm -rf build && rm -rf node_modules && rm -rf .turbo", "clean:cache": "rm -rf .turbo" - } + }, + "keywords": [ + "tanstack-intent" + ] } diff --git a/packages/ui-components/skills/accessibility/SKILL.md b/packages/ui-components/skills/accessibility/SKILL.md new file mode 100644 index 0000000000..f00fc72690 --- /dev/null +++ b/packages/ui-components/skills/accessibility/SKILL.md @@ -0,0 +1,280 @@ +--- +name: accessibility +description: > + Use when ensuring a Juno UI built with @cloudoperators/juno-ui-components is accessible: + choosing semantic HTML over div/span for actions and navigation, giving every input and + icon-only button an accessible name, grouping related inputs, wiring help and error text, + keeping keyboard navigation and visible focus intact, trapping and returning focus in modals, + avoiding color-only signals, and announcing dynamic content (loading, success, errors) to + screen readers. For the DataGrid empty/loading/error pattern see the datagrid skill; for form + validation wiring see the forms skill. +metadata: + purpose: > + Teaches developers to build accessible Juno UIs by preferring semantic Juno primitives + (Button, TextInput, CheckboxGroup, RadioGroup, Modal, Status) that already carry the correct + roles, labels, and focus behaviour, and by filling the gaps the components do not enforce — + accessible names for icon-only controls, grouped-input labelling, non-color status signals, + and aria-live announcement of application-driven dynamic content. + type: core + library: "@cloudoperators/juno-ui-components" + library_version: "9.6.0" +sources: + - cloudoperators/juno:packages/ui-components/src/components/Button/Button.component.tsx + - cloudoperators/juno:packages/ui-components/src/components/Button/Button.stories.tsx + - cloudoperators/juno:packages/ui-components/src/components/Icon/Icon.component.tsx + - cloudoperators/juno:packages/ui-components/src/components/TextInput/TextInput.component.tsx + - cloudoperators/juno:packages/ui-components/src/components/CheckboxGroup/CheckboxGroup.component.tsx + - cloudoperators/juno:packages/ui-components/src/components/RadioGroup/RadioGroup.component.tsx + - cloudoperators/juno:packages/ui-components/src/components/Modal/Modal.component.tsx + - cloudoperators/juno:packages/ui-components/src/components/Status/Status.component.tsx + - cloudoperators/juno:docs/ux/accessibility.md + - cloudoperators/juno:docs/ux/interaction-guidelines.md +--- + +# Make a Juno UI accessible + +The single most effective accessibility measure is correct semantic HTML — the right element for +the right purpose (`