-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'mantinedev:master' into master
- Loading branch information
Showing
222 changed files
with
3,904 additions
and
569 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ packages/*/*/styles.layer.css | |
packages/*/*/styles/*.css | ||
docs/.next | ||
docs/out | ||
*.mdx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
apps/help.mantine.dev/src/pages/q/color-scheme-flickering.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { Layout } from '@/layout'; | ||
|
||
export const meta = { | ||
title: | ||
'Why I see color scheme flickering on page load?', | ||
description: | ||
'Color scheme flickering is caused by incorrect usage of ColorSchemeScript', | ||
slug: 'color-scheme-flickering', | ||
category: 'common', | ||
tags: ['FART', 'color-scheme', 'defaultColorScheme', 'forceColorScheme'], | ||
created_at: 'November 25, 2024', | ||
last_updated_at: 'November 25, 2024', | ||
}; | ||
|
||
export default Layout(meta); | ||
|
||
## How Mantine applies color scheme | ||
|
||
Mantine color scheme is defined by `data-mantine-color-scheme="{value}"` | ||
attribute on the `:root` element (usually `html`). This attribute is used by | ||
all components to assign color scheme specific styles. | ||
|
||
Usually, you do not need to set `data-mantine-color-scheme` attribute manually, | ||
it is added by `ColorSchemeScript` (before hydration) and `MantineProvider` | ||
(after the app has been mounted) components automatically. | ||
|
||
## Flash of inaccurate color scheme | ||
|
||
Flash of inaccurate color scheme (FART) happens when the color scheme selected | ||
by the user is different from the color scheme value with which the application | ||
has been initialized. FART can occur only in applications with server-side | ||
rendering (SSR) or static site generation (SSG). | ||
|
||
In most case, FART is caused by incorrect usage of `ColorSchemeScript` component. | ||
For example, a common issue is a mismatch of `defaultColorScheme` values defined | ||
on `ColorSchemeScript` and `MantineProvider`: | ||
|
||
```tsx | ||
import { ColorSchemeScript, MantineProvider } from '@mantine/core'; | ||
|
||
// ❌ Incorrect usage – defaultColorScheme values do not match, | ||
// this will cause color scheme flickering | ||
function IncorrectDemo() { | ||
return ( | ||
<> | ||
<ColorSchemeScript defaultColorScheme="light" /> | ||
<MantineProvider defaultColorScheme="auto"> | ||
{/* Your app here */} | ||
</MantineProvider> | ||
</> | ||
); | ||
} | ||
|
||
// ✅ Correct usage – defaultColorScheme values match, no FART | ||
function CorrectDemo() { | ||
return ( | ||
<> | ||
<ColorSchemeScript defaultColorScheme="light" /> | ||
<MantineProvider defaultColorScheme="light"> | ||
{/* Your app here */} | ||
</MantineProvider> | ||
</> | ||
); | ||
} | ||
``` |
28 changes: 28 additions & 0 deletions
28
apps/help.mantine.dev/src/pages/q/how-that-thing-is-done.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { Layout } from '@/layout'; | ||
|
||
export const meta = { | ||
title: 'How that thing is done on mantine.dev website?', | ||
description: | ||
'Learn how various elements are implemented on mantine.dev website', | ||
slug: 'how-that-thing-is-done', | ||
category: 'about', | ||
tags: ['footer', 'floating button', 'layout'], | ||
created_at: 'November 16, 2024', | ||
last_updated_at: 'November 16, 2024', | ||
}; | ||
|
||
export default Layout(meta); | ||
|
||
## mantine.dev website | ||
|
||
[Mantine documentation](https://mantine.dev) website is built with Next.js and Mantine. | ||
You can find the source code of the website in the [repository](https://github.com/mantinedev/mantine). | ||
If you are interested how specific part of the website is implemented, you can browse the source code and learn from it. | ||
|
||
## How can I build the same footer? | ||
|
||
- Give footer fixed position with `position: fixed` and `bottom: 0` properties. | ||
- Create a div element that will contain all content except footer. | ||
- Set `min-height: 100vh` on the content container to make sure that footer is always under by the content. | ||
- Make sure that your content container has background color. | ||
- Done! You have a footer at the bottom of the page. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import { Layout } from '@/layout'; | ||
|
||
export const meta = { | ||
title: 'How can I test Modal/Drawer/Popover components?', | ||
description: | ||
'Learn how to use react-testing-library to test components that use portals and transitions.', | ||
slug: 'portals-testing', | ||
category: 'testing', | ||
tags: [ | ||
'modal', | ||
'drawer', | ||
'menu', | ||
'combobox', | ||
'jest', | ||
'vitest', | ||
], | ||
created_at: 'November 25, 2024', | ||
last_updated_at: 'November 25, 2024', | ||
}; | ||
|
||
export default Layout(meta); | ||
|
||
## Getting started | ||
|
||
Before jumping into the testing part, make sure that you've configured | ||
[Jest](https://mantine.dev/guides/jest) or [Vitest](https://mantine.dev/guides/vitest) in your project | ||
as specified in the documentation. Assume that `render`, `screen` and `userEvent` variables | ||
are imported from your project `test-utils` file. | ||
|
||
This guide is applicable to: | ||
|
||
- [Modal](https://mantine.dev/core/modal) | ||
- [Drawer](https://mantine.dev/core/drawer) | ||
- [Popover](https://mantine.dev/core/popover) | ||
- [Menu](https://mantine.dev/core/menu) | ||
- [Combobox](https://mantine.dev/core/combobox) | ||
- Most other component that uses [portals](https://mantine.dev/core/portal) and [transitions](https://mantine.dev/core/transition) | ||
|
||
## Testing example | ||
|
||
In all following examples we will use `AuthModal` component, it contains | ||
a button and a modal with a simple authentication form: | ||
|
||
```tsx | ||
import { Button, Modal, PasswordInput, TextInput } from '@mantine/core'; | ||
import { useDisclosure } from '@mantine/hooks'; | ||
|
||
export function AuthModal() { | ||
const [opened, { open, close }] = useDisclosure(); | ||
|
||
return ( | ||
<> | ||
<Modal title="Authenticate" opened={opened} onClose={close}> | ||
<form | ||
onSubmit={(event) => { | ||
event.preventDefault(); | ||
close(); | ||
}} | ||
> | ||
<TextInput data-autofocus label="Username" placeholder="Enter your username" /> | ||
<PasswordInput label="Password" placeholder="Enter your password" /> | ||
<Button type="submit">Log in</Button> | ||
</form> | ||
</Modal> | ||
|
||
<Button onClick={open}>Open authentication modal</Button> | ||
</> | ||
); | ||
} | ||
``` | ||
|
||
## Failing tests | ||
|
||
If try to write tests for `AuthModal` without any additional configuration, | ||
you will notice that they fail because, by default, modals use [Transition](https://mantine.dev/core/transition) | ||
component to animate opening and closing. Transition component uses `setTimeout` to delay | ||
animation start and `@testing-library/react` does not wait for `setTimeout` to finish. | ||
|
||
Example of failing tests: | ||
|
||
```tsx | ||
import { render, screen, userEvent } from '@/test-utils'; | ||
import { AuthModal } from './AuthModal'; | ||
|
||
describe('AuthModal', () => { | ||
it('opens modal when button is clicked', async () => { | ||
render(<AuthModal />); | ||
await userEvent.click(screen.getByRole('button', { name: 'Open authentication modal' })); | ||
// ⛔ Test fails, modal heading is not in the document yet | ||
// Error message: TestingLibraryElementError: Unable to find an accessible element | ||
// with the role "heading" and name "Authenticate" | ||
expect(screen.getByRole('heading', { name: 'Authenticate' })).toBeInTheDocument(); | ||
}); | ||
}); | ||
``` | ||
|
||
## Fixing failing tests | ||
|
||
The easiest way to fix this issue is to disable transitions in your tests. | ||
This can be done by creating a separate [theme](https://mantine.dev/theming/theme-object) | ||
for tests. In this theme, you need to disable transitions for all | ||
components that you plan to test. | ||
|
||
To create a custom theme for tests, replace your `render` function | ||
in `test-utils` folder with the following code: | ||
|
||
```tsx | ||
import { render as testingLibraryRender } from '@testing-library/react'; | ||
import { createTheme, MantineProvider, mergeThemeOverrides, Modal } from '@mantine/core'; | ||
// Your project theme | ||
import { theme } from '../theme'; | ||
|
||
// Merge your project theme with tests specific overrides | ||
const testTheme = mergeThemeOverrides( | ||
theme, | ||
createTheme({ | ||
components: { | ||
Modal: Modal.extend({ | ||
defaultProps: { | ||
transitionProps: { duration: 0 }, | ||
}, | ||
}), | ||
}, | ||
}) | ||
); | ||
|
||
export function render(ui: React.ReactNode) { | ||
return testingLibraryRender(<>{ui}</>, { | ||
wrapper: ({ children }: { children: React.ReactNode }) => ( | ||
<MantineProvider theme={testTheme}>{children}</MantineProvider> | ||
), | ||
}); | ||
} | ||
``` | ||
|
||
✅ Now the test from the previous example should pass is passing! | ||
|
||
## How to test that the modal is opened/closed? | ||
|
||
To verify that the modal is opened, you can check that the modal heading is in the document | ||
and an interactive element with `data-autofocus` attribute has focus: | ||
|
||
```tsx | ||
describe('AuthModal', () => { | ||
it('opens modal when button is clicked', async () => { | ||
render(<AuthModal />); | ||
await userEvent.click(screen.getByRole('button', { name: 'Open authentication modal' })); | ||
expect(screen.getByRole('heading', { name: 'Authenticate' })).toBeInTheDocument(); | ||
expect(screen.getByRole('textbox', { name: 'Username' })).toHaveFocus(); | ||
}); | ||
}); | ||
``` | ||
|
||
To verify that the modal has been closed, check that the modal heading is not in the document: | ||
|
||
```tsx | ||
describe('AuthModal', () => { | ||
it('closes modal after the form has been submitted', async () => { | ||
render(<AuthModal />); | ||
await userEvent.click(screen.getByRole('button', { name: 'Open authentication modal' })); | ||
await userEvent.type(screen.getByRole('textbox', { name: 'Username' }), 'john.doe'); | ||
await userEvent.type(screen.getByLabelText('Password'), 'password'); | ||
await userEvent.click(screen.getByRole('button', { name: 'Log in' })); | ||
expect(screen.queryByRole('heading', { name: 'Authenticate' })).not.toBeInTheDocument(); | ||
}); | ||
}); | ||
``` |
17 changes: 14 additions & 3 deletions
17
...mantine.dev/src/pages/submit-template.mdx → ...ntine.dev/src/pages/q/submit-template.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.