3

在反应中使用 Rebass/Forms,我无法正确使用样式正确调整 Switch 组件的大小。(我也在用@emotion/styled

我试过使用一个size属性,但这并没有给出简单改变开关比例的预期效果。

我尝试使用该sx属性并给它 awidth和 a height,但这只会调整按钮元素的大小,而不是“滑动点”的内部 div

我知道我可以编写一些针对内部 div 本身的样式,但我想找到一种方法来一次性给它一个高度和宽度,并且它适用于按钮和内部 div。

<Switch
  sx={{ width: "30px", height: "15px" }}
/>

https://codesandbox.io/s/styling-rebass-switch-uu7wg

4

5 回答 5

4

因为高度和宽度在源代码中是硬编码的,所以不可能做你想要的“开箱即用”

幸运的rebass是,它的内部结构非常好,因此可以使用 rebass 源代码中的一些复制粘贴来创建自己的。

import React from "react";
import { Box } from "reflexbox";

export const ResizableSwitch = ({
  checked,
  height = 24,
  width = 40,
  ...props
}) => (
  <Box
    as="button"
    type="button"
    role="switch"
    tx="forms"
    variant="switch"
    aria-checked={checked}
    {...props}
    __css={{
      appearance: "none",
      m: 0,
      p: 0,
      width,
      height,
      color: "primary",
      bg: "transparent",
      border: "1px solid",
      borderColor: "primary",
      borderRadius: 9999,
      "&[aria-checked=true]": {
        bg: "primary"
      },
      ":focus": {
        outline: "none",
        boxShadow: "0 0 0 2px"
      }
    }}
  >
    <Box
      aria-hidden
      style={{
        transform: checked ? `translateX(${width - height}px)` : "translateX(0)"
      }}
      sx={{
        mt: "-1px",
        ml: "-1px",
        width: height,
        height,
        borderRadius: 9999,
        border: "1px solid",
        borderColor: "primary",
        bg: "background",
        transitionProperty: "transform",
        transitionTimingFunction: "ease-out",
        transitionDuration: "0.1s",
        variant: "forms.switch.thumb"
      }}
    />
  </Box>
);

https://codesandbox.io/s/styling-rebass-switch-r6tmx?file=/src/App.js

于 2020-07-16T23:27:03.603 回答
1

https://codesandbox.io/s/styling-rebass-switch-zto4z?file=/src/styles.css:37-1020

button.switch,
button.switch:hover,
button.switch:focus {
  outline: none;
  border: 1px solid grey;
  box-shadow: none;
}

button.switch > div {
  content: "";
  width: 14px;
  height: 14px;
  background-color: #9fa2ab;
}

button.switch > div:after {
  content: "";
  position: absolute;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  left: -2px;
  top: -3px;
  transition: left 0.3s ease, background-color 0.3s ease, box-shadow 0.1s ease,
    transform 0.1s ease;
  background-color: #5b5c60;
  -webkit-box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2),
    0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
  box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2),
    0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
}

button.switch[aria-checked="true"] {
  background-color: #d0f35e;
}
button.switch[aria-checked="true"] > div:after {
  background-color: #86af00;
}
button.switch[aria-checked="false"] {
  background-color: #ffffff;
  left: 18px;
}

添加类开关

<Switch
            
            className="switch"
            sx={{ width: "30px", height: "15px" }}
            checked={switched}
            onClick={() => toggleSwitch()}
          />
于 2020-07-21T19:36:34.757 回答
1

不幸的是,你不能。我深入研究了包本身,似乎这个包中编写的组件没有固定的规则。一些组件确实得到propssx。但是有些组件,例如switch将另一个组件作为子组件托管,并且没有传递给它的道具。

如果您在switch 此处查看此页面中的实现:

export const Switch = forwardRef(({
  checked,
  ...props
}, ref) =>
  <Box
    ref={ref}
    as='button'
    type='button'
    role='switch'
    tx='forms'
    variant='switch'
    aria-checked={checked}
    {...props}
    __css={{
      appearance: 'none',
      m: 0,
      p: 0,
      width: 40,
      height: 24,
      color: 'primary',
      bg: 'transparent',
      border: '1px solid',
      borderColor: 'primary',
      borderRadius: 9999,
      '&[aria-checked=true]': {
        bg: 'primary',
      },
      ':focus': {
        outline: 'none',
        boxShadow: '0 0 0 2px'
      },
    }}>
    <Box
      aria-hidden
      style={{
        transform: checked ? 'translateX(16px)' : 'translateX(0)',
      }}
      sx={{
        mt: '-1px',
        ml: '-1px',
        width: 24,
        height: 24,
        borderRadius: 9999,
        border: '1px solid',
        borderColor: 'primary',
        bg: 'background',
        transitionProperty: 'transform',
        transitionTimingFunction: 'ease-out',
        transitionDuration: '0.1s',
        variant: 'forms.switch.thumb',
      }}
    />
  </Box>
)

有 2 个Box组件(它们是包的基本组件),一个是另一个的子组件。第一个Box是开关的区域,子Box元素是你要找的圆圈/按钮,如果你看一下这个组件,你会发现没有传递给它的外部变量,所以什么都不能改变 -样式已经写好了。

这是 Button/Circle 组件:

    <Box
      aria-hidden
      style={{
        transform: checked ? 'translateX(16px)' : 'translateX(0)',
      }}
      sx={{
        mt: '-1px',
        ml: '-1px',
        width: 24,
        height: 24,
        borderRadius: 9999,
        border: '1px solid',
        borderColor: 'primary',
        bg: 'background',
        transitionProperty: 'transform',
        transitionTimingFunction: 'ease-out',
        transitionDuration: '0.1s',
        variant: 'forms.switch.thumb',
      }}
    />

如果你仍然愿意使用那个包,你可以通过覆盖 css 来克服这个问题,给组件一个 className 并将样式应用到它的子组件。

另外,您可以在包 github 存储库上打开问题或提出修复建议。

于 2020-07-16T23:34:09.353 回答
1

查看Switch 源代码,似乎没有属性传播到内部<div>......你会打开一个问题吗?

同时,您可以为子级和/或基于属性设置 css 属性:

.myswitch {
  width: 30px !important;
  height: 15px !important;
  background: gray !important;
}

.myswitch[aria-checked="true"] {
  background: red !important;
}

.myswitch div {
  width: 15px;
  height: 15px;
  background: red;
}

然后:

<Switch className="myswitch" />

https://codesandbox.io/s/styling-rebass-switch-o0j8t

于 2020-07-16T23:35:08.603 回答
1

您可以使用 CSS 变换比例来缩小/放大元素及其子元素。因为,你正在使用情感,这里有一些与之相伴的东西。

规模文件

CodeSandbox:https ://codesandbox.io/s/styling-rebass-switch-5fqku?file=/src/App.js

import React, { useState } from "react";
import styled from "@emotion/styled";
import { Label, Checkbox, Switch } from "@rebass/forms";

const Title = styled.h1`
  text-align: center;
`;

const FormLabel = styled(Label)`
  align-items: center;
`;

const Control = styled.div`
  width: 40px;
`;

const Toggle = styled(Switch)`
  transform: scale(.7)
`;


export default function App() {
  const [switched, setSwitched] = useState(false);
  const toggleSwitch = () => {
    setSwitched(!switched);
  };
  return (
    <div className="App">
      <Title>How to Style Rebass/Forms Switch</Title>
      <FormLabel sx={{ padding: "10px" }}>
        <Control>
          <Checkbox size="16px" sx={{ marginLeft: "10px" }} />
        </Control>
        CheckBox
      </FormLabel>
      <FormLabel sx={{ padding: "10px" }}>
        <Control>
          <Toggle
            checked={switched}
            onClick={() => toggleSwitch()}
          />
        </Control>
        Switch
      </FormLabel>
    </div>
  );
}
于 2020-07-20T15:51:53.277 回答