Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Admin UI - Grid / Column Components #4252

Merged
merged 18 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/admin-ui/src/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const meta: Meta<typeof Button> = {
export default meta;
type Story = StoryObj<typeof Button>;

// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
args: {
variant: "primary",
Expand Down
3 changes: 0 additions & 3 deletions packages/admin-ui/src/Card/Card.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ import type { Meta, StoryObj } from "@storybook/react";

import { Card, CardContent, CardFooter, CardHeader } from "./Card";

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta: Meta<typeof Card> = {
title: "Components/Card",
component: Card,
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"]
};

Expand All @@ -21,7 +19,6 @@ const defaultContentProps = {
footer: <CardFooter content={"This is card footer. Anything can go in here."} />
};

// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Default: Story = {
args: {
...defaultContentProps,
Expand Down
89 changes: 89 additions & 0 deletions packages/admin-ui/src/Grid/Grid.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";

import { Grid } from "./Grid";

const meta: Meta<typeof Grid> = {
title: "Components/Grid",
component: Grid,
tags: ["autodocs"]
};

export default meta;

type Story = StoryObj<typeof Grid>;

const StyledColumn = ({ ...props }) => (
<Grid.Column className="bg-primary text-neutral-light p-2 text-md rounded-sm" {...props} />
);

export const Default: Story = {
args: {
className: "bg-neutral-light p-4",
children: (
<>
<StyledColumn>Col 1</StyledColumn>
<StyledColumn span={3}>
Col 2 (<code>span: 3</code>)
</StyledColumn>
<StyledColumn>Col 3</StyledColumn>
<StyledColumn>Col 4</StyledColumn>
<StyledColumn>Col 5</StyledColumn>
<StyledColumn>Col 6</StyledColumn>
<StyledColumn span={2}>
Col 7 (<code>span: 2</code>)
</StyledColumn>
<StyledColumn>Col 8</StyledColumn>
<StyledColumn>Col 9</StyledColumn>
</>
)
}
};

export const SpaciousGap: Story = {
args: {
...Default.args,
gap: "spacious"
}
};

export const WithOffset: Story = {
parameters: {
layout: "padded"
},
decorators: [
Story => (
<div className="w-full">
<Story />
</div>
)
],
args: {
...Default.args,
children: (
<>
{/* Row 1 */}
<StyledColumn span={8} offset={2}>
Col (<code>span: 8</code>, <code>offset: 2</code>)
</StyledColumn>
<Grid.Column span={2} />

{/* Row 2 */}
<StyledColumn span={8} offset={4}>
Col (<code>span: 8</code>, <code>offset: 4</code>)
</StyledColumn>

{/* Row 3 */}
<StyledColumn span={10} offset={1}>
Col (<code>span: 10</code>, <code>offset: 1</code>)
</StyledColumn>
<Grid.Column span={1} />

{/* Row 4 */}
<StyledColumn span={12}>
Col (<code>span: 12</code>)
</StyledColumn>
</>
)
}
};
111 changes: 111 additions & 0 deletions packages/admin-ui/src/Grid/Grid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import React from "react";
import { makeDecoratable } from "@webiny/react-composition";
import { cva, type VariantProps } from "class-variance-authority";
import { cn, withStaticProps } from "~/utils";

const columnVariants = cva("", {
variants: {
span: {
auto: "col-auto",
1: "col-span-1",
2: "col-span-2",
3: "col-span-3",
4: "col-span-4",
5: "col-span-5",
6: "col-span-6",
7: "col-span-7",
8: "col-span-8",
9: "col-span-9",
10: "col-span-10",
11: "col-span-11",
12: "col-span-12"
},
offset: {
1: "col-start-2",
2: "col-start-3",
3: "col-start-4",
4: "col-start-5",
5: "col-start-6",
6: "col-start-7",
7: "col-start-8",
8: "col-start-9",
9: "col-start-10",
10: "col-start-11",
11: "col-start-12"
},
align: {
top: "self-start",
middle: "self-center",
bottom: "self-end"
}
},
defaultVariants: {
span: "auto"
}
});

interface ColumnProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof columnVariants> {
children?: React.ReactNode;
}

const ColumnBase = React.forwardRef<HTMLDivElement, ColumnProps>(
({ span, align, children, className, offset, ...props }, ref) => {
return (
<div
{...props}
className={cn(columnVariants({ span, offset, align, className }))}
ref={ref}
>
{children}
</div>
);
}
);

ColumnBase.displayName = "Column";

const Column = makeDecoratable("Column", ColumnBase);

const gridVariants = cva("grid", {
variants: {
gap: {
comfortable: "gap-lg",
spacious: "gap-xl"
}
},
defaultVariants: {
gap: "comfortable"
}
});

interface GridProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof gridVariants> {
children:
| React.ReactElement<ColumnProps, typeof Column>
| Array<React.ReactElement<ColumnProps, typeof Column>>;
}

const GridBase = React.forwardRef<HTMLDivElement, GridProps>(
({ gap, children, className, ...props }, ref) => {
return (
<div
{...props}
className={cn("grid-cols-12", gridVariants({ gap }), className)}
ref={ref}
>
{children}
</div>
);
}
);

GridBase.displayName = "Grid";

const DecoratableGrid = makeDecoratable("Grid", GridBase);

const Grid = withStaticProps(DecoratableGrid, { Column });

export { Grid, type GridProps, type ColumnProps };
1 change: 1 addition & 0 deletions packages/admin-ui/src/Grid/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./Grid";
2 changes: 1 addition & 1 deletion packages/admin-ui/src/Heading/Heading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const TAG_MAP: Record<HeadingLevels, HeadingTags> = {
6: "h6"
};

const headingVariants = cva("font-sans font-semibold", {
const headingVariants = cva("font-sans", {
variants: {
level: {
1: "text-h1",
Expand Down
2 changes: 0 additions & 2 deletions packages/admin-ui/src/Icon/Icon.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ import type { Meta, StoryObj } from "@storybook/react";
import { ReactComponent as XIcon } from "@material-design-icons/svg/filled/close.svg";
import { Icon } from "./Icon";

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta: Meta<typeof Icon> = {
title: "Components/Icon",
component: Icon,
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"]
};

Expand Down
2 changes: 1 addition & 1 deletion packages/admin-ui/src/Text/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { cn } from "~/utils";

type TextTags = "span" | "div";

const textVariants = cva("font-sans font-normal", {
const textVariants = cva("font-sans", {
variants: {
size: {
xl: "text-xl",
Expand Down
1 change: 1 addition & 0 deletions packages/admin-ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from "./Alert";
export * from "./Avatar";
export * from "./Button";
export * from "./Card";
export * from "./Grid";
export * from "./Heading";
export * from "./Input";
export * from "./Label";
Expand Down
9 changes: 7 additions & 2 deletions packages/ui/src/Elevation/Elevation.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import cn from "classnames";

export type ElevationProps = {
// Any element that needs to be highlighted.
Expand All @@ -21,8 +22,12 @@ export type ElevationProps = {
* @deprecated This component is deprecated and will be removed in future releases.
* Please use the `Card` component from the `@webiny/admin-ui` package instead.
*/
const Elevation = (props: ElevationProps) => {
return <div className={"bg-white shadow-md p-4"}>{props.children}</div>;
const Elevation = ({ className, ...props }: ElevationProps) => {
return (
<div {...props} className={cn("bg-white shadow-md p-4", className)}>
{props.children}
</div>
);
};

Elevation.displayName = "Elevation";
Expand Down
52 changes: 36 additions & 16 deletions packages/ui/src/Grid/Grid.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import React from "react";
import {
Grid as RmwcGrid,
GridCell as RmwcGridCell,
GridRow as RmwcGridInner,
GridCellProps as RmwcGridCellProps,
GridProps as RmwcGridProps
} from "@rmwc/grid";
import cn from "classnames";
import { GridCellProps as RmwcGridCellProps, GridProps as RmwcGridProps } from "@rmwc/grid";
import { CSSProperties } from "react";

import { Grid as AdminUiGrid, ColumnProps as AdminUiColumnProps } from "@webiny/admin-ui";

export type CellProps = RmwcGridCellProps & {
// One or more Cell components.
children?: React.ReactNode;
Expand All @@ -18,16 +15,21 @@ export type CellProps = RmwcGridCellProps & {
style?: { [key: string]: any };
};

export type GridProps = RmwcGridProps & {
className?: string;
style?: CSSProperties;
};

/**
* Cell must be direct children of Grid component.
*/
export const Cell = (props: CellProps) => {
return <RmwcGridCell {...props}>{props.children}</RmwcGridCell>;
const { children, style, className, align } = props;
return (
<AdminUiGrid.Column
className={className}
style={style}
span={props.span as AdminUiColumnProps["span"]}
align={align}
>
{children}
</AdminUiGrid.Column>
);
};

export type GridInnerProps = {
Expand All @@ -40,15 +42,33 @@ export type GridInnerProps = {
className?: string;
};

export const GridInner = (props: GridInnerProps) => {
return <RmwcGridInner {...props}>{props.children}</RmwcGridInner>;
export const GridInner = ({ className, ...props }: GridInnerProps) => {
return (
<div
{...props}
className={cn("grid grid-cols-12 gap-6 m-0 flex flex-wrap items-stretch", className)}
>
{props.children}
</div>
);
};

GridInner.displayName = "GridInner";

export type GridProps = RmwcGridProps & {
className?: string;
style?: CSSProperties;
};

/**
* Use Grid component to display a list of choices, once the handler is triggered.
*/
export const Grid = (props: GridProps) => {
return <RmwcGrid {...props}>{props.children}</RmwcGrid>;
const { children, style, className } = props;

return (
<AdminUiGrid className={className} style={style}>
{children as React.ReactElement<AdminUiColumnProps, typeof AdminUiGrid.Column>}
</AdminUiGrid>
);
};
15 changes: 1 addition & 14 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2414,20 +2414,7 @@ __metadata:
languageName: node
linkType: hard

"@babel/generator@npm:^7.23.0":
version: 7.26.2
resolution: "@babel/generator@npm:7.26.2"
dependencies:
"@babel/parser": ^7.26.2
"@babel/types": ^7.26.0
"@jridgewell/gen-mapping": ^0.3.5
"@jridgewell/trace-mapping": ^0.3.25
jsesc: ^3.0.2
checksum: 6ff850b7d6082619f8c2f518d993cf7254cfbaa20b026282cbef5c9b2197686d076a432b18e36c4d1a42721c016df4f77a8f62c67600775d9683621d534b91b4
languageName: node
linkType: hard

"@babel/generator@npm:^7.25.9, @babel/generator@npm:^7.26.0":
"@babel/generator@npm:^7.23.0, @babel/generator@npm:^7.25.9, @babel/generator@npm:^7.26.0":
version: 7.26.2
resolution: "@babel/generator@npm:7.26.2"
dependencies:
Expand Down