他のフレームワークよりもTailwindCSS が大好きですが、BootstrapやMaterializeなどのより本格的なフレームワークで得られるようなコンポーネントがないことに常に失望しています。 私は最近、この問題の完璧な解決策を発見しました:ChakraUI

Chakra UIは、Tailwind CSSと同じミニマルでモジュール式のアプローチに従うため、デフォルト構成を元に戻したりオーバーライドしたりするために時間を無駄にする必要はありません。

この記事では、このフレームワークが私たちのために何ができるのか、そしてなぜそれがユニークなのかを探求し始めます。

インストール

インストールには少し厄介なものがあります。これは、デフォルトで付属しているはずのピア依存関係がいくつかあるためですが、何らかの理由でそのようになっています¯\ _(ツ)_/¯。

Chakra UIは👩‍🎤emotion CSS-in-JS ライブラリに依存しているため、ChakraUI自体とEmotionのいくつかのものが必要です。

利用します npx Reactアプリを作成してReactアプリを初期化します。

$ npx create-react-app chakra-app
$ npm install @chakra-ui/core @emotion/core @emotion/styled emotion-theming

設定

何かをする前に、アプリ全体を ThemeProvider、これにより、コンポーネントのすべてのデフォルトスタイルが確立されます。

index.js
import { ThemeProvider } from "@chakra-ui/core";

const ThemedApp = () => <ThemeProvider> <App /> </ThemeProvider>;

ReactDOM.render(<ThemedApp />, document.getElementById('root'));

レイアウト

スライダーやドロップダウンなどの通常のUIコンポーネントに加えて、Chakra UIには、複数のコンポーネントのレスポンシブレイアウトを簡単に追加するための、いくつかの「メタコンポーネント」(正式な用語ではありません)があります。 それらすべてを使用すると、次のように、期待するプロパティを渡すことができます。 bg また justifyContent 小道具としてCSSで。

  • Stack -等間隔のコンポーネントにセットをグループ化します。デフォルトでは垂直ですが、次のコマンドでオーバーライドできます。 isInline.
  • Flex -すべてをFlexboxコンテナでラップします。
  • Grid -すべてをCSSグリッドコンテナにラップします。
  • Box -スタイルの小道具を受け取るための単なるdiv。
App.js
import { Stack, Flex, Box, Grid } from "@chakra-ui/core";

const App = () => {
  const flexSettings = {
    flex: "1",
    minW: "300px",
    textAlign: "center",
    color: "white",
    mx: "6",
    mb: "6"
  };

  const gridSettings = {
    w: "100%",
    textAlign: "center",
    color: "white",
  };

  return (
    <div>
      <Flex w="100%" justify="space-between" flexWrap="wrap">
        <Box {...flexSettings} bg={"red.500"}>I'm a box</Box>
        <Box {...flexSettings} bg={"blue.500"}>I'm a box</Box>
        <Box {...flexSettings} bg={"green.500"}>I'm a box</Box>
        <Box {...flexSettings} bg={"purple.500"}>I'm a box</Box>
      </Flex>

      <Grid w="100%" templateColumns="repeat(auto-fit, minmax(300px, 1fr))" gap={6}>
        <Box {...gridSettings} bg={"red.500"}>I'm a box</Box>
        <Box {...gridSettings} bg={"blue.500"}>I'm a box</Box>
        <Box {...gridSettings} bg={"green.500"}>I'm a box</Box>
        <Box {...gridSettings} bg={"purple.500"}>I'm a box</Box>
      </Grid>
    </div>
  );
};

スタイリング

Chakra UIはスタイリングのEmotionに基づいているため、CSS-in-JSを使用でき、Tailwind CSSと同じスタイルの共通プロパティの独自の省略形を追加します。これが、使用できた理由です。 wtemplateColumns それ以外の widthgridTemplateColumns.

このスタイリングのアプローチに慣れていない場合は、CSSを作成する方法であるため、スタイルをコンポーネントの状態に接続するなど、Sassにも付属していないすべてのJavaScript機能を利用できます。

この例では、ボックスのスタイルをコンポーネントの状態に基づいて作成し、小さなUIを使用して操作しています。

App.js
const BoxController = () => {
  let [boxHeight, editHeight] = useState(20);
  let [boxColor, editColor] = useState('red');
  let [colorIntensity, editIntensity] = useState(500);

  const boxSettings = {
    flex: "1",
    textAlign: "center",
    color: "white",
    h: `${boxHeight}px`,
    bg: `${boxColor}.${colorIntensity}`
  };

  return (
    <div>
      <Box {...boxSettings}>I'm a Box</Box>
      <Flex justifyContent="space-around">
        <Stack>
          <Heading size="md">Size</Heading>
          <Button variantColor="red" onClick={() => editHeight(boxHeight -= 10)} border="none">Shrink</Button>
          <Button variantColor="green" onClick={() => editHeight(boxHeight += 10)} border="none">Grow</Button>
        </Stack>

        <Stack>
          <Heading size="md">Color</Heading>

          <Flex w="200px" justifyContent="space-between">

            <Stack>
              <Button variantColor="green" onClick={() => editColor('green')} border="none">Green</Button>
              <Button variantColor="blue" onClick={() => editColor('blue')} border="none">Blue</Button>
              <Button variantColor="red" onClick={() => editColor('red')} border="none">Red</Button>
            </Stack>

            <Stack>
              <Button variantColor="gray" variant="outline" onClick={() => editIntensity(colorIntensity -= 100)} border="none">Lighter</Button>
              <Button variantColor="gray" variant="outline" onClick={() => editIntensity(colorIntensity += 100)} border="none">Darker</Button>
            </Stack>

          </Flex>
        </Stack>
      </Flex>
    </div>
  );
};

コンポーネント

明らかにすべてのコンポーネントを調べることはできないので、ChakraUIに固有のいくつかに焦点を当てましょう。

引き出し

引き出しコンポーネントは、どんなサイドナビゲーションバーにも最適な、すっきりとした小さなスライドアウトメカニズムです。 チャクラのカスタムを使用していることに注意してください useDisclosure 私たちに与えるフック isOpen, onOpen、 と onClose 引き出しやモーダルなどの同様のコンポーネントの状態を制御するため。

App.js
import {
  Drawer,
  DrawerBody,
  DrawerFooter,
  DrawerHeader,
  DrawerOverlay,
  DrawerContent,
  DrawerCloseButton,
  Input,
  Button,
  useDisclosure,
  Stack,
  Textarea
} from "@chakra-ui/core"

const SignUpForm = () =>  {
  const { isOpen, onOpen, onClose } = useDisclosure();
  const btnRef = useRef();

  return (
    <div>
      <Button ref={btnRef} variantColor="teal" border="none" onClick={onOpen}>
        Sign Up
      </Button>
      <Drawer
        isOpen={isOpen} placement="bottom"
        onClose={onClose} finalFocusRef={btnRef}
      >
        <DrawerOverlay />
        <DrawerContent>

          <DrawerCloseButton border="none" />
          <DrawerHeader>Sign up Now</DrawerHeader>

          {/* Form */}
          <DrawerBody >
            <Stack height="30vh">
              <Input w="98%" placeholder="Name" />
              <Input w="98%" placeholder="Email" />
              <Textarea w="98%" h="100%" placeholder="Message" />
            </Stack>
          </DrawerBody>

          <DrawerFooter>
            <Button variantColor="red" border="none" mr={3} onClick={onClose}>
              Cancel
            </Button>
            <Button variantColor="blue" border="none">Save</Button>
          </DrawerFooter>

        </DrawerContent>
      </Drawer>
    </div>
  );
}

ローダー

Chakra UIは、非常に簡単にカスタマイズできるアニメーションローダーの素晴らしい配列を提供します。 この例では、ローダーの動作を確認するためのループを追加しましたが、外部のものに基づく必要はなく、完全に静的にすることもできます。

App.js
import {
  Stack,
  CircularProgress,
  CircularProgressLabel,
  Progress,
  Spinner
} from "@chakra-ui/core"

const Spinners = () => {
  let [progress, update] = useState(0)

  const randomNum = (min, max) => Math.floor(Math.random() * (max - min + 1) + min)

  useEffect(() => setInterval(() => {
    // Reset to 0 when reaches 100
    update(progress < 100 ? progress += randomNum(0, 4) : 0)
  }, 500), [])

  return (
    <div>
      <Stack>
        <CircularProgress color="green" isIndeterminate>
          <CircularProgressLabel>{progress}%</CircularProgressLabel>
        </CircularProgress>
        <CircularProgress value={progress} size="100px" thickness={0.1} color="purple" />
        <Progress value={progress} w="90%" />
        <Progress value={progress + 10} w="90%" hasStripe isAnimated />
        <Spinner
          thickness="3px"
          speed="1s"
          emptyColor="gray.200"
          color="blue.500"
          size="2xl"
        />
      </Stack>
    </div>
  );
}

テーマ

他のフレームワークから私がまだ見ていないことは、アプリ全体にテーマを設定する機能です。 ダークテーマでも冬のテーマでも、サイト/アプリ全体のスタイルを1か所で簡単にカスタマイズできます。

この例では、ホリデーシーズンに基づいたデザインとテキストのボックスをいくつか追加しました。 Alligator.io のように、サイトで最も気に入ったデザインを選択できる場合、私は個人的に大好きです。 😉

index.js
import { useTheme, ThemeProvider } from "@chakra-ui/core"


const ThemedApp = () => {
  const theme = useTheme()
  const customTheme = {
    ...theme,
    colors: { ...theme.colors },
    holidays: {
        text: {
          none: "Welcome to the site!",
          stPatricksDay: "Happy St.Patty's Day!",
          valentinesDay: "Happy Valentines Day!",
          halloween: "Good luck trick-or-treating!",
          christmas: "Merry Christmas!"
        },
        colors: {
            none: {
              "one": "#808080",
              "two": "#808080",
              "three": "#808080"
            },
            stPatricksDay: {
              "one": "#224D17",
              "two": "#60A830",
              "three": "#099441"
            },
            valentinesDay: {
              "one": "#b11d4d",
              "two": "#fd6fa0",
              "three": "#e986a3"
            },
            halloween: {
              "one": "#810806",
              "two": "#BF200E",
              "three": "#FA4113"
            },
            christmas: {
              "one": "#44b09e",
              "two": "#e0d2c7",
              "three": "#e01c34"
            },
        }
      }
  };
  return (
    <div>
      <ThemeProvider theme={customTheme}><App /></ThemeProvider>
    </div>
  )
}
App.js
import {
  Flex,
  Button,
  useTheme,
  Box
} from "@chakra-ui/core"

const HolidayPicker = () => {
  const [holiday, updateHoliday] = useState("none")
  const theme = useTheme()

  const holidayText = theme.holidays.text[holiday]
  const holidayColor = theme.holidays.colors[holiday]

  const btnStyles = {
    border: 'none',
    h: '25px',
    borderRadius: '20px',
    color: 'white',
    fontWeight: 'bold',
    cursor: 'pointer'
  }
  return (
    <div>
      <Flex justifyContent="space-around">
        <Box bg={holidayColor.one} w="100%" h="400px" color="white">{holidayText}</Box>
        <Box bg={holidayColor.two} w="100%" h="400px" color="white">{holidayText}</Box>
        <Box bg={holidayColor.three} w="100%" h="400px" color="white">{holidayText}</Box>
      </Flex>

      <Flex justifyContent="space-around" mt="20px">
        <Button bg={theme.holidays.colors.none} {...btnStyles}
          onClick={() => updateHoliday('none')}>None</Button>
        <Button bg={theme.holidays.colors.stPatricksDay} {...btnStyles}
          onClick={() => updateHoliday('stPatricksDay')}
        >St.Patrick's Day</Button>
        <Button bg={theme.holidays.colors.valentinesDay} {...btnStyles}
          onClick={() => updateHoliday('valentinesDay')}
        >Valentine's Day</Button>
        <Button bg={theme.holidays.colors.halloween} {...btnStyles}
          onClick={() => updateHoliday('halloween')}
        >Halloween</Button>
        <Button bg={theme.holidays.colors.christmas} {...btnStyles}
          onClick={() => updateHoliday('christmas')}
        >Christmas</Button>
      </Flex>
    </div>
  );
}

まとめ

TailwindCSSとともに、ChakraUIは私のすべてのプロジェクトで不可欠なツールの1つになりました。 それは絶えず改善されており、今でもappBarやカルーセルコンポーネントのようないくつかのプルリクエストがあり、おそらくすぐに追加されるでしょう。 これが、ChakraUIがReact/UIアーセナルに含まれるに値するかどうかを判断するのに十分であったことを願っています。