Skip to content

Commit

Permalink
feat: Center and Stack atoms (#277)
Browse files Browse the repository at this point in the history
* feat: `Center` and `Stack` atoms
  • Loading branch information
alexgoff committed Sep 24, 2024
1 parent 347eccd commit 40560e0
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 5 deletions.
67 changes: 67 additions & 0 deletions packages/epo-react-lib/src/atomic/Center/Center.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Meta, StoryFn, StoryObj } from "@storybook/react";

import Center from ".";
import { FunctionComponent } from "react";
import Stack from "../Stack";

const meta: Meta<typeof Center> = {
component: Center,
argTypes: {
maxWidth: { control: "text" },
andText: { control: "boolean" },
intrinsic: { control: "boolean" },
gutter: { control: "text" },
},
};
export default meta;

const Iterator: FunctionComponent<{
backgroundColor?: string;
iterables: Array<number | Array<number>>;
}> = ({ backgroundColor = "var(--color-rubin-teal-400)", iterables }) => {
return iterables.map((iteration, i) => {
const hasChildren = Array.isArray(iteration);
return (
<div
key={i}
style={
hasChildren
? {}
: {
backgroundColor,
borderRadius: "var(--size-spacing-2xs)",
color: "var(--color-font-invert)",
padding: "var(--size-spacing-s)",
}
}
>
{hasChildren ? (
<Iterator
backgroundColor="var(--color-rubin-teal-200)"
iterables={iteration}
/>
) : (
iteration
)}
</div>
);
});
};

const Template: StoryFn<typeof Center> = (args) => {
const iterables = [1, 2, 3, 4, 5, 6];

return (
<Center {...args}>
<Stack>
<Iterator {...{ iterables }} />
</Stack>
</Center>
);
};

export const Primary: StoryObj<typeof Center> = Template.bind({});

Primary.args = {
maxWidth: "60ch",
};
38 changes: 38 additions & 0 deletions packages/epo-react-lib/src/atomic/Center/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { FunctionComponent, PropsWithChildren } from "react";
import * as Styled from "./styles";

export interface CenterProps {
/** The maximum width of the centered element */
maxWidth?: string;
/** Whether to apply `text-align: center` too */
andText?: boolean;
/** The width of the gutters (leave empty for no gutters) */
gutter?: string;
/** Whether to center and child elements narrower than the max value */
intrinsic?: boolean;
className?: string;
}

const Center: FunctionComponent<PropsWithChildren<CenterProps>> = ({
maxWidth = "auto",
andText,
gutter = "0",
intrinsic,
className,
children,
}) => {
return (
<Styled.Center
data-center-text={andText}
data-intrinsic={intrinsic}
style={{ "--size-width-center": maxWidth, "--size-gutters": gutter }}
className={className}
>
{children}
</Styled.Center>
);
};

Center.displayName = "Atom.Center";

export default Center;
19 changes: 19 additions & 0 deletions packages/epo-react-lib/src/atomic/Center/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use client";
import styled from "styled-components";

export const Center = styled.div`
box-sizing: content-box;
margin-inline: auto;
max-inline-size: var(--size-width-center);
padding-inline: var(--size-gutters);
&[data-center-text="true"] {
text-align: center;
}
&[data-intrinsic="true"] {
display: flex;
flex-direction: column;
align-items: center;
}
`;
54 changes: 54 additions & 0 deletions packages/epo-react-lib/src/atomic/Stack/Stack.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Meta, StoryFn, StoryObj } from "@storybook/react";

import Stack from ".";
import { FunctionComponent } from "react";

const meta: Meta<typeof Stack> = {
component: Stack,
};
export default meta;

const Iterator: FunctionComponent<{
backgroundColor?: string;
iterables: Array<number | Array<number>>;
}> = ({ backgroundColor = "var(--color-rubin-teal-400)", iterables }) => {
return iterables.map((iteration, i) => {
const hasChildren = Array.isArray(iteration);
return (
<div
key={i}
style={
hasChildren
? {}
: {
backgroundColor,
borderRadius: "var(--size-spacing-2xs)",
color: "var(--color-font-invert)",
padding: "var(--size-spacing-s)",
}
}
>
{hasChildren ? (
<Iterator
backgroundColor="var(--color-rubin-teal-200)"
iterables={iteration}
/>
) : (
iteration
)}
</div>
);
});
};

const Template: StoryFn<typeof Stack> = (args) => {
const iterables = [1, 2, 3, [3.1, 3.2], 4, 5, 6];

return (
<Stack {...args}>
<Iterator {...{ iterables }} />
</Stack>
);
};

export const Primary: StoryObj<typeof Stack> = Template.bind({});
33 changes: 33 additions & 0 deletions packages/epo-react-lib/src/atomic/Stack/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { FunctionComponent, PropsWithChildren } from "react";
import * as Styled from "./styles";

export interface StackProps {
/** A CSS `margin` value */
space?: string;
/** Whether the spaces apply recursively (i.e. regardless of nesting level) */
recursive?: boolean;
className?: string;
}

const Stack: FunctionComponent<PropsWithChildren<StackProps>> = ({
space = "var(--size-spacing-s)",
recursive = false,
className,
children,
}) => {
return (
<Styled.Stack
style={{
"--size-spacing-stack": space,
}}
data-recursive={recursive}
className={className}
>
{children}
</Styled.Stack>
);
};

Stack.displayName = "Atom.Stack";

export default Stack;
28 changes: 28 additions & 0 deletions packages/epo-react-lib/src/atomic/Stack/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client";
import styled from "styled-components";

export const Stack = styled.div`
display: flex;
flex-direction: column;
justify-content: flex-start;
&[data-recursive="true"] {
* {
margin-block: 0;
}
* + * {
margin-block-start: var(--size-spacing-stack, 1rem);
}
}
&[data-recursive="false"] {
> * {
margin-block: 0;
}
> * + * {
margin-block-start: var(--size-spacing-stack, 1rem);
}
}
`;
1 change: 1 addition & 0 deletions packages/epo-react-lib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export { default as ResponsiveImage } from "@/atomic/ResponsiveImage";
export * from "@/atomic/Share";
export { default as Toast } from "@/atomic/Toast";
export { default as Video } from "@/atomic/Video";
export { default as Stack } from "@/atomic/Stack";

// Content Blocks
export { default as SimpleTable } from "@/content-blocks/SimpleTable";
Expand Down
7 changes: 2 additions & 5 deletions packages/epo-react-lib/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import postcss from "./postcss.config";
const defaultFormat = "es";

const packages = Object.fromEntries(
sync(["src/molecules/**/*.tsx"], {
sync(["src/atomic/*/index.tsx", "src/molecules/*/*.tsx"], {
ignore: ["src/**/*.stories.tsx", "src/**/*.test.tsx"],
}).map((file) => {
const path = resolve(__dirname, file);
Expand All @@ -32,7 +32,6 @@ const entry = {
ExpandToggle: resolve(__dirname, "src/atomic/ExpandToggle/ExpandToggle.tsx"),
ExternalLink: resolve(__dirname, "src/atomic/ExternalLink/ExternalLink.tsx"),
Figure: resolve(__dirname, "src/atomic/Figure/Figure.tsx"),
Image: resolve(__dirname, "src/atomic/Image/index.tsx"),
Link: resolve(__dirname, "src/atomic/Link/Link.tsx"),
MixedLink: resolve(__dirname, "src/atomic/MixedLink/MixedLink.tsx"),
ProgressBar: resolve(__dirname, "src/atomic/Progress/Bar/ProgressBar.tsx"),
Expand All @@ -47,7 +46,6 @@ const entry = {
),
Share: resolve(__dirname, "src/atomic/Share"),
Toast: resolve(__dirname, "src/atomic/Toast/Toast.tsx"),
Video: resolve(__dirname, "src/atomic/Video/index.tsx"),
SimpleTable: resolve(
__dirname,
"src/content-blocks/SimpleTable/SimpleTable.tsx"
Expand Down Expand Up @@ -77,8 +75,6 @@ const entry = {
SlideoutMenu: resolve(__dirname, "src/layout/SlideoutMenu"),
IconComposer: resolve(__dirname, "src/svg/IconComposer/index.tsx"),
icons: resolve(__dirname, "src/svg/icons"),
Slideout: resolve(__dirname, "src/atomic/Slideout/index.tsx"),
Picture: resolve(__dirname, "src/atomic/Picture/index.tsx"),
...packages,
};

Expand Down Expand Up @@ -136,6 +132,7 @@ export default defineConfig({
external: [
"@castiron/style-mixins",
"@headlessui/react",
"classnames",
"flickity",
"focus-trap",
"i18next",
Expand Down

0 comments on commit 40560e0

Please sign in to comment.