Skip to content

Instantly share code, notes, and snippets.

@Grawl
Last active April 16, 2025 15:44
Show Gist options
  • Save Grawl/3ae35d9e7a250d1dcf3b8fd5583f2b2b to your computer and use it in GitHub Desktop.
Save Grawl/3ae35d9e7a250d1dcf3b8fd5583f2b2b to your computer and use it in GitHub Desktop.
unplugin-mantine-autoload-css
import { readdirSync } from 'node:fs'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tsconfigPaths from 'vite-tsconfig-paths'
import { createVitePlugin, type UnpluginFactory } from 'unplugin'
const mantineCoreStylesDirectory = '@mantine/core/styles'
// https://mantine.dev/styles/css-files-list/#components-dependencies
// shared subcomponents dependencies are not detected by this module
// so we load them all
// all these files are ~30KB combined VS more than 200 KB of all Mantine styles combined
const shared = [
'ScrollArea',
'UnstyledButton',
'VisuallyHidden',
'Paper',
'Popover',
'CloseButton',
'Group',
'Loader',
'Overlay',
'ModalBase',
'Input',
'InlineInput',
'Flex',
'FloatingIndicator',
'ActionIcon',
]
const mantineAutoloadCSSFactory: UnpluginFactory<{ layer: boolean } | undefined> = (
{ layer } = { layer: true },
) => {
const selectVariant = (name: string): string => [name, layer ? '.layer.css' : '.css'].join('')
const cssFileNames = readdirSync(`node_modules/${mantineCoreStylesDirectory}`)
return {
name: 'unplugin-mantine-autoload-css',
transformInclude: (id) => id.endsWith('.ts') || id.endsWith('.tsx'),
transform: (code) => {
const lines = code.split('\n')
// find component imports
const maybeComponents = lines
// types is not present here
.filter(
(line) =>
line.startsWith('import') &&
line.includes('@mantine/core') &&
line.includes('{') &&
line.includes('}'),
)
.flatMap((line) => {
// find component names
const entries = line.match(/{.*}/)?.[0] ?? ('' as const)
return entries
.replace(/[{}]/g, '')
.split(',')
.map((word) => word.trim())
})
const stylesToAdd = cssFileNames
.filter((fileName) =>
maybeComponents.find((maybeComponent) => fileName.startsWith(maybeComponent)),
)
.filter((fileName) => {
const isLayer = fileName.endsWith('.layer.css')
return layer ? isLayer : !isLayer
})
if (stylesToAdd.length > 0) {
// add global styles and all variants
const files = [selectVariant('global'), ...shared.map(selectVariant), ...stylesToAdd]
return [
...files.map((fileName) => `import '${mantineCoreStylesDirectory}/${fileName}'`),
code,
].join('\n')
}
return code
},
}
}
const mantineAutoloadCSS = createVitePlugin(mantineAutoloadCSSFactory)
export default defineConfig({
plugins: [react(), tsconfigPaths(), mantineAutoloadCSS()],
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment