From 3342b2af2926936c0dd71ca9d45010f4a16709b8 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 23 Jan 2026 15:10:25 +0000 Subject: [PATCH 01/11] Add new changelog format for BUI Signed-off-by: Charles de Dreuille --- .changeset/README.md | 55 +++++++++++++++ REVIEWING.md | 31 +++++++++ docs-ui/scripts/sync-changelog.mjs | 54 +++++++++++++-- docs-ui/src/utils/types.ts | 1 + packages/ui/CHANGELOG.md | 106 +++++++++++++---------------- 5 files changed, 185 insertions(+), 62 deletions(-) diff --git a/.changeset/README.md b/.changeset/README.md index 4f3b76b096..6c68425e59 100644 --- a/.changeset/README.md +++ b/.changeset/README.md @@ -6,3 +6,58 @@ find the full documentation for it [in our repository](https://github.com/change We have a quick list of common questions to get you started engaging with this project in [our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md) + +--- + +## Backstage UI Changesets + +For `@backstage/ui` changesets, use this format: + +```markdown +--- +'@backstage/ui': patch +--- + +Brief summary + +Optional description with code examples. + +**Migration:** + +Migration instructions (breaking changes only). + +**Affected components:** button, card +``` + +**Required:** + +- End with `**Affected components:**` + comma-separated component names +- For breaking changes: Add `**Migration:**` section +- No headings (`##`, `###`) inside - use bold markers + +**Examples:** + +```markdown +Fixed button hover state + +**Affected components:** button +``` + +````markdown +**BREAKING**: New Table API + +**Migration:** + +Update imports: + +```diff +- import { Table } from '@backstage/ui'; ++ import { Table, type ColumnConfig } from '@backstage/ui'; +``` +```` + +**Affected components:** table + +``` + +``` diff --git a/REVIEWING.md b/REVIEWING.md index 66af880f43..27da917805 100644 --- a/REVIEWING.md +++ b/REVIEWING.md @@ -62,6 +62,37 @@ Some things that changeset should NOT contain are: - Documentation - changesets can describe new features, but it should not be relied on for documenting them. Documentation should either be placed in [TSDoc](https://tsdoc.org) comments, package README, or [./docs/](./docs/). - Diffs of internal code, for example mirroring what the pull request changes _inside_ a plugin rather than public surfaces. This is not of interest to the reader of a package changelog. Sometimes, however, a small and concise diff can be used in a changeset to illustrate changes that the user will have to make in _their own_ Backstage installation as part of an upgrade, specifically when breaking changes are made to a package. +### Backstage UI Changeset Format + +Changesets for `@backstage/ui` must follow a standardized format to enable proper documentation generation. See [`.changeset/README.md`](.changeset/README.md#backstage-ui-changeset-format) for the complete guide. + +**Required structure:** + +```markdown +--- +'@backstage/ui': patch +--- + +Brief one-line summary of the change + +Optional detailed description with any markdown content. + +**Migration:** + +Migration instructions (only for breaking changes) + +**Affected components:** Button, ButtonIcon +``` + +**Key requirements:** + +1. **Affected components marker** - Must end with `**Affected components:**` followed by comma-separated component names +2. **Migration marker** - Use `**Migration:**` (bold, with colon) for breaking changes only +3. **No headings** - Never use `##`, `###`, or `####` inside changeset entries (these break semantic structure when the entry becomes a list item in CHANGELOG.md) +4. **Bold markers** - Use bold text markers, not plain text, for reliable parsing + +These markers enable the documentation system to extract metadata for per-component changelogs and separate migration guides. + ### When is a changeset needed? In general our changeset feedback bot will take care of informing whether a changeset is needed or not, but there are some edge cases. Whether a changeset is needed depends mostly on what files have been changed, but sometimes also on the kind of change that has been made. diff --git a/docs-ui/scripts/sync-changelog.mjs b/docs-ui/scripts/sync-changelog.mjs index 5eab3616dd..d405a74fd9 100644 --- a/docs-ui/scripts/sync-changelog.mjs +++ b/docs-ui/scripts/sync-changelog.mjs @@ -301,9 +301,11 @@ async function parseListItem( // Remove the commit SHA prefix from markdown let description = fullMarkdown.replace(/^-?\s*[a-f0-9]+:\s*/, '').trim(); - // Auto-detect components from "Affected components:" line + // Extract components using bold marker (standard format) let components = []; - const componentMatch = description.match(/Affected components?:\s*([^\n]+)/i); + const componentMatch = description.match( + /\*\*Affected components:\*\*\s*([^\n]+)/, + ); if (componentMatch) { const componentNames = componentMatch[1] .split(',') @@ -314,9 +316,42 @@ async function parseListItem( .map(name => mapComponentName(name, validComponents)) .filter(Boolean); - // Optionally strip "Affected components:" line from description + // Strip "**Affected components:**" line from description description = description - .replace(/\n*Affected components?:[ \t]*[^\n]+/i, '') + .replace(/\n*\*\*Affected components:\*\*[ \t]*[^\n]+/g, '') + .trim(); + } else { + // Fallback: try old format without bold markers + const oldFormatMatch = description.match( + /Affected components?:\s*([^\n]+)/i, + ); + if (oldFormatMatch) { + const componentNames = oldFormatMatch[1] + .split(',') + .map(name => name.trim()) + .filter(Boolean); + + components = componentNames + .map(name => mapComponentName(name, validComponents)) + .filter(Boolean); + + // Strip old format line from description + description = description + .replace(/\n*Affected components?:[ \t]*[^\n]+/i, '') + .trim(); + } + } + + // Extract migration notes using bold marker (standard format) + let migration = null; + const migrationMatch = description.match( + /\*\*Migration:\*\*\s*\n([\s\S]+?)(?=\n\s*$|$)/, + ); + if (migrationMatch) { + migration = migrationMatch[1].trim(); + // Strip migration section from description + description = description + .replace(/\n*\*\*Migration:\*\*[\s\S]+$/, '') .trim(); } @@ -333,6 +368,7 @@ async function parseListItem( components, prs, type, + migration, }; } @@ -467,12 +503,20 @@ async function generateVersionFiles(entries, changelogsDir, dryRun = false) { .replace(/`/g, '\\`') .replace(/\${/g, '\\${'); + // Escape migration notes if present + const migrationStr = entry.migration + ? `migration: \`${entry.migration + .replace(/\\/g, '\\\\') + .replace(/`/g, '\\`') + .replace(/\${/g, '\\${')}\`,\n ` + : ''; + return ` { components: ${componentsStr}, version: '${entry.version}', prs: ${prsStr}, description: \`${descEscaped}\`, - ${typeStr} + ${migrationStr}${typeStr} ${shaStr} }`; }) diff --git a/docs-ui/src/utils/types.ts b/docs-ui/src/utils/types.ts index f2f773ebc2..173dcd4329 100644 --- a/docs-ui/src/utils/types.ts +++ b/docs-ui/src/utils/types.ts @@ -43,4 +43,5 @@ export interface ChangelogProps { prs: string[]; type?: 'breaking' | 'new' | 'fix'; commitSha?: string; + migration?: string; } diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 944c521afa..ae913d5e80 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -13,7 +13,7 @@ New features include unified pagination modes, debounced query changes, stale data preservation during reloads, and row selection with toggle/replace behaviors. - **Migration guide:** + **Migration:** 1. Update imports and use the new `useTable` hook: @@ -43,11 +43,11 @@ + ``` - Affected components: Table, TableRoot, TablePagination + **Affected components:** Table, TableRoot, TablePagination - 95246eb: **Breaking** Updating color tokens to match the new neutral style on different surfaces. - ## Migration notes + **Migration:** There's no direct replacement for the old tint tokens but you can use the new neutral set of color tokens on surface 0 or 1 as a replacement. @@ -64,11 +64,11 @@ - 1880402: Fixes app background color on dark mode. - d2fdded: Added indeterminate state support to the Checkbox component for handling partial selection scenarios like table header checkboxes. - Affected components: Checkbox + **Affected components:** Checkbox - 4fb15d2: Added missing `aria-label` attributes to `SearchField` components in `Select`, `MenuAutocomplete`, and `MenuAutocompleteListbox` to fix accessibility warnings. - Affected components: Select, MenuAutocomplete, MenuAutocompleteListbox + **Affected components:** Select, MenuAutocomplete, MenuAutocompleteListbox - 21c87cc: Fixes disabled state in primary and secondary buttons in Backstage UI. - 9c76682: build(deps-dev): bump `storybook` from 10.1.9 to 10.1.10 @@ -76,29 +76,29 @@ - 133d5c6: Added new Popover component for Backstage UI with automatic overflow handling, and full placement support. Also introduced `--bui-shadow` token for consistent elevation styling across overlay components (Popover, Tooltip, Menu). - 973c839: Fixed Table sorting indicator not being visible when a column is actively sorted. - Affected components: Table, Column + **Affected components:** Table, Column - df40cfc: Fixed Menu component trigger button not toggling correctly. Removed custom click-outside handler that was interfering with React Aria's built-in state management, allowing the menu to properly open and close when clicking the trigger button. - b01ab96: Added support for column width configuration in Table component. Columns now accept `width`, `defaultWidth`, `minWidth`, and `maxWidth` props for responsive layout control. - Affected components: Table, Column + **Affected components:** Table, Column - b4a4911: Fixed SearchField `startCollapsed` prop not working correctly in Backstage UI. The field now properly starts in a collapsed state, expands when clicked and focused, and collapses back when unfocused with no input. Also fixed CSS logic to work correctly in all layout contexts (flex row, flex column, and regular containers). - Affected components: SearchField + **Affected components:** SearchField - b3253b6: Fixed `Link` component causing hard page refreshes for internal routes. The component now properly uses React Router's navigation instead of full page reloads. - fe7fe69: Added support for custom pagination options in `useTable` hook and `Table` component. You can now configure `pageSizeOptions` to customize the page size dropdown, and hook into pagination events via `onPageSizeChange`, `onNextPage`, and `onPreviousPage` callbacks. When `pageSize` doesn't match any option, the first option is used and a warning is logged. - Affected components: Table, TablePagination + **Affected components:** Table, TablePagination - cfac8a4: Fixed missing border styles on table selection cells in multi-select mode. - Affected components: Table + **Affected components:** Table - 2532d2a: Added `className` and `style` props to the `Table` component. - Affected components: Table + **Affected components:** Table ## 0.11.0-next.1 @@ -113,7 +113,7 @@ New features include unified pagination modes, debounced query changes, stale data preservation during reloads, and row selection with toggle/replace behaviors. - **Migration guide:** + **Migration:** 1. Update imports and use the new `useTable` hook: @@ -143,11 +143,11 @@ +
``` - Affected components: Table, TableRoot, TablePagination + **Affected components:** Table, TableRoot, TablePagination - 95246eb: **Breaking** Updating color tokens to match the new neutral style on different surfaces. - ## Migration notes + **Migration:** There's no direct replacement for the old tint tokens but you can use the new neutral set of color tokens on surface 0 or 1 as a replacement. @@ -175,7 +175,7 @@ - 9c76682: build(deps-dev): bump `storybook` from 10.1.9 to 10.1.10 - b4a4911: Fixed SearchField `startCollapsed` prop not working correctly in Backstage UI. The field now properly starts in a collapsed state, expands when clicked and focused, and collapses back when unfocused with no input. Also fixed CSS logic to work correctly in all layout contexts (flex row, flex column, and regular containers). - Affected components: SearchField + **Affected components:** SearchField ## 0.10.0 @@ -183,7 +183,7 @@ - 16543fa: **Breaking change** The `Cell` component has been refactored to be a generic wrapper component that accepts `children` for custom cell content. The text-specific functionality (previously part of `Cell`) has been moved to a new `CellText` component. - ### Migration Guide + **Migration:** If you were using `Cell` with text-specific props (`title`, `description`, `leadingIcon`, `href`), you need to update your code to use `CellText` instead: @@ -219,24 +219,24 @@ - 50b7927: Fixed Checkbox indicator showing checkmark color when unchecked. - Affected components: Checkbox + **Affected components:** Checkbox - 5bacf55: Fixed `ButtonIcon` incorrectly applying `className` to inner elements instead of only the root element. - Affected components: ButtonIcon + **Affected components:** ButtonIcon - b3ad928: Fixed Table Row component to correctly handle cases where no `href` is provided, preventing unnecessary router provider wrapping and fixing the cursor incorrectly showing as a pointer despite the element not being a link. - Affected components: Row + **Affected components:** Row - a20d317: Added row selection support with visual state styling for hover, selected, and pressed states. Fixed checkbox rendering to only show for multi-select toggle mode. - Affected components: Table, TableHeader, Row, Column + **Affected components:** Table, TableHeader, Row, Column - fe7c751: Fixed `useTable` hook to prioritize `providedRowCount` over data length for accurate row count in server-side pagination scenarios. - c145031: Fixed Table column sorting indicator to show up arrow when no sort is active, correctly indicating that clicking will sort ascending. - Affected components: Column + **Affected components:** Column ## 0.10.0-next.1 @@ -244,7 +244,7 @@ - 16543fa: **Breaking change** The `Cell` component has been refactored to be a generic wrapper component that accepts `children` for custom cell content. The text-specific functionality (previously part of `Cell`) has been moved to a new `CellText` component. - ### Migration Guide + **Migration:** If you were using `Cell` with text-specific props (`title`, `description`, `leadingIcon`, `href`), you need to update your code to use `CellText` instead: @@ -280,15 +280,15 @@ - 50b7927: Fixed Checkbox indicator showing checkmark color when unchecked. - Affected components: Checkbox + **Affected components:** Checkbox - 5bacf55: Fixed `ButtonIcon` incorrectly applying `className` to inner elements instead of only the root element. - Affected components: ButtonIcon + **Affected components:** ButtonIcon - a20d317: Added row selection support with visual state styling for hover, selected, and pressed states. Fixed checkbox rendering to only show for multi-select toggle mode. - Affected components: Table, TableHeader, Row, Column + **Affected components:** Table, TableHeader, Row, Column ## 0.9.1-next.0 @@ -296,12 +296,12 @@ - b3ad928: Fixed Table Row component to correctly handle cases where no `href` is provided, preventing unnecessary router provider wrapping and fixing the cursor incorrectly showing as a pointer despite the element not being a link. - Affected components: Row + **Affected components:** Row - fe7c751: Fixed `useTable` hook to prioritize `providedRowCount` over data length for accurate row count in server-side pagination scenarios. - c145031: Fixed Table column sorting indicator to show up arrow when no sort is active, correctly indicating that clicking will sort ascending. - Affected components: Column + **Affected components:** Column ## 0.9.0 @@ -317,7 +317,7 @@ - `large` size **changed from 3rem to 2.5rem** (40px) - New `x-large` size added (3rem / 48px) - Migration: + **Migration:** ```diff # Remove Base UI-specific props @@ -344,7 +344,7 @@ - Data attribute: `data-checked` → `data-selected` - Use without label is no longer supported - Migration examples: + **Migration:** Before: @@ -400,21 +400,15 @@ - b78fc45: **BREAKING**: Changed className prop behavior to augment default styles instead of being ignored or overriding them. - Affected components: - - - Menu, MenuListBox, MenuAutocomplete, MenuAutocompleteListbox, MenuItem, MenuListBoxItem, MenuSection, MenuSeparator - - Switch - - Skeleton - - FieldLabel - - Header, HeaderToolbar - - HeaderPage - - Tabs, TabList, Tab, TabPanel - If you were passing custom className values to any of these components that relied on the previous behavior, you may need to adjust your styles to account for the default classes now being applied alongside your custom classes. + **Affected components:** Menu, MenuListBox, MenuAutocomplete, MenuAutocompleteListbox, MenuItem, MenuListBoxItem, MenuSection, MenuSeparator, Switch, Skeleton, FieldLabel, Header, HeaderToolbar, HeaderPage, Tabs, TabList, Tab, TabPanel + - 83c100e: **BREAKING**: Removed `Collapsible` component. Migrate to `Accordion` or use React Aria `Disclosure`. - ## Migration Path 1: Accordion (Opinionated Styled Component) + **Migration:** + + **Path 1: Accordion (Opinionated Styled Component)** Accordion provides preset styling with a similar component structure. @@ -435,7 +429,7 @@ CSS classes: `.bui-CollapsibleRoot` → `.bui-Accordion`, `.bui-CollapsibleTrigger` → `.bui-AccordionTrigger` (now on heading element), `.bui-CollapsiblePanel` → `.bui-AccordionPanel` - ## Migration Path 2: React Aria Disclosure (Full Customization) + **Path 2: React Aria Disclosure (Full Customization)** For custom styling without preset styles: @@ -452,7 +446,9 @@ Added searchable and multiple selection support to Select component. The component now accepts `searchable`, `selectionMode`, and `searchPlaceholder` props to enable filtering and multi-selection modes. - Migration: If you're using `SelectProps` type directly, update from `SelectProps` to `SelectProps<'single' | 'multiple'>`. Component usage remains backward compatible. + **Migration:** + + If you're using `SelectProps` type directly, update from `SelectProps` to `SelectProps<'single' | 'multiple'>`. Component usage remains backward compatible. ### Patch Changes @@ -483,7 +479,9 @@ - 83c100e: **BREAKING**: Removed `Collapsible` component. Migrate to `Accordion` or use React Aria `Disclosure`. - ## Migration Path 1: Accordion (Opinionated Styled Component) + **Migration:** + + **Path 1: Accordion (Opinionated Styled Component)** Accordion provides preset styling with a similar component structure. @@ -504,7 +502,7 @@ CSS classes: `.bui-CollapsibleRoot` → `.bui-Accordion`, `.bui-CollapsibleTrigger` → `.bui-AccordionTrigger` (now on heading element), `.bui-CollapsiblePanel` → `.bui-AccordionPanel` - ## Migration Path 2: React Aria Disclosure (Full Customization) + **Path 2: React Aria Disclosure (Full Customization)** For custom styling without preset styles: @@ -521,7 +519,9 @@ Added searchable and multiple selection support to Select component. The component now accepts `searchable`, `selectionMode`, and `searchPlaceholder` props to enable filtering and multi-selection modes. - Migration: If you're using `SelectProps` type directly, update from `SelectProps` to `SelectProps<'single' | 'multiple'>`. Component usage remains backward compatible. + **Migration:** + + If you're using `SelectProps` type directly, update from `SelectProps` to `SelectProps<'single' | 'multiple'>`. Component usage remains backward compatible. ### Patch Changes @@ -546,7 +546,7 @@ - `large` size **changed from 3rem to 2.5rem** (40px) - New `x-large` size added (3rem / 48px) - Migration: + **Migration:** ```diff # Remove Base UI-specific props @@ -589,7 +589,7 @@ - Data attribute: `data-checked` → `data-selected` - Use without label is no longer supported - Migration examples: + **Migration:** Before: @@ -633,18 +633,10 @@ - b78fc45: **BREAKING**: Changed className prop behavior to augment default styles instead of being ignored or overriding them. - Affected components: - - - Menu, MenuListBox, MenuAutocomplete, MenuAutocompleteListbox, MenuItem, MenuListBoxItem, MenuSection, MenuSeparator - - Switch - - Skeleton - - FieldLabel - - Header, HeaderToolbar - - HeaderPage - - Tabs, TabList, Tab, TabPanel - If you were passing custom className values to any of these components that relied on the previous behavior, you may need to adjust your styles to account for the default classes now being applied alongside your custom classes. + **Affected components:** Menu, MenuListBox, MenuAutocomplete, MenuAutocompleteListbox, MenuItem, MenuListBoxItem, MenuSection, MenuSeparator, Switch, Skeleton, FieldLabel, Header, HeaderToolbar, HeaderPage, Tabs, TabList, Tab, TabPanel + ### Patch Changes - ff9f0c3: Enable tree-shaking of imports other than `*.css`. From 2f709e15ab55df810cbb311d9f00e59e03d30408 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 23 Jan 2026 18:34:28 +0000 Subject: [PATCH 02/11] Add new changelog structure Signed-off-by: Charles de Dreuille --- .changeset/polite-symbols-act.md | 2 +- docs-ui/package.json | 1 + docs-ui/scripts/sync-changelog.mjs | 70 +-- docs-ui/src/components/Changelog/index.tsx | 162 +++++-- docs-ui/src/css/globals.css | 4 + docs-ui/src/css/mdx.module.css | 5 + docs-ui/src/utils/changelog.ts | 6 + docs-ui/src/utils/changelogs/v0.1.0.ts | 56 +-- docs-ui/src/utils/changelogs/v0.10.0.ts | 150 ++++++ docs-ui/src/utils/changelogs/v0.11.0.ts | 308 +++++++++++++ docs-ui/src/utils/changelogs/v0.2.0.ts | 120 ++--- docs-ui/src/utils/changelogs/v0.2.1.ts | 20 +- docs-ui/src/utils/changelogs/v0.3.0.ts | 319 ++++++++----- docs-ui/src/utils/changelogs/v0.3.2.ts | 4 +- docs-ui/src/utils/changelogs/v0.4.0.ts | 227 ++++++--- docs-ui/src/utils/changelogs/v0.5.0.ts | 174 ++++--- docs-ui/src/utils/changelogs/v0.6.0.ts | 191 ++++---- docs-ui/src/utils/changelogs/v0.7.0.ts | 152 +++--- docs-ui/src/utils/changelogs/v0.7.1.ts | 28 +- docs-ui/src/utils/changelogs/v0.7.2.ts | 46 +- docs-ui/src/utils/changelogs/v0.8.0.ts | 114 ++--- docs-ui/src/utils/changelogs/v0.8.2.ts | 26 +- docs-ui/src/utils/changelogs/v0.9.0.ts | 508 +++++++++++++++------ docs-ui/src/utils/changelogs/v0.9.1.ts | 28 ++ docs-ui/src/utils/types.ts | 2 +- packages/ui/CHANGELOG.md | 151 ++++-- 26 files changed, 2054 insertions(+), 820 deletions(-) create mode 100644 docs-ui/src/utils/changelogs/v0.10.0.ts create mode 100644 docs-ui/src/utils/changelogs/v0.11.0.ts create mode 100644 docs-ui/src/utils/changelogs/v0.9.1.ts diff --git a/.changeset/polite-symbols-act.md b/.changeset/polite-symbols-act.md index 73c7950d80..9c3489f670 100644 --- a/.changeset/polite-symbols-act.md +++ b/.changeset/polite-symbols-act.md @@ -2,7 +2,7 @@ '@backstage/ui': minor --- -**BREAKING (CSS)**: Changed CSS selectors for `ButtonIcon` and `ButtonLink` components. Custom styles targeting `.bui-Button` to style these components must be updated to use `.bui-ButtonIcon` or `.bui-ButtonLink` respectively. +**BREAKING**: Changed CSS selectors for `ButtonIcon` and `ButtonLink` components. Custom styles targeting `.bui-Button` to style these components must be updated to use `.bui-ButtonIcon` or `.bui-ButtonLink` respectively. ```diff -/* This no longer styles ButtonIcon or ButtonLink */ diff --git a/docs-ui/package.json b/docs-ui/package.json index 3fd8d192c4..fe12c6425f 100644 --- a/docs-ui/package.json +++ b/docs-ui/package.json @@ -10,6 +10,7 @@ "start": "next dev", "sync:changelog": "node scripts/sync-changelog.mjs", "sync:changelog:dry-run": "node scripts/sync-changelog.mjs --dry-run", + "sync:changelog:force": "node scripts/sync-changelog.mjs --force", "sync:css": "node scripts/sync-css.js", "sync:css:watch": "node scripts/sync-css.js --watch" }, diff --git a/docs-ui/scripts/sync-changelog.mjs b/docs-ui/scripts/sync-changelog.mjs index d405a74fd9..0c51a67f6b 100644 --- a/docs-ui/scripts/sync-changelog.mjs +++ b/docs-ui/scripts/sync-changelog.mjs @@ -348,7 +348,12 @@ async function parseListItem( /\*\*Migration:\*\*\s*\n([\s\S]+?)(?=\n\s*$|$)/, ); if (migrationMatch) { - migration = migrationMatch[1].trim(); + // Clean up indentation from list format (remove leading 2 spaces from each line) + migration = migrationMatch[1] + .split('\n') + .map(line => line.replace(/^ /, '')) + .join('\n') + .trim(); // Strip migration section from description description = description .replace(/\n*\*\*Migration:\*\*[\s\S]+$/, '') @@ -357,8 +362,8 @@ async function parseListItem( const prs = []; // Will be populated later by fetchPRNumbers() - // Infer type from section and description - const type = inferChangeType(section, description, version); + // Check if this is a breaking change + const breaking = isBreakingChange(section, description, version); return { version: normalizeVersion(version), @@ -367,7 +372,7 @@ async function parseListItem( description, components, prs, - type, + breaking, migration, }; } @@ -375,27 +380,18 @@ async function parseListItem( /** * Infer change type from section and description */ -function inferChangeType(section, description, version) { - const isPre1 = version.startsWith('0.'); - - // Check description keywords first - if (description.match(/^(New|Add(ed)?)\s/i)) { - return 'new'; - } +function isBreakingChange(section, description, version) { + // Mark as breaking if explicitly mentioned in description if (description.includes('BREAKING')) { - return 'breaking'; + return true; } - // Infer from section - if (section === 'Minor Changes') { - return isPre1 ? 'breaking' : undefined; - } else if (section === 'Major Changes') { - return 'breaking'; - } else if (section === 'Patch Changes') { - return 'fix'; + // Or if it's in the Major or Minor Changes section + if (section === 'Major Changes' || section === 'Minor Changes') { + return true; } - return undefined; + return false; } /** @@ -450,7 +446,12 @@ async function fetchPRNumbers(entries, dryRun = false) { /** * Generate per-version changelog files in changelogs/ directory */ -async function generateVersionFiles(entries, changelogsDir, dryRun = false) { +async function generateVersionFiles( + entries, + changelogsDir, + dryRun = false, + force = false, +) { // Group entries by normalized version const byVersion = {}; entries.forEach(entry => { @@ -470,8 +471,8 @@ async function generateVersionFiles(entries, changelogsDir, dryRun = false) { const filePath = path.join(changelogsDir, fileName); const varName = `changelog_${version.replace(/\./g, '_')}`; - // Check if file already exists - skip if it does - if (fs.existsSync(filePath)) { + // Check if file already exists - skip if it does (unless force flag) + if (fs.existsSync(filePath) && !force) { skippedVersions.push(version); // Still add to versionFiles array so main changelog.ts can import it versionFiles.push({ @@ -492,7 +493,7 @@ async function generateVersionFiles(entries, changelogsDir, dryRun = false) { .map(c => `'${c}'`) .join(', ')}]`; const prsStr = `[${entry.prs.map(pr => `'${pr}'`).join(', ')}]`; - const typeStr = entry.type ? `type: '${entry.type}',` : ''; + const breakingStr = entry.breaking ? `breaking: true,` : ''; const shaStr = entry.commitSha ? `commitSha: '${entry.commitSha}',` : ''; @@ -516,7 +517,7 @@ async function generateVersionFiles(entries, changelogsDir, dryRun = false) { version: '${entry.version}', prs: ${prsStr}, description: \`${descEscaped}\`, - ${migrationStr}${typeStr} + ${migrationStr}${breakingStr} ${shaStr} }`; }) @@ -846,6 +847,7 @@ async function findPRNumber(commitSha) { async function main() { const args = process.argv.slice(2); const dryRun = args.includes('--dry-run'); + const force = args.includes('--force'); const changelogTsPath = path.join(__dirname, '../src/utils/changelog.ts'); const changelogMdPath = path.join( @@ -862,10 +864,15 @@ async function main() { } console.log('📋 Syncing UI component changelogs...\n'); + if (force) { + console.log('⚠️ Force mode: Will overwrite existing version files\n'); + } - // Get last synced version - const lastVersion = getLastSyncedVersion(changelogTsPath); - console.log(`Last synced version: ${lastVersion || '(none)'}`); + // Get last synced version (null if force mode to process all) + const lastVersion = force ? null : getLastSyncedVersion(changelogTsPath); + console.log( + `Last synced version: ${lastVersion || '(none - processing all versions)'}`, + ); // Get valid components const validComponents = getValidComponents(changelogTsPath); @@ -878,7 +885,11 @@ async function main() { lastVersion, validComponents, ); - console.log(`Found ${allEntries.length} total entries since ${lastVersion}`); + console.log( + `Found ${allEntries.length} total entries${ + force ? '' : ` since ${lastVersion}` + }`, + ); // Read existing changelog content for duplicate detection const existingContent = fs.readFileSync(changelogTsPath, 'utf-8'); @@ -964,6 +975,7 @@ async function main() { relevantEntries, changelogsDir, dryRun, + force, ); // Generate main changelog.ts diff --git a/docs-ui/src/components/Changelog/index.tsx b/docs-ui/src/components/Changelog/index.tsx index d7a547b901..b38972259a 100644 --- a/docs-ui/src/components/Changelog/index.tsx +++ b/docs-ui/src/components/Changelog/index.tsx @@ -2,7 +2,53 @@ import { changelog } from '@/utils/changelog'; import { MDXRemote } from 'next-mdx-remote-client/rsc'; import { formattedMDXComponents } from '@/mdx-components'; +const Badge = ({ + children, + variant = 'gray', +}: { + children: React.ReactNode; + variant?: 'red' | 'gray'; +}) => { + const colors = { + red: { + backgroundColor: 'var(--badge-red-bg)', + color: 'var(--badge-red-color)', + }, + gray: { + backgroundColor: 'var(--badge-gray-bg)', + color: 'var(--badge-gray-color)', + }, + }; + + return ( + + {children} + + ); +}; + +const BreakingBadge = () => Breaking; + export function Changelog() { + // Convert kebab-case to Title Case + const toTitleCase = (kebabCase: string) => { + return kebabCase + .split('-') + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + }; + // Group changelog entries by version const groupedChangelog = changelog.reduce((acc, entry) => { if (!acc[entry.version]) { @@ -12,44 +58,50 @@ export function Changelog() { return acc; }, {} as Record); - // Sort versions in descending order - const sortedVersions = Object.keys(groupedChangelog).sort((a, b) => - b.localeCompare(a), - ); + // Sort versions in descending order (semantic versioning) + const sortedVersions = Object.keys(groupedChangelog).sort((a, b) => { + const aParts = a.split('.').map(Number); + const bParts = b.split('.').map(Number); + + for (let i = 0; i < 3; i++) { + if (bParts[i] !== aParts[i]) { + return bParts[i] - aParts[i]; // Descending order + } + } + return 0; + }); const content = sortedVersions .map(version => { const entries = groupedChangelog[version]; - // Group entries by bump type - const groupedByBump = entries.reduce((acc, entry) => { - const bumpType = entry.type || 'other'; - if (!acc[bumpType]) { - acc[bumpType] = []; - } - acc[bumpType].push(entry); - return acc; - }, {} as Record); + // Group entries: Breaking vs Everything Else + const breakingChanges = entries.filter(e => e.breaking); + const otherChanges = entries.filter(e => !e.breaking); - // Define the order of bump types - const bumpOrder = ['breaking', 'new', 'fix', 'other']; + const sections = []; - const bumpSections = bumpOrder - .filter(bumpType => groupedByBump[bumpType]?.length > 0) - .map(bumpType => { - const bumpEntries = groupedByBump[bumpType]; - let sectionTitle = 'Other Changes'; - if (bumpType === 'breaking') { - sectionTitle = 'Breaking Changes'; - } else if (bumpType === 'new') { - sectionTitle = 'New Features'; - } else if (bumpType === 'fix') { - sectionTitle = 'Bug Fixes'; - } + // Breaking changes section + if (breakingChanges.length > 0) { + sections.push({ + title: 'Breaking Changes', + entries: breakingChanges, + }); + } - return `### ${sectionTitle} - - ${bumpEntries + // All other changes section + if (otherChanges.length > 0) { + sections.push({ + title: 'Changes', + entries: otherChanges, + }); + } + + const bumpSections = sections + .map(({ title, entries: bumpEntries }) => { + const sectionTitle = title; + + const entriesMarkdown = bumpEntries .map(e => { const prs = e.prs.length > 0 @@ -60,9 +112,44 @@ export function Changelog() { ) .join(', ') : ''; - return `- ${e.description}${prs ? ` ${prs}` : ''}`; + + // Prepend component names as badges if available + const componentBadges = + e.components.length > 0 + ? e.components + .map( + c => `${toTitleCase(c)}`, + ) + .join(' ') + ' ' + : ''; + + // Add breaking badge if this is a breaking change + const breakingBadge = e.breaking ? ' ' : ''; + + // Remove **BREAKING**: text from description since we show it as a badge + let description = e.description.replace( + /\*\*BREAKING\*\*:?\s*/, + '', + ); + + // Description already has proper indentation from CHANGELOG + let entry = `- ${componentBadges}${breakingBadge}${description}`; + if (prs) { + entry += ` ${prs}`; + } + + // Add migration if present (should already be in description, but check) + if (e.migration && !e.description.includes('**Migration:**')) { + entry += `\n\n Migration Guide:\n\n ${e.migration + .split('\n') + .join('\n ')}`; + } + + return entry; }) - .join('\n')}`; + .join('\n\n'); + + return `### ${sectionTitle}\n\n${entriesMarkdown}`; }) .join('\n\n'); @@ -72,5 +159,14 @@ export function Changelog() { }) .join('\n'); - return ; + return ( + + ); } diff --git a/docs-ui/src/css/globals.css b/docs-ui/src/css/globals.css index dcc348a9ee..407138fd61 100644 --- a/docs-ui/src/css/globals.css +++ b/docs-ui/src/css/globals.css @@ -17,6 +17,10 @@ --surface-1: #f4f4f4; --code-bg: #3e444f; --code-title: #505865; + --badge-red-bg: color(display-p3 0.831 0.184 0.012/0.091); + --badge-red-color: color(display-p3 0.755 0.259 0.152); + --badge-gray-bg: #dee3ec; + --badge-gray-color: #35363d; } [data-theme-mode='dark'] { diff --git a/docs-ui/src/css/mdx.module.css b/docs-ui/src/css/mdx.module.css index 7a3821891f..ea6e3c6549 100644 --- a/docs-ui/src/css/mdx.module.css +++ b/docs-ui/src/css/mdx.module.css @@ -40,6 +40,11 @@ color: var(--primary); margin-bottom: 0.5rem; line-height: 1.5; + padding-left: 0.4rem; +} + +.li::marker { + color: var(--text-secondary); } .a { diff --git a/docs-ui/src/utils/changelog.ts b/docs-ui/src/utils/changelog.ts index 0c3286d051..a99c0e8335 100644 --- a/docs-ui/src/utils/changelog.ts +++ b/docs-ui/src/utils/changelog.ts @@ -1,4 +1,7 @@ export * from './types'; +import { changelog_0_11_0 } from './changelogs/v0.11.0'; +import { changelog_0_10_0 } from './changelogs/v0.10.0'; +import { changelog_0_9_1 } from './changelogs/v0.9.1'; import { changelog_0_9_0 } from './changelogs/v0.9.0'; import { changelog_0_8_2 } from './changelogs/v0.8.2'; import { changelog_0_8_0 } from './changelogs/v0.8.0'; @@ -15,6 +18,9 @@ import { changelog_0_2_0 } from './changelogs/v0.2.0'; import { changelog_0_1_0 } from './changelogs/v0.1.0'; export const changelog = [ + ...changelog_0_11_0, + ...changelog_0_10_0, + ...changelog_0_9_1, ...changelog_0_9_0, ...changelog_0_8_2, ...changelog_0_8_0, diff --git a/docs-ui/src/utils/changelogs/v0.1.0.ts b/docs-ui/src/utils/changelogs/v0.1.0.ts index cf333e92e9..c93e2c3a5a 100644 --- a/docs-ui/src/utils/changelogs/v0.1.0.ts +++ b/docs-ui/src/utils/changelogs/v0.1.0.ts @@ -4,113 +4,113 @@ export const changelog_0_1_0: ChangelogProps[] = [ { components: [], version: '0.1.0', - description: `**BREAKING**: Merged the Stack and Inline component into a single component called Flex.`, prs: ['28634'], - type: 'breaking', + description: `**BREAKING**: Merged the Stack and Inline component into a single component called Flex.`, + breaking: true, commitSha: '72c9800', }, { components: [], version: '0.1.0', - description: `This is the first alpha release for Canon. As part of this release we are introducing 5 layout components and 7 components. All theming is done through CSS variables.`, prs: ['28562'], - type: 'breaking', + description: `**BREAKING**: This is the first alpha release for Canon. As part of this release we are introducing 5 layout components and 7 components. All theming is done through CSS variables.`, + breaking: true, commitSha: '65f4acc', }, { components: [], version: '0.1.0', - description: `**BREAKING**: Fixing css structure and making sure that props are applying the correct styles for all responsive values.`, prs: ['28630'], - type: 'breaking', + description: `**BREAKING**: Fixing css structure and making sure that props are applying the correct styles for all responsive values.`, + breaking: true, commitSha: '1e4ccce', }, { components: [], version: '0.1.0', - description: `Updated core CSS tokens and fixing the Button component accordingly.`, prs: ['28789'], - type: 'breaking', + description: `**BREAKING**: Updated core CSS tokens and fixing the Button component accordingly.`, + breaking: true, commitSha: '8309bdb', }, { components: [], version: '0.1.0', - description: `Removed client directive as they are not needed in React 18.`, prs: ['28626'], - type: 'fix', + description: `Removed client directive as they are not needed in React 18.`, + commitSha: '989af25', }, { components: [], version: '0.1.0', - description: `Fix spacing props not being applied for custom values.`, prs: ['28770'], - type: 'fix', + description: `Fix spacing props not being applied for custom values.`, + commitSha: 'f44e5cf', }, { components: [], version: '0.1.0', - description: `Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.`, prs: ['28579'], - type: 'fix', + description: `Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.`, + commitSha: '58ec9e7', }, { components: [], version: '0.1.0', - description: `Updated core CSS tokens and fixing the Button component accordingly.`, prs: ['28789'], - type: 'breaking', + description: `Updated core CSS tokens and fixing the Button component accordingly.`, + breaking: true, commitSha: '8309bdb', }, { components: [], version: '0.1.0', - description: `Fix spacing props not being applied for custom values.`, prs: ['28770'], - type: 'fix', + description: `Fix spacing props not being applied for custom values.`, + commitSha: 'f44e5cf', }, { components: [], version: '0.1.0', - description: `**BREAKING**: Merged the Stack and Inline component into a single component called Flex.`, prs: ['28634'], - type: 'breaking', + description: `**BREAKING**: Merged the Stack and Inline component into a single component called Flex.`, + breaking: true, commitSha: '72c9800', }, { components: [], version: '0.1.0', - description: `**BREAKING**: Fixing css structure and making sure that props are applying the correct styles for all responsive values.`, prs: ['28630'], - type: 'breaking', + description: `**BREAKING**: Fixing css structure and making sure that props are applying the correct styles for all responsive values.`, + breaking: true, commitSha: '1e4ccce', }, { components: [], version: '0.1.0', - description: `Removed client directive as they are not needed in React 18.`, prs: ['28626'], - type: 'fix', + description: `Removed client directive as they are not needed in React 18.`, + commitSha: '989af25', }, { components: [], version: '0.1.0', - description: `Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.`, prs: ['28579'], - type: 'fix', + description: `Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.`, + commitSha: '58ec9e7', }, { components: [], version: '0.1.0', - description: `This is the first alpha release for Canon. As part of this release we are introducing 5 layout components and 7 components. All theming is done through CSS variables.`, prs: ['28562'], - type: 'breaking', + description: `This is the first alpha release for Canon. As part of this release we are introducing 5 layout components and 7 components. All theming is done through CSS variables.`, + breaking: true, commitSha: '65f4acc', }, ]; diff --git a/docs-ui/src/utils/changelogs/v0.10.0.ts b/docs-ui/src/utils/changelogs/v0.10.0.ts new file mode 100644 index 0000000000..4df6785bfb --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.10.0.ts @@ -0,0 +1,150 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_10_0: ChangelogProps[] = [ + { + components: [], + version: '0.10.0', + prs: ['31917'], + description: `**BREAKING**: The \`Cell\` component has been refactored to be a generic wrapper component that accepts \`children\` for custom cell content. The text-specific functionality (previously part of \`Cell\`) has been moved to a new \`CellText\` component.`, + migration: `If you were using \`Cell\` with text-specific props (\`title\`, \`description\`, \`leadingIcon\`, \`href\`), you need to update your code to use \`CellText\` instead: + +**Before:** + +\`\`\`tsx +} + href="/path" +/> +\`\`\` + +**After:** + +\`\`\`tsx +} + href="/path" +/> +\`\`\` + +For custom cell content, use the new generic \`Cell\` component: + +\`\`\`tsx +{/* Your custom content */} +\`\`\``, + breaking: true, + commitSha: '16543fa', + }, + { + components: ['checkbox'], + version: '0.10.0', + prs: ['31904'], + description: `Fixed Checkbox indicator showing checkmark color when unchecked.`, + + commitSha: '50b7927', + }, + { + components: ['button-icon'], + version: '0.10.0', + prs: ['31900'], + description: `Fixed \`ButtonIcon\` incorrectly applying \`className\` to inner elements instead of only the root element.`, + + commitSha: '5bacf55', + }, + { + components: [], + version: '0.10.0', + prs: ['31843'], + description: `Fixed Table Row component to correctly handle cases where no \`href\` is provided, preventing unnecessary router provider wrapping and fixing the cursor incorrectly showing as a pointer despite the element not being a link.`, + + commitSha: 'b3ad928', + }, + { + components: ['table'], + version: '0.10.0', + prs: ['31907'], + description: `Added row selection support with visual state styling for hover, selected, and pressed states. Fixed checkbox rendering to only show for multi-select toggle mode.`, + + commitSha: 'a20d317', + }, + { + components: [], + version: '0.10.0', + prs: ['31817'], + description: `Fixed \`useTable\` hook to prioritize \`providedRowCount\` over data length for accurate row count in server-side pagination scenarios.`, + + commitSha: 'fe7c751', + }, + { + components: [], + version: '0.10.0', + prs: ['31844'], + description: `Fixed Table column sorting indicator to show up arrow when no sort is active, correctly indicating that clicking will sort ascending.`, + + commitSha: 'c145031', + }, + { + components: [], + version: '0.10.0', + prs: ['31917'], + description: `**BREAKING**: The \`Cell\` component has been refactored to be a generic wrapper component that accepts \`children\` for custom cell content. The text-specific functionality (previously part of \`Cell\`) has been moved to a new \`CellText\` component.`, + migration: `If you were using \`Cell\` with text-specific props (\`title\`, \`description\`, \`leadingIcon\`, \`href\`), you need to update your code to use \`CellText\` instead: + +**Before:** + +\`\`\`tsx +} + href="/path" +/> +\`\`\` + +**After:** + +\`\`\`tsx +} + href="/path" +/> +\`\`\` + +For custom cell content, use the new generic \`Cell\` component: + +\`\`\`tsx +{/* Your custom content */} +\`\`\``, + breaking: true, + commitSha: '16543fa', + }, + { + components: ['checkbox'], + version: '0.10.0', + prs: ['31904'], + description: `Fixed Checkbox indicator showing checkmark color when unchecked.`, + + commitSha: '50b7927', + }, + { + components: ['button-icon'], + version: '0.10.0', + prs: ['31900'], + description: `Fixed \`ButtonIcon\` incorrectly applying \`className\` to inner elements instead of only the root element.`, + + commitSha: '5bacf55', + }, + { + components: ['table'], + version: '0.10.0', + prs: ['31907'], + description: `Added row selection support with visual state styling for hover, selected, and pressed states. Fixed checkbox rendering to only show for multi-select toggle mode.`, + + commitSha: 'a20d317', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.11.0.ts b/docs-ui/src/utils/changelogs/v0.11.0.ts new file mode 100644 index 0000000000..680037774f --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.11.0.ts @@ -0,0 +1,308 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_11_0: ChangelogProps[] = [ + { + components: ['table'], + version: '0.11.0', + prs: ['32050'], + description: `**BREAKING**: Redesigned Table component with new \`useTable\` hook API. + + - The \`Table\` component (React Aria wrapper) is renamed to \`TableRoot\` + - New high-level \`Table\` component that handles data display, pagination, sorting, and selection + - The \`useTable\` hook is completely redesigned with a new API supporting three pagination modes (complete, offset, cursor) + - New types: \`ColumnConfig\`, \`TableProps\`, \`TableItem\`, \`UseTableOptions\`, \`UseTableResult\` + + New features include unified pagination modes, debounced query changes, stale data preservation during reloads, and row selection with toggle/replace behaviors.`, + migration: `1. Update imports and use the new \`useTable\` hook: + +\`\`\`diff +-import { Table, useTable } from '@backstage/ui'; +-const { data, paginationProps } = useTable({ data: items, pagination: {...} }); ++import { Table, useTable, type ColumnConfig } from '@backstage/ui'; ++const { tableProps } = useTable({ ++ mode: 'complete', ++ getData: () => items, ++}); +\`\`\` + +2. Define columns and render with the new Table API: + +\`\`\`diff +-
+- ... +- ... +-
+- ++const columns: ColumnConfig[] = [ ++ { id: 'name', label: 'Name', isRowHeader: true, cell: item => }, ++ { id: 'type', label: 'Type', cell: item => }, ++]; ++ ++ +\`\`\``, + breaking: true, + commitSha: '243e5e7', + }, + { + components: [], + version: '0.11.0', + prs: ['32202'], + description: `**BREAKING**: Updating color tokens to match the new neutral style on different surfaces.`, + migration: `There's no direct replacement for the old tint tokens but you can use the new neutral set of color tokens on surface 0 or 1 as a replacement. + +- \`--bui-bg-tint\` can be replaced by \`--bui-bg-neutral-on-surface-0\` +- \`--bui-bg-tint-hover\` can be replaced by \`--bui-bg-neutral-on-surface-0-hover\` +- \`--bui-bg-tint-pressed\` can be replaced by \`--bui-bg-neutral-on-surface-0-pressed\` +- \`--bui-bg-tint-disabled\` can be replaced by \`--bui-bg-neutral-on-surface-0-disabled\``, + breaking: true, + commitSha: '95246eb', + }, + { + components: [], + version: '0.11.0', + prs: ['32232'], + description: `**BREAKING**: Introduce new \`ToggleButton\` & \`ToggleButtonGroup\` components in Backstage UI`, + breaking: true, + commitSha: 'ea0c6d8', + }, + { + components: [], + version: '0.11.0', + prs: ['32200'], + description: `**BREAKING**: Renamed CSS variable \`--bui-bg\` to \`--bui-bg-surface-0\` for consistency.`, + breaking: true, + commitSha: '4ea1d15', + }, + { + components: ['box'], + version: '0.11.0', + prs: ['32203'], + description: `Fixes app background color on dark mode.`, + + commitSha: '1880402', + }, + { + components: ['checkbox'], + version: '0.11.0', + prs: ['32371'], + description: `Added indeterminate state support to the Checkbox component for handling partial selection scenarios like table header checkboxes.`, + + commitSha: 'd2fdded', + }, + { + components: ['select'], + version: '0.11.0', + prs: ['32337'], + description: `Added missing \`aria-label\` attributes to \`SearchField\` components in \`Select\`, \`MenuAutocomplete\`, and \`MenuAutocompleteListbox\` to fix accessibility warnings.`, + + commitSha: '4fb15d2', + }, + { + components: ['button'], + version: '0.11.0', + prs: ['32297'], + description: `Fixes disabled state in primary and secondary buttons in Backstage UI.`, + + commitSha: '21c87cc', + }, + { + components: [], + version: '0.11.0', + prs: ['32185'], + description: `build(deps-dev): bump \`storybook\` from 10.1.9 to 10.1.10`, + + commitSha: '9c76682', + }, + { + components: ['button'], + version: '0.11.0', + prs: ['32385'], + description: `Fixed disabled tertiary buttons incorrectly showing hover effects on surfaces.`, + + commitSha: 'de80336', + }, + { + components: [], + version: '0.11.0', + prs: ['32313'], + description: `Added new Popover component for Backstage UI with automatic overflow handling, and full placement support. Also introduced \`--bui-shadow\` token for consistent elevation styling across overlay components (Popover, Tooltip, Menu).`, + + commitSha: '133d5c6', + }, + { + components: ['table'], + version: '0.11.0', + prs: ['32350'], + description: `Fixed Table sorting indicator not being visible when a column is actively sorted.`, + + commitSha: '973c839', + }, + { + components: ['menu'], + version: '0.11.0', + prs: ['32347'], + description: `Fixed Menu component trigger button not toggling correctly. Removed custom click-outside handler that was interfering with React Aria's built-in state management, allowing the menu to properly open and close when clicking the trigger button.`, + + commitSha: 'df40cfc', + }, + { + components: ['table'], + version: '0.11.0', + prs: ['32336'], + description: `Added support for column width configuration in Table component. Columns now accept \`width\`, \`defaultWidth\`, \`minWidth\`, and \`maxWidth\` props for responsive layout control.`, + + commitSha: 'b01ab96', + }, + { + components: ['searchfield'], + version: '0.11.0', + prs: ['32123'], + description: `Fixed SearchField \`startCollapsed\` prop not working correctly in Backstage UI. The field now properly starts in a collapsed state, expands when clicked and focused, and collapses back when unfocused with no input. Also fixed CSS logic to work correctly in all layout contexts (flex row, flex column, and regular containers).`, + + commitSha: 'b4a4911', + }, + { + components: [], + version: '0.11.0', + prs: ['32265'], + description: `Fixed \`Link\` component causing hard page refreshes for internal routes. The component now properly uses React Router's navigation instead of full page reloads.`, + + commitSha: 'b3253b6', + }, + { + components: ['table'], + version: '0.11.0', + prs: ['32321'], + description: `Added support for custom pagination options in \`useTable\` hook and \`Table\` component. You can now configure \`pageSizeOptions\` to customize the page size dropdown, and hook into pagination events via \`onPageSizeChange\`, \`onNextPage\`, and \`onPreviousPage\` callbacks. When \`pageSize\` doesn't match any option, the first option is used and a warning is logged.`, + + commitSha: 'fe7fe69', + }, + { + components: ['table'], + version: '0.11.0', + prs: ['32369'], + description: `Fixed missing border styles on table selection cells in multi-select mode.`, + + commitSha: 'cfac8a4', + }, + { + components: ['table'], + version: '0.11.0', + prs: ['32342'], + description: `Added \`className\` and \`style\` props to the \`Table\` component.`, + + commitSha: '2532d2a', + }, + { + components: ['table'], + version: '0.11.0', + prs: ['32050'], + description: `**BREAKING**: Redesigned Table component with new \`useTable\` hook API. + + - The \`Table\` component (React Aria wrapper) is renamed to \`TableRoot\` + - New high-level \`Table\` component that handles data display, pagination, sorting, and selection + - The \`useTable\` hook is completely redesigned with a new API supporting three pagination modes (complete, offset, cursor) + - New types: \`ColumnConfig\`, \`TableProps\`, \`TableItem\`, \`UseTableOptions\`, \`UseTableResult\` + + New features include unified pagination modes, debounced query changes, stale data preservation during reloads, and row selection with toggle/replace behaviors.`, + migration: `1. Update imports and use the new \`useTable\` hook: + +\`\`\`diff +-import { Table, useTable } from '@backstage/ui'; +-const { data, paginationProps } = useTable({ data: items, pagination: {...} }); ++import { Table, useTable, type ColumnConfig } from '@backstage/ui'; ++const { tableProps } = useTable({ ++ mode: 'complete', ++ getData: () => items, ++}); +\`\`\` + +2. Define columns and render with the new Table API: + +\`\`\`diff +-
+- ... +- ... +-
+- ++const columns: ColumnConfig[] = [ ++ { id: 'name', label: 'Name', isRowHeader: true, cell: item => }, ++ { id: 'type', label: 'Type', cell: item => }, ++]; ++ ++ +\`\`\``, + breaking: true, + commitSha: '243e5e7', + }, + { + components: [], + version: '0.11.0', + prs: ['32202'], + description: `**BREAKING**: Updating color tokens to match the new neutral style on different surfaces.`, + migration: `There's no direct replacement for the old tint tokens but you can use the new neutral set of color tokens on surface 0 or 1 as a replacement. + +- \`--bui-bg-tint\` can be replaced by \`--bui-bg-neutral-on-surface-0\` +- \`--bui-bg-tint-hover\` can be replaced by \`--bui-bg-neutral-on-surface-0-hover\` +- \`--bui-bg-tint-pressed\` can be replaced by \`--bui-bg-neutral-on-surface-0-pressed\` +- \`--bui-bg-tint-disabled\` can be replaced by \`--bui-bg-neutral-on-surface-0-disabled\``, + breaking: true, + commitSha: '95246eb', + }, + { + components: [], + version: '0.11.0', + prs: ['32232'], + description: `Introduce new \`ToggleButton\` & \`ToggleButtonGroup\` components in Backstage UI`, + breaking: true, + commitSha: 'ea0c6d8', + }, + { + components: [], + version: '0.11.0', + prs: ['32297'], + description: `Fixes disabled state in primary and secondary buttons in Backstage UI.`, + + commitSha: '21c87cc', + }, + { + components: [], + version: '0.11.0', + prs: ['32265'], + description: `Fixed \`Link\` component causing hard page refreshes for internal routes. The component now properly uses React Router's navigation instead of full page reloads.`, + + commitSha: 'b3253b6', + }, + { + components: [], + version: '0.11.0', + prs: ['32200'], + description: `**BREAKING**: Renamed CSS variable \`--bui-bg\` to \`--bui-bg-surface-0\` for consistency.`, + breaking: true, + commitSha: '4ea1d15', + }, + { + components: [], + version: '0.11.0', + prs: ['32203'], + description: `Fixes app background color on dark mode.`, + + commitSha: '1880402', + }, + { + components: [], + version: '0.11.0', + prs: ['32185'], + description: `build(deps-dev): bump \`storybook\` from 10.1.9 to 10.1.10`, + + commitSha: '9c76682', + }, + { + components: ['searchfield'], + version: '0.11.0', + prs: ['32123'], + description: `Fixed SearchField \`startCollapsed\` prop not working correctly in Backstage UI. The field now properly starts in a collapsed state, expands when clicked and focused, and collapses back when unfocused with no input. Also fixed CSS logic to work correctly in all layout contexts (flex row, flex column, and regular containers).`, + + commitSha: 'b4a4911', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.2.0.ts b/docs-ui/src/utils/changelogs/v0.2.0.ts index b90cec0309..383a16afb0 100644 --- a/docs-ui/src/utils/changelogs/v0.2.0.ts +++ b/docs-ui/src/utils/changelogs/v0.2.0.ts @@ -2,97 +2,115 @@ import type { ChangelogProps } from '../types'; export const changelog_0_2_0: ChangelogProps[] = [ { - components: ['menu'], + components: [], version: '0.2.0', - description: 'New `Menu` component', - prs: ['29151'], - type: 'new', + prs: ['28961'], + description: `**BREAKING**: Fix CSS imports and move CSS outputs out of the dist folder.`, + breaking: true, + commitSha: '5a5db29', }, { - components: ['button-icon'], + components: [], + version: '0.2.0', + prs: ['29241'], + description: `**BREAKING**: Added a new Tooltip component to Canon.`, + breaking: true, + commitSha: '4557beb', + }, + { + components: [], version: '0.2.0', - description: 'New `IconButton` component', prs: ['29239'], - type: 'new', + description: `**BREAKING**: We added a new IconButton component with fixed sizes showcasing a single icon.`, + breaking: true, + commitSha: '1e4dfdb', }, { - components: ['scrollarea'], + components: [], version: '0.2.0', - description: 'New `ScrollArea` component', - prs: ['29240'], - type: 'new', - }, - { - components: ['button', 'checkbox'], - version: '0.2.0', - description: 'Improve `Button` & `Checkbox` styles', - prs: ['29127', '28789'], - }, - { - components: ['text'], - version: '0.2.0', - description: 'Improve `Text` styles', - prs: ['29200'], - }, - { - components: ['icon'], - version: '0.2.0', - description: 'Renamed `CanonProvider` to `IconProvider`', - prs: ['29002'], - }, - { - components: ['icon'], - version: '0.2.0', - description: 'Added about 40+ new icons', prs: ['29264'], + description: `**BREAKING**: Added about 40 new icons to Canon.`, + breaking: true, + commitSha: 'e8d12f9', }, { components: [], version: '0.2.0', - description: 'Simplified styling into a unique styles.css file', - prs: ['29199'], + prs: ['29002'], + description: `**BREAKING**: We are renaming CanonProvider to IconProvider to improve clarity on how to override icons.`, + breaking: true, + commitSha: '8689010', }, { components: [], version: '0.2.0', - description: 'Added global styles to Backstage', - prs: ['29137'], - type: 'new', + prs: ['29151'], + description: `**BREAKING**: Added a new Menu component to Canon.`, + breaking: true, + commitSha: 'bf319b7', }, { components: [], version: '0.2.0', - description: 'Update global CSS tokens', - prs: ['28804'], + prs: ['29200'], + description: `**BREAKING**: Updating styles for Text and Link components as well as global surface tokens.`, + breaking: true, + commitSha: 'cb7e99d', }, { - components: ['flex'], + components: [], version: '0.2.0', - description: 'Merge Stack + Inline into Flex', - prs: ['28634'], + prs: ['29240'], + description: `**BREAKING**: Added a new ScrollArea component for Canon.`, + breaking: true, + commitSha: 'bd8520d', }, { - components: ['button'], + components: [], version: '0.2.0', - description: 'Improve `Button` types', prs: ['29205'], + description: `Fix Button types that was preventing the use of native attributes like onClick.`, + + commitSha: '56850ca', }, { components: [], version: '0.2.0', - description: 'Move font weight and family back to each components', prs: ['28972'], + description: `To avoid conflicts with Backstage, we removed global styles and set font-family and font-weight for each components.`, + + commitSha: '89e8686', }, { components: [], version: '0.2.0', - description: 'Fix custom values in spacing props', - prs: ['28770'], + prs: ['29137'], + description: `Introducing Canon to Backstage. Canon styling system is based on pure CSS. We are adding our styles.css at the top of your Backstage instance.`, + + commitSha: '05e9d41', }, { components: [], version: '0.2.0', - description: 'Multiple updates on the docs site', - prs: ['28760'], + prs: ['29002'], + description: `We are renaming CanonProvider to IconProvider to improve clarity on how to override icons.`, + breaking: true, + commitSha: '8689010', + }, + { + components: [], + version: '0.2.0', + prs: ['28972'], + description: `To avoid conflicts with Backstage, we removed global styles and set font-family and font-weight for each components.`, + + commitSha: '89e8686', + }, + { + components: [], + version: '0.2.0', + prs: ['28961'], + description: `Fix CSS imports and move CSS outputs out of the dist folder.`, + breaking: true, + commitSha: '5a5db29', }, ]; diff --git a/docs-ui/src/utils/changelogs/v0.2.1.ts b/docs-ui/src/utils/changelogs/v0.2.1.ts index cbf0f9be0f..0815a886c3 100644 --- a/docs-ui/src/utils/changelogs/v0.2.1.ts +++ b/docs-ui/src/utils/changelogs/v0.2.1.ts @@ -4,41 +4,41 @@ export const changelog_0_2_1: ChangelogProps[] = [ { components: [], version: '0.2.1', - description: `Internal refactor and fixes to the prop extraction logic for layout components.`, prs: ['29389'], - type: 'fix', + description: `Internal refactor and fixes to the prop extraction logic for layout components.`, + commitSha: 'f7cb538', }, { components: [], version: '0.2.1', - description: `Fix types on the Icon component.`, prs: ['29306'], - type: 'fix', + description: `Fix types on the Icon component.`, + commitSha: '5e80f0b', }, { components: [], version: '0.2.1', - description: `Updated styles for the Menu component in Canon.`, prs: ['29351'], - type: 'fix', + description: `Updated styles for the Menu component in Canon.`, + commitSha: '6af7b16', }, { components: [], version: '0.2.1', - description: `Add global CSS reset for anchor tags.`, prs: ['29357'], - type: 'new', + description: `Add global CSS reset for anchor tags.`, + commitSha: '513477f', }, { components: [], version: '0.2.1', - description: `Fix the Icon component when the name is not found to return null instead of an empty SVG.`, prs: ['29280'], - type: 'fix', + description: `Fix the Icon component when the name is not found to return null instead of an empty SVG.`, + commitSha: '05a5003', }, ]; diff --git a/docs-ui/src/utils/changelogs/v0.3.0.ts b/docs-ui/src/utils/changelogs/v0.3.0.ts index 750ad292cf..eec2590e91 100644 --- a/docs-ui/src/utils/changelogs/v0.3.0.ts +++ b/docs-ui/src/utils/changelogs/v0.3.0.ts @@ -1,139 +1,240 @@ import type { ChangelogProps } from '../types'; export const changelog_0_3_0: ChangelogProps[] = [ - { - components: ['datatable'], - version: '0.3.0', - description: 'Add `DataTable` component', - prs: ['29484', '29603'], - type: 'new', - }, - { - components: ['select'], - version: '0.3.0', - description: 'Add `Select` component', - prs: ['29440'], - type: 'new', - }, - { - components: ['avatar'], - version: '0.3.0', - description: 'Add `Avatar` component', - prs: ['29594'], - type: 'new', - }, - { - components: ['collapsible'], - version: '0.3.0', - description: 'Add `Collapsible` component', - prs: ['29617'], - type: 'new', - }, - { - components: ['textfield'], - version: '0.3.0', - description: 'Add `TextField` component instead of `Field` + `Input`', - prs: ['29364'], - type: 'new', - }, - { - components: ['datatable'], - version: '0.3.0', - description: 'Add `TableCellProfile`', - prs: ['29600'], - type: 'new', - }, { components: [], version: '0.3.0', - description: 'Add breakpoint hooks - `up()` and `down()`', - prs: ['29564'], - type: 'new', - }, - { - components: [], - version: '0.3.0', - description: 'Add gray scale css tokens', - prs: ['29543'], - type: 'new', - }, - { - components: [], - version: '0.3.0', - description: - 'Update CSS styling API using `[data-___]` instead of class names for props', prs: ['29560'], + description: `**BREAKING**: Improve class name structure using data attributes instead of class names.`, + breaking: true, + commitSha: 'df4e292', }, { - components: ['checkbox'], + components: [], version: '0.3.0', - description: 'Update `Checkbox` dark mode', - prs: ['29544'], - }, - { - components: ['container'], - version: '0.3.0', - description: 'Update `Container` styles', - prs: ['29475'], - }, - { - components: ['menu'], - version: '0.3.0', - description: 'Update `Menu` styles', - prs: ['29351'], - }, - { - components: ['select'], - version: '0.3.0', - description: 'Fix `Select` styles on small sizes + with long option names', - prs: ['29545'], - }, - { - components: ['link'], - version: '0.3.0', - description: 'Fix render prop on `Link`', - prs: ['29247'], - }, - { - components: ['textfield', 'select'], - version: '0.3.0', - description: 'Remove `Field` from `TextField` + `Select`', prs: ['29482'], - }, - { - components: ['text', 'heading'], - version: '0.3.0', - description: 'Update `textDecoration` to `none` on `Text` / `Heading`', - prs: ['29357'], - }, - { - components: ['text', 'heading'], - version: '0.3.0', - description: 'Update `textDecoration` to `none` on `Text` / `Heading`', - prs: ['29357'], + description: `**BREAKING**: Updated TextField and Select component to work with React Hook Form.`, + breaking: true, + commitSha: 'f038613', + }, + { + components: [], + version: '0.3.0', + prs: ['29440'], + description: `**BREAKING**: Add new Select component for Canon`, + breaking: true, + commitSha: '1b0cf40', + }, + { + components: [], + version: '0.3.0', + prs: ['29364'], + description: `**BREAKING**: Added a new TextField component to replace the Field and Input component. After feedback, it became clear that we needed to build a more opinionated version to avoid any problem in the future.`, + breaking: true, + commitSha: '5074d61', + }, + { + components: [], + version: '0.3.0', + prs: ['29351'], + description: `Updated styles for the Menu component in Canon.`, + + commitSha: '6af7b16', + }, + { + components: [], + version: '0.3.0', + prs: ['29544'], + description: `Fix Checkbox styles on dark theme in Canon.`, + + commitSha: 'bcbc593', + }, + { + components: [], + version: '0.3.0', + prs: ['29564'], + description: `Add new breakpoint helpers up(), down() and current breakpoint to help you use our breakpoints in your React components.`, + + commitSha: 'e7efb7d', + }, + { + components: [], + version: '0.3.0', + prs: ['29389'], + description: `Internal refactor and fixes to the prop extraction logic for layout components.`, + + commitSha: 'f7cb538', + }, + { + components: [], + version: '0.3.0', + prs: ['29617'], + description: `Add new Collapsible component for Canon.`, + + commitSha: '35b36ec', + }, + { + components: [], + version: '0.3.0', + prs: ['29499'], + description: `Removes instances of default React imports, a necessary update for the upcoming React 19 migration. + + https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html`, + + commitSha: 'a47fd39', + }, + { + components: [], + version: '0.3.0', + prs: ['29357'], + description: `Add global CSS reset for anchor tags.`, + + commitSha: '513477f', + }, + { + components: [], + version: '0.3.0', + prs: ['29475'], + description: `Improved Container styles, changing our max-width to 120rem and improving padding on smaller screens.`, + + commitSha: '24f0e08', + }, + { + components: [], + version: '0.3.0', + prs: ['29594'], + description: `Add new Avatar component to Canon.`, + + commitSha: '851779d', + }, + { + components: [], + version: '0.3.0', + prs: ['29600'], + description: `Add new TableCellProfile component for Table and DataTable in Canon.`, + + commitSha: 'ec5ebd1', }, { components: [], version: '0.3.0', - description: 'Docs - Use stories from Storybook for all examples in Nextjs', prs: ['29306'], + description: `Fix types on the Icon component.`, + + commitSha: '5e80f0b', }, { components: [], version: '0.3.0', - description: 'Docs - Add release page (this one 🤗)', - prs: ['29461'], + prs: ['29484'], + description: `Add new DataTable component and update Table component styles.`, + + commitSha: '0e654bf', }, { components: [], version: '0.3.0', - description: 'Docs - Add docs for Menu, Link', - prs: ['29576'], + prs: ['29466'], + description: `Move styles to the root of the TextField component.`, + + commitSha: '7ae28ba', }, { components: [], version: '0.3.0', - description: 'Fix CSS watch mode', - prs: ['29352'], + prs: ['29247'], + description: `We added a render prop to the Link component to make sure it can work with React Router.`, + + commitSha: '4fe5b08', + }, + { + components: [], + version: '0.3.0', + prs: ['29545'], + description: `Fix Select styles on small sizes + with long option names in Canon.`, + + commitSha: '74d463c', + }, + { + components: [], + version: '0.3.0', + prs: ['29543'], + description: `Added a new gray scale for Canon for both light and dark theme.`, + + commitSha: 'f25a5be', + }, + { + components: [], + version: '0.3.0', + prs: ['29603'], + description: `Add support for column sizing in DataTable.`, + + commitSha: '5ee4fc2', + }, + { + components: [], + version: '0.3.0', + prs: ['29280'], + description: `Fix the Icon component when the name is not found to return null instead of an empty SVG.`, + + commitSha: '05a5003', + }, + { + components: [], + version: '0.3.0', + prs: ['29482'], + description: `Updated TextField and Select component to work with React Hook Form.`, + breaking: true, + commitSha: 'f038613', + }, + { + components: [], + version: '0.3.0', + prs: ['29440'], + description: `Add new Select component for Canon`, + breaking: true, + commitSha: '1b0cf40', + }, + { + components: [], + version: '0.3.0', + prs: ['29364'], + description: `**BREAKING**: Added a new TextField component to replace the Field and Input component. After feedback, it became clear that we needed to build a more opinionated version to avoid any problem in the future.`, + breaking: true, + commitSha: '5074d61', + }, + { + components: [], + version: '0.3.0', + prs: ['29499'], + description: `Removes instances of default React imports, a necessary update for the upcoming React 19 migration. + + https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html`, + + commitSha: 'a47fd39', + }, + { + components: [], + version: '0.3.0', + prs: ['29475'], + description: `Improved Container styles, changing our max-width to 120rem and improving padding on smaller screens.`, + + commitSha: '24f0e08', + }, + { + components: [], + version: '0.3.0', + prs: ['29466'], + description: `Move styles to the root of the TextField component.`, + + commitSha: '7ae28ba', + }, + { + components: [], + version: '0.3.0', + prs: ['29247'], + description: `We added a render prop to the Link component to make sure it can work with React Router.`, + + commitSha: '4fe5b08', }, ]; diff --git a/docs-ui/src/utils/changelogs/v0.3.2.ts b/docs-ui/src/utils/changelogs/v0.3.2.ts index 26dd225299..93ae7f7e63 100644 --- a/docs-ui/src/utils/changelogs/v0.3.2.ts +++ b/docs-ui/src/utils/changelogs/v0.3.2.ts @@ -4,9 +4,9 @@ export const changelog_0_3_2: ChangelogProps[] = [ { components: [], version: '0.3.2', - description: `Fix Canon missing dependencies`, prs: ['29642'], - type: 'fix', + description: `Fix Canon missing dependencies`, + commitSha: 'e996368', }, ]; diff --git a/docs-ui/src/utils/changelogs/v0.4.0.ts b/docs-ui/src/utils/changelogs/v0.4.0.ts index 91cd641f4d..014679ae33 100644 --- a/docs-ui/src/utils/changelogs/v0.4.0.ts +++ b/docs-ui/src/utils/changelogs/v0.4.0.ts @@ -2,86 +2,179 @@ import type { ChangelogProps } from '../types'; export const changelog_0_4_0: ChangelogProps[] = [ { - components: ['tabs'], + components: [], version: '0.4.0', - description: 'New `Tabs` component', - prs: ['29996'], - type: 'new', - }, - { - components: ['text', 'heading'], - version: '0.4.0', - description: 'Add `truncate` prop to `Text` and `Heading`', - prs: ['29988'], - type: 'new', - }, - { - components: ['menu'], - version: '0.4.0', - description: 'Add combobox option to `Menu`', - prs: ['29986'], - type: 'new', - }, - { - components: ['textfield'], - version: '0.4.0', - description: 'Add icon prop on `TextField`', - prs: ['29820'], - type: 'new', - }, - { - components: ['button', 'button-icon'], - version: '0.4.0', - description: 'Improve icon props on `Button` and `IconButton`', prs: ['29667'], - }, - { - components: ['text', 'heading'], - version: '0.4.0', - description: - 'Improve the way we treat custom render on `Text` and `Heading`', - prs: ['29989'], - }, - { - components: ['menu'], - version: '0.4.0', - description: 'Improve `Menu` styles', - prs: ['29986'], - }, - { - components: ['textfield'], - version: '0.4.0', - description: 'Improve `TextField` styles', - prs: ['29974'], - }, - { - components: ['textfield'], - version: '0.4.0', - description: 'Improve clear button on `TextField`', - prs: ['29878'], - }, - { - components: ['flex'], - version: '0.4.0', - description: 'Fix spacing props on all layout components', - prs: ['30013'], + description: `**BREAKING**: Icons on Button and IconButton now need to be imported and placed like this: \`} /> +- Content +- - - - - } /> - - Content - - ++ ++ ++ Content ++ +\`\`\` - + - + - + Content - + - \`\`\` +CSS classes: \`.bui-CollapsibleRoot\` → \`.bui-Accordion\`, \`.bui-CollapsibleTrigger\` → \`.bui-AccordionTrigger\` (now on heading element), \`.bui-CollapsiblePanel\` → \`.bui-AccordionPanel\` - CSS classes: \`.bui-CollapsibleRoot\` → \`.bui-Accordion\`, \`.bui-CollapsibleTrigger\` → \`.bui-AccordionTrigger\` (now on heading element), \`.bui-CollapsiblePanel\` → \`.bui-AccordionPanel\` +**Path 2: React Aria Disclosure (Full Customization)** - ## Migration Path 2: React Aria Disclosure (Full Customization) +For custom styling without preset styles: - For custom styling without preset styles: +\`\`\`tsx +import { Disclosure, Button, DisclosurePanel } from 'react-aria-components'; - \`\`\`tsx - import { Disclosure, Button, DisclosurePanel } from 'react-aria-components'; - - - - Content - ; - \`\`\``, - type: 'breaking', + + + Content +; +\`\`\``, + breaking: true, commitSha: '83c100e', }, { @@ -185,10 +165,9 @@ export const changelog_0_9_0: ChangelogProps[] = [ prs: ['31649'], description: `**BREAKING**: The \`SelectProps\` interface now accepts a generic type parameter for selection mode. - Added searchable and multiple selection support to Select component. The component now accepts \`searchable\`, \`selectionMode\`, and \`searchPlaceholder\` props to enable filtering and multi-selection modes. - - Migration: If you're using \`SelectProps\` type directly, update from \`SelectProps\` to \`SelectProps<'single' | 'multiple'>\`. Component usage remains backward compatible.`, - type: 'breaking', + Added searchable and multiple selection support to Select component. The component now accepts \`searchable\`, \`selectionMode\`, and \`searchPlaceholder\` props to enable filtering and multi-selection modes.`, + migration: `If you're using \`SelectProps\` type directly, update from \`SelectProps\` to \`SelectProps<'single' | 'multiple'>\`. Component usage remains backward compatible.`, + breaking: true, commitSha: '816af0f', }, { @@ -196,7 +175,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31525'], description: `Fix broken external links in Backstage UI Header component.`, - type: 'fix', + commitSha: 'd01de00', }, { @@ -204,23 +183,23 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31618'], description: `Fixed CSS issues in Select component including popover width constraints, focus outline behavior, and overflow handling.`, - type: 'fix', + commitSha: '35a3614', }, { - components: ['password-field', 'searchfield', 'menu'], + components: ['password-field', 'searchfield'], version: '0.9.0', prs: ['31679'], description: `Improved visual consistency of PasswordField, SearchField, and MenuAutocomplete components.`, - type: 'fix', + commitSha: '01476f0', }, { - components: [], + components: ['text'], version: '0.9.0', prs: ['31429'], description: `Fix default text color in Backstage UI`, - type: 'fix', + commitSha: '26c6a78', }, { @@ -228,7 +207,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31615'], description: `Fixed Text component to prevent \`truncate\` prop from being spread to the underlying DOM element.`, - type: 'fix', + commitSha: 'deaa427', }, { @@ -236,7 +215,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31524'], description: `Improved the Link component structure in Backstage UI.`, - type: 'fix', + commitSha: '1059f95', }, { @@ -244,15 +223,15 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31673'], description: `Fixed dialog backdrop appearance in dark mode.`, - type: 'fix', + commitSha: '836b0c7', }, { - components: ['table', 'avatar'], + components: ['avatar'], version: '0.9.0', prs: ['31608'], description: `Migrated CellProfile component from Base UI Avatar to Backstage UI Avatar component.`, - type: 'fix', + commitSha: '6874094', }, { @@ -260,7 +239,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31623'], description: `Avatar components in x-small and small sizes now display only one initial instead of two, improving readability at smaller dimensions.`, - type: 'fix', + commitSha: '719d772', }, { @@ -268,7 +247,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31672'], description: `Removed \`@base-ui-components/react\` dependency as all components now use React Aria Components.`, - type: 'fix', + commitSha: '6d35a6b', }, { @@ -276,7 +255,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31435'], description: `Fix the default font size in Backstage UI.`, - type: 'fix', + commitSha: 'dac851f', }, { @@ -284,15 +263,15 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31448'], description: `Fix CSS layer ordering in Backstage UI to make sure component styles are loaded after tokens and base declarations.`, - type: 'fix', + commitSha: '3c0ea67', }, { - components: ['radiogroup'], + components: ['radio-group'], version: '0.9.0', prs: ['31576'], description: `Fixed RadioGroup radio button ellipse distortion by preventing flex shrink and grow.`, - type: 'fix', + commitSha: '3b18d80', }, { @@ -300,7 +279,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31444'], description: `Fix font smoothing as default in Backstage UI.`, - type: 'fix', + commitSha: '4eb455c', }, { @@ -308,7 +287,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31516'], description: `Enable tree-shaking of imports other than \`*.css\`.`, - type: 'fix', + commitSha: 'ff9f0c3', }, { @@ -316,7 +295,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31681'], description: `Added \`loading\` prop to Button and ButtonIcon components for displaying spinner during async operations.`, - type: 'new', + commitSha: '7839e7b', }, { @@ -324,7 +303,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31680'], description: `Fixed Table Row component to properly support opening links in new tabs via right-click or Cmd+Click when using the \`href\` prop.`, - type: 'fix', + commitSha: 'a00fb88', }, { @@ -332,7 +311,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31469'], description: `Set the color-scheme property depending on theme`, - type: 'fix', + commitSha: 'e16ece5', }, { @@ -340,7 +319,7 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31484'], description: `Added new VisuallyHidden component for hiding content visually while keeping it accessible to screen readers.`, - type: 'new', + commitSha: '1ef3ca4', }, { @@ -348,7 +327,282 @@ export const changelog_0_9_0: ChangelogProps[] = [ version: '0.9.0', prs: ['31432'], description: `Fix default font wight and font family in Backstage UI.`, - type: 'fix', + commitSha: '00bfb83', }, + { + components: [], + version: '0.9.0', + prs: ['31493'], + description: `**BREAKING**: Removed \`Collapsible\` component. Migrate to \`Accordion\` or use React Aria \`Disclosure\`.`, + migration: `**Path 1: Accordion (Opinionated Styled Component)** + +Accordion provides preset styling with a similar component structure. + +\`\`\`diff +- import { Collapsible } from '@backstage/ui'; ++ import { Accordion, AccordionTrigger, AccordionPanel } from '@backstage/ui'; + +- +- } /> +- Content +- + ++ ++ ++ Content ++ +\`\`\` + +CSS classes: \`.bui-CollapsibleRoot\` → \`.bui-Accordion\`, \`.bui-CollapsibleTrigger\` → \`.bui-AccordionTrigger\` (now on heading element), \`.bui-CollapsiblePanel\` → \`.bui-AccordionPanel\` + +**Path 2: React Aria Disclosure (Full Customization)** + +For custom styling without preset styles: + +\`\`\`tsx +import { Disclosure, Button, DisclosurePanel } from 'react-aria-components'; + + + + Content +; +\`\`\``, + breaking: true, + commitSha: '83c100e', + }, + { + components: [], + version: '0.9.0', + prs: ['31649'], + description: `**BREAKING**: The \`SelectProps\` interface now accepts a generic type parameter for selection mode. + + Added searchable and multiple selection support to Select component. The component now accepts \`searchable\`, \`selectionMode\`, and \`searchPlaceholder\` props to enable filtering and multi-selection modes.`, + migration: `If you're using \`SelectProps\` type directly, update from \`SelectProps\` to \`SelectProps<'single' | 'multiple'>\`. Component usage remains backward compatible.`, + breaking: true, + commitSha: '816af0f', + }, + { + components: [], + version: '0.9.0', + prs: ['31618'], + description: `Fixed CSS issues in Select component including popover width constraints, focus outline behavior, and overflow handling.`, + + commitSha: '35a3614', + }, + { + components: [], + version: '0.9.0', + prs: ['31679'], + description: `Improved visual consistency of PasswordField, SearchField, and MenuAutocomplete components.`, + + commitSha: '01476f0', + }, + { + components: [], + version: '0.9.0', + prs: ['31673'], + description: `Fixed dialog backdrop appearance in dark mode.`, + + commitSha: '836b0c7', + }, + { + components: [], + version: '0.9.0', + prs: ['31672'], + description: `Removed \`@base-ui-components/react\` dependency as all components now use React Aria Components.`, + + commitSha: '6d35a6b', + }, + { + components: [], + version: '0.9.0', + prs: ['31681'], + description: `Added \`loading\` prop to Button and ButtonIcon components for displaying spinner during async operations.`, + + commitSha: '7839e7b', + }, + { + components: [], + version: '0.9.0', + prs: ['31680'], + description: `Fixed Table Row component to properly support opening links in new tabs via right-click or Cmd+Click when using the href prop.`, + + commitSha: 'a00fb88', + }, + { + components: [], + version: '0.9.0', + prs: ['31566'], + description: `**BREAKING**: Migrated Avatar component from Base UI to custom implementation with size changes: + + - Base UI-specific props are no longer supported + - Size values have been updated: + - New \`x-small\` size added (1.25rem / 20px) + - \`small\` size unchanged (1.5rem / 24px) + - \`medium\` size unchanged (2rem / 32px, default) + - \`large\` size **changed from 3rem to 2.5rem** (40px) + - New \`x-large\` size added (3rem / 48px)`, + migration: `\`\`\`diff +# Remove Base UI-specific props +- ++ + +# Update large size usage to x-large for same visual size +- ++ +\`\`\` + +Added \`purpose\` prop for accessibility control (\`'informative'\` or \`'decoration'\`).`, + breaking: true, + commitSha: '539cf26', + }, + { + components: [], + version: '0.9.0', + prs: ['31507'], + description: `**BREAKING**: Fixing styles on SearchField in Backstage UI after migration to CSS modules. \`SearchField\` has now its own set of class names. We previously used class names from \`TextField\` but this approach was creating some confusion so going forward in your theme you'll be able to theme \`TextField\` and \`SearchField\` separately.`, + breaking: true, + commitSha: '134151f', + }, + { + components: [], + version: '0.9.0', + prs: ['31525'], + description: `Fix broken external links in Backstage UI Header component.`, + + commitSha: 'd01de00', + }, + { + components: [], + version: '0.9.0', + prs: ['31615'], + description: `Fixed Text component to prevent \`truncate\` prop from being spread to the underlying DOM element.`, + + commitSha: 'deaa427', + }, + { + components: [], + version: '0.9.0', + prs: ['31524'], + description: `Improved the Link component structure in Backstage UI.`, + + commitSha: '1059f95', + }, + { + components: [], + version: '0.9.0', + prs: ['31608'], + description: `Migrated CellProfile component from Base UI Avatar to Backstage UI Avatar component.`, + + commitSha: '6874094', + }, + { + components: [], + version: '0.9.0', + prs: ['31623'], + description: `Avatar components in x-small and small sizes now display only one initial instead of two, improving readability at smaller dimensions.`, + + commitSha: '719d772', + }, + { + components: [], + version: '0.9.0', + prs: ['31576'], + description: `Fixed RadioGroup radio button ellipse distortion by preventing flex shrink and grow.`, + + commitSha: '3b18d80', + }, + { + components: [], + version: '0.9.0', + prs: ['31469'], + description: `Set the color-scheme property depending on theme`, + + commitSha: 'e16ece5', + }, + { + components: [], + version: '0.9.0', + prs: ['31517'], + description: `**BREAKING**: Migrated Checkbox component from Base UI to React Aria Components. + + API changes required: + + - \`checked\` → \`isSelected\` + - \`defaultChecked\` → \`defaultSelected\` + - \`disabled\` → \`isDisabled\` + - \`required\` → \`isRequired\` + - \`label\` prop removed - use \`children\` instead + - CSS: \`bui-CheckboxLabel\` class removed + - Data attribute: \`data-checked\` → \`data-selected\` + - Use without label is no longer supported`, + migration: `Before: + +\`\`\`tsx + +\`\`\` + +After: + +\`\`\`tsx + + Accept terms + +\`\`\` + +Before: + +\`\`\`tsx + +\`\`\` + +After: + +\`\`\`tsx +Option +\`\`\` + +Before: + +\`\`\`tsx + +\`\`\` + +After: + +\`\`\`tsx + + Accessible label + +\`\`\``, + breaking: true, + commitSha: '5c614ff', + }, + { + components: ['menu', 'switch', 'skeleton', 'header', 'header-page', 'tabs'], + version: '0.9.0', + prs: ['31496'], + description: `**BREAKING**: Changed className prop behavior to augment default styles instead of being ignored or overriding them. + + If you were passing custom className values to any of these components that relied on the previous behavior, you may need to adjust your styles to account for the default classes now being applied alongside your custom classes.`, + breaking: true, + commitSha: 'b78fc45', + }, + { + components: [], + version: '0.9.0', + prs: ['31516'], + description: `Enable tree-shaking of imports other than \`*.css\`.`, + + commitSha: 'ff9f0c3', + }, + { + components: [], + version: '0.9.0', + prs: ['31484'], + description: `Added new VisuallyHidden component for hiding content visually while keeping it accessible to screen readers.`, + + commitSha: '1ef3ca4', + }, ]; diff --git a/docs-ui/src/utils/changelogs/v0.9.1.ts b/docs-ui/src/utils/changelogs/v0.9.1.ts new file mode 100644 index 0000000000..c71c10a2e0 --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.9.1.ts @@ -0,0 +1,28 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_9_1: ChangelogProps[] = [ + { + components: [], + version: '0.9.1', + prs: ['31843'], + description: `Fixed Table Row component to correctly handle cases where no \`href\` is provided, preventing unnecessary router provider wrapping and fixing the cursor incorrectly showing as a pointer despite the element not being a link.`, + + commitSha: 'b3ad928', + }, + { + components: [], + version: '0.9.1', + prs: ['31817'], + description: `Fixed \`useTable\` hook to prioritize \`providedRowCount\` over data length for accurate row count in server-side pagination scenarios.`, + + commitSha: 'fe7c751', + }, + { + components: [], + version: '0.9.1', + prs: ['31844'], + description: `Fixed Table column sorting indicator to show up arrow when no sort is active, correctly indicating that clicking will sort ascending.`, + + commitSha: 'c145031', + }, +]; diff --git a/docs-ui/src/utils/types.ts b/docs-ui/src/utils/types.ts index 173dcd4329..3bc4006bf6 100644 --- a/docs-ui/src/utils/types.ts +++ b/docs-ui/src/utils/types.ts @@ -41,7 +41,7 @@ export interface ChangelogProps { description: string; version: Version; prs: string[]; - type?: 'breaking' | 'new' | 'fix'; + breaking?: boolean; commitSha?: string; migration?: string; } diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index ae913d5e80..76496f8a86 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -45,7 +45,7 @@ **Affected components:** Table, TableRoot, TablePagination -- 95246eb: **Breaking** Updating color tokens to match the new neutral style on different surfaces. +- 95246eb: **BREAKING**: Updating color tokens to match the new neutral style on different surfaces. **Migration:** @@ -56,12 +56,18 @@ - `--bui-bg-tint-pressed` can be replaced by `--bui-bg-neutral-on-surface-0-pressed` - `--bui-bg-tint-disabled` can be replaced by `--bui-bg-neutral-on-surface-0-disabled` -- ea0c6d8: Introduce new `ToggleButton` & `ToggleButtonGroup` components in Backstage UI +- ea0c6d8: **BREAKING**: Introduce new `ToggleButton` & `ToggleButtonGroup` components in Backstage UI + + **Affected components:** ToggleButton, ToggleButtonGroup + - 4ea1d15: **BREAKING**: Renamed CSS variable `--bui-bg` to `--bui-bg-surface-0` for consistency. ### Patch Changes - 1880402: Fixes app background color on dark mode. + + **Affected components:** Box + - d2fdded: Added indeterminate state support to the Checkbox component for handling partial selection scenarios like table header checkboxes. **Affected components:** Checkbox @@ -71,14 +77,26 @@ **Affected components:** Select, MenuAutocomplete, MenuAutocompleteListbox - 21c87cc: Fixes disabled state in primary and secondary buttons in Backstage UI. + + **Affected components:** Button + - 9c76682: build(deps-dev): bump `storybook` from 10.1.9 to 10.1.10 - de80336: Fixed disabled tertiary buttons incorrectly showing hover effects on surfaces. + + **Affected components:** Button + - 133d5c6: Added new Popover component for Backstage UI with automatic overflow handling, and full placement support. Also introduced `--bui-shadow` token for consistent elevation styling across overlay components (Popover, Tooltip, Menu). + + **Affected components:** Popover + - 973c839: Fixed Table sorting indicator not being visible when a column is actively sorted. **Affected components:** Table, Column - df40cfc: Fixed Menu component trigger button not toggling correctly. Removed custom click-outside handler that was interfering with React Aria's built-in state management, allowing the menu to properly open and close when clicking the trigger button. + + **Affected components:** Menu + - b01ab96: Added support for column width configuration in Table component. Columns now accept `width`, `defaultWidth`, `minWidth`, and `maxWidth` props for responsive layout control. **Affected components:** Table, Column @@ -145,7 +163,7 @@ **Affected components:** Table, TableRoot, TablePagination -- 95246eb: **Breaking** Updating color tokens to match the new neutral style on different surfaces. +- 95246eb: **BREAKING**: Updating color tokens to match the new neutral style on different surfaces. **Migration:** @@ -181,7 +199,7 @@ ### Minor Changes -- 16543fa: **Breaking change** The `Cell` component has been refactored to be a generic wrapper component that accepts `children` for custom cell content. The text-specific functionality (previously part of `Cell`) has been moved to a new `CellText` component. +- 16543fa: **BREAKING**: The `Cell` component has been refactored to be a generic wrapper component that accepts `children` for custom cell content. The text-specific functionality (previously part of `Cell`) has been moved to a new `CellText` component. **Migration:** @@ -242,7 +260,7 @@ ### Minor Changes -- 16543fa: **Breaking change** The `Cell` component has been refactored to be a generic wrapper component that accepts `children` for custom cell content. The text-specific functionality (previously part of `Cell`) has been moved to a new `CellText` component. +- 16543fa: **BREAKING**: The `Cell` component has been refactored to be a generic wrapper component that accepts `children` for custom cell content. The text-specific functionality (previously part of `Cell`) has been moved to a new `CellText` component. **Migration:** @@ -331,6 +349,8 @@ Added `purpose` prop for accessibility control (`'informative'` or `'decoration'`). + **Affected components:** Avatar + - 5c614ff: **BREAKING**: Migrated Checkbox component from Base UI to React Aria Components. API changes required: @@ -386,12 +406,12 @@ ``` -- 134151f: Fixing styles on SearchField in Backstage UI after migration to CSS modules. `SearchField` has now its own set of class names. We previously used class names from `TextField` but this approach was creating some confusion so going forward in your theme you'll be able to theme `TextField` and `SearchField` separately. +- 134151f: **BREAKING**: Fixing styles on SearchField in Backstage UI after migration to CSS modules. `SearchField` has now its own set of class names. We previously used class names from `TextField` but this approach was creating some confusion so going forward in your theme you'll be able to theme `TextField` and `SearchField` separately. - a67670d: **BREAKING**: Removed central `componentDefinitions` object and related type utilities (`ComponentDefinitionName`, `ComponentClassNames`). Component definitions are primarily intended for documenting the CSS class API for theming purposes, not for programmatic use in JavaScript/TypeScript. - **Migration Guide:** + **Migration:** If you were using component definitions or class names to build custom components, we recommend migrating to either: @@ -450,27 +470,68 @@ If you're using `SelectProps` type directly, update from `SelectProps` to `SelectProps<'single' | 'multiple'>`. Component usage remains backward compatible. + **Affected components:** Select + ### Patch Changes - d01de00: Fix broken external links in Backstage UI Header component. + + **Affected components:** Header + - 35a3614: Fixed CSS issues in Select component including popover width constraints, focus outline behavior, and overflow handling. + + **Affected components:** Select + - 01476f0: Improved visual consistency of PasswordField, SearchField, and MenuAutocomplete components. + + **Affected components:** PasswordField, SearchField, MenuAutocomplete + - 26c6a78: Fix default text color in Backstage UI + + **Affected components:** Text + - deaa427: Fixed Text component to prevent `truncate` prop from being spread to the underlying DOM element. + + **Affected components:** Text + - 1059f95: Improved the Link component structure in Backstage UI. + + **Affected components:** Link + - 836b0c7: Fixed dialog backdrop appearance in dark mode. + + **Affected components:** Dialog + - 6874094: Migrated CellProfile component from Base UI Avatar to Backstage UI Avatar component. + + **Affected components:** Avatar + - 719d772: Avatar components in x-small and small sizes now display only one initial instead of two, improving readability at smaller dimensions. + + **Affected components:** Avatar + - 6d35a6b: Removed `@base-ui-components/react` dependency as all components now use React Aria Components. - dac851f: Fix the default font size in Backstage UI. - 3c0ea67: Fix CSS layer ordering in Backstage UI to make sure component styles are loaded after tokens and base declarations. - 3b18d80: Fixed RadioGroup radio button ellipse distortion by preventing flex shrink and grow. + + **Affected components:** RadioGroup + - 4eb455c: Fix font smoothing as default in Backstage UI. - ff9f0c3: Enable tree-shaking of imports other than `*.css`. - 7839e7b: Added `loading` prop to Button and ButtonIcon components for displaying spinner during async operations. + + **Affected components:** Button, ButtonIcon + - a00fb88: Fixed Table Row component to properly support opening links in new tabs via right-click or Cmd+Click when using the `href` prop. + + **Affected components:** Table + - e16ece5: Set the color-scheme property depending on theme - 1ef3ca4: Added new VisuallyHidden component for hiding content visually while keeping it accessible to screen readers. + + **Affected components:** VisuallyHidden + - 00bfb83: Fix default font wight and font family in Backstage UI. ## 0.9.0-next.3 @@ -560,7 +621,7 @@ Added `purpose` prop for accessibility control (`'informative'` or `'decoration'`). -- 134151f: Fixing styles on SearchField in Backstage UI after migration to CSS modules. `SearchField` has now its own set of class names. We previously used class names from `TextField` but this approach was creating some confusion so going forward in your theme you'll be able to theme `TextField` and `SearchField` separately. +- 134151f: **BREAKING**: Fixing styles on SearchField in Backstage UI after migration to CSS modules. `SearchField` has now its own set of class names. We previously used class names from `TextField` but this approach was creating some confusion so going forward in your theme you'll be able to theme `TextField` and `SearchField` separately. ### Patch Changes @@ -723,10 +784,10 @@ ### Minor Changes -- 0615e54: We are moving our DataTable component to React Aria. We removed our DataTable to only use Table as a single and opinionated option for tables. This new structure is made possible by using React Aria under the hood. -- b245c9d: Backstage UI - HeaderPage - We are updating the breadcrumb to be more visible and accessible. -- 800f593: **Breaking change** We are updating the Menu component to use React Aria under the hood. The structure and all props are changing to follow React Aria's guidance. -- b0e47f3: **Breaking** We are upgrading our `Text` component to support all font sizes making the `Heading` component redundant. The new `Text` component introduces 4 sizes for title and 4 sizes for body text. All of these work in multiple colors and font weights. We improved the `as` prop to include all possible values. The `Link` component has also been updated to match the new `Text` component. +- 0615e54: **BREAKING**: We are moving our DataTable component to React Aria. We removed our DataTable to only use Table as a single and opinionated option for tables. This new structure is made possible by using React Aria under the hood. +- b245c9d: **BREAKING**: Backstage UI - HeaderPage - We are updating the breadcrumb to be more visible and accessible. +- 800f593: **BREAKING**: We are updating the Menu component to use React Aria under the hood. The structure and all props are changing to follow React Aria's guidance. +- b0e47f3: **BREAKING**: We are upgrading our `Text` component to support all font sizes making the `Heading` component redundant. The new `Text` component introduces 4 sizes for title and 4 sizes for body text. All of these work in multiple colors and font weights. We improved the `as` prop to include all possible values. The `Link` component has also been updated to match the new `Text` component. ### Patch Changes @@ -735,7 +796,7 @@ - f761306: Add new TagGroup component to Backstage UI. - 75fead9: Fixes a couple of small bugs in BUI including setting H1 and H2 correctly on the Header and HeaderPage. - e7ff178: Update styling of Tooltip element -- 230b410: **Breaking change** Move breadcrumb to fit in the `HeaderPage` instead of the `Header` in Backstage UI. +- 230b410: **BREAKING**: Move breadcrumb to fit in the `HeaderPage` instead of the `Header` in Backstage UI. - 2f9a084: We are motion away from `motion` to use `gsap` instead to make Backstage UI backward compatible with React 17. - d4e603e: Updated Menu component in Backstage UI to use useId() from React Aria instead of React to support React 17. - 8bdc491: Remove stylesheet import from Select component. @@ -746,11 +807,11 @@ ### Minor Changes -- 0615e54: We are moving our DataTable component to React Aria. We removed our DataTable to only use Table as a single and opinionated option for tables. This new structure is made possible by using React Aria under the hood. +- 0615e54: **BREAKING**: We are moving our DataTable component to React Aria. We removed our DataTable to only use Table as a single and opinionated option for tables. This new structure is made possible by using React Aria under the hood. ### Patch Changes -- 230b410: **Breaking change** Move breadcrumb to fit in the `HeaderPage` instead of the `Header` in Backstage UI. +- 230b410: **BREAKING**: Move breadcrumb to fit in the `HeaderPage` instead of the `Header` in Backstage UI. - 8bdc491: Remove stylesheet import from Select component. - 404b426: Add `startCollapsed` prop on the `SearchField` component in BUI. @@ -772,7 +833,7 @@ ### Minor Changes -- b0e47f3: **Breaking** We are upgrading our `Text` component to support all font sizes making the `Heading` component redundant. The new `Text` component introduces 4 sizes for title and 4 sizes for body text. All of these work in multiple colors and font weights. We improved the `as` prop to include all possible values. The `Link` component has also been updated to match the new `Text` component. +- b0e47f3: **BREAKING**: We are upgrading our `Text` component to support all font sizes making the `Heading` component redundant. The new `Text` component introduces 4 sizes for title and 4 sizes for body text. All of these work in multiple colors and font weights. We improved the `as` prop to include all possible values. The `Link` component has also been updated to match the new `Text` component. ### Patch Changes @@ -783,13 +844,13 @@ ### Minor Changes -- e92bb9b: Canon has been renamed to Backstage UI. This means that `@backstage/canon` has been deprecated and replaced by `@backstage/ui`. +- e92bb9b: **BREAKING**: Canon has been renamed to Backstage UI. This means that `@backstage/canon` has been deprecated and replaced by `@backstage/ui`. ## 0.6.0-next.1 ### Minor Changes -- 2e30459: We are moving our Tooltip component to use React Aria under the hood. In doing so, the structure of the component and its prop are changing to follow the new underlying structure. +- 2e30459: **BREAKING**: We are moving our Tooltip component to use React Aria under the hood. In doing so, the structure of the component and its prop are changing to follow the new underlying structure. ### Patch Changes @@ -804,7 +865,7 @@ ### Minor Changes -- 4c6d891: **BREAKING CHANGES** +- 4c6d891: **BREAKING**: We’re updating our Button component to provide better support for button links. @@ -827,12 +888,12 @@ ### Minor Changes -- 621fac9: We are updating the default size of the Button component in Canon to be small instead of medium. -- a842554: We set the default size for IconButton in Canon to be small instead of medium. -- 35fd51d: Move TextField component to use react Aria under the hood. Introducing a new FieldLabel component to help build custom fields. -- 78204a2: **Breaking** We are adding a new as prop on the Heading and Text component to make it easier to change the component tag. We are removing the render prop in favour of the as prop. -- c49e335: TextField in Canon now has multiple label sizes as well as the capacity to hide label and description but still make them available for screen readers. -- 24b45ef: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using instead of just . +- 621fac9: **BREAKING**: We are updating the default size of the Button component in Canon to be small instead of medium. +- a842554: **BREAKING**: We set the default size for IconButton in Canon to be small instead of medium. +- 35fd51d: **BREAKING**: Move TextField component to use react Aria under the hood. Introducing a new FieldLabel component to help build custom fields. +- 78204a2: **BREAKING**: We are adding a new as prop on the Heading and Text component to make it easier to change the component tag. We are removing the render prop in favour of the as prop. +- c49e335: **BREAKING**: TextField in Canon now has multiple label sizes as well as the capacity to hide label and description but still make them available for screen readers. +- 24b45ef: **BREAKING**: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using `` instead of just ``. ### Patch Changes @@ -862,7 +923,7 @@ ### Minor Changes -- 24b45ef: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using instead of just . +- 24b45ef: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using `` instead of just ``. ### Patch Changes @@ -872,9 +933,9 @@ ### Minor Changes -- ea36f74: **Breaking Change** Icons on Button and IconButton now need to be imported and placed like this:
-- ... -- ... --
-- -+const columns: ColumnConfig[] = [ -+ { id: 'name', label: 'Name', isRowHeader: true, cell: item => }, -+ { id: 'type', label: 'Type', cell: item => }, -+]; -+ -+ -\`\`\``, - breaking: true, - commitSha: '243e5e7', - }, - { - components: [], - version: '0.11.0', - prs: ['32202'], - description: `**BREAKING**: Updating color tokens to match the new neutral style on different surfaces.`, - migration: `There's no direct replacement for the old tint tokens but you can use the new neutral set of color tokens on surface 0 or 1 as a replacement. - -- \`--bui-bg-tint\` can be replaced by \`--bui-bg-neutral-on-surface-0\` -- \`--bui-bg-tint-hover\` can be replaced by \`--bui-bg-neutral-on-surface-0-hover\` -- \`--bui-bg-tint-pressed\` can be replaced by \`--bui-bg-neutral-on-surface-0-pressed\` -- \`--bui-bg-tint-disabled\` can be replaced by \`--bui-bg-neutral-on-surface-0-disabled\``, - breaking: true, - commitSha: '95246eb', - }, - { - components: [], - version: '0.11.0', - prs: ['32232'], - description: `Introduce new \`ToggleButton\` & \`ToggleButtonGroup\` components in Backstage UI`, - breaking: true, - commitSha: 'ea0c6d8', - }, - { - components: [], - version: '0.11.0', - prs: ['32297'], - description: `Fixes disabled state in primary and secondary buttons in Backstage UI.`, - - commitSha: '21c87cc', - }, - { - components: [], - version: '0.11.0', - prs: ['32265'], - description: `Fixed \`Link\` component causing hard page refreshes for internal routes. The component now properly uses React Router's navigation instead of full page reloads.`, - - commitSha: 'b3253b6', - }, - { - components: [], - version: '0.11.0', - prs: ['32200'], - description: `**BREAKING**: Renamed CSS variable \`--bui-bg\` to \`--bui-bg-surface-0\` for consistency.`, - breaking: true, - commitSha: '4ea1d15', - }, - { - components: [], - version: '0.11.0', - prs: ['32203'], - description: `Fixes app background color on dark mode.`, - - commitSha: '1880402', - }, - { - components: [], - version: '0.11.0', - prs: ['32185'], - description: `build(deps-dev): bump \`storybook\` from 10.1.9 to 10.1.10`, - - commitSha: '9c76682', - }, - { - components: ['searchfield'], - version: '0.11.0', - prs: ['32123'], - description: `Fixed SearchField \`startCollapsed\` prop not working correctly in Backstage UI. The field now properly starts in a collapsed state, expands when clicked and focused, and collapses back when unfocused with no input. Also fixed CSS logic to work correctly in all layout contexts (flex row, flex column, and regular containers).`, - - commitSha: 'b4a4911', - }, ]; diff --git a/docs-ui/src/utils/changelogs/v0.2.0.ts b/docs-ui/src/utils/changelogs/v0.2.0.ts index 383a16afb0..9f39331898 100644 --- a/docs-ui/src/utils/changelogs/v0.2.0.ts +++ b/docs-ui/src/utils/changelogs/v0.2.0.ts @@ -89,28 +89,4 @@ export const changelog_0_2_0: ChangelogProps[] = [ commitSha: '05e9d41', }, - { - components: [], - version: '0.2.0', - prs: ['29002'], - description: `We are renaming CanonProvider to IconProvider to improve clarity on how to override icons.`, - breaking: true, - commitSha: '8689010', - }, - { - components: [], - version: '0.2.0', - prs: ['28972'], - description: `To avoid conflicts with Backstage, we removed global styles and set font-family and font-weight for each components.`, - - commitSha: '89e8686', - }, - { - components: [], - version: '0.2.0', - prs: ['28961'], - description: `Fix CSS imports and move CSS outputs out of the dist folder.`, - breaking: true, - commitSha: '5a5db29', - }, ]; diff --git a/docs-ui/src/utils/changelogs/v0.3.0.ts b/docs-ui/src/utils/changelogs/v0.3.0.ts index eec2590e91..4a2e9faa15 100644 --- a/docs-ui/src/utils/changelogs/v0.3.0.ts +++ b/docs-ui/src/utils/changelogs/v0.3.0.ts @@ -179,62 +179,4 @@ export const changelog_0_3_0: ChangelogProps[] = [ commitSha: '05a5003', }, - { - components: [], - version: '0.3.0', - prs: ['29482'], - description: `Updated TextField and Select component to work with React Hook Form.`, - breaking: true, - commitSha: 'f038613', - }, - { - components: [], - version: '0.3.0', - prs: ['29440'], - description: `Add new Select component for Canon`, - breaking: true, - commitSha: '1b0cf40', - }, - { - components: [], - version: '0.3.0', - prs: ['29364'], - description: `**BREAKING**: Added a new TextField component to replace the Field and Input component. After feedback, it became clear that we needed to build a more opinionated version to avoid any problem in the future.`, - breaking: true, - commitSha: '5074d61', - }, - { - components: [], - version: '0.3.0', - prs: ['29499'], - description: `Removes instances of default React imports, a necessary update for the upcoming React 19 migration. - - https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html`, - - commitSha: 'a47fd39', - }, - { - components: [], - version: '0.3.0', - prs: ['29475'], - description: `Improved Container styles, changing our max-width to 120rem and improving padding on smaller screens.`, - - commitSha: '24f0e08', - }, - { - components: [], - version: '0.3.0', - prs: ['29466'], - description: `Move styles to the root of the TextField component.`, - - commitSha: '7ae28ba', - }, - { - components: [], - version: '0.3.0', - prs: ['29247'], - description: `We added a render prop to the Link component to make sure it can work with React Router.`, - - commitSha: '4fe5b08', - }, ]; diff --git a/docs-ui/src/utils/changelogs/v0.4.0.ts b/docs-ui/src/utils/changelogs/v0.4.0.ts index 014679ae33..a85f59c0dc 100644 --- a/docs-ui/src/utils/changelogs/v0.4.0.ts +++ b/docs-ui/src/utils/changelogs/v0.4.0.ts @@ -113,68 +113,4 @@ export const changelog_0_4_0: ChangelogProps[] = [ commitSha: '1ea1db0', }, - { - components: [], - version: '0.4.0', - prs: ['29878'], - description: `Use correct colour token for TextField clear button icon, prevent layout shift whenever it is hidden or shown and properly size focus area around it. Also stop leading icon shrinking when used together with clear button.`, - - commitSha: 'c8f32db', - }, - { - components: [], - version: '0.4.0', - prs: ['29820'], - description: `Added new icon and onClear props to the TextField to make it easier to accessorize inputs.`, - - commitSha: '6189bfd', - }, - { - components: [], - version: '0.4.0', - prs: ['29782'], - description: `Pin version of @base-ui-components/react.`, - - commitSha: '97b25a1', - }, - { - components: [], - version: '0.4.0', - prs: ['29826'], - description: `Use the Field component from Base UI within the TextField.`, - - commitSha: '185d3a8', - }, - { - components: [], - version: '0.4.0', - prs: ['29667'], - description: `**BREAKING**: Icons on Button and IconButton now need to be imported and placed like this: \`} /> -- Content -- - -+ -+ -+ Content -+ -\`\`\` - -CSS classes: \`.bui-CollapsibleRoot\` → \`.bui-Accordion\`, \`.bui-CollapsibleTrigger\` → \`.bui-AccordionTrigger\` (now on heading element), \`.bui-CollapsiblePanel\` → \`.bui-AccordionPanel\` - -**Path 2: React Aria Disclosure (Full Customization)** - -For custom styling without preset styles: - -\`\`\`tsx -import { Disclosure, Button, DisclosurePanel } from 'react-aria-components'; - - - - Content -; -\`\`\``, - breaking: true, - commitSha: '83c100e', - }, - { - components: [], - version: '0.9.0', - prs: ['31649'], - description: `**BREAKING**: The \`SelectProps\` interface now accepts a generic type parameter for selection mode. - - Added searchable and multiple selection support to Select component. The component now accepts \`searchable\`, \`selectionMode\`, and \`searchPlaceholder\` props to enable filtering and multi-selection modes.`, - migration: `If you're using \`SelectProps\` type directly, update from \`SelectProps\` to \`SelectProps<'single' | 'multiple'>\`. Component usage remains backward compatible.`, - breaking: true, - commitSha: '816af0f', - }, - { - components: [], - version: '0.9.0', - prs: ['31618'], - description: `Fixed CSS issues in Select component including popover width constraints, focus outline behavior, and overflow handling.`, - - commitSha: '35a3614', - }, - { - components: [], - version: '0.9.0', - prs: ['31679'], - description: `Improved visual consistency of PasswordField, SearchField, and MenuAutocomplete components.`, - - commitSha: '01476f0', - }, - { - components: [], - version: '0.9.0', - prs: ['31673'], - description: `Fixed dialog backdrop appearance in dark mode.`, - - commitSha: '836b0c7', - }, - { - components: [], - version: '0.9.0', - prs: ['31672'], - description: `Removed \`@base-ui-components/react\` dependency as all components now use React Aria Components.`, - - commitSha: '6d35a6b', - }, - { - components: [], - version: '0.9.0', - prs: ['31681'], - description: `Added \`loading\` prop to Button and ButtonIcon components for displaying spinner during async operations.`, - - commitSha: '7839e7b', - }, - { - components: [], - version: '0.9.0', - prs: ['31680'], - description: `Fixed Table Row component to properly support opening links in new tabs via right-click or Cmd+Click when using the href prop.`, - - commitSha: 'a00fb88', - }, - { - components: [], - version: '0.9.0', - prs: ['31566'], - description: `**BREAKING**: Migrated Avatar component from Base UI to custom implementation with size changes: - - - Base UI-specific props are no longer supported - - Size values have been updated: - - New \`x-small\` size added (1.25rem / 20px) - - \`small\` size unchanged (1.5rem / 24px) - - \`medium\` size unchanged (2rem / 32px, default) - - \`large\` size **changed from 3rem to 2.5rem** (40px) - - New \`x-large\` size added (3rem / 48px)`, - migration: `\`\`\`diff -# Remove Base UI-specific props -- -+ - -# Update large size usage to x-large for same visual size -- -+ -\`\`\` - -Added \`purpose\` prop for accessibility control (\`'informative'\` or \`'decoration'\`).`, - breaking: true, - commitSha: '539cf26', - }, - { - components: [], - version: '0.9.0', - prs: ['31507'], - description: `**BREAKING**: Fixing styles on SearchField in Backstage UI after migration to CSS modules. \`SearchField\` has now its own set of class names. We previously used class names from \`TextField\` but this approach was creating some confusion so going forward in your theme you'll be able to theme \`TextField\` and \`SearchField\` separately.`, - breaking: true, - commitSha: '134151f', - }, - { - components: [], - version: '0.9.0', - prs: ['31525'], - description: `Fix broken external links in Backstage UI Header component.`, - - commitSha: 'd01de00', - }, - { - components: [], - version: '0.9.0', - prs: ['31615'], - description: `Fixed Text component to prevent \`truncate\` prop from being spread to the underlying DOM element.`, - - commitSha: 'deaa427', - }, - { - components: [], - version: '0.9.0', - prs: ['31524'], - description: `Improved the Link component structure in Backstage UI.`, - - commitSha: '1059f95', - }, - { - components: [], - version: '0.9.0', - prs: ['31608'], - description: `Migrated CellProfile component from Base UI Avatar to Backstage UI Avatar component.`, - - commitSha: '6874094', - }, - { - components: [], - version: '0.9.0', - prs: ['31623'], - description: `Avatar components in x-small and small sizes now display only one initial instead of two, improving readability at smaller dimensions.`, - - commitSha: '719d772', - }, - { - components: [], - version: '0.9.0', - prs: ['31576'], - description: `Fixed RadioGroup radio button ellipse distortion by preventing flex shrink and grow.`, - - commitSha: '3b18d80', - }, - { - components: [], - version: '0.9.0', - prs: ['31469'], - description: `Set the color-scheme property depending on theme`, - - commitSha: 'e16ece5', - }, - { - components: [], - version: '0.9.0', - prs: ['31517'], - description: `**BREAKING**: Migrated Checkbox component from Base UI to React Aria Components. - - API changes required: - - - \`checked\` → \`isSelected\` - - \`defaultChecked\` → \`defaultSelected\` - - \`disabled\` → \`isDisabled\` - - \`required\` → \`isRequired\` - - \`label\` prop removed - use \`children\` instead - - CSS: \`bui-CheckboxLabel\` class removed - - Data attribute: \`data-checked\` → \`data-selected\` - - Use without label is no longer supported`, - migration: `Before: - -\`\`\`tsx - -\`\`\` - -After: - -\`\`\`tsx - - Accept terms - -\`\`\` - -Before: - -\`\`\`tsx - -\`\`\` - -After: - -\`\`\`tsx -Option -\`\`\` - -Before: - -\`\`\`tsx - -\`\`\` - -After: - -\`\`\`tsx - - Accessible label - -\`\`\``, - breaking: true, - commitSha: '5c614ff', - }, - { - components: ['menu', 'switch', 'skeleton', 'header', 'header-page', 'tabs'], - version: '0.9.0', - prs: ['31496'], - description: `**BREAKING**: Changed className prop behavior to augment default styles instead of being ignored or overriding them. - - If you were passing custom className values to any of these components that relied on the previous behavior, you may need to adjust your styles to account for the default classes now being applied alongside your custom classes.`, - breaking: true, - commitSha: 'b78fc45', - }, - { - components: [], - version: '0.9.0', - prs: ['31516'], - description: `Enable tree-shaking of imports other than \`*.css\`.`, - - commitSha: 'ff9f0c3', - }, - { - components: [], - version: '0.9.0', - prs: ['31484'], - description: `Added new VisuallyHidden component for hiding content visually while keeping it accessible to screen readers.`, - - commitSha: '1ef3ca4', - }, ]; From 1df8ef4a47332372c54cb12aa014bc6c83541f31 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 23 Jan 2026 22:58:51 +0000 Subject: [PATCH 07/11] Cleanup Signed-off-by: Charles de Dreuille --- docs-ui/src/components/Theming/index.tsx | 12 ++++++------ packages/ui/CHANGELOG.md | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs-ui/src/components/Theming/index.tsx b/docs-ui/src/components/Theming/index.tsx index f47e86306a..9f67c3a111 100644 --- a/docs-ui/src/components/Theming/index.tsx +++ b/docs-ui/src/components/Theming/index.tsx @@ -38,12 +38,12 @@ export function Theming({ definition }: ThemingProps) { ...Object.values(classNames).slice(1), ]; - // Use the same styled components from MDX - const H2 = formattedMDXComponents.h2!; - const P = formattedMDXComponents.p!; - const Ul = formattedMDXComponents.ul!; - const Li = formattedMDXComponents.li!; - const Code = formattedMDXComponents.code!; + // Use the same styled components from MDX, with fallbacks to HTML elements + const H2 = formattedMDXComponents.h2 || 'h2'; + const P = formattedMDXComponents.p || 'p'; + const Ul = formattedMDXComponents.ul || 'ul'; + const Li = formattedMDXComponents.li || 'li'; + const Code = formattedMDXComponents.code || 'code'; return (
diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 76496f8a86..80c42db125 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -532,7 +532,7 @@ **Affected components:** VisuallyHidden -- 00bfb83: Fix default font wight and font family in Backstage UI. +- 00bfb83: Fix default font weight and font family in Backstage UI. ## 0.9.0-next.3 From 4926084387c84852786ba3ced2c8d6e26e012c31 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 26 Jan 2026 10:12:10 +0000 Subject: [PATCH 08/11] Improve script Signed-off-by: Charles de Dreuille --- docs-ui/scripts/sync-changelog.mjs | 16 +++++++--------- docs-ui/src/utils/changelogs/v0.7.0.ts | 2 +- docs-ui/src/utils/changelogs/v0.9.0.ts | 2 +- packages/ui/CHANGELOG.md | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/docs-ui/scripts/sync-changelog.mjs b/docs-ui/scripts/sync-changelog.mjs index d46ff2b108..5d89b87242 100644 --- a/docs-ui/scripts/sync-changelog.mjs +++ b/docs-ui/scripts/sync-changelog.mjs @@ -188,7 +188,9 @@ async function parseChangelogMd(changelogPath, sinceVersion, validComponents) { // Skip headings that are just markdown content within changelog entries if (/^\d+\.\d+\.\d+/.test(versionText)) { // Skip pre-release versions (e.g., 0.11.0-next.1, 0.9.0-alpha.2) to avoid duplicates - // Pre-release commits are included in the final release version + // While normalizeVersion() strips the suffix when writing entries, we need to skip + // pre-release sections entirely during parsing, otherwise we'd process the same + // commits twice: once from 0.11.0-next.1 and again from 0.11.0 if (/^\d+\.\d+\.\d+-/.test(versionText)) { currentVersion = null; currentSection = null; @@ -328,7 +330,8 @@ async function parseListItem( .replace(/\n*\*\*Affected components:\*\*[ \t]*[^\n]+/g, '') .trim(); } else { - // Fallback: try old format without bold markers + // Fallback: try old format without bold markers for backwards compatibility + // Some older changelog entries may not have been migrated to the new format const oldFormatMatch = description.match( /Affected components?:\s*([^\n]+)/i, ); @@ -385,18 +388,13 @@ async function parseListItem( } /** - * Infer change type from section and description + * Determine if a change is breaking based on semver rules * Breaking change rules (semver): * - version >= 1.0.0: Major changes are breaking * - version < 1.0.0: Major and Minor changes are breaking */ function isBreakingChange(section, description, version) { - // Mark as breaking if explicitly mentioned in description - if (description.includes('BREAKING')) { - return true; - } - - // Parse version to determine breaking change rules + // Parse version to determine breaking change rules based on semver const normalizedVersion = normalizeVersion(version); const [major] = normalizedVersion.split('.').map(Number); diff --git a/docs-ui/src/utils/changelogs/v0.7.0.ts b/docs-ui/src/utils/changelogs/v0.7.0.ts index a42d693661..ebef164d96 100644 --- a/docs-ui/src/utils/changelogs/v0.7.0.ts +++ b/docs-ui/src/utils/changelogs/v0.7.0.ts @@ -78,7 +78,7 @@ export const changelog_0_7_0: ChangelogProps[] = [ version: '0.7.0', prs: ['30701'], description: `**BREAKING**: Move breadcrumb to fit in the \`HeaderPage\` instead of the \`Header\` in Backstage UI.`, - breaking: true, + commitSha: '230b410', }, { diff --git a/docs-ui/src/utils/changelogs/v0.9.0.ts b/docs-ui/src/utils/changelogs/v0.9.0.ts index 0e6d90b978..a8e0fc6680 100644 --- a/docs-ui/src/utils/changelogs/v0.9.0.ts +++ b/docs-ui/src/utils/changelogs/v0.9.0.ts @@ -326,7 +326,7 @@ import { Disclosure, Button, DisclosurePanel } from 'react-aria-components'; components: [], version: '0.9.0', prs: ['31432'], - description: `Fix default font wight and font family in Backstage UI.`, + description: `Fix default font weight and font family in Backstage UI.`, commitSha: '00bfb83', }, diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 80c42db125..0cff52fe45 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -711,7 +711,7 @@ - dac851f: Fix the default font size in Backstage UI. - 3c0ea67: Fix CSS layer ordering in Backstage UI to make sure component styles are loaded after tokens and base declarations. - 4eb455c: Fix font smoothing as default in Backstage UI. -- 00bfb83: Fix default font wight and font family in Backstage UI. +- 00bfb83: Fix default font weight and font family in Backstage UI. ## 0.8.0 From 9d712d3e808bc68acbfb2bf83518e6b0f61f9c41 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 26 Jan 2026 10:26:47 +0000 Subject: [PATCH 09/11] Remove old format support Signed-off-by: Charles de Dreuille --- docs-ui/scripts/sync-changelog.mjs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/docs-ui/scripts/sync-changelog.mjs b/docs-ui/scripts/sync-changelog.mjs index 5d89b87242..6b56edd84b 100644 --- a/docs-ui/scripts/sync-changelog.mjs +++ b/docs-ui/scripts/sync-changelog.mjs @@ -329,27 +329,6 @@ async function parseListItem( description = description .replace(/\n*\*\*Affected components:\*\*[ \t]*[^\n]+/g, '') .trim(); - } else { - // Fallback: try old format without bold markers for backwards compatibility - // Some older changelog entries may not have been migrated to the new format - const oldFormatMatch = description.match( - /Affected components?:\s*([^\n]+)/i, - ); - if (oldFormatMatch) { - const componentNames = oldFormatMatch[1] - .split(',') - .map(name => name.trim()) - .filter(Boolean); - - components = componentNames - .map(name => mapComponentName(name, validComponents)) - .filter(Boolean); - - // Strip old format line from description - description = description - .replace(/\n*Affected components?:[ \t]*[^\n]+/i, '') - .trim(); - } } // Extract migration notes using bold marker (standard format) From 988b46ff13b0a9c72802c29f3b0ce1416c894fd3 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 26 Jan 2026 10:37:20 +0000 Subject: [PATCH 10/11] Update sync-changelog.mjs Signed-off-by: Charles de Dreuille --- docs-ui/scripts/sync-changelog.mjs | 99 +++++++----------------------- 1 file changed, 23 insertions(+), 76 deletions(-) diff --git a/docs-ui/scripts/sync-changelog.mjs b/docs-ui/scripts/sync-changelog.mjs index 6b56edd84b..f49e13c5e4 100644 --- a/docs-ui/scripts/sync-changelog.mjs +++ b/docs-ui/scripts/sync-changelog.mjs @@ -13,22 +13,18 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); /** - * Compare two semantic versions. + * Compare two semantic versions for sorting. * Returns: 1 if versionA > versionB, -1 if versionA < versionB, 0 if equal - * Handles pre-release versions (e.g., "0.9.0-next.2") + * Example: compareVersions("0.11.0", "0.10.0") => 1 */ function compareVersions(versionA, versionB) { // Strip 'v' prefix if present versionA = versionA.replace(/^v/, ''); versionB = versionB.replace(/^v/, ''); - // Split into [major.minor.patch, prerelease] - const [versionABase, versionAPre] = versionA.split('-'); - const [versionBBase, versionBPre] = versionB.split('-'); - - // Compare base versions - const versionAParts = versionABase.split('.').map(Number); - const versionBParts = versionBBase.split('.').map(Number); + // Compare major.minor.patch versions + const versionAParts = versionA.split('.').map(Number); + const versionBParts = versionB.split('.').map(Number); for ( let i = 0; @@ -42,13 +38,7 @@ function compareVersions(versionA, versionB) { if (versionAPart < versionBPart) return -1; } - // If base versions equal, compare pre-release - if (!versionAPre && !versionBPre) return 0; - if (!versionAPre) return 1; // versionA is release, versionB is pre-release - if (!versionBPre) return -1; // versionA is pre-release, versionB is release - - // Both have pre-release, compare them - return versionAPre.localeCompare(versionBPre); + return 0; } /** @@ -58,15 +48,6 @@ function isNewerVersion(versionA, versionB) { return compareVersions(versionA, versionB) > 0; } -/** - * Normalize version to base version (remove pre-release suffix) - * "0.9.0-next.3" → "0.9.0" - * "0.9.0" → "0.9.0" - */ -function normalizeVersion(version) { - return version.split('-')[0]; -} - /** * Read the existing changelog.ts and find the highest version number * by scanning the changelogs/ directory for version files @@ -169,6 +150,7 @@ function getValidComponents(changelogPath) { /** * Parse CHANGELOG.md and extract entries newer than sinceVersion + * Only processes main release versions (e.g., 0.11.0), skips pre-releases (e.g., 0.11.0-next.1) */ async function parseChangelogMd(changelogPath, sinceVersion, validComponents) { const content = fs.readFileSync(changelogPath, 'utf-8'); @@ -181,23 +163,17 @@ async function parseChangelogMd(changelogPath, sinceVersion, validComponents) { // Walk through the markdown AST async function walk(node, depth = 0) { - // Version headers (## 0.9.0) + // Version headers (## 0.11.0) if (node.type === 'heading' && node.depth === 2) { const versionText = extractText(node).trim(); - // Validate that this is actually a version number (X.Y.Z or X.Y.Z-pre.N) - // Skip headings that are just markdown content within changelog entries - if (/^\d+\.\d+\.\d+/.test(versionText)) { - // Skip pre-release versions (e.g., 0.11.0-next.1, 0.9.0-alpha.2) to avoid duplicates - // While normalizeVersion() strips the suffix when writing entries, we need to skip - // pre-release sections entirely during parsing, otherwise we'd process the same - // commits twice: once from 0.11.0-next.1 and again from 0.11.0 - if (/^\d+\.\d+\.\d+-/.test(versionText)) { - currentVersion = null; - currentSection = null; - } else { - currentVersion = versionText; - currentSection = null; - } + // Only process main release versions (X.Y.Z format) + if (/^\d+\.\d+\.\d+$/.test(versionText)) { + currentVersion = versionText; + currentSection = null; + } else { + // Skip pre-release versions (e.g., 0.11.0-next.1) and non-version headings + currentVersion = null; + currentSection = null; } return; } @@ -355,7 +331,7 @@ async function parseListItem( const breaking = isBreakingChange(section, description, version); return { - version: normalizeVersion(version), + version, section, commitSha, description, @@ -374,8 +350,7 @@ async function parseListItem( */ function isBreakingChange(section, description, version) { // Parse version to determine breaking change rules based on semver - const normalizedVersion = normalizeVersion(version); - const [major] = normalizedVersion.split('.').map(Number); + const [major] = version.split('.').map(Number); // Version >= 1.0.0: Only Major Changes are breaking if (major >= 1) { @@ -444,7 +419,7 @@ async function generateVersionFiles( dryRun = false, force = false, ) { - // Group entries by normalized version + // Group entries by version const byVersion = {}; entries.forEach(entry => { const version = entry.version; @@ -887,20 +862,16 @@ async function main() { const existingContent = fs.readFileSync(changelogTsPath, 'utf-8'); // Filter to only new, non-duplicate entries - const relevantEntries = allEntries.filter(e => { - const hasComponents = e.components.length > 0 || e.components.length === 0; - const notDuplicate = !isDuplicate(e, existingContent); - return hasComponents && notDuplicate; - }); + const relevantEntries = allEntries.filter( + e => !isDuplicate(e, existingContent), + ); const duplicatesCount = allEntries.length - relevantEntries.length; if (duplicatesCount > 0) { console.log(`Skipped ${duplicatesCount} duplicate entries`); } - console.log( - `Relevant entries (with or without components): ${relevantEntries.length}`, - ); + console.log(`Relevant entries: ${relevantEntries.length}`); if (relevantEntries.length === 0) { console.log('\n✅ No new entries to sync'); @@ -926,30 +897,6 @@ async function main() { console.log(` - ${comp}: ${count} ${count === 1 ? 'entry' : 'entries'}`); }); - // Warn about unknown components - const unknownComponents = []; - allEntries.forEach(entry => { - const fullText = entry.description; - const componentMatch = fullText.match( - /Affected components?:[ \t]*([^\n]+)/i, - ); - if (componentMatch) { - const names = componentMatch[1].split(',').map(n => n.trim()); - names.forEach(name => { - if (!mapComponentName(name, validComponents)) { - unknownComponents.push(name); - } - }); - } - }); - - if (unknownComponents.length > 0) { - console.log('\n⚠️ Unknown components (skipped):'); - [...new Set(unknownComponents)].forEach(name => { - console.log(` - ${name}`); - }); - } - // Create changelogs directory if it doesn't exist const changelogsDir = path.join(__dirname, '../src/utils/changelogs'); if (!fs.existsSync(changelogsDir) && !dryRun) { From 95c70b128500ddab593629564e904db41c0117c1 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 26 Jan 2026 10:47:32 +0000 Subject: [PATCH 11/11] Update sync-changelog.mjs Signed-off-by: Charles de Dreuille --- docs-ui/scripts/sync-changelog.mjs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs-ui/scripts/sync-changelog.mjs b/docs-ui/scripts/sync-changelog.mjs index f49e13c5e4..0745979430 100644 --- a/docs-ui/scripts/sync-changelog.mjs +++ b/docs-ui/scripts/sync-changelog.mjs @@ -897,6 +897,30 @@ async function main() { console.log(` - ${comp}: ${count} ${count === 1 ? 'entry' : 'entries'}`); }); + // Warn about unknown components + const unknownComponents = []; + allEntries.forEach(entry => { + const fullText = entry.description; + const componentMatch = fullText.match( + /Affected components?:[ \t]*([^\n]+)/i, + ); + if (componentMatch) { + const names = componentMatch[1].split(',').map(n => n.trim()); + names.forEach(name => { + if (!mapComponentName(name, validComponents)) { + unknownComponents.push(name); + } + }); + } + }); + + if (unknownComponents.length > 0) { + console.log('\n⚠️ Unknown components (skipped):'); + [...new Set(unknownComponents)].forEach(name => { + console.log(` - ${name}`); + }); + } + // Create changelogs directory if it doesn't exist const changelogsDir = path.join(__dirname, '../src/utils/changelogs'); if (!fs.existsSync(changelogsDir) && !dryRun) {