diff --git a/packages/canon/src/components/Box/Box.stories.tsx b/packages/canon/src/components/Box/Box.stories.tsx
index 98ae922c2e..7b9aecca1a 100644
--- a/packages/canon/src/components/Box/Box.stories.tsx
+++ b/packages/canon/src/components/Box/Box.stories.tsx
@@ -18,7 +18,6 @@ import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Box } from './Box';
import { Flex } from '../Flex';
-import { Inline } from '../Inline';
const meta = {
title: 'Components/Box',
@@ -81,8 +80,8 @@ const CardDisplay = ({ children }: { children?: React.ReactNode }) => {
export const Display: Story = {
render: args => (
-
-
+
+
Block
@@ -92,7 +91,7 @@ export const Display: Story = {
None
-
+
Responsive
@@ -116,8 +115,8 @@ export const Padding: Story = {
},
},
render: args => (
-
-
+
+
Padding
@@ -127,8 +126,8 @@ export const Padding: Story = {
Padding Y
-
-
+
+
Padding Top
@@ -141,7 +140,7 @@ export const Padding: Story = {
Padding Left
-
+
),
};
@@ -156,8 +155,8 @@ export const Margin: Story = {
},
},
render: args => (
-
-
+
+
Margin
@@ -173,8 +172,8 @@ export const Margin: Story = {
Margin Y
-
-
+
+
Margin Top
@@ -195,7 +194,7 @@ export const Margin: Story = {
Margin Left
-
+
),
};
diff --git a/packages/canon/src/components/Button/Button.stories.tsx b/packages/canon/src/components/Button/Button.stories.tsx
index 719da4758c..cd52c7fdba 100644
--- a/packages/canon/src/components/Button/Button.stories.tsx
+++ b/packages/canon/src/components/Button/Button.stories.tsx
@@ -17,7 +17,6 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
-import { Inline } from '../Inline';
import { Flex } from '../Flex';
import { Text } from '../Text';
import { ButtonProps } from './types';
@@ -51,7 +50,7 @@ export const Variants: Story = {
},
},
render: () => (
-
+
@@ -61,7 +60,7 @@ export const Variants: Story = {
-
+
),
};
@@ -70,10 +69,10 @@ export const Sizes: Story = {
children: 'Button',
},
render: () => (
-
+
-
+
),
};
@@ -82,11 +81,11 @@ export const WithIcons: Story = {
children: 'Button',
},
render: args => (
-
+
-
+
),
};
@@ -132,12 +131,12 @@ export const Playground: Story = {
children: 'Button',
},
render: () => (
-
+
{variants.map(variant => (
-
+
{variant}
{['small', 'medium'].map(size => (
-
+
-
+
))}
))}
diff --git a/packages/canon/src/components/Checkbox/Checkbox.stories.tsx b/packages/canon/src/components/Checkbox/Checkbox.stories.tsx
index 40fee4a177..db320cb3ce 100644
--- a/packages/canon/src/components/Checkbox/Checkbox.stories.tsx
+++ b/packages/canon/src/components/Checkbox/Checkbox.stories.tsx
@@ -17,7 +17,6 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Checkbox } from './Checkbox';
-import { Inline } from '../Inline';
import { Flex } from '../Flex';
import { Text } from '../Text';
@@ -40,12 +39,12 @@ export const Default: Story = {
export const AllVariants: Story = {
render: () => (
-
+
-
+
),
};
@@ -53,12 +52,12 @@ export const Playground: Story = {
render: () => (
All variants
-
+
-
+
),
};
diff --git a/packages/canon/src/components/Flex/Flex.props.ts b/packages/canon/src/components/Flex/Flex.props.ts
index 7d758c5ee3..97a602b42f 100644
--- a/packages/canon/src/components/Flex/Flex.props.ts
+++ b/packages/canon/src/components/Flex/Flex.props.ts
@@ -23,6 +23,7 @@ const directionValues = [
'row-reverse',
'column-reverse',
] as const;
+const justifyValues = ['start', 'center', 'end', 'between'] as const;
/** @public */
const flexPropDefs = {
@@ -38,9 +39,16 @@ const flexPropDefs = {
values: directionValues,
responsive: true,
},
+ justify: {
+ type: 'enum',
+ className: 'cu-jc',
+ values: justifyValues,
+ responsive: true,
+ },
} satisfies {
align: PropDef<(typeof alignValues)[number]>;
direction: PropDef<(typeof directionValues)[number]>;
+ justify: PropDef<(typeof justifyValues)[number]>;
};
/** @public */
diff --git a/packages/canon/src/components/Flex/types.ts b/packages/canon/src/components/Flex/types.ts
index c01af20e99..d449bc609a 100644
--- a/packages/canon/src/components/Flex/types.ts
+++ b/packages/canon/src/components/Flex/types.ts
@@ -23,6 +23,7 @@ export interface FlexProps extends SpaceProps {
children: React.ReactNode;
gap?: GapProps['gap'];
align?: FlexOwnProps['align'];
+ justify?: FlexOwnProps['justify'];
direction?: FlexOwnProps['direction'];
className?: string;
style?: React.CSSProperties;
diff --git a/packages/canon/src/components/Heading/Heading.stories.tsx b/packages/canon/src/components/Heading/Heading.stories.tsx
index 09c0a76ea0..1357bde877 100644
--- a/packages/canon/src/components/Heading/Heading.stories.tsx
+++ b/packages/canon/src/components/Heading/Heading.stories.tsx
@@ -19,6 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { Heading } from './Heading';
import { Flex } from '../Flex';
import { Text } from '../Text';
+
const meta = {
title: 'Components/Heading',
component: Heading,
diff --git a/packages/canon/src/components/Inline/Inline.stories.tsx b/packages/canon/src/components/Inline/Inline.stories.tsx
deleted file mode 100644
index 96833d1f64..0000000000
--- a/packages/canon/src/components/Inline/Inline.stories.tsx
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2024 The Backstage Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
-import { Inline } from './Inline';
-import { Box } from '../Box/Box';
-
-const meta = {
- title: 'Components/Inline',
- component: Inline,
- argTypes: {
- align: {
- control: 'inline-radio',
- options: ['left', 'center', 'right'],
- },
- alignY: {
- control: 'inline-radio',
- options: ['top', 'center', 'bottom'],
- },
- children: {
- control: false,
- },
- as: {
- control: false,
- },
- className: {
- control: 'text',
- },
- },
- args: {
- children: 'hello world',
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const fakeBlockList = [
- { width: 45, height: 60 },
- { width: 150, height: 75 },
- { width: 80, height: 50 },
- { width: 120, height: 70 },
- { width: 95, height: 65 },
- { width: 80, height: 32 },
- { width: 130, height: 60 },
- { width: 100, height: 80 },
- { width: 140, height: 45 },
- { width: 85, height: 70 },
- { width: 125, height: 50 },
-];
-
-const FakeBox = ({
- width = 120,
- height = 80,
-}: {
- width?: number;
- height?: number;
-}) => (
-
-);
-
-export const Default: Story = {
- render: () => (
-
- {fakeBlockList.map((block, index) => (
-
- ))}
-
- ),
-};
-
-export const AlignLeft: Story = {
- args: {
- align: 'left',
- },
-};
-
-export const AlignCenter: Story = {
- args: {
- align: 'center',
- },
-};
-
-export const AlignRight: Story = {
- args: {
- align: 'right',
- },
-};
-
-export const VerticalAlignTop: Story = {
- args: {
- alignY: 'top',
- },
-};
-
-export const VerticalAlignCenter: Story = {
- args: {
- alignY: 'center',
- },
-};
-
-export const VerticalAlignBottom: Story = {
- args: {
- alignY: 'bottom',
- },
-};
-
-export const LargeGap: Story = {
- args: {
- gap: 'xl',
- },
-};
diff --git a/packages/canon/src/components/Inline/Inline.tsx b/packages/canon/src/components/Inline/Inline.tsx
deleted file mode 100644
index 599033996c..0000000000
--- a/packages/canon/src/components/Inline/Inline.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2024 The Backstage Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { createElement, forwardRef } from 'react';
-import type { InlineProps } from './types';
-import { getClassNames } from '../../utils/getClassNames';
-import { JustifyContent, Breakpoint, AlignItems } from '../../types';
-import clsx from 'clsx';
-
-// Function to map align values
-const mapAlignValue = (value?: InlineProps['align']) => {
- if (typeof value === 'string') {
- let returnedValue: JustifyContent = 'stretch';
- if (value === 'left') returnedValue = 'start';
- if (value === 'center') returnedValue = 'center';
- if (value === 'right') returnedValue = 'end';
- return returnedValue;
- } else if (typeof value === 'object') {
- const returnedValue: Partial> = {};
- for (const [key, val] of Object.entries(value)) {
- returnedValue[key as Breakpoint] = mapAlignValue(val) as JustifyContent;
- }
- return returnedValue;
- }
- return 'stretch';
-};
-
-const mapAlignYValue = (value?: InlineProps['alignY']) => {
- if (typeof value === 'string') {
- let returnedValue: AlignItems = 'stretch';
- if (value === 'top') returnedValue = 'start';
- if (value === 'center') returnedValue = 'center';
- if (value === 'bottom') returnedValue = 'end';
- return returnedValue;
- } else if (typeof value === 'object') {
- const returnedValue: Partial> = {};
- for (const [key, val] of Object.entries(value)) {
- returnedValue[key as Breakpoint] = mapAlignYValue(val) as AlignItems;
- }
- return returnedValue;
- }
- return 'stretch';
-};
-
-/** @public */
-export const Inline = forwardRef((props, ref) => {
- const {
- as = 'div',
- children,
- align = 'left',
- alignY = 'top',
- gap = 'xs',
- className,
- style,
- ...restProps
- } = props;
-
- // Generate utility class names
- const utilityClassNames = getClassNames({
- gap,
- alignItems: mapAlignYValue(alignY),
- justifyContent: mapAlignValue(align),
- ...restProps,
- });
-
- return createElement(as, {
- ref,
- className: clsx('canon-Inline', utilityClassNames, className),
- style,
- children,
- });
-});
diff --git a/packages/canon/src/components/Inline/index.ts b/packages/canon/src/components/Inline/index.ts
deleted file mode 100644
index 2cc100c02a..0000000000
--- a/packages/canon/src/components/Inline/index.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2024 The Backstage Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export { Inline } from './Inline';
-export type { InlineProps } from './types';
diff --git a/packages/canon/src/components/Inline/styles.css b/packages/canon/src/components/Inline/styles.css
deleted file mode 100644
index d68ee9dcbd..0000000000
--- a/packages/canon/src/components/Inline/styles.css
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2024 The Backstage Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-.canon-Inline {
- display: flex;
- flex-wrap: wrap;
-}
diff --git a/packages/canon/src/components/Inline/types.ts b/packages/canon/src/components/Inline/types.ts
deleted file mode 100644
index c86f500018..0000000000
--- a/packages/canon/src/components/Inline/types.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2024 The Backstage Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import type {
- SpaceProps,
- UtilityProps,
- AsProps,
- Breakpoint,
-} from '../../types';
-
-/** @public */
-export interface InlineProps extends SpaceProps {
- children: React.ReactNode;
- as?: AsProps;
- gap?: UtilityProps['gap'];
- align?:
- | 'left'
- | 'center'
- | 'right'
- | Partial>;
- alignY?:
- | 'top'
- | 'center'
- | 'bottom'
- | Partial>;
- className?: string;
- style?: React.CSSProperties;
-}
diff --git a/packages/canon/src/components/Input/Input.stories.tsx b/packages/canon/src/components/Input/Input.stories.tsx
index a215162688..c1c76ddc09 100644
--- a/packages/canon/src/components/Input/Input.stories.tsx
+++ b/packages/canon/src/components/Input/Input.stories.tsx
@@ -17,7 +17,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Input } from './Input';
-import { Inline } from '../Inline';
+import { Flex } from '../Flex';
const meta = {
title: 'Components/Input',
@@ -33,9 +33,9 @@ export const Primary: Story = {
export const Sizes: Story = {
render: () => (
-
+
-
+
),
};
diff --git a/packages/canon/src/css/utilities/flex.css b/packages/canon/src/css/utilities/flex.css
index fb69f57aee..5311aac3e8 100644
--- a/packages/canon/src/css/utilities/flex.css
+++ b/packages/canon/src/css/utilities/flex.css
@@ -14,6 +14,22 @@
align-items: stretch;
}
+.cu-jc-start {
+ justify-content: start;
+}
+
+.cu-jc-center {
+ justify-content: center;
+}
+
+.cu-jc-end {
+ justify-content: end;
+}
+
+.cu-jc-between {
+ justify-content: space-between;
+}
+
.cu-fd-row {
flex-direction: row;
}
@@ -48,6 +64,22 @@
align-items: stretch;
}
+ .xs\:cu-jc-start {
+ justify-content: start;
+ }
+
+ .xs\:cu-jc-center {
+ justify-content: center;
+ }
+
+ .xs\:cu-jc-end {
+ justify-content: end;
+ }
+
+ .xs\:cu-jc-between {
+ justify-content: space-between;
+ }
+
.xs\:cu-fd-row {
flex-direction: row;
}
@@ -83,6 +115,22 @@
align-items: stretch;
}
+ .sm\:cu-jc-start {
+ justify-content: start;
+ }
+
+ .sm\:cu-jc-center {
+ justify-content: center;
+ }
+
+ .sm\:cu-jc-end {
+ justify-content: end;
+ }
+
+ .sm\:cu-jc-between {
+ justify-content: space-between;
+ }
+
.sm\:cu-fd-row {
flex-direction: row;
}
@@ -118,6 +166,22 @@
align-items: stretch;
}
+ .md\:cu-jc-start {
+ justify-content: start;
+ }
+
+ .md\:cu-jc-center {
+ justify-content: center;
+ }
+
+ .md\:cu-jc-end {
+ justify-content: end;
+ }
+
+ .md\:cu-jc-between {
+ justify-content: space-between;
+ }
+
.md\:cu-fd-row {
flex-direction: row;
}
@@ -153,6 +217,22 @@
align-items: stretch;
}
+ .lg\:cu-jc-start {
+ justify-content: start;
+ }
+
+ .lg\:cu-jc-center {
+ justify-content: center;
+ }
+
+ .lg\:cu-jc-end {
+ justify-content: end;
+ }
+
+ .lg\:cu-jc-between {
+ justify-content: space-between;
+ }
+
.lg\:cu-fd-row {
flex-direction: row;
}
@@ -188,6 +268,22 @@
align-items: stretch;
}
+ .xl\:cu-jc-start {
+ justify-content: start;
+ }
+
+ .xl\:cu-jc-center {
+ justify-content: center;
+ }
+
+ .xl\:cu-jc-end {
+ justify-content: end;
+ }
+
+ .xl\:cu-jc-between {
+ justify-content: space-between;
+ }
+
.xl\:cu-fd-row {
flex-direction: row;
}