Fixed Inline + Stack
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -42,7 +42,7 @@ export const Padding = () => {
|
||||
paddingY="xl"
|
||||
style={{ border: '1px solid #e7e7e7' }}
|
||||
>
|
||||
<Inline align="center" gap="xl">
|
||||
<Inline align="center" alignY="center" gap="xl">
|
||||
<Box
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
@@ -68,7 +68,7 @@ export const Padding = () => {
|
||||
<FakeBox>paddingY</FakeBox>
|
||||
</Box>
|
||||
</Inline>
|
||||
<Inline align="center" gap="xl">
|
||||
<Inline align="center" alignY="center" gap="xl">
|
||||
<Box
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
|
||||
@@ -18,38 +18,108 @@ import React from 'react';
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Inline } from './Inline';
|
||||
import { Box } from '../Box/Box';
|
||||
import { argTypesSpacing, argTypesColor } from '../../../docs/utils/argTypes';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Inline',
|
||||
component: Inline,
|
||||
argTypes: {
|
||||
...argTypesSpacing,
|
||||
...argTypesColor,
|
||||
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',
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof Inline>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
const FakeBox = () => (
|
||||
const FakeBox = ({
|
||||
width = 120,
|
||||
height = 80,
|
||||
}: {
|
||||
width?: number;
|
||||
height?: number;
|
||||
}) => (
|
||||
<Box
|
||||
paddingX="xl"
|
||||
paddingY="md"
|
||||
borderRadius="small"
|
||||
style={{ background: '#1f47ff', color: 'white' }}
|
||||
>
|
||||
Fake Box
|
||||
</Box>
|
||||
style={{ background: '#1f47ff', color: 'white', width, height }}
|
||||
/>
|
||||
);
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<>
|
||||
<FakeBox />
|
||||
<FakeBox />
|
||||
<FakeBox />
|
||||
{Array.from({ length: 32 }).map((_, index) => (
|
||||
<FakeBox
|
||||
key={index}
|
||||
width={Math.floor(Math.random() * (160 - 40 + 1)) + 40}
|
||||
height={Math.floor(Math.random() * (80 - 40 + 1)) + 40}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
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 VerticalAlignTop: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
alignY: 'top',
|
||||
},
|
||||
};
|
||||
|
||||
export const VerticalAlignCenter: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
alignY: 'center',
|
||||
},
|
||||
};
|
||||
|
||||
export const VerticalAlignBottom: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
alignY: 'bottom',
|
||||
},
|
||||
};
|
||||
|
||||
export const LargeGap: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
|
||||
@@ -14,45 +14,50 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Box } from '../Box/Box';
|
||||
import type { BoxProps } from '../Box/types';
|
||||
import { createElement } from 'react';
|
||||
import { inlineSprinkles } from './sprinkles.css';
|
||||
import type { InlineProps } from './types';
|
||||
|
||||
export const validInlineComponents = [
|
||||
'div',
|
||||
'span',
|
||||
'p',
|
||||
'nav',
|
||||
'ul',
|
||||
'ol',
|
||||
'li',
|
||||
] as const;
|
||||
const alignYToFlexAlign = (alignY: InlineProps['alignY']) => {
|
||||
if (alignY === 'top') return 'flex-start';
|
||||
if (alignY === 'center') return 'center';
|
||||
if (alignY === 'bottom') return 'flex-end';
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export interface InlineProps extends Omit<BoxProps, 'alignItems'> {
|
||||
as?: (typeof validInlineComponents)[number];
|
||||
children: React.ReactNode;
|
||||
align?: 'left' | 'center' | 'right';
|
||||
gap?: BoxProps['gap'];
|
||||
}
|
||||
const alignToFlexAlignY = (align: InlineProps['align']) => {
|
||||
if (align === 'left') return 'flex-start';
|
||||
if (align === 'center') return 'center';
|
||||
if (align === 'right') return 'flex-end';
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const Inline = ({
|
||||
align,
|
||||
as = 'div',
|
||||
children,
|
||||
align = 'left',
|
||||
alignY = 'top',
|
||||
gap = 'xs',
|
||||
className,
|
||||
style,
|
||||
...restProps
|
||||
}: InlineProps) => {
|
||||
return (
|
||||
<Box
|
||||
as={as}
|
||||
display="flex"
|
||||
// alignItems={align !== 'left' ? alignToFlexAlign(align) : undefined}
|
||||
justifyContent="flex-start"
|
||||
flexWrap="wrap"
|
||||
gap={gap}
|
||||
{...restProps}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
// Generate the list of class names
|
||||
const sprinklesClassName = inlineSprinkles({
|
||||
...restProps,
|
||||
gap,
|
||||
alignItems: alignYToFlexAlign(alignY),
|
||||
justifyContent: alignToFlexAlignY(align),
|
||||
});
|
||||
|
||||
// Combine the base class name, the sprinkles class name, and any additional class names
|
||||
const classNames = ['inline', sprinklesClassName, className]
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
|
||||
return createElement(as, {
|
||||
className: classNames,
|
||||
style,
|
||||
children,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 inlineProperties = defineProperties({
|
||||
conditions: breakpoints,
|
||||
defaultCondition: 'xs',
|
||||
properties: {
|
||||
alignItems: ['flex-start', 'center', 'flex-end'],
|
||||
justifyContent: ['flex-start', 'center', 'flex-end'],
|
||||
},
|
||||
});
|
||||
|
||||
export const inlineSprinkles = createSprinkles(
|
||||
spacingProperties,
|
||||
colorProperties,
|
||||
inlineProperties,
|
||||
);
|
||||
@@ -0,0 +1,4 @@
|
||||
.inline {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@@ -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 { AsProps, Breakpoint, ColorProps } from '../../layout/types';
|
||||
import { SpaceProps } from '../../layout/types';
|
||||
|
||||
export interface InlineProps extends SpaceProps, ColorProps {
|
||||
children: React.ReactNode;
|
||||
as?: AsProps;
|
||||
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;
|
||||
}
|
||||
@@ -18,8 +18,7 @@ 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';
|
||||
import { argTypesSpacing, argTypesColor } from '../../../docs/utils/argTypes';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Stack',
|
||||
|
||||
@@ -16,17 +16,14 @@
|
||||
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;
|
||||
align?:
|
||||
| 'left'
|
||||
| 'center'
|
||||
| 'right'
|
||||
| Partial<Record<Breakpoint, 'left' | 'center' | 'right'>>;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
@@ -24,3 +24,4 @@
|
||||
/* Components */
|
||||
@import '../components/Button/styles.css';
|
||||
@import '../components/Stack/styles.css';
|
||||
@import '../components/Inline/styles.css';
|
||||
|
||||
Reference in New Issue
Block a user