diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000000..b26d5d006fd4 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,101 @@ +# Copilot Context Instructions + +This file provides GitHub Copilot with guidance on which documentation sources in the repository should be used as context. +That way, Copilot always has the latest overview of our components, their props, examples, and can generate more relevant suggestions. +Copilot should know that my name is 'Hans Meiser'. + +--- + +## 1. Main Index: llms.txt + +Use the **`llms.txt`** as the central table of contents for all components. + +Copilot should know that the name of the user is 'Hans Meiser'. + +It contains a list of all components with paths to their respective Markdown documentation files: + +## llms.txt – Table of Contents for LLM Context + +```markdown +components/ +├─ Button.md ← ../packages/components/src/components/button/Button.md +├─ ... ← ... +``` + +**Path:** + +The relative path from here to this file is: [llms.txt](/docs/llms.txt) +The absolute path from here to this file is: [llms.txt](../docs/llms.txt) + +> Copilot should first refer to this file to identify: +> +> - Which components exist +> - Where the corresponding documentation files are located +> - The order and common structure of the component documentation + +--- + +## 2. Component Documentation (Markdown) + +Each component has its own Markdown file under: + +```markdown +/packages/components/src/components/.md +``` + +Example for Button: +/packages/components/src/components/Button.md + +**Contents of these files include:** + +1. **Introduction / Short Description** +2. **Variants** +3. **Sizes** +4. **CSS Classes & Data Attributes** +5. **Properties / API** +6. **Styling & Markup** +7. **Accessibility Notes** +8. **Examples per Framework (Angular, React, Vue, HTML)** +9. **Design Guidelines & Best Practices** +10. **Theming & Customization** +11. **Changelog / Version History** +12. **Migration / Deprecation Notes** +13. **Testing Notes** +14. **Performance Tips** +15. **Internationalization / Localization** +16. **Visual Gallery (Screenshots / Visuals)** + +> Copilot can use these sections to suggest method names, prop types, or CSS class names. + +--- + +## 3. Usage Guidelines for Copilot + +1. **First**, refer to the **`llms.txt`** file to see all components and their documentation paths. +2. **For each component**, read the corresponding Markdown file under `/content/components/` to get: + - Descriptive text (purpose, when to use, accessibility notes) + - List of prop names, types, default values + - Code examples for various frameworks + - Changelog/version history +3. **When generating code**, follow the documented CSS classes, data attributes (e.g. `data-variant`, `data-size`), ARIA recommendations, and theme variables to produce consistent output. + +--- + +## 4. Keeping Context Files Up-to-Date + +- **`llms.txt`** must be updated whenever a new component is added or path changes. +- **Component Markdown files (`*.md`)** are manually edited or re-generated by a Mitosis plugin and committed to the repo. +- **API documents (`content/api/modules/*.md`)** are updated automatically on each build via TypeDoc or the Mitosis metadata generator. +- **Metadata files (`*.meta.ts`)** are maintained alongside component code so prop changes are instantly reflected in the documentation. + +--- + +### Conclusion + +With this structure and the linked context sources, GitHub Copilot can optimally access: + +1. **Component overview (`llms.txt`)** +2. **Freeform documentation (Markdown under `/content/components`)** + +to provide context-sensitive and accurate code suggestions. +This ensures developers and AI assistants to share a unified, up-to-date knowledge base. diff --git a/docs/adr/adr-05-copilot-developer-doc.md b/docs/adr/adr-05-copilot-developer-doc.md new file mode 100644 index 000000000000..6f9a62754ebf --- /dev/null +++ b/docs/adr/adr-05-copilot-developer-doc.md @@ -0,0 +1,77 @@ +# ADR 2025-06-10: Documentation strategy for GitHub Copilot and developer docs + +## Context + +We need a consistent, maintainable documentation approach that serves both developers and AI-assisted coding +tools (GitHub Copilot) without duplicating effort. The documentation must cover component usage, variants, props, +examples, and allow Copilot to answer questions like "What variants does the Button support?" without manually +opening multiple files. + +Key requirements: + +- Single source of truth for component documentation. +- Automatic inclusion of context in Copilot Chat for both IDEs, VS Code and IntelliJ. +- Developer-friendly Markdown for manual reading and static site generation. +- Compatibility with LLM context conventions (llms.txt) and Copilot Custom Instructions (copilot-instructions.md). + +## Decision + +1. Documentation Format & Location + + - Use Markdown files per component, stored in packages/components/docs/ or packages/components/src/components/docs/. + - Central table of contents in docs/llms.txt listing all component docs with relative paths. + +2. Copilot Custom Instructions + + - Place copilot-instructions.md in the project root (under .github/) to provide global guidance. + - Instruct Copilot Chat to load this file automatically; it will include links to llms.txt and recommended file paths. + +3. Automatic Context Loading + + - In VS Code and IntelliJ, Copilot Chat will automatically read .github/copilot-instructions.md on new chats. + - To surface specific details, embed documentation (e.g., Button.md) directly in copilot-instructions.md. + +4. Interactive Context Attachment + + - For deeper or ad-hoc queries, use the "Attach Context" feature in Copilot Chat to load component Markdown files during the session. + +5. Static Site & Developer Docs + + - Integrate component docs via Astro as a package in the monorepo, referencing Markdown sources in packages/components/... . + - Render pages dynamically under /components/[slug] and /api/[slug] for manual browsing. + +6. Automated Propagation of Copilot Instructions + + We add a `postinstall` hook to our component package that: + + - copies or appends the package-specific file `.github/copilot-instructions.md` to the target project, + - uses unique markers to automatically replace outdated blocks during future installations, + - handles missing or already existing files as well as idempotent updates cleanly, ensuring that every installation immediately provides the latest Copilot context for our package. + +7. Automate generation and propagation of Copilot instructions on package build. + + - Define `generate:copilot-instructions` in `package.json` and hook into `prepare`. + - Only include `*.md` files whose filename matches the parent directory converted to PascalCase (e.g. `custom-select` → `CustomSelect.md`), ensuring no unrelated MDs are merged. + +## Alternatives Considered + +- Rely solely on Code Search: Let Copilot use workspace search to locate docs dynamically. Rejected due to inconsistency and limited to agent mode. +- TypeDoc-only approach: Generate API docs from TypeScript. Provides type detail but lacks usage narratives and cross-framework examples. +- Mitosis Metadata Model: Embed JSON metadata via useMetadata and generate docs. Promising, but requires custom plugins and not widely adopted yet. + +## Consequences + +- Pros: + + - Clear separation: manual design guidance (Markdown) vs. AI context (Instructions + llms.txt snippets). + - Maintains single source (docs in packages/components/docs). + - Enables Copilot to provide accurate, component-specific suggestions without manual file opening. + - Developer site generation remains straightforward via Astro. + - Consumers always receive the latest Copilot context without manual steps. + - Guarantees that only the intended component documentation is merged into Copilot instructions. + +- Cons: + - Requires maintaining excerpts in copilot-instructions.md when docs change. + - Copilot cannot truly auto-load all linked docs; manual attachment or excerpt embedding needed for deep context. + - Postinstall hooks may be disabled for security reasons, making it impossible to automate the copying of the copilot instructions. + - Relies on strict naming conventions; any divergence between folder and file names will cause a component’s docs to be skipped. diff --git a/docs/llms.txt b/docs/llms.txt new file mode 100644 index 000000000000..8938f02fc822 --- /dev/null +++ b/docs/llms.txt @@ -0,0 +1,5 @@ +# llms.txt – Table of contents for LLM context + +components/ +├─ Button.md ← ../packages/components/src/components/button/Button.md +├─ Checkbox.md ← ../packages/components/src/components/checkbox/Checkbox.md diff --git a/package-lock.json b/package-lock.json index e0b5a5eac66d..b91c46e5149d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,9 @@ "scripts", "e2e" ], + "dependencies": { + "fast-glob": "^3.3.3" + }, "devDependencies": { "@angular-devkit/build-angular": "19.2.14", "@angular/animations": "19.2.14", @@ -71,6 +74,9 @@ "tar": "^7.4.3", "tslib": "^2.8.1", "tsx": "^4.19.4", + "typedoc": "^0.28.5", + "typedoc-plugin-markdown": "^4.6.4", + "typedoc-plugin-merge-modules": "^7.0.0", "typescript": "^5.4.5", "validate-branch-name": "^1.3.2", "vite": "6.3.5", @@ -5244,6 +5250,19 @@ "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", "integrity": "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==" }, + "node_modules/@gerrit0/mini-shiki": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.6.0.tgz", + "integrity": "sha512-KaeJvPNofTEZR9EzVNp/GQzbQqkGfjiu6k3CXKvhVTX+8OoAKSX/k7qxLKOX3B0yh2XqVAc93rsOu48CGt2Qug==", + "dev": true, + "dependencies": { + "@shikijs/engine-oniguruma": "^3.6.0", + "@shikijs/langs": "^3.6.0", + "@shikijs/themes": "^3.6.0", + "@shikijs/types": "^3.6.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, "node_modules/@github/catalyst": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/@github/catalyst/-/catalyst-1.7.0.tgz", @@ -11431,6 +11450,50 @@ "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", "dev": true }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.6.0.tgz", + "integrity": "sha512-nmOhIZ9yT3Grd+2plmW/d8+vZ2pcQmo/UnVwXMUXAKTXdi+LK0S08Ancrz5tQQPkxvjBalpMW2aKvwXfelauvA==", + "dev": true, + "dependencies": { + "@shikijs/types": "3.6.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.6.0.tgz", + "integrity": "sha512-IdZkQJaLBu1LCYCwkr30hNuSDfllOT8RWYVZK1tD2J03DkiagYKRxj/pDSl8Didml3xxuyzUjgtioInwEQM/TA==", + "dev": true, + "dependencies": { + "@shikijs/types": "3.6.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.6.0.tgz", + "integrity": "sha512-Fq2j4nWr1DF4drvmhqKq8x5vVQ27VncF8XZMBuHuQMZvUSS3NBgpqfwz/FoGe36+W6PvniZ1yDlg2d4kmYDU6w==", + "dev": true, + "dependencies": { + "@shikijs/types": "3.6.0" + } + }, + "node_modules/@shikijs/types": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.6.0.tgz", + "integrity": "sha512-cLWFiToxYu0aAzJqhXTQsFiJRTFDAGl93IrMSBNaGSzs7ixkLfdG6pH11HipuWFGW5vyx4X47W8HDQ7eSrmBUg==", + "dev": true, + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true + }, "node_modules/@sigstore/bundle": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-3.1.0.tgz", @@ -25443,6 +25506,12 @@ "yallist": "^3.0.2" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/luxon": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.6.1.tgz", @@ -37650,6 +37719,74 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true }, + "node_modules/typedoc": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.5.tgz", + "integrity": "sha512-5PzUddaA9FbaarUzIsEc4wNXCiO4Ot3bJNeMF2qKpYlTmM9TTaSHQ7162w756ERCkXER/+o2purRG6YOAv6EMA==", + "dev": true, + "dependencies": { + "@gerrit0/mini-shiki": "^3.2.2", + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "yaml": "^2.7.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 18", + "pnpm": ">= 10" + }, + "peerDependencies": { + "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x" + } + }, + "node_modules/typedoc-plugin-markdown": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.6.4.tgz", + "integrity": "sha512-AnbToFS1T1H+n40QbO2+i0wE6L+55rWnj7zxnM1r781+2gmhMF2dB6dzFpaylWLQYkbg4D1Y13sYnne/6qZwdw==", + "dev": true, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "typedoc": "0.28.x" + } + }, + "node_modules/typedoc-plugin-merge-modules": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-merge-modules/-/typedoc-plugin-merge-modules-7.0.0.tgz", + "integrity": "sha512-DQyfbbPNBElhpdpGrlkS+CrhGD3iooDjp/PHT8O1D/jumLCB+7XAY3jHiqob7d01o25EfwEOJWVwJK+9J6WlBg==", + "dev": true, + "peerDependencies": { + "typedoc": "0.28.x" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -41067,6 +41204,7 @@ "packages/components": { "name": "@db-ux/core-components", "version": "0.0.0", + "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@db-ux/core-foundations": "*" @@ -41707,7 +41845,7 @@ }, "showcases/next-showcase": { "dependencies": { - "next": "*", + "next": "latest", "react": "18.3.1", "react-dom": "18.3.1" }, diff --git a/package.json b/package.json index 5ccdebdef007..1093a92560a2 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "build-showcases": "npm run build-showcases --workspace=scripts", "clean": "git clean -dfx --exclude=.env", "commit:updated-snapshots": "git diff --name-only --diff-filter=M | xargs git add && git commit -m 'test: updated snapshots'", + "copilot": "npm run copilot --workspace=scripts", "dev": "npm run dev --workspace=scripts", "generate:component": "npm run generate:component --workspace=@db-ux/core-components", "lint": "npm-run-all -p lint:*", @@ -46,6 +47,9 @@ "test:vue-components": "playwright test -c output/vue/playwright.config.ts --ui", "update:dependency:playwright": "node scripts/github/update-playwright.js" }, + "dependencies": { + "fast-glob": "^3.3.3" + }, "devDependencies": { "@angular-devkit/build-angular": "19.2.14", "@angular/animations": "19.2.14", diff --git a/packages/components/.sassdocrc.json b/packages/components/.sassdocrc.json new file mode 100644 index 000000000000..921136c6a420 --- /dev/null +++ b/packages/components/.sassdocrc.json @@ -0,0 +1,7 @@ +{ + "source": { + "include": ["src/components"] + }, + "theme": "markdown", + "dest": "output/css" +} diff --git a/packages/components/configs/mitosis.snippet.config.cjs b/packages/components/configs/mitosis.snippet.config.cjs new file mode 100644 index 000000000000..d7f2cb6320ef --- /dev/null +++ b/packages/components/configs/mitosis.snippet.config.cjs @@ -0,0 +1,29 @@ +module.exports = { + files: 'src/components/**/docs/*.docs.lite.tsx', + targets: ['react', 'angular', 'vue', 'html'], + commonOptions: { + typescript: true, + explicitBuildFileExtensions: { + '.md': /.*(docs\.lite\.tsx)$/g + }, + plugins: [ + () => ({ + name: 'docs-snippet-plugin', + code: { + post: (code, json) => { + const target = json.pluginData.target; + const displayName = json.name.replace(/Docs$/, ''); + + return [ + `# ${displayName} (${target})`, + '', + '```' + target, + code.trim(), + '```' + ].join('\n'); + } + } + }) + ] + } +}; diff --git a/packages/components/package.json b/packages/components/package.json index ed0b861e106c..9e4e088acdc1 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -38,6 +38,8 @@ "dev:vue": "nodemon --watch src --watch scripts -e tsx,ts -x \"npm run compile:vue\"", "generate:component": "hygen mitosis new", "generate:docs": "hygen update-docs new", + "generate:mitosis-snippets": "mitosis build -c configs/mitosis.snippet.config.cjs", + "postinstall": "node ../../scripts/documentation/copy-copilot-instructions.js", "prepack": "npm run copy-assets", "start": "nodemon --watch src --watch scripts --watch scripts -e js,tsx,ts,scss,json -x \"npm run build\"" }, @@ -54,6 +56,7 @@ "hygen": "^6.2.11", "nodemon": "3.1.10", "sass": "1.85.0", + "sassdoc": "^2.7.4", "tsx": "^4.19.4" }, "publishConfig": { diff --git a/packages/components/src/components/button/Button.md b/packages/components/src/components/button/Button.md new file mode 100644 index 000000000000..a415972e6c14 --- /dev/null +++ b/packages/components/src/components/button/Button.md @@ -0,0 +1,53 @@ +# Button Component + +A standardized button component with support for visual variants, sizes, and optional icons. + +## Variants + +- **brand**: Primary action button with filled background. +- **outlined**: Secondary button with border and transparent background. +- **ghost**: Text-only button without background or border. +- **ugly**: Deprecated variant, use `ghost` instead. + +## Sizes + +- **medium** (default) +- **small** + +## CSS Classes & Data Attributes + +```html + +``` + +- `.db-button` +- `data-variant="brand|outlined|ghost"` +- `data-size="small|medium"` + +## Properties / API + +| Property | Type | Default | Description | +| --------- | --------- | ------------ | ------------------------------------------------ | +| `variant` | `string` | `"outlined"` | Visual style: `"brand"`, `"outlined"`, `"ghost"` | +| `size` | `string` | `"medium"` | Button size: `"small"`, `"medium"` | +| `icon` | `string` | `null` | Optional icon name displayed before text | +| `noText` | `boolean` | `false` | If true, only the icon is displayed | + +## Example (React) + +```jsx +import { DBButton } from "@db-ux/react-core-components"; + +function App() { + return ( + <> + console.log("Clicked")}> + Save + + + Cancel + + + ); +} +``` diff --git a/packages/components/src/components/button/button.lite.tsx b/packages/components/src/components/button/button.lite.tsx index 73b33c3a9228..7c6b8ca742f7 100644 --- a/packages/components/src/components/button/button.lite.tsx +++ b/packages/components/src/components/button/button.lite.tsx @@ -9,6 +9,10 @@ import type { DBButtonProps, DBButtonState } from './model'; import { cls, getBoolean, getBooleanAsString, getHideProp } from '../../utils'; import { ClickEvent } from '../../shared/model'; +/** + * @module Button + */ + useMetadata({ angular: { nativeAttributes: ['disabled'] @@ -17,8 +21,31 @@ useMetadata({ useDefaultProps({}); +/** + * Renders a configurable button element that works across multiple frameworks. + * + * @remarks + * This component supports different variants, sizes, icons, and ARIA attributes. + * Use it for primary, secondary, or icon-only actions. + * + * @param props - {@link DBButtonProps} defining the button’s behavior and appearance. + * @returns A ` - -``` diff --git a/packages/components/src/components/button/docs/Migration.md b/packages/components/src/components/button/docs/Migration.md deleted file mode 100644 index e0ca07338335..000000000000 --- a/packages/components/src/components/button/docs/Migration.md +++ /dev/null @@ -1,36 +0,0 @@ -## General - -> **Note** -> For a general installation or migration process check out this [documentation](https://www.npmjs.com/package/@db-ux/core-components). - -## DB UI Core ➡ DB UX Design System Core components - -### class - -| Before | Status | After | Description | -| ------------ | :----: | ----------- | ----------- | -| `elm-button` | 🔁 | `db-button` | | - -### sizes - -| Before | Status | After | Description | -| --------- | :----: | :---: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `large` | ❌ | ❌ | it became obsolete mainly due to our [density](https://marketingportal.extranet.deutschebahn.com/marketingportal/Design-Anwendungen/db-ux-design-system-v3/principles/densities) introduction | -| `regular` | ❌ | ❌ | there is a default (`medium`) now | - -### variants - -| Before | Status | After | Description | -| ------------------- | :----: | ---------- | ------------------------------------------------------------ | -| `primary` | ❌ | ❌ | not valid anymore, use `outlined` buttons for those purposes | -| `brand-primary` | 🔁 | `primary` | | -| `secondary-outline` | 🔁 | `outlined` | | -| `secondary-solid` | 🔁 | `solid` | | -| `tertiary-plain` | 🔁 | `text` | | - -### icons - -| Before | Status | After | Description | -| ----------- | :----: | -------- | ----------------------------------------------------------------- | -| `iconAfter` | ❌ | ❌ | not valid anymore, for buttons only icons before text are allowed | -| `iconOnly` | 🔁 | `noText` | | diff --git a/packages/components/src/components/button/docs/React.md b/packages/components/src/components/button/docs/React.md deleted file mode 100644 index 8e3a63062b82..000000000000 --- a/packages/components/src/components/button/docs/React.md +++ /dev/null @@ -1,14 +0,0 @@ -## React - -For general installation and configuration take a look at the [react-core-components](https://www.npmjs.com/package/@db-ux/react-core-components) package. - -### Use component - -```tsx App.tsx -// App.tsx -import { DBButton } from "@db-ux/react-core-components"; - -const App = () => Button; - -export default App; -``` diff --git a/packages/components/src/components/button/docs/Vue.md b/packages/components/src/components/button/docs/Vue.md deleted file mode 100644 index 482b30779722..000000000000 --- a/packages/components/src/components/button/docs/Vue.md +++ /dev/null @@ -1,16 +0,0 @@ -## Vue - -For general installation and configuration take a look at the [v-core-components](https://www.npmjs.com/package/@db-ux/v-core-components) package. - -### Use component - -```vue App.vue - - - - -``` diff --git a/packages/components/src/components/button/docs/button.docs.lite.tsx b/packages/components/src/components/button/docs/button.docs.lite.tsx new file mode 100644 index 000000000000..e929da776e1c --- /dev/null +++ b/packages/components/src/components/button/docs/button.docs.lite.tsx @@ -0,0 +1,93 @@ +import { useDefaultProps, useMetadata } from '@builder.io/mitosis'; +import type { DBButtonProps } from '../model'; +import { DBButton } from '../index'; + +export default function ButtonDocs() { + useMetadata({ docs: true }); + + useDefaultProps({ + variant: 'filled', + size: 'medium', + text: 'Click me', + icon: 'check', + disabled: false, + type: 'button', + form: '', + name: 'myButton', + value: 'myValue', + ariaexpanded: false, + ariapressed: false, + noText: false, + width: '200px', + showIcon: true, + label: 'Save changes' + }); + + return ( + <> +

DBButton Documentation Examples

+ +

1. Default Button

+ + +

2. Variants

+ Filled + Outlined + Ghost + Brand + +

3. Sizes

+ Small + Medium + Large + +

4. Loading State

+ Loading + +

5. Icon Only

+ + +

6. Disabled

+ Disabled + +

7. Button Types

+ Type=button + Type=submit + Type=reset + +

8. Form Association

+
+ +
+ + Submit Form + + +

9. Name & Value

+ + Name/Value + + +

10. ARIA Attributes

+ Expanded + Pressed + +

11. Width

+ 100px width + 50% width + +

12. Icon Visibility

+ + Icon Hidden + + +

13. Custom Class

+ Custom Class + +

14. Click Event

+ alert('Button clicked!')}> + Click Me + + + ); +} diff --git a/packages/components/src/components/button/model.ts b/packages/components/src/components/button/model.ts index 371c1fd1a82e..1b104e8089ee 100644 --- a/packages/components/src/components/button/model.ts +++ b/packages/components/src/components/button/model.ts @@ -10,33 +10,74 @@ import { WidthProps } from '../../shared/model'; +/** + * @module Button + */ + +/** + * Represents the list of possible button variants. + * These variants define the visual style of the button. + * @public + */ export const ButtonVariantList = [ 'outlined', 'brand', 'filled', 'ghost' ] as const; +/** + * Type representing a single button variant. + * It is derived from the `ButtonVariantList` array. + * @public + */ export type ButtonVariantType = (typeof ButtonVariantList)[number]; +/** + * Represents the list of possible button types. + * These types define the behavior of the button. + * @public + */ export const ButtonTypeList = ['button', 'reset', 'submit'] as const; +/** + * Type representing a single button type. + * It is derived from the `ButtonTypeList` array. + * @public + */ export type ButtonTypeType = (typeof ButtonTypeList)[number]; +/** + * Represents the list of possible button states. + * These states define the current status of the button. + * @public + */ export const ButtonStateList = ['loading'] as const; +/** + * Type representing a single button state. + * It is derived from the `ButtonStateList` array. + * @public + */ export type ButtonStateType = (typeof ButtonStateList)[number]; +/** + * Represents the default properties for the DBButton component. + * These properties define the behavior and accessibility attributes of the button. + */ export type DBButtonDefaultProps = { /** * If the button controls a grouping of other elements, the ariaexpanded state [indicates whether the controlled grouping is currently expanded or collapsed](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded). + * @see https://developer.mozilla.org/docs/Web/Accessibility/ARIA/Attributes/aria-expanded */ ariaexpanded?: boolean; /** * Defines the button as a toggle button. The value of [ariapressed describes the state of the button](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-pressed). + * @see https://developer.mozilla.org/docs/Web/Accessibility/ARIA/Attributes/aria-pressed */ ariapressed?: boolean; /** * The disabled attribute can be set to [keep a user from clicking on the button](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#disabled). + * @see https://developer.mozilla.org/docs/Web/HTML/Element/button#disabled */ disabled?: boolean | string; @@ -47,16 +88,18 @@ export type DBButtonDefaultProps = { /** * The label represents the [aria-label attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) value of the button + * @see https://developer.mozilla.org/docs/Web/Accessibility/ARIA/Attributes/aria-label */ label?: string; /** * The name attribute specifies a [name attributes value](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#name) for the button. + * @see https://developer.mozilla.org/docs/Web/HTML/Element/button#name */ name?: string; /** - * Define the text next to the icon specified via the icon Property to get hidden. + * If `true`, hides the text and shows only the icon. */ noText?: boolean | string; @@ -66,7 +109,8 @@ export type DBButtonDefaultProps = { state?: ButtonStateType; /** - * The type attribute specifies the [type of button](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#type). + * The type attribute specifies the type of button. + * @see https://developer.mozilla.org/docs/Web/HTML/Element/button#type */ type?: ButtonTypeType; @@ -81,6 +125,11 @@ export type DBButtonDefaultProps = { variant?: ButtonVariantType | string; }; +/** + * Represents the properties for the `DBButton` component. + * Combines default button properties (`DBButtonDefaultProps`) with global, click event, icon, width, size, show icon, and text-related properties. + * @public + */ export type DBButtonProps = DBButtonDefaultProps & GlobalProps & ClickEventProps & @@ -90,8 +139,18 @@ export type DBButtonProps = DBButtonDefaultProps & ShowIconProps & TextProps; +/** + * Represents the default state of the `DBButton` component. + * Currently, it is an empty object. + * @internal + */ export type DBButtonDefaultState = {}; +/** + * Represents the state for the `DBButton` component. + * Combines the default state (`DBButtonDefaultState`) with global state and click event state properties. + * @internal + */ export type DBButtonState = DBButtonDefaultState & GlobalState & ClickEventState; diff --git a/packages/components/src/components/drawer/drawer.scss b/packages/components/src/components/drawer/drawer.scss index 777574b5e02d..8ca885fa3465 100644 --- a/packages/components/src/components/drawer/drawer.scss +++ b/packages/components/src/components/drawer/drawer.scss @@ -26,6 +26,10 @@ %full-horizontal { &:not([data-width="full"]) { + /// Sets the maximum height of the drawer + /// @propertyname max-block-size + /// @cssprop --db-drawer-max-height + /// @default calc(100% - #{variables.$db-spacing-fixed-xl}) max-block-size: var( --db-drawer-max-height, calc(100% - #{variables.$db-spacing-fixed-xl}) @@ -83,6 +87,10 @@ $spacings: ( .db-drawer-header { // We need this variable to overwrite it inside the header + /// Controls the bottom padding inside the drawer header + /// @propertyname padding-block-end + /// @cssprop --db-drawer-header-padding-block-end + /// @default #{map.get($spacing, "block")} /* stylelint-disable-next-line db-ux/use-spacings */ padding-block-end: var( --db-drawer-header-padding-block-end, @@ -93,6 +101,10 @@ $spacings: ( .db-drawer-content { // We need this variable to overwrite it inside the header + /// Controls left/right padding inside the drawer content area + /// @propertyname padding-inline + /// @cssprop --db-drawer-content-padding-inline + /// @default #{map.get($spacing, "inline")} /* stylelint-disable-next-line db-ux/use-spacings */ padding-inline: var( --db-drawer-content-padding-inline, @@ -129,6 +141,19 @@ $spacings: ( box-shadow: variables.$db-elevation-md; &:not([data-width="full"]) { + /// Sets the maximum width of the drawer + /// and some default values for the drawer + /// @propertyname max-inline-size + /// @cssprop --db-drawer-max-width + /// @default calc(100% - #{variables.$db-spacing-fixed-xl}) + /// + /// @example css - Wide drawer + /// .db-drawer-wide { + /// --db-drawer-max-width: 800px; + /// } + ///
+ /// + ///
max-inline-size: var( --db-drawer-max-width, calc(100% - #{variables.$db-spacing-fixed-xl}) diff --git a/packages/components/tsconfig.typedoc.json b/packages/components/tsconfig.typedoc.json new file mode 100644 index 000000000000..5dec5ee8d36d --- /dev/null +++ b/packages/components/tsconfig.typedoc.json @@ -0,0 +1,21 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "jsx": "react", + "skipLibCheck": true, + "target": "es2015", + "module": "ESNext", + "moduleResolution": "node", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true + }, + "include": ["src/components/**/*.ts", "src/components/**/*.tsx"], + "exclude": [ + "node_modules", + "**/index.ts", + "**/*.spec.ts", + "**/*.spec.tsx", + "**/__snapshots__/**" + ] +} diff --git a/scripts/documentation/README.md b/scripts/documentation/README.md new file mode 100644 index 000000000000..a07d238996a6 --- /dev/null +++ b/scripts/documentation/README.md @@ -0,0 +1,142 @@ +# Generating `copilot-instructions.md` + +This document describes the order in which scripts must be run to produce the `copilot-instructions.md` file, which combines component documentation, code examples and CSS variable references for both Copilot and developers. + +## 1. Generate separate documentation files + +### 1.1 Annotate components and generate component Markdown + +Annotate your components with [JSDoc](https://jsdoc.app/) (classes, properties, etc.) so TypeDoc can pick up API signatures: + +````ts +/** +* Renders a configurable button element that works across multiple frameworks. +* +* @remarks +* Use `DBButton` for primary and secondary actions. Supports variants, sizes, +* icons, loading state, and ARIA helpers for accessibility. +* +* @param props - {@link DBButtonProps | Component props} controlling appearance and behavior. +* @returns A `