Merge branch 'master' of https://github.com/backstage/backstage into feat/oauth-dialog-custom-message

This commit is contained in:
Stephen Glass
2025-07-03 18:40:23 -04:00
1525 changed files with 63701 additions and 31658 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
Fixed an issue causing TechDocs to not properly handle initial redirect.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-graph': patch
---
Catalog graph plugin support i18n
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/create-app': patch
---
Bumped create-app version.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/canon': patch
---
We are consolidating all css files into a single styles.css in Canon.
+14
View File
@@ -0,0 +1,14 @@
---
'@backstage/plugin-catalog-backend': major
'@backstage/create-app': patch
---
**BREAKING:** The experimental `catalog.useUrlReadersSearch` configuration flag (introduced in v1.36) has been removed.
The `UrlReaderProcessor` now always uses the `search` method of `UrlReaders`. Built-in `UrlReaderService` implementations have been updated accordingly.
If you use custom `UrlReaderService` implementations, you need to adapt their `search` method to correctly handle both specific URLs and potential
search patterns (see changes on built-in readers [in the original PR](https://github.com/backstage/backstage/pull/28379/files#diff-68b0452f173ee54bdd40f7b5e047a9cb8bb59200425622c212c217b76dac1d1b)).
Previous behavior was to call the `search` method only if the parsed Git URL's filename contained a wildcard and use `readUrl` otherwise. Each `UrlReaderService` must implement this logic in the `search` method instead.
This allows each `UrlReaderService` implementation to check whether it's a search URL (that contains a wildcard pattern) or not using logic that is specific to each provider.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/canon': patch
---
Add new SearchField component in Canon
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/config-loader': patch
'@backstage/config': patch
---
Loosen the requirements for a key to be considered valid config.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/canon': patch
---
Add new Header component to Canon.
+17
View File
@@ -0,0 +1,17 @@
---
'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch
'@backstage/plugin-search-backend-module-elasticsearch': patch
'@backstage/backend-dynamic-feature-service': patch
'@backstage/plugin-catalog-backend-module-puppetdb': patch
'@backstage/plugin-catalog-backend-module-msgraph': patch
'@backstage/plugin-catalog-backend-module-ldap': patch
'@backstage/frontend-app-api': patch
'@backstage/plugin-permission-common': patch
'@backstage/plugin-kubernetes-node': patch
'@backstage/plugin-permission-node': patch
'@backstage/catalog-model': patch
'@backstage/plugin-catalog-react': patch
'@backstage/config': patch
---
Just some more circular dep cleanup
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': patch
---
Filter MultiEntityPicker options based on rendered option value
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/canon': patch
---
Add new `RadioGroup` + `Radio` component to Canon
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch
---
Fixed bug in `IncrementalIngestionEngine` by adding `burstLength` check when a burst completes
+5
View File
@@ -0,0 +1,5 @@
---
'yarn-plugin-backstage': patch
---
Fixed a bug that would prevent the yarn plugin from installing new dependencies with the `backstage:^` protocol.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/backend-defaults': patch
'@backstage/backend-test-utils': minor
---
Add a standard `toString` on credentials objects
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/repo-tools': patch
---
Fix an issue where errors were not printed to console when running `backstage-repo-tools schema openapi generate` without the `--watch` flag.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/repo-tools': minor
---
Clear output directory before running `package-docs` and skip all internal packages.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-dynamic-feature-service': patch
---
Fix wrong imports which lead to module initialization failures when enabling dynamic plugins.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-scaffolder-node-test-utils': patch
'@backstage/plugin-scaffolder-backend': patch
'@backstage/plugin-scaffolder-node': patch
---
An internal refactor which adds additional types to experimental checkpoints
+207 -172
View File
@@ -2,204 +2,239 @@
"mode": "pre",
"tag": "next",
"initialVersions": {
"example-app": "0.2.109",
"@backstage/app-defaults": "1.6.2",
"example-app-next": "0.0.23",
"app-next-example-plugin": "0.0.23",
"example-backend": "0.0.38",
"@backstage/backend-app-api": "1.2.3",
"@backstage/backend-defaults": "0.10.0",
"example-app": "0.2.110",
"@backstage/app-defaults": "1.6.3",
"example-app-next": "0.0.24",
"app-next-example-plugin": "0.0.24",
"example-backend": "0.0.39",
"@backstage/backend-app-api": "1.2.4",
"@backstage/backend-defaults": "0.11.0",
"@backstage/backend-dev-utils": "0.1.5",
"@backstage/backend-dynamic-feature-service": "0.7.0",
"@backstage/backend-openapi-utils": "0.5.3",
"@backstage/backend-plugin-api": "1.3.1",
"@backstage/backend-test-utils": "1.5.0",
"@backstage/canon": "0.4.0",
"@backstage/catalog-client": "1.10.0",
"@backstage/backend-dynamic-feature-service": "0.7.1",
"@backstage/backend-openapi-utils": "0.5.4",
"@backstage/backend-plugin-api": "1.4.0",
"@backstage/backend-test-utils": "1.6.0",
"@backstage/canon": "0.5.0",
"@backstage/catalog-client": "1.10.1",
"@backstage/catalog-model": "1.7.4",
"@backstage/cli": "0.32.1",
"@backstage/cli": "0.33.0",
"@backstage/cli-common": "0.1.15",
"@backstage/cli-node": "0.2.13",
"@backstage/codemods": "0.1.52",
"@backstage/config": "1.3.2",
"@backstage/config-loader": "1.10.1",
"@backstage/core-app-api": "1.17.0",
"@backstage/core-compat-api": "0.4.2",
"@backstage/core-components": "0.17.2",
"@backstage/core-plugin-api": "1.10.7",
"@backstage/create-app": "0.6.2",
"@backstage/dev-utils": "1.1.10",
"e2e-test": "0.2.28",
"@backstage/core-app-api": "1.17.1",
"@backstage/core-compat-api": "0.4.3",
"@backstage/core-components": "0.17.3",
"@backstage/core-plugin-api": "1.10.8",
"@backstage/create-app": "0.7.0",
"@backstage/dev-utils": "1.1.11",
"e2e-test": "0.2.29",
"@backstage/e2e-test-utils": "0.1.1",
"@backstage/errors": "1.2.7",
"@backstage/eslint-plugin": "0.1.10",
"@backstage/frontend-app-api": "0.11.2",
"@backstage/frontend-defaults": "0.2.2",
"@backstage/frontend-dynamic-feature-loader": "0.1.1",
"@internal/frontend": "0.0.9",
"@backstage/frontend-plugin-api": "0.10.2",
"@backstage/frontend-test-utils": "0.3.2",
"@backstage/eslint-plugin": "0.1.11",
"@backstage/frontend-app-api": "0.11.3",
"@backstage/frontend-defaults": "0.2.3",
"@backstage/frontend-dynamic-feature-loader": "0.1.2",
"@internal/frontend": "0.0.10",
"@backstage/frontend-plugin-api": "0.10.3",
"@backstage/frontend-test-utils": "0.3.3",
"@backstage/integration": "1.17.0",
"@backstage/integration-aws-node": "0.1.16",
"@backstage/integration-react": "1.2.7",
"@backstage/integration-react": "1.2.8",
"@internal/opaque": "0.0.1",
"@backstage/release-manifests": "0.0.13",
"@backstage/repo-tools": "0.13.3",
"@internal/scaffolder": "0.0.9",
"@techdocs/cli": "1.9.3",
"techdocs-cli-embedded-app": "0.2.108",
"@backstage/test-utils": "1.7.8",
"@backstage/repo-tools": "0.14.0",
"@internal/scaffolder": "0.0.10",
"@techdocs/cli": "1.9.4",
"techdocs-cli-embedded-app": "0.2.109",
"@backstage/test-utils": "1.7.9",
"@backstage/theme": "0.6.6",
"@backstage/types": "1.2.1",
"@backstage/version-bridge": "1.0.11",
"yarn-plugin-backstage": "0.0.5",
"@backstage/plugin-api-docs": "0.12.7",
"yarn-plugin-backstage": "0.0.6",
"@backstage/plugin-api-docs": "0.12.8",
"@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.10",
"@backstage/plugin-app": "0.1.9",
"@backstage/plugin-app-backend": "0.5.2",
"@backstage/plugin-app-node": "0.1.33",
"@backstage/plugin-app-visualizer": "0.1.19",
"@backstage/plugin-auth-backend": "0.25.0",
"@backstage/plugin-auth-backend-module-atlassian-provider": "0.4.3",
"@backstage/plugin-auth-backend-module-auth0-provider": "0.2.3",
"@backstage/plugin-auth-backend-module-aws-alb-provider": "0.4.3",
"@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.8",
"@backstage/plugin-auth-backend-module-bitbucket-provider": "0.3.3",
"@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.2.3",
"@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.4.3",
"@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.4.3",
"@backstage/plugin-auth-backend-module-github-provider": "0.3.3",
"@backstage/plugin-auth-backend-module-gitlab-provider": "0.3.3",
"@backstage/plugin-auth-backend-module-google-provider": "0.3.3",
"@backstage/plugin-auth-backend-module-guest-provider": "0.2.8",
"@backstage/plugin-auth-backend-module-microsoft-provider": "0.3.3",
"@backstage/plugin-auth-backend-module-oauth2-provider": "0.4.3",
"@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.8",
"@backstage/plugin-auth-backend-module-oidc-provider": "0.4.3",
"@backstage/plugin-auth-backend-module-okta-provider": "0.2.3",
"@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.3",
"@backstage/plugin-auth-backend-module-pinniped-provider": "0.3.3",
"@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.5.3",
"@backstage/plugin-auth-node": "0.6.3",
"@backstage/plugin-auth-react": "0.1.15",
"@backstage/plugin-app": "0.1.10",
"@backstage/plugin-app-backend": "0.5.3",
"@backstage/plugin-app-node": "0.1.34",
"@backstage/plugin-app-visualizer": "0.1.20",
"@backstage/plugin-auth-backend": "0.25.1",
"@backstage/plugin-auth-backend-module-atlassian-provider": "0.4.4",
"@backstage/plugin-auth-backend-module-auth0-provider": "0.2.4",
"@backstage/plugin-auth-backend-module-aws-alb-provider": "0.4.4",
"@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.9",
"@backstage/plugin-auth-backend-module-bitbucket-provider": "0.3.4",
"@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.2.4",
"@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.4.4",
"@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.4.4",
"@backstage/plugin-auth-backend-module-github-provider": "0.3.4",
"@backstage/plugin-auth-backend-module-gitlab-provider": "0.3.4",
"@backstage/plugin-auth-backend-module-google-provider": "0.3.4",
"@backstage/plugin-auth-backend-module-guest-provider": "0.2.9",
"@backstage/plugin-auth-backend-module-microsoft-provider": "0.3.4",
"@backstage/plugin-auth-backend-module-oauth2-provider": "0.4.4",
"@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.9",
"@backstage/plugin-auth-backend-module-oidc-provider": "0.4.4",
"@backstage/plugin-auth-backend-module-okta-provider": "0.2.4",
"@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.4",
"@backstage/plugin-auth-backend-module-pinniped-provider": "0.3.4",
"@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.5.4",
"@backstage/plugin-auth-node": "0.6.4",
"@backstage/plugin-auth-react": "0.1.16",
"@backstage/plugin-bitbucket-cloud-common": "0.3.0",
"@backstage/plugin-catalog": "1.30.0",
"@backstage/plugin-catalog-backend": "2.0.0",
"@backstage/plugin-catalog-backend-module-aws": "0.4.11",
"@backstage/plugin-catalog-backend-module-azure": "0.3.5",
"@backstage/plugin-catalog-backend-module-backstage-openapi": "0.5.2",
"@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.4.8",
"@backstage/plugin-catalog-backend-module-bitbucket-server": "0.4.1",
"@backstage/plugin-catalog-backend-module-gcp": "0.3.8",
"@backstage/plugin-catalog-backend-module-gerrit": "0.3.2",
"@backstage/plugin-catalog-backend-module-gitea": "0.1.0",
"@backstage/plugin-catalog-backend-module-github": "0.9.0",
"@backstage/plugin-catalog-backend-module-github-org": "0.3.10",
"@backstage/plugin-catalog-backend-module-gitlab": "0.6.6",
"@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.9",
"@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.7.0",
"@backstage/plugin-catalog-backend-module-ldap": "0.11.5",
"@backstage/plugin-catalog-backend-module-logs": "0.1.10",
"@backstage/plugin-catalog-backend-module-msgraph": "0.7.0",
"@backstage/plugin-catalog-backend-module-openapi": "0.2.10",
"@backstage/plugin-catalog-backend-module-puppetdb": "0.2.10",
"@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.8",
"@backstage/plugin-catalog-backend-module-unprocessed": "0.6.0",
"@backstage/plugin-catalog": "1.31.0",
"@backstage/plugin-catalog-backend": "2.1.0",
"@backstage/plugin-catalog-backend-module-aws": "0.4.12",
"@backstage/plugin-catalog-backend-module-azure": "0.3.6",
"@backstage/plugin-catalog-backend-module-backstage-openapi": "0.5.3",
"@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.5.0",
"@backstage/plugin-catalog-backend-module-bitbucket-server": "0.5.0",
"@backstage/plugin-catalog-backend-module-gcp": "0.3.9",
"@backstage/plugin-catalog-backend-module-gerrit": "0.3.3",
"@backstage/plugin-catalog-backend-module-gitea": "0.1.1",
"@backstage/plugin-catalog-backend-module-github": "0.10.0",
"@backstage/plugin-catalog-backend-module-github-org": "0.3.11",
"@backstage/plugin-catalog-backend-module-gitlab": "0.7.0",
"@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.10",
"@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.7.1",
"@backstage/plugin-catalog-backend-module-ldap": "0.11.6",
"@backstage/plugin-catalog-backend-module-logs": "0.1.11",
"@backstage/plugin-catalog-backend-module-msgraph": "0.7.1",
"@backstage/plugin-catalog-backend-module-openapi": "0.2.11",
"@backstage/plugin-catalog-backend-module-puppetdb": "0.2.11",
"@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.9",
"@backstage/plugin-catalog-backend-module-unprocessed": "0.6.1",
"@backstage/plugin-catalog-common": "1.1.4",
"@backstage/plugin-catalog-graph": "0.4.19",
"@backstage/plugin-catalog-import": "0.13.0",
"@backstage/plugin-catalog-node": "1.17.0",
"@backstage/plugin-catalog-react": "1.18.0",
"@backstage/plugin-catalog-unprocessed-entities": "0.2.17",
"@backstage/plugin-catalog-graph": "0.4.20",
"@backstage/plugin-catalog-import": "0.13.1",
"@backstage/plugin-catalog-node": "1.17.1",
"@backstage/plugin-catalog-react": "1.19.0",
"@backstage/plugin-catalog-unprocessed-entities": "0.2.18",
"@backstage/plugin-catalog-unprocessed-entities-common": "0.0.8",
"@backstage/plugin-config-schema": "0.1.68",
"@backstage/plugin-devtools": "0.1.27",
"@backstage/plugin-devtools-backend": "0.5.5",
"@backstage/plugin-config-schema": "0.1.69",
"@backstage/plugin-devtools": "0.1.28",
"@backstage/plugin-devtools-backend": "0.5.6",
"@backstage/plugin-devtools-common": "0.1.16",
"@backstage/plugin-events-backend": "0.5.2",
"@backstage/plugin-events-backend-module-aws-sqs": "0.4.11",
"@backstage/plugin-events-backend-module-azure": "0.2.20",
"@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.20",
"@backstage/plugin-events-backend-module-bitbucket-server": "0.1.1",
"@backstage/plugin-events-backend-module-gerrit": "0.2.20",
"@backstage/plugin-events-backend-module-github": "0.4.0",
"@backstage/plugin-events-backend-module-gitlab": "0.3.1",
"@backstage/plugin-events-backend-module-google-pubsub": "0.1.0",
"@backstage/plugin-events-backend-test-utils": "0.1.44",
"@backstage/plugin-events-node": "0.4.11",
"@internal/plugin-todo-list": "1.0.39",
"@internal/plugin-todo-list-backend": "1.0.39",
"@backstage/plugin-events-backend": "0.5.3",
"@backstage/plugin-events-backend-module-aws-sqs": "0.4.12",
"@backstage/plugin-events-backend-module-azure": "0.2.21",
"@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.21",
"@backstage/plugin-events-backend-module-bitbucket-server": "0.1.2",
"@backstage/plugin-events-backend-module-gerrit": "0.2.21",
"@backstage/plugin-events-backend-module-github": "0.4.1",
"@backstage/plugin-events-backend-module-gitlab": "0.3.2",
"@backstage/plugin-events-backend-module-google-pubsub": "0.1.1",
"@backstage/plugin-events-backend-module-kafka": "0.1.0",
"@backstage/plugin-events-backend-test-utils": "0.1.45",
"@backstage/plugin-events-node": "0.4.12",
"@internal/plugin-todo-list": "1.0.40",
"@internal/plugin-todo-list-backend": "1.0.40",
"@internal/plugin-todo-list-common": "1.0.25",
"@backstage/plugin-gateway-backend": "1.0.1",
"@backstage/plugin-home": "0.8.8",
"@backstage/plugin-home-react": "0.1.26",
"@backstage/plugin-kubernetes": "0.12.7",
"@backstage/plugin-kubernetes-backend": "0.19.6",
"@backstage/plugin-kubernetes-cluster": "0.0.25",
"@backstage/plugin-gateway-backend": "1.0.2",
"@backstage/plugin-home": "0.8.9",
"@backstage/plugin-home-react": "0.1.27",
"@backstage/plugin-kubernetes": "0.12.8",
"@backstage/plugin-kubernetes-backend": "0.19.7",
"@backstage/plugin-kubernetes-cluster": "0.0.26",
"@backstage/plugin-kubernetes-common": "0.9.5",
"@backstage/plugin-kubernetes-node": "0.3.0",
"@backstage/plugin-kubernetes-react": "0.5.7",
"@backstage/plugin-notifications": "0.5.5",
"@backstage/plugin-notifications-backend": "0.5.6",
"@backstage/plugin-notifications-backend-module-email": "0.3.9",
"@backstage/plugin-notifications-backend-module-slack": "0.1.1",
"@backstage/plugin-notifications-common": "0.0.8",
"@backstage/plugin-notifications-node": "0.2.15",
"@backstage/plugin-org": "0.6.39",
"@backstage/plugin-org-react": "0.1.38",
"@backstage/plugin-permission-backend": "0.7.0",
"@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.8",
"@backstage/plugin-kubernetes-node": "0.3.1",
"@backstage/plugin-kubernetes-react": "0.5.8",
"@backstage/plugin-mcp-actions-backend": "0.1.0",
"@backstage/plugin-notifications": "0.5.6",
"@backstage/plugin-notifications-backend": "0.5.7",
"@backstage/plugin-notifications-backend-module-email": "0.3.10",
"@backstage/plugin-notifications-backend-module-slack": "0.1.2",
"@backstage/plugin-notifications-common": "0.0.9",
"@backstage/plugin-notifications-node": "0.2.16",
"@backstage/plugin-org": "0.6.40",
"@backstage/plugin-org-react": "0.1.39",
"@backstage/plugin-permission-backend": "0.7.1",
"@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.9",
"@backstage/plugin-permission-common": "0.9.0",
"@backstage/plugin-permission-node": "0.10.0",
"@backstage/plugin-permission-react": "0.4.34",
"@backstage/plugin-proxy-backend": "0.6.2",
"@backstage/plugin-proxy-node": "0.1.4",
"@backstage/plugin-scaffolder": "1.31.0",
"@backstage/plugin-scaffolder-backend": "1.33.0",
"@backstage/plugin-scaffolder-backend-module-azure": "0.2.9",
"@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.10",
"@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.9",
"@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.9",
"@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.9",
"@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.10",
"@backstage/plugin-scaffolder-backend-module-gcp": "0.2.9",
"@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.9",
"@backstage/plugin-scaffolder-backend-module-gitea": "0.2.9",
"@backstage/plugin-scaffolder-backend-module-github": "0.7.1",
"@backstage/plugin-scaffolder-backend-module-gitlab": "0.9.1",
"@backstage/plugin-scaffolder-backend-module-notifications": "0.1.10",
"@backstage/plugin-scaffolder-backend-module-rails": "0.5.9",
"@backstage/plugin-scaffolder-backend-module-sentry": "0.2.9",
"@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.10",
"@backstage/plugin-permission-node": "0.10.1",
"@backstage/plugin-permission-react": "0.4.35",
"@backstage/plugin-proxy-backend": "0.6.3",
"@backstage/plugin-proxy-node": "0.1.5",
"@backstage/plugin-scaffolder": "1.32.0",
"@backstage/plugin-scaffolder-backend": "2.0.0",
"@backstage/plugin-scaffolder-backend-module-azure": "0.2.10",
"@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.11",
"@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.10",
"@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.10",
"@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.10",
"@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.11",
"@backstage/plugin-scaffolder-backend-module-gcp": "0.2.10",
"@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.10",
"@backstage/plugin-scaffolder-backend-module-gitea": "0.2.10",
"@backstage/plugin-scaffolder-backend-module-github": "0.8.0",
"@backstage/plugin-scaffolder-backend-module-gitlab": "0.9.2",
"@backstage/plugin-scaffolder-backend-module-notifications": "0.1.11",
"@backstage/plugin-scaffolder-backend-module-rails": "0.5.10",
"@backstage/plugin-scaffolder-backend-module-sentry": "0.2.10",
"@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.11",
"@backstage/plugin-scaffolder-common": "1.5.11",
"@backstage/plugin-scaffolder-node": "0.8.2",
"@backstage/plugin-scaffolder-node-test-utils": "0.2.2",
"@backstage/plugin-scaffolder-react": "1.16.0",
"@backstage/plugin-search": "1.4.26",
"@backstage/plugin-search-backend": "2.0.2",
"@backstage/plugin-search-backend-module-catalog": "0.3.4",
"@backstage/plugin-search-backend-module-elasticsearch": "1.7.2",
"@backstage/plugin-search-backend-module-explore": "0.3.2",
"@backstage/plugin-search-backend-module-pg": "0.5.44",
"@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.9",
"@backstage/plugin-search-backend-module-techdocs": "0.4.2",
"@backstage/plugin-search-backend-node": "1.3.11",
"@backstage/plugin-scaffolder-node": "0.9.0",
"@backstage/plugin-scaffolder-node-test-utils": "0.3.0",
"@backstage/plugin-scaffolder-react": "1.17.0",
"@backstage/plugin-search": "1.4.27",
"@backstage/plugin-search-backend": "2.0.3",
"@backstage/plugin-search-backend-module-catalog": "0.3.5",
"@backstage/plugin-search-backend-module-elasticsearch": "1.7.3",
"@backstage/plugin-search-backend-module-explore": "0.3.3",
"@backstage/plugin-search-backend-module-pg": "0.5.45",
"@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.10",
"@backstage/plugin-search-backend-module-techdocs": "0.4.3",
"@backstage/plugin-search-backend-node": "1.3.12",
"@backstage/plugin-search-common": "1.2.18",
"@backstage/plugin-search-react": "1.9.0",
"@backstage/plugin-signals": "0.0.19",
"@backstage/plugin-signals-backend": "0.3.4",
"@backstage/plugin-signals-node": "0.1.20",
"@backstage/plugin-signals-react": "0.0.13",
"@backstage/plugin-techdocs": "1.12.6",
"@backstage/plugin-techdocs-addons-test-utils": "1.0.48",
"@backstage/plugin-techdocs-backend": "2.0.2",
"@backstage/plugin-techdocs-common": "0.1.0",
"@backstage/plugin-techdocs-module-addons-contrib": "1.1.24",
"@backstage/plugin-techdocs-node": "1.13.3",
"@backstage/plugin-techdocs-react": "1.2.17",
"@backstage/plugin-user-settings": "0.8.22",
"@backstage/plugin-user-settings-backend": "0.3.2",
"@backstage/plugin-search-react": "1.9.1",
"@backstage/plugin-signals": "0.0.20",
"@backstage/plugin-signals-backend": "0.3.5",
"@backstage/plugin-signals-node": "0.1.21",
"@backstage/plugin-signals-react": "0.0.14",
"@backstage/plugin-techdocs": "1.13.0",
"@backstage/plugin-techdocs-addons-test-utils": "1.0.49",
"@backstage/plugin-techdocs-backend": "2.0.3",
"@backstage/plugin-techdocs-common": "0.1.1",
"@backstage/plugin-techdocs-module-addons-contrib": "1.1.25",
"@backstage/plugin-techdocs-node": "1.13.4",
"@backstage/plugin-techdocs-react": "1.3.0",
"@backstage/plugin-user-settings": "0.8.23",
"@backstage/plugin-user-settings-backend": "0.3.3",
"@backstage/plugin-user-settings-common": "0.0.1"
},
"changesets": []
"changesets": [
"chubby-dots-kiss",
"clear-bananas-end",
"create-app-1751370514",
"curly-zoos-thank",
"cyan-islands-swim",
"dark-cougars-go",
"dry-hornets-stop",
"eleven-pans-turn",
"empty-mugs-agree",
"empty-poets-give",
"fancy-nails-call",
"fuzzy-cooks-dress",
"gentle-llamas-press",
"mean-lemons-dream",
"odd-clubs-teach",
"petite-paths-remain",
"public-nails-melt",
"red-trams-join",
"rich-eagles-rule",
"shaggy-cobras-rhyme",
"shaky-parents-enter",
"sharp-stars-report",
"silent-vans-tie",
"six-dots-agree",
"sixty-ties-matter",
"social-insects-cheat",
"stupid-donuts-sit",
"three-shoes-behave",
"tired-bats-attend",
"wicked-socks-share",
"wise-frogs-talk",
"yummy-pugs-battle"
]
}
+13
View File
@@ -0,0 +1,13 @@
---
'@backstage/canon': minor
---
**BREAKING CHANGES**
Were updating our Button component to provide better support for button links.
- Were introducing a new `ButtonLink` component, which replaces the previous render prop pattern.
- To maintain naming consistency across components, `IconButton` is being renamed to `ButtonIcon`.
- Additionally, the render prop will be removed from all button-related components.
These changes aim to simplify usage and improve clarity in our component API.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-notifications-backend': patch
---
Fix `addTopic` migration when `user_settings` present
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-mcp-actions-backend': patch
---
Fixed the example in the README for generating a static token by adding a subject field
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/create-app': minor
---
Add .cache directory to shipped gitignore.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/canon': patch
---
Update return types for Heading & Text components for React 19.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/canon': patch
---
We are transforming how we structure our class names and data attributes definitions for all components. They are now all set in the same place.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/catalog-client': patch
---
allow arrays in the InMemoryCatalogClient to filter entities
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Replaced deprecated uses of `@backstage/backend-common` with the equivalents in `@backstage/backend-defaults` and `@backstage/backend-plugin-api`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/canon': patch
---
Added placeholder prop to TextField component.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/backend-defaults': patch
'@backstage/integration': patch
---
UrlReader: Fix handling of access tokens for GitLab readURL requests
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/repo-tools': minor
---
Add support for caching the per-package output from the `package-docs` command.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch
---
Fixing the typescript issue with using `z.unknown()`
+21
View File
@@ -0,0 +1,21 @@
---
'@backstage/plugin-scaffolder-backend-module-github': patch
---
Added support for file deletion to `publish:github:pull-request` action.
Example usage:
```diff
- action: publish:github:pull-request
id: clean-up-pr
input:
description: This is the description
+ filesToDelete:
+ - outdated/changelog.md
+ - sample-file.txt
owner: owner
repo: repo
title: Title Goes Here
```
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-import': patch
---
Fixed bug with error message since ResponseError is now thrown from CatalogClient
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/canon': patch
---
adding export for ButtonLink so it's importable
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/integration-react': patch
---
Separated gitlab `write_repository` and `api` scope to pass checks in `RefreshingAuthSessionManager`
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/canon': minor
---
Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using <Grid.Root /> instead of just <Grid />.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-search-backend': patch
---
Error messages should not contain backend SQL query strings in the API response, this change will ensure that messages are logged and empty response is returned to the user
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/backend-defaults': patch
'@backstage/integration': patch
---
Fixed bug where the GitLab user token and GitLab integration token were being merged together
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/canon': patch
---
Remove leftover console.log from Container component.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/theme': patch
---
Update uncomfortably bright color in recently visited and top visited home page cards
+19 -1
View File
@@ -18,8 +18,26 @@ var path = require('path');
module.exports = {
root: true,
plugins: ['@spotify', 'notice', 'react', 'testing-library'],
plugins: ['@spotify', 'notice', 'react', 'testing-library', '@backstage'],
rules: {
'@backstage/no-mixed-plugin-imports': [
'error',
{
// TODO: Fix these either by right role or by moving things to new packages
excludedTargetPackages: [
'@backstage/plugin-catalog',
'@backstage/plugin-techdocs',
'@backstage/plugin-app',
'@backstage/plugin-catalog-backend',
'@backstage/test-utils',
'@backstage/plugin-auth-backend',
'@backstage/plugin-permission-backend',
'@backstage/plugin-kubernetes-backend',
'@backstage/config-loader',
'@backstage/plugin-app-backend'
],
}
],
'react/react-in-jsx-scope': 'off',
'notice/notice': [
'error',
+5
View File
@@ -35,6 +35,11 @@
rangeStrategy: 'replace',
matchSourceUrls: ['https://github.com/gregberge/svgr{/,}**'],
},
{
groupName: 'Module-federation monorepo packages',
rangeStrategy: 'replace',
matchSourceUrls: ['https://github.com/module-federation/core{/,}**'],
},
// We update yarn packages manually as it's gzip'd and we don't want to pollute the repository too much.
{
matchSourceUrls: ['https://github.com/yarnpkg/berry'],
@@ -43,6 +43,7 @@ bugfixes
builtins
bundler
bundlers
bursty
callout
CDNs
Chai
@@ -433,6 +434,7 @@ statefulsets
stdout
storable
storages
Streamable
stringified
stringify
subcommand
+3 -3
View File
@@ -52,17 +52,17 @@ jobs:
working-directory: ./example-app
- name: Login to GitHub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Build and push
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: './example-app'
file: ./example-app/packages/backend/Dockerfile
+2 -2
View File
@@ -321,12 +321,12 @@ jobs:
name: storybook
path: microsite/build/storybook
- uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: stable-reference-beta
path: microsite/build/api/stable/
- uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: next-reference-beta
path: microsite/build/api/next/
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
- name: Run Prettier on ADOPTERS.md
uses: creyD/prettier_action@31355f8eef017f8aeba2e0bc09d8502b13dbbad1 # v4.3
uses: creyD/prettier_action@8c18391fdc98ed0d884c6345f03975edac71b8f0 # v4.6
with:
# Modifies commit only if prettier autofixed the ADOPTERS.md
prettier_options: --config docs/prettier.config.js --write ADOPTERS.md
+2 -2
View File
@@ -325,13 +325,13 @@ jobs:
working-directory: microsite
- name: download stable reference (beta)
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: stable-reference-beta
path: api/stable/
- name: download next reference (beta)
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: next-reference-beta
path: api/next/
+1 -1
View File
@@ -54,7 +54,7 @@ jobs:
- run: yarn --cwd packages/canon build-storybook
- uses: chromaui/action@e8cc4c31775280b175a3c440076c00d19a9014d7 # v11
- uses: chromaui/action@1cfa065cbdab28f6ca3afaeb3d761383076a35aa # v11
with:
token: ${{ secrets.GITHUB_TOKEN }}
# projectToken intentionally shared to allow collaborators to run Chromatic on forks
+1
View File
@@ -284,3 +284,4 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/
| [Scalepoint](https://scalepoint.com) | [Yuriy Ostapenko](https://github.com/yuriyostapenko), [Dmytro Pasko](https://github.com/dimapasko), [Yuri Sedykh ](https://github.com/yuiri-sedykh), [Bartosz Wisniewski](https://github.com/Epgor) | Internal Developer Portal: Software Catalog with infrastructure resources and dependencies, Software Templates, TechDocs, Tech Radar, Kubernetes and Observability, as well as custom CI/CD components |
| [VR](https://www.vr.com.br) | [Felipe Gomes](https://www.linkedin.com/in/felipe-gomes-da-silva), [Tiago Garcia](https://www.linkedin.com/in/tiago-garcia-6301a925) | Internal portal for development squads, service catalog, documentation hub, and application mapping for the entire company ecosystem, simplifying cloud infrastructure construction through templates. |
| [Plata](https://platacard.mx/en) | [Shamil Ganiev](https://github.com/ganievs) | Internal Developer Portal for the whole engineering team |
| [Syngenta Digital](https://www.syngentadigital.com) | [Bitan Mallick](https://www.linkedin.com/in/bitanmallick) | Internal developer portal, designed to empower developers and streamline workflows. We use software catalog, tech-radar, software templates, tech-docs and various custom plugins to ensure an efficient and collaborative development experience. |
+10 -3
View File
@@ -26,6 +26,7 @@ These labels indicate what is needed to move an issue forward before it can be a
- `needs:bep` - The issue is an advanced addition that needs a [Backstage Enhancement Proposal](./beps/README.md).
- `needs:direction` - The issue needs direction from the owners of the area.
- `needs:discussion` - The way forward for this issue is unclear and it needs further discussion with the author and other participants.
- `needs:more-info` - The issue needs more information from the author.
- `needs:motivation` - It is not clear why this change is needed. The author should provide motivation for the change, for instance by giving examples of concrete use cases or scenarios.
- `needs:repro` - The issue cannot be reproduced by the owners of the area. The author should provide more information to help them reproduce the issue, if possible with a minimal reproduction repository.
@@ -81,11 +82,17 @@ These labels indicate that an issue is related to specific domains of expertise.
- `domain:tooling` - Tooling and automation in Node.js and GitHub Actions.
- `domain:web` - Frontend development using TypeScript and React.
## Workflow Labels
These labels indicate a workflow status for the owners.
- `workflow:do-not-merge` - The Pull Request should not be merged.
- `workflow:before-release` - Should be handled before the next main-line release.
- `workflow:after-release` - Should be handled after the next main-line release.
- `workflow:after-vacations` - To be handled once the owners return from vacation.
## General Labels
- `after vacations` - To be handled once the owners return from vacation.
- `do not merge` - The pull request should not be merged.
- `fix before release` - Should be handled before the next release.
- `good first issue` - Good for new contributors.
- `stale` - The issue or pull request has not seen any activity for a while and will be closed if no further activity is seen.
- `no stale` - The issue or pull request should not be closed due to inactivity.
+25 -23
View File
@@ -56,6 +56,18 @@ Scope: The Backstage design system, component library, as well as surrounding to
| Charles de Dreuille | Spotify | | [cdedreuille](https://github.com/cdedreuille) | `cdedreuille` |
| Patrik Oldsberg | Spotify | Cubic Belugas | [Rugvip](https://github.com/Rugvip) | `Rugvip` |
### Documentation
Team: @backstage/documentation-maintainers
Scope: The Backstage Documentation and Microsite, excluding the plugins listing
| Name | Organization | GitHub | Discord |
| --------------- | ------------- | ----------------------------------------------------- | ------------- |
| Andre Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` |
| Aramis Sennyey | DoorDash | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` |
| Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` |
### Framework
Team: @backstage/framework-maintainers
@@ -77,11 +89,11 @@ Team: @backstage/helm-chart-maintainers
Scope: The Backstage [Helm Chart(s)](https://github.com/backstage/charts).
| Name | Organization | Team | GitHub | Discord |
| -------------------- | ------------ | ---- | ---------------------------------------- | -------------- |
| Andrew Block | Red Hat | | [sabre1041](http://github.com/sabre1041) | sabre1041#2622 |
| Tom Coufal | Red Hat | | [tumido](http://github.com/tumido) | Tumi#4346 |
| Vincenzo Scamporlino | Spotify | | [vinzscam](http://github.com/vinzscam) | vinzscam#6944 |
| Name | Organization | Team | GitHub | Discord |
| -------------------- | ------------ | ---- | ---------------------------------------- | ---------------- |
| Andrew Block | Red Hat | | [sabre1041](http://github.com/sabre1041) | `sabre1041#2622` |
| Tom Coufal | Red Hat | | [tumido](http://github.com/tumido) | `Tumi#4346` |
| Vincenzo Scamporlino | Spotify | | [vinzscam](http://github.com/vinzscam) | `vinzscam#6944` |
### Home
@@ -89,12 +101,14 @@ Team: @backstage/home-maintainers
Scope: The Backstage home page and information architecture
| Name | Organization | Team | GitHub | Discord |
| ------------------------ | ------------ | -------------- | ---------------------------------------- | ----------------- |
| Avantika Iyer | Spotify | Infinite Buck$ | [tikabom](http://github.com/tikabom) | - |
| Emma Indal | Spotify | Infinite Buck$ | [emmaindal](http://github.com/emmaindal) | emmaindal#7503 |
| Djamaile Rahamat | Spotify | Infinite Buck$ | [djamaile](http://github.com/djamaile) | dyoqi |
| Raghunandan Balachandran | Spotify | Infinite Buck$ | [soapraj](http://github.com/soapraj) | raghunandanb#1114 |
| Name | Organization | Team | GitHub | Discord |
| ------------------ | ------------ | --------------- | ----------------------------------------- | ------- |
| Ainhoa Larumbe | Spotify | Imaginary Goats | [ainhoaL](http://github.com/ainhoaL) | - |
| Avantika Iyer | Spotify | Imaginary Goats | [tikabom](http://github.com/tikabom) | - |
| Daniel Jelčić | Spotify | Imaginary Goats | [djelcic](http://github.com/danieljelcic) | - |
| Eric Peterson | Spotify | Imaginary Goats | [iamEAP](http://github.com/iamEAP) | - |
| Musaab Elfaqih | Spotify | Imaginary Goats | [TheSabby](http://github.com/TheSabby) | - |
| Landry Zinda-Snead | Spotify | Imaginary Goats | [landryzs](http://github.com/landryzs) | - |
### Kubernetes
@@ -206,18 +220,6 @@ Scope: Tooling and Community Repo Maintainers for the Backstage [Community Plugi
| Vincenzo Scamporlino | Spotify | [vinzscam](https://github.com/vinzscam) | `vinzscam` |
| Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` |
### Documentation
Team: @backstage/documentation-maintainers
Scope: The Backstage Documentation and Microsite, excluding the plugins listing
| Name | Organization | GitHub | Discord |
| --------------- | ------------- | ----------------------------------------------------- | ------------- |
| Andre Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` |
| Aramis Sennyey | DoorDash | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` |
| Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` |
### Events
Team: @backstage/events-maintainers
+11 -212
View File
@@ -36,6 +36,12 @@ backend:
# keys:
# - secret: ${BACKEND_SECRET}
# Used for testing rate limiting locally
# rateLimit:
# windowMs: 1m
# incomingRequestLimit: 1
# ipAllowList: []
auth:
# TODO: once plugins have been migrated we can remove this, but right now it
# is require for the backend-next to work in this repo
@@ -64,83 +70,11 @@ backend:
# See README.md in the proxy-backend plugin for information on the configuration format
proxy:
endpoints:
'/circleci/api':
target: https://circleci.com/api/v1.1
headers:
Circle-Token: ${CIRCLECI_AUTH_TOKEN}
'/jenkins/api':
target: http://localhost:8080
headers:
Authorization: ${JENKINS_BASIC_AUTH_HEADER}
'/travisci/api':
target: https://api.travis-ci.com
changeOrigin: true
headers:
Authorization: ${TRAVISCI_AUTH_TOKEN}
travis-api-version: '3'
'/newrelic/apm/api':
target: https://api.newrelic.com/v2
headers:
X-Api-Key: ${NEW_RELIC_REST_API_KEY}
allowedHeaders:
- link
'/newrelic/api':
target: https://api.newrelic.com
headers:
X-Api-Key: ${NEW_RELIC_USER_KEY}
'/pagerduty':
target: https://api.pagerduty.com
headers:
Authorization: Token token=${PAGERDUTY_TOKEN}
'/buildkite/api':
target: https://api.buildkite.com/v2/
headers:
Authorization: ${BUILDKITE_TOKEN}
'/sentry/api':
target: https://sentry.io/api/
allowedMethods: ['GET']
headers:
Authorization: ${SENTRY_TOKEN}
'/ilert':
target: https://api.ilert.com
allowedMethods: ['GET', 'POST', 'PUT']
allowedHeaders: ['Authorization']
headers:
Authorization: ${ILERT_AUTH_HEADER}
'/airflow':
target: https://your.airflow.instance.com/api/v1
headers:
Authorization: ${AIRFLOW_BASIC_AUTH_HEADER}
'/gocd':
target: https://your.gocd.instance.com/go/api
allowedMethods: ['GET']
allowedHeaders: ['Authorization']
headers:
Authorization: Basic ${GOCD_AUTH_CREDENTIALS}
'/dynatrace':
target: https://your.dynatrace.instance.com/api/v2
headers:
Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}'
'/stackstorm':
target: https://your.stackstorm.instance.com/api
headers:
St2-Api-Key: ${ST2_API_KEY}
'/puppetdb':
target: https://your.puppetdb.instance.com
organization:
name: My Company
@@ -157,46 +91,6 @@ techdocs:
publisher:
type: 'local' # Alternatives - 'googleGcs' or 'awsS3' or 'azureBlobStorage' or 'openStackSwift'. Read documentation for using alternatives.
dynatrace:
baseUrl: https://your.dynatrace.instance.com
nomad:
addr: 0.0.0.0
# Score-cards sample configuration.
scorecards:
jsonDataUrl: https://raw.githubusercontent.com/Oriflame/backstage-plugins/main/plugins/score-card/sample-data/
wikiLinkTemplate: https://link-to-wiki/{id}
sentry:
organization: my-company
rollbar:
organization: my-company
# NOTE: The rollbar-backend & accountToken key may be deprecated in the future (replaced by a proxy config)
accountToken: my-rollbar-account-token
lighthouse:
baseUrl: http://localhost:3003
kubernetes:
serviceLocatorMethod:
type: 'multiTenant'
clusterLocatorMethods:
- type: 'config'
clusters: []
kafka:
clientId: backstage
clusters:
- name: cluster
dashboardUrl: https://akhq.io/
brokers:
- localhost:9092
allure:
baseUrl: http://localhost:5050/allure-docker-service
integrations:
github:
- host: github.com
@@ -244,7 +138,6 @@ integrations:
secretAccessKey: ${AWS_SECRET_ACCESS_KEY}
catalog:
useUrlReadersSearch: true
import:
entityFilename: catalog-info.yaml
pullRequestBranchName: backstage-integration
@@ -269,26 +162,6 @@ catalog:
plugins:
- catalog
- search
processors:
ldapOrg:
### Example for how to add your enterprise LDAP server
# providers:
# - target: ldaps://ds.example.net
# bind:
# dn: uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net
# secret: ${LDAP_SECRET}
# users:
# dn: ou=people,ou=example,dc=example,dc=net
# options:
# filter: (uid=*)
# map:
# description: l
# groups:
# dn: ou=access,ou=groups,ou=example,dc=example,dc=net
# options:
# filter: (&(objectClass=some-group-class)(!(groupType=email)))
locations:
# Add a location here to ingest it, for example from a URL:
#
@@ -325,13 +198,14 @@ catalog:
target: ../../plugins/scaffolder-backend/sample-templates/all-templates.yaml
rules:
- allow: [Template]
scaffolder:
# Use to customize default commit author info used when new components are created
# defaultAuthor:
# name: Scaffolder
# email: scaffolder@backstage.io
defaultAuthor:
name: Scaffolder
email: scaffolder@backstage.io
# Use to customize the default commit message when new components are created
# defaultCommitMessage: 'Initial commit'
defaultCommitMessage: 'Initial commit'
auth:
### Add auth.keyStore.provider to more granularly control how to store JWK data when running
@@ -422,80 +296,5 @@ auth:
myproxy: {}
guest: {}
costInsights:
engineerCost: 200000
engineerThreshold: 0.5
products:
computeEngine:
name: Compute Engine
icon: compute
cloudDataflow:
name: Cloud Dataflow
icon: data
cloudStorage:
name: Cloud Storage
icon: storage
bigQuery:
name: BigQuery
icon: search
events:
name: Events
icon: data
metrics:
DAU:
name: Daily Active Users
default: true
MSC:
name: Monthly Subscribers
currencies:
engineers:
label: 'Engineers 🛠'
unit: 'engineer'
usd:
label: 'US Dollars 💵'
kind: 'USD'
unit: 'dollar'
prefix: '$'
rate: 1
carbonOffsetTons:
label: 'Carbon Offset Tons ♻️⚖️s'
kind: 'CARBON_OFFSET_TONS'
unit: 'carbon offset ton'
rate: 3.5
beers:
label: 'Beers 🍺'
kind: 'BEERS'
unit: 'beer'
rate: 4.5
pintsIceCream:
label: 'Pints of Ice Cream 🍦'
kind: 'PINTS_OF_ICE_CREAM'
unit: 'ice cream pint'
rate: 5.5
pagerDuty:
eventsBaseUrl: 'https://events.pagerduty.com/v2'
jenkins:
instances:
- name: default
baseUrl: https://jenkins.example.com
username: backstage-bot
apiKey: 123456789abcdef0123456789abcedf012
azureDevOps:
host: dev.azure.com
token: my-token
organization: my-company
apacheAirflow:
baseUrl: https://your.airflow.instance.com
gocd:
baseUrl: https://your.gocd.instance.com
stackstorm:
webUrl: https://your.stackstorm.webui.instance.com
permission:
enabled: true
+5
View File
@@ -8,6 +8,11 @@ const nextConfig = {
images: {
unoptimized: true,
},
typescript: {
// Ignore TypeScript errors during build - safe for React 18/19 compatibility issues
// These are type-level conflicts that don't affect runtime behavior
ignoreBuildErrors: true,
},
};
const withMDX = createMDX({});
+23 -10
View File
@@ -3,24 +3,35 @@
"version": "0.1.0",
"private": true,
"scripts": {
"build": "npm run build:css && next build",
"build:css": "node scripts/build-css.js",
"prebuild": "yarn sync:css",
"build": "next build",
"lint": "next lint",
"start": "npm run build:css && next dev"
"prestart": "yarn sync:css",
"start": "concurrently \"yarn sync:css:watch\" \"next dev\"",
"sync:css": "node scripts/sync-css.js",
"sync:css:watch": "node scripts/sync-css.js --watch"
},
"resolutions": {
"@types/react": "19.1.8",
"@types/react-dom": "19.1.6"
},
"dependencies": {
"@codemirror/lang-sass": "^6.0.2",
"@codemirror/view": "^6.34.4",
"@lezer/highlight": "^1.2.1",
"@mdx-js/loader": "^3.1.0",
"@mdx-js/react": "^3.1.0",
"@next/mdx": "^15.1.4",
"@next/mdx": "15.3.4",
"@storybook/react": "^8.6.8",
"@uiw/codemirror-themes": "^4.23.7",
"@uiw/react-codemirror": "^4.23.7",
"html-react-parser": "^5.2.5",
"motion": "^12.4.1",
"next": "14.2.26",
"react": "^18.0.2",
"react-dom": "^18.0.2",
"next": "15.3.4",
"next-mdx-remote-client": "^2.1.2",
"prop-types": "^15.8.1",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-frame-component": "^5.2.7",
"shiki": "^1.26.1",
"storybook": "^8.6.8"
@@ -28,10 +39,12 @@
"devDependencies": {
"@types/mdx": "^2.0.13",
"@types/node": "^20",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@types/react": "19.1.8",
"@types/react-dom": "19.1.6",
"chokidar": "^3.6.0",
"concurrently": "^8.2.2",
"eslint": "^8",
"eslint-config-next": "14.2.23",
"eslint-config-next": "15.3.4",
"lightningcss": "^1.28.2",
"typescript": "^5"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
@font-face{font-family:CircularSp;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff)format("woff")}[data-theme=dark][data-theme-name=spotify]{--canon-font-text:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--canon-font-title:CircularSpTitle,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--canon-font-regular:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--canon-gray-1:#191919;--canon-gray-2:#242424;--canon-gray-3:#373737;--canon-gray-4:#464646;--canon-gray-5:#575757;--canon-gray-6:#7b7b7b;--canon-gray-7:#9e9e9e;--canon-gray-8:#b4b4b4;--canon-bg:#000;--canon-bg-surface-1:#191919;--canon-bg-surface-2:#242424;--canon-bg-solid:#1ed760;--canon-bg-solid-hover:#3be477;--canon-bg-solid-pressed:#1abc54;--canon-bg-solid-disabled:#0f6c30;--canon-bg-tint:#242424;--canon-bg-tint-hover:#202020;--canon-bg-tint-pressed:#292929;--canon-bg-tint-disabled:#fffc;--canon-bg-danger:#3b1219;--canon-bg-warning:#302008;--canon-bg-success:#132d21;--canon-bg-underline:#d16ecb;--canon-fg-primary:#fff;--canon-fg-secondary:#9e9e9e;--canon-fg-link:#fff;--canon-fg-link-hover:#fff;--canon-fg-disabled:#575757;--canon-fg-solid:#000;--canon-fg-solid-disabled:#083618;--canon-fg-tint:#fff;--canon-fg-tint-disabled:#575757;--canon-fg-danger:#e22b2b;--canon-fg-warning:#e36d05;--canon-fg-success:#1db954;--canon-border:var(--canon-gray-3);--canon-border-hover:#fff6;--canon-border-pressed:#ffffff80;--canon-border-disabled:#fff3;--canon-border-danger:#f87a7a;--canon-border-warning:#e36d05;--canon-border-success:#53db83;--canon-ring:#fff3}#root{padding-top:var(--header-height)}.canon-Button,.canon-IconButton{border-radius:var(--canon-radius-3);transition:background-color .2s ease-in-out,color .2s ease-in-out,box-shadow .2s ease-in-out}.canon-Button--variant-primary,.canon-IconButton--variant-primary{&:hover{box-shadow:inset 0 0 0 1px var(--canon-bg-solid);color:var(--canon-fg-primary);background-color:#0000}&:active{background-color:#1ed7601a}&:disabled{background-color:var(--canon-bg-solid-disabled);color:var(--canon-fg-solid-disabled);box-shadow:none}}.canon-Button[data-size=medium],.canon-Button[data-size=small]{padding-inline:var(--canon-space-3)}.canon-MenuTrigger{all:unset;display:inline-flex}.canon-MenuPopup{box-sizing:border-box;max-width:21.25rem}.canon-MenuSubmenuTrigger,.canon-MenuItem{height:auto;min-height:2rem}.canon-Text{font-family:var(--canon-font-text)}.canon-Heading{font-family:var(--canon-font-title)}.canon-TableRow{border-radius:var(--canon-radius-4);border:none}.canon-TableRow:hover td:first-child{border-top-left-radius:var(--canon-radius-2);border-bottom-left-radius:var(--canon-radius-2)}.canon-TableRow:hover td:last-child{border-top-right-radius:var(--canon-radius-2);border-bottom-right-radius:var(--canon-radius-2)}.canon-TableBody:before,.canon-TableBody:after{line-height:var(--canon-space-1);content:"";display:block}.canon-TableHeader .canon-TableRow{border-bottom:1px solid var(--canon-border)}.canon-TableHead{font-size:var(--canon-font-size-2);color:var(--canon-fg-secondary);font-weight:var(--canon-font-weight-regular)}.canon-ScrollAreaRoot{width:100%;height:unset}.canon-TabsIndicator{background-color:var(--canon-bg-underline)}.canon-TabsTab[data-selected]{background:radial-gradient(at bottom,#d16ecb40 0%,#0000 95%)}
-39
View File
@@ -1,39 +0,0 @@
const fs = require('fs');
const path = require('path');
const { bundle } = require('lightningcss');
const source = '../../packages/canon/src/css';
const destination = '../public';
const source1 = path.join(__dirname, `${source}/core.css`);
const destination1 = path.join(__dirname, `${destination}/core.css`);
const source2 = path.join(__dirname, `${source}/components.css`);
const destination2 = path.join(__dirname, `${destination}/components.css`);
// Function to bundle and copy the CSS file
const bundleAndCopyFile = async (source, destination) => {
try {
const result = await bundle({
filename: source,
minify: true,
});
fs.writeFileSync(destination, result.code);
console.log('File bundled and copied successfully!');
} catch (err) {
console.error('Error bundling file:', err);
}
};
// Initial bundle and copy
Promise.all([
bundleAndCopyFile(source1, destination1),
bundleAndCopyFile(source2, destination2),
])
.then(() => {
// Add an empty line after all operations are complete - It looks better in the terminal :)
console.log('');
})
.catch(err => {
console.error('Error in processing files:', err);
});
+149
View File
@@ -0,0 +1,149 @@
const fs = require('fs');
const path = require('path');
const { bundle } = require('lightningcss');
const chokidar = require('chokidar');
// Configuration
const config = {
canonPath: '../../packages/canon',
publicPath: '../public',
files: [
{
source: 'css/styles.css',
destination: 'theme-backstage.css',
name: 'Main Styles',
},
{
source: '.storybook/themes/spotify.css',
destination: 'theme-spotify.css',
name: 'Spotify Theme',
},
],
};
class CSSSync {
constructor() {
this.canonPath = path.resolve(__dirname, config.canonPath);
this.publicPath = path.resolve(__dirname, config.publicPath);
this.isWatching = process.argv.includes('--watch');
}
async syncFile(fileConfig) {
const sourcePath = path.join(this.canonPath, fileConfig.source);
const destPath = path.join(this.publicPath, fileConfig.destination);
try {
// Check if source file exists
if (!fs.existsSync(sourcePath)) {
console.warn(`⚠️ Source file not found: ${sourcePath}`);
return false;
}
// Ensure destination directory exists
fs.mkdirSync(path.dirname(destPath), { recursive: true });
// Bundle and optimize CSS
const result = await bundle({
filename: sourcePath,
minify: true,
});
// Write to destination
fs.writeFileSync(destPath, result.code);
console.log(
`${fileConfig.name}: ${fileConfig.source}${fileConfig.destination}`,
);
return true;
} catch (error) {
console.error(`❌ Error syncing ${fileConfig.name}:`, error.message);
return false;
}
}
async syncAll() {
console.log('🔄 Syncing CSS files...\n');
let successCount = 0;
for (const fileConfig of config.files) {
if (await this.syncFile(fileConfig)) {
successCount++;
}
}
console.log(
`\n✨ Synced ${successCount}/${config.files.length} CSS files successfully!`,
);
if (successCount > 0) {
console.log('\n📁 Available CSS files in public/:');
config.files.forEach(file => {
const destPath = path.join(this.publicPath, file.destination);
if (fs.existsSync(destPath)) {
const stats = fs.statSync(destPath);
const size = (stats.size / 1024).toFixed(2);
console.log(`${file.destination} (${size} KB)`);
}
});
}
}
startWatching() {
console.log('👀 Watching for CSS changes...\n');
// Watch all source files
const watchPaths = config.files.map(file =>
path.join(this.canonPath, file.source),
);
const watcher = chokidar.watch(watchPaths, {
ignored: /node_modules/,
persistent: true,
});
watcher.on('change', async filePath => {
console.log(
`\n🔄 Change detected: ${path.relative(this.canonPath, filePath)}`,
);
// Find which file changed and sync it
const fileConfig = config.files.find(file =>
filePath.endsWith(file.source.replace(/\//g, path.sep)),
);
if (fileConfig) {
await this.syncFile(fileConfig);
}
});
watcher.on('error', error => console.error('❌ Watch error:', error));
// Handle process termination
process.on('SIGINT', () => {
console.log('\n👋 Stopping CSS sync...');
watcher.close();
process.exit(0);
});
}
async run() {
console.log('🎨 Canon CSS Sync Tool\n');
console.log(`📂 Canon path: ${this.canonPath}`);
console.log(`📂 Public path: ${this.publicPath}\n`);
// Initial sync
await this.syncAll();
// Watch for changes if requested
if (this.isWatching) {
this.startWatching();
}
}
}
// Run the sync tool
const cssSync = new CSSSync();
cssSync.run().catch(error => {
console.error('❌ CSS Sync failed:', error);
process.exit(1);
});
@@ -0,0 +1,13 @@
import { Changelog } from '@/components/Changelog';
# Changelog
<Changelog />
## Version 0.1.0
We're excited to share the initial release of Canon 💚 In this first alpha version,
you'll find the foundation of our design system: a set of versatile layout components
and a handful of essential atomic elements to help you get started. While Canon is
still in its early stages, it's ready for exploration and we'd love for you to give
it a try and share your feedback.
@@ -0,0 +1,25 @@
import { components, layoutComponents } from '@/utils/data';
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const { default: Component } = await import(
`@/content/components/${slug}.mdx`
);
return <Component />;
}
export function generateStaticParams() {
const list = [...components, ...layoutComponents];
return list.map(component => ({
slug: component.slug,
}));
}
export const dynamicParams = false;
@@ -1,75 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { AvatarSnippet } from '@/snippets/stories-snippets';
import { avatarPropDefs } from './props';
# Avatar
An avatar component with a fallback for initials.
<Snippet
align="center"
py={4}
preview={<AvatarSnippet story="Default" />}
code={`<Avatar src="https://avatars.githubusercontent.com/u/1540635?v=4" name="Charles de Dreuille" />`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Avatar } from '@backstage/canon';
<Avatar src="https://avatars.githubusercontent.com/u/1540635?v=4" name="Charles de Dreuille" />`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `canon-AvatarRoot`
- `canon-AvatarRoot[data-size='small']`
- `canon-AvatarRoot[data-size='medium']`
- `canon-AvatarRoot[data-size='large']`
- `canon-AvatarImage`
- `canon-AvatarFallback`
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={avatarPropDefs} />
## Examples
### Sizes
Avatar sizes can be set using the `size` prop.
<Snippet
align="center"
py={4}
open
preview={<AvatarSnippet story="Sizes" />}
code={`<Flex gap="4" direction="column">
<Avatar src="https://avatars.githubusercontent.com/u/1540635?v=4" name="Charles de Dreuille" size="small" />
<Avatar src="https://avatars.githubusercontent.com/u/1540635?v=4" name="Charles de Dreuille" size="medium" />
<Avatar src="https://avatars.githubusercontent.com/u/1540635?v=4" name="Charles de Dreuille" size="large" />
</Flex>`}
/>
### Fallback
If the image is not available, the avatar will show the initials of the name.
<Snippet
align="center"
py={4}
open
preview={<AvatarSnippet story="Fallback" />}
code={`<Avatar src="https://avatars.githubusercontent.com/u/15406AAAAAAAAA" name="Charles de Dreuille" />`}
/>
@@ -1,19 +0,0 @@
import { classNamePropDefs, stylePropDefs } from '@/utils/propDefs';
import type { PropDef } from '@/utils/propDefs';
export const avatarPropDefs: Record<string, PropDef> = {
src: {
type: 'string',
},
name: {
type: 'string',
},
size: {
type: 'enum',
values: ['small', 'medium', 'large'],
default: 'medium',
responsive: true,
},
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,24 +0,0 @@
import {
classNamePropDefs,
displayPropDefs,
heightPropDefs,
positionPropDefs,
stylePropDefs,
widthPropDefs,
} from '../../../../utils/propDefs';
import type { PropDef } from '../../../../utils/propDefs';
export const boxPropDefs: Record<string, PropDef> = {
as: {
type: 'enum',
values: ['div', 'span'],
default: 'div',
responsive: true,
},
...widthPropDefs,
...heightPropDefs,
...positionPropDefs,
...displayPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,136 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { ButtonSnippet } from '@/snippets/stories-snippets';
import { buttonVariants } from '@/snippets/code-snippets';
import { buttonPropDefs } from './props';
# Button
A button component that can be used to trigger actions.
<Snippet
align="center"
py={4}
preview={<ButtonSnippet story="Variants" />}
code={`<Inline alignY="center">
<Button iconStart="cloud" variant="primary">
Button
</Button>
<Button iconStart="cloud" variant="secondary">
Button
</Button>
<Button iconStart="cloud" variant="tertiary">
Button
</Button>
</Inline>`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Button } from '@backstage/canon';
<Button />
`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
<CodeBlock
code={`<Button className="button" />`}
/>
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={buttonPropDefs} />
## Examples
### Variants
Here's a view when buttons have different variants.
<Snippet
align="center"
py={4}
open
preview={<ButtonSnippet story="Variants" />}
code={buttonVariants}
/>
### Sizes
Here's a view when buttons have different sizes.
<Snippet
align="center"
py={4}
open
preview={<ButtonSnippet story="Sizes" />}
code={`<Inline alignY="center">
<Button size="small">Small</Button>
<Button size="medium">Medium</Button>
</Inline>`}
/>
### With Icons
Here's a view when buttons have icons.
<Snippet
align="center"
py={4}
open
preview={<ButtonSnippet story="WithIcons" />}
code={`<Inline alignY="center">
<Button iconStart="cloud">Button</Button>
<Button iconEnd="chevronRight">Button</Button>
<Button iconStart="cloud" iconEnd="chevronRight">Button</Button>
</Inline>`}
/>
### Full width
Here's a view when buttons are full width.
<Snippet
align="center"
py={4}
open
preview={<ButtonSnippet story="FullWidth" />}
code={`<Flex style={{ width: '300px' }}>
<Button fullWidth>Full width</Button>
</Flex>`}
/>
### Disabled
Here's a view when buttons are disabled.
<Snippet
align="center"
py={4}
open
preview={<ButtonSnippet story="Disabled" />}
code={`<Button disabled>Button</Button>`}
/>
### Responsive
Here's a view when buttons are responsive.
<CodeBlock
code={`<Button variant={{ initial: 'primary', lg: 'secondary' }}>
Responsive Button
</Button>`}
/>
@@ -1,19 +0,0 @@
import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs';
import type { PropDef } from '../../../../utils/propDefs';
export const buttonPropDefs: Record<string, PropDef> = {
variant: {
type: 'enum',
values: ['primary', 'secondary'],
default: 'primary',
responsive: true,
},
size: {
type: 'enum',
values: ['small', 'medium'],
default: 'medium',
responsive: true,
},
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,66 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { CheckboxSnippet } from '@/snippets/stories-snippets';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { BaseUI } from '@/components/HeadlessBanners/BaseUI';
import { checkboxPropDefs } from './props';
# Checkbox
A checkbox component that can be used to trigger actions.
<Snippet
align="center"
py={4}
preview={<CheckboxSnippet story="Default" />}
code={`<Checkbox label="Accept terms and conditions" />`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Checkbox } from '@backstage/canon';
<Checkbox />
`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
<CodeBlock
code={`<Checkbox className="checkbox" />`}
/>
</Tabs.Panel>
</Tabs.Root>
## API reference
<BaseUI href="https://base-ui.com/react/components/checkbox" />
<PropsTable data={checkboxPropDefs} />
## Examples
### All variants
Here's a view when checkboxes have different variants.
<Snippet
align="center"
py={4}
open
preview={<CheckboxSnippet story="AllVariants" />}
code={`<Inline alignY="center">
<Checkbox />
<Checkbox checked />
<Checkbox label="Checkbox" />
<Checkbox label="Checkbox" checked />
</Inline>`}
/>
@@ -1,113 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { CollapsibleSnippet } from '@/snippets/stories-snippets';
import {
collapsibleRootPropDefs,
collapsibleTriggerPropDefs,
collapsiblePanelPropDefs,
} from './props';
# Collapsible
An avatar component with a fallback for initials.
<Snippet
align="center"
py={4}
height={240}
preview={<CollapsibleSnippet story="Default" />}
code={`<Collapsible.Root>
<Collapsible.Trigger render={(props, state) => (
<Button {...props}>
{state.open ? 'Close Panel' : 'Open Panel'}
</Button>
)} />
<Collapsible.Panel>
<Box>
<Text>It's the edge of the world and all of Western civilization</Text>
<Text>The sun may rise in the East, at least it settled in a final location</Text>
<Text>It's understood that Hollywood sells Californication</Text>
</Box>
</Collapsible.Panel>
</Collapsible.Root>`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Collapsible } from '@backstage/canon';
<Collapsible.Root>
<Collapsible.Trigger render={(props, state) => (
<Button {...props}>
{state.open ? 'Close Panel' : 'Open Panel'}
</Button>
)} />
<Collapsible.Panel>Your content</Collapsible.Panel>
</Collapsible.Root>`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `canon-CollapsibleRoot`
- `canon-CollapsibleTrigger`
- `canon-CollapsiblePanel`
</Tabs.Panel>
</Tabs.Root>
## API reference
### Collapsible.Root
Groups all parts of the collapsible. Renders a `<div>` element.
<PropsTable data={collapsibleRootPropDefs} />
### Collapsible.Trigger
The trigger by default render a simple unstyled button. Because menus can be rendered in different ways, we recommend
using the `render` prop to render a custom trigger.
<CodeBlock
code={`<Collapsible.Trigger render={props => <Button {...props} />} />`}
/>
<PropsTable data={collapsibleTriggerPropDefs} />
### Collapsible.Panel
A panel with the collapsible contents. Renders a `<div>` element.
<PropsTable data={collapsiblePanelPropDefs} />
## Examples
Open the panel by default by setting the `defaultOpen` prop to `true`.
<Snippet
align="center"
py={4}
open
preview={<CollapsibleSnippet story="Open" />}
code={`<Collapsible.Root defaultOpen>
<Collapsible.Trigger render={(props, state) => (
<Button {...props}>
{state.open ? 'Close Panel' : 'Open Panel'}
</Button>
)} />
<Collapsible.Panel>
<Box>
<Text>It's the edge of the world and all of Western civilization</Text>
<Text>The sun may rise in the East, at least it settled in a final location</Text>
<Text>It's understood that Hollywood sells Californication</Text>
</Box>
</Collapsible.Panel>
</Collapsible.Root>`}
/>
@@ -1,43 +0,0 @@
import {
classNamePropDefs,
stylePropDefs,
renderPropDefs,
} from '@/utils/propDefs';
import type { PropDef } from '@/utils/propDefs';
export const collapsibleRootPropDefs: Record<string, PropDef> = {
defaultOpen: {
type: 'boolean',
default: 'false',
},
open: {
type: 'boolean',
},
onOpenChange: {
type: 'enum',
values: ['(open) => void'],
},
...renderPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
export const collapsibleTriggerPropDefs: Record<string, PropDef> = {
...renderPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
export const collapsiblePanelPropDefs: Record<string, PropDef> = {
hiddenUntilFound: {
type: 'boolean',
default: 'false',
},
keepMounted: {
type: 'boolean',
default: 'false',
},
...renderPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,12 +0,0 @@
import {
classNamePropDefs,
stylePropDefs,
gapPropDefs,
} from '../../../../utils/propDefs';
import type { PropDef } from '../../../../utils/propDefs';
export const containerPropDefs: Record<string, PropDef> = {
...gapPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,83 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import {
flexFAQ1,
flexSimple,
flexResponsive,
flexAlign,
} from '@/snippets/code-snippets';
import { Snippet } from '@/components/Snippet';
import { FlexSnippet } from '@/snippets/stories-snippets';
import { flexPropDefs } from './props';
import { spacingPropDefs } from '../../../../utils/propDefs';
# Flex
This is the flex container component. It will help to define the number of
columns that will be used in the grid. You can also define the gap between the
columns. All values are responsive.
<Snippet
py={4}
align="center"
preview={<FlexSnippet story="Default" />}
code={`<Flex>
<DecorativeBox />
<DecorativeBox />
<DecorativeBox />
</Flex>`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Flex } from '@backstage/canon';
<Flex />
`}
/>
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={flexPropDefs} />
The grid component also accepts all the spacing props from the Box component.
<PropsTable data={spacingPropDefs} />
## Common questions
### Can I stack horizontally?
The Flex component only allows for stacking elements vertically. If you want
to create a column layout, please use the Grid component.
<CodeBlock code={flexFAQ1} />
## Examples
### Simple
A simple example of how to use the Flex component.
<CodeBlock code={flexSimple} />
### Responsive
The Flex component also supports responsive values, making it easy to create
responsive designs.
<CodeBlock code={flexResponsive} />
### Align
The Flex component also supports responsive alignment, making it easy to
create responsive designs.
<CodeBlock code={flexAlign} />
@@ -1,27 +0,0 @@
import {
PropDef,
childrenPropDefs,
classNamePropDefs,
stylePropDefs,
} from '../../../../utils/propDefs';
export const flexPropDefs: Record<string, PropDef> = {
align: {
type: 'enum',
values: ['start', 'center', 'end', 'baseline', 'stretch'],
responsive: true,
},
direction: {
type: 'enum',
values: ['row', 'column', 'row-reverse', 'column-reverse'],
responsive: true,
},
justify: {
type: 'enum',
values: ['start', 'center', 'end', 'between'],
responsive: true,
},
...childrenPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,59 +0,0 @@
import {
PropDef,
childrenPropDefs,
classNamePropDefs,
stylePropDefs,
} from '../../../../utils/propDefs';
const columnsValues = [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
];
export const gridPropDefs: Record<string, PropDef> = {
columns: {
type: 'enum | string',
values: [...columnsValues, 'auto'],
responsive: true,
default: 'auto',
},
...childrenPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
export const gridItemPropDefs: Record<string, PropDef> = {
colSpan: {
type: 'enum | string',
values: [...columnsValues, 'full'],
responsive: true,
},
rowSpan: {
type: 'enum | string',
values: [...columnsValues, 'full'],
responsive: true,
},
start: {
type: 'enum | string',
values: [...columnsValues, 'auto'],
responsive: true,
},
end: {
type: 'enum | string',
values: [...columnsValues, 'auto'],
responsive: true,
},
...childrenPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,90 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { HeadingSnippet } from '@/snippets/stories-snippets';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { headingPropDefs } from './props';
# Heading
Headings are used to structure the content of your page.
<Snippet
py={4}
preview={<HeadingSnippet story="Title1" />}
code={`<Heading variant="title1">Hello World!</Heading>`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Heading } from '@backstage/canon';
<Heading />
`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
<CodeBlock
code={`<Heading className="heading" />`}
/>
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={headingPropDefs} />
## Examples
### All variants
The `Heading` component has a `variant` prop that can be used to change the
appearance of the heading.
<Snippet
py={2}
open
preview={<HeadingSnippet story="AllVariants" />}
code={`<Flex direction="column" gap="4">
<Heading variant="display">Display</Heading>
<Heading variant="title1">Title 1</Heading>
<Heading variant="title2">Title 2</Heading>
<Heading variant="title3">Title 3</Heading>
<Heading variant="title4">Title 4</Heading>
</Flex>`}
/>
### Truncate
The `Heading` component has a `truncate` prop that can be used to truncate the
heading.
<Snippet
py={2}
open
preview={<HeadingSnippet story="Truncate" />}
code={`<Heading style={{ maxWidth: '400px' }} truncate>
A man looks at a painting in a museum and says, “Brothers and sisters I
have none, but that man&apos;s father is my father's son.” Who is
in the painting?
</Heading>`}
/>
### Responsive
You can also use the `variant` prop to change the appearance of the text based
on the screen size.
<CodeBlock
code={`<Heading variant={{ initial: 'title2', lg: 'title1' }}>
Responsive heading
</Heading>`}
/>
@@ -1,21 +0,0 @@
import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs';
import type { PropDef } from '../../../../utils/propDefs';
export const headingPropDefs: Record<string, PropDef> = {
variant: {
type: 'enum',
values: ['display', 'title1', 'title2', 'title3', 'title4', 'title5'],
responsive: true,
},
children: {
type: 'enum',
values: ['ReactNode'],
responsive: false,
},
truncate: {
type: 'boolean',
default: 'false',
},
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,97 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { IconButtonSnippet } from '@/snippets/stories-snippets';
import { iconButtonVariants } from '@/snippets/code-snippets';
import { iconButtonPropDefs } from './props';
# Icon Button
A button component with a single icon that can be used to trigger actions.
<Snippet
align="center"
py={4}
preview={<IconButtonSnippet story="Variants" />}
code={`<Flex align="center">
<IconButton icon="cloud" variant="primary" />
<IconButton icon="cloud" variant="secondary" />
</Flex>`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { IconButton } from '@backstage/canon';
<IconButton />
`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
<CodeBlock
code={`<IconButton className="canon-IconButton" />`}
/>
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={iconButtonPropDefs} />
## Examples
### Variants
Here's a view when buttons have different variants.
<Snippet
align="center"
py={4}
open
preview={<IconButtonSnippet story="Variants" />}
code={iconButtonVariants}
/>
### Sizes
Here's a view when buttons have different sizes.
<Snippet
align="center"
py={4}
open
preview={<IconButtonSnippet story="Sizes" />}
code={`<Flex align="center">
<IconButton icon="cloud" size="small" />
<IconButton icon="cloud" size="medium" />
</Flex>`}
/>
### Disabled
Here's a view when buttons are disabled.
<Snippet
align="center"
py={4}
open
preview={<IconButtonSnippet story="Disabled" />}
code={`<IconButton icon="cloud" disabled />`}
/>
### Responsive
Here's a view when buttons are responsive.
<CodeBlock
code={`<IconButton icon="cloud" variant={{ initial: 'primary', lg: 'secondary' }} />`}
/>
@@ -1,20 +0,0 @@
import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs';
import type { PropDef } from '../../../../utils/propDefs';
export const iconButtonPropDefs: Record<string, PropDef> = {
variant: {
type: 'enum',
values: ['primary', 'secondary'],
default: 'primary',
responsive: true,
},
size: {
type: 'enum',
values: ['small', 'medium'],
default: 'medium',
responsive: true,
},
icon: { type: 'enum', values: 'icon', responsive: false },
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,44 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { IconSnippet } from '@/snippets/stories-snippets';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { iconPropDefs } from './props';
# Icon
Icons are used to represent an action or a state.
<Snippet
py={4}
align="center"
preview={<IconSnippet story="Default" />}
code={`<Icon name="heart" />`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Icon } from '@backstage/canon';
<Icon />
`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
<CodeBlock
code={`<Icon className="icon" />`}
/>
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={iconPropDefs} />
@@ -1,84 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import {
MenuSnippet,
ButtonSnippet,
LinkSnippet,
} from '@/snippets/stories-snippets';
import { linkPropDefs } from './props';
# Link
A link component that renders a `<a>` element.
<Snippet
align="center"
py={4}
preview={<LinkSnippet story="Default" />}
code={`<Link href="https://backstage.io">Sign up for Backstage</Link>`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Link } from '@backstage/canon';
<Link href="https://backstage.io">Sign up for Backstage</Link>`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `canon-Link`
- `canon-Link[data-variant='body']`
- `canon-Link[data-variant='subtitle']`
- `canon-Link[data-variant='caption']`
- `canon-Link[data-variant='label']`
- `canon-Link[data-weight='regular']`
- `canon-Link[data-weight='bold']`
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={linkPropDefs} />
## Examples
### Variants
Here's a view when links have different variants.
<Snippet
align="center"
py={4}
open
preview={<LinkSnippet story="AllVariants" />}
code={`<Flex gap="4" direction="column">
<Link href="https://canon.backstage.io" variant="subtitle" />
<Link href="https://canon.backstage.io" variant="body" />
<Link href="https://canon.backstage.io" variant="caption" />
<Link href="https://canon.backstage.io" variant="label" />
</Flex>`}
/>
### Weights
Here's a view when links have different weights.
<Snippet
align="center"
py={4}
open
preview={<LinkSnippet story="AllWeights" />}
code={`<Flex gap="4" direction="column">
<Link href="https://canon.backstage.io" weight="regular" />
<Link href="https://canon.backstage.io" weight="bold" />
</Flex>`}
/>
@@ -1,22 +0,0 @@
import { classNamePropDefs, stylePropDefs } from '@/utils/propDefs';
import type { PropDef } from '@/utils/propDefs';
export const linkPropDefs: Record<string, PropDef> = {
to: {
type: 'string',
},
variant: {
type: 'enum',
values: ['subtitle', 'body', 'caption', 'label'],
default: 'body',
responsive: true,
},
weight: {
type: 'enum',
values: ['regular', 'bold'],
default: 'regular',
responsive: true,
},
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,202 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { MenuSnippet } from '@/snippets/stories-snippets';
import { BaseUI } from '@/components/HeadlessBanners/BaseUI';
import {
menuRootPropDefs,
menuTriggerPropDefs,
menuPositionerPropDefs,
menuItemPropDefs,
} from './props';
# Menu
A list of actions in a dropdown, enhanced with keyboard navigation.
<Snippet
align="center"
py={4}
preview={<MenuSnippet story="Default" />}
code={`<Menu.Root>
<Menu.Trigger
render={props => (
<Button
{...props}
size="medium"
variant="secondary"
iconEnd="chevron-down"
>
Menu
</Button>
)}
/>
<Menu.Portal>
<Menu.Positioner sideOffset={8} align="start">
<Menu.Popup>
<Menu.Item>Settings</Menu.Item>
<Menu.Item>Invite new members</Menu.Item>
<Menu.Item>Download app</Menu.Item>
<Menu.Item>Log out</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>
</Menu.Root>`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Menu } from '@backstage/canon';
<Menu.Root>
<Menu.Trigger />
<Menu.Portal>
<Menu.Positioner>
<Menu.Popup>
<Menu.Item />
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>
</Menu.Root>`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `canon-MenuTrigger`
- `canon-MenuBackdrop`
- `canon-MenuPositioner`
- `canon-MenuPopup`
- `canon-MenuArrow`
- `canon-MenuItem`
- `canon-MenuGroup`
- `canon-MenuGroupLabel`
- `canon-MenuRadioGroup`
- `canon-MenuRadioItem`
- `canon-MenuRadioItemIndicator`
- `canon-MenuCheckboxItem`
- `canon-MenuCheckboxItemIndicator`
- `canon-MenuSubmenuTrigger`
- `canon-MenuSeparator`
</Tabs.Panel>
</Tabs.Root>
## API reference
<BaseUI href="https://base-ui.com/react/components/menu" />
### Menu.Root
Groups all parts of the menu. Doesn't render its own HTML element.
<PropsTable data={menuRootPropDefs} />
### Menu.Trigger
The trigger by default render a simple unstyled button. Because menus can be rendered in different ways, we recommend
using the `render` prop to render a custom trigger.
<CodeBlock code={`<Menu.Trigger render={props => <Button {...props} />} />`} />
<PropsTable data={menuTriggerPropDefs} />
### Menu.Positioner
Positions the menu popup against the trigger. Renders a `<div>` element.
<PropsTable data={menuPositionerPropDefs} />
### Menu.Item
An individual interactive item in the menu. Renders a `<div>` element.
<PropsTable data={menuItemPropDefs} />
## Examples
### Open on hover
To create a menu that opens on hover, add the `openOnHover` prop to the Root part.
You can additionally configure how quickly the menu opens on hover using the `delay` prop.
<Snippet
align="center"
py={4}
open
preview={<MenuSnippet story="OpenOnHover" />}
code={`<Menu.Root openOnHover delay={100}>
<Menu.Trigger
render={props => (
<Button
{...props}
size="medium"
variant="secondary"
iconEnd="chevron-down"
>
Menu
</Button>
)}
/>
<Menu.Portal>
<Menu.Positioner sideOffset={8} align="start">
<Menu.Popup>
<Menu.Item>Settings</Menu.Item>
<Menu.Item>Invite new members</Menu.Item>
<Menu.Item>Download app</Menu.Item>
<Menu.Item>Log out</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>
</Menu.Root>`}
/>
### Nested navigation
You can nest menus to create a more complex navigation structure.
<Snippet
align="center"
py={4}
open
preview={<MenuSnippet story="Submenu" />}
code={`<Menu.Trigger
render={props => (
<Button
{...props}
size="small"
variant="secondary"
iconEnd={<Icon name="chevron-down" />}
>
Menu
</Button>
)}
/>
<Menu.Portal>
<Menu.Positioner sideOffset={8} align="start">
<Menu.Popup>
<Menu.Item>Settings</Menu.Item>
<Menu.Item>Invite new members</Menu.Item>
<Menu.Item>Download app</Menu.Item>
<Menu.Item>Log out</Menu.Item>
<Menu.Root>
<Menu.SubmenuTrigger>Submenu</Menu.SubmenuTrigger>
<Menu.Portal>
<Menu.Positioner>
<Menu.Popup>
<Menu.Item>Submenu Item 1</Menu.Item>
<Menu.Item>Submenu Item 2</Menu.Item>
<Menu.Item>Submenu Item 3</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>
</Menu.Root>
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>`}
/>
@@ -1,128 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { SelectSnippet } from '@/snippets/stories-snippets';
import { selectPropDefs } from './props';
# Select
A common form component for choosing a predefined value in a dropdown menu.
<Snippet
align="center"
py={4}
preview={<SelectSnippet story="Preview" />}
code={`<Select name="font" label="Font Family" options={[
{ value: 'sans', label: 'Sans-serif' },
{ value: 'serif', label: 'Serif' },
{ value: 'mono', label: 'Monospace' },
{ value: 'cursive', label: 'Cursive' },
]} />
`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Select } from '@backstage/canon';
<Select
name="font"
options={[
{ value: 'sans', label: 'Sans-serif' },
{ value: 'serif', label: 'Serif' },
{ value: 'mono', label: 'Monospace' },
{ value: 'cursive', label: 'Cursive' },
]}
/>
`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
<CodeBlock
code={`<Select className="canon-SelectFieldRoot" />`}
/>
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={selectPropDefs} />
## Examples
### With Label and description
Select component with label and description.
<Snippet
align="center"
py={4}
open
preview={<SelectSnippet story="WithDescription" />}
code={`<Select
name="font"
label="Font Family"
description="Choose a font family for your document"
options={[ ... ]}
/>`}
/>
### Sizes
Here's a view when the selects have different sizes.
<Snippet
align="center"
py={4}
open
preview={<SelectSnippet story="Sizes" />}
code={`<Flex>
<Select
size="small"
label="Font family"
options={[ ... ]}
/>
<Select
size="medium"
label="Font family"
options={[ ... ]}
/>
</Flex>`}
/>
### Disabled
Here's a view when the select is disabled.
<Snippet
align="center"
py={4}
open
preview={<SelectSnippet story="Disabled" />}
code={`<Select
disabled
label="Font family"
options={[ ... ]}
/>`}
/>
### Responsive
Here's a view when the select is responsive.
<CodeBlock
code={`<Select
size={{ initial: 'small', lg: 'medium' }}
label="Font family"
options={[ ... ]}
/>`}
/>
@@ -1,54 +0,0 @@
import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs';
import type { PropDef } from '../../../../utils/propDefs';
export const selectPropDefs: Record<string, PropDef> = {
label: {
type: 'string',
default: 'Select an option',
responsive: false,
},
description: {
type: 'string',
responsive: false,
},
name: {
type: 'string',
responsive: false,
required: true,
},
options: {
type: 'enum',
values: ['Array<{ value: string, label: string }>'],
required: true,
},
value: {
type: 'string',
responsive: false,
},
defaultValue: {
type: 'string',
responsive: false,
},
placeholder: {
type: 'string',
responsive: false,
},
size: {
type: 'enum',
values: ['small', 'medium'],
default: 'medium',
responsive: true,
},
onValueChange: {
type: 'enum',
values: ['(value: string) => void'],
responsive: false,
},
onOpenChange: {
type: 'enum',
values: ['(open: boolean) => void'],
responsive: false,
},
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,92 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { TabsSnippet } from '@/snippets/stories-snippets';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import {
tabsRootPropDefs,
tabsListPropDefs,
tabsTabPropDefs,
tabsPanelPropDefs,
} from './props';
import { BaseUI } from '@/components/HeadlessBanners/BaseUI';
# Tabs
A component for toggling between related panels on the same page.
<Snippet
py={4}
preview={<TabsSnippet story="Default" />}
code={`<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Tab 1</Tabs.Tab>
<Tabs.Tab>Tab 2</Tabs.Tab>
<Tabs.Tab>Tab 3 With long title</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>Content for Tab 1</Tabs.Panel>
<Tabs.Panel>Content for Tab 2</Tabs.Panel>
<Tabs.Panel>Content for Tab 3</Tabs.Panel>
</Tabs.Root>`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Tabs } from '@backstage/canon';
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Tab 1</Tabs.Tab>
<Tabs.Tab>Tab 2</Tabs.Tab>
<Tabs.Tab>Tab 3</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>Content for Tab 1</Tabs.Panel>
<Tabs.Panel>Content for Tab 2</Tabs.Panel>
<Tabs.Panel>Content for Tab 3</Tabs.Panel>
</Tabs.Root>
`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `canon-TabsRoot`
- `canon-TabsList`
- `canon-TabsTab`
- `canon-TabsPanel`
- `canon-TabsIndicator`
</Tabs.Panel>
</Tabs.Root>
## API reference
<BaseUI href="https://base-ui.com/react/components/menu" />
### Tabs.Root
Groups the tabs and the corresponding panels. Renders a `<div>` element.
<PropsTable data={tabsRootPropDefs} />
### Tabs.List
Groups the individual tab buttons. Renders a `<div>` element.
<PropsTable data={tabsListPropDefs} />
### Tabs.Tab
An individual interactive tab button that toggles the corresponding panel. Renders a `<button>` element.
<PropsTable data={tabsTabPropDefs} />
### Tabs.Panel
A panel displayed when the corresponding tab is active. Renders a `<div>` element.
<PropsTable data={tabsPanelPropDefs} />
@@ -1,80 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { TextFieldSnippet } from '@/snippets/stories-snippets';
import { BaseUI } from '@/components/HeadlessBanners/BaseUI';
import { inputPropDefs } from './props';
# TextField
A text field component for your forms.
<Snippet
align="center"
py={4}
preview={<TextFieldSnippet story="WithLabel" />}
code={`<TextField label="Label" placeholder="Enter a URL" />`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { TextField } from '@backstage/canon';
<TextField />
`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `canon-TextField`
- `canon-TextFieldLabel`
- `canon-TextFieldRequired`
- `canon-TextFieldInputWrapper`
- `canon-TextFieldIcon`
- `canon-TextFieldInput`
- `canon-TextFieldClearButton`
- `canon-TextFieldClearButtonIcon`
- `canon-TextFieldDescription`
- `canon-TextFieldError`
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={inputPropDefs} />
## Examples
### Sizes
We support two different sizes: `small`, `medium`.
<Snippet
align="center"
py={4}
open
preview={<TextFieldSnippet story="Sizes" />}
code={`<Flex direction="row" gap="4">
<TextField size="small" placeholder="Small" icon={<Icon name="sparkling" />} />
<TextField size="medium" placeholder="Medium" icon={<Icon name="sparkling" />} />
</Flex>`}
/>
### With description
Here's a simple TextField with a description.
<Snippet
align="center"
py={4}
open
preview={<TextFieldSnippet story="WithDescription" />}
code={`<TextField label="Label" description="Description" placeholder="Enter a URL" />`}
/>
@@ -1,27 +0,0 @@
import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs';
import type { PropDef } from '../../../../utils/propDefs';
export const inputPropDefs: Record<string, PropDef> = {
size: {
type: 'enum',
values: ['small', 'medium'],
default: 'small',
responsive: true,
},
label: {
type: 'string',
},
icon: {
type: 'enum',
values: ['ReactNode'],
},
description: {
type: 'string',
},
name: {
type: 'string',
required: true,
},
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,129 +0,0 @@
import { PropsTable } from '@/components/PropsTable';
import { TextSnippet } from '@/snippets/stories-snippets';
import { Snippet } from '@/components/Snippet';
import { Tabs } from '@/components/Tabs';
import { CodeBlock } from '@/components/CodeBlock';
import { textPropDefs } from './props';
# Text
The `Text` component is used to display content on your page.
<Snippet
py={4}
preview={<TextSnippet story="Default" />}
code={`<Text style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, “Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son.” Who is in
the painting?
</Text>`}
/>
<Tabs.Root>
<Tabs.List>
<Tabs.Tab>Usage</Tabs.Tab>
<Tabs.Tab>Theming</Tabs.Tab>
</Tabs.List>
<Tabs.Panel>
<CodeBlock
code={`import { Text } from '@backstage/canon';
<Text />
`}
/>
</Tabs.Panel>
<Tabs.Panel>
We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
your brand. For additional flexibility, you can use the provided class names for each element listed below.
<CodeBlock
code={`<Text className="text" />`}
/>
</Tabs.Panel>
</Tabs.Root>
## API reference
<PropsTable data={textPropDefs} />
## Examples
### All variants
The `Text` component has a `variant` prop that can be used to change the
appearance of the text.
<Snippet
open
preview={<TextSnippet story="AllVariants" />}
code={`<Flex direction="column" gap="4">
<Text variant="subtitle" style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, “Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son.” Who is
in the painting?
</Text>
<Text variant="body" style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, “Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son.” Who is
in the painting?
</Text>
<Text variant="caption" style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, “Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son.” Who is
in the painting?
</Text>
<Text variant="label" style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, “Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son.” Who is
in the painting?
</Text>
</Flex>`}
/>
### All weights
The `Text` component has a `weight` prop that can be used to change the
appearance of the text.
<Snippet
open
preview={<TextSnippet story="AllWeights" />}
code={`<Flex direction="column" gap="4">
<Text weight="regular" style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, “Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son.” Who is
in the painting?
</Text>
<Text weight="bold" style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, “Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son.” Who is
in the painting?
</Text>
</Flex>`}
/>
### Truncate
The `Text` component has a `truncate` prop that can be used to truncate the
text.
<Snippet
open
preview={<TextSnippet story="Truncate" />}
code={`<Text weight="regular" style={{ maxWidth: '600px' }} truncate>
A man looks at a painting in a museum and says, “Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son.” Who is
in the painting?
</Text>`}
/>
### Responsive
You can also use the `variant` prop to change the appearance of the text based
on the screen size.
<CodeBlock
code={`<Text variant={{ initial: 'body', lg: 'subtitle' }}>
Responsive text
</Text>`}
/>
@@ -1,26 +0,0 @@
import {
childrenPropDefs,
classNamePropDefs,
stylePropDefs,
} from '../../../../utils/propDefs';
import type { PropDef } from '../../../../utils/propDefs';
export const textPropDefs: Record<string, PropDef> = {
variant: {
type: 'enum',
values: ['display', 'title1', 'title2', 'title3', 'title4', 'title5'],
responsive: true,
},
weight: {
type: 'enum',
values: ['regular', 'bold'],
responsive: true,
},
truncate: {
type: 'boolean',
default: 'false',
},
...childrenPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
@@ -1,59 +0,0 @@
# Releases
## Version 0.3.0
### Main updates
- Add `DataTable` component - ([#29484](https://github.com/backstage/backstage/pull/29484), [#29603](https://github.com/backstage/backstage/pull/29603))
- Add `Select` component - ([#29440](https://github.com/backstage/backstage/pull/29440))
- Add `Avatar` component - ([#29594](https://github.com/backstage/backstage/pull/29594))
- Add `Collapsible` component - ([#29617](https://github.com/backstage/backstage/pull/29617))
- Add `TextField` component instead of `Field` + `Input` - ([#29364](https://github.com/backstage/backstage/pull/29364))
- Add `TableCellProfile` - ([#29600](https://github.com/backstage/backstage/pull/29600))
- Add breakpoint hooks - `up()` and `down()` - ([#29564](https://github.com/backstage/backstage/pull/29564))
- Add gray scale css tokens - ([#29543](https://github.com/backstage/backstage/pull/29543))
- Update CSS styling API using `[data-___]` instead of class names for props - ([#29560](https://github.com/backstage/backstage/pull/29560))
- Update `Checkbox` dark mode - ([#29544](https://github.com/backstage/backstage/pull/29544))
- Update `Container` styles - ([#29475](https://github.com/backstage/backstage/pull/29475))
- Update `Menu` styles - ([#29351](https://github.com/backstage/backstage/pull/29351))
- Fix `Select` styles on small sizes + with long option names - ([#29545](https://github.com/backstage/backstage/pull/29545))
- Fix render prop on `Link` - ([#29247](https://github.com/backstage/backstage/pull/29247))
- Remove `Field` from `TextField` + `Select` - ([#29482](https://github.com/backstage/backstage/pull/29482))
- Update `textDecoration` to `none` on `Text` / `Heading` - ([#29357](https://github.com/backstage/backstage/pull/29357))
### Notable fixes
- Docs - Use stories from Storybook for all examples in Nextjs - ([#29306](https://github.com/backstage/backstage/pull/29306))
- Docs - Add release page (this one 🤗) - ([#29461](https://github.com/backstage/backstage/pull/29461))
- Docs - Add docs for Menu, Link - ([#29576](https://github.com/backstage/backstage/pull/29576))
- Fix CSS watch mode - ([#29352](https://github.com/backstage/backstage/pull/29352))
## Version 0.2.0
### Main updates
- New `Tooltip` component ([#29241](https://github.com/backstage/backstage/pull/29241))
- New `Menu` component. ([#29151](https://github.com/backstage/backstage/pull/29151))
- New `IconButton` component. ([#29239](https://github.com/backstage/backstage/pull/29239))
- New `ScrollArea` component. ([#29240](https://github.com/backstage/backstage/pull/29240))
- Improve `Button` & `Checkbox` styles. ([#29127](https://github.com/backstage/backstage/pull/29127)) ([#28789](https://github.com/backstage/backstage/pull/28789))
- Improve `Text` styles. ([#29200](https://github.com/backstage/backstage/pull/29200))
- Renamed `CanonProvider` to `IconProvider`. ([#29002](https://github.com/backstage/backstage/pull/29002))
- Added about 40+ new icons. ([#29264](https://github.com/backstage/backstage/pull/29264))
- Simplified styling into a unique styles.css file ([#29199](https://github.com/backstage/backstage/pull/29199))
- Added Canon styles to Backstage ([#29137](https://github.com/backstage/backstage/pull/29137))
- Update global CSS tokens ([#28804](https://github.com/backstage/backstage/pull/28804))
- Merge Stack + Inline into Flex ([#28634](https://github.com/backstage/backstage/pull/28634))
### Notable fixes:
- Improve `Button` types. ([#29205](https://github.com/backstage/backstage/pull/29205))
- Move font weight and family back to each components ([#28972](https://github.com/backstage/backstage/pull/28972))
- Fix custom values in spacing props ([#28770](https://github.com/backstage/backstage/pull/28770))
- Multiple updates on the Canon Docs site ([#28760](https://github.com/backstage/backstage/pull/28760)) ([#28591](https://github.com/backstage/backstage/pull/28591))
## Version 0.1.0
We're excited to share the initial release of Canon 💚 In this first alpha version, you'll find the foundation of our design system:
a set of versatile layout components and a handful of essential atomic elements to help you get started. While Canon is still in its
early stages, it's ready for exploration and we'd love for you to give it a try and share your feedback.
@@ -71,20 +71,17 @@ const Content = () => {
{selectedComponents.find(c => c === 'text') && (
<Line content={<TextSnippet story="Playground" />} title="Text" />
)}
{/* {selectedComponents.find(c => c === 'input') && (
<Line content={<InputPlayground />} title="Input" />
)} */}
</Flex>
);
};
const Line = ({ content, title }: { content: ReactNode; title: string }) => {
return (
<Grid gap={{ xs: '2', md: '4' }}>
<Grid.Root gap={{ xs: '2', md: '4' }}>
<Grid.Item colSpan="2">
<Text>{title}</Text>
</Grid.Item>
<Grid.Item colSpan="10">{content}</Grid.Item>
</Grid>
</Grid.Root>
);
};
+2 -2
View File
@@ -6,8 +6,8 @@ import { CustomTheme } from '@/components/CustomTheme';
import styles from '../css/page.module.css';
import '../css/globals.css';
import '/public/core.css';
import '/public/components.css';
import '/public/theme-backstage.css';
import '/public/theme-spotify.css';
export const metadata: Metadata = {
title: 'Canon',
@@ -1,18 +1,3 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import styles from './styles.module.css';
export const Banner = ({
-15
View File
@@ -1,16 +1 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { Banner } from './Banner';
@@ -0,0 +1,43 @@
import { changelog } from '@/utils/changelog';
import { MDXRemote } from 'next-mdx-remote-client/rsc';
import { formattedMDXComponents } from '@/mdx-components';
export function Changelog() {
// Group changelog entries by version
const groupedChangelog = changelog.reduce((acc, entry) => {
if (!acc[entry.version]) {
acc[entry.version] = [];
}
acc[entry.version].push(entry);
return acc;
}, {} as Record<string, typeof changelog>);
// Sort versions in descending order
const sortedVersions = Object.keys(groupedChangelog).sort((a, b) =>
b.localeCompare(a),
);
const content = sortedVersions
.map(version => {
const entries = groupedChangelog[version];
return `## Version ${version}
${entries
.map(e => {
const prs =
e.prs.length > 0 &&
e.prs
.map(
pr =>
`[#${pr}](https://github.com/backstage/backstage/pull/${pr})`,
)
.join(', ');
return `- ${e.description} ${prs}`;
})
.join('\n')}`;
})
.join('\n');
return <MDXRemote components={formattedMDXComponents} source={content} />;
}
-16
View File
@@ -1,19 +1,3 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ReactNode } from 'react';
import styles from './styles.module.css';
-15
View File
@@ -1,16 +1 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { Chip } from './Chip';
@@ -1,19 +1,3 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.chip {
display: inline-flex;
align-items: center;
@@ -25,7 +9,6 @@
margin-right: 4px;
background-color: #f0f0f0;
color: #5d5d5d;
transition: background-color 0.2s ease-in-out;
}
.head {
@@ -39,5 +22,5 @@
}
[data-theme='dark'] .chip.head {
background-color: #26417b;
background-color: #33405b;
}
@@ -1,8 +1,9 @@
'use client';
import { CodeBlockProps } from '.';
import { Text } from '../../../../packages/canon';
import { Text } from '@backstage/canon';
import styles from './styles.module.css';
import parse from 'html-react-parser';
export const CodeBlockClient = ({
out,
@@ -18,7 +19,7 @@ export const CodeBlockClient = ({
<Text variant="body">{title}</Text>
</div>
)}
<div dangerouslySetInnerHTML={{ __html: out }} className={styles.code} />
<div className={styles.code}>{parse(out)}</div>
</div>
);
};
@@ -4,9 +4,8 @@
position: relative;
background: transparent;
overflow-x: auto;
font-family: var(--canon-font-monospace);
font-family: var(--font-mono);
background-color: #fff;
transition: background-color 0.2s ease-in-out;
margin-bottom: 1rem;
}
@@ -1,19 +1,3 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ReactNode, CSSProperties } from 'react';
export const Columns = ({

Some files were not shown because too many files have changed in this diff Show More