Merge pull request #27912 from backstage/canon-layout-components
Improve Canon layout components
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
import { Unstyled } from '@storybook/blocks';
|
||||
import { Columns, Text, ComponentStatus, Banner, Title } from './components';
|
||||
import {
|
||||
Columns,
|
||||
Text,
|
||||
ComponentStatus,
|
||||
Banner,
|
||||
Title,
|
||||
Roadmap,
|
||||
} from './components';
|
||||
import { list } from './components/Roadmap/list';
|
||||
|
||||
<Unstyled>
|
||||
|
||||
@@ -19,7 +27,7 @@ import { Columns, Text, ComponentStatus, Banner, Title } from './components';
|
||||
</Banner>
|
||||
|
||||
<Title style={{ marginTop: '48px' }} type="h2">
|
||||
Project Status
|
||||
Component Status
|
||||
</Title>
|
||||
<Text>
|
||||
We are still in the process of documenting the API and building the
|
||||
@@ -29,51 +37,45 @@ import { Columns, Text, ComponentStatus, Banner, Title } from './components';
|
||||
</Text>
|
||||
|
||||
<Columns style={{ marginTop: '32px' }}>
|
||||
<ComponentStatus name="Storybook setup" status="done" />
|
||||
<ComponentStatus
|
||||
name="Iconography"
|
||||
status="done"
|
||||
link="/?path=/docs/iconography--docs"
|
||||
/>
|
||||
<ComponentStatus name="Global tokens" status="inProgress" />
|
||||
<ComponentStatus
|
||||
name="Theming system"
|
||||
status="inProgress"
|
||||
link="/?path=/docs/theme--docs"
|
||||
/>
|
||||
<ComponentStatus
|
||||
name="Box component"
|
||||
status="inProgress"
|
||||
name="Box"
|
||||
status="alpha"
|
||||
link="/?path=/docs/components-box--docs"
|
||||
/>
|
||||
<ComponentStatus
|
||||
name="Inline component"
|
||||
status="inProgress"
|
||||
link="/?path=/story/components-inline--default"
|
||||
/>
|
||||
<ComponentStatus
|
||||
name="Stack component"
|
||||
status="inProgress"
|
||||
name="Stack"
|
||||
status="alpha"
|
||||
link="/?path=/docs/components-stack--default"
|
||||
/>
|
||||
<ComponentStatus
|
||||
name="Button component"
|
||||
name="Inline"
|
||||
status="alpha"
|
||||
link="/?path=/story/components-inline--default"
|
||||
/>
|
||||
<ComponentStatus
|
||||
name="Button"
|
||||
status="inProgress"
|
||||
link="/?path=/docs/components-button--docs"
|
||||
/>
|
||||
<ComponentStatus
|
||||
name="Icon component"
|
||||
status="inProgress"
|
||||
name="Icon"
|
||||
status="alpha"
|
||||
link="/?path=/docs/components-icon--docs"
|
||||
/>
|
||||
<ComponentStatus name="Input component" status="notStarted" />
|
||||
<ComponentStatus name="Select component" status="notStarted" />
|
||||
<ComponentStatus name="Checkbox component" status="notStarted" />
|
||||
<ComponentStatus name="Radio component" status="notStarted" />
|
||||
<ComponentStatus name="Switch component" status="notStarted" />
|
||||
<ComponentStatus name="Tooltip component" status="notStarted" />
|
||||
<ComponentStatus name="Header component" status="notStarted" />
|
||||
<ComponentStatus name="Tabs component" status="notStarted" />
|
||||
<ComponentStatus name="Input" status="notStarted" />
|
||||
<ComponentStatus name="Select" status="notStarted" />
|
||||
<ComponentStatus name="Checkbox" status="notStarted" />
|
||||
<ComponentStatus name="Radio" status="notStarted" />
|
||||
<ComponentStatus name="Switch" status="notStarted" />
|
||||
<ComponentStatus name="Tooltip" status="notStarted" />
|
||||
<ComponentStatus name="Header" status="notStarted" />
|
||||
<ComponentStatus name="Tabs" status="notStarted" />
|
||||
</Columns>
|
||||
|
||||
<Title style={{ marginTop: '48px' }} type="h2">
|
||||
Roadmap
|
||||
</Title>
|
||||
|
||||
<Roadmap list={list} />
|
||||
|
||||
</Unstyled>
|
||||
|
||||
@@ -18,7 +18,7 @@ import { style } from '@vanilla-extract/css';
|
||||
|
||||
export const styles = style({
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
gridTemplateColumns: 'repeat(3, 1fr)',
|
||||
rowGap: '20px',
|
||||
columnGap: '80px',
|
||||
});
|
||||
|
||||
@@ -57,7 +57,17 @@ export const pill = recipe({
|
||||
borderColor: '#FFD000',
|
||||
color: '#D79927',
|
||||
},
|
||||
done: {
|
||||
alpha: {
|
||||
backgroundColor: '#D7F9D7',
|
||||
borderColor: '#4ED14A',
|
||||
color: '#3A9837',
|
||||
},
|
||||
beta: {
|
||||
backgroundColor: '#D7F9D7',
|
||||
borderColor: '#4ED14A',
|
||||
color: '#3A9837',
|
||||
},
|
||||
stable: {
|
||||
backgroundColor: '#D7F9D7',
|
||||
borderColor: '#4ED14A',
|
||||
color: '#3A9837',
|
||||
|
||||
@@ -24,7 +24,7 @@ export const ComponentStatus = ({
|
||||
link,
|
||||
}: {
|
||||
name: string;
|
||||
status: 'notStarted' | 'inProgress' | 'done';
|
||||
status: 'notStarted' | 'inProgress' | 'alpha' | 'beta' | 'stable';
|
||||
style?: React.CSSProperties;
|
||||
link?: string;
|
||||
}) => {
|
||||
@@ -40,7 +40,9 @@ export const ComponentStatus = ({
|
||||
<span className={pill({ status })}>
|
||||
{status === 'notStarted' && 'Not Started'}
|
||||
{status === 'inProgress' && 'In Progress'}
|
||||
{status === 'done' && 'Done'}
|
||||
{status === 'alpha' && 'Alpha'}
|
||||
{status === 'beta' && 'Beta'}
|
||||
{status === 'stable' && 'Stable'}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 { RoadmapItem } from './list';
|
||||
|
||||
export const Roadmap = ({ list }: { list: RoadmapItem[] }) => {
|
||||
const orderList = ['inProgress', 'notStarted', 'completed'];
|
||||
return (
|
||||
<div className="roadmap">
|
||||
{list
|
||||
.sort(
|
||||
(a, b) => orderList.indexOf(a.status) - orderList.indexOf(b.status),
|
||||
)
|
||||
.map(Item)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Item = ({
|
||||
title,
|
||||
status = 'notStarted',
|
||||
}: {
|
||||
title: string;
|
||||
status: 'notStarted' | 'inProgress' | 'inReview' | 'completed';
|
||||
}) => {
|
||||
return (
|
||||
<div className={['roadmap-item', status].join(' ')}>
|
||||
<div className="left">
|
||||
<div className="dot" />
|
||||
<div className="title">{title}</div>
|
||||
</div>
|
||||
<span className="pill">
|
||||
{status === 'notStarted' && 'Not Started'}
|
||||
{status === 'inProgress' && 'In Progress'}
|
||||
{status === 'inReview' && 'Ready for Review'}
|
||||
{status === 'completed' && 'Completed'}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 type RoadmapItem = {
|
||||
title: string;
|
||||
status: 'notStarted' | 'inProgress' | 'inReview' | 'completed';
|
||||
};
|
||||
|
||||
export const list: RoadmapItem[] = [
|
||||
{
|
||||
title: 'Remove Vanilla Extract and use pure CSS instead',
|
||||
status: 'inProgress',
|
||||
},
|
||||
{
|
||||
title: 'Add collapsing across breakpoints for the Inline component',
|
||||
status: 'notStarted',
|
||||
},
|
||||
{
|
||||
title: 'Add reversing the order for the Inline component',
|
||||
status: 'notStarted',
|
||||
},
|
||||
{
|
||||
title: 'Set up Storybook',
|
||||
status: 'completed',
|
||||
},
|
||||
{
|
||||
title: 'Set up iconography',
|
||||
status: 'completed',
|
||||
},
|
||||
{
|
||||
title: 'Set up global tokens',
|
||||
status: 'inProgress',
|
||||
},
|
||||
{
|
||||
title: 'Set up theming system',
|
||||
status: 'inProgress',
|
||||
},
|
||||
{
|
||||
title: 'Create first pass at box component',
|
||||
status: 'completed',
|
||||
},
|
||||
{
|
||||
title: 'Create first pass at stack component',
|
||||
status: 'completed',
|
||||
},
|
||||
{
|
||||
title: 'Create first pass at inline component',
|
||||
status: 'completed',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,102 @@
|
||||
.roadmap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item {
|
||||
font-family: 'Geist', sans-serif;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
padding: 8px 0px;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item .left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 12px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item .dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.notStarted {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.inProgress {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.inReview {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.completed .title {
|
||||
color: #a2a2a2;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.notStarted .dot {
|
||||
background-color: #d1d1d1;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.inProgress .dot {
|
||||
background-color: #ffd000;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.inReview .dot {
|
||||
background-color: #4ed14a;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.completed .dot {
|
||||
background-color: #4ed14a;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item .title {
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item .pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 24px;
|
||||
padding: 0px 8px;
|
||||
border-radius: 40px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-left: 8px;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.notStarted .pill {
|
||||
background-color: #f2f2f2;
|
||||
border-color: #cdcdcd;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.inProgress .pill {
|
||||
background-color: #fff2b9;
|
||||
border-color: #ffd000;
|
||||
color: #d79927;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.inReview .pill {
|
||||
background-color: #d7f9d7;
|
||||
border-color: #4ed14a;
|
||||
color: #3a9837;
|
||||
}
|
||||
|
||||
.roadmap .roadmap-item.completed .pill {
|
||||
background-color: #d7f9d7;
|
||||
border-color: #4ed14a;
|
||||
color: #3a9837;
|
||||
}
|
||||
@@ -23,3 +23,4 @@ export * from './ComponentStatus';
|
||||
export * from './LayoutComponents';
|
||||
export * from './Banner';
|
||||
export * from './IconLibrary';
|
||||
export * from './Roadmap';
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
@import './IconLibrary/styles.css';
|
||||
@import './Roadmap/styles.css';
|
||||
|
||||
@@ -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;
|
||||
}, {});
|
||||
@@ -6,12 +6,12 @@
|
||||
/// <reference types="react" />
|
||||
|
||||
import { CSSProperties } from 'react';
|
||||
import { JSXElementConstructor } from 'react';
|
||||
import { DOMElement } from 'react';
|
||||
import { default as React_2 } from 'react';
|
||||
import { ReactElement } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
// @public (undocumented)
|
||||
export type AlignItems =
|
||||
export type AlignItemsProps =
|
||||
| 'stretch'
|
||||
| 'flex-start'
|
||||
| 'center'
|
||||
@@ -20,6 +20,25 @@ export type AlignItems =
|
||||
Record<Breakpoint, 'stretch' | 'flex-start' | 'center' | 'flex-end'>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type AsProps =
|
||||
| 'div'
|
||||
| 'span'
|
||||
| 'p'
|
||||
| 'article'
|
||||
| 'section'
|
||||
| 'main'
|
||||
| 'nav'
|
||||
| 'aside'
|
||||
| 'ul'
|
||||
| 'ol'
|
||||
| 'li'
|
||||
| 'details'
|
||||
| 'summary'
|
||||
| 'dd'
|
||||
| 'dl'
|
||||
| 'dt';
|
||||
|
||||
// @public (undocumented)
|
||||
export type Background =
|
||||
| 'background'
|
||||
@@ -31,7 +50,7 @@ export type Background =
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type BorderRadius =
|
||||
export type BorderRadiusProps =
|
||||
| 'none'
|
||||
| 'small'
|
||||
| 'medium'
|
||||
@@ -39,68 +58,35 @@ export type BorderRadius =
|
||||
| Partial<Record<Breakpoint, 'none' | 'small' | 'medium' | 'full'>>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const Box: (props: BoxProps) => ReactElement<
|
||||
export const Box: (props: BoxProps) => DOMElement<
|
||||
{
|
||||
className: string;
|
||||
style: CSSProperties | undefined;
|
||||
children: ReactNode;
|
||||
},
|
||||
string | JSXElementConstructor<any>
|
||||
Element
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface BoxProps {
|
||||
export interface BoxProps extends SpaceProps, ColorProps {
|
||||
// (undocumented)
|
||||
alignItems?: AlignItems;
|
||||
alignItems?: AlignItemsProps;
|
||||
// (undocumented)
|
||||
as?: keyof JSX.IntrinsicElements;
|
||||
// (undocumented)
|
||||
background?: Background;
|
||||
// (undocumented)
|
||||
borderRadius?: BorderRadius;
|
||||
borderRadius?: BorderRadiusProps;
|
||||
// (undocumented)
|
||||
children?: React.ReactNode;
|
||||
// (undocumented)
|
||||
className?: string;
|
||||
// (undocumented)
|
||||
color?: Color;
|
||||
display?: DisplayProps;
|
||||
// (undocumented)
|
||||
display?: Display;
|
||||
flexDirection?: FlexDirectionProps;
|
||||
// (undocumented)
|
||||
flexDirection?: FlexDirection;
|
||||
flexWrap?: FlexWrapProps;
|
||||
// (undocumented)
|
||||
flexWrap?: FlexWrap;
|
||||
// (undocumented)
|
||||
gap?: Gap;
|
||||
// (undocumented)
|
||||
justifyContent?: JustifyContent;
|
||||
// (undocumented)
|
||||
margin?: Margin;
|
||||
// (undocumented)
|
||||
marginBottom?: MarginBottom;
|
||||
// (undocumented)
|
||||
marginLeft?: MarginLeft;
|
||||
// (undocumented)
|
||||
marginRight?: MarginRight;
|
||||
// (undocumented)
|
||||
marginTop?: MarginTop;
|
||||
// (undocumented)
|
||||
marginX?: MarginX;
|
||||
// (undocumented)
|
||||
marginY?: MarginY;
|
||||
// (undocumented)
|
||||
padding?: Padding;
|
||||
// (undocumented)
|
||||
paddingBottom?: PaddingBottom;
|
||||
// (undocumented)
|
||||
paddingLeft?: PaddingLeft;
|
||||
// (undocumented)
|
||||
paddingRight?: PaddingRight;
|
||||
// (undocumented)
|
||||
paddingTop?: PaddingTop;
|
||||
// (undocumented)
|
||||
paddingX?: PaddingX;
|
||||
// (undocumented)
|
||||
paddingY?: PaddingY;
|
||||
justifyContent?: JustifyContentProps;
|
||||
// (undocumented)
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
@@ -163,7 +149,15 @@ export type Color =
|
||||
| Partial<Record<Theme, 'primary' | 'secondary' | 'error'>>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type Display =
|
||||
export interface ColorProps {
|
||||
// (undocumented)
|
||||
background?: Background;
|
||||
// (undocumented)
|
||||
color?: Color;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type DisplayProps =
|
||||
| 'flex'
|
||||
| 'none'
|
||||
| 'inline'
|
||||
@@ -171,13 +165,13 @@ export type Display =
|
||||
| Partial<Record<Breakpoint, 'flex' | 'none' | 'inline' | 'block'>>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type FlexDirection =
|
||||
export type FlexDirectionProps =
|
||||
| 'row'
|
||||
| 'column'
|
||||
| Partial<Record<Breakpoint, 'row' | 'column'>>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type FlexWrap =
|
||||
export type FlexWrapProps =
|
||||
| 'wrap'
|
||||
| 'nowrap'
|
||||
| Partial<Record<Breakpoint, 'wrap' | 'nowrap'>>;
|
||||
@@ -203,7 +197,7 @@ export type IconNames =
|
||||
| 'trash';
|
||||
|
||||
// @public (undocumented)
|
||||
export type JustifyContent =
|
||||
export type JustifyContentProps =
|
||||
| 'stretch'
|
||||
| 'flex-start'
|
||||
| 'center'
|
||||
@@ -279,6 +273,40 @@ export const space: {
|
||||
xxl: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export interface SpaceProps {
|
||||
// (undocumented)
|
||||
gap?: Gap;
|
||||
// (undocumented)
|
||||
margin?: Margin;
|
||||
// (undocumented)
|
||||
marginBottom?: MarginBottom;
|
||||
// (undocumented)
|
||||
marginLeft?: MarginLeft;
|
||||
// (undocumented)
|
||||
marginRight?: MarginRight;
|
||||
// (undocumented)
|
||||
marginTop?: MarginTop;
|
||||
// (undocumented)
|
||||
marginX?: MarginX;
|
||||
// (undocumented)
|
||||
marginY?: MarginY;
|
||||
// (undocumented)
|
||||
padding?: Padding;
|
||||
// (undocumented)
|
||||
paddingBottom?: PaddingBottom;
|
||||
// (undocumented)
|
||||
paddingLeft?: PaddingLeft;
|
||||
// (undocumented)
|
||||
paddingRight?: PaddingRight;
|
||||
// (undocumented)
|
||||
paddingTop?: PaddingTop;
|
||||
// (undocumented)
|
||||
paddingX?: PaddingX;
|
||||
// (undocumented)
|
||||
paddingY?: PaddingY;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type Theme = keyof typeof themes;
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Stack } from '../../Stack';
|
||||
import { Inline } from '../../Inline';
|
||||
import { Box } from '../Box';
|
||||
|
||||
@@ -32,74 +31,77 @@ const FakeBox = ({ children }: { children: string }) => (
|
||||
|
||||
export const Padding = () => {
|
||||
return (
|
||||
<Stack
|
||||
align="center"
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
marginBottom="md"
|
||||
gap="xl"
|
||||
paddingY="xl"
|
||||
style={{ border: '1px solid #e7e7e7' }}
|
||||
>
|
||||
<Inline align="center" gap="xl">
|
||||
<Stack
|
||||
align="center"
|
||||
<Inline align="center" alignY="center" gap="xl">
|
||||
<Box
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
padding="md"
|
||||
style={{ background: '#c4cafb', color: 'white' }}
|
||||
>
|
||||
<FakeBox>padding</FakeBox>
|
||||
</Stack>
|
||||
<Stack
|
||||
align="center"
|
||||
</Box>
|
||||
<Box
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
paddingX="md"
|
||||
style={{ background: '#c4cafb', color: 'white' }}
|
||||
>
|
||||
<FakeBox>paddingX</FakeBox>
|
||||
</Stack>
|
||||
<Stack
|
||||
align="center"
|
||||
</Box>
|
||||
<Box
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
paddingY="md"
|
||||
style={{ background: '#c4cafb', color: 'white' }}
|
||||
>
|
||||
<FakeBox>paddingY</FakeBox>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Inline>
|
||||
<Inline align="center" gap="xl">
|
||||
<Stack
|
||||
align="center"
|
||||
<Inline align="center" alignY="center" gap="xl">
|
||||
<Box
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
paddingTop="md"
|
||||
style={{ background: '#c4cafb', color: 'white' }}
|
||||
>
|
||||
<FakeBox>paddingTop</FakeBox>
|
||||
</Stack>
|
||||
<Stack
|
||||
align="center"
|
||||
</Box>
|
||||
<Box
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
paddingBottom="md"
|
||||
style={{ background: '#c4cafb', color: 'white' }}
|
||||
>
|
||||
<FakeBox>paddingBottom</FakeBox>
|
||||
</Stack>
|
||||
<Stack
|
||||
align="center"
|
||||
</Box>
|
||||
<Box
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
paddingLeft="md"
|
||||
style={{ background: '#c4cafb', color: 'white' }}
|
||||
>
|
||||
<FakeBox>paddingLeft</FakeBox>
|
||||
</Stack>
|
||||
<Stack
|
||||
align="center"
|
||||
</Box>
|
||||
<Box
|
||||
alignItems="center"
|
||||
borderRadius="small"
|
||||
paddingRight="md"
|
||||
style={{ background: '#c4cafb', color: 'white' }}
|
||||
>
|
||||
<FakeBox>paddingRight</FakeBox>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Inline>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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 { spacingProperties } from '../../../layout/sprinkles.css';
|
||||
import { space } from '../../../layout/properties';
|
||||
|
||||
export const SpacingTable = () => {
|
||||
return (
|
||||
@@ -30,7 +30,7 @@ export const SpacingTable = () => {
|
||||
</Table.HeaderRow>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{Object.keys(responsiveProperties.styles)
|
||||
{Object.keys(spacingProperties.styles)
|
||||
.filter(n =>
|
||||
[
|
||||
'padding',
|
||||
@@ -55,9 +55,7 @@ export const SpacingTable = () => {
|
||||
<Chip head>{n}</Chip>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{listResponsiveValues(
|
||||
'paddingTop' as keyof typeof responsiveProperties.styles,
|
||||
).map(value => (
|
||||
{Object.keys(space).map(value => (
|
||||
<Chip key={value}>{value}</Chip>
|
||||
))}
|
||||
</Table.Cell>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,46 +14,50 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Box } from '../Box/Box';
|
||||
import { alignToFlexAlign } from '../../utils/align';
|
||||
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,10 +18,32 @@ import React from 'react';
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Stack } from './Stack';
|
||||
import { Box } from '../Box/Box';
|
||||
import { argTypesSpacing, 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 +72,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,
|
||||
|
||||
@@ -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,29 @@
|
||||
/*
|
||||
* 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 StackProps extends SpaceProps, ColorProps {
|
||||
children: React.ReactNode;
|
||||
as?: AsProps;
|
||||
align?:
|
||||
| 'left'
|
||||
| 'center'
|
||||
| 'right'
|
||||
| Partial<Record<Breakpoint, 'left' | 'center' | 'right'>>;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
@@ -23,3 +23,4 @@
|
||||
export * from './components/Button';
|
||||
export * from './components/Box';
|
||||
export * from './components/Icon';
|
||||
export * from './layout/types';
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -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;
|
||||
}
|
||||
@@ -23,3 +23,5 @@
|
||||
|
||||
/* Components */
|
||||
@import '../components/Button/styles.css';
|
||||
@import '../components/Stack/styles.css';
|
||||
@import '../components/Inline/styles.css';
|
||||
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user