Skip to content

Releases: mantinedev/mantine

7.2.0 ⭐

06 Nov 13:22
Compare
Choose a tag to compare

Community templates

You are welcome to share your GitHub templates with the community. Community templates are
featured on the getting started page. You can find a guide on how to
create and submit a template here.

Examples of templates that you can submit:

  • Next.js pages router + MDX + Mantine blog template
  • Next.js app router + Mantine + styled-components template
  • Vite + Mantine + Emotion template

NumberFormatter component

New NumberFormatter component allows to format numbers
with thousands separators, decimal separators, and custom number of decimal places.
It supports the same formatting related props as NumberInput component.

import { NumberFormatter } from '@mantine/core';

function Demo() {
  return <NumberFormatter prefix="$ " value={1000000} thousandSeparator />;
}

Form actions

@mantine/form package now exports createFormActions function that
can be used to change form state from anywhere in your application.
The mechanism of form actions is similar to notifications system,
modals manager and other similar packages.

To use form actions, set name property in use-form settings:

import { useForm } from '@mantine/form';

export interface DemoFormValues {
  name: string;
  age: number;
}

function Demo() {
  const form = useForm<DemoFormValues>({
    name: 'demo-form',
    initialValues: {
      name: '',
      age: 0,
    },
  });
}

Then call createFormActions function with the same form name as specified in useForm settings:

// Import type of form values from the file where you defined useForm
import type { DemoFormValues } from './DemoForm';
import { createFormActions } from '@mantine/form';

export const demoFormActions = createFormActions<DemoFormValues>('demo-form');

After that, you can use demoFormActions to change form state from anywhere in your application.
For example, after a fetch request or after a user interaction with a component that does not have access
to the form state:

import { useEffect } from 'react';
import { Button } from '@mantine/core';
import { demoFormActions } from './demoFormActions';

function ExternalComponent() {
  useEffect(() => {
    fetch('/api/user')
      .then((res) => res.json())
      .then((res) =>
        demoFormActions.setValues({
          name: res.name,
          age: res.age,
        })
      );
  }, []);

  return <Button onClick={() => demoFormActions.reset()}>Reset demo form</Button>;
}

Table data prop

Table component now supports data prop which can be used to generate table rows
from given data:

import { Table, TableData } from '@mantine/core';

const tableData: TableData = {
  caption: 'Some elements from periodic table',
  head: ['Element position', 'Atomic mass', 'Symbol', 'Element name'],
  body: [
    [6, 12.011, 'C', 'Carbon'],
    [7, 14.007, 'N', 'Nitrogen'],
    [39, 88.906, 'Y', 'Yttrium'],
    [56, 137.33, 'Ba', 'Barium'],
    [58, 140.12, 'Ce', 'Cerium'],
  ],
};

function Demo() {
  return <Table data={tableData} />;
}

Table sticky header

Table component now supports stickyHeader prop, which can be used to make the table header
stick to the top of the table:

import { Table } from '@mantine/core';

const elements = [
  { position: 6, mass: 12.011, symbol: 'C', name: 'Carbon' },
  { position: 7, mass: 14.007, symbol: 'N', name: 'Nitrogen' },
  { position: 39, mass: 88.906, symbol: 'Y', name: 'Yttrium' },
  { position: 56, mass: 137.33, symbol: 'Ba', name: 'Barium' },
  { position: 58, mass: 140.12, symbol: 'Ce', name: 'Cerium' },
];

function Demo() {
  const rows = elements.map((element) => (
    <Table.Tr key={element.name}>
      <Table.Td>{element.position}</Table.Td>
      <Table.Td>{element.name}</Table.Td>
      <Table.Td>{element.symbol}</Table.Td>
      <Table.Td>{element.mass}</Table.Td>
    </Table.Tr>
  ));

  return (
    <Table stickyHeader stickyHeaderOffset={60}>
      <Table.Thead>
        <Table.Tr>
          <Table.Th>Element position</Table.Th>
          <Table.Th>Element name</Table.Th>
          <Table.Th>Symbol</Table.Th>
          <Table.Th>Atomic mass</Table.Th>
        </Table.Tr>
      </Table.Thead>
      <Table.Tbody>{rows}</Table.Tbody>
      <Table.Caption>Scroll page to see sticky thead</Table.Caption>
    </Table>
  );
}

Usage with Sass

It is now possible to use Mantine with Sass. You can find documentation
on this page. Note that it is still required to set up postcss-preset-mantine
in order for all functions to work properly. Sass can be used as a replacement for CSS modules
– it supports all features that CSS modules support.

You can find examples of Mantine + Sass usage in separate branches of templates:

Inline loaders

Loader component now supports children prop. The prop allows overriding the default
loader with any React node. It is useful in components that support loaderProps (Button, LoadingOverlay, Dropzone, etc.)
– with loaderProps.children you can now display any React node instead of the loader.

import { useDisclosure } from '@mantine/hooks';
import { LoadingOverlay, Button, Group, Box } from '@mantine/core';

function Demo() {
  const [visible, { toggle }] = useDisclosure(false);

  return (
    <>
      <Box pos="relative">
        <LoadingOverlay visible={visible} loaderProps={{ children: 'Loading...' }} />
        {/* ...other content */}
      </Box>

      <Group position="center">
        <Button onClick={toggle}>Toggle overlay</Button>
      </Group>
    </>
  );
}

lightHidden and darkHidden props

All Mantine components now support lightHidden and darkHidden props that can be used to hide
components in a specific color scheme:

import { Button } from '@mantine/core';

function Demo() {
  return (
    <>
      <Button color="cyan" lightHidden>
        Visible in dark color scheme only
      </Button>

      <Button color="pink" darkHidden>
        Visible in light color scheme only
      </Button>
    </>
  );
}

light-root and dark-root mixins

New light-root and dark-root mixins were added to postcss-preset-mantine.
These mixins can be used to add color scheme specific styles to the :root/html element.
Note that to use these mixins, you need to update postcss-preset-mantine to 1.9.0 or higher.

:root {
  @mixin light-root {
    --color: red;
  }

  @mixin dark-root {
    --color: blue;
  }
}

Documentation updates

Other changes

  • Dropzone now supports loaderProps prop to pass props down to the Loader component
  • theme.variantColorResolver now supports hoverColor prop, which allows controlling color property when the component is hovered. New property is supported in Button and ActionIcon components.
  • Flex is now a polymorphic component – it accepts renderRoot and component props
  • Checkbox root element now has data-checked attribute when the checkbox is checked
  • Checkbox and Radio components now support changing icon color with iconColor prop
  • use-form now supports `onVal...
Read more

7.1.7

26 Oct 06:31
Compare
Choose a tag to compare

What's Changed

  • [@mantine/core] Change how primary color fallback is applied in default theme.variantColorResolver to allow setting custom fallback values and undefined handling
  • [@mantine/core] Select: Fix error thrown on blur when given value is not in the data array
  • [@mantine/core] Fix option icon being smaller when option text has multiple lines
  • [@mantine/core] Spoiler: Fix unexpected empty space when hide label is null (#5126)
  • [@mantine/core] Button: Fix different border width of regular and disabled buttons
  • [@mantine/core] Table: Fix row background changing on hover in dark color scheme even when highlightOnHover prop is not set
  • [@mantine/carousel] Fix slideSize prop not handling number values (#5050)
  • [@mantine/core] Add option to keep transitions when color scheme changes in useMantineColorScheme hook (#5092)
  • [@mantine/core] Improve pop-* transitions animations (#5096)
  • [@mantine/hooks] use-local-storage: Fix error throwing if localStorage/sessionStorage is blocked by browser (#5091)
  • [@mantine/dates] Calendar: Fix incorrect focus logic when first item is disabled (#5078)

New Contributors

Full Changelog: 7.1.5...7.1.6

7.1.5

19 Oct 09:11
Compare
Choose a tag to compare

What's Changed

  • [@mantine/core] HoverCard: Fix dropdown not visible when Checkbox/Switch is used as target (#5072)
  • [@mantine/code-highlight] Fix code not updating when content changes (#5073)
  • [@mantine/core] Highlight: Fix incorrect highlighted parts when one of the array items includes substrings of other item (#5045)
  • [@mantine/core] Rating: Fix container overflow when the width of total item exceeds parent element width (#5057)
  • [@mantine/core] Radio: Fix checked icon clipping and not being centered with some sizes (#5064)
  • [@mantine/core] Fix incorrect callback arguments values types (#5067)
  • [@mantine/core] TagsInput: Fix required prop not working correctly (#5032)

New Contributors

Full Changelog: 7.1.3...7.1.5

7.1.3

12 Oct 10:00
Compare
Choose a tag to compare

What's Changed

  • [@mantine/core] Paper: Fix incorrect withBorder prop cascading to nested Paper components (#4930)
  • [@mantine/core] MultiSelect: Fix incorrect input styles without placeholder (#4954)
  • [@mantine/core] NumberInput: Fix focus shifting from the input when one of the controls is pressed (#5013)
  • [@mantine/notifications] Fix style prop breaking animations (#5007)
  • [@mantine/core] Rating: Fix incorrect touch events handling (#4976)
  • [@mantine/carousel] Fix onClick handler from nextControlProps being overwritten by internal props (#4985)
  • [@mantine/core] MultiSelect: Fix selectFirstOptionOnChange prop not working (#4997)
  • [@mantine/core] Select: Fix incorrect behavior when both searchValue and value are controlled (#4998)
  • [@mantine/spotlight] Fix DOM error thrown after HMR and several other cases (#4992)
  • [@mantine/hooks] use-timeout: Fix callback not running after state change (#4968)
  • [@mantine/hooks] use-focus-trap: Fix incorrect input[type="radio"] handling (#4856)

New Contributors

Full Changelog: 7.1.2...7.1.3

7.1.2

02 Oct 17:33
Compare
Choose a tag to compare
  • [@mantine/dropzone] Fix incorrect pointer events of inner element (#4934)
  • [@mantine/dropzone] Fix broken exports from react-dropzone-esm package

Full Changelog: 7.1.1...7.1.2

7.1.1

02 Oct 13:09
Compare
Choose a tag to compare

What's Changed

  • [@mantine/core] Radio: Fix description and error being misaligned when the component is rendered inside Radio.Group
  • [@mantine/core] HoverCard: Add missing HoverCard.extend
  • [@mantine/core] Drawer: Fix incorrect transitions in rtl direction (#4917)
  • [@mantine/core] TagsInput: Fix incorrect IME keyboard input handling (#4947)
  • [@mantine/core] Container: Fix nested Container components inheriting some properties from parent Container component (#4859)
  • [@mantine/core] Menu: Fix incorrect Menu.Item rtl styles (#4936)
  • [@mantine/core] Spoiler: remove margin-bottom when "Show more" is hidden (#4928)
  • [@mantine/dropzone] Migrate to react-dropzone-esm package to support frameworks that work only with esm (#4920)
  • [@mantine/core] Button: Fix incorrect border-radius of loading overlay (#4939)
  • [@mantine/core] Portal: Fix error when value of className prop contained whitespace (#4935)
  • [@mantine/core] MultiSelect: Fix incorrect input sizes values (#4925)
  • [@mantine/core] Affix: Fix position prop set as attribute on the root element (#4932)
  • [@mantine/core] Update react-textarea-autosize dependency to the latest version to fix issues with edge runtime (#4923)
  • [@mantine/core] Select: Fix search value not changing when component value is controlled (#4915)
  • [@mantine/core] Fix incorrect ActionIcon.Group, Button.Group and Rating components RTL styles (#4907)
  • [@mantine/core] TagsInput: Fix onOptionSubmit not being called when tag is submitted with Enter key (#4892)
  • [@mantine/core] NumberInput: Fix value reset to zero when leading non-zero number is deleted (#4916)

New Contributors

Full Changelog: 7.1.0...7.1.1

7.1.0 ⭐

28 Sep 09:38
Compare
Choose a tag to compare

CSS layers

Starting from 7.1.0 it is possible to import all @mantine/* packages styles with rules
defined in mantine CSS layer.
CSS rules within a layer are grouped together and applied before rules without a layer. This means that
even if you do not have control over styles import order, you can still override Mantine styles with
regular styles.

// If your styles are not wrapped in @layer directive,
// they will be applied after Mantine styles.
// Import order does not affect styles in this case
import classes from './Demo.module.css';
import '@mantine/core/styles.layer.css';

You can import styles within a layer by importing @mantine/*/styles.layer.css files.
Note that these files are a full replacement for @mantine/*/styles.css files –
you should not import both of them.

import '@mantine/core/styles.layer.css';
import '@mantine/dates/styles.layer.css';
// ... other styles

CSS layers are also useful if you want to combine Mantine components with other libraries which also
provide styles. You can use @layer directive to control the order of styles:

@layer base, mantine, components;

In this example, Mantine styles will take precedence over other library base styles, but other library
components styles will take precedence over Mantine component styles.

As of September 2023, CSS layers are supported in all modern browsers and have 90% browser support.

renderRoot prop

All polymorphic components now support renderRoot prop, which
is an alternative to component prop. renderRoot prop allows changing the root element
to any other component or HTML tag with a callback function. It can be used in cases when
component prop is not flexible enough:

  • Target component props are incompatible with Mantine component. For example, Button component expects className
    to be a string, but react-router-dom NavLink expects
    className to be a function.
  • Target component is a generic – it either accepts type as a parameter or its type changes depending
    on its props. Examples: typed Next.js Link, TanStack router Link

renderRoot example with react-router-dom NavLink:

import cx from 'clsx';
import { Button } from '@mantine/core';
import { NavLink } from 'react-router-dom';

function Demo() {
  return (
    <Button
      renderRoot={({ className, ...others }) => (
        <NavLink
          className={({ isActive }) => cx(className, { 'active-class': isActive })}
          {...others}
        />
      )}
    >
      React router NavLink
    </Button>
  );
}

renderRoot example with typed Next.js Link:

import Link from 'next/link';
import { Button } from '@mantine/core';

function Demo() {
  return (
    <Button renderRoot={(props) => <Link href="/hello" {...props} />}>
      Typed Next link button
    </Button>
  );
}

Improved ESM support

All @mantine/* packages now have improved ESM support:

  • Files in esm folder now have .mjs extension
  • You can use @mantine/* packages with type: module in package.json without any additional configuration
  • All packages are now fully compatible with Remix v2
  • Tree shaking was improved for some bundlers

CSS variables in style prop

It is now possible to define CSS variables in style prop in all Mantine components –
style prop is no longer restricted by React.CSSProperties type:

import { Box } from '@mantine/core';

function Demo() {
  return <Box style={{ '--radius': '0.5rem', borderRadius: 'var(--radius)' }} />;
}

form.setInitialValues

@mantine/form now supports form.setInitialValues method
which allows updating initial values after the form was initialized. This method is useful when you
want to update values that are used in form.reset and to compare values for dirty fields state:

import { useEffect } from 'react';
import { useForm } from '@mantine/form';

function Demo() {
  const form = useForm({
    initialValues: {
      name: '',
      email: '',
    },
  });

  useEffect(() => {
    fetch('/api/user')
      .then((res) => res.json())
      .then((data) => {
        // Update initial values after form was initialized
        // These values will be used in form.reset
        // and to compare values to get dirty state
        form.setInitialValues(data);
        form.setValues(data);
      });
  }, []);
}

7.0.2

26 Sep 09:00
Compare
Choose a tag to compare

What's Changed

  • [@mantine/dates] Fix DatePickerInput and other similar inputs not having correct height when used without placeholder
  • [@mantine/core] MultiSelect: Fix check icon not displayed in selected grouped options
  • [@mantine/dates] Fix broken esm imports of dayjs plugins (#4875)

New Contributors

Full Changelog: 7.0.1...7.0.2

7.0.1

25 Sep 13:01
Compare
Choose a tag to compare

What's Changed

  • [@mantine/core] Loader: Make dots loader look the same as in v6 (#4801)
  • [@mantine/core] Button: Fix incorrect disabled styles of outline variant (#4815)
  • [@mantine/core] Fix broken theme.other type override type in .d.ts files (#4831)
  • [@mantine/core] SegmentedControl: Fix error when selected item removed from the data array (#4122)
  • [@mantine/core] AppShell: Fix AppShell.Main not taking up full height (#4842)
  • [@mantine/core] Input: Fix incorrect focus styles when error prop is set (#4832)
  • [@mantine/core] Add clearable prop back to Select, MultiSelect and TagsInput components
  • [@mantine/core] Portal: Reduce output DOM structure to a single div element, add data-portal attribute to the root portal element to indentify portals in devtools
  • [@mantine/code-highlight] Add missing static classes on CodeHighlight and CodeHighlightTabs components
  • [@mantine/hooks] use-local-storage: Fix hook throwing error if local storage is blocked by user (#3259)
  • [@mantine/tiptap] Fix onBlur called each time controls are clicked (#3209)
  • [@mantine/core] Add aria-describedby and aria-labelledby attributes to Radio.Group, Checkbox.Group and Switch.Group components (#3170)
  • [@mantine/core] Spoiler: Add aria-expanded and aria-controls attributes to show/hide control (#3183)
  • [@mantine/core] Spoiler: Change tab order of the show/hide button to make it receive focus before the content (#3183)
  • [@mantine/form] Fix incorrect values type in deeply nested validation rules (#4735)
  • [@mantine/dates] DateTimePicker: Set seconds to 0 if withSecond prop is not set (#4737)
  • [@mantine/dropzone] Fix Dropzone.FullScreen staying opened after file was droppped for the first time (#4580)
  • [@mantine/core] Modal: Fix closeButtonProps not including CloseButtonProps (#4793)
  • [@mantine/core] Select: Fix id prop not setting id attribute on the input element (#4809)
  • [@mantine/core] Allow using custom keys in theme.spacing and other similar values when theme is extended with createTheme
  • [@mantine/core] PasswordInput: Fix input field not taking entire width of the field in Firefox
  • [@mantine/core] Add default props to Group and Stack to prevent unwanted inheritance
  • [@mantine/core] Menu: Fix dropdown opening when keepMounted prop is set and outside click is registered
  • [@mantine/core] Select: Fix search value not updating when data array changes (#4822)
  • [@mantine/core] Fix broken colors override type (#4816)
  • [@mantine/core] Table: Fix row hover not working in dark mode when striped prop is set (#4817)
  • [@mantine/core] Fix styles breaking if color scheme value in local storage is not valid

New Contributors

Full Changelog: 7.0.0...7.0.1

7.0.0 πŸŽ‰

18 Sep 13:26
Compare
Choose a tag to compare

Migration to native CSS

Mantine no longer depends on Emotion for styles generation. All @mantine/*
packages are now shipped with native CSS files which can be imported from @mantine/{package}/styles.css,
for example:

import '@mantine/core/styles.css';

This change improves performance, reduces bundle size of the library and allows using Mantine
in environments where CSS-in-JS is not supported (or supported with limitations), for example,
Next.js app directory.

Important breaking changes:

  • createStyles function is no longer available, use CSS modules or any other styling solution of your choice instead
  • Components no longer support sx prop. You can use className or style props instead.
  • styles prop no longer supports nested selectors

It is now recommended to use CSS modules to style Mantine components.
To update your project to CSS modules, follow the 6.x β†’ 7.x migration guide.

Vanilla extract integration

If you prefer CSS-in-JS syntax for styling, you can use Vanilla extract
as a TypeScript CSS preprocessor. You will be able to use most of Mantine styling features
with Vanilla extract.

System color scheme support

All components now support system color scheme – when colorScheme value is auto,
components will use prefers-color-scheme media query to determine if the user prefers light or dark color scheme.

Note that auto is not the default value. You need to set it manually to enable system color scheme support
both on MantineProvider and in ColorSchemeScript:

import { MantineProvider, ColorSchemeScript } from '@mantine/core';

function Demo() {
  return (
    <>
      <ColorSchemeScript defaultColorScheme="auto" />
      <MantineProvider defaultColorScheme="auto">
        <App />
      </MantineProvider>
    </>
  );
}

Built-in color scheme manager

MantineProvider now comes with a built-in color scheme manager.
It is no longer required to use any other components to set up color scheme logic.
Color scheme can be changed with useMantineColorScheme hook:

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

CSS modules is now the recommended way to style Mantine components,
although it is not required – you can choose any other styling solution of your choice.

It is also recommended to use postcss-preset-mantine. It includes
mixins and functions to simplify styling of Mantine components. postcss-preset-mantine
is included in all templates.

Global styles

Mantine no longer includes normalize.css. Instead, it uses a bare minimum set of global styles.
These styles are part of the @mantine/core package and are applied automatically when you import
@mantine/core/styles.css in your application. Note that these styles cannot be decoupled from the
rest of the library.

Mantine as a headless UI library

You can now use Mantine as a headless library. To achieve that, just do not import
@mantine/*/styles.css in your application. Then you will be able to apply styles with
Styles API.

createTheme function

createTheme function is a replacement for MantineThemeOverride type. Use it to create a theme
override, it will give you autocomplete for all theme properties:

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

All components that support default props or Styles API now have a static extend function which allows getting autocomplete when customizing
defaultProps, classNames and styles of the component
on theme:

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

You can now get component props in classNames and styles to conditionally apply styles.
This feature is a more powerful replacement for styles params.

import cx from 'clsx';
import { MantineProvider, createTheme, TextInput } from '@mantine/core';
import classes from './Demo.module.css';

const theme = createTheme({
  components: {
    TextInput: TextInput.extend({
      classNames: (_theme, props) => ({
        label: cx({ [classes.labelRequired]: props.required }),
        input: cx({ [classes.inputError]: props.error }),
      }),
    }),
  },
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <TextInput required label="Required input" placeholder="Required input" />
      <TextInput error label="Input with error" placeholder="Input with error" mt="md" />
    </MantineProvider>
  );
}
.labelRequired {
  color: var(--mantine-color-red-filled);
}

.inputError {
  background-color: var(--mantine-color-red-light);
}

Components CSS variables

You can now customize components CSS variables to change component styles based on its props.
For example, it can be used to add new sizes:

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>
  );
}

New variants system

All components now have data-variant attribute on the root element, even if the component does not have any predefined variants.
You can use it to apply styles to all components of the same type on theme:

import { Input, MantineProvider, createTheme } from '@mantine/core';
import classes from './Demo.module.css';

// It is better to add new variants in theme.components
// This way you will be able to use them in anywhere in the app
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>
  );
}
.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);
    }
  }
}

New sizes system

There are multiple ways to customize component sizes:

Example of customizing [Button](https://mantine.dev/core/b...

Read more