Mantine v7.0.0のまとめ
こちらは以下の記事の一部(既存コンポーネントの変更点や新規コンポーネントなどの一部が除外してあります)を翻訳して軽くまとめた記事になります。
Migration to native CSS
Mantine はスタイル生成を Emotion に依存しなくなりました。これによりパフォーマンスの向上とバンドルサイズが小さくなりました。またCSS-in-JSがサポートされていないNext.jsのappディレクトリなどで使用できるようになりました。
重要な変更点は以下の3点
- createStyles関数は使用できなくなりました。代わりにCSS modulesや他のスタイリングライブラリを使用してください。
- sx propsのサポート終了。代わりにclassNameやstyle propsを使用してください。
- styles propsはネストされたセレクタをサポートしなくなりました。
Mantineのスタイル設定にはCSS modulesが推奨されるようになりました。CSS modulesを使用したスタイリングに更新する場合は以下の記事に従ってください。
Vanilla extract integration
CSS-in-jsの構文を使いたいならVanilla extractが使用できる。詳しくは以下の記事へ。
System color scheme support
全てのコンポーネントがsystem color scheme(システムカラーテーマ)をサポートするようになりました。colorSchemeの値がautoの場合、コンポーネントはprefers-color-schemeメディアクエリを使用して、ユーザーが明るい配色を好むか暗い配色を好むかを判断します。
autoはデフォルト値ではなく、以下のようにMantineProvierとColorSchemeScriptの両方で設定が必要です。
import { MantineProvider, ColorSchemeScript } from '@mantine/core';
function Demo() {
return (
<>
<ColorSchemeScript defaultColorScheme="auto" />
<MantineProvider defaultColorScheme="auto">
<App />
</MantineProvider>
</>
);
}
Built-in color scheme manager
MantineProvierにビルトインのカラーテーママネージャーが搭載されました。useMantineColorSchemeフックを使用してカラーテーマを変更することができます。値にはlight,dark,autoがセットできます。
import { useMantineColorScheme, Button, Group } from '@mantine/core';
function Demo() {
const { setColorScheme, clearColorScheme } = useMantineColorScheme();
return (
<Group>
<Button onClick={() => setColorScheme('light')}>Light</Button>
<Button onClick={() => setColorScheme('dark')}>Dark</Button>
<Button onClick={() => setColorScheme('auto')}>Auto</Button>
<Button onClick={clearColorScheme}>Clear</Button>
</Group>
);
}
CSS modules and PostCSS preset
postcss-preset-mantineはスタイリングの際に便利な関数とmixinを提供してくれます。こちらの使用を推奨しています。
Global styles
Mantineはもはやnormalize.cssを含んでいません。その代わりに、最低限のグローバルスタイルを使用します。これらのスタイルは @mantine/core パッケージの一部であり、アプリケーションで @mantine/core/styles.css をインポートすると自動的に適用されます。この最低限のグローバルスタイルを削除することはできません。
Mantine as a headless UI library
アプリケーションの中で @mantine/*/styles.css をインポートしなければ、Mantine をヘッドレスライブラリとして使うことができます。
createTheme function
createTheme関数でテーマの上書きができます。その際にプロパティ名を自動補完してくれます。
import { createTheme, MantineProvider } from '@mantine/core';
const theme = createTheme({
fontFamily: 'sans-serif',
primaryColor: 'orange',
});
function Demo() {
return (
<MantineProvider theme={theme}>
<App />
</MantineProvider>
);
}
Components extend functions
default propsまたはStyles APIをサポートするすべてのコンポーネントにextend関数が追加され、テーマ上でコンポーネントのdefaultProps、classNames、stylesをカスタマイズする際に自動補完をしてくれるようになりました。
import { useState } from 'react';
import { TextInput, MantineProvider, createTheme } from '@mantine/core';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
TextInput: TextInput.extends({
styles: (theme, props) => ({
input: {
fontSize: props.size === 'compact' ? theme.fontSizes.sm : undefined,
}
})
classNames: {
root: classes.root,
input: classes.input,
label: classes.label,
},
defaultProps: {
size: 'compact',
},
}),
},
});
function Demo() {
return (
<MantineProvider theme={theme}>
<App />
</MantineProvider>
);
}
classNames based on component props
classNamesとstylesでコンポーネントのpropsを取得し、条件付きでスタイルを適用できるようになりました。
.labelRequired {
color: var(--mantine-color-red-filled);
}
.inputError {
background-color: var(--mantine-color-red-light);
}
import cx from 'clsx';
import { TextInput } from '@mantine/core';
import { useEffect, useState } from 'react';
import { theme } from '../theme';
import classes from './Demo.module.css';
function Demo() {
return (
<MantineProvider theme={theme}>
<TextInput
label="Required input"
placeholder="Required input"
required
classNames={(_, props) => ({
label: cx({ [classes.labelRequired]: props.required }),
input: cx({ [classes.inputError]: props.error }),
})}
/>
</MantineProvider>
);
}
Components CSS variables
ほとんどの Mantine コンポーネントは、色、サイズ、パディング、その他のプロパティを定義するために CSS変数を使用します。CSS変数の情報は、コンポーネントドキュメントの「Styles API」タブで確認できます。これらの値を上書きするには、theme.componentsのカスタムCSS変数リゾルバー関数を使うか、vars propを使用します。
- theme.componentsをカスタムする場合
import { Button, rem, Group, MantineProvider, createTheme } from '@mantine/core';
const theme = createTheme({
components: {
Button: Button.extend({
vars: (theme, props) => {
if (props.size === 'xxl') {
return {
root: {
'--button-height': rem(60),
'--button-padding-x': rem(30),
'--button-fz': rem(24),
},
};
}
if (props.size === 'xxs') {
return {
root: {
'--button-height': rem(24),
'--button-padding-x': rem(10),
'--button-fz': rem(10),
},
};
}
return { root: {} };
},
}),
},
});
function Demo() {
return (
<MantineProvider theme={theme}>
<Group>
<Button size="xxl">XXL Button</Button>
<Button size="xxs">XXS Button</Button>
</Group>
</MantineProvider>
);
}
- vars propを使用する場合
import { Button, rem, PartialVarsResolver, ButtonFactory, Group } from '@mantine/core';
const varsResolver: PartialVarsResolver<ButtonFactory> = (theme, props) => {
if (props.size === 'xxl') {
return {
root: {
'--button-height': rem(60),
'--button-padding-x': rem(30),
'--button-fz': rem(24),
},
};
}
if (props.size === 'xxs') {
return {
root: {
'--button-height': rem(24),
'--button-padding-x': rem(10),
'--button-fz': rem(10),
},
};
}
return { root: {} };
};
function Demo() {
return (
<Group>
<Button vars={varsResolver} size="xxl">
XXL Button
</Button>
<Button vars={varsResolver} size="xxs">
XXS Button
</Button>
</Group>
);
}
New variants system
すべてのコンポーネントがルート要素にdata-variant属性を持つようになりました。同じvariantを持つすべてのコンポーネントにスタイルを適用するために使用できます。
.input {
&[data-variant='underline'] {
border-bottom: rem(2px) solid;
border-radius: 0;
padding-left: 0;
padding-right: 0;
@mixin light {
border-color: var(--mantine-color-gray-3);
}
@mixin dark {
border-color: var(--mantine-color-dark-3);
}
&:focus {
border-color: var(--mantine-color-blue-filled);
}
}
}
import { Input, MantineProvider, createTheme } from '@mantine/core';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
Input: Input.extend({ classNames: classes }),
}
});
function Demo() {
return (
<MantineProvider theme={theme}>
<Input variant="underline" placeholder="Underline input" />
<Input variant="filled" placeholder="Filled input" mt="md" />
</MantineProvider>
);
}
New sizes system
コンポーネントのsizeのカスタマイズ方法は複数存在します。
- data-size属性
- CSS variables
- static CSS variables
以下の例はdata-size属性でサイズをカスタマイズする方法になります。
.wrapper {
&[data-size='xxl'] {
& .input {
padding-left: rem(28px);
padding-right: rem(28px);
height: rem(68px);
font-size: rem(28px);
}
}
&[data-size='xxs'] {
& .input {
padding-left: rem(10px);
padding-right: rem(10px);
height: rem(28px);
font-size: rem(10px);
}
}
}
import { Input, createTheme, MantineProvider } from '@mantine/core';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
Input: Input.extend({ classNames: classes }),
},
});
function Demo() {
return (
<MantineProvider theme={theme}>
<Input placeholder="Size XXL" size="xxl" />
<Input placeholder="Size XXS" size="xxs" mt="md" />
</MantineProvider>
);
}
theme.variantColorResolver
theme.variantColorResolver を使って、デフォルトのvariantで扱う色をカスタマイズしたり、新しいvariantのサポートを追加したりすることができます。theme.variantColorResolverは以下のプロパティを持つオブジェクトを返さなければなりません。
interface VariantColorResolverResult {
background: string;
hover: string;
color: string;
border: string;
}
以下はデフォルトのvariantで扱う色のカスタムと新しいvariantのサポート追加の例です。
import {
Button,
Group,
MantineProvider,
defaultVariantColorsResolver,
VariantColorsResolver,
parseThemeColor,
rem,
rgba,
darken,
} from '@mantine/core';
const variantColorResolver: VariantColorsResolver = (input) => {
const defaultResolvedColors = defaultVariantColorsResolver(input);
const parsedColor = parseThemeColor({
color: input.color || input.theme.primaryColor,
theme: input.theme,
});
// プロパティの上書き
if (parsedColor.isThemeColor && parsedColor.color === 'lime' && input.variant === 'filled') {
return { ...defaultResolvedColors, color: 'var(--mantine-color-black)' };
}
// 完全に上書き
if (input.variant === 'light') {
return {
background: rgba(parsedColor.value, 0.1),
hover: rgba(parsedColor.value, 0.15),
border: `${rem(1)} solid ${parsedColor.value}`,
color: darken(parsedColor.value, 0.1),
};
}
// 新しいvariantの追加
if (input.variant === 'danger') {
return {
background: 'var(--mantine-color-red-9)',
hover: 'var(--mantine-color-red-8)',
color: 'var(--mantine-color-white)',
border: 'none',
};
}
return defaultResolvedColors;
};
function Demo() {
return (
<MantineProvider theme={{ variantColorResolver }}>
<Group>
<Button color="lime.4" variant="filled">
Lime filled button
</Button>
<Button color="orange" variant="light">
Orange light button
</Button>
<Button variant="danger">Danger button</Button>
</Group>
</MantineProvider>
);
}
rem units scaling
rem単位の拡大縮小が可能になりました。html/:root要素のフォントサイズを変更し、Mantineコンポーネントのサイズを保持したい場合に便利です。例えば、htmlのフォントサイズを10pxに設定した場合、scaleを1 / (10 / 16)= 1 / 0.625 = 1.6に設定するとコンポーネントのサイズを保持できます。
import { MantineProvider, createTheme } from '@mantine/core';
const theme = createTheme({
scale: 1.6,
});
function Demo() {
return (
<MantineProvider theme={theme}>
<App />
</MantineProvider>
);
}
color prop improvements
カラーpropをサポートするすべてのコンポーネントが、以下のカラー値をサポートするようになりました。
- theme.colorsのキー。例えばblue
- theme.colorsのインデックス参照。例えばblue.5
- 有効な色を表す値。例えば #fff, rgba(0, 0, 0, 0.5), hsl(0, 0%, 100%)
Components classes
各コンポーネントのクラスは、Component.classesオブジェクトで利用できるようになりました。例えば、ButtonのクラスはButton.classesにあります。これらのクラスを使用して、Mantineコンポーネントと同じスタイルのコンポーネントを作成できます。
import { Button } from '@mantine/core';
function Demo() {
return <button type="button" className={Button.classes.root} />;
}
Colors generator
新しい@mantine/colors-generatorパッケージは、単一のカラー値に基づいてカラーパレットを生成するために利用可能になりました。オンラインツールとしても利用できます。コントラストの問題を避けるためにも通常は事前に色を生成しておく方がよいでしょう。
New setup for RTL
mantine/coreパッケージはDirectionProviderコンポーネントをエクスポートするようになりました。すべてのコンポーネントがデフォルトでRTLスタイルを含むようになりました。DirectionProviderの設定でコンポーネントの向きを変えられるようです。
詳しくはRTLのドキュメントをご覧ください。
React 18+ only
バージョン7.0から、Mantineは古いバージョンのReactをサポートしなくなりました。最小サポートバージョンは React 18 になりました。これは Mantine コンポーネントが useId と useSyncExternalStore フックを使用するようになり、React 18 でのみ使用できるようになったためです。
left and right section
以前rightSectionとiconのプロップを持っていたコンポーネントは、iconの代わりにleftSectionを使うようになりました。
withErrorStyles prop
全てのInputコンポーネントでwithErrorStyles propのサポートがされた。error propが設定されているときにテキストとボーダーの色を赤くするかどうか設定できます。デフォルトではtrue。
hiddenFrom and visibleFrom props
すべてのMantineコンポーネントがhiddenFromとvisibleFromプロップをサポートするようになりました。これらのプロップはブレークポイント(xs, sm, md, lg, xl)を受け取り、ビューポートの幅が指定されたブレークポイントにより大きいか小さいかでコンポーネントの表示を切り替えることができます。
まとめ
今回の記事は以上になります。大きな変更もありv6からv7にアップデートするためには少し対応に時間が必要かなと思いました!
もっと詳しく知りたいと思った方は是非公式ドキュメントを読んでみてください!
Discussion