Add first pass at Grid component

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2024-12-03 21:05:03 +00:00
parent 6bdc5a7d76
commit 12c796488c
9 changed files with 367 additions and 16 deletions
+21 -16
View File
@@ -43,33 +43,38 @@ import { list } from './components/Roadmap/list';
link="/?path=/docs/components-box--docs"
/>
<ComponentStatus
name="Stack"
name="Button"
status="inProgress"
link="/?path=/docs/components-button--docs"
/>
<ComponentStatus name="Checkbox" status="notStarted" />
<ComponentStatus
name="Grid"
status="alpha"
link="/?path=/docs/components-stack--default"
link="/?path=/story/components-grid--docs"
/>
<ComponentStatus name="Header" status="notStarted" />
<ComponentStatus
name="Icon"
status="alpha"
link="/?path=/docs/components-icon--docs"
/>
<ComponentStatus
name="Inline"
status="alpha"
link="/?path=/story/components-inline--default"
/>
<ComponentStatus
name="Button"
status="inProgress"
link="/?path=/docs/components-button--docs"
/>
<ComponentStatus
name="Icon"
status="alpha"
link="/?path=/docs/components-icon--docs"
/>
<ComponentStatus name="Input" status="notStarted" />
<ComponentStatus name="Select" status="notStarted" />
<ComponentStatus name="Checkbox" status="notStarted" />
<ComponentStatus name="Radio" status="notStarted" />
<ComponentStatus name="Select" status="notStarted" />
<ComponentStatus
name="Stack"
status="alpha"
link="/?path=/docs/components-stack--default"
/>
<ComponentStatus name="Switch" status="notStarted" />
<ComponentStatus name="Tooltip" status="notStarted" />
<ComponentStatus name="Header" status="notStarted" />
<ComponentStatus name="Tabs" status="notStarted" />
<ComponentStatus name="Tooltip" status="notStarted" />
</Columns>
<Title style={{ marginTop: '48px' }} type="h2">
@@ -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';
import type { Meta, StoryObj } from '@storybook/react';
import { Grid } from './Grid';
import type { GridItemProps } from './types';
import { Box } from '../Box/Box';
import { argTypesSpacing, argTypesColor } from '../../../docs/utils/argTypes';
import { Stack } from '../Stack';
const meta = {
title: 'Components/Grid',
component: Grid,
argTypes: {
...argTypesSpacing,
...argTypesColor,
children: {
control: false,
},
className: {
control: 'text',
},
},
args: {
gap: 'xs',
},
} satisfies Meta<typeof Grid>;
export default meta;
type Story = StoryObj<typeof meta>;
const FakeBox = () => (
<Box
borderRadius="small"
style={{ background: '#1f47ff', color: 'white', height: '64px' }}
/>
);
export const Default: Story = {
args: {
columns: 3,
},
render: args => (
<Grid {...args}>
<Grid.Item>
<FakeBox />
</Grid.Item>
<Grid.Item>
<FakeBox />
</Grid.Item>
<Grid.Item>
<FakeBox />
</Grid.Item>
</Grid>
),
};
export const ColumnSizes: Story = {
args: {
columns: 12,
gap: 'md',
},
render: args => (
<Stack gap="md">
{Array.from({ length: 11 }, (_, i) => (
<Grid {...args} key={i}>
<Grid.Item span={(i + 1) as GridItemProps['span']}>
<FakeBox />
</Grid.Item>
<Grid.Item span={(11 - i) as GridItemProps['span']}>
<FakeBox />
</Grid.Item>
</Grid>
))}
</Stack>
),
};
@@ -0,0 +1,70 @@
/*
* 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 { createElement } from 'react';
import { GridItemProps, GridProps } from './types';
import { gridItemSprinkles, gridSprinkles } from './sprinkles.css';
export const Grid = ({
children,
columns = 1,
gap = 'xs',
className,
style,
...restProps
}: GridProps) => {
const sprinklesClassName = gridSprinkles({
...restProps,
gap,
gridTemplateColumns: columns,
});
const classNames = ['grid', sprinklesClassName, className]
.filter(Boolean)
.join(' ');
return createElement(
'div',
{
className: classNames,
style,
},
children,
);
};
const GridItem = ({
children,
span = 1,
start,
end,
className,
style,
}: GridItemProps) => {
const sprinklesClassName = gridItemSprinkles({
span,
start,
end,
});
const classNames = ['grid-item', sprinklesClassName, className]
.filter(Boolean)
.join(' ');
return createElement('div', { className: classNames, style }, children);
};
Grid.Item = GridItem;
@@ -0,0 +1,17 @@
/*
* 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 { Grid } from './Grid';
export type { GridProps, GridItemProps } from './types';
@@ -0,0 +1,113 @@
/*
* 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 { defineProperties, createSprinkles } from '@vanilla-extract/sprinkles';
import { breakpoints } from '../../layout/properties';
import { colorProperties, spacingProperties } from '../../layout/sprinkles.css';
const gridProperties = defineProperties({
conditions: breakpoints,
defaultCondition: 'xs',
properties: {
gridTemplateColumns: {
1: 'repeat(1, minmax(0, 1fr))',
2: 'repeat(2, minmax(0, 1fr))',
3: 'repeat(3, minmax(0, 1fr))',
4: 'repeat(4, minmax(0, 1fr))',
5: 'repeat(5, minmax(0, 1fr))',
6: 'repeat(6, minmax(0, 1fr))',
7: 'repeat(7, minmax(0, 1fr))',
8: 'repeat(8, minmax(0, 1fr))',
9: 'repeat(9, minmax(0, 1fr))',
10: 'repeat(10, minmax(0, 1fr))',
11: 'repeat(11, minmax(0, 1fr))',
12: 'repeat(12, minmax(0, 1fr))',
},
},
shorthands: {
columns: ['gridTemplateColumns'],
},
});
export const gridSprinkles = createSprinkles(
spacingProperties,
colorProperties,
gridProperties,
);
const gridItemProperties = defineProperties({
conditions: breakpoints,
defaultCondition: 'xs',
properties: {
gridColumn: {
1: 'span 1 / span 1',
2: 'span 2 / span 2',
3: 'span 3 / span 3',
4: 'span 4 / span 4',
5: 'span 5 / span 5',
6: 'span 6 / span 6',
7: 'span 7 / span 7',
8: 'span 8 / span 8',
9: 'span 9 / span 9',
10: 'span 10 / span 10',
11: 'span 11 / span 11',
12: 'span 12 / span 12',
full: '1 / -1',
},
gridColumnStart: {
1: '1',
2: '2',
3: '3',
4: '4',
5: '5',
6: '6',
7: '7',
8: '8',
9: '9',
10: '10',
11: '11',
12: '12',
13: '13',
auto: 'auto',
},
gridColumnEnd: {
1: '1',
2: '2',
3: '3',
4: '4',
5: '5',
6: '6',
7: '7',
8: '8',
9: '9',
10: '10',
11: '11',
12: '12',
13: '13',
auto: 'auto',
},
},
shorthands: {
span: ['gridColumn'],
start: ['gridColumnStart'],
end: ['gridColumnEnd'],
},
});
export const gridItemSprinkles = createSprinkles(
colorProperties,
gridItemProperties,
);
@@ -0,0 +1,3 @@
.grid {
display: grid;
}
@@ -0,0 +1,48 @@
/*
* 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 { Breakpoint, ColorProps } from '../../layout/types';
import { SpaceProps } from '../../layout/types';
export interface GridProps extends SpaceProps, ColorProps {
children?: React.ReactNode;
columns?:
| 1
| 2
| 3
| 4
| 5
| 6
| 7
| 8
| 9
| 10
| 11
| 12
| Partial<
Record<Breakpoint, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12>
>;
className?: string;
style?: React.CSSProperties;
}
export interface GridItemProps {
children: React.ReactNode;
span?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'full';
start?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 'auto';
end?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 'auto';
className?: string;
style?: React.CSSProperties;
}
+3
View File
@@ -24,3 +24,6 @@ export * from './components/Button';
export * from './components/Box';
export * from './components/Icon';
export * from './layout/types';
export * from './components/Grid';
export * from './components/Stack';
export * from './components/Inline';
+1
View File
@@ -25,3 +25,4 @@
@import '../components/Button/styles.css';
@import '../components/Stack/styles.css';
@import '../components/Inline/styles.css';
@import '../components/Grid/styles.css';