Merge pull request #31389 from backstage/bui-restructure-usestyles
BUI - Restructure useStyles hook
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Fix margin utility classes in Backstage UI.
|
||||
@@ -22,7 +22,7 @@ import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
preview={<BoxSnippet story="Preview" />}
|
||||
preview={<BoxSnippet story="Default" />}
|
||||
code={boxPreviewSnippet}
|
||||
align="center"
|
||||
/>
|
||||
|
||||
+41
-41
@@ -1352,7 +1352,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&[data-start-collapsed="true"] {
|
||||
&[data-startCollapsed="true"] {
|
||||
flex: 0 auto;
|
||||
padding: 0;
|
||||
transition: flex-basis .3s ease-in-out;
|
||||
@@ -5455,7 +5455,7 @@
|
||||
|
||||
@media (width >= 640px) {
|
||||
.xs\:bui-ml {
|
||||
margin-left: var(--pl-xs);
|
||||
margin-left: var(--ml-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-ml-0\.5 {
|
||||
@@ -5525,7 +5525,7 @@
|
||||
|
||||
@media (width >= 768px) {
|
||||
.sm\:bui-ml {
|
||||
margin-left: var(--pl-sm);
|
||||
margin-left: var(--ml-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-ml-0\.5 {
|
||||
@@ -5595,7 +5595,7 @@
|
||||
|
||||
@media (width >= 1024px) {
|
||||
.md\:bui-ml {
|
||||
margin-left: var(--pl-md);
|
||||
margin-left: var(--ml-md);
|
||||
}
|
||||
|
||||
.md\:bui-ml-0\.5 {
|
||||
@@ -5665,7 +5665,7 @@
|
||||
|
||||
@media (width >= 1280px) {
|
||||
.lg\:bui-ml {
|
||||
margin-left: var(--pl-lg);
|
||||
margin-left: var(--ml-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-ml-0\.5 {
|
||||
@@ -5735,7 +5735,7 @@
|
||||
|
||||
@media (width >= 1536px) {
|
||||
.xl\:bui-ml {
|
||||
margin-left: var(--pl-xl);
|
||||
margin-left: var(--ml-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-ml-0\.5 {
|
||||
@@ -5873,7 +5873,7 @@
|
||||
|
||||
@media (width >= 640px) {
|
||||
.xs\:bui-mr {
|
||||
margin-right: var(--pr-xs);
|
||||
margin-right: var(--mr-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-mr-0\.5 {
|
||||
@@ -5943,7 +5943,7 @@
|
||||
|
||||
@media (width >= 768px) {
|
||||
.sm\:bui-mr {
|
||||
margin-right: var(--pr-sm);
|
||||
margin-right: var(--mr-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-mr-0\.5 {
|
||||
@@ -6013,7 +6013,7 @@
|
||||
|
||||
@media (width >= 1024px) {
|
||||
.md\:bui-mr {
|
||||
margin-right: var(--pr-md);
|
||||
margin-right: var(--mr-md);
|
||||
}
|
||||
|
||||
.md\:bui-mr-0\.5 {
|
||||
@@ -6083,7 +6083,7 @@
|
||||
|
||||
@media (width >= 1280px) {
|
||||
.lg\:bui-mr {
|
||||
margin-right: var(--pr-lg);
|
||||
margin-right: var(--mr-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-mr-0\.5 {
|
||||
@@ -6153,7 +6153,7 @@
|
||||
|
||||
@media (width >= 1536px) {
|
||||
.xl\:bui-mr {
|
||||
margin-right: var(--pr-xl);
|
||||
margin-right: var(--mr-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-mr-0\.5 {
|
||||
@@ -6291,7 +6291,7 @@
|
||||
|
||||
@media (width >= 640px) {
|
||||
.xs\:bui-mt {
|
||||
margin-top: var(--pt-xs);
|
||||
margin-top: var(--mt-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-mt-0\.5 {
|
||||
@@ -6361,7 +6361,7 @@
|
||||
|
||||
@media (width >= 768px) {
|
||||
.sm\:bui-mt {
|
||||
margin-top: var(--pt-sm);
|
||||
margin-top: var(--mt-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-mt-0\.5 {
|
||||
@@ -6431,7 +6431,7 @@
|
||||
|
||||
@media (width >= 1024px) {
|
||||
.md\:bui-mt {
|
||||
margin-top: var(--pt-md);
|
||||
margin-top: var(--mt-md);
|
||||
}
|
||||
|
||||
.md\:bui-mt-0\.5 {
|
||||
@@ -6501,7 +6501,7 @@
|
||||
|
||||
@media (width >= 1280px) {
|
||||
.lg\:bui-mt {
|
||||
margin-top: var(--pt-lg);
|
||||
margin-top: var(--mt-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-mt-0\.5 {
|
||||
@@ -6571,7 +6571,7 @@
|
||||
|
||||
@media (width >= 1536px) {
|
||||
.xl\:bui-mt {
|
||||
margin-top: var(--pt-xl);
|
||||
margin-top: var(--mt-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-mt-0\.5 {
|
||||
@@ -6709,7 +6709,7 @@
|
||||
|
||||
@media (width >= 640px) {
|
||||
.xs\:bui-mb {
|
||||
margin-bottom: var(--pb-xs);
|
||||
margin-bottom: var(--mb-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-mb-0\.5 {
|
||||
@@ -6779,7 +6779,7 @@
|
||||
|
||||
@media (width >= 768px) {
|
||||
.sm\:bui-mb {
|
||||
margin-bottom: var(--pb-sm);
|
||||
margin-bottom: var(--mb-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-mb-0\.5 {
|
||||
@@ -6849,7 +6849,7 @@
|
||||
|
||||
@media (width >= 1024px) {
|
||||
.md\:bui-mb {
|
||||
margin-bottom: var(--pb-md);
|
||||
margin-bottom: var(--mb-md);
|
||||
}
|
||||
|
||||
.md\:bui-mb-0\.5 {
|
||||
@@ -6919,7 +6919,7 @@
|
||||
|
||||
@media (width >= 1280px) {
|
||||
.lg\:bui-mb {
|
||||
margin-bottom: var(--pb-lg);
|
||||
margin-bottom: var(--mb-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-mb-0\.5 {
|
||||
@@ -6989,7 +6989,7 @@
|
||||
|
||||
@media (width >= 1536px) {
|
||||
.xl\:bui-mb {
|
||||
margin-bottom: var(--pb-xl);
|
||||
margin-bottom: var(--mb-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-mb-0\.5 {
|
||||
@@ -7144,8 +7144,8 @@
|
||||
|
||||
@media (width >= 640px) {
|
||||
.xs\:bui-my {
|
||||
margin-top: var(--py-xs);
|
||||
margin-bottom: var(--py-xs);
|
||||
margin-top: var(--my-xs);
|
||||
margin-bottom: var(--my-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-my-0\.5 {
|
||||
@@ -7231,8 +7231,8 @@
|
||||
|
||||
@media (width >= 768px) {
|
||||
.sm\:bui-my {
|
||||
margin-top: var(--py-sm);
|
||||
margin-bottom: var(--py-sm);
|
||||
margin-top: var(--my-sm);
|
||||
margin-bottom: var(--my-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-my-0\.5 {
|
||||
@@ -7318,8 +7318,8 @@
|
||||
|
||||
@media (width >= 1024px) {
|
||||
.md\:bui-my {
|
||||
margin-top: var(--py-md);
|
||||
margin-bottom: var(--py-md);
|
||||
margin-top: var(--my-md);
|
||||
margin-bottom: var(--my-md);
|
||||
}
|
||||
|
||||
.md\:bui-my-0\.5 {
|
||||
@@ -7405,8 +7405,8 @@
|
||||
|
||||
@media (width >= 1280px) {
|
||||
.lg\:bui-my {
|
||||
margin-top: var(--py-lg);
|
||||
margin-bottom: var(--py-lg);
|
||||
margin-top: var(--my-lg);
|
||||
margin-bottom: var(--my-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-my-0\.5 {
|
||||
@@ -7492,8 +7492,8 @@
|
||||
|
||||
@media (width >= 1536px) {
|
||||
.xl\:bui-my {
|
||||
margin-top: var(--py-xl);
|
||||
margin-bottom: var(--py-xl);
|
||||
margin-top: var(--my-xl);
|
||||
margin-bottom: var(--my-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-my-0\.5 {
|
||||
@@ -7664,8 +7664,8 @@
|
||||
|
||||
@media (width >= 640px) {
|
||||
.xs\:bui-mx {
|
||||
margin-left: var(--px-xs);
|
||||
margin-right: var(--px-xs);
|
||||
margin-left: var(--mx-xs);
|
||||
margin-right: var(--mx-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-mx-0\.5 {
|
||||
@@ -7751,8 +7751,8 @@
|
||||
|
||||
@media (width >= 768px) {
|
||||
.sm\:bui-mx {
|
||||
margin-left: var(--px-sm);
|
||||
margin-right: var(--px-sm);
|
||||
margin-left: var(--mx-sm);
|
||||
margin-right: var(--mx-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-mx-0\.5 {
|
||||
@@ -7838,8 +7838,8 @@
|
||||
|
||||
@media (width >= 1024px) {
|
||||
.md\:bui-mx {
|
||||
margin-left: var(--px-md);
|
||||
margin-right: var(--px-md);
|
||||
margin-left: var(--mx-md);
|
||||
margin-right: var(--mx-md);
|
||||
}
|
||||
|
||||
.md\:bui-mx-0\.5 {
|
||||
@@ -7925,8 +7925,8 @@
|
||||
|
||||
@media (width >= 1280px) {
|
||||
.lg\:bui-mx {
|
||||
margin-left: var(--px-lg);
|
||||
margin-right: var(--px-lg);
|
||||
margin-left: var(--mx-lg);
|
||||
margin-right: var(--mx-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-mx-0\.5 {
|
||||
@@ -8012,8 +8012,8 @@
|
||||
|
||||
@media (width >= 1536px) {
|
||||
.xl\:bui-mx {
|
||||
margin-left: var(--px-xl);
|
||||
margin-right: var(--px-xl);
|
||||
margin-left: var(--mx-xl);
|
||||
margin-right: var(--mx-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-mx-0\.5 {
|
||||
|
||||
+112
-179
@@ -107,44 +107,34 @@ export const Box: ForwardRefExoticComponent<
|
||||
BoxProps & RefAttributes<HTMLDivElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type BoxOwnProps = GetPropDefTypes<typeof boxPropDefs>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const boxPropDefs: {
|
||||
as: {
|
||||
type: 'enum';
|
||||
values: readonly ['div', 'span'];
|
||||
default: 'div';
|
||||
};
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export interface BoxProps extends SpaceProps {
|
||||
// (undocumented)
|
||||
as?: BoxOwnProps['as'];
|
||||
as?: keyof JSX.IntrinsicElements;
|
||||
// (undocumented)
|
||||
children?: React.ReactNode;
|
||||
// (undocumented)
|
||||
className?: string;
|
||||
// (undocumented)
|
||||
display?: DisplayProps['display'];
|
||||
display?: Responsive<'none' | 'flex' | 'block' | 'inline'>;
|
||||
// (undocumented)
|
||||
height?: HeightProps['height'];
|
||||
height?: Responsive<string>;
|
||||
// (undocumented)
|
||||
maxHeight?: HeightProps['maxHeight'];
|
||||
maxHeight?: Responsive<string>;
|
||||
// (undocumented)
|
||||
maxWidth?: WidthProps['maxWidth'];
|
||||
maxWidth?: Responsive<string>;
|
||||
// (undocumented)
|
||||
minHeight?: HeightProps['minHeight'];
|
||||
minHeight?: Responsive<string>;
|
||||
// (undocumented)
|
||||
minWidth?: WidthProps['minWidth'];
|
||||
minWidth?: Responsive<string>;
|
||||
// (undocumented)
|
||||
position?: PositionProps['position'];
|
||||
position?: Responsive<
|
||||
'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'
|
||||
>;
|
||||
// (undocumented)
|
||||
style?: React.CSSProperties;
|
||||
// (undocumented)
|
||||
width?: WidthProps['width'];
|
||||
width?: Responsive<string>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
@@ -358,7 +348,20 @@ export const Column: (
|
||||
) => JSX_2.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export type Columns = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'auto';
|
||||
export type Columns =
|
||||
| '1'
|
||||
| '2'
|
||||
| '3'
|
||||
| '4'
|
||||
| '5'
|
||||
| '6'
|
||||
| '7'
|
||||
| '8'
|
||||
| '9'
|
||||
| '10'
|
||||
| '11'
|
||||
| '12'
|
||||
| 'auto';
|
||||
|
||||
// @public
|
||||
export type ComponentClassNames<T extends ComponentDefinitionName> =
|
||||
@@ -370,6 +373,8 @@ export interface ComponentDefinition {
|
||||
classNames: ClassNamesMap;
|
||||
// (undocumented)
|
||||
dataAttributes?: DataAttributesMap;
|
||||
// (undocumented)
|
||||
utilityProps?: string[];
|
||||
}
|
||||
|
||||
// @public
|
||||
@@ -391,6 +396,30 @@ export const componentDefinitions: {
|
||||
readonly classNames: {
|
||||
readonly root: 'bui-Box';
|
||||
};
|
||||
readonly utilityProps: [
|
||||
'm',
|
||||
'mb',
|
||||
'ml',
|
||||
'mr',
|
||||
'mt',
|
||||
'mx',
|
||||
'my',
|
||||
'p',
|
||||
'pb',
|
||||
'pl',
|
||||
'pr',
|
||||
'pt',
|
||||
'px',
|
||||
'py',
|
||||
'position',
|
||||
'display',
|
||||
'width',
|
||||
'minWidth',
|
||||
'maxWidth',
|
||||
'height',
|
||||
'minHeight',
|
||||
'maxHeight',
|
||||
];
|
||||
};
|
||||
readonly Button: {
|
||||
readonly classNames: {
|
||||
@@ -440,6 +469,7 @@ export const componentDefinitions: {
|
||||
readonly classNames: {
|
||||
readonly root: 'bui-Container';
|
||||
};
|
||||
readonly utilityProps: ['my', 'mt', 'mb', 'py', 'pt', 'pb', 'display'];
|
||||
};
|
||||
readonly Dialog: {
|
||||
readonly classNames: {
|
||||
@@ -463,12 +493,55 @@ export const componentDefinitions: {
|
||||
readonly classNames: {
|
||||
readonly root: 'bui-Flex';
|
||||
};
|
||||
readonly utilityProps: [
|
||||
'm',
|
||||
'mb',
|
||||
'ml',
|
||||
'mr',
|
||||
'mt',
|
||||
'mx',
|
||||
'my',
|
||||
'p',
|
||||
'pb',
|
||||
'pl',
|
||||
'pr',
|
||||
'pt',
|
||||
'px',
|
||||
'py',
|
||||
'gap',
|
||||
'align',
|
||||
'justify',
|
||||
'direction',
|
||||
];
|
||||
};
|
||||
readonly Grid: {
|
||||
readonly classNames: {
|
||||
readonly root: 'bui-Grid';
|
||||
readonly item: 'bui-GridItem';
|
||||
};
|
||||
readonly utilityProps: [
|
||||
'columns',
|
||||
'gap',
|
||||
'm',
|
||||
'mb',
|
||||
'ml',
|
||||
'mr',
|
||||
'mt',
|
||||
'mx',
|
||||
'my',
|
||||
'p',
|
||||
'pb',
|
||||
'pl',
|
||||
'pr',
|
||||
'pt',
|
||||
'px',
|
||||
'py',
|
||||
];
|
||||
};
|
||||
readonly GridItem: {
|
||||
readonly classNames: {
|
||||
readonly root: 'bui-GridItem';
|
||||
};
|
||||
readonly utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan'];
|
||||
};
|
||||
readonly Header: {
|
||||
readonly classNames: {
|
||||
@@ -546,6 +619,9 @@ export const componentDefinitions: {
|
||||
readonly root: 'bui-PasswordField';
|
||||
readonly inputVisibility: 'bui-InputVisibility';
|
||||
};
|
||||
readonly dataAttributes: {
|
||||
readonly size: readonly ['small', 'medium'];
|
||||
};
|
||||
};
|
||||
readonly Popover: {
|
||||
readonly classNames: {
|
||||
@@ -574,6 +650,7 @@ export const componentDefinitions: {
|
||||
};
|
||||
readonly dataAttributes: {
|
||||
readonly startCollapsed: readonly [true, false];
|
||||
readonly size: readonly ['small', 'medium'];
|
||||
};
|
||||
};
|
||||
readonly Select: {
|
||||
@@ -670,6 +747,7 @@ export const componentDefinitions: {
|
||||
readonly dataAttributes: {
|
||||
readonly invalid: readonly [true, false];
|
||||
readonly disabled: readonly [true, false];
|
||||
readonly size: readonly ['small', 'medium'];
|
||||
};
|
||||
};
|
||||
readonly Tooltip: {
|
||||
@@ -825,45 +903,20 @@ export const Flex: ForwardRefExoticComponent<
|
||||
// @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'];
|
||||
align?: Responsive<'start' | 'center' | 'end' | 'baseline' | 'stretch'>;
|
||||
// (undocumented)
|
||||
children: React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
// (undocumented)
|
||||
className?: string;
|
||||
// (undocumented)
|
||||
direction?: FlexOwnProps['direction'];
|
||||
direction?: Responsive<'row' | 'column' | 'row-reverse' | 'column-reverse'>;
|
||||
// (undocumented)
|
||||
gap?: GapProps['gap'];
|
||||
gap?: Responsive<Space>;
|
||||
// (undocumented)
|
||||
justify?: FlexOwnProps['justify'];
|
||||
justify?: Responsive<'start' | 'center' | 'end' | 'between'>;
|
||||
// (undocumented)
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
@@ -922,97 +975,6 @@ export const Grid: {
|
||||
>;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type GridItemOwnProps = GetPropDefTypes<typeof gridItemPropDefs>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const gridItemPropDefs: {
|
||||
colSpan: {
|
||||
type: 'enum | string';
|
||||
className: string;
|
||||
customProperties: '--col-span'[];
|
||||
values: readonly [
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'auto',
|
||||
];
|
||||
responsive: true;
|
||||
};
|
||||
colEnd: {
|
||||
type: 'enum | string';
|
||||
className: string;
|
||||
customProperties: '--col-end'[];
|
||||
values: readonly [
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'auto',
|
||||
];
|
||||
responsive: true;
|
||||
};
|
||||
colStart: {
|
||||
type: 'enum | string';
|
||||
className: string;
|
||||
customProperties: '--col-start'[];
|
||||
values: readonly [
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'auto',
|
||||
];
|
||||
responsive: true;
|
||||
};
|
||||
rowSpan: {
|
||||
type: 'enum | string';
|
||||
className: string;
|
||||
customProperties: '--row-span'[];
|
||||
values: readonly [
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'auto',
|
||||
];
|
||||
responsive: true;
|
||||
};
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GridItemProps {
|
||||
// (undocumented)
|
||||
@@ -1020,46 +982,17 @@ export interface GridItemProps {
|
||||
// (undocumented)
|
||||
className?: string;
|
||||
// (undocumented)
|
||||
colEnd?: GridItemOwnProps['colEnd'];
|
||||
colEnd?: Responsive<Columns>;
|
||||
// (undocumented)
|
||||
colSpan?: GridItemOwnProps['colSpan'];
|
||||
colSpan?: Responsive<Columns>;
|
||||
// (undocumented)
|
||||
colStart?: GridItemOwnProps['colStart'];
|
||||
colStart?: Responsive<Columns>;
|
||||
// (undocumented)
|
||||
rowSpan?: GridItemOwnProps['rowSpan'];
|
||||
rowSpan?: Responsive<Columns>;
|
||||
// (undocumented)
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type GridOwnProps = GetPropDefTypes<typeof gridPropDefs>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const gridPropDefs: {
|
||||
columns: {
|
||||
type: 'enum | string';
|
||||
className: string;
|
||||
customProperties: '--columns'[];
|
||||
values: readonly [
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'auto',
|
||||
];
|
||||
responsive: true;
|
||||
default: string;
|
||||
};
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GridProps extends SpaceProps {
|
||||
// (undocumented)
|
||||
@@ -1067,9 +1000,9 @@ export interface GridProps extends SpaceProps {
|
||||
// (undocumented)
|
||||
className?: string;
|
||||
// (undocumented)
|
||||
columns?: GridOwnProps['columns'];
|
||||
columns?: Responsive<Columns>;
|
||||
// (undocumented)
|
||||
gap?: GapProps['gap'];
|
||||
gap?: Responsive<Space>;
|
||||
// (undocumented)
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 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 { PropDef, GetPropDefTypes } from '../../props/prop-def';
|
||||
|
||||
const as = ['div', 'span'] as const;
|
||||
|
||||
/** @public */
|
||||
const boxPropDefs = {
|
||||
as: { type: 'enum', values: as, default: 'div' },
|
||||
} satisfies {
|
||||
as: PropDef<(typeof as)[number]>;
|
||||
};
|
||||
|
||||
// Use all of the imported prop defs to ensure that JSDoc works
|
||||
/** @public */
|
||||
type BoxOwnProps = GetPropDefTypes<typeof boxPropDefs>;
|
||||
|
||||
export { boxPropDefs };
|
||||
export type { BoxOwnProps };
|
||||
@@ -36,35 +36,277 @@ const meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
const Card = () => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '64px',
|
||||
height: '64px',
|
||||
background: '#eaf2fd',
|
||||
borderRadius: '4px',
|
||||
border: '1px solid #2563eb',
|
||||
color: '#2563eb',
|
||||
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")',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const diagonalStripePattern = (() => {
|
||||
const svg = `
|
||||
<svg width="6" height="6" viewBox="0 0 6 6" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#2563eb" fill-opacity="0.6" fill-rule="evenodd">
|
||||
<path d="M5 0h1L0 6V5zM6 5v1H5z"/>
|
||||
</g>
|
||||
</svg>
|
||||
`.trim();
|
||||
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
||||
})();
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
children: 'Hello World',
|
||||
mb: '4',
|
||||
width: '64px',
|
||||
height: '64px',
|
||||
style: {
|
||||
background: '#eaf2fd',
|
||||
borderRadius: '4px',
|
||||
border: '1px solid #2563eb',
|
||||
backgroundImage: `url("${diagonalStripePattern}")`,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontWeight: 'bold',
|
||||
color: '#2563eb',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Preview: Story = {
|
||||
args: {
|
||||
children: <Card />,
|
||||
display: 'inline',
|
||||
},
|
||||
export const Margin: Story = {
|
||||
args: { ...Default.args },
|
||||
render: args => (
|
||||
<Flex align="center">
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} ml="6" children="ML" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mr="6" children="MR" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mx="6" children="MX" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mt="6" children="MT" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mb="6" children="MB" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} my="6" children="MY" />
|
||||
</Box>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const ResponsiveMargin: Story = {
|
||||
args: { ...Default.args },
|
||||
render: args => (
|
||||
<Flex align="center">
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} ml={{ initial: '2', sm: '6' }} children="ML" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mr={{ initial: '2', sm: '6' }} children="MR" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mx={{ initial: '2', sm: '6' }} children="MX" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mt={{ initial: '2', sm: '6' }} children="MT" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mb={{ initial: '2', sm: '6' }} children="MB" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} my={{ initial: '2', sm: '6' }} children="MY" />
|
||||
</Box>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const CustomMargin: Story = {
|
||||
args: { ...Default.args },
|
||||
render: args => (
|
||||
<Flex align="center">
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} ml="42px" children="ML" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mr="42px" children="MR" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mx="42px" children="MX" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mt="42px" children="MT" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mb="42px" children="MB" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} my="42px" children="MY" />
|
||||
</Box>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const CustomResponsiveMargin: Story = {
|
||||
args: { ...Default.args },
|
||||
render: args => (
|
||||
<Flex align="center">
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} ml={{ initial: '9px', sm: '42px' }} children="ML" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mr={{ initial: '9px', sm: '42px' }} children="MR" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mx={{ initial: '9px', sm: '42px' }} children="MX" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mt={{ initial: '9px', sm: '42px' }} children="MT" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} mb={{ initial: '9px', sm: '42px' }} children="MB" />
|
||||
</Box>
|
||||
<Box style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} my={{ initial: '9px', sm: '42px' }} children="MY" />
|
||||
</Box>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const Padding: Story = {
|
||||
args: { ...Default.args },
|
||||
render: args => (
|
||||
<Flex align="center">
|
||||
<Box pl="6" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PL" />
|
||||
</Box>
|
||||
<Box pr="6" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PR" />
|
||||
</Box>
|
||||
<Box px="6" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PX" />
|
||||
</Box>
|
||||
<Box pt="6" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PT" />
|
||||
</Box>
|
||||
<Box pb="6" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PB" />
|
||||
</Box>
|
||||
<Box py="6" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PY" />
|
||||
</Box>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const ResponsivePadding: Story = {
|
||||
args: { ...Default.args },
|
||||
render: args => (
|
||||
<Flex align="center">
|
||||
<Box
|
||||
pl={{ initial: '2', sm: '6' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PL" />
|
||||
</Box>
|
||||
<Box
|
||||
pr={{ initial: '2', sm: '6' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PR" />
|
||||
</Box>
|
||||
<Box
|
||||
px={{ initial: '2', sm: '6' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PX" />
|
||||
</Box>
|
||||
<Box
|
||||
pt={{ initial: '2', sm: '6' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PT" />
|
||||
</Box>
|
||||
<Box
|
||||
pb={{ initial: '2', sm: '6' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PB" />
|
||||
</Box>
|
||||
<Box
|
||||
py={{ initial: '2', sm: '6' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PY" />
|
||||
</Box>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const CustomPadding: Story = {
|
||||
args: { ...Default.args },
|
||||
render: args => (
|
||||
<Flex align="center">
|
||||
<Box pl="42px" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PL" />
|
||||
</Box>
|
||||
<Box pr="42px" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PR" />
|
||||
</Box>
|
||||
<Box px="42px" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PX" />
|
||||
</Box>
|
||||
<Box pt="42px" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PT" />
|
||||
</Box>
|
||||
<Box pb="42px" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PB" />
|
||||
</Box>
|
||||
<Box py="42px" style={{ border: '1px solid red', borderRadius: '5px' }}>
|
||||
<Box {...args} children="PY" />
|
||||
</Box>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const CustomResponsivePadding: Story = {
|
||||
args: { ...Default.args },
|
||||
render: args => (
|
||||
<Flex align="center">
|
||||
<Box
|
||||
pl={{ initial: '9px', sm: '42px' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PL" />
|
||||
</Box>
|
||||
<Box
|
||||
pr={{ initial: '9px', sm: '42px' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PR" />
|
||||
</Box>
|
||||
<Box
|
||||
px={{ initial: '9px', sm: '42px' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PX" />
|
||||
</Box>
|
||||
<Box
|
||||
pt={{ initial: '9px', sm: '42px' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PT" />
|
||||
</Box>
|
||||
<Box
|
||||
pb={{ initial: '9px', sm: '42px' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PB" />
|
||||
</Box>
|
||||
<Box
|
||||
py={{ initial: '9px', sm: '42px' }}
|
||||
style={{ border: '1px solid red', borderRadius: '5px' }}
|
||||
>
|
||||
<Box {...args} children="PY" />
|
||||
</Box>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
const CardDisplay = ({ children }: { children?: ReactNode }) => {
|
||||
@@ -105,151 +347,3 @@ export const Display: Story = {
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
const styleInsideBox = {
|
||||
background: 'rgb(196, 202, 251)',
|
||||
color: 'white',
|
||||
borderRadius: '4px',
|
||||
};
|
||||
|
||||
export const Padding: Story = {
|
||||
args: {
|
||||
style: {
|
||||
background: '#1f47ff',
|
||||
color: 'white',
|
||||
borderRadius: '4px',
|
||||
padding: '12px 12px',
|
||||
},
|
||||
},
|
||||
render: args => (
|
||||
<Flex direction="column" align="center" gap="4">
|
||||
<Flex gap="4" align="center">
|
||||
<Box p="3" style={styleInsideBox}>
|
||||
<Box {...args}>Padding</Box>
|
||||
</Box>
|
||||
<Box px="3" style={styleInsideBox}>
|
||||
<Box {...args}>Padding X</Box>
|
||||
</Box>
|
||||
<Box py="3" style={styleInsideBox}>
|
||||
<Box {...args}>Padding Y</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex gap="4" align="center">
|
||||
<Box pt="3" style={styleInsideBox}>
|
||||
<Box {...args}>Padding Top</Box>
|
||||
</Box>
|
||||
<Box pr="3" style={styleInsideBox}>
|
||||
<Box {...args}>Padding Right</Box>
|
||||
</Box>
|
||||
<Box pb="3" style={styleInsideBox}>
|
||||
<Box {...args}>Padding Bottom</Box>
|
||||
</Box>
|
||||
<Box pl="3" style={styleInsideBox}>
|
||||
<Box {...args}>Padding Left</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex gap="4" align="center">
|
||||
<Box p="10px" style={styleInsideBox}>
|
||||
<Box {...args}>Custom Padding</Box>
|
||||
</Box>
|
||||
<Box px="10px" style={styleInsideBox}>
|
||||
<Box {...args}>Custom Padding X</Box>
|
||||
</Box>
|
||||
<Box py="10px" style={styleInsideBox}>
|
||||
<Box {...args}>Custom Padding Y</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex gap="4" align="center">
|
||||
<Box pt="10px" pb="10px" style={styleInsideBox}>
|
||||
<Box {...args}>Custom Padding Top Bottom</Box>
|
||||
</Box>
|
||||
<Box pl="10px" pr="10px" style={styleInsideBox}>
|
||||
<Box {...args}>Custom Padding Left Right</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const Margin: Story = {
|
||||
args: {
|
||||
style: {
|
||||
background: '#1f47ff',
|
||||
color: 'white',
|
||||
borderRadius: '4px',
|
||||
padding: '12px 12px',
|
||||
},
|
||||
},
|
||||
render: args => (
|
||||
<Flex direction="column" align="center" gap="4">
|
||||
<Flex align="center" gap="4">
|
||||
<Box style={styleInsideBox}>
|
||||
<Box m="3" {...args}>
|
||||
Margin
|
||||
</Box>
|
||||
</Box>
|
||||
<Box style={styleInsideBox}>
|
||||
<Box mx="3" {...args}>
|
||||
Margin X
|
||||
</Box>
|
||||
</Box>
|
||||
<Box style={styleInsideBox}>
|
||||
<Box my="3" {...args}>
|
||||
Margin Y
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex align="center" gap="4">
|
||||
<Box style={styleInsideBox}>
|
||||
<Box mt="3" {...args}>
|
||||
Margin Top
|
||||
</Box>
|
||||
</Box>
|
||||
<Box style={styleInsideBox}>
|
||||
<Box mr="3" {...args}>
|
||||
Margin Right
|
||||
</Box>
|
||||
</Box>
|
||||
<Box style={styleInsideBox}>
|
||||
<Box mb="3" {...args}>
|
||||
Margin Bottom
|
||||
</Box>
|
||||
</Box>
|
||||
<Box style={styleInsideBox}>
|
||||
<Box ml="3" {...args}>
|
||||
Margin Left
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex align="center" gap="4">
|
||||
<Box style={styleInsideBox}>
|
||||
<Box m="10px" {...args}>
|
||||
Custom Margin
|
||||
</Box>
|
||||
</Box>
|
||||
<Box style={styleInsideBox}>
|
||||
<Box mx="10px" {...args}>
|
||||
Custom Margin X
|
||||
</Box>
|
||||
</Box>
|
||||
<Box style={styleInsideBox}>
|
||||
<Box my="10px" {...args}>
|
||||
Custom Margin Y
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex align="center" gap="4">
|
||||
<Box style={styleInsideBox}>
|
||||
<Box mt="10px" mb="10px" {...args}>
|
||||
Custom Margin Top Bottom
|
||||
</Box>
|
||||
</Box>
|
||||
<Box style={styleInsideBox}>
|
||||
<Box ml="10px" mr="10px" {...args}>
|
||||
Custom Margin Left Right
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
@@ -17,38 +17,27 @@
|
||||
import { createElement, forwardRef } from 'react';
|
||||
import { BoxProps } from './types';
|
||||
import clsx from 'clsx';
|
||||
import { extractProps } from '../../utils/extractProps';
|
||||
import { spacingPropDefs } from '../../props/spacing.props';
|
||||
import { boxPropDefs } from './Box.props';
|
||||
import { widthPropDefs } from '../../props/width.props';
|
||||
import { heightPropDefs } from '../../props/height.props';
|
||||
import { positionPropDefs } from '../../props/position.props';
|
||||
import { displayPropDefs } from '../../props/display.props';
|
||||
import { useStyles } from '../../hooks/useStyles';
|
||||
|
||||
/** @public */
|
||||
export const Box = forwardRef<HTMLDivElement, BoxProps>((props, ref) => {
|
||||
const { children } = props;
|
||||
const { classNames, utilityClasses, style, cleanedProps } = useStyles(
|
||||
'Box',
|
||||
props,
|
||||
);
|
||||
|
||||
const propDefs = {
|
||||
...spacingPropDefs,
|
||||
...widthPropDefs,
|
||||
...heightPropDefs,
|
||||
...positionPropDefs,
|
||||
...displayPropDefs,
|
||||
...boxPropDefs,
|
||||
};
|
||||
const { as = 'div', children, className, ...rest } = cleanedProps;
|
||||
|
||||
const { classNames } = useStyles('Box');
|
||||
const { className, style, dataProps } = extractProps(props, propDefs);
|
||||
|
||||
return createElement(props.as || 'div', {
|
||||
ref,
|
||||
className: clsx(classNames.root, className),
|
||||
...dataProps,
|
||||
style,
|
||||
return createElement(
|
||||
as,
|
||||
{
|
||||
ref,
|
||||
className: clsx(classNames.root, utilityClasses, className),
|
||||
style,
|
||||
...rest,
|
||||
},
|
||||
children,
|
||||
});
|
||||
);
|
||||
});
|
||||
|
||||
Box.displayName = 'Box';
|
||||
|
||||
@@ -15,5 +15,3 @@
|
||||
*/
|
||||
export { Box } from './Box';
|
||||
export type * from './types';
|
||||
export type { BoxOwnProps } from './Box.props';
|
||||
export { boxPropDefs } from './Box.props';
|
||||
|
||||
@@ -14,24 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { HeightProps } from '../../props/height.props';
|
||||
import type { WidthProps } from '../../props/width.props';
|
||||
import type { PositionProps } from '../../props/position.props';
|
||||
import type { DisplayProps } from '../../props/display.props';
|
||||
import type { SpaceProps } from '../../types';
|
||||
import type { BoxOwnProps } from './Box.props';
|
||||
import type { SpaceProps, Responsive } from '../../types';
|
||||
|
||||
/** @public */
|
||||
export interface BoxProps extends SpaceProps {
|
||||
display?: DisplayProps['display'];
|
||||
as?: BoxOwnProps['as'];
|
||||
width?: WidthProps['width'];
|
||||
minWidth?: WidthProps['minWidth'];
|
||||
maxWidth?: WidthProps['maxWidth'];
|
||||
height?: HeightProps['height'];
|
||||
minHeight?: HeightProps['minHeight'];
|
||||
maxHeight?: HeightProps['maxHeight'];
|
||||
position?: PositionProps['position'];
|
||||
display?: Responsive<'none' | 'flex' | 'block' | 'inline'>;
|
||||
as?: keyof JSX.IntrinsicElements;
|
||||
width?: Responsive<string>;
|
||||
minWidth?: Responsive<string>;
|
||||
maxWidth?: Responsive<string>;
|
||||
height?: Responsive<string>;
|
||||
minHeight?: Responsive<string>;
|
||||
maxHeight?: Responsive<string>;
|
||||
position?: Responsive<
|
||||
'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'
|
||||
>;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
|
||||
@@ -23,21 +23,14 @@ import { useStyles } from '../../hooks/useStyles';
|
||||
/** @public */
|
||||
export const Button = forwardRef(
|
||||
(props: ButtonProps, ref: Ref<HTMLButtonElement>) => {
|
||||
const {
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
iconStart,
|
||||
iconEnd,
|
||||
children,
|
||||
className,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const { classNames, dataAttributes } = useStyles('Button', {
|
||||
size,
|
||||
variant,
|
||||
const { classNames, dataAttributes, cleanedProps } = useStyles('Button', {
|
||||
size: 'small',
|
||||
variant: 'primary',
|
||||
...props,
|
||||
});
|
||||
|
||||
const { children, className, iconStart, iconEnd, ...rest } = cleanedProps;
|
||||
|
||||
return (
|
||||
<RAButton
|
||||
className={clsx(classNames.root, className)}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-vite';
|
||||
import { ButtonIcon } from './ButtonIcon';
|
||||
import { Flex } from '../Flex';
|
||||
import { Text } from '../Text';
|
||||
import { Icon } from '../Icon';
|
||||
|
||||
const meta = {
|
||||
@@ -84,42 +83,3 @@ export const Responsive: Story = {
|
||||
},
|
||||
render: args => <ButtonIcon {...args} icon={<Icon name="cloud" />} />,
|
||||
};
|
||||
|
||||
const variants = ['primary', 'secondary'] as const;
|
||||
const sizes = ['small', 'medium'] as const;
|
||||
|
||||
export const Playground: Story = {
|
||||
render: args => (
|
||||
<Flex direction="column">
|
||||
{variants.map(variant => (
|
||||
<Flex direction="column" key={variant}>
|
||||
<Text>{variant}</Text>
|
||||
{sizes.map(size => (
|
||||
<Flex align="center" key={size}>
|
||||
<ButtonIcon
|
||||
{...args}
|
||||
variant={variant}
|
||||
size={size}
|
||||
icon={<Icon name="cloud" />}
|
||||
/>
|
||||
<ButtonIcon
|
||||
{...args}
|
||||
icon={<Icon name="chevron-right" />}
|
||||
aria-label="Chevron right icon button"
|
||||
variant={variant}
|
||||
size={size}
|
||||
/>
|
||||
<ButtonIcon
|
||||
{...args}
|
||||
icon={<Icon name="chevron-right" />}
|
||||
aria-label="Chevron right icon button"
|
||||
variant={variant}
|
||||
size={size}
|
||||
/>
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
@@ -23,22 +23,16 @@ import { useStyles } from '../../hooks/useStyles';
|
||||
/** @public */
|
||||
export const ButtonIcon = forwardRef(
|
||||
(props: ButtonIconProps, ref: Ref<HTMLButtonElement>) => {
|
||||
const {
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
icon,
|
||||
className,
|
||||
style,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const { classNames, dataAttributes } = useStyles('Button', {
|
||||
size,
|
||||
variant,
|
||||
const { classNames, dataAttributes, cleanedProps } = useStyles('Button', {
|
||||
size: 'small',
|
||||
variant: 'primary',
|
||||
...props,
|
||||
});
|
||||
|
||||
const { classNames: classNamesButtonIcon } = useStyles('ButtonIcon');
|
||||
|
||||
const { className, icon, ...rest } = cleanedProps;
|
||||
|
||||
return (
|
||||
<RAButton
|
||||
className={clsx(classNames.root, classNamesButtonIcon.root, className)}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
import type { Meta, StoryFn, StoryObj } from '@storybook/react-vite';
|
||||
import { ButtonLink } from './ButtonLink';
|
||||
import { Flex } from '../Flex';
|
||||
import { Text } from '../Text';
|
||||
import { Icon } from '../Icon';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
@@ -162,70 +161,3 @@ export const Responsive: Story = {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const variants = ['primary', 'secondary'] as const;
|
||||
const sizes = ['small', 'medium'] as const;
|
||||
|
||||
export const Playground: Story = {
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
render: () => (
|
||||
<Flex direction="column">
|
||||
{variants.map(variant => (
|
||||
<Flex direction="column" key={variant}>
|
||||
<Text>{variant}</Text>
|
||||
{sizes.map(size => (
|
||||
<Flex align="center" key={size}>
|
||||
<ButtonLink variant={variant} size={size}>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconStart={<Icon name="cloud" />}
|
||||
variant={variant}
|
||||
size={size}
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
variant={variant}
|
||||
size={size}
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconStart={<Icon name="cloud" />}
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
style={{ width: '200px' }}
|
||||
variant={variant}
|
||||
size={size}
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink variant={variant} size={size} isDisabled>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconStart={<Icon name="cloud" />}
|
||||
variant={variant}
|
||||
size={size}
|
||||
isDisabled
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
iconEnd={<Icon name="chevron-right" />}
|
||||
variant={variant}
|
||||
size={size}
|
||||
isDisabled
|
||||
>
|
||||
Button
|
||||
</ButtonLink>
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
@@ -26,24 +26,18 @@ import { isExternalLink } from '../../utils/isExternalLink';
|
||||
export const ButtonLink = forwardRef(
|
||||
(props: ButtonLinkProps, ref: Ref<HTMLAnchorElement>) => {
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
size = 'small',
|
||||
variant = 'primary',
|
||||
iconStart,
|
||||
iconEnd,
|
||||
children,
|
||||
className,
|
||||
href,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const { classNames, dataAttributes } = useStyles('Button', {
|
||||
size,
|
||||
variant,
|
||||
const { classNames, dataAttributes, cleanedProps } = useStyles('Button', {
|
||||
size: 'small',
|
||||
variant: 'primary',
|
||||
...props,
|
||||
});
|
||||
|
||||
const { classNames: classNamesButtonLink } = useStyles('ButtonLink');
|
||||
|
||||
const { children, className, iconStart, iconEnd, href, ...rest } =
|
||||
cleanedProps;
|
||||
|
||||
const isExternal = isExternalLink(href);
|
||||
|
||||
// If it's an external link, render RALink without RouterProvider
|
||||
|
||||
@@ -14,43 +14,28 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createElement, forwardRef } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
import { ContainerProps } from './types';
|
||||
import clsx from 'clsx';
|
||||
import { displayPropDefs } from '../../props/display.props';
|
||||
import { extractProps } from '../../utils/extractProps';
|
||||
import { spacingPropDefs } from '../../props/spacing.props';
|
||||
import { useStyles } from '../../hooks/useStyles';
|
||||
|
||||
/** @public */
|
||||
export const Container = forwardRef<HTMLDivElement, ContainerProps>(
|
||||
(props, ref) => {
|
||||
const { children } = props;
|
||||
const { classNames, utilityClasses, style, cleanedProps } = useStyles(
|
||||
'Container',
|
||||
props,
|
||||
);
|
||||
|
||||
const { classNames } = useStyles('Container');
|
||||
const { className, ...rest } = cleanedProps;
|
||||
|
||||
// Create a subset of spacing props that match the interface
|
||||
const containerSpacingProps = {
|
||||
my: spacingPropDefs.my,
|
||||
mt: spacingPropDefs.mt,
|
||||
mb: spacingPropDefs.mb,
|
||||
py: spacingPropDefs.py,
|
||||
pt: spacingPropDefs.pt,
|
||||
pb: spacingPropDefs.pb,
|
||||
};
|
||||
|
||||
const propDefs = {
|
||||
...displayPropDefs,
|
||||
...containerSpacingProps,
|
||||
};
|
||||
const { className, style, dataProps } = extractProps(props, propDefs);
|
||||
|
||||
return createElement('div', {
|
||||
ref,
|
||||
className: clsx(classNames.root, className),
|
||||
...dataProps,
|
||||
style,
|
||||
children,
|
||||
});
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, utilityClasses, className)}
|
||||
style={style}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 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 { 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 flexPropDefs = {
|
||||
align: {
|
||||
type: 'enum',
|
||||
className: 'bui-align',
|
||||
values: alignValues,
|
||||
responsive: true,
|
||||
},
|
||||
direction: {
|
||||
type: 'enum',
|
||||
className: 'bui-fd',
|
||||
values: directionValues,
|
||||
responsive: true,
|
||||
},
|
||||
justify: {
|
||||
type: 'enum',
|
||||
className: 'bui-jc',
|
||||
values: justifyValues,
|
||||
responsive: true,
|
||||
},
|
||||
} satisfies {
|
||||
align: PropDef<(typeof alignValues)[number]>;
|
||||
direction: PropDef<(typeof directionValues)[number]>;
|
||||
justify: PropDef<(typeof justifyValues)[number]>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
type FlexOwnProps = GetPropDefTypes<typeof flexPropDefs>;
|
||||
|
||||
export { flexPropDefs };
|
||||
export type { FlexOwnProps };
|
||||
@@ -17,6 +17,7 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-vite';
|
||||
import { Flex } from './Flex';
|
||||
import { Text } from '../Text';
|
||||
import { Box } from '../Box';
|
||||
|
||||
const meta = {
|
||||
title: 'Backstage UI/Flex',
|
||||
@@ -24,36 +25,54 @@ const meta = {
|
||||
argTypes: {
|
||||
align: {
|
||||
control: 'inline-radio',
|
||||
options: ['left', 'center', 'right'],
|
||||
options: ['start', 'center', 'end', 'baseline', 'stretch'],
|
||||
},
|
||||
children: {
|
||||
control: false,
|
||||
justify: {
|
||||
control: 'inline-radio',
|
||||
options: ['start', 'center', 'end', 'between'],
|
||||
},
|
||||
className: {
|
||||
control: 'text',
|
||||
direction: {
|
||||
control: 'inline-radio',
|
||||
options: ['row', 'column', 'row-reverse', 'column-reverse'],
|
||||
},
|
||||
},
|
||||
args: {
|
||||
align: 'stretch',
|
||||
gap: '4',
|
||||
children: 'hello world',
|
||||
},
|
||||
} satisfies Meta<typeof Flex>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
const DecorativeBox = () => {
|
||||
const DecorativeBox = ({
|
||||
width = '48px',
|
||||
height = '48px',
|
||||
}: {
|
||||
width?: string;
|
||||
height?: string;
|
||||
}) => {
|
||||
const diagonalStripePattern = (() => {
|
||||
const svg = `
|
||||
<svg width="6" height="6" viewBox="0 0 6 6" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#2563eb" fill-opacity="0.6" fill-rule="evenodd">
|
||||
<path d="M5 0h1L0 6V5zM6 5v1H5z"/>
|
||||
</g>
|
||||
</svg>
|
||||
`.trim();
|
||||
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
||||
})();
|
||||
|
||||
return (
|
||||
<div
|
||||
<Box
|
||||
width={width}
|
||||
height={height}
|
||||
style={{
|
||||
background: '#eaf2fd',
|
||||
borderRadius: '4px',
|
||||
boxShadow: '0 0 0 1px #2563eb',
|
||||
height: '32px',
|
||||
minWidth: '100px',
|
||||
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")',
|
||||
border: '1px solid #2563eb',
|
||||
backgroundImage: `url("${diagonalStripePattern}")`,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontWeight: 'bold',
|
||||
color: '#2563eb',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -85,49 +104,109 @@ export const RowDirection: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const AlignLeft: Story = {
|
||||
render: () => (
|
||||
<Flex align="start">
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
export const AlignStartInColumn: Story = {
|
||||
args: {
|
||||
align: 'start',
|
||||
direction: 'column',
|
||||
},
|
||||
render: args => (
|
||||
<Flex {...args}>
|
||||
<DecorativeBox height="32px" />
|
||||
<DecorativeBox height="24px" />
|
||||
<DecorativeBox height="48px" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AlignCenter: Story = {
|
||||
render: () => (
|
||||
<Flex align="center">
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
export const AlignStartInRow: Story = {
|
||||
args: {
|
||||
align: 'start',
|
||||
direction: 'row',
|
||||
},
|
||||
render: args => (
|
||||
<Flex {...args}>
|
||||
<DecorativeBox height="32px" />
|
||||
<DecorativeBox height="24px" />
|
||||
<DecorativeBox height="48px" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AlignRight: Story = {
|
||||
render: () => (
|
||||
<Flex align="end">
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
export const AlignCenterInColumn: Story = {
|
||||
args: {
|
||||
align: 'center',
|
||||
direction: 'column',
|
||||
},
|
||||
render: args => (
|
||||
<Flex {...args}>
|
||||
<DecorativeBox height="32px" />
|
||||
<DecorativeBox height="24px" />
|
||||
<DecorativeBox height="48px" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AlignCenterInRow: Story = {
|
||||
args: {
|
||||
align: 'center',
|
||||
direction: 'row',
|
||||
},
|
||||
render: args => (
|
||||
<Flex {...args}>
|
||||
<DecorativeBox height="32px" />
|
||||
<DecorativeBox height="24px" />
|
||||
<DecorativeBox height="48px" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AlignEndInColumn: Story = {
|
||||
args: {
|
||||
align: 'end',
|
||||
direction: 'column',
|
||||
},
|
||||
render: args => (
|
||||
<Flex {...args}>
|
||||
<DecorativeBox height="32px" />
|
||||
<DecorativeBox height="24px" />
|
||||
<DecorativeBox height="48px" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AlignEndInRow: Story = {
|
||||
args: {
|
||||
align: 'end',
|
||||
direction: 'row',
|
||||
},
|
||||
render: args => (
|
||||
<Flex {...args}>
|
||||
<DecorativeBox height="32px" />
|
||||
<DecorativeBox height="24px" />
|
||||
<DecorativeBox height="48px" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const ResponsiveAlign: Story = {
|
||||
render: () => (
|
||||
<Flex align={{ xs: 'start', md: 'center', lg: 'end' }}>
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
args: {
|
||||
align: { xs: 'start', md: 'center', lg: 'end' },
|
||||
},
|
||||
render: args => (
|
||||
<Flex {...args}>
|
||||
<DecorativeBox height="32px" />
|
||||
<DecorativeBox height="24px" />
|
||||
<DecorativeBox height="48px" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const ResponsiveGap: Story = {
|
||||
render: () => (
|
||||
<Flex gap={{ xs: '4', md: '8', lg: '12' }}>
|
||||
args: {
|
||||
gap: { xs: '4', md: '8', lg: '12' },
|
||||
},
|
||||
render: args => (
|
||||
<Flex {...args}>
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
@@ -136,8 +215,11 @@ export const ResponsiveGap: Story = {
|
||||
};
|
||||
|
||||
export const LargeGap: Story = {
|
||||
render: () => (
|
||||
<Flex gap="8">
|
||||
args: {
|
||||
gap: '8',
|
||||
},
|
||||
render: args => (
|
||||
<Flex {...args}>
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
<DecorativeBox />
|
||||
|
||||
@@ -14,31 +14,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createElement, forwardRef } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
import { FlexProps } from './types';
|
||||
import clsx from 'clsx';
|
||||
import { flexPropDefs } from './Flex.props';
|
||||
import { extractProps } from '../../utils/extractProps';
|
||||
import { gapPropDefs } from '../../props/gap-props';
|
||||
import { spacingPropDefs } from '../../props/spacing.props';
|
||||
import { useStyles } from '../../hooks/useStyles';
|
||||
|
||||
/** @public */
|
||||
export const Flex = forwardRef<HTMLDivElement, FlexProps>((props, ref) => {
|
||||
const propDefs = {
|
||||
...gapPropDefs,
|
||||
...flexPropDefs,
|
||||
...spacingPropDefs,
|
||||
};
|
||||
const { classNames, utilityClasses, style, cleanedProps } = useStyles(
|
||||
'Flex',
|
||||
{ gap: '4', ...props },
|
||||
);
|
||||
|
||||
const { classNames } = useStyles('Flex');
|
||||
const { className, style, dataProps } = extractProps(props, propDefs);
|
||||
const { className, ...rest } = cleanedProps;
|
||||
|
||||
return createElement('div', {
|
||||
ref,
|
||||
className: clsx(classNames.root, className),
|
||||
...dataProps,
|
||||
style,
|
||||
children: props.children,
|
||||
});
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, utilityClasses, className)}
|
||||
style={style}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -14,6 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { Flex } from './Flex';
|
||||
export { flexPropDefs } from './Flex.props';
|
||||
export type { FlexProps } from './types';
|
||||
export type { FlexOwnProps } from './Flex.props';
|
||||
|
||||
@@ -14,17 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { SpaceProps } from '../../types';
|
||||
import { FlexOwnProps } from './Flex.props';
|
||||
import type { GapProps } from '../../props/gap-props';
|
||||
import type { Responsive, Space, SpaceProps } from '../../types';
|
||||
|
||||
/** @public */
|
||||
export interface FlexProps extends SpaceProps {
|
||||
children: React.ReactNode;
|
||||
gap?: GapProps['gap'];
|
||||
align?: FlexOwnProps['align'];
|
||||
justify?: FlexOwnProps['justify'];
|
||||
direction?: FlexOwnProps['direction'];
|
||||
children?: React.ReactNode;
|
||||
gap?: Responsive<Space>;
|
||||
align?: Responsive<'start' | 'center' | 'end' | 'baseline' | 'stretch'>;
|
||||
justify?: Responsive<'start' | 'center' | 'end' | 'between'>;
|
||||
direction?: Responsive<'row' | 'column' | 'row-reverse' | 'column-reverse'>;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 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 { PropDef, GetPropDefTypes } from '../../props/prop-def';
|
||||
|
||||
const columnsValues = [
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'auto',
|
||||
] as const;
|
||||
|
||||
/** @public */
|
||||
const gridPropDefs = {
|
||||
columns: {
|
||||
type: 'enum | string',
|
||||
className: 'bui-columns',
|
||||
customProperties: ['--columns'],
|
||||
values: columnsValues,
|
||||
responsive: true,
|
||||
default: 'auto',
|
||||
},
|
||||
} satisfies {
|
||||
columns: PropDef<(typeof columnsValues)[number]>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
const gridItemPropDefs = {
|
||||
colSpan: {
|
||||
type: 'enum | string',
|
||||
className: 'bui-col-span',
|
||||
customProperties: ['--col-span'],
|
||||
values: columnsValues,
|
||||
responsive: true,
|
||||
},
|
||||
colEnd: {
|
||||
type: 'enum | string',
|
||||
className: 'bui-col-end',
|
||||
customProperties: ['--col-end'],
|
||||
values: columnsValues,
|
||||
responsive: true,
|
||||
},
|
||||
colStart: {
|
||||
type: 'enum | string',
|
||||
className: 'bui-col-start',
|
||||
customProperties: ['--col-start'],
|
||||
values: columnsValues,
|
||||
responsive: true,
|
||||
},
|
||||
rowSpan: {
|
||||
type: 'enum | string',
|
||||
className: 'bui-row-span',
|
||||
customProperties: ['--row-span'],
|
||||
values: columnsValues,
|
||||
responsive: true,
|
||||
},
|
||||
} satisfies {
|
||||
colSpan: PropDef<(typeof columnsValues)[number]>;
|
||||
colEnd: PropDef<(typeof columnsValues)[number]>;
|
||||
colStart: PropDef<(typeof columnsValues)[number]>;
|
||||
rowSpan: PropDef<(typeof columnsValues)[number]>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
type GridOwnProps = GetPropDefTypes<typeof gridPropDefs>;
|
||||
|
||||
/** @public */
|
||||
type GridItemOwnProps = GetPropDefTypes<typeof gridItemPropDefs>;
|
||||
|
||||
export { gridPropDefs, gridItemPropDefs };
|
||||
export type { GridOwnProps, GridItemOwnProps };
|
||||
@@ -14,50 +14,45 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createElement, forwardRef } from 'react';
|
||||
import { gapPropDefs } from '../../props/gap-props';
|
||||
import { extractProps } from '../../utils/extractProps';
|
||||
import { gridItemPropDefs, gridPropDefs } from './Grid.props';
|
||||
import { forwardRef } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import type { GridItemProps, GridProps } from './types';
|
||||
import { spacingPropDefs } from '../../props/spacing.props';
|
||||
import { useStyles } from '../../hooks/useStyles';
|
||||
|
||||
const GridRoot = forwardRef<HTMLDivElement, GridProps>((props, ref) => {
|
||||
const propDefs = {
|
||||
...gapPropDefs,
|
||||
...gridPropDefs,
|
||||
...spacingPropDefs,
|
||||
};
|
||||
const { classNames, utilityClasses, style, cleanedProps } = useStyles(
|
||||
'Grid',
|
||||
{ columns: 'auto', gap: '4', ...props },
|
||||
);
|
||||
|
||||
const { classNames } = useStyles('Grid');
|
||||
const { className, ...rest } = cleanedProps;
|
||||
|
||||
const { className, style, dataProps } = extractProps(props, propDefs);
|
||||
|
||||
return createElement('div', {
|
||||
ref,
|
||||
className: clsx(classNames.root, className),
|
||||
...dataProps,
|
||||
style,
|
||||
children: props.children,
|
||||
});
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, utilityClasses, className)}
|
||||
style={style}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const GridItem = forwardRef<HTMLDivElement, GridItemProps>((props, ref) => {
|
||||
const propDefs = {
|
||||
...gridItemPropDefs,
|
||||
};
|
||||
const { classNames, utilityClasses, style, cleanedProps } = useStyles(
|
||||
'GridItem',
|
||||
props,
|
||||
);
|
||||
|
||||
const { classNames } = useStyles('Grid');
|
||||
const { className, style, dataProps } = extractProps(props, propDefs);
|
||||
const { className, ...rest } = cleanedProps;
|
||||
|
||||
return createElement('div', {
|
||||
ref,
|
||||
className: clsx(classNames.item, className),
|
||||
...dataProps,
|
||||
style,
|
||||
children: props.children,
|
||||
});
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, utilityClasses, className)}
|
||||
style={style}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
/** @public */
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { Grid } from './Grid';
|
||||
export { gridPropDefs, gridItemPropDefs } from './Grid.props';
|
||||
export type { GridProps, GridItemProps } from './types';
|
||||
export type { GridOwnProps, GridItemOwnProps } from './Grid.props';
|
||||
|
||||
@@ -14,16 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { GapProps } from '../../props/gap-props';
|
||||
import type { SpaceProps } from '../../types';
|
||||
import type { GridItemOwnProps, GridOwnProps } from './Grid.props';
|
||||
import type { Space, SpaceProps, Responsive, Columns } from '../../types';
|
||||
|
||||
/** @public */
|
||||
export interface GridProps extends SpaceProps {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
columns?: GridOwnProps['columns'];
|
||||
gap?: GapProps['gap'];
|
||||
columns?: Responsive<Columns>;
|
||||
gap?: Responsive<Space>;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
@@ -31,9 +29,9 @@ export interface GridProps extends SpaceProps {
|
||||
export interface GridItemProps {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
colSpan?: GridItemOwnProps['colSpan'];
|
||||
colEnd?: GridItemOwnProps['colEnd'];
|
||||
colStart?: GridItemOwnProps['colStart'];
|
||||
rowSpan?: GridItemOwnProps['rowSpan'];
|
||||
colSpan?: Responsive<Columns>;
|
||||
colEnd?: Responsive<Columns>;
|
||||
colStart?: Responsive<Columns>;
|
||||
rowSpan?: Responsive<Columns>;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
@@ -32,17 +32,9 @@ import { RiEyeLine, RiEyeOffLine } from '@remixicon/react';
|
||||
export const PasswordField = forwardRef<HTMLDivElement, PasswordFieldProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
className,
|
||||
icon,
|
||||
size = 'small',
|
||||
label,
|
||||
secondaryLabel,
|
||||
description,
|
||||
isRequired,
|
||||
'aria-label': ariaLabel,
|
||||
'aria-labelledby': ariaLabelledBy,
|
||||
placeholder,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
@@ -53,15 +45,28 @@ export const PasswordField = forwardRef<HTMLDivElement, PasswordFieldProps>(
|
||||
}
|
||||
}, [label, ariaLabel, ariaLabelledBy]);
|
||||
|
||||
const { classNames: passwordFieldClassNames, dataAttributes } = useStyles(
|
||||
'PasswordField',
|
||||
{
|
||||
size,
|
||||
},
|
||||
);
|
||||
|
||||
const { classNames: textFieldClassNames } = useStyles('TextField', {});
|
||||
|
||||
const {
|
||||
classNames: passwordFieldClassNames,
|
||||
dataAttributes,
|
||||
style,
|
||||
cleanedProps,
|
||||
} = useStyles('PasswordField', {
|
||||
size: 'small',
|
||||
...props,
|
||||
});
|
||||
|
||||
const {
|
||||
className,
|
||||
description,
|
||||
icon,
|
||||
isRequired,
|
||||
secondaryLabel,
|
||||
placeholder,
|
||||
...rest
|
||||
} = cleanedProps;
|
||||
|
||||
// If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required.
|
||||
const secondaryLabelText =
|
||||
secondaryLabel || (isRequired ? 'Required' : null);
|
||||
@@ -76,6 +81,7 @@ export const PasswordField = forwardRef<HTMLDivElement, PasswordFieldProps>(
|
||||
aria-label={ariaLabel}
|
||||
aria-labelledby={ariaLabelledBy}
|
||||
type="password"
|
||||
style={style}
|
||||
{...rest}
|
||||
ref={ref}
|
||||
>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&[data-start-collapsed='true'] {
|
||||
&[data-startCollapsed='true'] {
|
||||
transition: flex-basis 0.3s ease-in-out;
|
||||
padding: 0;
|
||||
flex: 0 1 auto;
|
||||
|
||||
@@ -32,19 +32,9 @@ import type { SearchFieldProps } from './types';
|
||||
export const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
className,
|
||||
icon,
|
||||
size = 'small',
|
||||
label,
|
||||
secondaryLabel,
|
||||
description,
|
||||
isRequired,
|
||||
onChange,
|
||||
placeholder = 'Search',
|
||||
startCollapsed = false,
|
||||
'aria-label': ariaLabel,
|
||||
'aria-labelledby': ariaLabelledBy,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||
@@ -58,14 +48,30 @@ export const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
|
||||
}
|
||||
}, [label, ariaLabel, ariaLabelledBy]);
|
||||
|
||||
const { classNames: textFieldClassNames, dataAttributes } = useStyles(
|
||||
'TextField',
|
||||
{
|
||||
size,
|
||||
},
|
||||
);
|
||||
const { classNames: textFieldClassNames } = useStyles('TextField');
|
||||
|
||||
const { classNames: searchFieldClassNames } = useStyles('SearchField', {});
|
||||
const {
|
||||
classNames: searchFieldClassNames,
|
||||
dataAttributes,
|
||||
style,
|
||||
cleanedProps,
|
||||
} = useStyles('SearchField', {
|
||||
size: 'small',
|
||||
placeholder: 'Search',
|
||||
startCollapsed: false,
|
||||
...props,
|
||||
});
|
||||
|
||||
const {
|
||||
className,
|
||||
description,
|
||||
icon,
|
||||
isRequired,
|
||||
secondaryLabel,
|
||||
placeholder,
|
||||
startCollapsed,
|
||||
...rest
|
||||
} = cleanedProps;
|
||||
|
||||
// If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required.
|
||||
const secondaryLabelText =
|
||||
@@ -101,10 +107,10 @@ export const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
|
||||
{...dataAttributes}
|
||||
aria-label={ariaLabel}
|
||||
aria-labelledby={ariaLabelledBy}
|
||||
data-start-collapsed={startCollapsed}
|
||||
data-collapsed={isCollapsed}
|
||||
onFocusChange={handleClick}
|
||||
onChange={handleChange}
|
||||
style={style}
|
||||
{...rest}
|
||||
ref={ref}
|
||||
>
|
||||
|
||||
@@ -27,17 +27,9 @@ import { useStyles } from '../../hooks/useStyles';
|
||||
export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
className,
|
||||
icon,
|
||||
size = 'small',
|
||||
label,
|
||||
secondaryLabel,
|
||||
description,
|
||||
isRequired,
|
||||
'aria-label': ariaLabel,
|
||||
'aria-labelledby': ariaLabelledBy,
|
||||
placeholder,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
@@ -48,9 +40,23 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
|
||||
}
|
||||
}, [label, ariaLabel, ariaLabelledBy]);
|
||||
|
||||
const { classNames, dataAttributes } = useStyles('TextField', {
|
||||
size,
|
||||
});
|
||||
const { classNames, dataAttributes, style, cleanedProps } = useStyles(
|
||||
'TextField',
|
||||
{
|
||||
size: 'small',
|
||||
...props,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
className,
|
||||
description,
|
||||
icon,
|
||||
isRequired,
|
||||
secondaryLabel,
|
||||
placeholder,
|
||||
...rest
|
||||
} = cleanedProps;
|
||||
|
||||
// If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required.
|
||||
const secondaryLabelText =
|
||||
@@ -62,6 +68,7 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
|
||||
{...dataAttributes}
|
||||
aria-label={ariaLabel}
|
||||
aria-labelledby={ariaLabelledBy}
|
||||
style={style}
|
||||
{...rest}
|
||||
ref={ref}
|
||||
>
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
/* Breakpoint xs */
|
||||
@media (min-width: 640px) {
|
||||
.xs\:bui-mb {
|
||||
margin-bottom: var(--pb-xs);
|
||||
margin-bottom: var(--mb-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-mb-0\.5 {
|
||||
@@ -157,7 +157,7 @@
|
||||
/* Breakpoint sm */
|
||||
@media (min-width: 768px) {
|
||||
.sm\:bui-mb {
|
||||
margin-bottom: var(--pb-sm);
|
||||
margin-bottom: var(--mb-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-mb-0\.5 {
|
||||
@@ -228,7 +228,7 @@
|
||||
/* Breakpoint md */
|
||||
@media (min-width: 1024px) {
|
||||
.md\:bui-mb {
|
||||
margin-bottom: var(--pb-md);
|
||||
margin-bottom: var(--mb-md);
|
||||
}
|
||||
|
||||
.md\:bui-mb-0\.5 {
|
||||
@@ -299,7 +299,7 @@
|
||||
/* Breakpoint lg */
|
||||
@media (min-width: 1280px) {
|
||||
.lg\:bui-mb {
|
||||
margin-bottom: var(--pb-lg);
|
||||
margin-bottom: var(--mb-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-mb-0\.5 {
|
||||
@@ -370,7 +370,7 @@
|
||||
/* Breakpoint xl */
|
||||
@media (min-width: 1536px) {
|
||||
.xl\:bui-mb {
|
||||
margin-bottom: var(--pb-xl);
|
||||
margin-bottom: var(--mb-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-mb-0\.5 {
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
/* Breakpoint xs */
|
||||
@media (min-width: 640px) {
|
||||
.xs\:bui-ml {
|
||||
margin-left: var(--pl-xs);
|
||||
margin-left: var(--ml-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-ml-0\.5 {
|
||||
@@ -157,7 +157,7 @@
|
||||
/* Breakpoint sm */
|
||||
@media (min-width: 768px) {
|
||||
.sm\:bui-ml {
|
||||
margin-left: var(--pl-sm);
|
||||
margin-left: var(--ml-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-ml-0\.5 {
|
||||
@@ -228,7 +228,7 @@
|
||||
/* Breakpoint md */
|
||||
@media (min-width: 1024px) {
|
||||
.md\:bui-ml {
|
||||
margin-left: var(--pl-md);
|
||||
margin-left: var(--ml-md);
|
||||
}
|
||||
|
||||
.md\:bui-ml-0\.5 {
|
||||
@@ -299,7 +299,7 @@
|
||||
/* Breakpoint lg */
|
||||
@media (min-width: 1280px) {
|
||||
.lg\:bui-ml {
|
||||
margin-left: var(--pl-lg);
|
||||
margin-left: var(--ml-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-ml-0\.5 {
|
||||
@@ -370,7 +370,7 @@
|
||||
/* Breakpoint xl */
|
||||
@media (min-width: 1536px) {
|
||||
.xl\:bui-ml {
|
||||
margin-left: var(--pl-xl);
|
||||
margin-left: var(--ml-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-ml-0\.5 {
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
/* Breakpoint xs */
|
||||
@media (min-width: 640px) {
|
||||
.xs\:bui-mr {
|
||||
margin-right: var(--pr-xs);
|
||||
margin-right: var(--mr-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-mr-0\.5 {
|
||||
@@ -157,7 +157,7 @@
|
||||
/* Breakpoint sm */
|
||||
@media (min-width: 768px) {
|
||||
.sm\:bui-mr {
|
||||
margin-right: var(--pr-sm);
|
||||
margin-right: var(--mr-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-mr-0\.5 {
|
||||
@@ -228,7 +228,7 @@
|
||||
/* Breakpoint md */
|
||||
@media (min-width: 1024px) {
|
||||
.md\:bui-mr {
|
||||
margin-right: var(--pr-md);
|
||||
margin-right: var(--mr-md);
|
||||
}
|
||||
|
||||
.md\:bui-mr-0\.5 {
|
||||
@@ -299,7 +299,7 @@
|
||||
/* Breakpoint lg */
|
||||
@media (min-width: 1280px) {
|
||||
.lg\:bui-mr {
|
||||
margin-right: var(--pr-lg);
|
||||
margin-right: var(--mr-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-mr-0\.5 {
|
||||
@@ -370,7 +370,7 @@
|
||||
/* Breakpoint xl */
|
||||
@media (min-width: 1536px) {
|
||||
.xl\:bui-mr {
|
||||
margin-right: var(--pr-xl);
|
||||
margin-right: var(--mr-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-mr-0\.5 {
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
/* Breakpoint xs */
|
||||
@media (min-width: 640px) {
|
||||
.xs\:bui-mt {
|
||||
margin-top: var(--pt-xs);
|
||||
margin-top: var(--mt-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-mt-0\.5 {
|
||||
@@ -157,7 +157,7 @@
|
||||
/* Breakpoint sm */
|
||||
@media (min-width: 768px) {
|
||||
.sm\:bui-mt {
|
||||
margin-top: var(--pt-sm);
|
||||
margin-top: var(--mt-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-mt-0\.5 {
|
||||
@@ -228,7 +228,7 @@
|
||||
/* Breakpoint md */
|
||||
@media (min-width: 1024px) {
|
||||
.md\:bui-mt {
|
||||
margin-top: var(--pt-md);
|
||||
margin-top: var(--mt-md);
|
||||
}
|
||||
|
||||
.md\:bui-mt-0\.5 {
|
||||
@@ -299,7 +299,7 @@
|
||||
/* Breakpoint lg */
|
||||
@media (min-width: 1280px) {
|
||||
.lg\:bui-mt {
|
||||
margin-top: var(--pt-lg);
|
||||
margin-top: var(--mt-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-mt-0\.5 {
|
||||
@@ -370,7 +370,7 @@
|
||||
/* Breakpoint xl */
|
||||
@media (min-width: 1536px) {
|
||||
.xl\:bui-mt {
|
||||
margin-top: var(--pt-xl);
|
||||
margin-top: var(--mt-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-mt-0\.5 {
|
||||
|
||||
@@ -103,8 +103,8 @@
|
||||
/* Breakpoint xs */
|
||||
@media (min-width: 640px) {
|
||||
.xs\:bui-mx {
|
||||
margin-left: var(--px-xs);
|
||||
margin-right: var(--px-xs);
|
||||
margin-left: var(--mx-xs);
|
||||
margin-right: var(--mx-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-mx-0\.5 {
|
||||
@@ -191,8 +191,8 @@
|
||||
/* Breakpoint sm */
|
||||
@media (min-width: 768px) {
|
||||
.sm\:bui-mx {
|
||||
margin-left: var(--px-sm);
|
||||
margin-right: var(--px-sm);
|
||||
margin-left: var(--mx-sm);
|
||||
margin-right: var(--mx-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-mx-0\.5 {
|
||||
@@ -279,8 +279,8 @@
|
||||
/* Breakpoint md */
|
||||
@media (min-width: 1024px) {
|
||||
.md\:bui-mx {
|
||||
margin-left: var(--px-md);
|
||||
margin-right: var(--px-md);
|
||||
margin-left: var(--mx-md);
|
||||
margin-right: var(--mx-md);
|
||||
}
|
||||
|
||||
.md\:bui-mx-0\.5 {
|
||||
@@ -367,8 +367,8 @@
|
||||
/* Breakpoint lg */
|
||||
@media (min-width: 1280px) {
|
||||
.lg\:bui-mx {
|
||||
margin-left: var(--px-lg);
|
||||
margin-right: var(--px-lg);
|
||||
margin-left: var(--mx-lg);
|
||||
margin-right: var(--mx-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-mx-0\.5 {
|
||||
@@ -455,8 +455,8 @@
|
||||
/* Breakpoint xl */
|
||||
@media (min-width: 1536px) {
|
||||
.xl\:bui-mx {
|
||||
margin-left: var(--px-xl);
|
||||
margin-right: var(--px-xl);
|
||||
margin-left: var(--mx-xl);
|
||||
margin-right: var(--mx-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-mx-0\.5 {
|
||||
|
||||
@@ -103,8 +103,8 @@
|
||||
/* Breakpoint xs */
|
||||
@media (min-width: 640px) {
|
||||
.xs\:bui-my {
|
||||
margin-top: var(--py-xs);
|
||||
margin-bottom: var(--py-xs);
|
||||
margin-top: var(--my-xs);
|
||||
margin-bottom: var(--my-xs);
|
||||
}
|
||||
|
||||
.xs\:bui-my-0\.5 {
|
||||
@@ -191,8 +191,8 @@
|
||||
/* Breakpoint sm */
|
||||
@media (min-width: 768px) {
|
||||
.sm\:bui-my {
|
||||
margin-top: var(--py-sm);
|
||||
margin-bottom: var(--py-sm);
|
||||
margin-top: var(--my-sm);
|
||||
margin-bottom: var(--my-sm);
|
||||
}
|
||||
|
||||
.sm\:bui-my-0\.5 {
|
||||
@@ -279,8 +279,8 @@
|
||||
/* Breakpoint md */
|
||||
@media (min-width: 1024px) {
|
||||
.md\:bui-my {
|
||||
margin-top: var(--py-md);
|
||||
margin-bottom: var(--py-md);
|
||||
margin-top: var(--my-md);
|
||||
margin-bottom: var(--my-md);
|
||||
}
|
||||
|
||||
.md\:bui-my-0\.5 {
|
||||
@@ -367,8 +367,8 @@
|
||||
/* Breakpoint lg */
|
||||
@media (min-width: 1280px) {
|
||||
.lg\:bui-my {
|
||||
margin-top: var(--py-lg);
|
||||
margin-bottom: var(--py-lg);
|
||||
margin-top: var(--my-lg);
|
||||
margin-bottom: var(--my-lg);
|
||||
}
|
||||
|
||||
.lg\:bui-my-0\.5 {
|
||||
@@ -455,8 +455,8 @@
|
||||
/* Breakpoint xl */
|
||||
@media (min-width: 1536px) {
|
||||
.xl\:bui-my {
|
||||
margin-top: var(--py-xl);
|
||||
margin-bottom: var(--py-xl);
|
||||
margin-top: var(--my-xl);
|
||||
margin-bottom: var(--my-xl);
|
||||
}
|
||||
|
||||
.xl\:bui-my-0\.5 {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import { useBreakpoint, breakpoints } from './useBreakpoint';
|
||||
import { componentDefinitions } from '../utils/componentDefinitions';
|
||||
import type { ComponentDefinitionName, ComponentClassNames } from '../types';
|
||||
import { utilityClassMap } from '../utils/utilityClassMap';
|
||||
|
||||
/**
|
||||
* Resolve a responsive value based on the current breakpoint
|
||||
@@ -55,8 +56,8 @@ function resolveResponsiveValue(
|
||||
/**
|
||||
* React hook to get class names and data attributes for a component with responsive support
|
||||
* @param componentName - The name of the component
|
||||
* @param props - Object with prop values (can be responsive)
|
||||
* @returns Object with classNames and dataAttributes
|
||||
* @param props - All component props
|
||||
* @returns Object with classNames, dataAttributes, utilityClasses, style, and cleanedProps
|
||||
*/
|
||||
export function useStyles<T extends ComponentDefinitionName>(
|
||||
componentName: T,
|
||||
@@ -64,29 +65,135 @@ export function useStyles<T extends ComponentDefinitionName>(
|
||||
): {
|
||||
classNames: ComponentClassNames<T>;
|
||||
dataAttributes: Record<string, string>;
|
||||
resolvedProps: Record<string, string>;
|
||||
utilityClasses: string;
|
||||
style: React.CSSProperties;
|
||||
cleanedProps: Record<string, any>;
|
||||
} {
|
||||
const { breakpoint } = useBreakpoint();
|
||||
const classNames = componentDefinitions[componentName]
|
||||
.classNames as ComponentClassNames<T>;
|
||||
const componentDefinition = componentDefinitions[componentName];
|
||||
const classNames = componentDefinition.classNames as ComponentClassNames<T>;
|
||||
const utilityPropNames =
|
||||
('utilityProps' in componentDefinition
|
||||
? componentDefinition.utilityProps
|
||||
: []) || [];
|
||||
|
||||
// Resolve responsive values and generate data attributes
|
||||
// Extract data attribute names from component definition
|
||||
const dataAttributeNames =
|
||||
'dataAttributes' in componentDefinition
|
||||
? Object.keys(componentDefinition.dataAttributes || {})
|
||||
: [];
|
||||
|
||||
// Extract existing style from props
|
||||
const incomingStyle = props.style || {};
|
||||
|
||||
// Generate data attributes from component definition
|
||||
const dataAttributes: Record<string, string> = {};
|
||||
const resolvedProps: Record<string, string> = {};
|
||||
|
||||
for (const [key, value] of Object.entries(props)) {
|
||||
for (const key of dataAttributeNames) {
|
||||
const value = props[key];
|
||||
if (value !== undefined && value !== null) {
|
||||
const resolvedValue = resolveResponsiveValue(value, breakpoint);
|
||||
if (resolvedValue !== undefined) {
|
||||
resolvedProps[key] = resolvedValue;
|
||||
dataAttributes[`data-${key}`] = resolvedValue;
|
||||
// Handle boolean and number values directly
|
||||
if (typeof value === 'boolean' || typeof value === 'number') {
|
||||
dataAttributes[`data-${key}`] = String(value);
|
||||
} else {
|
||||
const resolvedValue = resolveResponsiveValue(value, breakpoint);
|
||||
if (resolvedValue !== undefined) {
|
||||
dataAttributes[`data-${key}`] = resolvedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate utility classes and custom styles from component's allowed utility props
|
||||
const utilityClassList: string[] = [];
|
||||
const generatedStyle: React.CSSProperties = {};
|
||||
|
||||
const handleUtilityValue = (
|
||||
key: string,
|
||||
val: unknown,
|
||||
prefix: string = '',
|
||||
) => {
|
||||
// Get utility class configuration for this key
|
||||
const utilityConfig = utilityClassMap[key as keyof typeof utilityClassMap];
|
||||
|
||||
if (!utilityConfig) {
|
||||
// Skip if no config found for this key
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if value is in the list of valid values for this utility
|
||||
if (
|
||||
utilityConfig.values.length > 0 &&
|
||||
utilityConfig.values.includes(val as string | number)
|
||||
) {
|
||||
// Generate utility class with value suffix and optional breakpoint prefix
|
||||
const className = prefix
|
||||
? `${prefix}${utilityConfig.class}-${val}`
|
||||
: `${utilityConfig.class}-${val}`;
|
||||
utilityClassList.push(className);
|
||||
} else if (utilityConfig.cssVar) {
|
||||
// Custom value - add CSS custom property AND utility class name
|
||||
// Only if cssVar is defined (properties with fixed values don't have cssVar)
|
||||
const cssVarKey = prefix
|
||||
? `${utilityConfig.cssVar}-${prefix.slice(0, -1)}`
|
||||
: utilityConfig.cssVar;
|
||||
// CSS custom properties need to be set on the style object as strings
|
||||
(generatedStyle as Record<string, unknown>)[cssVarKey] = val;
|
||||
|
||||
// Add utility class name (without value suffix) with optional breakpoint prefix
|
||||
const className = prefix
|
||||
? `${prefix}${utilityConfig.class}`
|
||||
: utilityConfig.class;
|
||||
utilityClassList.push(className);
|
||||
}
|
||||
// If no cssVar and value is not in valid values, skip (invalid value for fixed-value property)
|
||||
};
|
||||
|
||||
for (const key of utilityPropNames) {
|
||||
const value = props[key];
|
||||
if (value === undefined || value === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if value is a responsive object
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
const breakpointValues = value as { [key: string]: unknown };
|
||||
// Handle responsive object values
|
||||
for (const bp in breakpointValues) {
|
||||
const prefix = bp === 'initial' ? '' : `${bp}:`;
|
||||
handleUtilityValue(key, breakpointValues[bp], prefix);
|
||||
}
|
||||
} else {
|
||||
// Handle simple value
|
||||
handleUtilityValue(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Create cleaned props by excluding data attributes, utility props, and style
|
||||
// Component-specific props like 'as' and 'children' remain in cleanedProps
|
||||
const processedKeys = new Set([
|
||||
...dataAttributeNames,
|
||||
...utilityPropNames,
|
||||
'style',
|
||||
]);
|
||||
|
||||
const cleanedProps = Object.keys(props).reduce((acc, key) => {
|
||||
if (!processedKeys.has(key)) {
|
||||
acc[key] = props[key];
|
||||
}
|
||||
return acc;
|
||||
}, {} as Record<string, any>);
|
||||
|
||||
// Merge incoming style with generated styles (incoming styles take precedence)
|
||||
const mergedStyle = {
|
||||
...generatedStyle,
|
||||
...incomingStyle,
|
||||
};
|
||||
|
||||
return {
|
||||
classNames,
|
||||
dataAttributes,
|
||||
resolvedProps, // Also return resolved props for convenience
|
||||
utilityClasses: utilityClassList.join(' '),
|
||||
style: mergedStyle,
|
||||
cleanedProps,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -78,7 +78,20 @@ export type BorderRadius =
|
||||
export type Border = 'none' | 'base' | 'error' | 'warning' | 'selected';
|
||||
|
||||
/** @public */
|
||||
export type Columns = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'auto';
|
||||
export type Columns =
|
||||
| '1'
|
||||
| '2'
|
||||
| '3'
|
||||
| '4'
|
||||
| '5'
|
||||
| '6'
|
||||
| '7'
|
||||
| '8'
|
||||
| '9'
|
||||
| '10'
|
||||
| '11'
|
||||
| '12'
|
||||
| 'auto';
|
||||
|
||||
/** @public */
|
||||
export interface SpaceProps {
|
||||
@@ -160,6 +173,7 @@ export type DataAttributesMap = Record<string, DataAttributeValues>;
|
||||
export interface ComponentDefinition {
|
||||
classNames: ClassNamesMap;
|
||||
dataAttributes?: DataAttributesMap;
|
||||
utilityProps?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,30 @@ export const componentDefinitions = {
|
||||
classNames: {
|
||||
root: 'bui-Box',
|
||||
},
|
||||
utilityProps: [
|
||||
'm',
|
||||
'mb',
|
||||
'ml',
|
||||
'mr',
|
||||
'mt',
|
||||
'mx',
|
||||
'my',
|
||||
'p',
|
||||
'pb',
|
||||
'pl',
|
||||
'pr',
|
||||
'pt',
|
||||
'px',
|
||||
'py',
|
||||
'position',
|
||||
'display',
|
||||
'width',
|
||||
'minWidth',
|
||||
'maxWidth',
|
||||
'height',
|
||||
'minHeight',
|
||||
'maxHeight',
|
||||
],
|
||||
},
|
||||
Button: {
|
||||
classNames: {
|
||||
@@ -84,6 +108,7 @@ export const componentDefinitions = {
|
||||
classNames: {
|
||||
root: 'bui-Container',
|
||||
},
|
||||
utilityProps: ['my', 'mt', 'mb', 'py', 'pt', 'pb', 'display'],
|
||||
},
|
||||
Dialog: {
|
||||
classNames: {
|
||||
@@ -107,12 +132,55 @@ export const componentDefinitions = {
|
||||
classNames: {
|
||||
root: 'bui-Flex',
|
||||
},
|
||||
utilityProps: [
|
||||
'm',
|
||||
'mb',
|
||||
'ml',
|
||||
'mr',
|
||||
'mt',
|
||||
'mx',
|
||||
'my',
|
||||
'p',
|
||||
'pb',
|
||||
'pl',
|
||||
'pr',
|
||||
'pt',
|
||||
'px',
|
||||
'py',
|
||||
'gap',
|
||||
'align',
|
||||
'justify',
|
||||
'direction',
|
||||
],
|
||||
},
|
||||
Grid: {
|
||||
classNames: {
|
||||
root: 'bui-Grid',
|
||||
item: 'bui-GridItem',
|
||||
},
|
||||
utilityProps: [
|
||||
'columns',
|
||||
'gap',
|
||||
'm',
|
||||
'mb',
|
||||
'ml',
|
||||
'mr',
|
||||
'mt',
|
||||
'mx',
|
||||
'my',
|
||||
'p',
|
||||
'pb',
|
||||
'pl',
|
||||
'pr',
|
||||
'pt',
|
||||
'px',
|
||||
'py',
|
||||
],
|
||||
},
|
||||
GridItem: {
|
||||
classNames: {
|
||||
root: 'bui-GridItem',
|
||||
},
|
||||
utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan'],
|
||||
},
|
||||
Header: {
|
||||
classNames: {
|
||||
@@ -190,6 +258,9 @@ export const componentDefinitions = {
|
||||
root: 'bui-PasswordField',
|
||||
inputVisibility: 'bui-InputVisibility',
|
||||
},
|
||||
dataAttributes: {
|
||||
size: ['small', 'medium'] as const,
|
||||
},
|
||||
},
|
||||
Popover: {
|
||||
classNames: {
|
||||
@@ -218,6 +289,7 @@ export const componentDefinitions = {
|
||||
},
|
||||
dataAttributes: {
|
||||
startCollapsed: [true, false] as const,
|
||||
size: ['small', 'medium'] as const,
|
||||
},
|
||||
},
|
||||
Select: {
|
||||
@@ -308,6 +380,7 @@ export const componentDefinitions = {
|
||||
dataAttributes: {
|
||||
invalid: [true, false] as const,
|
||||
disabled: [true, false] as const,
|
||||
size: ['small', 'medium'] as const,
|
||||
},
|
||||
},
|
||||
Tooltip: {
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 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.
|
||||
*/
|
||||
|
||||
type BasePropDef = {
|
||||
type: string;
|
||||
values?: readonly unknown[];
|
||||
default?: unknown;
|
||||
required?: boolean;
|
||||
className?: string;
|
||||
responsive?: true;
|
||||
customProperties?: string[];
|
||||
};
|
||||
|
||||
export function extractProps(
|
||||
props: {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
children?: React.ReactNode;
|
||||
as?: keyof JSX.IntrinsicElements;
|
||||
[key: string]: any;
|
||||
},
|
||||
propDefs: { [name in string]: BasePropDef },
|
||||
) {
|
||||
let className: string[] = (props.className || '').split(' ');
|
||||
let style: React.CSSProperties = { ...props.style };
|
||||
|
||||
for (const key in propDefs) {
|
||||
const propDef = propDefs[key];
|
||||
|
||||
// Check if the prop is present or has a default value
|
||||
if (!Object.hasOwn(props, key) && !propDef.hasOwnProperty('default')) {
|
||||
continue; // Skip processing if neither is present
|
||||
}
|
||||
|
||||
const value = Object.hasOwn(props, key)
|
||||
? (props[key] as unknown)
|
||||
: propDefs[key].default;
|
||||
const propDefsValues = propDef.values;
|
||||
const propDefsCustomProperties = propDef.customProperties;
|
||||
const propDefsClassName = propDef.className;
|
||||
const isResponsive = propDef.responsive;
|
||||
|
||||
const handleValue = (val: unknown, prefix: string = '') => {
|
||||
// Skip adding class name if the key is "as"
|
||||
if (key === 'as') return;
|
||||
|
||||
if (propDefsValues?.includes(val)) {
|
||||
className.push(`${prefix}${propDefsClassName}-${val}`);
|
||||
} else {
|
||||
if (propDefsCustomProperties) {
|
||||
for (const customProperty of propDefsCustomProperties) {
|
||||
const customPropertyKey =
|
||||
isResponsive && prefix
|
||||
? `${customProperty}-${prefix.slice(0, -1)}`
|
||||
: customProperty;
|
||||
style[customPropertyKey as keyof typeof style] = val as any;
|
||||
}
|
||||
}
|
||||
className.push(`${prefix}${propDefsClassName}`);
|
||||
}
|
||||
};
|
||||
|
||||
if (isResponsive && typeof value === 'object' && value !== null) {
|
||||
const breakpointValues = value as { [key: string]: unknown };
|
||||
// Handle responsive object values
|
||||
for (const breakpoint in breakpointValues) {
|
||||
const prefix = breakpoint === 'initial' ? '' : `${breakpoint}:`;
|
||||
handleValue(breakpointValues[breakpoint], prefix);
|
||||
}
|
||||
} else {
|
||||
handleValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure keys from props that are defined in propDefs are removed
|
||||
const { cleanedProps, dataProps } = Object.keys(props).reduce(
|
||||
(acc, key) => {
|
||||
if (key.startsWith('data-')) {
|
||||
acc.dataProps[key] = props[key];
|
||||
}
|
||||
if (!propDefs.hasOwnProperty(key)) {
|
||||
acc.cleanedProps[key] = props[key];
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{ dataProps: {}, cleanedProps: {} } as {
|
||||
dataProps: { [key: string]: any };
|
||||
cleanedProps: { [key: string]: any };
|
||||
},
|
||||
);
|
||||
|
||||
const newClassNames = className
|
||||
.filter(name => name && name.trim() !== '')
|
||||
.join(' ');
|
||||
|
||||
return { ...cleanedProps, className: newClassNames, style, dataProps };
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2025 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.
|
||||
*/
|
||||
|
||||
// Valid spacing values that have predefined utility classes
|
||||
const validSpacingValues = [
|
||||
'0.5',
|
||||
'1',
|
||||
'1.5',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'13',
|
||||
'14',
|
||||
] as const;
|
||||
|
||||
const columnsValues = [
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'auto',
|
||||
] as const;
|
||||
|
||||
export const utilityClassMap: Record<
|
||||
string,
|
||||
{ class: string; cssVar?: string; values: readonly (string | number)[] }
|
||||
> = {
|
||||
m: {
|
||||
class: 'bui-m',
|
||||
cssVar: '--m',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
mb: {
|
||||
class: 'bui-mb',
|
||||
cssVar: '--mb',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
ml: {
|
||||
class: 'bui-ml',
|
||||
cssVar: '--ml',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
mr: {
|
||||
class: 'bui-mr',
|
||||
cssVar: '--mr',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
mt: {
|
||||
class: 'bui-mt',
|
||||
cssVar: '--mt',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
mx: {
|
||||
class: 'bui-mx',
|
||||
cssVar: '--mx',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
my: {
|
||||
class: 'bui-my',
|
||||
cssVar: '--my',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
p: {
|
||||
class: 'bui-p',
|
||||
cssVar: '--p',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
pb: {
|
||||
class: 'bui-pb',
|
||||
cssVar: '--pb',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
pl: {
|
||||
class: 'bui-pl',
|
||||
cssVar: '--pl',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
pr: {
|
||||
class: 'bui-pr',
|
||||
cssVar: '--pr',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
pt: {
|
||||
class: 'bui-pt',
|
||||
cssVar: '--pt',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
px: {
|
||||
class: 'bui-px',
|
||||
cssVar: '--px',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
py: {
|
||||
class: 'bui-py',
|
||||
cssVar: '--py',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
width: {
|
||||
class: 'bui-w',
|
||||
cssVar: '--width',
|
||||
values: [], // Always use custom value
|
||||
},
|
||||
minWidth: {
|
||||
class: 'bui-min-w',
|
||||
cssVar: '--min-width',
|
||||
values: [], // Always use custom value
|
||||
},
|
||||
maxWidth: {
|
||||
class: 'bui-max-w',
|
||||
cssVar: '--max-width',
|
||||
values: [], // Always use custom value
|
||||
},
|
||||
height: {
|
||||
class: 'bui-h',
|
||||
cssVar: '--height',
|
||||
values: [], // Always use custom value
|
||||
},
|
||||
minHeight: {
|
||||
class: 'bui-min-h',
|
||||
cssVar: '--min-height',
|
||||
values: [], // Always use custom value
|
||||
},
|
||||
maxHeight: {
|
||||
class: 'bui-max-h',
|
||||
cssVar: '--max-height',
|
||||
values: [], // Always use custom value
|
||||
},
|
||||
gap: {
|
||||
class: 'bui-gap',
|
||||
cssVar: '--gap',
|
||||
values: validSpacingValues,
|
||||
},
|
||||
position: {
|
||||
class: 'bui-position',
|
||||
values: ['static', 'relative', 'absolute', 'fixed', 'sticky'],
|
||||
},
|
||||
display: {
|
||||
class: 'bui-display',
|
||||
values: ['none', 'flex', 'block', 'inline'],
|
||||
},
|
||||
align: {
|
||||
class: 'bui-align',
|
||||
values: ['start', 'center', 'end', 'baseline', 'stretch'],
|
||||
},
|
||||
justify: {
|
||||
class: 'bui-jc',
|
||||
values: ['start', 'center', 'end', 'between'],
|
||||
},
|
||||
direction: {
|
||||
class: 'bui-fd',
|
||||
values: ['row', 'column', 'row-reverse', 'column-reverse'],
|
||||
},
|
||||
columns: {
|
||||
class: 'bui-columns',
|
||||
values: columnsValues,
|
||||
},
|
||||
colSpan: {
|
||||
class: 'bui-col-span',
|
||||
values: columnsValues,
|
||||
},
|
||||
colEnd: {
|
||||
class: 'bui-col-end',
|
||||
values: columnsValues,
|
||||
},
|
||||
colStart: {
|
||||
class: 'bui-col-start',
|
||||
values: columnsValues,
|
||||
},
|
||||
rowSpan: {
|
||||
class: 'bui-row-span',
|
||||
values: columnsValues,
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user