From f87f22df725adcec85189b1bface21730dcbd10e Mon Sep 17 00:00:00 2001 From: Aarni Halinen Date: Thu, 23 Jul 2020 20:58:12 +0300 Subject: [PATCH] Custom RadioButton --- src/components/Checkbox/Checkbox.tsx | 16 ++-- src/components/RadioButton/RadioButton.tsx | 69 +++++++++++++++++ .../RadioButton/RadioButtonWidget.tsx | 74 +++++++++++++++++++ src/views/SignUpPage/SignUpPageView.tsx | 3 +- 4 files changed, 153 insertions(+), 9 deletions(-) create mode 100644 src/components/RadioButton/RadioButton.tsx create mode 100644 src/components/RadioButton/RadioButtonWidget.tsx diff --git a/src/components/Checkbox/Checkbox.tsx b/src/components/Checkbox/Checkbox.tsx index 9d5378c..451e962 100644 --- a/src/components/Checkbox/Checkbox.tsx +++ b/src/components/Checkbox/Checkbox.tsx @@ -10,13 +10,13 @@ const Container = styled.label` user-select: none; /* On mouse-over, add a grey background color */ - &:hover input ~ .custombox { + &:hover input ~ .custom-cbox { background-color: #d4d0c7; /* grey1 */ } `; /* Hide the browser's default checkbox */ -const DefaultBox = styled.input` +const HiddenDefaultElement = styled.input` position: absolute; opacity: 0; height: 0; @@ -24,14 +24,14 @@ const DefaultBox = styled.input` `; /* Create a custom checkbox */ -const CustomBox = styled.span<{checked?: boolean}>` +const CustomCBoxElement = styled.span<{checked?: boolean}>` border-radius: 4px; position: absolute; top: 0; left: 0; height: 1em; width: 1em; - background-color: ${(props) => props.checked ? "#002d3a" : "#efece4"}; /* dark-blue or grey2 */ + background-color: ${(props) => props.checked ? "#57b2df" : "#efece4"}; /* blue1 or grey2 */ &:focus &:before { transition: box-shadow 150ms ease; @@ -47,7 +47,7 @@ const CustomBox = styled.span<{checked?: boolean}>` } `; -const Checkmark = styled.span` +const Checkmark = styled.div` position: absolute; left: 0.375em; top: calc(0.25em - 1px); @@ -66,15 +66,15 @@ type CheckboxProps = Omit< const Checkbox: React.FC = ({children, checked, ...props}) => ( {children} - - + {checked && ()} - + ) diff --git a/src/components/RadioButton/RadioButton.tsx b/src/components/RadioButton/RadioButton.tsx new file mode 100644 index 0000000..2f9bc27 --- /dev/null +++ b/src/components/RadioButton/RadioButton.tsx @@ -0,0 +1,69 @@ +import React from "react"; +import styled from "styled-components"; + +const Container = styled.label` + display: block; + position: relative; + padding-left: 2rem; + cursor: pointer; + font-size: 1.5rem; /* 24px */ + user-select: none; + + /* On mouse-over, add a grey background color */ + &:hover input ~ .custom-radio { + background-color: #d4d0c7; /* grey1 */ + } +`; + +const HiddenDefaultElement = styled.input` + position: absolute; + opacity: 0; + height: 0; + width: 0; +`; + +const CustomRadioElement = styled.span<{checked?: boolean}>` + position: absolute; + top: 0; + left: 0; + height: 1em; + width: 1em; + background-color: ${(props) => props.checked ? "#57b2df" : "#efece4"}; /* blue1 or grey2 */ + border-radius: 50%; +`; + +const Indicator = styled.div` + position: absolute; + top: 0.25em; + left: 0.25em; + width: 0.5em; + height: 0.5em; + border-radius: 50%; + background: white; +`; + +type RadioButtonProps = Omit< + React.InputHTMLAttributes, + "type" +>; + +const RadioButton: React.FC = ({ + checked, + children, + ...props +}) => ( + + {children} + + + {checked && ()} + + +); + +export default RadioButton; diff --git a/src/components/RadioButton/RadioButtonWidget.tsx b/src/components/RadioButton/RadioButtonWidget.tsx new file mode 100644 index 0000000..920059e --- /dev/null +++ b/src/components/RadioButton/RadioButtonWidget.tsx @@ -0,0 +1,74 @@ +import React from "react"; +import styled from "styled-components"; +import { WidgetProps } from "react-jsonschema-form"; +import RadioButton from "./RadioButton"; + +type RadioButtonWidgetProps = Omit & { + options: any; +}; + +const RadioButtonContainer = styled.div` + margin-bottom: 0.5rem; +`; + +const RadioButtonWidget: React.FC = (props) => { + const { + options, + value, + required, + disabled, + readonly, + autofocus, + onBlur, + onFocus, + onChange, + id, + } = props; + // Generating a unique field name to identify this set of radio buttons + const name = Math.random().toString(); + const { enumOptions, enumDisabled, inline } = options; + // checked={checked} has been moved above name={name}, As mentioned in #349; + // this is a temporary fix for radio button rendering bug in React, facebook/react#7630. + return ( +
+ {enumOptions.map((option, i) => { + const checked = option.value === value; + const itemDisabled = + enumDisabled && enumDisabled.indexOf(option.value) != -1; + const disabledCls = + disabled || itemDisabled || readonly ? "disabled" : ""; + const radio = ( + onChange(option.value)} + onBlur={onBlur && (event => onBlur(id, event.target.value))} + onFocus={onFocus && (event => onFocus(id, event.target.value))} + > + {option.label} + + ); + + return inline ? ( + + ) : ( + + {radio} + + ); + })} +
+ ); +} + +RadioButtonWidget.defaultProps = { + autofocus: false, +}; + +export default RadioButtonWidget; \ No newline at end of file diff --git a/src/views/SignUpPage/SignUpPageView.tsx b/src/views/SignUpPage/SignUpPageView.tsx index 991eaa2..62d208a 100644 --- a/src/views/SignUpPage/SignUpPageView.tsx +++ b/src/views/SignUpPage/SignUpPageView.tsx @@ -7,9 +7,10 @@ import { buildSchema, buildUISchema } from "./FormUtils"; import AsideSection from "@components/AsideSection"; import MainSection from "@components/MainSection"; import Checkboxes from "@components/Checkbox/Checkboxes"; +import RadioButtonWidget from "@components/RadioButton/RadioButtonWidget"; const customWidgets = { - // "radio": Checkbox, + "radio": RadioButtonWidget, "checkboxes": Checkboxes };