Improve docs

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2024-12-30 15:24:36 +01:00
parent eb16a03768
commit 436e92cd17
14 changed files with 403 additions and 130 deletions
+6 -1
View File
@@ -15,6 +15,7 @@
*/
import React from 'react';
import styles from './styles.module.css';
export const Chip = ({
children,
@@ -23,5 +24,9 @@ export const Chip = ({
children: React.ReactNode;
head?: boolean;
}) => {
return <span className={`chip ${head ? 'head' : ''}`}>{children}</span>;
return (
<span className={`${styles.chip} ${head ? styles.head : ''}`}>
{children}
</span>
);
};
@@ -25,9 +25,9 @@
margin-right: 4px;
background-color: #f0f0f0;
color: #5d5d5d;
&.head {
background-color: #eaf2fd;
color: #2563eb;
}
}
.head {
background-color: #eaf2fd;
color: #2563eb;
}
@@ -15,8 +15,8 @@
*/
import React from 'react';
import * as Table from '..';
import { Chip } from '..';
import * as Table from '../Table';
import { Chip } from '../Chip';
// Modify the PropsTable component to accept a generic type
export const PropsTable = <T extends Record<string, any>>({
@@ -1,43 +0,0 @@
/*
* 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 function getProps(styles: Record<string, any>) {
return Object.keys(styles).reduce(
(acc: Record<string, { type: any[]; responsive: boolean }>, n) => {
const style = styles[n];
let values: string[] = [];
if (style.values) {
// If values exist, use them
values = Object.keys(style.values);
} else if (style.mappings && style.mappings.length > 0) {
// If mappings exist, use the first mapping's values
const firstMapping = style.mappings[0];
values = Object.keys(styles[firstMapping].values);
} else {
// Default to an empty array if neither values nor mappings exist
values = [];
}
acc[n] = {
type: values,
responsive: true,
};
return acc;
},
{} as Record<string, { type: string[]; responsive: boolean }>,
);
}
@@ -14,4 +14,3 @@
* limitations under the License.
*/
export { PropsTable } from './PropsTable';
export { getProps } from './getProps';
@@ -0,0 +1,21 @@
'use client';
import { useTheme } from 'next-themes';
import styles from './styles.module.css';
export const Story = ({ id, height }: { id: string; height?: number }) => {
const { theme } = useTheme();
const localTheme = theme === 'dark' ? 'Dark' : 'Light';
const chromaticId = '67584b7e8c2eb09c0422c27e-dmfbzicnkw';
const chromaticUrl = `https://${chromaticId}.chromatic.com/iframe.html`;
const iframeUrl = `${chromaticUrl}?globals=theme%3A${localTheme}&args=&id=${id}`;
return (
<div
className={styles.container}
style={{ height: height ? `${height}px` : '120px' }}
>
<iframe src={iframeUrl} width="100%" height="100%" />
</div>
);
};
@@ -0,0 +1,7 @@
.container {
width: 100%;
border: 1px solid var(--canon-border-base);
margin-bottom: 1rem;
border-radius: 0.5rem;
overflow: hidden;
}
+10 -5
View File
@@ -15,11 +15,12 @@
*/
import React from 'react';
import styles from './styles.module.css';
export const Root = ({ children }: { children: React.ReactNode }) => {
return (
<div className="sb-table-wrapper">
<table className="sb-table">{children}</table>
<div className={styles.wrapper}>
<table className={styles.table}>{children}</table>
</div>
);
};
@@ -37,13 +38,17 @@ export const HeaderRow = ({ children }: { children: React.ReactNode }) => {
};
export const HeaderCell = ({ children }: { children: React.ReactNode }) => {
return <th className="sb-table-cell sb-table-header-cell">{children}</th>;
return (
<th className={`${styles.tableCell} ${styles.tableHeaderCell}`}>
{children}
</th>
);
};
export const Row = ({ children }: { children: React.ReactNode }) => {
return <tr className="sb-table-row">{children}</tr>;
return <tr className={styles.tableRow}>{children}</tr>;
};
export const Cell = ({ children }: { children: React.ReactNode }) => {
return <td className="sb-table-cell">{children}</td>;
return <td className={styles.tableCell}>{children}</td>;
};
@@ -1,72 +0,0 @@
/*
* 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.
*/
.sb-table-wrapper {
border: 1px solid #e7e7e7;
border-radius: 4px;
overflow: hidden;
& .sb-table {
width: 100%;
margin: 0 !important;
padding: 0 !important;
border-spacing: 0px;
border-collapse: collapse;
}
& .sb-table-cell {
padding: 12px 16px !important;
border: none !important;
text-align: left;
background-color: white !important;
font-size: 16px;
& p {
margin: 0;
}
}
& .sb-table-header-cell {
background-color: #f5f5f5 !important;
border-bottom: 1px solid #e7e7e7 !important;
font-weight: 500;
font-size: 14px;
}
& .sb-table-row {
border: none;
border-bottom: 1px solid #e7e7e7;
&:last-child {
border-bottom: none;
}
}
& .sb-table-chip {
display: inline-block;
font-size: 14px !important;
border: 1px solid #e7e7e7;
border-radius: 6px;
padding: 0px 6px;
height: 24px;
}
& .sb-table-type {
display: flex;
flex-wrap: wrap;
flex-direction: row;
gap: 8px;
}
}
@@ -0,0 +1,73 @@
/*
* 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.
*/
.wrapper {
border: 1px solid #e7e7e7;
border-radius: 4px;
overflow: hidden;
margin-bottom: 1rem;
}
.table {
width: 100%;
margin: 0 !important;
padding: 0 !important;
border-spacing: 0px;
border-collapse: collapse;
}
.tableCell {
padding: 12px 16px !important;
border: none !important;
text-align: left;
background-color: white !important;
font-size: 16px;
& p {
margin: 0;
}
}
.tableHeaderCell {
/* background-color: #f5f5f5 !important; */
border-bottom: 1px solid #e7e7e7 !important;
font-weight: 500;
font-size: 14px;
}
.tableRow {
border: none;
border-bottom: 1px solid #e7e7e7;
&:last-child {
border-bottom: none;
}
}
.tableChip {
display: inline-block;
font-size: 14px !important;
border: 1px solid #e7e7e7;
border-radius: 6px;
padding: 0px 6px;
height: 24px;
}
.tableType {
display: flex;
flex-wrap: wrap;
flex-direction: row;
gap: 8px;
}
+99
View File
@@ -0,0 +1,99 @@
import { Story } from '../components/Story';
import { CodeBlock } from '../components/CodeBlock';
import { PropsTable } from '../components/PropsTable';
import { spacePropsList } from '../utils/spaceProps';
# Box
Box is the lowest-level component in Canon. We use it internally to build all
of our components. It provides a consistent API for styling and layout.
<CodeBlock
code={`import { Box } from "@backstage/canon";
<Box>Hello World!</Box>`} />
## API reference
### Box
This is the Box component, our lowest-level component. Here are all the
available properties.
<PropsTable
data={{
alignItems: {
type: ['stretch', 'start', 'center', 'end'],
responsive: true,
},
border: {
type: ['none', 'base', 'error', 'warning', 'selected'],
responsive: true,
},
borderRadius: {
type: ['none', '2xs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl'],
responsive: true,
},
children: {
type: 'ReactNode',
responsive: false,
},
className: {
type: 'string',
responsive: false,
},
display: {
type: ['none', 'flex', 'block', 'inline'],
responsive: true,
},
flexDirection: {
type: ['row', 'column'],
responsive: true,
},
flexWrap: {
type: ['wrap', 'nowrap', 'wrap-reverse'],
responsive: true,
},
gap: {
type: ['2xs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl'],
responsive: true,
},
justifyContent: {
type: ['stretch', 'start', 'center', 'end', 'around', 'between'],
responsive: true,
},
style: {
type: 'CSSProperties',
responsive: false,
},
}}
/>
Padding and margin are used to create space around your component using our
predefined spacing tokens. We would recommend to use padding over margin to
avoid collapsing margins but both are available.
<PropsTable data={spacePropsList} />
## Examples
### Simple example
A simple example of how to use the Box component.
<CodeBlock
title="Usage"
code={`<Box padding="md" borderRadius="md">Hello World</Box>`}
/>
### Responsive
Here's a view when buttons are responsive.
<CodeBlock
code={`<Box
padding={{ xs: 'sm', md: 'md' }}
borderRadius={{ xs: 'sm', md: 'md' }}>
Hello World
</Box>`}
/>
+125 -1
View File
@@ -1 +1,125 @@
# Hello
import { Story } from '../components/Story';
import { CodeBlock } from '../components/CodeBlock';
import { PropsTable } from '../components/PropsTable';
# Button
A button component that can be used to trigger actions.
<Story id="components-button--primary" />
<CodeBlock
code={`<Button>Click me</Button>
`}
/>
## API reference
<PropsTable
data={{
size: {
type: ['small', 'medium'],
responsive: true,
},
variant: {
type: ['primary', 'secondary', 'tertiary'],
responsive: true,
},
disabled: {
type: 'boolean',
responsive: false,
},
children: {
type: 'ReactNode',
responsive: false,
},
className: {
type: 'string',
responsive: false,
},
style: {
type: 'CSSProperties',
responsive: false,
},
}}
/>
## Examples
### Variants
Here's a view when buttons have different variants.
<Story id="components-button--variants" />
<CodeBlock
title="Usage"
code={`<Inline alignY="center">
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
</Inline>`}
/>
### Sizes
Here's a view when buttons have different sizes.
<Story id="components-button--sizes" />
<CodeBlock
title="Usage"
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.
<Story id="components-button--with-icons" />
<CodeBlock
title="Usage"
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.
<Story id="components-button--full-width" height={240} />
<CodeBlock
code={`<Stack style={{ width: '300px' }}>
<Button fullWidth>Full width</Button>
</Stack>`}
/>
### Disabled
Here's a view when buttons are disabled.
<Story id="components-button--disabled" />
<CodeBlock title="Usage" code={`<Button disabled>Button</Button>`} />
### Responsive
Here's a view when buttons are responsive.
<Story id="components-button--responsive" />
<CodeBlock
code={`<Button
variant={{ xs: 'primary', sm: 'secondary', md: 'tertiary' }}
size={{ xs: 'small', sm: 'medium' }}>
Button
</Button>`}
/>
+14
View File
@@ -36,12 +36,26 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
{children as ReactNode}
</h2>
),
h3: ({ children }) => (
<h3
style={{
color: 'var(--canon-text-primary)',
fontSize: '1.25rem',
marginTop: '2.5rem',
marginBottom: '0.5rem',
}}
>
{children as ReactNode}
</h3>
),
p: ({ children }) => (
<p
style={{
color: 'var(--canon-text-primary)',
fontSize: '1rem',
lineHeight: '1.5rem',
marginTop: '0',
marginBottom: '1rem',
}}
>
{children as ReactNode}
+41
View File
@@ -0,0 +1,41 @@
/*
* 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 const spacePropsList = [
'margin',
'marginBottom',
'marginLeft',
'marginRight',
'marginTop',
'marginX',
'marginY',
'padding',
'paddingBottom',
'paddingLeft',
'paddingRight',
'paddingTop',
'paddingX',
'paddingY',
].reduce(
(acc: { [key: string]: { type: string[]; responsive: boolean } }, prop) => {
acc[prop] = {
type: ['2xs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl'],
responsive: true,
};
return acc;
},
{},
);