跳到内容
+

Material UI Sync 插件 🧪

Sync 是一款 Figma 插件,可直接从设计稿生成 Material UI 主题代码。

简介

Material UI Sync 是一款 Figma 插件,可让您从 Material UI for Figma Design Kit 生成主题。

Customizing the Material UI Switch component in Figma with the Sync plugin running.

Sync 与 Material UI for Figma Design Kit v5.16.0 及更高版本的设计套件结合使用。

运行插件

如果您没有安装 完整和最新版本 的 Material UI for Figma Design Kit,您可以使用 社区版本 来测试此插件。

在 Figma 中安装并打开后,前往 Community 选项卡上的 Material UI Sync 插件页面,然后点击 Open in… 并选择 Material UI for Figma Design Kit。

Accessing Material UI Sync via the Resources menu in Figma.

自定义设计令牌

设计令牌在 Design Kit 的 本地变量集合 中定义,包括调色板、断点、形状和间距令牌。排版和阴影相关的令牌可以在 本地样式集合 中找到。

修改现有令牌

Design Kit 完全加载了设计令牌,这些令牌映射到 Material UI React 库的默认主题

要自定义现有令牌,请点击如下所示的过滤器图标,打开本地变量模态框。根据需要调整集合中可用的任何变量(例如调色板、断点、形状和间距)。

The Local variables menu in Figma, where all design tokens are stored and new ones can be added.

然后打开 Material UI Sync 插件并点击 Generate theme(生成主题)。

The Generate theme button in the Material UI Sync plugin UI.

包含修改后令牌的主题将被生成并显示在插件的 Theme(主题)选项卡中。

The generated theme displayed in the Material UI Sync plugin UI.

您还可以通过导航到 Storybook 预览选项卡来预览生成的主题和自定义的令牌。

The generated theme previewed in Storybook in the Material UI Sync plugin UI.

添加新令牌

您可以通过以下方式使用自己的令牌扩展现有令牌集:将新变量添加到现有的本地变量集合,或者将新的 elevation 和 typography 样式添加到本地样式集合。添加自定义令牌后,点击 Regenerate theme(重新生成主题)以将这些令牌包含在您的主题中。

The Regenerate button in the Connect plugin UI.

自定义组件

Sync 插件还可以为自定义组件生成主题样式,使您能够完全更改其外观和风格,并从 Figma 中创建自定义设计系统。

例如,以下是如何自定义 Switch 组件的选中状态、中等尺寸和原色,以复制 iOS 的外观和风格

A specific variant of the Switch component selected in the Design Kit.

Sync 插件为自定义的 Switch 生成以下主题代码

{
  components: {
    MuiSwitch: {
      styleOverrides: {
        root: {
          '&.MuiSwitch-sizeMedium:has(.MuiSwitch-colorPrimary)': {
            '&:has(.Mui-checked):not(:has(.Mui-disabled)):not(:has(.Mui-focusVisible))':
              {
                width: '40px',
                height: '21px',
                padding: '0',
                '& .MuiSwitch-switchBase': {
                  transform: 'translateX(19px) translateY(2px)',
                  padding: '0',
                  '& .MuiSwitch-thumb': {
                    width: '17px',
                    height: '17px',
                    background: '#FAFAFA',
                  },
                  '& + .MuiSwitch-track': {
                    width: '38px',
                    height: '21px',
                    background: 'var(--mui-palette-success-light)',
                    opacity: '1',
                  },
                },
              },
          },
        },
      },
    },
  },
}

生成的主题针对与上述特定 Switch 配置相对应的类,因此仅当 Material UI 组件的 props 和状态与自定义 Figma 组件的 props 和状态匹配时,才会应用样式。

要自定义其他状态,您需要按照以下步骤将所需的设计更改应用于 Figma 中的每个变体

  1. 自定义单个“基础”变体——例如,处于选中状态、中等尺寸和原色的 Switch 组件。
  2. 克隆此变体并重命名它,以定位您想要自定义的下一个变体——例如,将 Checked=True, Size=Medium, Color=Primary, State=Enabled 的克隆版本重命名为 Checked=False, Size=Medium, Color=Primary, State=Enabled
  3. 删除同一变体的旧版本。
  4. 将新版本移动到变体网格中的正确方格。
  5. 对变体的子图层进行必要的样式调整。

为您要自定义的每个变体重复此过程。以下是示例外观

A fully customized Switch component in the Material UI Design Kit.

从这里您可以运行 Sync 以生成新主题——以下是从上述示例中生成的主题

{
  components: {
    MuiSwitch: {
      styleOverrides: {
        root: {
          '&.MuiSwitch-sizeMedium:has(.MuiSwitch-colorPrimary)': {
            width: '40px',
            height: '21px',
            padding: '0',
            '& .MuiSwitch-switchBase': {
              padding: '0',
              '& .MuiSwitch-thumb': {
                width: '17px',
                height: '17px',
                background: '#FAFAFA',
              },
              '& + .MuiSwitch-track': {
                width: '38px',
                height: '21px',
                borderRadius: '100px',
                opacity: '1',
              },
            },
            '&:not(:has(.Mui-checked)):not(:has(.Mui-disabled)):not(:has(.Mui-focusVisible))': {
              '& .MuiSwitch-switchBase': {
                transform: 'translateX(3px) translateY(2px)',
                '& + .MuiSwitch-track': {
                  background: '#BDBDBD',
                },
              },
            },
            '&:not(:has(.Mui-checked)):has(.Mui-disabled):not(:has(.Mui-focusVisible))': {
              '& .MuiSwitch-switchBase': {
                transform: 'translateX(3px) translateY(2px)',
                '& + .MuiSwitch-track': {
                  background: 'rgba(229, 229, 229, 0.99)',
                },
              },
            },
            '&:not(:has(.Mui-checked)):not(:has(.Mui-disabled)):has(.Mui-focusVisible)': {
              '& .MuiSwitch-switchBase': {
                transform: 'translateX(3px) translateY(2px)',
                '& + .MuiSwitch-track': {
                  border: '1px solid #000',
                  background: '#BDBDBD',
                },
              },
            },
            '&:has(.Mui-checked):has(.Mui-disabled):not(:has(.Mui-focusVisible))': {
              '& .MuiSwitch-switchBase': {
                transform: 'translateX(19px) translateY(2px)',
                '& + .MuiSwitch-track': {
                  background: 'rgba(187, 231, 188, 0.99)',
                },
              },
            },
            '&:not(:has(.Mui-checked)):not(:has(.Mui-disabled)):not(:has(.Mui-focusVisible)):hover': {
              '& .MuiSwitch-switchBase': {
                transform: 'translateX(3px) translateY(2px)',
                '& + .MuiSwitch-track': {
                  background: '#616161',
                },
              },
            },
            '&:has(.Mui-checked):not(:has(.Mui-disabled)):not(:has(.Mui-focusVisible))': {
              '& .MuiSwitch-switchBase': {
                transform: 'translateX(19px) translateY(2px)',
                '& + .MuiSwitch-track': {
                  background: 'var(--mui-palette-success-light)',
                },
              },
            },
            '&:has(.Mui-checked):not(:has(.Mui-disabled)):not(:has(.Mui-focusVisible)):hover': {
              '& .MuiSwitch-switchBase': {
                transform: 'translateX(19px) translateY(2px)',
                '& + .MuiSwitch-track': {
                  background: 'var(--mui-palette-success-dark)',
                },
              },
            },
            '&:has(.Mui-checked):not(:has(.Mui-disabled)):has(.Mui-focusVisible)': {
              '& .MuiSwitch-switchBase': {
                transform: 'translateX(19px) translateY(2px)',
                '& + .MuiSwitch-track': {
                  border: '1px solid #000',
                  background: 'var(--mui-palette-success-light)',
                },
              },
            },
          },
        },
      },
    },
  },
}

您还可以查看 Storybook 预览来测试 Material UI 版本的组件。

A fully customized Switch component in Storybook.

使用生成的主题

以下是如何将 Sync 生成的主题添加到您的代码库的示例

_app.tsx
import { createTheme, ThemeProvider } from '@mui/material/styles';

const theme = createTheme({
  cssVariables: true,
  shape: {
    borderRadiusRound: 999,
  },
  components: {
    MuiSwitch: {
      styleOverrides: {
        root: {
          '&.MuiSwitch-sizeMedium:has(.MuiSwitch-colorPrimary)': {
            '&:has(.Mui-checked):not(:has(.Mui-disabled)):not(:has(.Mui-focusVisible))':
              {
                width: '40px',
                height: '21px',
                padding: '0',
                '& .MuiSwitch-switchBase': {
                  transform: 'translateX(19px) translateY(2px)',
                  padding: '0',
                  '& .MuiSwitch-thumb': {
                    width: '17px',
                    height: '17px',
                    background: '#FAFAFA',
                  },
                  '& + .MuiSwitch-track': {
                    width: '38px',
                    height: '21px',
                    background: 'var(--mui-palette-success-light)',
                    borderRadius: 'var(--mui-shape-borderRadiusRound)',
                    opacity: '1',
                  },
                },
              },
          },
        },
      },
    },
  },
});

export default function MyApp(props) {
  const { Component, pageProps } = props;

  return (
    <ThemeProvider theme={theme}>
      <Component {...pageProps} />
    </ThemeProvider>
  );
}

反馈和错误报告

如果您有任何反馈,我们很乐意听取您的意见