如何在不使用 sx props 的情况下,针对 MUI Paper 组件进行样式定位?

huangapple go评论56阅读模式
英文:

How to target the mui paper component from select style without using the sx props?

问题

I am trying to style the Select MUI component using the styled function. Since I want to share this style later on, I don't want to keep using sx. I've tried a couple of approaches, but I am missing the right class to be able to target the Paper directly from within the styled function.

// Styled 
export const StyledSelect = styled(Select)<SelectProps>(({ theme }) => ({
  textAlign: 'start',
  margin: '5px',
  fontWeight: 800,
  
  '& .MuiSelect-select': {
    // List
    '& .MuiList-root': {
      color: 'green',
      backgroundColor: 'red',
    },
    // Paper 
    '& .MuiMenu-paper': {
      backgroundColor: 'red',
    },
  },
}))

// Component
<FormControl>
  <StyledSelect
    variant={variant}
    labelId='select-label'
    name={name}
    disabled={disabled}
    value={value}
    onChange={onChangeFn}
    displayEmpty
  >
  </StyledSelect>
</FormControl>

请注意,上述代码是对你提供的代码片段的翻译,不包含其他额外信息。

英文:

I am trying to style the Select MUI component using the styled function. Since I want to share this style later on, I don't want to keep using sx. I've tried a couple of approaches, but I am missing the right class to be able to target the Paper directly from within the styled function

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

// Styled 
export const StyledSelect = styled(Select)&lt;SelectProps&gt;(({ theme }) =&gt; ({
  textAlign: &#39;start&#39;,
  margin: &#39;5px&#39;,
  fontWeight: 800,
  
  &#39;&amp; .MuiSelect-select&#39;: {
    // List
    &#39;&amp; .MuiList-root&#39;: {
      color: &#39;green&#39;,
      backgroundColor: &#39;red&#39;,
    },
    // Paper 
    &#39;&amp; .MuiMenu-paper&#39;: {
      backgroundColor: &#39;red&#39;,
    },
  },
})

// Component
&lt;FormControl&gt;
  &lt;StyledSelect
  variant={variant}
  labelId=&#39;select-label&#39;
  // This works 100%
  // MenuProps={{
  //   PaperProps: {
  //     sx: {
  //       backgroundColor: &#39;transparent&#39;,
  //       backdropFilter: &#39;blur(10px)&#39;,
  //     },
  //   },
  // }}
  name={name}
  disabled={disabled}
  value={value}

  onChange={onChangeFn}
  displayEmpty
  &gt;
  &lt;/StyledSelect&gt;
&lt;/FormControl&gt;

<!-- end snippet -->

答案1

得分: 1

The MUI Paper 在默认的 Select 内部一直是一个比较棘手的部分,因为 Paper 被作为一个样式化组件来处理,因为它在 Select 的DOM层次结构之外(因为它使用了 Portal)。为了对其进行样式化(以及 Select),你首先需要对 Select 进行样式化,然后使用样式化的 Select 作为基本组件,用来对 Paper 进行样式化。例如:

const BaseSelect = styled(Select)(({ theme }) => ({
  backgroundColor: "green", // 仅用于示例
  textAlign: 'start',
  margin: '5px',
  fontWeight: 800,
}));

// 对 Menu Paper 进行样式化
const StyledSelect = styled(({ className, ...props }: SelectProps) => (
  <BaseSelect {...props} MenuProps={{ PaperProps: { className } }} />
))(({ theme }) => ({
  backgroundColor: "red", // 仅用于示例
  // backgroundColor: "transparent",
  backdropFilter: "blur(10px)"
}));

...

// 正常使用
// <StyledSelect ... >

工作中的 CodeSandbox: https://codesandbox.io/s/styled-mui-select-and-paper-2dmpct?file=/demo.tsx

英文:

The MUI Paper within a default Select has always been a trickier to handle as a styled component because the Paper falls outside of the Select's DOM hierarchy (due to it use of a Portal). In order to style it (and the Select), you first need to style the Select and then use that styled Select as the base component from which to style the Paper. For example:

const BaseSelect = styled(Select)(({ theme }) =&gt; ({
  backgroundColor: &quot;green&quot;, // Added just for the example
  textAlign: &#39;start&#39;,
  margin: &#39;5px&#39;,
  fontWeight: 800,
}));

// To style the Menu Paper
const StyledSelect = styled(({ className, ...props }: SelectProps) =&gt; (
  &lt;BaseSelect {...props} MenuProps={{ PaperProps: { className } }} /&gt;
))(({ theme }) =&gt; ({
  backgroundColor: &quot;red&quot;, // Added just for the example
  // backgroundColor: &quot;transparent&quot;,
  backdropFilter: &quot;blur(10px)&quot;
}));

...

// Use as you normally would
// &lt;StyledSelect ... &gt;

Working CodeSandbox: https://codesandbox.io/s/styled-mui-select-and-paper-2dmpct?file=/demo.tsx

答案2

得分: 1

1️⃣ 使用 sx 属性创建基础组件:

export const BaseSelect = (props: SelectProps) => {
    return (
       <Select
         {...props}
         sx={{
            bgcolor: 'green',
            ...props.sx, // 从 props 中扩展 sx,以便在需要时覆盖这些样式
          }}
         MenuProps={{
            PaperProps: {
               sx: {
                  bgcolor: 'red', // Paper 的 sx 样式
               },
             },
           }}
         />
      )}


// 用法
<BaseSelect
     value={age}
     label="Age"
     sx={{
       height: 100, // 仍然可以使用 sx 并在需要时覆盖基础样式
     }}
   >

2️⃣ 创建可重用的 sx 变量:

export const SELECT_BASE_SX: SxProps = {
  bgcolor: 'green',
}

export const PAPER_SX: SxProps = {
  bgcolor: 'red',
}

// 用法
<Select
  sx={{
    ...SELECT_BASE_SX,
    height: 100,
  }}
  MenuProps={{
    PaperProps: {
      sx: {
        ...PAPER_SX,
      },
    },
  }}
/>

希望这有所帮助。

英文:

We have faced similar issues while using styled-components to target child classes to create a base component. Sometimes there are multiple child components you want to target. It's a bit tricky. You will face similar issues with components like Autocomplete, DatePicker, etc.
So we start using two different approaches.

✅1️⃣ Create a base component using sx props:

export const BaseSelect = (props: SelectProps) =&gt; {
    return (
       &lt;Select
         {...props}
         sx={{
            bgcolor: &#39;green&#39;,
            ...props.sx, //spread your sx from props, so you can override these styles if needed
          }}
         MenuProps={{
            PaperProps: {
               sx: {
                  bgcolor: &#39;red&#39;, //sx for Paper
               },
             },
           }}
         /&gt;
      )}


//USAGE
&lt;BaseSelect
     value={age}
     label=&quot;Age&quot;
     sx={{
       height: 100, //You can still use sx and override base styling if needed
     }}
   &gt;

<br/>

✅2️⃣ Create reusable sx variables:

export const SELECT_BASE_SX: SxProps = {
  bgcolor: &#39;green&#39;,
}

export const PAPER_SX: SxProps = {
  bgcolor: &#39;red&#39;,
}

//USAGE
&lt;Select
  sx={{
    ...SELECT_BASE_SX,
    height: 100,
  }}
  MenuProps={{
    PaperProps: {
      sx: {
        ...PAPER_SX,
      },
    },
  }}
/&gt;

I hope it helps.

huangapple
  • 本文由 发表于 2023年7月3日 12:06:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76601784.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定