Skip to content
/ YUIS Public

The system is designed to help you build UI components.

License

Notifications You must be signed in to change notification settings

PK-Yakkun/YUIS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 

Repository files navigation



🦄 YUISとは

React, Next.js環境下で『UIコンポーネントライブラリを構築するための』自作フレームワークです。

MUIライクにスタイリングを行うことを目的としており、下記のような記述でUIを構築する仕組みを提供しています。

※下記のようなコンポーネント群そのものを提供しているわけではないことにご注意ください

<Box w={{ sm: "100px", md: "200px"}} py={ 4 } mb={ 6 }>

デザイン設計はAtomic Designを前提としており、デモとしてコンポーネント設計の参考になるよう、いくつかサンプルのUIを作成しています。

npmパッケージとしてUIライブラリを提供しているわけではなく、単なる設計思想です。

そのため、みなさまがYUISをもとにオリジナルのUIライブラリを構築することを前提としています。

サンプルページは下記リンクからご覧いただけます。

サンプルページ: https://yuis.vercel.app/

📚 導入手順

1-A. Next.jsまたはReactの環境がすでにある場合(TypeScript必須)

本リポジトリのsrc配下を丸ごとコピーしてソース群と置換していただければOKです。

1-B. Next.jsやReactのプロジェクトがまだない場合

下記コマンドを実行してプロジェクトを立ち上げます。

{app-name}部分は自由に入力してください。

npx create-next-app {app-name} --use-npm --ts

その後、pages, stylesを削除し本リポジトリのsrcを移植します。

2. 必要なパッケージをインストール

下記コマンドを実行し、ふたつのパッケージをインストールします。

npm i @emotion/react @emotion/styled

3. tsconfigでエイリアスの設定

import文で絶対パスを利用するため、tsconfig.jsonに下記を追記します。

{
  "compilerOptions": {
    // 省略
    "baseUrl": "./src",
    "paths": {
      "@/*": ["./*"]
    }
  },
   // 省略
}

以上です。

🗒 YUISの使い方

基本的にはあらかじめ定義されたMixinや型を利用し、独自にコンポーネントを定義していきます。

汎用的なdivをミニマムに構築する

冒頭にあったような、wというpropsをもってwidthを指定できる機能を持った<Box>コンポーネントを作成したい場合。

import styled from "@emotion/styled";
import { LayoutProps, layoutMixin } from "@/styles/mixins/layout";

export type BoxStyleProps = Partial<LayoutProps>

export const BoxStyled = styled.div<BoxStyleProps>(
  layoutMixin
);

export type BoxProps = BoxStyleProps & {
  children?: React.ReactNode;
};
export const Box = (props: BoxProps) => {
  return <BoxStyled {...props} />;
};

layoutMixinにはwhなどのレイアウトに関するCSS Mixinが定義されており、それに必要な型がLayoutPropsです。

それらを使いstyled-componentsを生成することで、簡単にpropsによりスタイリングが可能なコンポーネントになります。

あとはこれを応用していくだけで、たとえばborderも与えられるようにしたい場合はborderMixinとそれに対応するBorderPropsをimportし、追加で与えればよいだけです。

実際に使用する

上記で作成した<Box>はこのように扱うことができます。

<Box w="100px" maxW="800px" h="180px" >
  {contents}
</Box>

padding, marginを与えたい

これらに必要なものはspaceMixinにまとめられています。SpacePropsを合わせてstyled-componentsに渡します。

import styled from "@emotion/styled";
import { SpaceProps, spaceMixin } from "@/styles/mixins/space";

export type BoxStyleProps = Partial<SpaceProps>;

export const BoxStyled = styled.div<BoxStyleProps>(spaceMixin);

export type BoxProps = BoxStyleProps & {
  children?: React.ReactNode;
};
export const Box = (props: BoxProps) => {
  return <BoxStyled {...props} />;
};

実際に使用する

使用時、spaceに関しては特殊な指定ができます。

<Box py="20px" mb={4} >

pyではpadding-top,padding-bottomに20pxを指定しています。

mbではmargin-bottomに24pxを指定しています。

24という値はnumber型で渡された4を6倍した処理結果であり、6倍という数値はspace.ts内に定義してあります。

渡された値がstring型かnumber型かで判別し、number型であれば6倍した数値をpxとし、CSSに変換されます。

基本設計として6の倍数で余白を取るようにしているため、それを改修したい場合はspace.ts内の値を変更することでカスタマイズすることができます。

レスポンシブに対応する

オブジェクトで値を渡すことでスマホ用とPC用のスタイルを一度に指定することができます。 デフォルトではブレイクポイントは900pxに指定されています。

<Box w={{ sm: "100px", md: "200px"}} >
  {contents}
</Box>
<Box p={{ sm: 4, md: 8}} >
  {contents}
</Box>
<Box m={{ sm: "15px", md: "30px"}} >
  {contents}
</Box>

ブレイクポイントをカスタマイズしたい

項目を増やすにはtypes/responsive.d.tsに追加します。 たとえば、lgなどを加えてさらに大きなディスプレイに対応したい場合などです。

// w, h, などのCSS用propsが受け付けるレスポンシブ用のオブジェクトの型
export type BreakPointProps = {
  sm?: CSS.Properties;
  md?: CSS.Properties;
};

ブレイクポイントの数値を変更したい場合はtheme/settings/breakpoints.tsを変更します。

import { css } from "@emotion/react";

export const breakpoints = {
  sm: (sm: any) =>
    sm != null && css({ "@media (max-width: 899px)": sm }),
  md: (md: any) => md != null && css({ "@media (min-width: 899px)": md }),
};

@media (max-width: 899px)の数値を変更すればブレイクポイントが変わります。

Themeで定義した色を適応したい

styled-components内では引数としてthemeを取ることができます。

最大の注意点は、theme.tsをimportしてはいけないという点です。

styled()の中でthemeを受け取ると自動的にグローバルに定義されているthemeから値を参照できるように、すでに型定義と_app.tsxでの読み込みを行なっています。

Typographyを例に見ます。

export const TypographyStyled = styled.span<TypographyProps>(
  ({ theme }) => `color: ${theme.color.typography};`,
)

こうすることでTypographyはデフォルトでtheme.color.typographyに定義されたカラーコードが代入され、テーマ切り替えを行なった際も切り替え先のカラーコードに動的に変更されます。

前述したように、このときtheme.tsをimportする必要はありません。

if文やswitch文と組み合わせることで、propsによるテーマカラーの出し分けも実装できます。

Themeをカスタマイズする

theme/theme.tsにまとめられています。

各設定ファイルはtheme/settings配下にあるのでそこで値を追加・変更することができます。

import { palette, nightPalette } from "./settings/palettes";
import { fonts } from "./settings/fonts";
import { breakpoints } from "./settings/breakpoints";
import { spacings } from "./settings/spacings";

export const theme = {
  color: palette,
  font: fonts,
  breakpoint: breakpoints,
  spacing: spacings,
};

export const nightTheme = {
  color: nightPalette,
  font: fonts,
  breakpoint: breakpoints,
  spacing: spacings,
};

Themeを切り替える

サンプルで用意しているThemeToggle.tsxを参考にしてください。

useContextを利用し、グローバルステートを切り替えることで<ThemeProvider>に渡すthemeを切り替えています。

import { Box } from "@/components/atoms/Box/Box";
import { Toggle } from "@/components/molecules/Toggle/Toggle";
import { ThemeContext } from "@/lib/store/theme";
import { useContext } from "react";

export const ThemeToggle = () => {
  const { isNightMode, setIsNightMode } = useContext(ThemeContext);
  return (
    <Box onClick={() => setIsNightMode(!isNightMode)}>
      <Toggle />
    </Box>
  );
};

<ThemeProvider>の定義元は_app.tsxになります。

🎨 Atomic Designについて

下記で語っているのでコンポーネント設計の参考になれば幸いです。

Zenn: https://zenn.dev/pk_yakkun/articles/54a8fcbcc0195e#%F0%9F%8E%A8-atomic-design%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

About

The system is designed to help you build UI components.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages