在 React Styled-Components 利用 Checkbox 的 checked 和 onChange 客製 Radio Button

Angel
Its Ok to Make Mistakes
10 min readApr 9, 2019

Radio Button

第一步:先確定 React Styled-Component 開發環境設定完成

可以參考:使用 Create-React-App 建構 React Styled-Components 及 Sass 開發環境

第二步: type 及 name

在 Template 用選項 Item 將RadioButtonRadioButtonLabel包在一起,並在 RadioButton 標註 type 及 name。

import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
const App = () => {
return (
<Wrapper>
<Item>
<RadioButton type="radio" name="radio" />
<RadioButtonLabel />
<div>Auto accept better price only</div>
</Item>
<Item>
<RadioButton type="radio" name="radio" />
<RadioButtonLabel />
<div>Auto accept any price change</div>
</Item>
<Item>
<RadioButton type="radio" name="radio" />
<RadioButtonLabel />
<div>Never auto accept a price change</div>
</Item>
</Wrapper>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

第三步:Style label 及 Button

RadioButtonLabel 使用 label 畫出沒有點擊時空心的按鈕狀態使用 label,RadioButton 使用 input 來製作點擊切換,設定透明度為0,大小與 RadioButtonLabel 一致,並將 RadioButton 與 RadioButtonLabel 重疊。!!!注意:RadioButton 的位置必須在 RadioButtonLabel 之前,才能夠點擊該按鈕。因此要在 RadioButton 加上 z-index: 1;

const Wrapper = styled.div`
height: auto;
width: 100%;
padding: 0px 16px 24px 16px;
box-sizing: border-box;
`;
const Item = styled.div`
display: flex;
align-items: center;
height: 48px;
position: relative;
`;
const RadioButtonLabel = styled.label`
position: absolute;
top: 25%;
left: 4px;
width: 24px;
height: 24px;
border-radius: 50%;
background: white;
border: 1px solid #bebebe;
`;
const RadioButton = styled.input`
opacity: 0;
z-index: 1;
border-radius: 50%;
width: 24px;
height: 24px;
margin-right: 10px;
`;

第四步:「:checked

設定點擊 CheckBox 的時候必須從 RadioButton 以:checked 搭配+控制${RadioButtonLabel}去切換背景顏色。

const RadioButton = styled.input`
opacity: 0;
z-index: 1;
border-radius: 50%;
width: 24px;
height: 24px;
margin-right: 10px;
&:checked + ${RadioButtonLabel} {
background: #db7290;
border: 1px solid #db7290;
}
`;

第五步:CSS 偽元素

使用 CSS 偽元素製作出可以切換的圓形按鈕於 RadioButton。

const RadioButton = styled.input`
opacity: 0;
z-index: 1;
border-radius: 50%;
width: 24px;
height: 24px;
margin-right: 10px;
&:checked + ${RadioButtonLabel} {
background: #db7290;
border: 1px solid #db7290;
&::after {
content: "";
display: block;
border-radius: 50%;
width: 12px;
height: 12px;
margin: 6px;
box-shadow: 1px 3px 3px 1px rgba(0, 0, 0, 0.1);
background: white;
}
}
`;

第六步:Mouse Over 效果

設定滑鼠的 hover 效果不能直接在 RadioButtonLabel 控制,因為 RadioButton 在 RadioButtonLabel 的上一層。必須在 RadioButton 使用+控制CheckBoxLabel去切換背景顏色。

const RadioButton = styled.input`
opacity: 0;
z-index: 1;
border-radius: 50%;
width: 24px;
height: 24px;
}
&:hover ~ ${RadioButtonLabel}{
background: #bebebe;
&::after {
content: "";
display: block;
border-radius: 50%;
width: 12px;
height: 12px;
margin: 6px;
background: #eeeeee;
}
}
&:checked + ${RadioButtonLabel} {
background: #db7290;
border: 1px solid #db7290;
Z-index: 3;
&::after {
content: "";
display: block;
border-radius: 50%;
width: 12px;
height: 12px;
margin: 6px;
box-shadow: 1px 3px 3px 1px rgba(0, 0, 0, 0.1);
background: white;
}
}
`

第七步:設定預設狀態

在 Template 用 React Hooks 的 useState 給予初始狀態,並設定不同 RadioButton 的 Value 及 checked 的時候 select 到哪一個 Button。

const { useState } = React;const App = () => {
const [select, setSelect] = useState("betterPriceOnly");
return (
<Wrapper>
<Item>
<RadioButton
type="radio"
name="radio"
value="betterPriceOnly"
checked={select === "betterPriceOnly"}
/>
<RadioButtonLabel />
<div>Auto accept better price only</div>
</Item>
<Item>
<RadioButton
type="radio"
name="radio"
value="anyPriceChange"
checked={select === "anyPriceChange"}
/>
<RadioButtonLabel />
<div>Auto accept any price change</div>
</Item>
<Item>
<RadioButton
type="radio"
name="radio"
value="neverAutoAccept"
checked={select === "neverAutoAccept"}
/>
<RadioButtonLabel />
<div>Never auto accept a price change</div>
</Item>
</Wrapper>
);
};

第八步:實作 onChange 事件

實作 onChange 事件,讓 event.target.value 在每一次 checked 發生時改變

const App = () => {
const [select, setSelect] = useState("betterPriceOnly");
const handleSelectChange = event => {
const value = event.target.value;
setSelect(value);
};
return (
<Wrapper>
<Item>
<RadioButton
type="radio"
name="radio"
value="betterPriceOnly"
checked={select === "betterPriceOnly"}
onChange={event => handleSelectChange(event)}
/>
<RadioButtonLabel />
<div>Auto accept better price only</div>
</Item>
<Item>
<RadioButton
type="radio"
name="radio"
value="anyPriceChange"
checked={select === "anyPriceChange"}
onChange={event => handleSelectChange(event)}
/>
<RadioButtonLabel />
<div>Auto accept any price change</div>
</Item>
<Item>
<RadioButton
type="radio"
name="radio"
value="neverAutoAccept"
checked={select === "neverAutoAccept"}
onChange={event => handleSelectChange(event)}
/>
<RadioButtonLabel />
<div>Never auto accept a price change</div>
</Item>
</Wrapper>
);
};
Say hello! 我是 Angel,這裏的內容如果有幫到你,希望能獲得一些拍手作為鼓勵 
工作上的合作歡迎隨時透過 Mail 聯繫我 contact@aneglho.design

Thanks for watching!

--

--

Angel
Its Ok to Make Mistakes

A web / UIUX designer, in digital entertainment industry, Taipei Taiwan.