Improve styling + add Table components

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2024-12-10 16:31:52 +00:00
parent b6d0969b16
commit 1ccd1d9206
17 changed files with 592 additions and 26 deletions
+8 -1
View File
@@ -6,7 +6,9 @@ import { withThemeByDataAttribute } from '@storybook/addon-themes';
import '../docs/components/styles.css';
// Canon specific styles
import '../src/theme/styles.css';
import '../src/css/backstage.css';
import '../src/css/components.css';
// Custom themes
import './themes/backstage.css';
@@ -22,6 +24,11 @@ const preview: Preview = {
backgrounds: {
disable: true,
},
options: {
storySort: {
method: 'alphabetical',
},
},
},
decorators: [
withThemeByDataAttribute<ReactRenderer>({
@@ -22,7 +22,7 @@
user-select: none;
font-family: var(--canon-font-regular);
font-weight: var(--canon-font-bold);
font-size: var(--canon-font-sizes-md);
font-size: var(--canon-font-size-md);
padding: 0;
transition: all 150ms ease;
cursor: pointer;
@@ -4,7 +4,7 @@
align-items: center;
justify-content: center;
gap: var(--canon-spacing-xs);
font-size: var(--canon-font-sizes-xs);
font-size: var(--canon-font-size-xs);
font-family: var(--canon-font-regular);
color: var(--canon-text-primary);
@@ -0,0 +1,5 @@
import { Meta, Controls } from '@storybook/blocks';
<Meta title="Components/Table" />
# Table
@@ -0,0 +1,93 @@
/*
* 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 * as React from 'react';
const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="table">
<table ref={ref} className={['', className].join(' ')} {...props} />
</div>
));
Table.displayName = 'Table';
const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={['', className].join(' ')} {...props} />
));
TableHeader.displayName = 'TableHeader';
const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody ref={ref} className={['', className].join(' ')} {...props} />
));
TableBody.displayName = 'TableBody';
const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot ref={ref} className={['', className].join(' ')} {...props} />
));
TableFooter.displayName = 'TableFooter';
const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr ref={ref} className={['', className].join(' ')} {...props} />
));
TableRow.displayName = 'TableRow';
const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th ref={ref} className={['', className].join(' ')} {...props} />
));
TableHead.displayName = 'TableHead';
const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td ref={ref} className={['', className].join(' ')} {...props} />
));
TableCell.displayName = 'TableCell';
const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption ref={ref} className={['', className].join(' ')} {...props} />
));
TableCaption.displayName = 'TableCaption';
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
};
@@ -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 type { Meta, StoryObj } from '@storybook/react';
import { Table } from '../Table';
const meta = {
title: 'Components/Table/Table',
component: Table,
} satisfies Meta<typeof Table>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {
children: "Hello World! I'm a basic table",
},
};
@@ -0,0 +1,30 @@
/*
* 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 type { Meta, StoryObj } from '@storybook/react';
import { TableBody } from '../Table';
const meta = {
title: 'Components/Table/TableBody',
component: TableBody,
} satisfies Meta<typeof TableBody>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {},
};
@@ -0,0 +1,30 @@
/*
* 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 type { Meta, StoryObj } from '@storybook/react';
import { TableCaption } from '../Table';
const meta = {
title: 'Components/Table/TableCaption',
component: TableCaption,
} satisfies Meta<typeof TableCaption>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {},
};
@@ -0,0 +1,30 @@
/*
* 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 type { Meta, StoryObj } from '@storybook/react';
import { TableCell } from '../Table';
const meta = {
title: 'Components/Table/TableCell',
component: TableCell,
} satisfies Meta<typeof TableCell>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {},
};
@@ -0,0 +1,30 @@
/*
* 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 type { Meta, StoryObj } from '@storybook/react';
import { TableFooter } from '../Table';
const meta = {
title: 'Components/Table/TableFooter',
component: TableFooter,
} satisfies Meta<typeof TableFooter>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {},
};
@@ -0,0 +1,30 @@
/*
* 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 type { Meta, StoryObj } from '@storybook/react';
import { TableHead } from '../Table';
const meta = {
title: 'Components/Table/TableHead',
component: TableHead,
} satisfies Meta<typeof TableHead>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {},
};
@@ -0,0 +1,30 @@
/*
* 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 type { Meta, StoryObj } from '@storybook/react';
import { TableHeader } from '../Table';
const meta = {
title: 'Components/Table/TableHeader',
component: TableHeader,
} satisfies Meta<typeof TableHeader>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {},
};
@@ -0,0 +1,30 @@
/*
* 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 type { Meta, StoryObj } from '@storybook/react';
import { TableRow } from '../Table';
const meta = {
title: 'Components/Table/TableRow',
component: TableRow,
} satisfies Meta<typeof TableRow>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {},
};
@@ -0,0 +1,11 @@
.table {
position: relative;
overflow: auto;
width: 100%;
table {
width: 100%;
caption-side: bottom;
font-size: var(--canon-font-size-sm);
}
}
@@ -14,7 +14,20 @@
* limitations under the License.
*/
/* Light theme */
/* Normalize */
@import './normalize.css';
/* Geist font */
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&family=Geist:wght@100..900&display=swap');
*,
html,
body {
font-family: var(--canon-font-regular);
}
/* Light theme tokens */
:root {
/* Colors */
--canon-accent: #000;
@@ -51,20 +64,20 @@
--canon-font-bold: 600;
/* Font sizes */
--canon-font-sizes-2xs: 0.625rem;
--canon-font-sizes-xs: 0.75rem;
--canon-font-sizes-sm: 0.875rem;
--canon-font-sizes-md: 1rem;
--canon-font-sizes-lg: 1.125rem;
--canon-font-sizes-xl: 1.25rem;
--canon-font-sizes-2xl: 1.5rem;
--canon-font-sizes-3xl: 1.875rem;
--canon-font-sizes-4xl: 2.25rem;
--canon-font-sizes-5xl: 3rem;
--canon-font-sizes-6xl: 3.75rem;
--canon-font-sizes-7xl: 4.5rem;
--canon-font-sizes-8xl: 6rem;
--canon-font-sizes-9xl: 8rem;
--canon-font-size-2xs: 0.625rem;
--canon-font-size-xs: 0.75rem;
--canon-font-size-sm: 0.875rem;
--canon-font-size-md: 1rem;
--canon-font-size-lg: 1.125rem;
--canon-font-size-xl: 1.25rem;
--canon-font-size-2xl: 1.5rem;
--canon-font-size-3xl: 1.875rem;
--canon-font-size-4xl: 2.25rem;
--canon-font-size-5xl: 3rem;
--canon-font-size-6xl: 3.75rem;
--canon-font-size-7xl: 4.5rem;
--canon-font-size-8xl: 6rem;
--canon-font-size-9xl: 8rem;
/* Spacing */
--canon-spacing-2xs: 0.25rem;
@@ -80,7 +93,7 @@
--canon-container-padding: 1rem;
}
/* Dark theme */
/* Dark theme tokens */
[data-theme='dark'] {
/* Colors */
--canon-accent: #fff;
@@ -14,13 +14,6 @@
* limitations under the License.
*/
/* Geist font */
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&family=Geist:wght@100..900&display=swap');
/* Theme */
@import './theme.css';
/* Components */
@import '../components/Button/styles.css';
@import '../components/Stack/styles.css';
@@ -29,3 +22,4 @@
@import '../components/Container/styles.css';
@import '../components/Icon/styles.css';
@import '../components/Checkbox/styles.css';
@import '../components/Table/styles.css';
+201
View File
@@ -0,0 +1,201 @@
/*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */
/*
Document
========
*/
/**
Use a better box model (opinionated).
*/
*,
::before,
::after {
box-sizing: border-box;
}
html {
/* Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) */
font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
'Apple Color Emoji', 'Segoe UI Emoji';
line-height: 1.15; /* 1. Correct the line height in all browsers. */
-webkit-text-size-adjust: 100%; /* 2. Prevent adjustments of font size after orientation changes in iOS. */
tab-size: 4; /* 3. Use a more readable tab size (opinionated). */
}
/*
Sections
========
*/
body {
margin: 0; /* Remove the margin in all browsers. */
}
/*
Text-level semantics
====================
*/
/**
Add the correct font weight in Chrome and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
2. Correct the odd 'em' font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo,
monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
Prevent 'sub' and 'sup' elements from affecting the line height in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/*
Tabular data
============
*/
/**
Correct table border color inheritance in Chrome and Safari. (https://issues.chromium.org/issues/40615503, https://bugs.webkit.org/show_bug.cgi?id=195016)
*/
table {
border-color: currentcolor;
}
/*
Forms
=====
*/
/**
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type='button'],
[type='reset'],
[type='submit'] {
-webkit-appearance: button;
}
/**
Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers.
*/
legend {
padding: 0;
}
/**
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
vertical-align: baseline;
}
/**
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/**
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type='search'] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to 'inherit' in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/*
Interactive
===========
*/
/*
Add the correct display in Chrome and Safari.
*/
summary {
display: list-item;
}