diff --git a/package.json b/package.json index d134d8c32..4f3d7672e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,10 @@ "version": "0.47.3", "main": "dist/index.js", "module": "dist/index.js", - "author": "Huw Wilkins ", + "author": { + "email": "webteam@canonical.com", + "name": "Canonical Webteam" + }, "license": "LGPL-3.0", "files": [ "dist/**/*.js", diff --git a/src/components/ApplicationLayout/AppAside/AppAside.stories.tsx b/src/components/ApplicationLayout/AppAside/AppAside.stories.tsx new file mode 100644 index 000000000..64dbe67b4 --- /dev/null +++ b/src/components/ApplicationLayout/AppAside/AppAside.stories.tsx @@ -0,0 +1,139 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +import React, { useState } from "react"; +import type { Meta, StoryObj } from "@storybook/react"; + +import Application from "components/ApplicationLayout/Application"; +import AppMain from "components/ApplicationLayout/AppMain"; +import Button from "components/Button"; +import Col from "components/Col"; +import Form from "components/Form"; +import Icon from "components/Icon"; +import Input from "components/Input"; +import Panel from "components/Panel"; +import Row from "components/Row"; + +import AppAside from "./AppAside"; + +const meta: Meta = { + component: AppAside, + tags: ["autodocs"], + argTypes: { + children: { + control: false, + }, + }, +}; + +export default meta; + +type Story = StoryObj; + +/** + * In most common cases an `AppAside` should contain a `` to display the + * content as intended in the application layout. + * + * `AppAside` should be a direct child of an `` or passed to the + * application layout `}>`. + */ +export const Default: Story = { + render: (args) => { + const [pinned, setPinned] = useState(false); + const [width, setWidth] = useState(null); + const [collapsed, setCollapsed] = useState(false); + return ( + + +

Scroll to the right to see the panel.

+ + + + +
+ + + + + + } + title="App aside" + > +
+ + + + + + + + + + +
+
+
+
+ ); + }, +}; diff --git a/src/components/ApplicationLayout/AppAside/AppAside.test.tsx b/src/components/ApplicationLayout/AppAside/AppAside.test.tsx new file mode 100644 index 000000000..e746e7562 --- /dev/null +++ b/src/components/ApplicationLayout/AppAside/AppAside.test.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import { render, screen } from "@testing-library/react"; + +import AppAside from "./AppAside"; + +it("displays collapsed", async () => { + render(Content); + expect(screen.queryByRole("complementary")).toHaveClass("is-collapsed"); +}); + +it("displays as narrow", async () => { + render(Content); + expect(screen.queryByRole("complementary")).toHaveClass("is-narrow"); +}); + +it("displays pinned", async () => { + render(Content); + expect(screen.queryByRole("complementary")).toHaveClass("is-pinned"); +}); + +it("displays as wide", async () => { + render(Content); + expect(screen.queryByRole("complementary")).toHaveClass("is-wide"); +}); diff --git a/src/components/ApplicationLayout/AppAside/AppAside.tsx b/src/components/ApplicationLayout/AppAside/AppAside.tsx new file mode 100644 index 000000000..2cb15b63e --- /dev/null +++ b/src/components/ApplicationLayout/AppAside/AppAside.tsx @@ -0,0 +1,63 @@ +import React from "react"; +import type { PropsWithSpread } from "types"; +import classNames from "classnames"; +import { type HTMLProps, type PropsWithChildren } from "react"; + +export type Props = PropsWithSpread< + { + /** + * Whether the aside panel should be collapsed. Toggling this state will animate + * the panel open or closed. + */ + collapsed?: boolean; + /** + * The panel content. + */ + children?: PropsWithChildren["children"]; + /** + * A ref that will be passed to the wrapping `