跳到主要內容
+

主題式元件

了解如何在主題層級將自訂樣式套用至元件。

元件識別符

如果您之前使用過 Material UI,您可能對此技術很熟悉。若要在主題中自訂特定元件,請在 components 節點內指定元件識別符 (Joy{ComponentImportName})。

  • 使用 defaultProps 變更元件的預設 React props。
  • 使用 styleOverrides 將樣式套用至每個元件插槽。
    • 每個 Joy UI 元件都包含 root 插槽。

請造訪 components.d.ts 檔案以查看所有元件識別符。

import { CssVarsProvider, extendTheme } from '@mui/joy/styles';

const theme = extendTheme({
  components: {
    JoyChip: {
      defaultProps: {
        size: 'sm',
      },
      styleOverrides: {
        root: {
          borderRadius: '4px',
        },
      },
    },
  },
});

function App() {
  return <CssVarsProvider theme={theme}>...</CssVarsProvider>;
}

主題預設 props

在主題中指定為 defaultProps 的值會影響元件的所有執行個體

extendTheme({
  components: {
    JoyIconButton: {
      defaultProps: {
        variant: 'outlined',
        color: 'neutral',
      },
    },
  },
});

// This is the same as:
// <IconButton variant="outlined" color="neutral">
<IconButton>...</IconButton>;

主題樣式覆寫

根據 props 變更樣式

若要變更指定 prop 的樣式,請使用回呼作為樣式覆寫的值。引數包含 themeownerState (props)。

extendTheme({
  components: {
    JoyChip: {
      styleOverrides: {
        // `ownerState` contains the component props and internal state
        root: ({ ownerState, theme }) => ({
          ...(ownerState.size === 'sm' && {
            borderRadius: theme.vars.radius.xs,
          }),
        }),
      },
    },
  },
});

我們建議使用來自 theme.vars.* 的 CSS 變數,因為它具有更佳的偵錯體驗,而且在某些情況下效能更高。

樣式也可以包含任何 CSS 選取器 (支援巢狀選取器),如下所示

extendTheme({
  components: {
    JoyChip: {
      styleOverrides: {
        root: ({ ownerState, theme }) => ({
          ...(ownerState.variant === 'solid' &&
            ownerState.clickable && {
              color: 'rgba(255 255 255 / 0.72)',
              '&:hover': {
                color: '#fff',
              },
            }),
        }),
      },
    },
  },
});

根據狀態變更樣式

當 Joy UI 元件處於給定狀態 (例如 selecteddisabledfocusVisible 等) 時,會增加樣式的 CSS 優先順序。

若要覆寫特定狀態的樣式,請使用元件類別選取器,方法是匯入元件名稱,並以駝峰式命名,後面加上 Classes

import { listItemButtonClasses } from '@mui/joy/ListItemButton';

extendTheme({
  components: {
    JoyListItemButton: {
      styleOverrides: {
        root: {
          [`&.${listItemButtonClasses.selected}`]: {
            color: 'rgba(255 255 255 / 0.7)',
          },
        },
      },
    },
  },
});

可用的狀態為:activecheckedcompleteddisablederrorexpandedfocusedfocusVisiblereadOnlyrequiredselected

擴充色彩

以下程式碼片段說明如何在 primarysuccessinfodangerneutralwarning 之外,為元件提供其他色彩。

請注意,建立新色彩時,您會自動選擇退出全域變體功能,這可讓您精細控制 CSS 屬性,例如 colorbackgroundborder

以下範例擴充 Button 色彩以包含 secondary

extendTheme({
  components: {
    JoyButton: {
      styleOverrides: {
        root: ({ ownerState, theme }) => ({
          ...(ownerState.color === 'secondary' && {
            color: theme.vars.palette.text.secondary,
            backgroundColor: theme.vars.palette.background.level1,
          }),
        }),
      },
    },
  },
});

一旦這些值如上定義,您就可以直接在 Button 元件的執行個體上使用它們

<Button color="secondary">Secondary color</Button>
<Button color="tertiary">Tertiary color</Button>

TypeScript

需要模組擴充才能將值傳遞至元件的 color prop。

介面格式為 {ComponentName}PropsColorOverrides,這對所有 Joy UI 元件都相同

// This part could be declared in your theme file
declare module '@mui/joy/Button' {
  interface ButtonPropsColorOverrides {
    secondary: true;
    tertiary: true;
  }
}

// typed-safe
<Button color="secondary" />
<Button color="tertiary" />

擴充尺寸

以下程式碼片段說明如何在 smmdlg 之外,為元件提供其他尺寸。我們建議遵循已建立的「T 恤尺寸」命名慣例 (例如 xsxlxxl 等),以維持與所有其他 props 的一致性。

以下範例擴充 Button 尺寸以包含 xsxl

extendTheme({
  components: {
    JoyButton: {
      styleOverrides: {
        root: ({ ownerState, theme }) => ({
          ...(ownerState.size === 'xs' && {
            '--Icon-fontSize': '1rem',
            '--Button-gap': '0.25rem',
            minHeight: 'var(--Button-minHeight, 1.75rem)',
            fontSize: theme.vars.fontSize.xs,
            paddingBlock: '2px',
            paddingInline: '0.5rem',
          }),
          ...(ownerState.size === 'xl' && {
            '--Icon-fontSize': '2rem',
            '--Button-gap': '1rem',
            minHeight: 'var(--Button-minHeight, 4rem)',
            fontSize: theme.vars.fontSize.xl,
            paddingBlock: '0.5rem',
            paddingInline: '2rem',
          }),
        }),
      },
    },
  },
});

一旦這些值如上定義,您就可以直接在 Button 元件的執行個體上使用它們

<Button size="xs">Extra small</Button>
<Button size="xl">Extra large</Button>

用於擴充尺寸的屬性應僅與元件的密度或尺寸相關。若要了解如何擴充變體屬性,請查看本文文件中的擴充變體章節。

TypeScript

需要模組擴充才能將值傳遞至元件的 size prop。

介面格式為 {ComponentName}PropsSizeOverrides,這對所有 Joy UI 元件都相同

// This part could be declared in your theme file
declare module '@mui/joy/Button' {
  interface ButtonPropsSizeOverrides {
    xs: true;
    xl: true;
  }
}

// typed-safe
<Button size="xs" />
<Button size="xl" />

擴充變體

以下程式碼片段顯示如何擴充色彩屬性的元件變體。請注意,建立新變體時,您會自動選擇退出全域變體功能,這可讓您精細控制 CSS 屬性,例如 colorbackgroundborder

此範例擴充 Sheet 變體以包含名為 glass 的自訂值

extendTheme({
  components: {
    JoySheet: {
      styleOverrides: {
        root: ({ ownerState, theme }) => ({
          ...(ownerState.variant === 'glass' && {
            color: theme.vars.palette.text.primary,
            background: 'rgba(255, 255, 255, 0.14)',
            backdropFilter: 'blur(5px)',
            border: '1px solid rgba(255, 255, 255, 0.3)',
            boxShadow: '0 4px 30px rgba(0, 0, 0, 0.1)',
          }),
        }),
      },
    },
  },
});

一旦值如上定義,您就可以直接在 Sheet 元件的執行個體上使用它

<Sheet variant="glass">Glassmorphism</Sheet>

TypeScript

需要模組擴充才能將值傳遞至元件的 variant prop。

介面格式為 {ComponentName}PropsSizeOverrides,這對所有 Joy UI 元件都相同

// This part could be declared in your theme file
declare module '@mui/joy/Sheet' {
  interface SheetPropsVariantOverrides {
    glass: true;
  }
}

// typed-safe
<Sheet variant="glass" />;

每個模式的不同樣式

若要為每個模式 (淺色和深色) 指定與預設主題中定義的值不同的值,請使用 CSS 屬性選取器。

Joy UI 會將具有目前色彩配置的 data-* 屬性附加至 DOM (預設為 HTML)。您可以使用 theme.getColorSchemeSelector 公用程式來變更元件樣式。

以下範例說明如何在淺色模式中變更 boxShadow 符記的強度,同時在深色模式中完全移除它

extendTheme({
  components: {
    JoyChip: {
      styleOverrides: {
        root: ({ ownerState, theme }) => ({
          // for the default color scheme (light)
          boxShadow: theme.vars.shadow.sm,

          // the result is `[data-joy-color-scheme="dark"] &`
          [theme.getColorSchemeSelector('dark')]: {
            boxShadow: 'none',
          },
        }),
      },
    },
  },
});

如果您有定義自訂色彩配置,此方法也適用。但是,請注意,它會建立額外的 CSS 優先順序,當父元件想要覆寫其子元件樣式時,可能會很麻煩。