Reactのスタイリングをするためのライブラリには、二種類あって
といった感じです(このタイプの呼び方は私が考えたんで、別の言い方があるかもしれませんが)。
前者はchakra ui、Material UI(MUI)など。
後者はBootstrap、tailwindcssといったものです。
ということで本記事では、chakra uiの使い方を簡単にご紹介。
chakra uiのインストール
まずは、chakra uiのライブラリをインストールしましょう。
chakra uiを使用する、Reactのディレクトリで
npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion
を入力しましょう。
詳細はこちらから(yarnやpnpmでのインストールも載っています。)。
chakra uiをimportする
// App.js
import React from "react";
import "./App.css";
// chakra-uiをimport
import { ChakraProvider } from "@chakra-ui/react";
import Todo from "./components/Todo";
function App() {
return (
{/* chakra-uiを使いたいコンポーネントを<ChakraProvider>で囲う */}
<ChakraProvider>
<div className="App">
<Todo />
</div>
</ChakraProvider>
);
}
export default App;
「import { chakra ui } from “@chakra-ui/react”;」でchakra uiをimport。
そして、chakra uiを使いたいコンポーネントを<ChakraProvider></ChakraProvider>で囲いましょう。
ちなみに、App.jsで展開している<Todo />コンポーネントのコードはこちら。
// Todo.js
import { useState } from "react";
import List from "./List";
import Form from "./Form";
import { Heading, VStack } from "@chakra-ui/react";
const Todo = () => {
const todosList = [
{
id: 1,
content: "英語の教材を購入する。",
},
{
id: 2,
content: "学際の衣装を作る",
},
{
id: 3,
content: "宅配便の再配送を頼む",
},
];
const [todos, setTodos] = useState(todosList);
const deleteTodo = (id) => {
const newTodos = todos.filter((todo) => {
return todo.id !== id;
});
setTodos(newTodos);
};
const createTodo = (todo) => {
setTodos([...todos, todo]);
};
return (
<VStack p="10" spacing="10">
<Heading color="blue.200" fontSize="5xl">
Todoリスト
</Heading>
<List todos={todos} deleteTodo={deleteTodo} />
<Form createTodo={createTodo} />
</VStack>
);
};
export default Todo;
chakra uiのサンプル
VStack, StackDivider, HStack, IconButton, Textコンポーネント
スタイリング前と後
chakra uiでスタイリングする前にはこんな感じの画面です。
スタイリングした後はこんな感じの画面になります。
chakra uiを適用したコード
// List.js
import { VStack, StackDivider, HStack, IconButton, Text } from "@chakra-ui/react";
import { VscCheck } from "react-icons/vsc";
const List = ({ todos, deleteTodo }) => {
const complete = (id) => {
deleteTodo(id);
};
return (
<VStack
divider={<StackDivider />}
color={{base:'gray.600', sm:'red.600',md:'blue.600',lg:'green.600'}}
borderColor="blackAlpha.300"
borderWidth="5px"
borderRadius="5px"
p={5}
alignItems="start"
>
{todos.map((todo) => {
return (
<HStack key={todo.id} spacing={5}>
<IconButton
onClick={() => complete(todo.id)}
icon={<VscCheck/>}
isRound
bgColor="red.200"
opacity="0.5"
>
完了
</IconButton>
<Text>{todo.content}</Text>
</HStack>
);
})}
</VStack>
);
};
export default List;
では、chakra uiを「VStack, StackDivider, HStack, IconButton, Textコンポーネント」を使ってご紹介。
VStack:垂直方向に要素を積み重ねるために使用される
import { VStack,StackDivider } from "@chakra-ui/react";
<VStack
divider={<StackDivider />}
color={{base:'whiteAlpha.200', sm:'red.600',md:'blue.600',lg:'green.600'}}
borderColor="blackAlpha.300"
borderWidth="5px"
borderRadius="5px"
p={5}
alignItems="start"
>
・・・・・
</VStack>
VStackを使ってリストをスタイリング。
「divider={<StackDivider />}」は、要素を分ける線を表示するというもの。
その他の指定は、だいたいcssに準じているのでわかると思います。
HStack: 水平方向に要素を積み重ねるために使用する。
import { HStack } from "@chakra-ui/react";
<HStack key={todo.id} spacing={5}>
<button onClick={() => complete(todo.id)}>完了</button>
<span>{todo.content}</span>
</HStack>
<button>と<span>はinline要素なので、それを<HStack>によってきれいに配置します。
spacing={5}によって、1.25remの間隔を空けて<button>と<span>を並べるということ。
Iconbuttonは、ボタン内にあるアイコンを描画します。
import { IconButton } from "@chakra-ui/react";
<IconButton onClick={() => complete(todo.id)} icon={<VscCheck/>}>完了</IconButton>
ボタンをicon buttonにすることができます。
<IconButton>コンポーネントは、プロップスにreact-iconsのコンポーネントを渡すことによって、ボタンをicon buttonにすることができます。
react-iconsについては、こちらで紹介しています。
Text:インターフェイス内のテキストと段落をレンダリングするために使用される
import { Text } from "@chakra-ui/react";
<Text>{todo.content}</Text>
<Text>コンポーネントは、<span>タグとほぼ同じ働きをしますが、<Text>コンポーネントに直接スタイリングをすることができます。
なので、chakura uiを使用しているなら、<span>タグを使用するより<Text>コンポーネントを使用した方が、後々のスタイリングが楽になります。
Input、Buttonコンポーネント useToast()関数
スタイリングの前と後
今回は赤枠のインプットエリアとボタンをchakra uiでスタイリングします。
スタイリング前にはこんな感じの画面です。
スタイリング後はこんな感じ。
chakra uiを適用したコード
// Form.js
import { Button, Input, useToast } from "@chakra-ui/react";
import { useState } from "react";
const Form = ({ createTodo }) => {
const [enteredTodo, setEnteredTodo] = useState("");
const toast = useToast();
const addTodo = (e) => {
e.preventDefault();
if (!enteredTodo) {
toast({
title: "タスクが入力されていません!",
status: "error",
duration: 2000,
isClosable: true,
});
return;
}
const newTodo = {
id: Math.floor(Math.random() * 1e5),
content: enteredTodo,
};
createTodo(newTodo);
setEnteredTodo("");
};
return (
<div>
<form onSubmit={addTodo}>
<Input
placeholder="タスクを入力してください"
_placeholder={{ opacity:0.4, color:"gray.600"}}
size="lg"
variant="Filled"
value={enteredTodo}
onChange={(e) => setEnteredTodo(e.target.value)}
/>
<Button
colorScheme="blue"
size="md"
variant="outline"
px={7}
type="submit"
>追加
</Button>
</form>
</div>
);
};
export default Form;
useToast()関数
少しスタイリングから離れますが、chakra uiでは、メッセージボードを出すことができます(トーストと呼んでいますが)。
今回の場合は、インプットエリアに何も記載されていないときに、「追加」ボタンが押下された場合に、メッセージが出るようにしました。
import { useToast } from "@chakra-ui/react";
const toast = useToast();
if (!enteredTodo) {
toast({
title: "タスクが入力されていません!",
status: "error",
duration: 2000,
isClosable: true,
});
return;
}
「useToast」をimportします。
toastを定義します。
ここで定義する理由は、useToast()は、関数コンポーネントのトップレベルか、カスタムHookの中でしか呼ぶことができないからです。
定義したtoast()のプロパティは以下の通りです。
InputとButtonコンポーネント
import { Button, Input } from "@chakra-ui/react";
<Input
placeholder="タスクを入力してください"
_placeholder={{ opacity:0.4, color:"gray.600"}}
size="lg"
variant="Filled"
value={enteredTodo}
onChange={(e) => setEnteredTodo(e.target.value)}
/>
<Button
colorScheme="blue"
size="md"
variant="outline"
px={7}
type="submit"
>追加
</Button>
variantを説明します。
Inputには、outline、unstyled、flushed、filledのスタイルが用意されています。
Buttonのvariantには、olid、ghost、outline、linkのスタイルが用意されています。
用途に合わせて、簡単にスタイルを変更できます。
最後に
chakra uiにはその他にもいろいろスタイルコンポーネントが用意されているので、こちらのコンポーネント一覧から確認してみてください。
付録
chakra uiのカラーの指定するときの定型のカラー、スペースの定数、メディアクエリーの指定方法とその幅の値を書いておきます。
カラー
borderColor="blackAlpha.300"
chakra uiには「blackAlpha.300」に見られるように定型的なカラーの指定ができて、サイトにカラーの統一感を持たせやすくなっています。カラーサンプルはこちらを参照してください。
スペース
p={5}
「p={5}」に見られるようにpaddingなどに対応するスペーシングの数値も定義されています。
スペーシングのサイズはこちらを参照してください。
メディアクエリー
color={{base:'whiteAlpha.200', sm:'red.600',md:'blue.600',lg:'green.600'}}
sm: ,md: などのように、メディアクエリーを指定(min-width)することができます。
smは”30em”(親要素が16pxの場合480px)
mdは”48em”親要素が16pxの場合768px)
lgは”62em”(親要素が16pxの場合992px)
xlは”80em”,(親要素が16pxの場合1280px)