Improve Box + Stack components

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2024-11-28 18:37:26 +00:00
parent 798991e74f
commit da1d5bbe8d
20 changed files with 426 additions and 427 deletions
@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { boxProperties } from '../../src/components/Box/sprinkles.css';
import {
responsiveProperties,
colorProperties,
} from '../components/Box/sprinkles.css';
spacingProperties,
} from '../../src/layout/sprinkles.css';
export const listResponsiveValues = (
value: keyof typeof responsiveProperties.styles,
value: keyof typeof boxProperties.styles,
) => {
const values = responsiveProperties.styles[value];
const values = boxProperties.styles[value];
if ('values' in values) {
return Object.keys(values.values);
@@ -40,3 +40,25 @@ export const listColorValues = (value: keyof typeof colorProperties.styles) => {
return [];
};
export const argTypesSpacing = Object.keys(spacingProperties.styles).reduce<
Record<string, any>
>((acc, n) => {
acc[n] = {
control: 'inline-radio',
options: ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'],
};
return acc;
}, {});
export const argTypesColor = Object.keys(colorProperties.styles).reduce<
Record<string, any>
>((acc, n) => {
acc[n as keyof typeof colorProperties.styles] = {
control: 'select',
options: Object.keys(
colorProperties.styles[n as keyof typeof colorProperties.styles].values,
),
};
return acc;
}, {});
@@ -17,87 +17,41 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Box } from './Box';
import { listResponsiveValues } from '../../utils/list-values';
import { responsiveProperties, colorProperties } from './sprinkles.css';
import {
listResponsiveValues,
argTypesSpacing,
argTypesColor,
} from '../../../docs/utils/argTypes';
import { boxProperties } from './sprinkles.css';
const argTypesResponsive = Object.keys(responsiveProperties.styles).reduce<
const argTypesBox = Object.keys(boxProperties.styles).reduce<
Record<string, any>
>((acc, n) => {
if (
[
'margin',
'marginBottom',
'marginLeft',
'marginRight',
'marginTop',
'marginX',
'marginY',
'padding',
'paddingBottom',
'paddingLeft',
'paddingRight',
'paddingTop',
'paddingX',
'paddingY',
].includes(n)
) {
acc[n] = {
control: 'select',
options: ['xs', 'sm', 'md', 'lg', 'xl', '2xl'],
};
} else {
acc[n] = {
control: 'select',
options: listResponsiveValues(
n as keyof typeof responsiveProperties.styles,
),
};
}
return acc;
}, {});
const argTypesColor = Object.keys(colorProperties.styles).reduce<
Record<string, any>
>((acc, n) => {
acc[n as keyof typeof colorProperties.styles] = {
acc[n] = {
control: 'select',
options: Object.keys(
colorProperties.styles[n as keyof typeof colorProperties.styles].values,
),
options: listResponsiveValues(n as keyof typeof boxProperties.styles),
};
return acc;
}, {});
const argTypes = {
...argTypesResponsive,
...argTypesColor,
};
// Sort the resulting object keys alphabetically
const sortedArgTypes = Object.keys(argTypes)
.sort()
.reduce((acc, key) => {
acc[key] = argTypes[key];
return acc;
}, {} as Record<string, any>);
// Add 'as' and 'children' to the sortedArgTypes
sortedArgTypes['as'] = {
control: 'select',
options: ['div', 'span', 'article', 'section'],
};
sortedArgTypes['children'] = {
control: 'text',
};
const meta = {
title: 'Components/Box',
component: Box,
parameters: {
layout: 'centered',
},
argTypes: sortedArgTypes,
argTypes: {
...argTypesSpacing,
...argTypesColor,
...argTypesBox,
as: {
control: { type: 'select' },
options: ['div', 'span', 'article', 'section'],
},
children: {
control: false,
},
},
args: {
as: 'div',
background: 'elevation1',
+9 -20
View File
@@ -21,30 +21,19 @@ import { BoxProps } from './types';
/** @public */
export const Box = (props: BoxProps) => {
const { as = 'div', className, style, ...rest } = props;
const boxSprinklesProps: Record<string, unknown> = {};
const nativeProps: Record<string, unknown> = {};
const { as = 'div', className, style, children, ...restProps } = props;
// Split props between sprinkles and native HTML props
Object.entries(rest).forEach(([key, value]) => {
if (value === undefined) return;
// Generate the list of class names
const sprinklesClassName = boxSprinkles(restProps);
if (
boxSprinkles.properties.has(
key as keyof Parameters<typeof boxSprinkles>[0],
)
) {
boxSprinklesProps[key] = value;
} else {
nativeProps[key] = value;
}
});
const sprinklesClassName = boxSprinkles(boxSprinklesProps);
// Combine the base class name, the sprinkles class name, and any additional class names
const classNames = [base, sprinklesClassName, className]
.filter(Boolean)
.join(' ');
return createElement(as, {
className: [base, sprinklesClassName, className].filter(Boolean).join(' '),
className: classNames,
style,
...nativeProps,
children,
});
};
@@ -1,13 +1,7 @@
import { Canvas, Meta, Unstyled } from '@storybook/blocks';
import * as BoxStories from './Box.stories';
import { Chip } from '../../../docs/components/Chip';
import * as Table from '../../../docs/components/Table';
import { Box } from './Box';
import { Stack } from '../Stack';
import { Title, Text } from '../../../docs/components';
import { Padding } from './docs/padding';
import { listResponsiveValues, listColorValues } from '../../utils/list-values';
import { responsiveProperties } from './sprinkles.css';
import { PropsTable } from './docs/props-table';
import { SpacingTable } from './docs/spacing-table';
@@ -17,8 +17,8 @@
import React from 'react';
import * as Table from '../../../../docs/components';
import { Chip } from '../../../../docs/components';
import { listResponsiveValues } from '../../../utils/list-values';
import { responsiveProperties } from '../sprinkles.css';
import { listResponsiveValues } from '../../../../docs/utils/argTypes';
import { boxProperties } from '../sprinkles.css';
export const PropsTable = () => {
return (
@@ -30,7 +30,7 @@ export const PropsTable = () => {
</Table.HeaderRow>
</Table.Header>
<Table.Body>
{Object.keys(responsiveProperties.styles)
{Object.keys(boxProperties.styles)
.filter(
n =>
![
@@ -57,7 +57,7 @@ export const PropsTable = () => {
</Table.Cell>
<Table.Cell>
{listResponsiveValues(
n as keyof typeof responsiveProperties.styles,
n as keyof typeof boxProperties.styles,
).map(value => (
<Chip key={value}>{value}</Chip>
))}
@@ -17,8 +17,8 @@
import React from 'react';
import * as Table from '../../../../docs/components';
import { Chip } from '../../../../docs/components';
import { listResponsiveValues } from '../../../utils/list-values';
import { responsiveProperties } from '../sprinkles.css';
import { listResponsiveValues } from '../../../../docs/utils/argTypes';
import { boxProperties } from '../sprinkles.css';
export const SpacingTable = () => {
return (
@@ -30,7 +30,7 @@ export const SpacingTable = () => {
</Table.HeaderRow>
</Table.Header>
<Table.Body>
{Object.keys(responsiveProperties.styles)
{Object.keys(boxProperties.styles)
.filter(n =>
[
'padding',
@@ -56,7 +56,7 @@ export const SpacingTable = () => {
</Table.Cell>
<Table.Cell>
{listResponsiveValues(
'paddingTop' as keyof typeof responsiveProperties.styles,
'paddingTop' as keyof typeof boxProperties.styles,
).map(value => (
<Chip key={value}>{value}</Chip>
))}
+1 -1
View File
@@ -15,4 +15,4 @@
*/
export { Box } from './Box';
export type * from './types';
export { breakpoints, space, themes } from './properties';
export { breakpoints, space, themes } from '../../layout/properties';
@@ -14,16 +14,11 @@
* limitations under the License.
*/
import {
defineProperties,
createSprinkles,
RequiredConditionalValue,
ConditionalValue,
createMapValueFn,
} from '@vanilla-extract/sprinkles';
import { breakpoints, space } from './properties';
import { defineProperties, createSprinkles } from '@vanilla-extract/sprinkles';
import { breakpoints } from '../../layout/properties';
import { colorProperties, spacingProperties } from '../../layout/sprinkles.css';
export const responsiveProperties = defineProperties({
export const boxProperties = defineProperties({
conditions: breakpoints,
defaultCondition: 'xs',
responsiveArray: ['xs', 'sm', 'md', 'lg', 'xl', '2xl'],
@@ -55,57 +50,12 @@ export const responsiveProperties = defineProperties({
error: '1px solid var(--canon-error)',
},
display: ['none', 'flex', 'block', 'inline'],
paddingTop: space,
paddingBottom: space,
paddingLeft: space,
paddingRight: space,
marginTop: space,
marginBottom: space,
marginLeft: space,
marginRight: space,
gap: space,
flexWrap: ['wrap', 'nowrap'],
},
shorthands: {
padding: ['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'],
paddingX: ['paddingLeft', 'paddingRight'],
paddingY: ['paddingTop', 'paddingBottom'],
margin: ['marginTop', 'marginBottom', 'marginLeft', 'marginRight'],
marginX: ['marginLeft', 'marginRight'],
marginY: ['marginTop', 'marginBottom'],
},
});
export const colorProperties = defineProperties({
conditions: {
light: { selector: '[data-theme="light"] &' },
dark: { selector: '[data-theme="dark"] &' },
},
defaultCondition: ['light', 'dark'],
properties: {
color: {
primary: 'var(--canon-text-primary)',
secondary: 'var(--canon-text-secondary)',
error: 'var(--canon-error)',
},
background: {
background: 'var(--canon-background)',
elevation1: 'var(--canon-surface-1)',
elevation2: 'var(--canon-surface-2)',
transparent: 'transparent',
},
},
});
export const boxSprinkles = createSprinkles(
responsiveProperties,
spacingProperties,
boxProperties,
colorProperties,
);
export type OptionalResponsiveValue<Value extends string | number> =
ConditionalValue<typeof responsiveProperties, Value>;
export type RequiredResponsiveValue<Value extends string | number> =
RequiredConditionalValue<typeof responsiveProperties, Value>;
export const mapResponsiveValue = createMapValueFn(responsiveProperties);
+15 -102
View File
@@ -13,19 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { breakpoints, space, themes } from './properties';
import { Breakpoint, SpaceProps, ColorProps } from '../../layout/types';
/** @public */
export type Breakpoint = keyof typeof breakpoints;
/** @public */
export type Space = keyof typeof space;
/** @public */
export type Theme = keyof typeof themes;
/** @public */
export type Display =
export type DisplayProps =
| 'flex'
| 'none'
| 'inline'
@@ -33,19 +25,19 @@ export type Display =
| Partial<Record<Breakpoint, 'flex' | 'none' | 'inline' | 'block'>>;
/** @public */
export type FlexDirection =
export type FlexDirectionProps =
| 'row'
| 'column'
| Partial<Record<Breakpoint, 'row' | 'column'>>;
/** @public */
export type FlexWrap =
export type FlexWrapProps =
| 'wrap'
| 'nowrap'
| Partial<Record<Breakpoint, 'wrap' | 'nowrap'>>;
/** @public */
export type JustifyContent =
export type JustifyContentProps =
| 'stretch'
| 'flex-start'
| 'center'
@@ -65,7 +57,7 @@ export type JustifyContent =
>;
/** @public */
export type AlignItems =
export type AlignItemsProps =
| 'stretch'
| 'flex-start'
| 'center'
@@ -75,7 +67,7 @@ export type AlignItems =
>;
/** @public */
export type BorderRadius =
export type BorderRadiusProps =
| 'none'
| 'small'
| 'medium'
@@ -83,94 +75,15 @@ export type BorderRadius =
| Partial<Record<Breakpoint, 'none' | 'small' | 'medium' | 'full'>>;
/** @public */
export type Gap = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingLeft = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingRight = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingTop = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingBottom = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type Padding = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingX = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingY = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginLeft = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginRight = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginTop = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginBottom = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type Margin = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginX = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginY = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type Background =
| 'background'
| 'elevation1'
| 'elevation2'
| 'transparent'
| Partial<
Record<Theme, 'background' | 'elevation1' | 'elevation2' | 'transparent'>
>;
/** @public */
export type Color =
| 'primary'
| 'secondary'
| 'error'
| Partial<Record<Theme, 'primary' | 'secondary' | 'error'>>;
/** @public */
export interface BoxProps {
export interface BoxProps extends SpaceProps, ColorProps {
as?: keyof JSX.IntrinsicElements;
background?: Background;
children?: React.ReactNode;
color?: Color;
display?: Display;
flexDirection?: FlexDirection;
flexWrap?: FlexWrap;
justifyContent?: JustifyContent;
alignItems?: AlignItems;
borderRadius?: BorderRadius;
gap?: Gap;
padding?: Padding;
paddingLeft?: PaddingLeft;
paddingRight?: PaddingRight;
paddingTop?: PaddingTop;
paddingBottom?: PaddingBottom;
paddingX?: PaddingX;
paddingY?: PaddingY;
margin?: Margin;
marginLeft?: MarginLeft;
marginRight?: MarginRight;
marginTop?: MarginTop;
marginBottom?: MarginBottom;
marginX?: MarginX;
marginY?: MarginY;
display?: DisplayProps;
flexDirection?: FlexDirectionProps;
flexWrap?: FlexWrapProps;
justifyContent?: JustifyContentProps;
alignItems?: AlignItemsProps;
borderRadius?: BorderRadiusProps;
className?: string;
style?: React.CSSProperties;
}
@@ -16,7 +16,6 @@
import React from 'react';
import { Box } from '../Box/Box';
import { alignToFlexAlign } from '../../utils/align';
import type { BoxProps } from '../Box/types';
export const validInlineComponents = [
@@ -47,7 +46,7 @@ export const Inline = ({
<Box
as={as}
display="flex"
alignItems={align !== 'left' ? alignToFlexAlign(align) : undefined}
// alignItems={align !== 'left' ? alignToFlexAlign(align) : undefined}
justifyContent="flex-start"
flexWrap="wrap"
gap={gap}
@@ -18,10 +18,33 @@ import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Stack } from './Stack';
import { Box } from '../Box/Box';
import { argTypesSpacing } from '../../../docs/utils/argTypes';
import { argTypesColor } from '../../../docs/utils/argTypes';
const meta = {
title: 'Components/Stack',
component: Stack,
argTypes: {
...argTypesSpacing,
...argTypesColor,
align: {
control: 'inline-radio',
options: ['left', 'center', 'right'],
},
children: {
control: false,
},
as: {
control: false,
},
className: {
control: 'text',
},
},
args: {
align: 'left',
gap: 'xs',
},
} satisfies Meta<typeof Stack>;
export default meta;
@@ -50,6 +73,49 @@ export const Default: Story = {
},
};
export const AlignLeft: Story = {
args: {
...Default.args,
align: 'left',
},
};
export const AlignCenter: Story = {
args: {
...Default.args,
align: 'center',
},
};
export const AlignRight: Story = {
args: {
...Default.args,
align: 'right',
},
};
export const ResponsiveAlign: Story = {
args: {
...Default.args,
align: {
xs: 'left',
md: 'center',
lg: 'right',
},
},
};
export const ResponsiveGap: Story = {
args: {
...Default.args,
gap: {
xs: 'xs',
md: 'md',
lg: 'xxl',
},
},
};
export const LargeGap: Story = {
args: {
...Default.args,
+31 -48
View File
@@ -14,61 +14,44 @@
* limitations under the License.
*/
import React from 'react';
import { Box } from '../Box/Box';
import { alignToFlexAlign } from '../../utils/align';
import type { BoxProps } from '../Box/types';
const validStackComponents = [
'div',
'span',
'p',
'article',
'section',
'main',
'nav',
'aside',
'ul',
'ol',
'li',
'details',
'summary',
'dd',
'dl',
'dt',
] as const;
import { createElement } from 'react';
import { StackProps } from './types';
import { stackSprinkles } from './sprinkles.css';
export interface StackProps extends Omit<BoxProps, 'alignItems'> {
children: React.ReactNode;
as?: (typeof validStackComponents)[number];
align?: 'left' | 'center' | 'right';
gap?: BoxProps['gap'];
}
const alignToFlexAlign = (align: StackProps['align']) => {
if (align === 'left') return 'stretch';
if (align === 'center') return 'center';
if (align === 'right') return 'flex-end';
return undefined;
};
export const Stack = ({
as = 'div',
children,
align: alignProp,
align = 'left',
gap = 'xs',
className,
style,
...restProps
}: StackProps) => {
/**
* Creating a seam between the provided prop and the default value
* to enable only setting the text alignment when the `align` prop
* is provided — not when it's defaulted.
*/
const align = alignProp || 'left';
// Transform the align prop
const flexAlign = alignToFlexAlign(align);
return (
<Box
as={as}
display="flex"
flexDirection="column"
alignItems={align !== 'left' ? alignToFlexAlign(align) : undefined}
gap={gap}
// textAlign={alignProp}
{...restProps}
>
{children}
</Box>
);
// Generate the list of class names
const sprinklesClassName = stackSprinkles({
...restProps,
gap,
alignItems: flexAlign,
});
// Combine the base class name, the sprinkles class name, and any additional class names
const classNames = ['stack', sprinklesClassName, className]
.filter(Boolean)
.join(' ');
return createElement(as, {
className: classNames,
style,
children,
});
};
@@ -13,74 +13,21 @@
* 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 '../Box/properties';
import { colorProperties } from '../Box/sprinkles.css';
const responsiveProperties = defineProperties({
import { defineProperties, createSprinkles } from '@vanilla-extract/sprinkles';
import { breakpoints } from '../../layout/properties';
import { colorProperties, spacingProperties } from '../../layout/sprinkles.css';
const stackProperties = defineProperties({
conditions: breakpoints,
defaultCondition: 'xs',
properties: {
flexDirection: ['row', 'column'],
justifyContent: [
'stretch',
'flex-start',
'center',
'flex-end',
'space-around',
'space-between',
],
alignItems: ['stretch', 'flex-start', 'center', 'flex-end'],
borderRadius: {
none: 0,
small: '4px',
medium: '8px',
full: '9999px',
},
boxShadow: {
small: 'var(--canon-box-shadow-small)',
medium: 'var(--canon-box-shadow-medium)',
large: 'var(--canon-box-shadow-large)',
},
border: {
none: 'none',
thin: '1px solid var(--canon-outline)',
error: '1px solid var(--canon-error)',
},
display: ['none', 'flex', 'block', 'inline'],
paddingTop: space,
paddingBottom: space,
paddingLeft: space,
paddingRight: space,
marginTop: space,
marginBottom: space,
marginLeft: space,
marginRight: space,
gap: space,
flexWrap: ['wrap', 'nowrap'],
},
shorthands: {
p: ['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'],
pt: ['paddingTop'],
pr: ['paddingRight'],
pb: ['paddingBottom'],
pl: ['paddingLeft'],
px: ['paddingLeft', 'paddingRight'],
py: ['paddingTop', 'paddingBottom'],
m: ['marginTop', 'marginBottom', 'marginLeft', 'marginRight'],
mt: ['marginTop'],
mr: ['marginRight'],
mb: ['marginBottom'],
ml: ['marginLeft'],
mx: ['marginLeft', 'marginRight'],
my: ['marginTop', 'marginBottom'],
direction: ['flexDirection'],
items: ['alignItems'],
justify: ['justifyContent'],
},
});
export const sprinkles = createSprinkles(responsiveProperties, colorProperties);
// It's a good idea to export the Sprinkles type too
export type Sprinkles = Parameters<typeof sprinkles>[0];
export const stackSprinkles = createSprinkles(
spacingProperties,
colorProperties,
stackProperties,
);
@@ -0,0 +1,4 @@
.stack {
display: flex;
flex-direction: column;
}
@@ -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 { AsProps, Breakpoint, ColorProps } from '../../layout/types';
import { SpaceProps } from '../../layout/types';
/** @public */
export type AlignProps =
| 'left'
| 'center'
| 'right'
| Partial<Record<Breakpoint, 'left' | 'center' | 'right'>>;
export interface StackProps extends SpaceProps, ColorProps {
children: React.ReactNode;
as?: AsProps;
align?: AlignProps;
className?: string;
style?: React.CSSProperties;
}
@@ -0,0 +1,63 @@
/*
* 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 } from '@vanilla-extract/sprinkles';
import { breakpoints, space } from './properties';
export const spacingProperties = defineProperties({
conditions: breakpoints,
defaultCondition: 'xs',
responsiveArray: ['xs', 'sm', 'md', 'lg', 'xl', '2xl'],
properties: {
paddingTop: space,
paddingBottom: space,
paddingLeft: space,
paddingRight: space,
marginTop: space,
marginBottom: space,
marginLeft: space,
marginRight: space,
gap: space,
},
shorthands: {
padding: ['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'],
paddingX: ['paddingLeft', 'paddingRight'],
paddingY: ['paddingTop', 'paddingBottom'],
margin: ['marginTop', 'marginBottom', 'marginLeft', 'marginRight'],
marginX: ['marginLeft', 'marginRight'],
marginY: ['marginTop', 'marginBottom'],
},
});
export const colorProperties = defineProperties({
conditions: {
light: { selector: '[data-theme="light"] &' },
dark: { selector: '[data-theme="dark"] &' },
},
defaultCondition: ['light', 'dark'],
properties: {
color: {
primary: 'var(--canon-text-primary)',
secondary: 'var(--canon-text-secondary)',
error: 'var(--canon-error)',
},
background: {
background: 'var(--canon-background)',
elevation1: 'var(--canon-surface-1)',
elevation2: 'var(--canon-surface-2)',
transparent: 'transparent',
},
},
});
+131
View File
@@ -0,0 +1,131 @@
/*
* 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 { breakpoints, space, themes } from './properties';
/** @public */
export type Breakpoint = keyof typeof breakpoints;
/** @public */
export type Space = keyof typeof space;
/** @public */
export type Theme = keyof typeof themes;
/** @public */
export type Gap = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingLeft = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingRight = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingTop = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingBottom = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type Padding = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingX = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type PaddingY = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginLeft = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginRight = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginTop = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginBottom = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type Margin = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginX = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export type MarginY = Space | Partial<Record<Breakpoint, Space>>;
/** @public */
export interface SpaceProps {
gap?: Gap;
padding?: Padding;
paddingLeft?: PaddingLeft;
paddingRight?: PaddingRight;
paddingTop?: PaddingTop;
paddingBottom?: PaddingBottom;
paddingX?: PaddingX;
paddingY?: PaddingY;
margin?: Margin;
marginLeft?: MarginLeft;
marginRight?: MarginRight;
marginTop?: MarginTop;
marginBottom?: MarginBottom;
marginX?: MarginX;
marginY?: MarginY;
}
/** @public */
export type Background =
| 'background'
| 'elevation1'
| 'elevation2'
| 'transparent'
| Partial<
Record<Theme, 'background' | 'elevation1' | 'elevation2' | 'transparent'>
>;
/** @public */
export type Color =
| 'primary'
| 'secondary'
| 'error'
| Partial<Record<Theme, 'primary' | 'secondary' | 'error'>>;
/** @public */
export type AsProps =
| 'div'
| 'span'
| 'p'
| 'article'
| 'section'
| 'main'
| 'nav'
| 'aside'
| 'ul'
| 'ol'
| 'li'
| 'details'
| 'summary'
| 'dd'
| 'dl'
| 'dt';
/** @public */
export interface ColorProps {
color?: Color;
background?: Background;
}
+1
View File
@@ -23,3 +23,4 @@
/* Components */
@import '../components/Button/styles.css';
@import '../components/Stack/styles.css';
-49
View File
@@ -1,49 +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.
*/
import {
type OptionalResponsiveValue,
mapResponsiveValue,
} from '../components/Box/sprinkles.css';
export type Align = 'left' | 'center' | 'right';
export type AlignY = 'top' | 'center' | 'bottom';
const alignToFlexAlignLookup = {
left: 'flex-start',
center: 'center',
right: 'flex-end',
} as const;
export const alignToFlexAlign = (
align: OptionalResponsiveValue<Align> | undefined,
) =>
align
? mapResponsiveValue(align, value => alignToFlexAlignLookup[value])
: undefined;
const alignYToFlexAlignLookup = {
top: 'flex-start',
center: 'center',
bottom: 'flex-end',
} as const;
export const alignYToFlexAlign = (
alignY: OptionalResponsiveValue<AlignY> | undefined,
) =>
alignY
? mapResponsiveValue(alignY, value => alignYToFlexAlignLookup[value])
: undefined;