-
+
{mainIcon}
@@ -31,15 +31,13 @@ export const InkLayout: React.FC
= ({
{headerContent}
) : null}
-
+
{sideNavigation && (
{sideNavigation}
)}
-
- {children}
-
+ {children}
);
diff --git a/src/layout/InkParts/InkHeader.stories.tsx b/src/layout/InkParts/InkHeader.stories.tsx
new file mode 100644
index 0000000..a1198c6
--- /dev/null
+++ b/src/layout/InkParts/InkHeader.stories.tsx
@@ -0,0 +1,35 @@
+import type { Meta, StoryObj } from "@storybook/react";
+import { InkHeader, InkHeaderProps } from "./InkHeader";
+import { InkIcon } from "../..";
+
+/**
+ * This component provides a unified header that can be used at the top of a page or a modal.
+ */
+const meta: Meta
= {
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+ title: "Layouts/InkHeader",
+ component: InkHeader,
+ tags: ["autodocs"],
+ args: {
+ title: "Example Title",
+ },
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Simple: Story = {
+ args: {},
+};
+
+export const WithIcon: Story = {
+ args: {
+ icon: ,
+ },
+};
diff --git a/src/layout/InkParts/InkHeader.tsx b/src/layout/InkParts/InkHeader.tsx
new file mode 100644
index 0000000..7608d80
--- /dev/null
+++ b/src/layout/InkParts/InkHeader.tsx
@@ -0,0 +1,26 @@
+import { PropsWithChildren } from "react";
+import { classNames } from "../../util/classes";
+
+export interface InkHeaderProps extends PropsWithChildren {
+ title: React.ReactNode;
+ children?: React.ReactNode;
+ icon?: React.ReactNode;
+}
+
+export const InkHeader: React.FC = ({
+ title,
+ icon,
+ children,
+}) => {
+ return (
+
+
{title}
+ {children}
+
{icon}
+
+ );
+};
diff --git a/src/layout/InkParts/InkPageLayout.stories.tsx b/src/layout/InkParts/InkPageLayout.stories.tsx
new file mode 100644
index 0000000..77ce9f9
--- /dev/null
+++ b/src/layout/InkParts/InkPageLayout.stories.tsx
@@ -0,0 +1,49 @@
+import type { Meta, StoryObj } from "@storybook/react";
+import { InkPageLayout, InkPageLayoutProps } from "./InkPageLayout";
+import { InkLayout } from "../InkLayout";
+import { ExampleDynamicContent } from "../ForStories/ExampleDynamicContent";
+
+/**
+ * This component provides a column layout for a page.
+ * The `columns` prop determines the number of columns to display. You must then pass the same number of children to the component.
+ *
+ * Note that the `InkLayout` component is included only as an example. It is not required for this component to function.
+ */
+const meta: Meta = {
+ parameters: {
+ layout: "fullscreen",
+ },
+ decorators: [
+ (Story, { args }) => (
+ Side Navigation}
+ headerContent={
Header Content
}
+ >
+
+ ),
+ }}
+ />
+
+ ),
+ ],
+ title: "Layouts/InkPageLayout",
+ component: InkPageLayout,
+ tags: ["autodocs"],
+ args: {
+ columns: 1,
+ },
+};
+
+export default meta;
+type Story = StoryObj
;
+
+export const Simple: Story = {
+ args: {},
+};
diff --git a/src/layout/InkParts/InkPageLayout.tsx b/src/layout/InkParts/InkPageLayout.tsx
new file mode 100644
index 0000000..35d9a8a
--- /dev/null
+++ b/src/layout/InkParts/InkPageLayout.tsx
@@ -0,0 +1,27 @@
+import { PropsWithChildren } from "react";
+import { classNames, variantClassNames } from "../../util/classes";
+
+export interface InkPageLayoutProps extends PropsWithChildren {
+ columns?: 1 | 2 | 3;
+}
+
+export const InkPageLayout: React.FC = ({
+ columns = 1,
+ children,
+}) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/layout/InkParts/InkPanel.stories.tsx b/src/layout/InkParts/InkPanel.stories.tsx
new file mode 100644
index 0000000..870254e
--- /dev/null
+++ b/src/layout/InkParts/InkPanel.stories.tsx
@@ -0,0 +1,59 @@
+import type { Meta, StoryObj } from "@storybook/react";
+import { InkHeader, InkIcon, InkPanel, InkPanelProps } from "../..";
+
+/**
+ * This component provides a simple layout container with a header and a content area.
+ */
+const meta: Meta = {
+ title: "Layouts/InkPanel",
+ component: InkPanel,
+ tags: ["autodocs"],
+ args: {
+ size: "md",
+ children: (
+ <>
+ }
+ />
+ And then some text here, how fun! And some more!
+ Some footer
+ >
+ ),
+ },
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Simple: Story = {
+ args: {},
+};
+
+/**
+ * Centering the content will make the content centered, but the header will still be at the top.
+ */
+export const Centered: Story = {
+ args: {
+ centered: true,
+ },
+};
+
+/**
+ * The automatic size will make the panel take space depending on the content.
+ */
+export const AutomaticSize: Story = {
+ args: {
+ size: "auto",
+ },
+};
+
+/**
+ * Centering the content will make the content centered, but the header will still be at the top.
+ */
+export const CenteredWithoutHeader: Story = {
+ args: {
+ centered: true,
+ children: Just some content here
,
+ },
+};
diff --git a/src/layout/InkParts/InkPanel.tsx b/src/layout/InkParts/InkPanel.tsx
new file mode 100644
index 0000000..8757119
--- /dev/null
+++ b/src/layout/InkParts/InkPanel.tsx
@@ -0,0 +1,36 @@
+import { PropsWithChildren } from "react";
+import { classNames, variantClassNames } from "../../util/classes";
+import { forwardRef } from "react";
+
+export interface InkPanelProps extends PropsWithChildren {
+ className?: string;
+ size?: "auto" | "lg" | "md";
+ centered?: boolean;
+}
+
+export const InkPanel = forwardRef(
+ ({ className, size = "auto", centered = false, children }, ref) => {
+ return (
+
+ {children}
+
+ );
+ }
+);
diff --git a/src/layout/InkParts/index.ts b/src/layout/InkParts/index.ts
new file mode 100644
index 0000000..5742719
--- /dev/null
+++ b/src/layout/InkParts/index.ts
@@ -0,0 +1,3 @@
+export * from "./InkHeader";
+export * from "./InkPageLayout";
+export * from "./InkPanel";
diff --git a/src/layout/index.ts b/src/layout/index.ts
index 5fb61ac..18ed428 100644
--- a/src/layout/index.ts
+++ b/src/layout/index.ts
@@ -1 +1,2 @@
export * from "./InkLayout";
+export * from "./InkParts";
diff --git a/src/util/classes.ts b/src/util/classes.ts
index e36540f..3de393f 100644
--- a/src/util/classes.ts
+++ b/src/util/classes.ts
@@ -65,7 +65,7 @@ export function classNames(...classes: ClassValue[]) {
return customTwMerge(clsx(...classes));
}
-export function variantClassNames(
+export function variantClassNames(
variant: T,
classes: Required>
) {