Props

そのコンポーネントで渡すことができるプロパティの名前、型、デフォルト値、説明です。

TypeScript の場合、大抵コンポーネント名Propsという名前でプロパティの型がインポートできる形になってます。

CSS

デフォルトスタイルを上書きする為のキー名やクラス名、簡単な説明が載ってます。makeStylesなどで変えたいキー名を使ってスタイルを作ることで、Material UI が適用する同じキー名のスタイルを高い優先度のセレクタで上書きできます。
高い優先度というのは単にMaterial UI のクラス名先に置かれるという意味です。

<div class="MuiXxx-xxx-n makeStyles-xxx-n">...</div>

恐らくすべてにclassNameプロパティも存在するのと、MuiXxxというような名前は決まっているので、そこにネスト構造な自分で定義したクラス名を渡す方法でも見た目を変えることができます。

このセクションが無い

セクションがない場合、そのコンポーネントにはclassesというプロパティはありません。そういうコンポーネントにはclassNameプロパティでクラス名を渡します。その動作は標準の HTML タグのclassNameを指定する場合と同じです。

関連

Material UI はスタイルを定義する為の CSS in JS モジュールを提供してます。

インストール

スタイル作成ユーティリティは@material-ui/stylesまたは、@material-ui/core/stylesから取り込めます。取り込む前に以下のどちらか適切な方でそれらをインストールする必要があります。

yarn add @material-ui/style
# または、
yarn add @material-ui/core

使う

スタイルを作成するユーティリティ関数は3つあります。

  1. withStyles

  2. makeStyles

  3. styled

これら3つの中身は正味 JSS で、以下の7つのプラグインを使うインスタンスを使ってます。

独自のインスタンスを使う

JSS インスタンスを作りStylesProviderコンポーネントに渡すことで、プラグインを追加したり、いらない機能を削除できます。

import {create} from 'jss';
import {
  StylesProvider,
  jssPreset
} from '@material-ui/core/styles';
import rtl from 'jss-rtl';

const jss = create({
  plugins: [
    // 上記の7つのプラグインがほしい場合、
    // コメントアウト
    // ...jssPreset().plugins,
    rtl()
  ]
});

export default () => {
  return (
    
      {/* ... */}
    
  );
};

withStyles

JSSjss-plugin-rule-value-functionjss-plugin-globaljss-plugin-nestedjss-plugin-camel-casejss-plugin-default-unitjss-plugin-vendor-prefixerjss-plugin-props-sortwithStyles はHOC(higher-order component)を作る為のユーティリティです。これは以下のように使います。

const propInjector = withStyles(
  style,
  options
);

styleにはクラスの目印(クラスキー)をプロパティ、 JSS プラグインによって許される様々なスタイルの値をバリューとしたオブジェクト、またはそれを返す関数を置きます。

JSS プラグインによって許される様々なスタイルの値とは以下のような種類があります。
スタイルがオブジェクトなのが一番普通ですが、

const styles = {
  // root はクラスキー
  root: {
    // CSSProperties
    color: 'orange',

    // CreateCSSProperties
    '&:hover': {
      background: 'blue'
    },
    background: props =>
      props.background
  }
};

スタイルはpropsを引数に渡される関数にもなれます。

const styles = {
  root: props => ({
    color: 'orange',
    '&:hover': {
      background: 'blue'
    },
    background: props.background
  })
};

また、それを返す関数とはテーマオブジェクトを引数に渡さる関数で、その戻り値は上記のstylesのような値になります。

const styles = theme => {
  root: props => ({
    background: props.background
  });
};

このthemeにはThemeProviderなどを使ってテーマオブジェクトを渡すことができます。

withStylesによって得たpropInjectorへコンポーネントを引数として渡して実行することで、そのコンポーネントはclassesオブジェクトをプロパティから扱えます。このオブジェクトはクラスキーとそのクラスキーと対になる実際の HTML クラス名(のグループ)になっているので、

のようにクラス名に適切なクラス名が当てられるようにします。

またpropInjectorで得られたコンポーネントはclassesプロパティを渡せるようになります。

const FooWithClasses = propInjector(
  Foo
);

このclassesプロパティにwithStylesを使う時に定義したものと同じクラスキーとクラス名のオブジェクトを渡すと、Foo内部で受け取るclassesは定義時に作られたものととプロパティとして渡されたものの同じクラスキーのクラス名を組み合わせたものになります。

const classes = {
  root:
    '定義時の`classes.root` プロパティで渡さた`classes.root`'
};
Material-UI: the key `heading` provided to the classes prop is not implemented in App.
You can only override one of the following: root.

makeStyles

JSSjss-plugin-rule-value-functionjss-plugin-globaljss-plugin-nestedjss-plugin-camel-casejss-plugin-default-unitjss-plugin-vendor-prefixerjss-plugin-props-sortwithStyles使った時に使っていないクラスキーを含めるmakeStylesclassesを返す React カスタムフックを作るためののユーティリティーです。これは、withStylesを作るう時のstyleと同じ値を引数に渡して実行します。

const useStyles = makeStyles(theme => {
  root: props => ({
    background: props.background
  });
});

後はこのuseStylesをコンポーネント内部で実行すればclassesが受け取れます。

const classes = useStyles();
/**
 * classes === {
 *   root: 'makeStyles-root-9',
 * };
 **/

また、このカスタムフックは引数にpropsが渡せ、それをスタイルオブジェクト部分で受け取れます。

styled

styled(Button)`
  color: orange;
`;

のようなタグ付けテンプレートリテラルでスタイルを記述したりはできないようです。

関連

Material UI のデフォルトテーマをカスタマイズすることで自分のサイト合う見た目を作れます。カスタマイズできる内容は以下の7項目があります。

  1. Palette

  2. Typography

  3. Spacing

  4. Breakpoints

  5. z-index

  6. Globals

  7. Density

テーマは@material-ui/core/stylesからcreateMuiThemeユーティリティも持ってきて使います。これはカスタマイズしたい項目だけを持つオブジェクトを引数で渡すと、他の必要な項目を補ってくれます。

import {createMuiTheme} from '@material-ui/core/styles';

console.log(createMuiTheme());

export default () => null;

つまり、何も与えないとデフォルト値を返します。

createMuiThemeによって作ったthemeThemeProviderに渡すことで、withStylesmakeStylesといったユーティリティの引数で受け取れます。

import {
  ThemeProvider,
  createMuiTheme
} from '@material-ui/core/styles';

const theme = createMuiTheme();


  {/* ... */}
;

Palette (色)

Material UI で使われるデフォルト値色をカスタマイズできます。これはpaletteプロパティに以下のような名前で各色情報を定義することで行なえます。

  1. primary

  2. secondary

  3. error

  4. warning

  5. info

  6. successs

また、それぞれの値は以下のような構造で定義したオブジェクト、

interface PaletteIntention {
  light?: string;
  main: string;
  dark?: string;
  contrastText?: string;
}

または以下から好きなデフォルト値色をカスタマイズカラーオブジェクトを渡します。

import {
  amber,
  blue,
  blueGrey,
  brown,
  common,
  cyan,
  deepOrange,
  deepPurple,
  green,
  grey,
  indigo,
  lightBlue,
  lightGreen,
  lime,
  orange,
  pink,
  purple,
  red,
  teal,
  yellow
} from '@material-ui/core/colors';

色を確認しながら選べる公式ツール

この辺は公式で便利なサイトが作られてます。このデフォルト値色をカスタマイズカラーオブジェクト色を確認しながら選べる公式ツールを使って、事前にプライマリ色やセカンダリ色の相性などを確認してから色値を取得できます。

Typography

フォントに関する領域です。typography.fontFamilyでフォントを、typographyy.fontSizeでフォントサイズ(デフォルトは14)、またtypography.htmlFontSizeで HTML のデフォルトフォントサイズをカスタマイズできます。
Material UI では単位はremが使われます。

theme[Typography variant name]へスタイルオブジェクトを置くことでTypographyコンポーネントのそのvariantを使用した時のデフォルト値色をカスタマイズカラーオブジェクト色を確認しながら選べる公式ツールスタイルをカスタマイズできます。

Typographyコンポーネントで使用できるvariant値は以下の通りです。

  • h1

  • h2

  • h3

  • h4

  • h5

  • h6

  • subtitle1

  • subtitle2

  • body1

  • body2

  • caption

  • button

  • overline

  • srOnly

  • inherit

Spacing

基準となるスペース値、またはユーティリティを設定する領域です。デフォルトは8theme.spacing(2)と実行することで16という値を得れます。

テーマ作成時に以下のようにすると、

const theme = createMuiTheme({
  spacing: 2
});

theme.spacing(2)4を返すようになります。

またユーティリティにすると好きな単位込みの値を取得できたり、割と自由です。

const theme = createMuiTheme({
  spacing: factor => `${[0, 4, 8, 16, 32, 64][factor]}rem`,
});

// theme.spacing(1) === '4rem'

Breakpoints

レスポンシブな為の値の為領域でデフォルトでは以下のようなブレークポイントになってます。

const breakpoints = {
  values: {
    xs: 0,
    sm: 600,
    md: 960,
    lg: 1280,
    xl: 1920
  }
};

theme.breakpointsには4つのヘルパー関数があります。

  1. up(key)

  2. down(key)

  3. only(key)

  4. between(start, end)

それぞれ@media (...)のようなメディアクエリな文字列を返します。
upやdownは単独のmax-widthmin-widthルールです。downの場合は指定したキーの値より0.05だけ小さい値が使われます。
onlybetweenmin-widthmax-widthの組み合わせで、「smサイズだけ」や「smからlgまで」なメディアクエリな文字列を取得できます。

z-index

使う予定のz-index値について名前を付けれます。(定数)
デフォルトでは以下のような値があります。

const zIndex = {
  mobileStepper: 1000,
  speedDial: 1050,
  appBar: 1100,
  drawer: 1200,
  modal: 1300,
  snackbar: 1400,
  tooltip: 1500
};

Globals

各 Material UI について、まとめてスタイルを変更したり、プロパティのデフォルト値を変えれます。overrides[MUI Component Name]からスタイルを、props[MUI Commponent Name]からプロパティをそれぞれ弄れます。

Density

いくつかのコンポーネントには密度(空間を開ける・開けない)を定義するようなプロパティやスタイルがあり、これを Globals で挙げたような方法でまとめて弄ることで、一貫したルールが保ちやすいまま変えることができます。

関連

Material UI でデフォルトで扱われる言語は英語になります。
例えば@material-ui/lib/Alertコンポーネントには、onCloseプロパティを渡すとcloseIconが表示されます。このアイコンはしばらくホバーすると「Close」というテキストが表示されます。

Material UI はこのようなテキストをまとめて日本語化する API を用意してます。それにはcreateMuiThemeユーティリティの第2引数にロケールオブジェクトを渡して使います。

日本語のロケールオブジェクト自体は、

import {jaJP} from '@material-ui/core/locale';

で取り込んで使うだけなので、これをcreateMuiThemeへ渡すだけで日本語化できます。
このロケールオブジェクトにはかなりの数が用意されているので公式サイトを参照してください。

あとは公式サイトこのように 作ったテーマをThemeProviderへ渡してコンポーネントを使うだけです。

import React from 'react';
import Alert from '@material-ui/lab/Alert';
import {
  createMuiTheme,
  ThemeProvider
} from '@material-ui/core/styles';
import {jaJP} from '@material-ui/core/locale';

const theme = createMuiTheme({}, jaJP);

export default function App() {
  return (
    
       {}}
      >
        error text
      
    
  );
}

「Close」から「閉じる」へ変わっていれば大丈夫です。

関連

汎用コンポーネントとしてBoxコンポーネントが用意されてます。これはスタイル調整用のプロパティを複数持ち、それらを組み合わせて主にレイアウト調整を行えます。

Boxコンポーネントは、以下のどちらかの方法で取り込んで使います。

import Box from '@material-ui/core/Box';
// import {Box} from '@material-ui/core';

値の設定の仕方

また各プロパティは数値や文字列といった値の他に配列やオブジェクトも置けます。配列やオブジェクトにした場合、それはレスポンシブな CSS として解決されます。

例えば Material UI デフォルトのブレークポイントは以下の通りで、

const breakpoints = {
  values: {
    xs: 0,
    sm: 600,
    md: 960,
    lg: 1280,
    xl: 1920
  }
};

この時width: ['100%', 300]のように値を設定すると、xsサイズの時は'100%'、それ(sm)以上の時は、300pxのように解釈されます。配列だと続きのブレークポイントで解決されてしまいますが、mdから300pxにしたい場合はオブジェクトで以下のようにします。

また一部のプロパティは、テーマにある値が使えます。その場合 CSS で扱える値かテーマのパスを指定できます。例えばz-indexが設定できるzIndexプロパティはtheme.zIndexオブジェクトの値が使えます。これはデフォルトで以下のようなものになってます。

const zIndex = {
  mobileStepper: 1000,
  speedDial: 1050,
  appBar: 1100,
  drawer: 1200,
  modal: 1300,
  snackbar: 1400,
  tooltip: 1500
};

よってzIndexは(無意味に)以下のように使えます。

もしテーマにある値は配列の場合はそのインデックス値、関数の場合は引数を渡します。

Boxコンポーネントは以下のようなセクションに分類されるプロパティを持ってます。

  1. Borders

  2. Display (Flexbox)

  3. Palette

  4. Positions

  5. Shadows

  6. Sizing

  7. Spacing

  8. Typography

Borders

Borders は、要素の境界線に関するプロパティです。これには以下のようなプロパティがあります。

  1. border

  2. borderTop

  3. borderLeft

  4. borderRight

  5. borderBottom

  6. borderColor

  7. borderRadius

border

border系のプロパティは、CSS のborderが扱える値かtheme.bordersに定義済のキー名が渡せます。

borderColor

borderColorは CSS のborder-colorで扱える値かtheme.paletteに定義済みのキー名が渡せます。

borderRadius

borderRadiusは、CSS のborder-radiusで扱える値かtheme.shapeに定義済のキー名が渡せます。デフォルトでtheme.shapeにはborderRadius: 4という値が登録されているので、これを使えます。

Display

  • display

  • overflow

  • textOverflow

  • visibility

  • whiteSpace

また厳密には Display の分類ではありませんが、以下のような Flexbox 用のプロパティもあります。

  • flexDirection

  • flexWrap

  • justifyContent

  • alignItems

  • alignContent

  • order

  • flex

  • flexGrow

  • flexShrink

  • alignSelf

これらに関して、関連するテーマ値はありません。

Palette

  • color

  • bgcolor

Positions

  • position

  • top

  • left

  • right

  • bottom

  • zIndex

zIndex以外は CSS て扱える値を渡します。

zIndex

zIndexには数値の他にtheme.zIndex以下のパスが指定できます。theme.zIndexはデフォルトで以下のような値になってます。

const zIndex = {
  mobileStepper: 1000,
  speedDial: 1050,
  appBar: 1100,
  drawer: 1200,
  modal: 1300,
  snackbar: 1400,
  tooltip: 1500
};

// 

Shadows

  • boxShadow

boxShadow

boxShadowには CSS のbox-shadowが扱える値かtheme.shadowsの値が使えます。theme.shadowsはデフォルトで以下のような配列値になっており、使う際はそのインデックス値を使います。

const shadows = [
  'none',
  '0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)',
  '0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12)',
  '0px 3px 3px -2px rgba(0,0,0,0.2),0px 3px 4px 0px rgba(0,0,0,0.14),0px 1px 8px 0px rgba(0,0,0,0.12)',
  '0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)',
  '0px 3px 5px -1px rgba(0,0,0,0.2),0px 5px 8px 0px rgba(0,0,0,0.14),0px 1px 14px 0px rgba(0,0,0,0.12)',
  '0px 3px 5px -1px rgba(0,0,0,0.2),0px 6px 10px 0px rgba(0,0,0,0.14),0px 1px 18px 0px rgba(0,0,0,0.12)',
  '0px 4px 5px -2px rgba(0,0,0,0.2),0px 7px 10px 1px rgba(0,0,0,0.14),0px 2px 16px 1px rgba(0,0,0,0.12)',
  '0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12)',
  '0px 5px 6px -3px rgba(0,0,0,0.2),0px 9px 12px 1px rgba(0,0,0,0.14),0px 3px 16px 2px rgba(0,0,0,0.12)',
  '0px 6px 6px -3px rgba(0,0,0,0.2),0px 10px 14px 1px…gba(0,0,0,0.14),0px 4px 18px 3px rgba(0,0,0,0.12)',
  '0px 6px 7px -4px rgba(0,0,0,0.2),0px 11px 15px 1px…gba(0,0,0,0.14),0px 4px 20px 3px rgba(0,0,0,0.12)',
  '0px 7px 8px -4px rgba(0,0,0,0.2),0px 12px 17px 2px…gba(0,0,0,0.14),0px 5px 22px 4px rgba(0,0,0,0.12)',
  '0px 7px 8px -4px rgba(0,0,0,0.2),0px 13px 19px 2px…gba(0,0,0,0.14),0px 5px 24px 4px rgba(0,0,0,0.12)',
  '0px 7px 9px -4px rgba(0,0,0,0.2),0px 14px 21px 2px…gba(0,0,0,0.14),0px 5px 26px 4px rgba(0,0,0,0.12)',
  '0px 8px 9px -5px rgba(0,0,0,0.2),0px 15px 22px 2px…gba(0,0,0,0.14),0px 6px 28px 5px rgba(0,0,0,0.12)',
  '0px 8px 10px -5px rgba(0,0,0,0.2),0px 16px 24px 2p…gba(0,0,0,0.14),0px 6px 30px 5px rgba(0,0,0,0.12)',
  '0px 8px 11px -5px rgba(0,0,0,0.2),0px 17px 26px 2p…gba(0,0,0,0.14),0px 6px 32px 5px rgba(0,0,0,0.12)',
  '0px 9px 11px -5px rgba(0,0,0,0.2),0px 18px 28px 2p…gba(0,0,0,0.14),0px 7px 34px 6px rgba(0,0,0,0.12)',
  '0px 9px 12px -6px rgba(0,0,0,0.2),0px 19px 29px 2p…gba(0,0,0,0.14),0px 7px 36px 6px rgba(0,0,0,0.12)',
  '0px 10px 13px -6px rgba(0,0,0,0.2),0px 20px 31px 3…gba(0,0,0,0.14),0px 8px 38px 7px rgba(0,0,0,0.12)',
  '0px 10px 13px -6px rgba(0,0,0,0.2),0px 21px 33px 3…gba(0,0,0,0.14),0px 8px 40px 7px rgba(0,0,0,0.12)',
  '0px 10px 14px -6px rgba(0,0,0,0.2),0px 22px 35px 3…gba(0,0,0,0.14),0px 8px 42px 7px rgba(0,0,0,0.12)',
  '0px 11px 14px -7px rgba(0,0,0,0.2),0px 23px 36px 3…gba(0,0,0,0.14),0px 9px 44px 8px rgba(0,0,0,0.12)',
  '0px 11px 15px -7px rgba(0,0,0,0.2),0px 24px 38px 3…gba(0,0,0,0.14),0px 9px 46px 8px rgba(0,0,0,0.12)'
];

Sizing

  • width

  • maxWidth

  • minWidth

  • height

  • maxHeight

  • minHeight

これらに関して、関連するテーマ値はありません。ただし値に関して1以下の(小数点含む)値を渡すと、それはパーセント値に変換されて使われます。これは以下のように値が変換される為です。

// `value`は指定した値
value => {
  if (value <= 1) {
    return `${value * 100}%`;
  }

  return value;
};

よって11pxではなく100%として扱われます。

Spacing

  • p

  • m

公式ドキュメントではpmプロパティが使われてますが、paddingmarginプロパティも用意されてます。

このプロパティの値へは数値を渡します。それはtheme.spacing関数の引数に使われ、その戻り値の値が実際に設定される値になります。
デフォルトのtheme.spacing値は8で、p={2}のように使うと8 x 216pxが設定されます。この基準値を変えたい場合は以下のようにテーマを作ります。

const theme = createMuiTheme({
  spacing: 2
});

またpmの後ろにtlrbと続けるとそれぞれ、paddingToppaddingLeftpaddingRightpaddingBottomのような1辺だけの値を設定できます。これらも省略しない名前のプロパティも用意されてます。

他にxyと続けて、xの場合はpaddingToppaddingBottomと縦軸、yの場合はpaddingLeftpaddingRightと横軸、を同時に設定する為のプロパティもあります。

Typography

  • fontFamily

  • fontSize

  • fontStyle

  • fontWeight

  • letterSpacing

  • lineHeight

  • textAlign

const typography = {
  htmlFontSize: 16,
  fontFamily:
    '"Roboto", "Helvetica", "Arial", sans-serif',
  fontSize: 14,
  fontWeightLight: 300,
  fontWeightRegular: 400,
  fontWeightMedium: 500,
  fontWeightBold: 700,
  h1: {
    fontFamily:
      '"Roboto", "Helvetica", "Arial", sans-serif',
    fontWeight: 300,
    fontSize: '6rem',
    lineHeight: 1.167,
    letterSpacing: '-0.01562em'
  },
  h2: {/* ... */},
  h3: {/* ... */},
  h4: {/* ... */},
  h5: {/* ... */},
  h6: {/* ... */},
  subtitle1: {/* ... */},
  subtitle2: {/* ... */},
  body1: {/* ... */},
  body2: {/* ... */},
  button: {/* ... */},
  caption: {/* ... */},
  overline: {/* ... */},
};

NoSsrコンポーネントを使うと、そのchildren要素をサーバーサイドレンダリングで無視できます。これは内部でwindowオブジェクトのようなクライアントサイドでしか動作しないようなコンポーネントを使っている場合にラップすることで、その問題を回避できます。

使うには以下で取り込みます。

import NoSsr from '@material-ui/core/NoSsr';
// import {NoSsr} from '@material-ui/core';

そして対象のコンポーネントをラップするだけです。


  

まずはRadioコンポーネントを使う準備をします。

import Radio from "@material-ui/core/Radio";

もし TypeScript 上でならRadioProps型も取り込むと便利かもしれません。

import Radio, {RadioProps} from "@material-ui/core/Radio";

まずは使ってみる

単に<Radio />と置くだけでも以下の画像のように動きます。(分かりやすいようにチェックを入れたものを横に置いてます。)

checked

(event: React.ChangeEvent, checked: boolean) => void;

 {
    console.log(changeEvent, checked /* === true */);
  }}
/>;

<input>valuechangeEventvalue

 {
    console.log(changeEvent.target.value /* === 'foo' */);
  }}
  value="foo"
/>;

<input>name

;

RadioProps<input>

;

data-foo

makeStylesuseStylesclasses

small | mediummedium

'primary' | 'secondary' | 'default''secondary'
'primary''default'

<svg>React.ReactNode<svg>

icon<svg>React.ReactNode

<>
  
    }
  />
  
    }
  />
;

import RadioGroup from '@material-ui/core/RadioGroup';

valuevalue

関連

インストール時

error An unexpected error occurred: "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.2.tgz: read ECONNRESET".

yarn install --network-timeout 1000000000                                                                                                              
# yarn install v1.17.0
# [1/4] 🔍  Resolving packages...
# [2/4] 🚚  Fetching packages...
# info There appears to be trouble with your network connection. Retrying...
# info There appears to be trouble with your network connection. Retrying...
# info There appears to be trouble with your network connection. Retrying...
# info There appears to be trouble with your network connection. Retrying...
# error An unexpected error occurred: "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.2.tgz: read ECONNRESET".
# info If you think this is a bug, please open a bug report with the information provided in "/Users/nju33/github/nju33/figma-tailwindcss/yarn-error.log".
# info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
# info There appears to be trouble with your network connection. Retrying...
# info There appears to be trouble with your network connection. Retrying...
# info There appears to be trouble with your network connection. Retrying...
# info There appears to be trouble with your network connection. Retrying...

brew upgrade yarnなど試しましたが結局治らず、結果的に再起動したら治りました🙄

JavaScript で飯食べたい歴約 8 年、 純( nju33 ) によるノートサイトです。

このサイトではドリンク代や奨学金返済の為、広告などを貼らせて頂いてますがご了承ください。

Change Log