From 1ea1e627efad620bb58deb5c37ef372aa09c1f1b Mon Sep 17 00:00:00 2001 From: Antonio Sonis Date: Wed, 23 Oct 2024 16:26:47 +0200 Subject: [PATCH] feat: checkbox and toggle switch with size prop Signed-off-by: Antonio Sonis --- src/components/Checkbox.jsx | 14 ++++++--- src/components/Checkbox.module.css | 31 ++++++++++++++++---- src/components/forms/ToggleSwitch.jsx | 15 ++++++++-- src/components/forms/ToggleSwitch.module.css | 28 +++++++++++++++--- src/stories/Checkbox.stories.jsx | 6 +++- 5 files changed, 77 insertions(+), 17 deletions(-) diff --git a/src/components/Checkbox.jsx b/src/components/Checkbox.jsx index 40fd1f58..6cfdb9e3 100644 --- a/src/components/Checkbox.jsx +++ b/src/components/Checkbox.jsx @@ -2,14 +2,16 @@ import React from 'react' import PropTypes from 'prop-types' import styles from './Checkbox.module.css' -import { MAIN_DARK_BLUE, RICH_BLACK, WHITE } from './constants' +import { MAIN_DARK_BLUE, MEDIUM, RICH_BLACK, SMALL, WHITE } from './constants' function Checkbox ({ disabled = false, color = MAIN_DARK_BLUE, + size = MEDIUM, ...rest }) { - let className = `${styles.checkbox} ` - className += styles[`checkbox--${color}`] + let className = `${styles.checkbox}` + className += ' ' + styles[`checkbox--${size}`] + className += ' ' + styles[`checkbox--${color}`] if (disabled) className += ` ${styles.disabled}` return ( @@ -24,7 +26,11 @@ Checkbox.propTypes = { /** * color */ - color: PropTypes.oneOf([WHITE, MAIN_DARK_BLUE, RICH_BLACK]) + color: PropTypes.oneOf([WHITE, MAIN_DARK_BLUE, RICH_BLACK]), + /** + * size + */ + size: PropTypes.oneOf([SMALL, MEDIUM]) } export default Checkbox diff --git a/src/components/Checkbox.module.css b/src/components/Checkbox.module.css index d4ba94bd..6166008d 100644 --- a/src/components/Checkbox.module.css +++ b/src/components/Checkbox.module.css @@ -1,8 +1,16 @@ .checkbox { - @apply border border-solid p-2 rounded-sm relative inline-block h-2 w-2 m-0; + @apply border border-solid rounded-sm relative inline-block m-0; -webkit-appearance: none; } +.checkbox--medium { + @apply p-2 h-2 w-2; +} + +.checkbox--small { + @apply p-[5px] h-[10px] w-[10px]; +} + .checkbox--main-dark-blue { @apply border-light-green bg-main-dark-blue } @@ -16,14 +24,20 @@ .checkbox--white:checked { @apply bg-white text-rich-black; } -.checkbox--main-dark-blue:checked:after, -.checkbox--rich-black:checked:after { +.checkbox--medium.checkbox--main-dark-blue:checked:after, +.checkbox--medium.checkbox--rich-black:checked:after { @apply absolute h-full w-full; top: 1px; left: 1.5px; content: url('data:image/svg+xml,%3Csvg%20width%3D%2213%22%20height%3D%229%22%20viewBox%3D%220%200%2013%209%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M1%204L5%208L12%201%22%20stroke%3D%22white%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E'); } - +.checkbox--small.checkbox--main-dark-blue:checked:after, +.checkbox--small.checkbox--rich-black:checked:after { + @apply absolute h-full w-full; + top: 1px; + left: 1px; + content: url('data:image/svg+xml,%3Csvg%20width%3D%2211%22%20height%3D%228%22%20viewBox%3D%220%200%2011%208%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%3Cpath%20d%3D%22M1.25%203.5L4.25%206.5L9.5%201.25%22%20stroke%3D%22white%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%20%3C%2Fsvg%3E'); +} .disabled { @apply border-white; } @@ -34,9 +48,16 @@ .checkbox--rich-black:checked { @apply bg-white text-rich-black; } -.checkbox--white:checked:after { +.checkbox--medium.checkbox--white:checked:after { @apply absolute h-full w-full; top: 1px; left: 1.5px; content: url('data:image/svg+xml,%3Csvg%20width=%2213%22%20height=%229%22%20viewBox=%220%200%2013%209%22%20fill=%22none%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cpath%20d=%22M1%204L5%208L12%201%22%20stroke%3D%22%2300050B%22%20stroke-width=%222%22%20stroke-linecap=%22round%22%20stroke-linejoin=%22round%22/%3E%3C/svg%3E'); } + +.checkbox--small.checkbox--white:checked:after { + @apply absolute h-full w-full; + top: -2px; + left: 0px; + content: url('data:image/svg+xml,%3Csvg%20width%3D%2211%22%20height%3D%228%22%20viewBox%3D%220%200%2011%208%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%3Cpath%20d%3D%22M1.25%203.5L4.25%206.5L9.5%201.25%22%20stroke%3D%22%2300050B%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%20%3C%2Fsvg%3E'); +} \ No newline at end of file diff --git a/src/components/forms/ToggleSwitch.jsx b/src/components/forms/ToggleSwitch.jsx index 24d6b0f2..ac6eb4d1 100644 --- a/src/components/forms/ToggleSwitch.jsx +++ b/src/components/forms/ToggleSwitch.jsx @@ -3,6 +3,7 @@ import React from 'react' import PropTypes from 'prop-types' import styles from './ToggleSwitch.module.css' import commonStyles from '../Common.module.css' +import { MEDIUM, SMALL } from '../constants' function ToggleSwitch ({ name = '', @@ -12,19 +13,23 @@ function ToggleSwitch ({ errorMessageTextClassName = '', onChange = () => {}, checked = false, - disabled = false + disabled = false, + size = MEDIUM }) { let className = `${styles.switch} ` + className += styles[`switch--${size}`] + ' ' if (disabled) className += styles.disabled const styleLabel = labelClassName || styles.defaultLabel const errorMessageClassName = errorMessageTextClassName || commonStyles['error-message'] + let sliderClassName = `${styles.slider} ${styles.round} ` + sliderClassName += styles[`slider--${size}`] return ( <>
{label}
@@ -65,7 +70,11 @@ ToggleSwitch.propTypes = { /** * labelClassName */ - labelClassName: PropTypes.string + labelClassName: PropTypes.string, + /** + * size + */ + size: PropTypes.oneOf([SMALL, MEDIUM]) } diff --git a/src/components/forms/ToggleSwitch.module.css b/src/components/forms/ToggleSwitch.module.css index 43a6d2b5..1f837080 100644 --- a/src/components/forms/ToggleSwitch.module.css +++ b/src/components/forms/ToggleSwitch.module.css @@ -2,7 +2,13 @@ @apply flex w-full h-10 items-center gap-x-2; } .switch { - @apply relative inline-block w-[50px] h-[24px] cursor-pointer; + @apply relative inline-block cursor-pointer; +} +.switch--medium { + @apply w-[50px] h-[24px] +} +.switch--small { + @apply w-[30px] h-[16px] } .switch input { @apply opacity-0 w-0 h-0; @@ -13,26 +19,40 @@ -webkit-transition: .4s; transition: .4s; } + .defaultLabel { @apply px-2 text-xs font-normal text-main-dark-blue; } -.slider:before { - @apply absolute h-4 w-4 left-[4px] bottom-[4px] bg-white; +.slider--small:before, +.slider--medium:before { content: ""; -webkit-transition: .4s; transition: .4s; } +.slider--medium:before { + @apply absolute h-[22px] w-[22px] left-[1px] bottom-[1px] bg-white; +} +.slider--small:before{ + @apply absolute h-[14px] w-[14px] left-[1px] bottom-[1px] bg-white; +} + input:checked + .slider { @apply bg-main-green; } -input:checked + .slider:before { +input:checked + .slider--medium:before { -webkit-transform: translateX(26px); -ms-transform: translateX(26px); transform: translateX(26px); } +input:checked + .slider--small:before { + -webkit-transform: translateX(14px); + -ms-transform: translateX(14px); + transform: translateX(14px); +} + /* Rounded sliders */ .slider.round { border-radius: 100px; diff --git a/src/stories/Checkbox.stories.jsx b/src/stories/Checkbox.stories.jsx index d9817382..974b10bf 100644 --- a/src/stories/Checkbox.stories.jsx +++ b/src/stories/Checkbox.stories.jsx @@ -1,6 +1,6 @@ 'use strict' import Checkbox from '../components/Checkbox' -import { WHITE } from '../components/constants' +import { MEDIUM, SMALL, WHITE } from '../components/constants' const divStyle = { width: '100%', height: 'auto', @@ -24,6 +24,10 @@ export default { }, disabled: { type: 'boolean' + }, + size: { + type: 'radio', + options: [SMALL, MEDIUM] } } }