7.x → 8.x 마이그레이션 가이드
7.x → 8.x 마이그레이션 가이드
7.x에서 8.x로 버전을 올리면서 주의해야 할 주요 변경 사항들을 다뤄요. 스타일 import, Portal, Switch, 날짜 문자열 값, CodeHighlight, Carousel 등 변경점을 하나씩 설명해 드릴게요.
출처: 문서
본문
전역 스타일 import
@mantine/core/styles/global.css를 따로 import했다면 새 파일을 사용하도록 바꿔야 해요. 이전에 @mantine/core/styles.css를 import했다면 변경이 필요 없어요. 모든 새 파일은 이미 styles.css에 포함되어 있거든요.
7.x 버전 import:
// ❌ No longer includes all global styles
import '@mantine/core/styles/global.css';
8.x 버전 import:
// ✅ Import all global styles separately
import '@mantine/core/styles/baseline.css';
import '@mantine/core/styles/default-css-variables.css';
import '@mantine/core/styles/global.css';
@mantine/core/styles.css를 사용했다면 변경이 필요 없어요. import가 7.x와 8.x에서 동일하게 동작해요:
// 👍 No changes needed if you used styles.css
import '@mantine/core/styles.css';
Portal reuseTargetNode
Portal 컴포넌트의 reuseTargetNode prop이 이제 기본적으로 활성화돼요. 이 옵션은 포털 렌더링 사이에 대상 노드를 재사용해 성능을 개선하지만, 일부 엣지 케이스에서 z-index 스태킹 컨텍스트 문제를 일으킬 수 있어요.
z-index 문제가 생기면 테마에서 reuseTargetNode prop을 false로 바꿔주세요:
import { createTheme, Portal } from '@mantine/core';
export const theme = createTheme({
components: {
Portal: Portal.extend({
defaultProps: {
// ✅ Disable reuseTargetNode by default if your application has z-index issues
reuseTargetNode: false,
},
}),
}
});
Switch withThumbIndicator
Switch 컴포넌트의 기본 스타일이 갱신되어 이제 썸(thumb) 안에 checked 상태 표시기가 포함돼요. 표시기 없는 예전 스타일을 쓰고 싶다면 테마에서 withThumbIndicator prop을 false로 설정하세요:
import { createTheme, Switch } from '@mantine/core';
export const theme = createTheme({
components: {
Switch: Switch.extend({
defaultProps: {
// ✅ Disable withThumbIndicator if you want to use old styles
withThumbIndicator: false,
},
}),
}
});
날짜 문자열 값 (Date string values)
@mantine/dates 컴포넌트는 이제 onChange와 다른 콜백에서 날짜 문자열 값을 사용해요. 7.x와 같은 방식으로 @mantine/dates 컴포넌트를 계속 사용하고 싶다면 콜백 값을 Date 객체로 변환해야 해요:
import { useState } from 'react';
import { DatePicker } from '@mantine/dates';
export function Demo7x() {
const [value, setValue] = useState<Date | null>(null);
// ⛔ 7.x – onChange is called with Date object
return <DatePicker value={value} onChange={setValue} />
}
export function Demo8x() {
const [value, setValue] = useState<Date | null>(null);
// ✅ 8.x – onChange is called with string date value (for example '1994-08-21')
// You can either
// 1. Convert it to Date object to preserve old behavior
// 2. Update your code to use date string values instead
return <DatePicker value={value} onChange={val => setValue(new Date(val))} />
}
DatesProvider timezone
DatesProvider 컴포넌트는 더 이상 timezone 옵션을 지원하지 않아요:
import { DatesProvider } from '@mantine/dates';
function Demo7x() {
// ❌ The timezone option is no longer supported
return (
<DatesProvider settings={{ timezone: 'UTC', consistentWeeks: true }}>
App
</DatesProvider>
);
}
function Demo8x() {
// ✅ Remove the timezone option
return (
<DatesProvider settings={{ consistentWeeks: true }}>
App
</DatesProvider>
);
}
애플리케이션에서 타임존을 처리해야 한다면 전용 날짜 라이브러리(dayjs, luxon, date-fns)로 타임존 값을 갱신할 수 있어요. dayjs와 함께 Mantine 컴포넌트를 사용하는 예시:
import dayjs from 'dayjs';
import { DatePicker } from '@mantine/dates';
function Demo() {
const [value, setValue] = useState<string | null>('2022-08-21');
// Mantine components use strings as values; you can pass these
// strings to a date library of your choice to assign a timezone
const dateWithTimeZone = dayjs(value).tz("America/Toronto").toDate();
return <DatePicker value={value} onChange={setValue} />;
}
DateTimePicker timeInputProps
DateTimePicker 컴포넌트는 더 이상 timeInputProps prop을 받지 않아요. 내부 TimeInput 컴포넌트가 TimePicker로 교체됐기 때문이에요. TimePicker 컴포넌트에 props를 전달하려면 timePickerProps prop을 사용하세요.
7.x 버전:
import { DateTimePicker } from '@mantine/dates';
import { ClockIcon } from '@phosphor-icons/react';
function Demo() {
return (
<DateTimePicker
// ❌ timeInputProps is no longer available
timeInputProps={{
leftSection: <ClockIcon size={16} />,
}}
/>
);
}
8.x 버전:
import { DateTimePicker } from '@mantine/dates';
function Demo() {
return (
<DateTimePicker
// ✅ Use timePickerProps instead of timeInputProps
timePickerProps={{
leftSection: <ClockIcon size={16} />,
minutesStep: 5,
withDropdown: true,
}}
/>
);
}
CodeHighlight 사용법
@mantine/code-highlight 패키지는 더 이상 highlight.js에 의존하지 않아요. 갱신된 문서를 따라 shiki로 구문 하이라이팅을 설정할 수 있어요.
애플리케이션에서 계속 highlight.js를 사용하고 싶다면 highlight.js 패키지를 설치하세요:
yarn add highlight.js
그런 다음 앱을 CodeHighlightAdapterProvider로 감싸고 adapter prop에 createHighlightJsAdapter를 제공하세요:
import { MantineProvider } from '@mantine/core';
import { CodeHighlightAdapterProvider, createHighlightJsAdapter } from '@mantine/code-highlight';
import hljs from 'highlight.js/lib/core';
import tsLang from 'highlight.js/lib/languages/typescript';
hljs.registerLanguage('typescript', tsLang);
const highlightJsAdapter = createHighlightJsAdapter(hljs);
function App() {
return (
<MantineProvider>
<CodeHighlightAdapterProvider adapter={highlightJsAdapter}>
{/* Your app here */}
</CodeHighlightAdapterProvider>
</MantineProvider>
);
}
그런 다음 highlight.js 테마 중 하나의 스타일을 애플리케이션에 추가해야 해요. highlight.js 패키지의 CSS 파일을 import하거나 CDN 링크로 애플리케이션의 <head>에 추가하면 돼요:
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css"
/>
이후에는 7.x에서 했던 것과 같은 방식으로 애플리케이션에서 CodeHighlight 컴포넌트를 사용할 수 있어요.
Menu data-hovered 속성
Menu.Item은 더 이상 hovered 상태를 나타내는 data-hovered 속성을 사용하지 않아요. 스타일에 data-hovered를 사용했다면 대신 :hover와 :focus 선택자로 바꿔야 해요:
// ❌ 7.x – styles with `data-hovered`,
// no longer works in 8.x
.item {
&[data-hovered] {
background-color: red;
}
}
// ✅ 8.x – use styles with `:hover` and `:focus`
.item {
&:hover,
&:focus {
background-color: red;
}
}
Popover hideDetached
Popover는 이제 대상 요소가 DOM에서 제거될 때 팝오버를 자동으로 닫는 hideDetached prop을 지원해요:
import { Box, Button, Group, Popover } from '@mantine/core';
function Demo() {
return (
<Box
bd="1px solid var(--mantine-color-dimmed)"
p="xl"
w={{ base: 340, sm: 400 }}
h={200}
style={{ overflow: 'auto' }}
>
<Box w={1000} h={400}>
<Group>
<Popover width="target" position="bottom" opened>
<Popover.Target>
<Button>Toggle popover</Button>
</Popover.Target>
<Popover.Dropdown>This popover dropdown is hidden when detached</Popover.Dropdown>
</Popover>
<Popover width="target" position="bottom" opened hideDetached={false}>
<Popover.Target>
<Button>Toggle popover</Button>
</Popover.Target>
<Popover.Dropdown>This popover dropdown is visible when detached</Popover.Dropdown>
</Popover>
</Group>
</Box>
</Box>
);
}
기본적으로 hideDetached는 활성화되어 있어요. 7.x에서 동작이 바뀐 것이에요. 예전 동작을 유지하고 싶다면 모든 컴포넌트에서 hideDetached를 비활성화할 수 있어요:
import { createTheme, Popover } from '@mantine/core';
export const theme = createTheme({
components: {
Popover: Popover.extend({
defaultProps: {
// ✅ Disable hideDetached by default
// if you want to keep the old behavior
hideDetached: false,
},
}),
}
});
Carousel 변경 사항
8.x부터 @mantine/carousel 패키지는 8.x 버전의 embla-carousel과 embla-carousel-react 패키지를 요구해요.
embla 의존성을 갱신해야 해요:
yarn add embla-carousel@^8.5.2 embla-carousel-react@^8.5.2
이전에 Carousel 컴포넌트에 전달하던 embla props를 emblaOptions로 바꾸세요. 전체 props 목록:
loopalignslidesToScrolldragFreeinViewThresholdskipSnapscontainScrollspeed와draggableprops는 제거됐어요. embla가 더 이상 지원하지 않아요
import { Carousel } from '@mantine/carousel';
// ❌ 7.x – embla options passed as props,
// no longer works in 8.x
function Demo7x() {
return <Carousel loop dragFree align="start" />
}
// ✅ 8.x – use emblaOptions to pass options to embla
function Demo8x() {
return <Carousel emblaOptions={{ loop: true, dragFree: true, align: 'start' }} />
}
useAnimationOffsetEffect 훅은 제거됐어요. 더 이상 필요하지 않으므로 코드에서 제거해야 해요:
// ❌ 7.x – useAnimationOffsetEffect is no longer available in 8.x
import { Carousel, Embla, useAnimationOffsetEffect } from '@mantine/carousel';
function Demo7x() {
const [embla, setEmbla] = useState<Embla | null>(null);
useAnimationOffsetEffect(embla, TRANSITION_DURATION);
return <Carousel getEmblaApi={setEmbla} />;
}
// ✅ 8.x – remove useAnimationOffsetEffect entirely; it is not required
import { Carousel } from '@mantine/carousel';
function Demo8x() {
return <Carousel />;
}
Embla 타입은 더 이상 @mantine/carousel 패키지에서 내보내지지 않아요. 이 import를 embla-carousel 패키지를 참조하도록 바꿔야 해요:
// ❌ 7.x – The Embla type is no longer available in 8.x
import { Carousel, Embla } from '@mantine/carousel';
function Demo7x() {
const [embla, setEmbla] = useState<Embla | null>(null);
return <Carousel getEmblaApi={setEmbla} />;
}
// ✅ 8.x – replace the Embla type import
import { Carousel } from '@mantine/carousel';
import { EmblaCarouselType } from 'embla-carousel';
function Demo8x() {
const [embla, setEmbla] = useState<EmblaCarouselType | null>(null);
return <Carousel getEmblaApi={setEmbla} />;
}
더 알아보기 (Learn more)
- 6.x to 7.x migration — 6.x → 7.x 마이그레이션
- 8.x to 9.x migration — 8.x → 9.x 마이그레이션