Add new Container component

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2024-12-06 17:20:52 +00:00
parent 8ca1549547
commit 64337dd2de
10 changed files with 282 additions and 1 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ import { list } from './components/Roadmap/list';
<ComponentStatus name="Checkbox" status="notStarted" />
<ComponentStatus
name="Container"
status="inProgress"
status="alpha"
link="/?path=/docs/components-container--docs"
/>
<ComponentStatus
@@ -0,0 +1,68 @@
/*
* 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 { Box } from '../Box/Box';
import { argTypesSpacing } from '../../../docs/utils/argTypes';
import { Container } from './Container';
const argTypesSpacingWithoutLeftAndRight = { ...argTypesSpacing };
delete argTypesSpacingWithoutLeftAndRight.padding;
delete argTypesSpacingWithoutLeftAndRight.paddingLeft;
delete argTypesSpacingWithoutLeftAndRight.paddingRight;
delete argTypesSpacingWithoutLeftAndRight.paddingX;
delete argTypesSpacingWithoutLeftAndRight.margin;
delete argTypesSpacingWithoutLeftAndRight.marginLeft;
delete argTypesSpacingWithoutLeftAndRight.marginRight;
delete argTypesSpacingWithoutLeftAndRight.marginX;
delete argTypesSpacingWithoutLeftAndRight.gap;
const meta = {
title: 'Components/Container',
component: Container,
argTypes: {
...argTypesSpacingWithoutLeftAndRight,
children: {
control: false,
},
className: {
control: 'text',
},
},
parameters: {
layout: 'fullscreen',
},
} satisfies Meta<typeof Container>;
export default meta;
type Story = StoryObj<typeof meta>;
const FakeBox = () => (
<Box
borderRadius="small"
style={{ background: '#1f47ff', color: 'white', height: '400px' }}
/>
);
export const Default: Story = {
args: {},
render: args => (
<Container {...args}>
<FakeBox />
</Container>
),
};
@@ -0,0 +1,37 @@
/*
* 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, { forwardRef } from 'react';
import { containerSprinkles } from './sprinkles.css';
import { ContainerProps } from './types';
/** @public */
export const Container = forwardRef<HTMLDivElement, ContainerProps>(
(props, ref) => {
const { children, className, style, ...restProps } = props;
const containerClassName = containerSprinkles(restProps);
return (
<div
ref={ref}
className={['container', containerClassName].filter(Boolean).join(' ')}
style={style}
>
{children}
</div>
);
},
);
@@ -0,0 +1,74 @@
import { Meta, Unstyled, Source } from '@storybook/blocks';
import * as ContainerStories from './Container.stories';
import { Title, Text } from '../../../docs/components';
import { PropsTable, getBoxProps } from '../../../docs/components/PropsTable';
import { spacingProperties } from '../../layout/sprinkles.css';
import { containerProperties } from './sprinkles.css';
<Meta of={ContainerStories} />
<Unstyled>
<Title type="h1">Container</Title>
<Text>
The container component let you use our default max-width and center the
content on the page.
</Text>
<Title type="h2">Installation</Title>
<Source code={`yarn install @backstage/canon/container`} language="bash" dark />
<Title type="h2" style={{ marginBottom: '16px' }}>
API reference
</Title>
<PropsTable
data={{
...getBoxProps(containerProperties.styles),
children: {
type: 'ReactNode',
required: false,
},
className: {
type: 'string',
required: false,
},
style: {
type: 'CSSProperties',
required: false,
},
}}
/>
<Title type="h2">Examples</Title>
<Title type="h3">Simple</Title>
<Text>A simple example of how to use the Container component.</Text>
<Source
code={`<Container>
<Box>Hello World</Box>
<Box>Hello World</Box>
<Box>Hello World</Box>
</Container>`}
language="tsx"
dark
/>
<Title type="h3">Responsive padding & margin</Title>
<Text>
The Container component also supports responsive values, making it easy to
create responsive designs.
</Text>
<Source
code={`<Container paddingY={{ xs: 'sm', md: 'md' }}>
<Box>Hello World</Box>
<Box>Hello World</Box>
<Box>Hello World</Box>
</Container>`}
language="tsx"
dark
/>
</Unstyled>
@@ -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 { Container } from './Container';
export type { ContainerProps } from './types';
@@ -0,0 +1,40 @@
/*
* 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, space } from '../../layout/properties';
import { colorProperties, spacingProperties } from '../../layout/sprinkles.css';
export const containerProperties = defineProperties({
conditions: breakpoints,
defaultCondition: 'xs',
properties: {
paddingTop: space,
paddingBottom: space,
marginTop: space,
marginBottom: space,
},
shorthands: {
paddingY: ['paddingTop', 'paddingBottom'],
marginY: ['marginTop', 'marginBottom'],
},
});
export const containerSprinkles = createSprinkles(
spacingProperties,
colorProperties,
containerProperties,
);
@@ -0,0 +1,5 @@
.container {
max-width: var(--canon-container-max-width);
margin: 0 auto;
padding: 0 var(--canon-container-padding);
}
@@ -0,0 +1,35 @@
/*
* 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 { SpaceProps } from '../../layout/types';
/** @public */
export interface ContainerProps
extends Omit<
SpaceProps,
| 'padding'
| 'paddingLeft'
| 'paddingRight'
| 'paddingX'
| 'margin'
| 'marginLeft'
| 'marginRight'
| 'marginX'
| 'gap'
> {
children?: React.ReactNode;
className?: string;
style?: React.CSSProperties;
}
+1
View File
@@ -26,3 +26,4 @@
@import '../components/Stack/styles.css';
@import '../components/Inline/styles.css';
@import '../components/Grid/styles.css';
@import '../components/Container/styles.css';
+4
View File
@@ -74,6 +74,10 @@
--canon-spacing-lg: 2rem;
--canon-spacing-xl: 3.25rem;
--canon-spacing-2xl: 5.25rem;
/* Container */
--canon-container-max-width: 1200px;
--canon-container-padding: 1rem;
}
/* Dark theme */