在 'Molecules' 中嵌套样式组件 'Atoms' -> 样式/定位

Nesting styled-components 'Atoms' together in 'Molecules' -> Styling / Positioning

我需要创建一个 React 组件库

为此,我将 React 与 Typescript 和样式化组件结合使用。

当我尝试在分子中重用我的原子时,我被卡住了...

我这样创建按钮原子组件:

interface IButtonProps {
    text?: string
    onClick?: React.MouseEventHandler<HTMLButtonElement>
}

const StyledButton = styled.button<IButtonProps>`
  height: 70px;
  width: 70px;
  border: none;
  border-radius: 5px;
  background-color: #88BDBC;
  color: #254E58;
  font-family: Alata, sans-serif;
  font-size: 35px;
  transition: all 350ms;

  &:hover {
    background-color: #254E58;
    color: #88BDBC;
  }

  &:active {
    background-color: #112D32;
    color: #88BDBC;
  }
`;

const Button = ({
   text = "",
   onClick
}: IButtonProps): React.ReactElement => {
    return (
        <StyledButton onClick={onClick}>{text}</StyledButton>
    );
};

这只是我的 Atoms 的一个非常不完美的例子。我这样创建所有原子。我只在 Atoms -> Colors、Borders、Margins 等中定义样式。不是外面的样式 -> 例如填充然后我认为它在很大程度上取决于使用这个按钮的上下文。

所以我很封闭。

当我想在 'Controller' 分子中使用 Button 时,我需要给 Button 一些 Positions 和一些 Paddings 等

但在我的父样式组件中,我现在不知道如何正确指向它们。特别是当我有一些像这里这样的更大的组件组合时。

interface IControllerProps {
    text1: string;
    text2: string;
    text3: string;
    onClick?: React.MouseEventHandler<HTMLButtonElement>
}

const StyledController = styled.div<IControllerProps>`
  /* ... */
`;

const Controller = ({
    onClick
}: IControllerProps) => {
    const [powerOn, setPowerOn] = React.useState(false);
    const [bankType, setBankType] = React.useState(false);
    const [volume, setVolume] = React.useState(50);

    return (
        <StyledController>
            <Text text="Hello"/>
            <Switch checked={powerOn} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {setPowerOn(e.target.checked)}}/>
            <Button onClick={() => false}/>
            <Text text="Hello"/>
            <RangeSlider value={volume} min={0} max={100} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setVolume(parseInt(e.target.value))} />
            <Text text="Hello"/>
            <Switch checked={bankType} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {setBankType(e.target.checked)}}/>
            <Button onClick={onClick}/>
            <Button onClick={onClick}/>
        </StyledController>
    )
};

我是否需要使用属性将其提供给按钮...用伪类指向所有内容...定义按钮中的所有内容(但是可重用按钮的上下文具有灵活性)...

最佳做法是什么?

您像这样定位样式(我在 javascript 中回答以降低复杂性):

// Button.react.js
export const StyledButton = styled.button`
  background-color: #88bdbc;
`;

// Controller.react.js
import { StyledButton } from './Button.react.js';

const StyledController = styled.div`
  ${StyledButton} {
    background-color: blue;
  }
`;

请检查related docs

除了 Dennis Vash 的回答:

对于我的示例按钮组件,这意味着我需要像这样更改它:

interface IButtonProps {
    text?: string
    onClick?: React.MouseEventHandler<HTMLButtonElement>
    className?: string
}

const UnstyledButton = ({
    text = "",
    onClick,
    className
}: IButtonProps): React.ReactElement => {
    return (
        <button onClick={onClick} className={className}>{text}</button>
    );
};

const Button = styled(UnstyledButton)<IButtonProps>`
  height: 70px;
  width: 70px;
  border: none;
  border-radius: 5px;
  background-color: #88BDBC;
  color: #254E58;
  font-family: Alata, sans-serif;
  font-size: 35px;
  transition: all 350ms;

  &:hover {
    background-color: #254E58;
    color: #88BDBC;
  }

  &:active {
    background-color: #112D32;
    color: #88BDBC;
  }
`;

原因是:这只适用于样式组件的上下文,而不适用于 ReactElement 的上下文。

来自样式化组件文档的要点: 但是,包装在 styled() 工厂中使其符合插值条件——只需确保包装的组件传递 className。

当您直接从 Styled Component 使用 Button(如 Dannis Vash 提到的)时,您可以直接引用它。