This commit is contained in:
bipproduction
2026-04-01 10:43:03 +08:00
parent 816db7568c
commit 39d659acd0
175 changed files with 21765 additions and 0 deletions

View File

@@ -0,0 +1,472 @@
# Styling & Theming Reference
Mantine styling: MantineProvider, theme object, CSS modules, style props, and Styles API.
## MantineProvider
Required wrapper for all Mantine components:
```tsx
import { createTheme, MantineProvider } from '@mantine/core';
const theme = createTheme({
primaryColor: 'blue',
fontFamily: 'Inter, sans-serif',
});
function App() {
return (
<MantineProvider theme={theme}>
{/* App content */}
</MantineProvider>
);
}
```
### Key Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `theme` | `MantineThemeOverride` | - | Theme customization |
| `defaultColorScheme` | `'light' \| 'dark' \| 'auto'` | `'light'` | Default color scheme |
| `forceColorScheme` | `'light' \| 'dark'` | - | Force specific scheme |
| `env` | `'default' \| 'test'` | `'default'` | Disable transitions for tests |
## Theme Object
```tsx
import { createTheme, rem } from '@mantine/core';
const theme = createTheme({
// Colors
primaryColor: 'blue',
primaryShade: { light: 6, dark: 8 },
// Typography
fontFamily: 'Inter, sans-serif',
headings: {
fontFamily: 'Greycliff CF, sans-serif',
fontWeight: '700',
},
// Spacing & Sizing
spacing: { xs: rem(10), sm: rem(12), md: rem(16), lg: rem(20), xl: rem(32) },
radius: { xs: rem(2), sm: rem(4), md: rem(8), lg: rem(16), xl: rem(32) },
// Defaults
defaultRadius: 'md',
cursorType: 'pointer',
respectReducedMotion: true,
});
```
## Custom Colors
```tsx
import { createTheme, MantineColorsTuple } from '@mantine/core';
const brand: MantineColorsTuple = [
'#f0f9ff', '#e0f2fe', '#bae6fd', '#7dd3fc', '#38bdf8',
'#0ea5e9', '#0284c7', '#0369a1', '#075985', '#0c4a6e',
];
const theme = createTheme({
colors: { brand },
primaryColor: 'brand',
});
```
## Color Scheme (Dark Mode)
```tsx
import { useMantineColorScheme, useComputedColorScheme } from '@mantine/core';
function ColorSchemeToggle() {
const { setColorScheme, toggleColorScheme } = useMantineColorScheme();
const computed = useComputedColorScheme('light'); // Resolved value
return (
<>
<Button onClick={() => setColorScheme('light')}>Light</Button>
<Button onClick={() => setColorScheme('dark')}>Dark</Button>
<Button onClick={toggleColorScheme}>Toggle</Button>
</>
);
}
// SSR: Prevent flash of wrong color scheme
import { ColorSchemeScript, mantineHtmlProps } from '@mantine/core';
<html {...mantineHtmlProps}>
<head>
<ColorSchemeScript defaultColorScheme="auto" />
</head>
</html>
```
## Style Props
All components accept style props for quick styling:
```tsx
import { Box, Text, Button } from '@mantine/core';
function Demo() {
return (
<Box
p="md" // padding
m="lg" // margin
mt="xl" // margin-top
bg="blue.6" // background (color.shade)
c="white" // color
w={200} // width (number = px)
h="100%" // height
maw={500} // max-width
pos="relative" // position
ta="center" // text-align
fz="sm" // font-size
fw={700} // font-weight
ff="monospace" // font-family
lh={1.5} // line-height
style={{ borderRadius: 'var(--mantine-radius-md)' }}
>
<Text c="dimmed" fz="xs" tt="uppercase">
Uppercase dimmed text
</Text>
</Box>
);
}
```
### Common Style Props
| Prop | CSS Property | Example |
|------|--------------|---------|
| `m`, `mx`, `my`, `mt`, `mr`, `mb`, `ml` | margin | `m="md"`, `mt={20}` |
| `p`, `px`, `py`, `pt`, `pr`, `pb`, `pl` | padding | `p="lg"` |
| `w`, `h`, `maw`, `mah`, `miw`, `mih` | width, height, max/min | `w="100%"` |
| `c` | color | `c="blue.6"`, `c="dimmed"` |
| `bg` | background-color | `bg="gray.1"` |
| `fz` | font-size | `fz="sm"`, `fz={14}` |
| `fw` | font-weight | `fw={500}`, `fw="bold"` |
| `ta` | text-align | `ta="center"` |
| `td` | text-decoration | `td="underline"` |
| `tt` | text-transform | `tt="uppercase"` |
| `ff` | font-family | `ff="monospace"` |
| `lh` | line-height | `lh={1.5}` |
| `pos` | position | `pos="absolute"` |
| `top`, `left`, `right`, `bottom` | position offsets | `top={10}` |
| `display` | display | `display="flex"` |
| `opacity` | opacity | `opacity={0.5}` |
### Responsive Props
```tsx
<Box
w={{ base: '100%', sm: '50%', md: 400 }}
p={{ base: 'xs', md: 'xl' }}
display={{ base: 'none', md: 'block' }}
>
Responsive box
</Box>
```
## CSS Modules
Recommended styling approach. Create `.module.css` files:
```css
/* Button.module.css */
.root {
background-color: var(--mantine-color-blue-6);
@mixin hover {
background-color: var(--mantine-color-blue-7);
}
/* Responsive */
@mixin smaller-than sm {
font-size: var(--mantine-font-size-xs);
}
@mixin larger-than md {
padding: var(--mantine-spacing-xl);
}
/* Dark mode */
@mixin dark {
background-color: var(--mantine-color-blue-8);
}
@mixin light {
background-color: var(--mantine-color-blue-4);
}
}
.label {
color: var(--mantine-color-white);
}
```
```tsx
import { Button } from '@mantine/core';
import classes from './Button.module.css';
function Demo() {
return (
<Button classNames={classes}>
Styled button
</Button>
);
}
```
## PostCSS Preset
`postcss-preset-mantine` provides:
### Mixins
```css
/* Hover state */
@mixin hover {
/* Hover-only styles */
}
/* Responsive breakpoints */
@mixin smaller-than sm { }
@mixin larger-than md { }
/* Color scheme */
@mixin light { }
@mixin dark { }
/* RTL support */
@mixin rtl { }
@mixin ltr { }
```
### Functions
```css
.element {
/* rem() - convert to rem */
font-size: rem(16px); /* 1rem */
/* em() - convert to em */
padding: em(24px); /* 1.5em */
/* light-dark() - color scheme values */
background: light-dark(white, black);
/* alpha() - add opacity to color */
background: alpha(var(--mantine-color-blue-5), 0.5);
}
```
## Styles API
Override internal component styles:
### classNames Prop
```tsx
import { TextInput } from '@mantine/core';
import classes from './TextInput.module.css';
// CSS module with selectors matching Styles API
// .root, .input, .label, .error, etc.
<TextInput
classNames={{
root: classes.root,
input: classes.input,
label: classes.label,
}}
/>
```
### styles Prop (CSS-in-JS)
```tsx
<TextInput
styles={{
root: { marginBottom: 20 },
input: { backgroundColor: 'var(--mantine-color-gray-0)' },
label: { fontWeight: 700 },
}}
/>
```
### styles Function
```tsx
<TextInput
styles={(theme, props) => ({
input: {
borderColor: props.error
? theme.colors.red[6]
: theme.colors.gray[4],
},
})}
/>
```
### Finding Selectors
All Styles API selectors are documented for each component. Common patterns:
- `root` - Root element
- `label` - Label text
- `input` - Input element
- `wrapper` - Input wrapper
- `error` - Error message
- `description` - Description text
- `required` - Required asterisk
- `section` - Input sections (left/right icons)
## hiddenFrom / visibleFrom
Hide/show at breakpoints:
```tsx
import { Text } from '@mantine/core';
<Text hiddenFrom="sm">Hidden on sm and larger</Text>
<Text visibleFrom="md">Visible only on md and larger</Text>
```
## lightHidden / darkHidden
Hide based on color scheme:
```tsx
<Text lightHidden>Only in dark mode</Text>
<Text darkHidden>Only in light mode</Text>
```
## Box Component
Base component for custom styling:
```tsx
import { Box } from '@mantine/core';
<Box
component="section" // Render as different element
className={classes.wrapper}
p="md"
bg="gray.1"
style={{ borderRadius: 'var(--mantine-radius-md)' }}
>
Content
</Box>
```
## Polymorphic Components
Many components accept `component` prop:
```tsx
import { Button } from '@mantine/core';
import { Link } from 'react-router-dom';
// Render Button as Link
<Button component={Link} to="/about">
About
</Button>
// Render as native anchor
<Button component="a" href="https://example.com">
External
</Button>
```
## CSS Variables in Styles
Access theme values:
```tsx
<Box
style={{
backgroundColor: 'var(--mantine-color-blue-6)',
padding: 'var(--mantine-spacing-md)',
borderRadius: 'var(--mantine-radius-sm)',
boxShadow: 'var(--mantine-shadow-md)',
}}
>
Styled with CSS variables
</Box>
```
## Global Styles
```tsx
// In your CSS
:root {
--my-custom-color: #ff6b6b;
}
/* Target Mantine root element */
[data-mantine-color-scheme="dark"] {
--my-custom-color: #ff8787;
}
/* Global component overrides */
.mantine-Button-root {
font-weight: 600;
}
```
## rem() and em() Utilities
```tsx
import { rem, em } from '@mantine/core';
// In styles or inline
<Box style={{ fontSize: rem(16), padding: rem(24) }} />
// rem(16) => '1rem'
// em(24) => '1.5em'
```
## Style Props vs CSS Modules
| Use Case | Recommended |
|----------|-------------|
| Quick prototyping | Style props |
| Simple spacing/colors | Style props |
| Complex hover/focus states | CSS modules |
| Responsive layouts | CSS modules |
| Reusable component styles | CSS modules |
| Performance critical | CSS modules |
## Component Default Props (Theme)
Override defaults globally:
```tsx
const theme = createTheme({
components: {
Button: Button.extend({
defaultProps: { variant: 'outline', size: 'md', radius: 'xl' },
}),
TextInput: TextInput.extend({
defaultProps: { size: 'md' },
classNames: { root: 'my-input-root', input: 'my-input' },
}),
},
});
```
## CSS Variables Reference
```
--mantine-color-{color}-{shade} // Colors (0-9)
--mantine-primary-color-{shade} // Primary color
--mantine-spacing-{size} // xs, sm, md, lg, xl
--mantine-radius-{size} // xs, sm, md, lg, xl
--mantine-font-family // Main font
--mantine-font-size-{size} // xs, sm, md, lg, xl
--mantine-breakpoint-{size} // Responsive breakpoints
```