;
+}
diff --git a/canon-docs/src/app/(docs)/page.mdx b/canon-docs/src/app/(docs)/page.mdx
new file mode 100644
index 0000000000..09d4d83ea3
--- /dev/null
+++ b/canon-docs/src/app/(docs)/page.mdx
@@ -0,0 +1,64 @@
+import { CodeBlock } from '@/components/CodeBlock';
+
+
+
+Welcome to the Canon, the new design library for Backstage plugins. This
+project is still under active development but we will make sure to document
+the API as we go. We are aiming to improve the general UI of Backstage and
+plugins across Backstage. This new library will take time to build but we are
+building it incrementally with not conflict with the existing theming system.
+
+## Installation
+
+### 1. Install canon
+
+Install Canon using a package manager.
+
+
+
+### 2. Import the css files
+
+Import the global CSS file at the root of your application.
+
+```tsx
+import '@backstage/canon/css/core.css';
+import '@backstage/canon/css/components.css';
+```
+
+### 3. Add the theme provider
+
+Add the theme provider to your application.
+
+```tsx
+import { ThemeProvider } from '@backstage/canon';
+
+
+
+;
+```
+
+### 4. Start building ✨
+
+Now you can start building your plugin using the new design system.
+
+```tsx
+import { Stack, Button } from '@backstage/canon';
+
+
+ Hello World
+
+;
+```
+
+## Roadmap
+
+You can check our roadmap [on GitHub](https://github.com/orgs/backstage/projects/10). We'll do our best to keep you updated on the progress.
+
+## Next steps
+
+Now that you have the basics down, you can start building your plugin using the new design system.
+Please familiarise yourself first with our theming principles. This will help you understand the core concepts of the design system.
+If you have any questions, please reach out to us on [Discord](https://discord.gg/MUpMjP2).
diff --git a/canon-docs/src/app/(docs)/theme/iconography/page.mdx b/canon-docs/src/app/(docs)/theme/iconography/page.mdx
new file mode 100644
index 0000000000..9083c93389
--- /dev/null
+++ b/canon-docs/src/app/(docs)/theme/iconography/page.mdx
@@ -0,0 +1,16 @@
+import { CodeBlock } from '@/components/CodeBlock';
+import { IconLibrary } from '@/components/IconLibrary';
+
+# Iconography
+
+All our default icons are provided by [Remix Icon](https://remixicon.com/). We
+don't import all icons to reduce the bundle size but we cherry pick a nice
+selection for you to use in your application. The list of names is set down
+below. To use an icon, you can use the `Icon` component and pass the name of
+the icon you want to use.
+
+`} />
+
+## Icon library
+
+
diff --git a/canon-docs/src/app/(docs)/theme/layout/page.mdx b/canon-docs/src/app/(docs)/theme/layout/page.mdx
new file mode 100644
index 0000000000..dc3a5d4585
--- /dev/null
+++ b/canon-docs/src/app/(docs)/theme/layout/page.mdx
@@ -0,0 +1,42 @@
+import { LayoutComponents } from '@/components/LayoutComponents';
+import { CodeBlock } from '@/components/CodeBlock';
+
+# Layout
+
+Canon is made for extensibility. We built this library to make it easy for any
+Backstage plugin creator to be able to build their ideas at speed ensuring
+consistency across the rest of your ecosystem. Each component is designed to
+be editable to match your need but sometimes you want to have more control
+over the layout of your page. To help you with that, we created a set of
+layout components that you can use to build your own layouts. All of these
+components are built to extend on our theming system, making it easy for you
+to build your own layouts. Sometimes these components are not enough so we
+created a set of helpers to be used with any CSS-in-JS library.
+
+## Layout Components
+
+We built a couple of layout components to help you build responsive elements
+that will be consistent with the rest of your Backstage instance. These
+components are opinionated and use TypeScript to ensure that the props you
+provide are the ones coming from the theme.
+
+
+ Hello World
+
+ Project 1
+ Project 2
+
+
+`}
+/>
+
+
+
+## Layout Helpers
+
+Sometimes you want to use global tokens dynamically outside of React
+components. To help you with that we would like to provide a set of helpers
+that you can use in your code. These helpers are not available just yet but we
+are working on it.
diff --git a/canon-docs/src/app/(docs)/theme/responsive/page.mdx b/canon-docs/src/app/(docs)/theme/responsive/page.mdx
new file mode 100644
index 0000000000..cdbd82533c
--- /dev/null
+++ b/canon-docs/src/app/(docs)/theme/responsive/page.mdx
@@ -0,0 +1,123 @@
+import * as Table from '@/components/Table';
+import { Chip } from '@/components/Chip';
+import { CodeBlock } from '@/components/CodeBlock';
+
+# Responsive
+
+Canon is built on a responsive design system, meaning that the components are
+designed to adapt to different screen sizes. By default we offer a set of
+breakpoints that you can use to create responsive components.
+
+## Breakpoints
+
+
+
+
+ Breakpoint prefix
+ Minimum width
+ CSS
+
+
+
+
+
+ xs
+
+
+ 0px
+
+
+ {`{ ... }`}
+
+
+
+
+ sm
+
+
+ 640px
+
+
+ {`@media (min-width: 640px) { ... }`}
+
+
+
+
+ md
+
+
+ 768px
+
+
+ {`@media (min-width: 768px) { ... }`}
+
+
+
+
+ lg
+
+
+ 1024px
+
+
+ {`@media (min-width: 1024px) { ... }`}
+
+
+
+
+ xl
+
+
+ 1280px
+
+
+ {`@media (min-width: 1280px) { ... }`}
+
+
+
+
+ 2xl
+
+
+ 1536px
+
+
+ {`@media (min-width: 1536px) { ... }`}
+
+
+
+
+
+## Responsive components
+
+Canon components are designed to be responsive, meaning that they will adapt
+to different screen sizes. Not every component is responsive, but the ones
+that are will have a prop to control the responsive behavior.
+
+The behaviour is the same for each component. For each prop, instead of adding
+the value, you add an object with the value and the breakpoint prefix.
+
+Button
+
+// Responsive value
+
+`} />
+
+## How to update breakpoints
+
+The set of keys are not to be changed, but you can update the minimum width of
+each breakpoint in the theme provider.
+
+`}
+/>
diff --git a/canon-docs/src/app/(docs)/theme/theming/page.mdx b/canon-docs/src/app/(docs)/theme/theming/page.mdx
new file mode 100644
index 0000000000..421b315a7b
--- /dev/null
+++ b/canon-docs/src/app/(docs)/theme/theming/page.mdx
@@ -0,0 +1,220 @@
+import { CodeBlock } from '@/components/CodeBlock';
+import * as Table from '@/components/Table';
+import { Chip } from '@/components/Chip';
+
+# Theming
+
+Backstage ships with a default theme with a light and dark mode variant. The
+themes are provided as a part of the `@backstage/canon` package, which also
+includes utilities for customizing the default theme, or creating completely
+new themes.
+
+## Light & Dark modes
+
+By default we are supporting both light and dark modes. Each user can opt to
+choose what theme they want to use or to use their system decide what theme to
+use. If you want to create your own theme, you will have to set both light and
+dark themes following the instructions below. If you only set one of them, the
+other mode will fallback to the default theme.
+
+## How to create your own theme
+
+To create your own theme, you will have to define the variables below. To do
+that, create a theme.css file and import it in your application. Here's an
+example below on how to set your light and dark mode.
+
+
+
+## Colors
+
+We provide a set of generic colours tokens that we use across Canon. By
+changing these colours you can easily change the look and feel of your
+application to match your brand.
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-accent
+
+ The accent color for the theme.
+
+
+
+ --canon-bg
+
+ The background color for the theme.
+
+
+
+ --canon-surface-1
+
+ The first surface color for the theme.
+
+
+
+ --canon-surface-2
+
+ The second surface color for the theme.
+
+
+
+ --canon-outline
+
+ The outline color for the theme.
+
+
+
+ --canon-outline-focus
+
+ The outline focus color for the theme.
+
+
+
+ --canon-text-primary
+
+ The primary text color for the theme.
+
+
+
+ --canon-text-secondary
+
+ The secondary text color for the theme.
+
+
+
+
+## Typography
+
+We have two fonts that we use across Canon. The first one is the sans-serif
+font that we use for the body of the application. The second one is the
+monospace font that we use for code blocks and tables.
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-font-regular
+
+ The sans-serif font for the theme.
+
+
+
+ --canon-font-mono
+
+ The monospace font for the theme.
+
+
+
+
+## Spacing
+
+Our default spacing system is made to work in most scenarios. We have 7 scale
+values from `xxs` to `xxl`. We use the values on padding and margin in our
+layout components mostly. If you prefer to use a different spacing system, you
+can do that by changing the values below.
+
+
+
+
+ Prop
+ Description
+
+
+
+
+
+ --canon-space-unit
+
+
+ The base unit for the spacing system. Default value is `1em`
+
+
+
+
+ --canon-space-xxs
+
+ Default value is `0.25 x space unit`
+
+
+
+ --canon-space-xs
+
+ Default value is `0.5 x space unit`
+
+
+
+ --canon-space-sm
+
+ Default value is `0.75 x space unit`
+
+
+
+ --canon-space-md
+
+ Default value is `1.25 x space unit`
+
+
+
+ --canon-space-lg
+
+ Default value is `2 x space unit`
+
+
+
+ --canon-space-xl
+
+ Default value is `3.25 x space unit`
+
+
+
+ --canon-space-xxl
+
+ Default value is `5.25 x space unit`
+
+
+
diff --git a/canon-docs/src/app/(docs)/theme/typography/page.mdx b/canon-docs/src/app/(docs)/theme/typography/page.mdx
new file mode 100644
index 0000000000..86be4d2e19
--- /dev/null
+++ b/canon-docs/src/app/(docs)/theme/typography/page.mdx
@@ -0,0 +1,66 @@
+import { HeadingAllVariants } from '@/snippets/heading';
+import { TextAllVariants } from '@/snippets/text';
+import { Snippet } from '@/components/Snippet';
+
+# Typography
+
+Canon offers a suite of typography components designed to seamlessly align
+with the rest of your Backstage instance. While you can customize their
+appearance to match your brand, the underlying API remains consistent and
+unchanged. Each component is built on a responsive structure, allowing you to
+define different typography values for various breakpoints.
+
+## Headings
+
+Headings are used to structure the content of your page. They are used to
+create a hierarchy of information and to make the content more readable. The
+best way to use add these headings to your page is to import the [Heading
+component](?path=/docs/components-heading--docs).
+
+}
+ code={`
+ Display
+ Title 1
+ Title 2
+ Title 3
+ Title 4
+`}
+/>
+
+## Text
+
+Canon provides four distinct text variants, each offering different font sizes
+carefully designed to cover the majority of use cases. These variants are
+versatile and can be paired with regular and bold of font weights. You can use
+the [Text component](?path=/docs/components-text--docs) to add text to your
+page.
+
+}
+ code={`
+
+ A man looks at a painting in a museum and says, “Brothers and sisters I
+ have none, but that man's father is my father's son.” Who is
+ in the painting?
+
+
+ A man looks at a painting in a museum and says, “Brothers and sisters I
+ have none, but that man's father is my father's son.” Who is
+ in the painting?
+
+
+ A man looks at a painting in a museum and says, “Brothers and sisters I
+ have none, but that man's father is my father's son.” Who is
+ in the painting?
+
+
+ A man looks at a painting in a museum and says, “Brothers and sisters I
+ have none, but that man's father is my father's son.” Who is
+ in the painting?
+
+ `}
+/>
diff --git a/canon-docs/src/app/(playground)/playground/page.tsx b/canon-docs/src/app/(playground)/playground/page.tsx
new file mode 100644
index 0000000000..c36a1d3492
--- /dev/null
+++ b/canon-docs/src/app/(playground)/playground/page.tsx
@@ -0,0 +1,82 @@
+'use client';
+
+import { ReactNode } from 'react';
+import { Grid, Stack, Text } from '../../../../../packages/canon';
+import { screenSizes } from '@/utils/data';
+import { Frame } from '@/components/Frame';
+import { usePlayground } from '@/utils/playground-context';
+import { ButtonPlayground } from '@/snippets/button';
+import { CheckboxPlayground } from '@/snippets/checkbox';
+import { HeadingPlayground } from '@/snippets/heading';
+import { TextPlayground } from '@/snippets/text';
+
+import styles from './styles.module.css';
+
+export default function PlaygroundPage() {
+ const { selectedScreenSizes } = usePlayground();
+
+ const filteredScreenSizes = screenSizes.filter(item =>
+ selectedScreenSizes.includes(item.slug),
+ );
+
+ if (filteredScreenSizes.length === 0) {
+ return (
+
+
+
+
+ );
+}
diff --git a/canon-docs/src/app/page.module.css b/canon-docs/src/app/page.module.css
new file mode 100644
index 0000000000..9119d2e9c5
--- /dev/null
+++ b/canon-docs/src/app/page.module.css
@@ -0,0 +1,44 @@
+.global {
+ width: 100%;
+}
+
+.container {
+ padding-left: 300px;
+ width: 100%;
+}
+
+.page {
+ flex: 1;
+}
+
+.page p {
+ color: var(--canon-text-primary);
+ font-size: 1rem;
+ line-height: 1.5rem;
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+.content {
+ width: 100%;
+ max-width: 960px;
+ margin: 0 auto;
+ padding: 64px 24px 64px;
+}
+
+.header {
+ width: 100%;
+ margin-bottom: 64px;
+}
+
+.header img {
+ width: 100%;
+ height: auto;
+}
+
+.pageContainer {
+ width: 100%;
+ max-width: 960px;
+ margin: 0 auto;
+ padding: 0 24px 64px;
+}
diff --git a/canon-docs/src/app/providers.tsx b/canon-docs/src/app/providers.tsx
new file mode 100644
index 0000000000..81a18136e8
--- /dev/null
+++ b/canon-docs/src/app/providers.tsx
@@ -0,0 +1,13 @@
+'use client';
+
+import { ReactNode } from 'react';
+import { CanonProvider } from '../../../packages/canon/src/contexts/canon';
+import { PlaygroundProvider } from '@/utils/playground-context';
+
+export const Providers = ({ children }: { children: ReactNode }) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/canon-docs/src/components/Banner/Banner.tsx b/canon-docs/src/components/Banner/Banner.tsx
new file mode 100644
index 0000000000..18aecba79f
--- /dev/null
+++ b/canon-docs/src/components/Banner/Banner.tsx
@@ -0,0 +1,42 @@
+/*
+ * 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 React from 'react';
+import styles from './styles.module.css';
+
+export const Banner = ({
+ variant = 'info',
+ text,
+}: {
+ variant?: 'info' | 'warning';
+ text?: string;
+}) => {
+ return (
+
+
+
+
+
{text}
+
+ );
+};
diff --git a/canon-docs/src/components/Banner/index.ts b/canon-docs/src/components/Banner/index.ts
new file mode 100644
index 0000000000..31f4aa88b0
--- /dev/null
+++ b/canon-docs/src/components/Banner/index.ts
@@ -0,0 +1,16 @@
+/*
+ * 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';
diff --git a/canon-docs/src/components/Banner/styles.module.css b/canon-docs/src/components/Banner/styles.module.css
new file mode 100644
index 0000000000..9666c5d521
--- /dev/null
+++ b/canon-docs/src/components/Banner/styles.module.css
@@ -0,0 +1,41 @@
+.banner {
+ display: flex;
+ align-items: center;
+ font-size: 16px;
+ line-height: 28px;
+ padding: 16px;
+ border-radius: 6px;
+ margin-bottom: 16px;
+ border: 1px solid #e0e0e0;
+
+ & > p {
+ margin: 0;
+ }
+}
+
+.info {
+ background-color: #f2f2f2;
+ border-color: #cdcdcd;
+ color: #888888;
+}
+
+.warning {
+ background-color: #fff2b9;
+ border-color: #ffd000;
+ color: #d79927;
+}
+
+.icon {
+ width: 32px;
+ height: 32px;
+ background-color: rgba(215, 153, 39, 0.2);
+ border-radius: 6px;
+ margin-right: 16px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.text {
+ line-height: 1.5;
+}
diff --git a/canon-docs/src/components/Chip/Chip.tsx b/canon-docs/src/components/Chip/Chip.tsx
new file mode 100644
index 0000000000..d6a74502e0
--- /dev/null
+++ b/canon-docs/src/components/Chip/Chip.tsx
@@ -0,0 +1,32 @@
+/*
+ * 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 React from 'react';
+import styles from './styles.module.css';
+
+export const Chip = ({
+ children,
+ head = false,
+}: {
+ children: React.ReactNode;
+ head?: boolean;
+}) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/canon-docs/src/components/Chip/index.ts b/canon-docs/src/components/Chip/index.ts
new file mode 100644
index 0000000000..ff9e4794c5
--- /dev/null
+++ b/canon-docs/src/components/Chip/index.ts
@@ -0,0 +1,16 @@
+/*
+ * 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';
diff --git a/canon-docs/src/components/Chip/styles.module.css b/canon-docs/src/components/Chip/styles.module.css
new file mode 100644
index 0000000000..44337afb0a
--- /dev/null
+++ b/canon-docs/src/components/Chip/styles.module.css
@@ -0,0 +1,43 @@
+/*
+ * 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;
+ font-family: monospace;
+ font-size: 13px;
+ border-radius: 6px;
+ padding: 0px 8px;
+ height: 24px;
+ margin-right: 4px;
+ background-color: #f0f0f0;
+ color: #5d5d5d;
+ transition: background-color 0.2s ease-in-out;
+}
+
+.head {
+ background-color: #eaf2fd;
+ color: #2563eb;
+}
+
+[data-theme='dark'] .chip {
+ background-color: #2c2c2c;
+ color: #fff;
+}
+
+[data-theme='dark'] .chip.head {
+ background-color: #26417b;
+}
diff --git a/canon-docs/src/components/CodeBlock/index.tsx b/canon-docs/src/components/CodeBlock/index.tsx
new file mode 100644
index 0000000000..bbcf4d63da
--- /dev/null
+++ b/canon-docs/src/components/CodeBlock/index.tsx
@@ -0,0 +1,32 @@
+import React from 'react';
+import type { BundledLanguage } from 'shiki';
+import { codeToHtml } from 'shiki';
+import { Text } from '../../../../packages/canon/src/components/Text';
+import styles from './styles.module.css';
+
+interface CodeBlockProps {
+ lang?: BundledLanguage;
+ title?: string;
+ code?: string;
+}
+
+export async function CodeBlock({ lang = 'tsx', title, code }: CodeBlockProps) {
+ const out = await codeToHtml(code || '', {
+ lang: lang,
+ themes: {
+ light: 'min-light',
+ dark: 'min-dark',
+ },
+ });
+
+ return (
+
+ {title && (
+
+ {title}
+
+ )}
+
+
+ );
+}
diff --git a/canon-docs/src/components/CodeBlock/styles.module.css b/canon-docs/src/components/CodeBlock/styles.module.css
new file mode 100644
index 0000000000..e74714e07c
--- /dev/null
+++ b/canon-docs/src/components/CodeBlock/styles.module.css
@@ -0,0 +1,26 @@
+.codeBlock {
+ border-radius: 4px;
+ border: 1px solid var(--canon-border-base);
+ position: relative;
+ background: transparent;
+ overflow-x: auto;
+ font-family: var(--canon-font-monospace);
+ background-color: #fff;
+ transition: background-color 0.2s ease-in-out;
+ margin-bottom: 1rem;
+}
+
+[data-theme='dark'] .codeBlock {
+ background-color: #121212;
+}
+
+.title {
+ border-bottom: 1px solid var(--canon-border-base);
+ padding: 12px 20px;
+ font-size: 0.875rem;
+ color: var(--canon-text-secondary);
+}
+
+.code {
+ padding: 20px;
+}
diff --git a/canon-docs/src/components/Columns/Columns.tsx b/canon-docs/src/components/Columns/Columns.tsx
new file mode 100644
index 0000000000..115ec50010
--- /dev/null
+++ b/canon-docs/src/components/Columns/Columns.tsx
@@ -0,0 +1,31 @@
+/*
+ * 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 React from 'react';
+
+export const Columns = ({
+ children,
+ style,
+}: {
+ children: React.ReactNode;
+ style?: React.CSSProperties;
+}) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/canon-docs/src/components/Columns/index.ts b/canon-docs/src/components/Columns/index.ts
new file mode 100644
index 0000000000..05de0850be
--- /dev/null
+++ b/canon-docs/src/components/Columns/index.ts
@@ -0,0 +1,16 @@
+/*
+ * 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 { Columns } from './Columns';
diff --git a/canon-docs/src/components/Columns/styles.css b/canon-docs/src/components/Columns/styles.css
new file mode 100644
index 0000000000..c34acfc406
--- /dev/null
+++ b/canon-docs/src/components/Columns/styles.css
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+.columns {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ row-gap: 20px;
+ column-gap: 80px;
+}
diff --git a/canon-docs/src/components/DecorativeBox/index.tsx b/canon-docs/src/components/DecorativeBox/index.tsx
new file mode 100644
index 0000000000..a5c20725bc
--- /dev/null
+++ b/canon-docs/src/components/DecorativeBox/index.tsx
@@ -0,0 +1,5 @@
+import styles from './styles.module.css';
+
+export const DecorativeBox = () => {
+ return ;
+};
diff --git a/canon-docs/src/components/DecorativeBox/styles.module.css b/canon-docs/src/components/DecorativeBox/styles.module.css
new file mode 100644
index 0000000000..84a6b579a0
--- /dev/null
+++ b/canon-docs/src/components/DecorativeBox/styles.module.css
@@ -0,0 +1,8 @@
+.box {
+ min-width: 64px;
+ min-height: 64px;
+ background-color: #eaf2fd;
+ border-radius: 4px;
+ box-shadow: 0 0 0 1px #2563eb;
+ background-image: url("data:image/svg+xml,%3Csvg width='6' height='6' viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%232563eb' fill-opacity='0.3' fill-rule='evenodd'%3E%3Cpath d='M5 0h1L0 6V5zM6 5v1H5z'/%3E%3C/g%3E%3C/svg%3E");
+}
diff --git a/canon-docs/src/components/Frame/index.tsx b/canon-docs/src/components/Frame/index.tsx
new file mode 100644
index 0000000000..c7e930df74
--- /dev/null
+++ b/canon-docs/src/components/Frame/index.tsx
@@ -0,0 +1,33 @@
+/* eslint-disable @next/next/no-css-tags */
+'use client';
+
+import { useEffect, useState } from 'react';
+import ReactFrame from 'react-frame-component';
+
+export const Frame = ({ children }: { children: React.ReactNode }) => {
+ const [show, setShow] = useState(false);
+
+ useEffect(() => {
+ setShow(true);
+ }, []);
+
+ if (!show) return null;
+
+ return (
+ `}
+ mountTarget=".frame-root"
+ head={
+ <>
+
+
+
+ >
+ }
+ >
+ {children}
+
+ );
+};
diff --git a/canon-docs/src/components/HeadlessBanners/BaseUI.tsx b/canon-docs/src/components/HeadlessBanners/BaseUI.tsx
new file mode 100644
index 0000000000..6d3a727333
--- /dev/null
+++ b/canon-docs/src/components/HeadlessBanners/BaseUI.tsx
@@ -0,0 +1,43 @@
+import styles from './styles.module.css';
+import { Text } from '../../../../packages/canon/src/components/Text';
+import { Icon } from '../../../../packages/canon/src/components/Icon';
+
+interface BaseUIProps {
+ href: string;
+}
+
+export const BaseUI = ({ href }: BaseUIProps) => {
+ return (
+
+
+
+
+ Base UI
+
+
+
+ This component is using Base UI under the hood. While most of the
+ original props are available, we have made some changes to the API
+ to fit our needs.
+
+
+ );
+};
diff --git a/canon-docs/src/components/HeadlessBanners/styles.module.css b/canon-docs/src/components/HeadlessBanners/styles.module.css
new file mode 100644
index 0000000000..c8eb2bc68d
--- /dev/null
+++ b/canon-docs/src/components/HeadlessBanners/styles.module.css
@@ -0,0 +1,42 @@
+.container {
+ display: flex;
+ background-color: var(--canon-surface-1);
+ padding: var(--canon-spacing-md);
+ border-radius: var(--canon-border-radius-xs);
+ border: 1px solid var(--canon-border-base);
+ margin-bottom: var(--canon-spacing-md);
+ gap: var(--canon-spacing-md);
+ transition: background-color 0.2s ease-in-out;
+}
+
+.icon path {
+ fill: var(--canon-text-primary);
+}
+
+.content {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+}
+
+.description {
+ max-width: 700px;
+}
+
+.button {
+ all: unset;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ background-color: var(--canon-surface-2);
+ border: 1px solid var(--canon-border-base);
+ border-radius: var(--canon-border-radius-xs);
+ padding: 0 var(--canon-spacing-xs);
+ height: 28px;
+ border-radius: 100px;
+ margin-top: var(--canon-spacing-xs);
+ font-size: var(--canon-font-size-body);
+ color: var(--canon-text-primary);
+ gap: var(--canon-spacing-2xs);
+}
diff --git a/canon-docs/src/components/IconLibrary/IconLibrary.tsx b/canon-docs/src/components/IconLibrary/IconLibrary.tsx
new file mode 100644
index 0000000000..b8ca8acdea
--- /dev/null
+++ b/canon-docs/src/components/IconLibrary/IconLibrary.tsx
@@ -0,0 +1,39 @@
+/*
+ * 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 React from 'react';
+import { Icon } from '../../../../packages/canon/src/components/Icon';
+import type { IconNames } from '../../../../packages/canon/src/components/Icon';
+import { Text } from '../../../../packages/canon/src/components/Text';
+import { icons } from '../../../../packages/canon/src/components/Icon/icons';
+import styles from './styles.module.css';
+
+export const IconLibrary = () => {
+ const list = Object.keys(icons);
+
+ return (
+
+ {list.map(icon => (
+
+
+
+
+ {icon}
+
+ ))}
+
+ );
+};
diff --git a/canon-docs/src/components/IconLibrary/index.ts b/canon-docs/src/components/IconLibrary/index.ts
new file mode 100644
index 0000000000..071c80db85
--- /dev/null
+++ b/canon-docs/src/components/IconLibrary/index.ts
@@ -0,0 +1,16 @@
+/*
+ * 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 { IconLibrary } from './IconLibrary';
diff --git a/canon-docs/src/components/IconLibrary/styles.module.css b/canon-docs/src/components/IconLibrary/styles.module.css
new file mode 100644
index 0000000000..40b177ced0
--- /dev/null
+++ b/canon-docs/src/components/IconLibrary/styles.module.css
@@ -0,0 +1,28 @@
+.library {
+ display: grid;
+ grid-template-columns: repeat(6, 1fr);
+ gap: 1rem;
+}
+
+.item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 8px;
+}
+
+.icon {
+ display: flex;
+ width: 100%;
+ justify-content: center;
+ align-items: center;
+ height: 80px;
+ border: 1px solid #d3d3d3;
+ border-radius: 0.5rem;
+ background-color: var(--canon-background);
+ transition: background-color 0.2s ease-in-out;
+
+ &:hover {
+ background-color: var(--canon-surface-1);
+ }
+}
diff --git a/canon-docs/src/components/LayoutComponents/LayoutComponents.module.css b/canon-docs/src/components/LayoutComponents/LayoutComponents.module.css
new file mode 100644
index 0000000000..0e42bc6fb6
--- /dev/null
+++ b/canon-docs/src/components/LayoutComponents/LayoutComponents.module.css
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+.layoutComponents {
+ display: flex;
+ justify-content: flex-start;
+ gap: 1rem;
+ flex-wrap: wrap;
+
+ & .box {
+ display: flex;
+ flex-direction: column;
+ width: calc(33.33% - 0.67rem);
+ margin-bottom: 1rem;
+ align-items: flex-start;
+ }
+
+ & .content {
+ flex: none;
+ background-color: #fff;
+ border-radius: 4px;
+ width: 100%;
+ height: 180px;
+ transition: all 0.2s ease-in-out;
+ margin-bottom: 0.75rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ &:hover {
+ transform: translateY(-4px);
+ }
+ }
+
+ & .title {
+ font-size: 16px;
+ transition: color 0.2s ease-in-out;
+ margin-bottom: 0.25rem;
+ }
+
+ & .description {
+ font-size: 16px;
+ color: #9e9e9e;
+ }
+}
diff --git a/canon-docs/src/components/LayoutComponents/LayoutComponents.tsx b/canon-docs/src/components/LayoutComponents/LayoutComponents.tsx
new file mode 100644
index 0000000000..7262b837b3
--- /dev/null
+++ b/canon-docs/src/components/LayoutComponents/LayoutComponents.tsx
@@ -0,0 +1,60 @@
+import React from 'react';
+import { BoxSvg } from './svgs/box';
+import { StackSvg } from './svgs/stack';
+import { GridSvg } from './svgs/grid';
+import { InlineSvg } from './svgs/inline';
+import { ContainerSvg } from './svgs/container';
+import styles from './LayoutComponents.module.css';
+import Link from 'next/link';
+
+export const LayoutComponents = () => {
+ return (
+
+
+
+
+
+
Box
+
+ The most basic layout component
+
+
+
+
+
+
+
Stack
+
+ Arrange your components vertically
+
+
+
+
+
+
+
Grid
+
+ Arrange your components in a grid
+
+
+
+
+
+
+
Inline
+
+ Arrange your components in a row
+
+
+
+
+
+
+
Container
+
+ A container for your components
+
+
+
+ );
+};
diff --git a/canon-docs/src/components/LayoutComponents/index.ts b/canon-docs/src/components/LayoutComponents/index.ts
new file mode 100644
index 0000000000..55cc9f25ef
--- /dev/null
+++ b/canon-docs/src/components/LayoutComponents/index.ts
@@ -0,0 +1,16 @@
+/*
+ * 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 { LayoutComponents } from './LayoutComponents';
diff --git a/canon-docs/src/components/LayoutComponents/svgs/box.tsx b/canon-docs/src/components/LayoutComponents/svgs/box.tsx
new file mode 100644
index 0000000000..5b90f971c3
--- /dev/null
+++ b/canon-docs/src/components/LayoutComponents/svgs/box.tsx
@@ -0,0 +1,54 @@
+/*
+ * 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 React from 'react';
+
+export const BoxSvg = () => {
+ return (
+
+ );
+};
diff --git a/canon-docs/src/components/LayoutComponents/svgs/container.tsx b/canon-docs/src/components/LayoutComponents/svgs/container.tsx
new file mode 100644
index 0000000000..5a8fe77af3
--- /dev/null
+++ b/canon-docs/src/components/LayoutComponents/svgs/container.tsx
@@ -0,0 +1,372 @@
+/*
+ * 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 React from 'react';
+
+export const ContainerSvg = () => {
+ return (
+
+ );
+};
diff --git a/canon-docs/src/components/LayoutComponents/svgs/grid.tsx b/canon-docs/src/components/LayoutComponents/svgs/grid.tsx
new file mode 100644
index 0000000000..ef071c9c91
--- /dev/null
+++ b/canon-docs/src/components/LayoutComponents/svgs/grid.tsx
@@ -0,0 +1,91 @@
+/*
+ * 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 React from 'react';
+
+export const GridSvg = () => {
+ return (
+
+ );
+};
diff --git a/canon-docs/src/components/LayoutComponents/svgs/inline.tsx b/canon-docs/src/components/LayoutComponents/svgs/inline.tsx
new file mode 100644
index 0000000000..ecbff566db
--- /dev/null
+++ b/canon-docs/src/components/LayoutComponents/svgs/inline.tsx
@@ -0,0 +1,92 @@
+/*
+ * 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 React from 'react';
+
+export const InlineSvg = () => {
+ return (
+
+ );
+};
diff --git a/canon-docs/src/components/LayoutComponents/svgs/stack.tsx b/canon-docs/src/components/LayoutComponents/svgs/stack.tsx
new file mode 100644
index 0000000000..c54cba57cf
--- /dev/null
+++ b/canon-docs/src/components/LayoutComponents/svgs/stack.tsx
@@ -0,0 +1,82 @@
+/*
+ * 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 React from 'react';
+
+export const StackSvg = () => {
+ return (
+
+ );
+};
diff --git a/canon-docs/src/components/PropsTable/PropsTable.tsx b/canon-docs/src/components/PropsTable/PropsTable.tsx
new file mode 100644
index 0000000000..6eb1f8cd88
--- /dev/null
+++ b/canon-docs/src/components/PropsTable/PropsTable.tsx
@@ -0,0 +1,47 @@
+import React from 'react';
+import * as Table from '../Table';
+import { Chip } from '../Chip';
+
+// Define a more specific type for the data object
+type PropData = {
+ type: string | string[];
+ responsive: boolean;
+};
+
+// Modify the PropsTable component to use the new type
+export const PropsTable = >({
+ data,
+}: {
+ data: T;
+}) => {
+ return (
+
+
+
+ Prop
+ Type
+ Responsive
+
+
+
+ {Object.keys(data).map(n => (
+
+
+ {n}
+
+
+ {Array.isArray(data[n].type) ? (
+ data[n].type.map(t => {t})
+ ) : (
+ {data[n].type}
+ )}
+
+
+ {data[n].responsive ? 'Yes' : 'No'}
+
+
+ ))}
+
+
+ );
+};
diff --git a/canon-docs/src/components/PropsTable/index.ts b/canon-docs/src/components/PropsTable/index.ts
new file mode 100644
index 0000000000..06d884c13d
--- /dev/null
+++ b/canon-docs/src/components/PropsTable/index.ts
@@ -0,0 +1,16 @@
+/*
+ * 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 { PropsTable } from './PropsTable';
diff --git a/canon-docs/src/components/Roadmap/Roadmap.tsx b/canon-docs/src/components/Roadmap/Roadmap.tsx
new file mode 100644
index 0000000000..2177ea558f
--- /dev/null
+++ b/canon-docs/src/components/Roadmap/Roadmap.tsx
@@ -0,0 +1,53 @@
+/*
+ * 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 React from 'react';
+import { RoadmapItem } from './list';
+
+export const Roadmap = ({ list }: { list: RoadmapItem[] }) => {
+ const orderList = ['inProgress', 'notStarted', 'completed'];
+ return (
+