Stack Overflow Asked by amaster on December 9, 2021
Using Rebass/Forms in react and I cannot properly resize the Switch component using styles properly. (I also am using @emotion/styled
)
I have tried using a size
attribute, but that does not give the desired effect of simply changing the scale of the switch.
I have tried using the sx
property and giving it a width
and a height
, but that only resizes the button element and not the inner div which is the "sliding dot"
I know that I could write some styling targeting the inner div itself, but I would like to find a way to give it a height and width a single time and it apply to both the button and the inner div.
<Switch
sx={{ width: "30px", height: "15px" }}
/>
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;
}
Add class switch
<Switch
className="switch"
sx={{ width: "30px", height: "15px" }}
checked={switched}
onClick={() => toggleSwitch()}
/>
Answered by Velu S Gautam on December 9, 2021
You could use CSS transform scale to scale down/up an element and it's children. As, you're using emotion, here's something that goes along with it.
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>
);
}
Answered by sudo bangbang on December 9, 2021
Looking at Switch source code it seems no properties are propagated to the inner <div>
... would you open an issue?
In the mean while you can set css properties for children and/or based on attributes:
.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;
}
then:
<Switch className="myswitch" />
Answered by Daniele Ricci on December 9, 2021
Unfortunately, you can't. I took a deep look into the package itself and it seems like there is no fixed rule for the components written in this package. Some component do get the props
and the sx
. But there are components, like switch
that hosts another component as a children, and no prop passed to it.
If you take a look at the implementation of switch
in this page here:
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>
)
There are 2 Box
components (which are the base component of the package), one is a children of the other. The first Box
is the area of the switch, and the child Box
is the circle/button you are looking for, If you take a look on this component, you will see there is no outside variable that passed to it, so nothing can be changed - the style is already written.
This is the Button/Circle component:
<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',
}}
/>
If you are still willing to use that package, you can overcome this by overwriting the css, giving the component a className and apply styling to its children.
Plus, you can open an issue or suggest a fix on the package github repository.
Answered by SomoKRoceS on December 9, 2021
It is not possible to do what you want 'out of the box' because the height and width are hard coded in the source
Luckily the internals of rebass
are very nice, so it's possible to create your own with a little copy-pasta from the rebass source code.
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
Answered by lastcanal on December 9, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP