Merge pull request #28634 from backstage/canon-flex

Canon - Merge Stack + Inline into Flex
This commit is contained in:
Charles de Dreuille
2025-01-28 10:52:47 +00:00
committed by GitHub
47 changed files with 498 additions and 1570 deletions
+48 -64
View File
@@ -283,9 +283,57 @@ export const Field: {
}) => React_2.JSX.Element;
};
// @public (undocumented)
export const Flex: ForwardRefExoticComponent<
FlexProps & RefAttributes<HTMLDivElement>
>;
// @public (undocumented)
export type FlexDirection = 'row' | 'column';
// @public (undocumented)
export type FlexOwnProps = GetPropDefTypes<typeof flexPropDefs>;
// @public (undocumented)
export const flexPropDefs: {
align: {
type: 'enum';
className: string;
values: readonly ['start', 'center', 'end', 'baseline', 'stretch'];
responsive: true;
};
direction: {
type: 'enum';
className: string;
values: readonly ['row', 'column', 'row-reverse', 'column-reverse'];
responsive: true;
};
justify: {
type: 'enum';
className: string;
values: readonly ['start', 'center', 'end', 'between'];
responsive: true;
};
};
// @public (undocumented)
export interface FlexProps extends SpaceProps {
// (undocumented)
align?: FlexOwnProps['align'];
// (undocumented)
children: React.ReactNode;
// (undocumented)
className?: string;
// (undocumented)
direction?: FlexOwnProps['direction'];
// (undocumented)
gap?: GapProps['gap'];
// (undocumented)
justify?: FlexOwnProps['justify'];
// (undocumented)
style?: React.CSSProperties;
}
// @public (undocumented)
export type FlexWrap = 'wrap' | 'nowrap' | 'wrap-reverse';
@@ -589,37 +637,6 @@ export type IconProps = {
// @public (undocumented)
export const icons: IconMap;
// @public (undocumented)
export const Inline: ForwardRefExoticComponent<
InlineProps & RefAttributes<HTMLElement>
>;
// @public (undocumented)
export interface InlineProps extends SpaceProps {
// (undocumented)
align?:
| 'left'
| 'center'
| 'right'
| Partial<Record<Breakpoint, 'left' | 'center' | 'right'>>;
// (undocumented)
alignY?:
| 'top'
| 'center'
| 'bottom'
| Partial<Record<Breakpoint, 'top' | 'center' | 'bottom'>>;
// (undocumented)
as?: AsProps;
// (undocumented)
children: React.ReactNode;
// (undocumented)
className?: string;
// (undocumented)
gap?: UtilityProps['gap'];
// (undocumented)
style?: React.CSSProperties;
}
// @public (undocumented)
export const Input: React_2.ForwardRefExoticComponent<
InputProps & React_2.RefAttributes<HTMLInputElement>
@@ -853,39 +870,6 @@ export interface SpaceProps {
py?: Responsive<Space>;
}
// @public (undocumented)
export const Stack: ForwardRefExoticComponent<
StackProps & RefAttributes<HTMLDivElement>
>;
// @public (undocumented)
export type StackOwnProps = GetPropDefTypes<typeof stackPropDefs>;
// @public (undocumented)
export const stackPropDefs: {
align: {
type: 'enum';
className: string;
values: readonly ['start', 'center', 'end', 'baseline', 'stretch'];
responsive: true;
default: 'stretch';
};
};
// @public (undocumented)
export interface StackProps extends SpaceProps {
// (undocumented)
align?: StackOwnProps['align'];
// (undocumented)
children: React.ReactNode;
// (undocumented)
className?: string;
// (undocumented)
gap?: GapProps['gap'];
// (undocumented)
style?: React.CSSProperties;
}
// @public (undocumented)
export type StringPropDef = {
type: 'string';
@@ -17,8 +17,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Box } from './Box';
import { Stack } from '../Stack';
import { Inline } from '../Inline';
import { Flex } from '../Flex';
const meta = {
title: 'Components/Box',
@@ -81,8 +80,8 @@ const CardDisplay = ({ children }: { children?: React.ReactNode }) => {
export const Display: Story = {
render: args => (
<Stack align="center">
<Inline>
<Flex direction="column" align="center">
<Flex>
<Box display="block" {...args}>
<CardDisplay>Block</CardDisplay>
</Box>
@@ -92,11 +91,11 @@ export const Display: Story = {
<Box display="none" {...args}>
<CardDisplay>None</CardDisplay>
</Box>
</Inline>
</Flex>
<Box display={{ initial: 'block', md: 'inline' }} {...args}>
<CardDisplay>Responsive</CardDisplay>
</Box>
</Stack>
</Flex>
),
};
@@ -116,8 +115,8 @@ export const Padding: Story = {
},
},
render: args => (
<Stack align="center" gap="md">
<Inline alignY="center" gap="md">
<Flex direction="column" align="center" gap="4">
<Flex gap="4" align="center">
<Box p="3" style={styleInsideBox}>
<Box {...args}>Padding</Box>
</Box>
@@ -127,8 +126,8 @@ export const Padding: Story = {
<Box py="3" style={styleInsideBox}>
<Box {...args}>Padding Y</Box>
</Box>
</Inline>
<Inline alignY="center" gap="md">
</Flex>
<Flex gap="4" align="center">
<Box pt="3" style={styleInsideBox}>
<Box {...args}>Padding Top</Box>
</Box>
@@ -141,8 +140,8 @@ export const Padding: Story = {
<Box pl="3" style={styleInsideBox}>
<Box {...args}>Padding Left</Box>
</Box>
</Inline>
</Stack>
</Flex>
</Flex>
),
};
@@ -156,8 +155,8 @@ export const Margin: Story = {
},
},
render: args => (
<Stack align="center" gap="md">
<Inline alignY="center" gap="md">
<Flex direction="column" align="center" gap="4">
<Flex align="center" gap="4">
<Box style={styleInsideBox}>
<Box m="3" {...args}>
Margin
@@ -173,8 +172,8 @@ export const Margin: Story = {
Margin Y
</Box>
</Box>
</Inline>
<Inline alignY="center" gap="md">
</Flex>
<Flex align="center" gap="4">
<Box style={styleInsideBox}>
<Box mt="3" {...args}>
Margin Top
@@ -195,7 +194,7 @@ export const Margin: Story = {
Margin Left
</Box>
</Box>
</Inline>
</Stack>
</Flex>
</Flex>
),
};
@@ -17,8 +17,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
import { Inline } from '../Inline';
import { Stack } from '../Stack';
import { Flex } from '../Flex';
import { Text } from '../Text';
import { ButtonProps } from './types';
@@ -51,7 +50,7 @@ export const Variants: Story = {
},
},
render: () => (
<Inline alignY="center">
<Flex align="center">
<Button iconStart="cloud" variant="primary">
Button
</Button>
@@ -61,7 +60,7 @@ export const Variants: Story = {
<Button iconStart="cloud" variant="tertiary">
Button
</Button>
</Inline>
</Flex>
),
};
@@ -70,10 +69,10 @@ export const Sizes: Story = {
children: 'Button',
},
render: () => (
<Inline alignY="center">
<Flex align="center">
<Button size="medium">Medium</Button>
<Button size="small">Small</Button>
</Inline>
</Flex>
),
};
@@ -82,11 +81,11 @@ export const WithIcons: Story = {
children: 'Button',
},
render: args => (
<Inline alignY="center">
<Flex align="center">
<Button {...args} iconStart="cloud" />
<Button {...args} iconEnd="chevronRight" />
<Button {...args} iconStart="cloud" iconEnd="chevronRight" />
</Inline>
</Flex>
),
};
@@ -95,11 +94,11 @@ export const FullWidth: Story = {
children: 'Button',
},
render: args => (
<Stack style={{ width: '300px' }}>
<Flex style={{ width: '300px' }}>
<Button {...args} iconStart="cloud" />
<Button {...args} iconEnd="chevronRight" />
<Button {...args} iconStart="cloud" iconEnd="chevronRight" />
</Stack>
</Flex>
),
};
@@ -132,12 +131,12 @@ export const Playground: Story = {
children: 'Button',
},
render: () => (
<Stack>
<Flex direction="column">
{variants.map(variant => (
<Stack key={variant}>
<Flex direction="column" key={variant}>
<Text>{variant}</Text>
{['small', 'medium'].map(size => (
<Inline alignY="center" key={size}>
<Flex align="center" key={size}>
<Button
iconStart="cloud"
variant={variant as ButtonProps['variant']}
@@ -161,10 +160,10 @@ export const Playground: Story = {
>
Button
</Button>
</Inline>
</Flex>
))}
</Stack>
</Flex>
))}
</Stack>
</Flex>
),
};
@@ -17,8 +17,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Checkbox } from './Checkbox';
import { Inline } from '../Inline';
import { Stack } from '../Stack';
import { Flex } from '../Flex';
import { Text } from '../Text';
const meta = {
@@ -40,25 +39,25 @@ export const Default: Story = {
export const AllVariants: Story = {
render: () => (
<Inline alignY="center">
<Flex align="center">
<Checkbox />
<Checkbox checked />
<Checkbox label="Checkbox" />
<Checkbox label="Checkbox" checked />
</Inline>
</Flex>
),
};
export const Playground: Story = {
render: () => (
<Stack>
<Flex>
<Text>All variants</Text>
<Inline alignY="center">
<Flex align="center">
<Checkbox />
<Checkbox checked />
<Checkbox label="Checkbox" />
<Checkbox label="Checkbox" checked />
</Inline>
</Stack>
</Flex>
</Flex>
),
};
@@ -17,22 +17,42 @@
import type { PropDef, GetPropDefTypes } from '../../props/prop-def';
const alignValues = ['start', 'center', 'end', 'baseline', 'stretch'] as const;
const directionValues = [
'row',
'column',
'row-reverse',
'column-reverse',
] as const;
const justifyValues = ['start', 'center', 'end', 'between'] as const;
/** @public */
const stackPropDefs = {
const flexPropDefs = {
align: {
type: 'enum',
className: 'cu-align',
values: alignValues,
responsive: true,
default: 'stretch',
},
direction: {
type: 'enum',
className: 'cu-fd',
values: directionValues,
responsive: true,
},
justify: {
type: 'enum',
className: 'cu-jc',
values: justifyValues,
responsive: true,
},
} satisfies {
align: PropDef<(typeof alignValues)[number]>;
direction: PropDef<(typeof directionValues)[number]>;
justify: PropDef<(typeof justifyValues)[number]>;
};
/** @public */
type StackOwnProps = GetPropDefTypes<typeof stackPropDefs>;
type FlexOwnProps = GetPropDefTypes<typeof flexPropDefs>;
export { stackPropDefs };
export type { StackOwnProps };
export { flexPropDefs };
export type { FlexOwnProps };
@@ -16,11 +16,11 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Stack } from './Stack';
import { Flex } from './Flex';
const meta = {
title: 'Components/Stack',
component: Stack,
title: 'Components/Flex',
component: Flex,
argTypes: {
align: {
control: 'inline-radio',
@@ -38,7 +38,7 @@ const meta = {
gap: '4',
children: 'hello world',
},
} satisfies Meta<typeof Stack>;
} satisfies Meta<typeof Flex>;
export default meta;
type Story = StoryObj<typeof meta>;
@@ -65,62 +65,76 @@ export const Default: Story = {
},
};
export const ColumnDirection: Story = {
args: {
direction: 'column',
children: [<DecorativeBox />, <DecorativeBox />, <DecorativeBox />],
},
};
export const RowDirection: Story = {
args: {
direction: 'row',
children: [<DecorativeBox />, <DecorativeBox />, <DecorativeBox />],
},
};
export const AlignLeft: Story = {
render: () => (
<Stack align="start">
<Flex align="start">
<DecorativeBox />
<DecorativeBox />
<DecorativeBox />
</Stack>
</Flex>
),
};
export const AlignCenter: Story = {
render: () => (
<Stack align="center">
<Flex align="center">
<DecorativeBox />
<DecorativeBox />
<DecorativeBox />
</Stack>
</Flex>
),
};
export const AlignRight: Story = {
render: () => (
<Stack align="end">
<Flex align="end">
<DecorativeBox />
<DecorativeBox />
<DecorativeBox />
</Stack>
</Flex>
),
};
export const ResponsiveAlign: Story = {
render: () => (
<Stack align={{ xs: 'start', md: 'center', lg: 'end' }}>
<Flex align={{ xs: 'start', md: 'center', lg: 'end' }}>
<DecorativeBox />
<DecorativeBox />
<DecorativeBox />
</Stack>
</Flex>
),
};
export const ResponsiveGap: Story = {
render: () => (
<Stack gap={{ xs: '4', md: '8', lg: '12' }}>
<Flex gap={{ xs: '4', md: '8', lg: '12' }}>
<DecorativeBox />
<DecorativeBox />
<DecorativeBox />
</Stack>
</Flex>
),
};
export const LargeGap: Story = {
render: () => (
<Stack gap="8">
<Flex gap="8">
<DecorativeBox />
<DecorativeBox />
<DecorativeBox />
</Stack>
</Flex>
),
};
@@ -15,24 +15,24 @@
*/
import { createElement, forwardRef } from 'react';
import { StackProps } from './types';
import { FlexProps } from './types';
import clsx from 'clsx';
import { stackPropDefs } from './Stack.props';
import { flexPropDefs } from './Flex.props';
import { extractProps } from '../../utils/extractProps';
import { gapPropDefs } from '../../props/gap-props';
/** @public */
export const Stack = forwardRef<HTMLDivElement, StackProps>((props, ref) => {
export const Flex = forwardRef<HTMLDivElement, FlexProps>((props, ref) => {
const propDefs = {
...gapPropDefs,
...stackPropDefs,
...flexPropDefs,
};
const { className, style } = extractProps(props, propDefs);
return createElement('div', {
ref,
className: clsx('canon-Stack', className),
className: clsx('canon-Flex', className),
style,
children: props.children,
});
@@ -13,5 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { Inline } from './Inline';
export type { InlineProps } from './types';
export { Flex } from './Flex';
export { flexPropDefs } from './Flex.props';
export type { FlexProps } from './types';
export type { FlexOwnProps } from './Flex.props';
@@ -14,7 +14,6 @@
* limitations under the License.
*/
.canon-Inline {
.canon-Flex {
display: flex;
flex-wrap: wrap;
}
@@ -15,14 +15,16 @@
*/
import type { SpaceProps } from '../../types';
import { StackOwnProps } from './Stack.props';
import { FlexOwnProps } from './Flex.props';
import type { GapProps } from '../../props/gap-props';
/** @public */
export interface StackProps extends SpaceProps {
export interface FlexProps extends SpaceProps {
children: React.ReactNode;
gap?: GapProps['gap'];
align?: StackOwnProps['align'];
align?: FlexOwnProps['align'];
justify?: FlexOwnProps['justify'];
direction?: FlexOwnProps['direction'];
className?: string;
style?: React.CSSProperties;
}
@@ -19,7 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { Grid } from './Grid';
import type { GridItemProps } from './types';
import { Box } from '../Box/Box';
import { Stack } from '../Stack';
import { Flex } from '../Flex';
const meta = {
title: 'Components/Grid',
@@ -82,7 +82,7 @@ export const ColumnSizes: Story = {
columns: '12',
},
render: args => (
<Stack gap="4">
<Flex gap="4">
{Array.from({ length: 11 }, (_, i) => (
<Grid {...args} key={i}>
<Grid.Item colSpan={String(i + 1) as GridItemProps['colSpan']}>
@@ -93,7 +93,7 @@ export const ColumnSizes: Story = {
</Grid.Item>
</Grid>
))}
</Stack>
</Flex>
),
};
@@ -102,7 +102,7 @@ export const RowAndColumns: Story = {
columns: '12',
},
render: args => (
<Stack gap="md">
<Flex gap="4">
<Grid {...args} columns="3">
<Grid.Item colSpan="1" rowSpan="2">
<Box
@@ -123,6 +123,6 @@ export const RowAndColumns: Story = {
<FakeBox />
</Grid.Item>
</Grid>
</Stack>
</Flex>
),
};
@@ -17,8 +17,9 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Heading } from './Heading';
import { Stack } from '../Stack';
import { Flex } from '../Flex';
import { Text } from '../Text';
const meta = {
title: 'Components/Heading',
component: Heading,
@@ -41,13 +42,13 @@ export const Title1: Story = {
export const AllVariants: Story = {
render: () => (
<Stack>
<Flex>
<Heading variant="display">Display</Heading>
<Heading variant="title1">Title 1</Heading>
<Heading variant="title2">Title 2</Heading>
<Heading variant="title3">Title 3</Heading>
<Heading variant="title4">Title 4</Heading>
</Stack>
</Flex>
),
};
@@ -69,7 +70,7 @@ export const CustomTag: Story = {
export const Playground: Story = {
render: () => (
<Stack>
<Flex>
<Text>All variants</Text>
<Heading variant="display">Display</Heading>
<Heading variant="title1">Title 1</Heading>
@@ -77,6 +78,6 @@ export const Playground: Story = {
<Heading variant="title3">Title 3</Heading>
<Heading variant="title4">Title 4</Heading>
<Heading variant="title5">Title 5</Heading>
</Stack>
</Flex>
),
};
@@ -1,136 +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 React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Inline } from './Inline';
import { Box } from '../Box/Box';
const meta = {
title: 'Components/Inline',
component: Inline,
argTypes: {
align: {
control: 'inline-radio',
options: ['left', 'center', 'right'],
},
alignY: {
control: 'inline-radio',
options: ['top', 'center', 'bottom'],
},
children: {
control: false,
},
as: {
control: false,
},
className: {
control: 'text',
},
},
args: {
children: 'hello world',
},
} satisfies Meta<typeof Inline>;
export default meta;
type Story = StoryObj<typeof meta>;
const fakeBlockList = [
{ width: 45, height: 60 },
{ width: 150, height: 75 },
{ width: 80, height: 50 },
{ width: 120, height: 70 },
{ width: 95, height: 65 },
{ width: 80, height: 32 },
{ width: 130, height: 60 },
{ width: 100, height: 80 },
{ width: 140, height: 45 },
{ width: 85, height: 70 },
{ width: 125, height: 50 },
];
const FakeBox = ({
width = 120,
height = 80,
}: {
width?: number;
height?: number;
}) => (
<Box
style={{
background: '#eaf2fd',
borderRadius: '4px',
boxShadow: '0 0 0 1px #2563eb',
width,
height,
backgroundImage:
'url("data:image/svg+xml,%3Csvg%20width%3D%226%22%20height%3D%226%22%20viewBox%3D%220%200%206%206%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Cg%20fill%3D%22%232563eb%22%20fill-opacity%3D%220.3%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M5%200h1L0%206V5zM6%205v1H5z%22/%3E%3C/g%3E%3C/svg%3E")',
}}
/>
);
export const Default: Story = {
render: () => (
<Inline>
{fakeBlockList.map((block, index) => (
<FakeBox key={index} width={block.width} height={block.height} />
))}
</Inline>
),
};
export const AlignLeft: Story = {
args: {
align: 'left',
},
};
export const AlignCenter: Story = {
args: {
align: 'center',
},
};
export const AlignRight: Story = {
args: {
align: 'right',
},
};
export const VerticalAlignTop: Story = {
args: {
alignY: 'top',
},
};
export const VerticalAlignCenter: Story = {
args: {
alignY: 'center',
},
};
export const VerticalAlignBottom: Story = {
args: {
alignY: 'bottom',
},
};
export const LargeGap: Story = {
args: {
gap: 'xl',
},
};
@@ -1,85 +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 { createElement, forwardRef } from 'react';
import type { InlineProps } from './types';
import { getClassNames } from '../../utils/getClassNames';
import { JustifyContent, Breakpoint, AlignItems } from '../../types';
import clsx from 'clsx';
// Function to map align values
const mapAlignValue = (value?: InlineProps['align']) => {
if (typeof value === 'string') {
let returnedValue: JustifyContent = 'stretch';
if (value === 'left') returnedValue = 'start';
if (value === 'center') returnedValue = 'center';
if (value === 'right') returnedValue = 'end';
return returnedValue;
} else if (typeof value === 'object') {
const returnedValue: Partial<Record<Breakpoint, JustifyContent>> = {};
for (const [key, val] of Object.entries(value)) {
returnedValue[key as Breakpoint] = mapAlignValue(val) as JustifyContent;
}
return returnedValue;
}
return 'stretch';
};
const mapAlignYValue = (value?: InlineProps['alignY']) => {
if (typeof value === 'string') {
let returnedValue: AlignItems = 'stretch';
if (value === 'top') returnedValue = 'start';
if (value === 'center') returnedValue = 'center';
if (value === 'bottom') returnedValue = 'end';
return returnedValue;
} else if (typeof value === 'object') {
const returnedValue: Partial<Record<Breakpoint, AlignItems>> = {};
for (const [key, val] of Object.entries(value)) {
returnedValue[key as Breakpoint] = mapAlignYValue(val) as AlignItems;
}
return returnedValue;
}
return 'stretch';
};
/** @public */
export const Inline = forwardRef<HTMLElement, InlineProps>((props, ref) => {
const {
as = 'div',
children,
align = 'left',
alignY = 'top',
gap = 'xs',
className,
style,
...restProps
} = props;
// Generate utility class names
const utilityClassNames = getClassNames({
gap,
alignItems: mapAlignYValue(alignY),
justifyContent: mapAlignValue(align),
...restProps,
});
return createElement(as, {
ref,
className: clsx('canon-Inline', utilityClassNames, className),
style,
children,
});
});
@@ -1,41 +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 {
SpaceProps,
UtilityProps,
AsProps,
Breakpoint,
} from '../../types';
/** @public */
export interface InlineProps extends SpaceProps {
children: React.ReactNode;
as?: AsProps;
gap?: UtilityProps['gap'];
align?:
| 'left'
| 'center'
| 'right'
| Partial<Record<Breakpoint, 'left' | 'center' | 'right'>>;
alignY?:
| 'top'
| 'center'
| 'bottom'
| Partial<Record<Breakpoint, 'top' | 'center' | 'bottom'>>;
className?: string;
style?: React.CSSProperties;
}
@@ -17,7 +17,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Input } from './Input';
import { Inline } from '../Inline';
import { Flex } from '../Flex';
const meta = {
title: 'Components/Input',
@@ -33,9 +33,9 @@ export const Primary: Story = {
export const Sizes: Story = {
render: () => (
<Inline>
<Flex>
<Input size="sm" />
<Input size="md" />
</Inline>
</Flex>
),
};
@@ -1,19 +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 { Stack } from './Stack';
export { stackPropDefs } from './Stack.props';
export type { StackProps } from './types';
export type { StackOwnProps } from './Stack.props';
@@ -1,20 +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.
*/
.canon-Stack {
display: flex;
flex-direction: column;
}
@@ -17,7 +17,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Text } from './Text';
import { Stack } from '../Stack';
import { Flex } from '../Flex';
const meta = {
title: 'Components/Text',
@@ -40,7 +40,7 @@ export const Default: Story = {
export const AllVariants: Story = {
render: () => (
<Stack gap="md">
<Flex gap="4">
<Text variant="subtitle" style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son. Who is
@@ -61,13 +61,13 @@ export const AllVariants: Story = {
have none, but that man&apos;s father is my father&apos;s son. Who is
in the painting?
</Text>
</Stack>
</Flex>
),
};
export const AllWeights: Story = {
render: () => (
<Stack gap="md">
<Flex gap="4">
<Text weight="regular" style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, Brothers and sisters I
have none, but that man&apos;s father is my father&apos;s son. Who is
@@ -78,7 +78,7 @@ export const AllWeights: Story = {
have none, but that man&apos;s father is my father&apos;s son. Who is
in the painting?
</Text>
</Stack>
</Flex>
),
};
@@ -93,7 +93,7 @@ export const Responsive: Story = {
export const Playground: Story = {
render: () => (
<Stack>
<Flex>
<Text>Subtitle</Text>
<Text variant="subtitle" style={{ maxWidth: '600px' }}>
A man looks at a painting in a museum and says, Brothers and sisters I
@@ -118,6 +118,6 @@ export const Playground: Story = {
have none, but that man&apos;s father is my father&apos;s son. Who is
in the painting?
</Text>
</Stack>
</Flex>
),
};
+1 -2
View File
@@ -17,8 +17,7 @@
/* Components */
@import '../components/Box/styles.css';
@import '../components/Button/styles.css';
@import '../components/Stack/styles.css';
@import '../components/Inline/styles.css';
@import '../components/Flex/styles.css';
@import '../components/Grid/styles.css';
@import '../components/Container/styles.css';
@import '../components/Icon/styles.css';
-18
View File
@@ -14,24 +14,6 @@
* limitations under the License.
*/
/* Default utilities */
@import './utilities/xs.css';
/* Min 640px */
@import './utilities/sm.css';
/* Min 768px */
@import './utilities/md.css';
/* Min 1024px */
@import './utilities/lg.css';
/* Min 1280px */
@import './utilities/xl.css';
/* Min 1536px */
@import './utilities/2xl.css';
/* Padding */
@import './utilities/p.css';
@import './utilities/pl.css';
-164
View File
@@ -1,164 +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.
*/
@layer utilities {
@media (min-width: 1536px) {
.cu-2xl-block {
display: block;
}
.cu-2xl-border-base {
border-color: var(--canon-border);
border-width: 1px;
border-style: solid;
}
.cu-2xl-border-error {
border-color: var(--canon-border-danger);
border-width: 1px;
border-style: solid;
}
.cu-2xl-border-none {
border-color: transparent;
border-width: 0;
}
.cu-2xl-border-selected {
border-color: var(--canon-border-focus);
border-width: 1px;
border-style: solid;
}
.cu-2xl-border-warning {
border-color: var(--canon-border-warning);
border-width: 1px;
border-style: solid;
}
.cu-2xl-flex {
display: flex;
}
.cu-2xl-flex-col {
flex-direction: column;
}
.cu-2xl-flex-nowrap {
flex-wrap: nowrap;
}
.cu-2xl-flex-row {
flex-direction: row;
}
.cu-2xl-flex-wrap {
flex-wrap: wrap;
}
.cu-2xl-flex-wrap-reverse {
flex-wrap: wrap-reverse;
}
.cu-2xl-hidden {
display: none;
}
.cu-2xl-inline {
display: inline;
}
.cu-2xl-inline-block {
display: inline-block;
}
.cu-2xl-items-center {
align-items: center;
}
.cu-2xl-items-end {
align-items: flex-end;
}
.cu-2xl-items-start {
align-items: flex-start;
}
.cu-2xl-items-stretch {
align-items: stretch;
}
.cu-2xl-justify-around {
justify-content: space-around;
}
.cu-2xl-justify-between {
justify-content: space-between;
}
.cu-2xl-justify-center {
justify-content: center;
}
.cu-2xl-justify-end {
justify-content: flex-end;
}
.cu-2xl-justify-start {
justify-content: flex-start;
}
.cu-2xl-justify-stretch {
justify-content: stretch;
}
.cu-2xl-rounded-2xl {
border-radius: var(--canon-radius-full);
}
.cu-2xl-rounded-2xs {
border-radius: var(--canon-radius-1);
}
.cu-2xl-rounded-lg {
border-radius: var(--canon-radius-5);
}
.cu-2xl-rounded-md {
border-radius: var(--canon-radius-4);
}
.cu-2xl-rounded-none {
border-radius: 0;
}
.cu-2xl-rounded-sm {
border-radius: var(--canon-radius-3);
}
.cu-2xl-rounded-xl {
border-radius: var(--canon-radius-6);
}
.cu-2xl-rounded-xs {
border-radius: var(--canon-radius-2);
}
.cu-2xl-wrap-reverse {
flex-wrap: wrap-reverse;
}
}
}
+216
View File
@@ -10,6 +10,42 @@
align-items: end;
}
.cu-align-stretch {
align-items: stretch;
}
.cu-jc-start {
justify-content: start;
}
.cu-jc-center {
justify-content: center;
}
.cu-jc-end {
justify-content: end;
}
.cu-jc-between {
justify-content: space-between;
}
.cu-fd-row {
flex-direction: row;
}
.cu-fd-column {
flex-direction: column;
}
.cu-fd-row-reverse {
flex-direction: row-reverse;
}
.cu-fd-column-reverse {
flex-direction: column-reverse;
}
/* Breakpoint xs */
@media (min-width: 640px) {
.xs\:cu-align-start {
@@ -23,6 +59,42 @@
.xs\:cu-align-end {
align-items: end;
}
.xs\:cu-align-stretch {
align-items: stretch;
}
.xs\:cu-jc-start {
justify-content: start;
}
.xs\:cu-jc-center {
justify-content: center;
}
.xs\:cu-jc-end {
justify-content: end;
}
.xs\:cu-jc-between {
justify-content: space-between;
}
.xs\:cu-fd-row {
flex-direction: row;
}
.xs\:cu-fd-column {
flex-direction: column;
}
.xs\:cu-fd-row-reverse {
flex-direction: row-reverse;
}
.xs\:cu-fd-column-reverse {
flex-direction: column-reverse;
}
}
/* Breakpoint sm */
@@ -38,6 +110,42 @@
.sm\:cu-align-end {
align-items: end;
}
.sm\:cu-align-stretch {
align-items: stretch;
}
.sm\:cu-jc-start {
justify-content: start;
}
.sm\:cu-jc-center {
justify-content: center;
}
.sm\:cu-jc-end {
justify-content: end;
}
.sm\:cu-jc-between {
justify-content: space-between;
}
.sm\:cu-fd-row {
flex-direction: row;
}
.sm\:cu-fd-column {
flex-direction: column;
}
.sm\:cu-fd-row-reverse {
flex-direction: row-reverse;
}
.sm\:cu-fd-column-reverse {
flex-direction: column-reverse;
}
}
/* Breakpoint md */
@@ -53,6 +161,42 @@
.md\:cu-align-end {
align-items: end;
}
.md\:cu-align-stretch {
align-items: stretch;
}
.md\:cu-jc-start {
justify-content: start;
}
.md\:cu-jc-center {
justify-content: center;
}
.md\:cu-jc-end {
justify-content: end;
}
.md\:cu-jc-between {
justify-content: space-between;
}
.md\:cu-fd-row {
flex-direction: row;
}
.md\:cu-fd-column {
flex-direction: column;
}
.md\:cu-fd-row-reverse {
flex-direction: row-reverse;
}
.md\:cu-fd-column-reverse {
flex-direction: column-reverse;
}
}
/* Breakpoint lg */
@@ -68,6 +212,42 @@
.lg\:cu-align-end {
align-items: end;
}
.lg\:cu-align-stretch {
align-items: stretch;
}
.lg\:cu-jc-start {
justify-content: start;
}
.lg\:cu-jc-center {
justify-content: center;
}
.lg\:cu-jc-end {
justify-content: end;
}
.lg\:cu-jc-between {
justify-content: space-between;
}
.lg\:cu-fd-row {
flex-direction: row;
}
.lg\:cu-fd-column {
flex-direction: column;
}
.lg\:cu-fd-row-reverse {
flex-direction: row-reverse;
}
.lg\:cu-fd-column-reverse {
flex-direction: column-reverse;
}
}
/* Breakpoint xl */
@@ -83,4 +263,40 @@
.xl\:cu-align-end {
align-items: end;
}
.xl\:cu-align-stretch {
align-items: stretch;
}
.xl\:cu-jc-start {
justify-content: start;
}
.xl\:cu-jc-center {
justify-content: center;
}
.xl\:cu-jc-end {
justify-content: end;
}
.xl\:cu-jc-between {
justify-content: space-between;
}
.xl\:cu-fd-row {
flex-direction: row;
}
.xl\:cu-fd-column {
flex-direction: column;
}
.xl\:cu-fd-row-reverse {
flex-direction: row-reverse;
}
.xl\:cu-fd-column-reverse {
flex-direction: column-reverse;
}
}
-164
View File
@@ -1,164 +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.
*/
@layer utilities {
@media (min-width: 1024px) {
.cu-lg-block {
display: block;
}
.cu-lg-border-base {
border-color: var(--canon-border);
border-width: 1px;
border-style: solid;
}
.cu-lg-border-error {
border-color: var(--canon-border-danger);
border-width: 1px;
border-style: solid;
}
.cu-lg-border-none {
border-color: transparent;
border-width: 0;
}
.cu-lg-border-selected {
border-color: var(--canon-border-focus);
border-width: 1px;
border-style: solid;
}
.cu-lg-border-warning {
border-color: var(--canon-border-warning);
border-width: 1px;
border-style: solid;
}
.cu-lg-flex {
display: flex;
}
.cu-lg-flex-col {
flex-direction: column;
}
.cu-lg-flex-nowrap {
flex-wrap: nowrap;
}
.cu-lg-flex-row {
flex-direction: row;
}
.cu-lg-flex-wrap {
flex-wrap: wrap;
}
.cu-lg-flex-wrap-reverse {
flex-wrap: wrap-reverse;
}
.cu-lg-hidden {
display: none;
}
.cu-lg-inline {
display: inline;
}
.cu-lg-inline-block {
display: inline-block;
}
.cu-lg-items-center {
align-items: center;
}
.cu-lg-items-end {
align-items: flex-end;
}
.cu-lg-items-start {
align-items: flex-start;
}
.cu-lg-items-stretch {
align-items: stretch;
}
.cu-lg-justify-around {
justify-content: space-around;
}
.cu-lg-justify-between {
justify-content: space-between;
}
.cu-lg-justify-center {
justify-content: center;
}
.cu-lg-justify-end {
justify-content: flex-end;
}
.cu-lg-justify-start {
justify-content: flex-start;
}
.cu-lg-justify-stretch {
justify-content: stretch;
}
.cu-lg-rounded-2xl {
border-radius: var(--canon-radius-full);
}
.cu-lg-rounded-2xs {
border-radius: var(--canon-radius-1);
}
.cu-lg-rounded-lg {
border-radius: var(--canon-radius-5);
}
.cu-lg-rounded-md {
border-radius: var(--canon-radius-4);
}
.cu-lg-rounded-none {
border-radius: 0;
}
.cu-lg-rounded-sm {
border-radius: var(--canon-radius-3);
}
.cu-lg-rounded-xl {
border-radius: var(--canon-radius-6);
}
.cu-lg-rounded-xs {
border-radius: var(--canon-radius-2);
}
.cu-lg-wrap-reverse {
flex-wrap: wrap-reverse;
}
}
}
-164
View File
@@ -1,164 +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.
*/
@layer utilities {
@media (min-width: 768px) {
.cu-md-block {
display: block;
}
.cu-md-border-base {
border-color: var(--canon-border);
border-width: 1px;
border-style: solid;
}
.cu-md-border-error {
border-color: var(--canon-border-danger);
border-width: 1px;
border-style: solid;
}
.cu-md-border-none {
border-color: transparent;
border-width: 0;
}
.cu-md-border-selected {
border-color: var(--canon-border-focus);
border-width: 1px;
border-style: solid;
}
.cu-md-border-warning {
border-color: var(--canon-border-warning);
border-width: 1px;
border-style: solid;
}
.cu-md-flex {
display: flex;
}
.cu-md-flex-col {
flex-direction: column;
}
.cu-md-flex-nowrap {
flex-wrap: nowrap;
}
.cu-md-flex-row {
flex-direction: row;
}
.cu-md-flex-wrap {
flex-wrap: wrap;
}
.cu-md-flex-wrap-reverse {
flex-wrap: wrap-reverse;
}
.cu-md-hidden {
display: none;
}
.cu-md-inline {
display: inline;
}
.cu-md-inline-block {
display: inline-block;
}
.cu-md-items-center {
align-items: center;
}
.cu-md-items-end {
align-items: flex-end;
}
.cu-md-items-start {
align-items: flex-start;
}
.cu-md-items-stretch {
align-items: stretch;
}
.cu-md-justify-around {
justify-content: space-around;
}
.cu-md-justify-between {
justify-content: space-between;
}
.cu-md-justify-center {
justify-content: center;
}
.cu-md-justify-end {
justify-content: flex-end;
}
.cu-md-justify-start {
justify-content: flex-start;
}
.cu-md-justify-stretch {
justify-content: stretch;
}
.cu-md-rounded-2xl {
border-radius: var(--canon-radius-full);
}
.cu-md-rounded-2xs {
border-radius: var(--canon-radius-1);
}
.cu-md-rounded-lg {
border-radius: var(--canon-radius-5);
}
.cu-md-rounded-md {
border-radius: var(--canon-radius-4);
}
.cu-md-rounded-none {
border-radius: 0;
}
.cu-md-rounded-sm {
border-radius: var(--canon-radius-3);
}
.cu-md-rounded-xl {
border-radius: var(--canon-radius-6);
}
.cu-md-rounded-xs {
border-radius: var(--canon-radius-2);
}
.cu-md-wrap-reverse {
flex-wrap: wrap-reverse;
}
}
}
-164
View File
@@ -1,164 +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.
*/
@layer utilities {
@media (min-width: 1280px) {
.cu-xl-block {
display: block;
}
.cu-xl-border-base {
border-color: var(--canon-border);
border-width: 1px;
border-style: solid;
}
.cu-xl-border-error {
border-color: var(--canon-border-danger);
border-width: 1px;
border-style: solid;
}
.cu-xl-border-none {
border-color: transparent;
border-width: 0;
}
.cu-xl-border-selected {
border-color: var(--canon-border-focus);
border-width: 1px;
border-style: solid;
}
.cu-xl-border-warning {
border-color: var(--canon-border-warning);
border-width: 1px;
border-style: solid;
}
.cu-xl-flex {
display: flex;
}
.cu-xl-flex-col {
flex-direction: column;
}
.cu-xl-flex-nowrap {
flex-wrap: nowrap;
}
.cu-xl-flex-row {
flex-direction: row;
}
.cu-xl-flex-wrap {
flex-wrap: wrap;
}
.cu-xl-flex-wrap-reverse {
flex-wrap: wrap-reverse;
}
.cu-xl-hidden {
display: none;
}
.cu-xl-inline {
display: inline;
}
.cu-xl-inline-block {
display: inline-block;
}
.cu-xl-items-center {
align-items: center;
}
.cu-xl-items-end {
align-items: flex-end;
}
.cu-xl-items-start {
align-items: flex-start;
}
.cu-xl-items-stretch {
align-items: stretch;
}
.cu-xl-justify-around {
justify-content: space-around;
}
.cu-xl-justify-between {
justify-content: space-between;
}
.cu-xl-justify-center {
justify-content: center;
}
.cu-xl-justify-end {
justify-content: flex-end;
}
.cu-xl-justify-start {
justify-content: flex-start;
}
.cu-xl-justify-stretch {
justify-content: stretch;
}
.cu-xl-rounded-2xl {
border-radius: var(--canon-radius-full);
}
.cu-xl-rounded-2xs {
border-radius: var(--canon-radius-1);
}
.cu-xl-rounded-lg {
border-radius: var(--canon-radius-5);
}
.cu-xl-rounded-md {
border-radius: var(--canon-radius-4);
}
.cu-xl-rounded-none {
border-radius: 0;
}
.cu-xl-rounded-sm {
border-radius: var(--canon-radius-3);
}
.cu-xl-rounded-xl {
border-radius: var(--canon-radius-6);
}
.cu-xl-rounded-xs {
border-radius: var(--canon-radius-2);
}
.cu-xl-wrap-reverse {
flex-wrap: wrap-reverse;
}
}
}
+1 -2
View File
@@ -26,8 +26,7 @@ export * from './contexts/canon';
// Layout components
export * from './components/Box';
export * from './components/Grid';
export * from './components/Stack';
export * from './components/Inline';
export * from './components/Flex';
export * from './components/Container';
export * from './components/Text';
export * from './components/Heading';
-206
View File
@@ -1,206 +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 { Breakpoint, UtilityProps } from '../types';
const spaceMap = (type: string) => ({
none: `${type}-none`,
'2xs': `${type}-2xs`,
xs: `${type}-xs`,
sm: `${type}-sm`,
md: `${type}-md`,
lg: `${type}-lg`,
xl: `${type}-xl`,
'2xl': `${type}-2xl`,
});
const valueMap: Record<string, Record<string, string>> = {
alignItems: {
stretch: 'items-stretch',
start: 'items-start',
center: 'items-center',
end: 'items-end',
},
border: {
none: 'border-none',
base: 'border-base',
error: 'border-error',
warning: 'border-warning',
selected: 'border-selected',
},
borderRadius: {
none: 'rounded-none',
'2xs': 'rounded-2xs',
xs: 'rounded-xs',
sm: 'rounded-sm',
md: 'rounded-md',
lg: 'rounded-lg',
xl: 'rounded-xl',
'2xl': 'rounded-2xl',
},
colEnd: {
1: 'col-end-1',
2: 'col-end-2',
3: 'col-end-3',
4: 'col-end-4',
5: 'col-end-5',
6: 'col-end-6',
7: 'col-end-7',
8: 'col-end-8',
9: 'col-end-9',
10: 'col-end-10',
11: 'col-end-11',
12: 'col-end-12',
auto: 'col-end-auto',
},
colSpan: {
1: 'col-span-1',
2: 'col-span-2',
3: 'col-span-3',
4: 'col-span-4',
5: 'col-span-5',
6: 'col-span-6',
7: 'col-span-7',
8: 'col-span-8',
9: 'col-span-9',
10: 'col-span-10',
11: 'col-span-11',
12: 'col-span-12',
auto: 'col-span-auto',
},
colStart: {
1: 'col-start-1',
2: 'col-start-2',
3: 'col-start-3',
4: 'col-start-4',
5: 'col-start-5',
6: 'col-start-6',
7: 'col-start-7',
8: 'col-start-8',
9: 'col-start-9',
10: 'col-start-10',
11: 'col-start-11',
12: 'col-start-12',
auto: 'col-start-auto',
},
columns: {
1: 'grid-cols-1',
2: 'grid-cols-2',
3: 'grid-cols-3',
4: 'grid-cols-4',
5: 'grid-cols-5',
6: 'grid-cols-6',
7: 'grid-cols-7',
8: 'grid-cols-8',
9: 'grid-cols-9',
10: 'grid-cols-10',
11: 'grid-cols-11',
12: 'grid-cols-12',
auto: 'grid-cols-auto',
},
display: {
none: 'hidden',
flex: 'flex',
block: 'block',
inline: 'inline',
},
flexDirection: {
row: 'flex-row',
column: 'flex-col',
},
flexWrap: {
wrap: 'flex-wrap',
nowrap: 'flex-nowrap',
'wrap-reverse': 'flex-wrap-reverse',
},
gap: spaceMap('gap'),
justifyContent: {
stretch: 'justify-stretch',
start: 'justify-start',
center: 'justify-center',
end: 'justify-end',
around: 'justify-around',
between: 'justify-between',
},
margin: spaceMap('m'),
marginBottom: spaceMap('mb'),
marginLeft: spaceMap('ml'),
marginRight: spaceMap('mr'),
marginTop: spaceMap('mt'),
marginX: spaceMap('mx'),
marginY: spaceMap('my'),
padding: spaceMap('p'),
paddingBottom: spaceMap('pb'),
paddingLeft: spaceMap('pl'),
paddingRight: spaceMap('pr'),
paddingTop: spaceMap('pt'),
paddingX: spaceMap('px'),
paddingY: spaceMap('py'),
rowSpan: {
1: 'row-span-1',
2: 'row-span-2',
3: 'row-span-3',
4: 'row-span-4',
5: 'row-span-5',
6: 'row-span-6',
7: 'row-span-7',
8: 'row-span-8',
9: 'row-span-9',
10: 'row-span-10',
11: 'row-span-11',
12: 'row-span-12',
full: 'row-span-full',
},
};
const generateClassNames = (propName: string, propValue: any) => {
const classNames: string[] = [];
// If the property name is not in the valueMap, return an empty array
if (!valueMap.hasOwnProperty(propName)) {
return classNames;
}
if (typeof propValue === 'string' || typeof propValue === 'number') {
// If the property value is a string, map it to the valueMap
const value = valueMap[propName]?.[propValue] || propValue;
classNames.push(`cu-${value}`);
} else if (typeof propValue === 'object') {
// If the property value is an object, map each key-value pair
Object.entries(propValue as Record<Breakpoint, string>).forEach(
([breakpoint, value]) => {
const mappedValue = valueMap[propName]?.[value] || value;
if (breakpoint === 'xs') {
classNames.push(`cu-${mappedValue}`);
} else {
classNames.push(`cu-${breakpoint}-${mappedValue}`);
}
},
);
}
return classNames;
};
export const getClassNames = (props: UtilityProps) => {
const classNames: string[] = [];
Object.entries(props).forEach(([propName, propValue]) => {
classNames.push(...generateClassNames(propName, propValue));
});
return classNames.filter(Boolean).join(' ');
};