Yamada UIを使ってどうしてもMantineのAppShellを作りたかっただけ
こんにちは!普段フロントエンド開発をしている人です🙌
最近はUI作成時によくMantineを使用しているのですが、Yamada UIもずうううっと気になっていたので触ってみたところ…
「え、AppShellない…🥺」ってなりました。
AppShellってなんだよって方はこちら→Mantineのドキュメント
もうちょこっと書けばアプリケーションの枠組みができる状態から開発するのに慣れていたため、1から書くのはめんどくさい…ので!
自分でAppShellっぽいもの作っておけばあとはパラメータ足すだけでいいやんって感じでゆるーく作りました。
まずはみんな大好きYamada UIのご紹介
日本初のReact UIコンポーネントライブラリです。概要は以下の開発者の山田さんが説明してくださっている記事があるのでそちらに飛んでみてください!
ドキュメントはこちら↓
英語さっぱりの私でも読める日本語ドキュメントでとっても助かってます!
Discordにしれっと参加しているのですが、結構頻繁に活動されている様子。(というか山田さんずっとmeeting roomにいる気がする)
私は眺めているだけなので、今回AppShell作って欲しいっていう文句言うだけの人になってます…許して
今回作成したもの
文句を言うだけの懺悔をしながら実際に作ってみたコードを紹介します。
import { AlignJustifyIcon } from "@yamada-ui/lucide";
import { Box, Collapse, Flex, IconButton } from "@yamada-ui/react";
import React, { useState } from "react";
export type AppshellProps = {
header?: React.ReactNode;
navBar?: React.ReactNode;
asideBar?: React.ReactNode;
headerHeight?: number | string;
navBarWidth?: number | string;
asideBarWidth?: number | string;
} & React.PropsWithChildren;
export const AppShell = (props: AppshellProps) => {
const {
header,
navBar,
asideBar,
children,
headerHeight,
navBarWidth,
asideBarWidth,
} = props;
const [opened, setOpened] = useState<boolean>(true);
return (
<Flex style={{ flexDirection: "column", width: "100%", height: "100%" }}>
{header && (
<Flex
style={{
width: "100%",
height: headerHeight ?? "40px",
borderBottom: "1px solid lightgray",
}}
>
{(navBar || asideBar) && (
<IconButton
icon={<AlignJustifyIcon />}
variant={"link"}
onClick={() => {
setOpened(!opened);
}}
style={{ width: "36px", height: "36px", margin: "auto 0" }}
/>
)}
<Box style={{ width: "calc(100% - 36px)", height: "100%" }}>
{header}
</Box>
</Flex>
)}
<Flex
style={{
width: "100%",
height: `calc(100% - ${headerHeight ?? "40px"})`,
}}
>
{navBar && (
<Collapse isOpen={opened} w={opened ? navBarWidth ?? "200px" : 0}>
<Box
style={{
width: "100%",
borderRight: "1px solid lightgray",
height: "100%",
}}
>
{navBar}
</Box>
</Collapse>
)}
<Box style={{ flex: 1 }}>{children}</Box>
{asideBar && (
<Collapse isOpen={opened} w={opened ? asideBarWidth ?? "200px" : 0}>
<Box
style={{
width: "100%",
borderLeft: "1px solid lightgray",
}}
>
{asideBar}
</Box>
</Collapse>
)}
</Flex>
</Flex>
);
};
実際に使ってみたらこんな感じ
import { Button, Flex, IconButton, Text, useColorMode } from "@yamada-ui/react";
import { AppShell } from "../components";
import { MoonIcon, SunIcon } from "@yamada-ui/lucide";
export const ContainerApp = () => {
const { colorMode, changeColorMode } = useColorMode();
return (
<AppShell
header={
<Flex w={"100%"} p={"0 0.5rem"} h={"100%"} justify={"space-between"}>
<Text m={"auto 0"}>これはタイトルです</Text>
<IconButton
icon={colorMode === "dark" ? <MoonIcon /> : <SunIcon />}
onClick={() =>
changeColorMode(colorMode === "light" ? "dark" : "light")
}
variant={"outline"}
w={"36px"}
h={"36px"}
m={"auto 0"}
/>
</Flex>
}
navBar={
<Flex w={"100%"} h={"100%"} direction={"column"}>
{Array.from({ length: 10 }).map((_, i) => (
<Button key={`navButton-${i}`} variant={"ghost"}>
navButton-{i + 1}
</Button>
))}
</Flex>
}
>
<Flex bg={"#79B6EB"} w={"100%"} h={"100%"}>
ここはmainComponentです
</Flex>
</AppShell>
);
};
どちらでもできるよ的な感じを伝えたかったため、styleの書き方はあえて統一していません。
普段からこんな汚いコード書いているのかよって思わないでください…もっと綺麗に書いているはずです多分…
出来上がった実際の画面がこちら
まあ枠組みはできたのではって感じですね。
今回使用したYamada UIのコンポーネントについて
個人的にいいなと思ったのは
の二つ。
Collapseは今回サイドバーの開閉で使用していて、これからも色々なもので使えそう🧐
useColorModeは私がMantineを使用していて欲しいなあと思っていたものだったので今回紹介したくて無理やり載せました笑
(MantineにもuseColorSchemaというものがありますが、現在のColorのモードを取得することしかできません)
まとめ
ほぼ自分用と言ってもいいようなAppShellの作成を行いました。
使用するときに、必要なパラメータがあれば追加していく感じで使おうと思います。
こんなパラメータもあった方がいいのではないかっていうご意見ありましたら、ぜひお聞かせください🙌
山田さんAppShell的なコンポーネント作ってください…
Discussion