AtomicデザインとはReactなどのフロントエンドでコンポーネントに分割する際の考え方です。
コンポーネントを5つの要素でデザインする
それぞれを以下の5つにまとめました。
- Atoms 原子 最も小さくそれ以上分解できない要素
- ボタン、テキストボックス、アイコンなど単一のHTMLタグで構成されることが多い。主にCSSを適用させるために使う
- molecules 分子(Atoms)の組み合わせて使う、意味を持つコンポーネント
- アイコン+メニュー名、アイコンセット、プロフィール画像+テキストボックス
- organisms 有機体 moleculesを組み合わせ単体で意味を持つ要素群となる
- ツイート入力エリア、サイドメニュー、1つのツイートエリア
- templates ページのレイアウトのみを表現する要素、実際のデータは持たない
- サイドメニュー、メインエリア、トピックエリアなど
- pages 最終的に表示される1画面
以下プロフィールカードの例
Atoms カードの雛形主にCSS
import styled from "styled-components";
export const Card = (props) => {
const { children } = props;
return <SCard>{children}</SCard>;
};
const SCard = styled.div`
background-color: #fff;
box-shadow: #ddd 0px 0px 4px 2px;
border-radius: 8px;
padding: 16px;
`;
molecules 名前とアイコン
import styled from "styled-components";
export const UserIconWithName = (props) => {
const { image, name } = props;
return (
<SContainer>
<SImage height={160} width={160} src={image} alt={name} />
<SName>{name}</SName>
</SContainer>
);
};
const SContainer = styled.div`
text-align: center;
`;
const SImage = styled.img`
border-radius: 50%;
`;
const SName = styled.p`
font-size: 18px;
font-weight: bold;
margin: 0;
`;
Organisms 1人分のプロフィールカード
import styled from "styled-components";
import { Card } from "../../atoms/card/Card";
import { UserIconWithName } from "../../atoms/molecules/user/UserIconWithName";
export const UserCard = (props) => {
const { user } = props;
return (
<Card>
<UserIconWithName image={user.image} name={user.name} />
<SDl>
<dt>メール</dt>
<dd>{user.email}</dd>
<dt>会社名</dt>
<dd>{user.company.name}</dd>
</SDl>
</Card>
);
};
const SDl = styled.dl`
text-align: left;
margin-bottom: 0;
dt {
float: left;
}
dd {
padding-left: 32px;
padding-bottom: 8px;
overflow-wrap: break-word;
}
`;
templates 全体のレイアウト
import { Header } from "../atoms/layout/Header";
import { Footer } from "../atoms/layout/Footer";
export const DefaultLayout = (props) => {
const { children } = props;
return (
<>
<Header />
{children}
<Footer />
</>
);
};
pages 具体的なデータはここにある
import styled from "styled-components"
import {SearchInput} from "../molecules/SearchInput"
import { UserCard } from "../organisms/user/UserCard";
const users = [...Array(10).keys()].map((val) => {
return {
id: val,
name: `パッチid${val}`,
image: "https://source.unsplash.com/v0_MCllHY9M",
email: "pachi@com",
company: {
name: "ぱち会社"
}
}
});
export const Users = () => {
return (
<SContainer>
<h2>ユーザー一覧</h2>
<SearchInput />
<SUserArea>
{users.map((user) =>(
<UserCard key={user.id} user={user} />
))}
</SUserArea>
</SContainer>
)
}
const SContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
padding: 24px;
`
const SUserArea = styled.div`
padding-top: 40px;
width: 100%;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap:20px;
`
ルーティング templateとpageが設定されている
import { BrowserRouter, Switch, Route } from "react-router-dom"
import { Top } from "../components/pages/Top"
import { Users } from "../components/pages/Users"
import { DefaultLayout } from "../components/templates/DefaultLayout"
import { HeaderOnly } from "../components/templates/HeaderOnly"
export const Router = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path="/">
<DefaultLayout>
<Top />
</DefaultLayout>
</Route>
<Route path="/users">
<HeaderOnly>
<Users />
</HeaderOnly>
</Route>
</Switch>
</BrowserRouter>
)
}
使う上でのポイントは最初から分割するのではなく作っていくうちに必要に応じて分割していくことだと思います。
だから、小規模なページの場合は5つの要素全てを使う必要がない場合もあります。
参考