mirror of
https://ghproxy.net/https://github.com/abhijitb/helix.git
synced 2025-08-27 20:13:02 +08:00
fixed toggle input
This commit is contained in:
parent
6235dc79c4
commit
c29c823d56
4 changed files with 122 additions and 57 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import FormField from './FormField';
|
||||
|
||||
/**
|
||||
* Toggle/Checkbox input component
|
||||
* Toggle switch component with proper accessibility
|
||||
* @param root0
|
||||
* @param root0.label
|
||||
* @param root0.description
|
||||
|
@ -12,6 +12,7 @@ import FormField from './FormField';
|
|||
* @param root0.disabled
|
||||
* @param root0.error
|
||||
* @param root0.className
|
||||
* @param root0.id
|
||||
*/
|
||||
const ToggleInput = ( {
|
||||
label,
|
||||
|
@ -22,10 +23,14 @@ const ToggleInput = ( {
|
|||
disabled = false,
|
||||
error = null,
|
||||
className = '',
|
||||
id = `toggle-${ Math.random().toString( 36 ).substr( 2, 9 ) }`,
|
||||
...props
|
||||
} ) => {
|
||||
const handleChange = ( event ) => {
|
||||
onChange( event.target.checked );
|
||||
const handleToggle = () => {
|
||||
if ( disabled ) {
|
||||
return;
|
||||
}
|
||||
onChange( ! value );
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -35,19 +40,41 @@ const ToggleInput = ( {
|
|||
required={ required }
|
||||
className={ `helix-toggle-field ${ className }` }
|
||||
>
|
||||
<label className="helix-toggle-wrapper">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={ !! value }
|
||||
onChange={ handleChange }
|
||||
required={ required }
|
||||
<div className="helix-toggle-wrapper">
|
||||
{ label && (
|
||||
<label
|
||||
htmlFor={ id }
|
||||
className={ `helix-toggle-label ${
|
||||
disabled ? 'helix-toggle-label-disabled' : ''
|
||||
}` }
|
||||
>
|
||||
{ label }
|
||||
</label>
|
||||
) }
|
||||
|
||||
<button
|
||||
id={ id }
|
||||
type="button"
|
||||
role="switch"
|
||||
aria-checked={ !! value }
|
||||
onClick={ handleToggle }
|
||||
disabled={ disabled }
|
||||
className="helix-toggle-input"
|
||||
className={ `helix-toggle-switch ${
|
||||
value
|
||||
? 'helix-toggle-switch-on'
|
||||
: 'helix-toggle-switch-off'
|
||||
} ${ disabled ? 'helix-toggle-switch-disabled' : '' }` }
|
||||
{ ...props }
|
||||
/>
|
||||
<span className="helix-toggle-slider"></span>
|
||||
<span className="helix-toggle-label">{ label }</span>
|
||||
</label>
|
||||
>
|
||||
<span
|
||||
className={ `helix-toggle-knob ${
|
||||
value
|
||||
? 'helix-toggle-knob-on'
|
||||
: 'helix-toggle-knob-off'
|
||||
}` }
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</FormField>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -364,45 +364,83 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.helix-toggle-input {
|
||||
position: relative;
|
||||
width: 48px;
|
||||
height: 24px;
|
||||
appearance: none;
|
||||
background: var(--helix-color-3);
|
||||
border-radius: 12px;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.helix-toggle-input:checked {
|
||||
background: var(--helix-color-8);
|
||||
}
|
||||
|
||||
.helix-toggle-input::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: var(--helix-color-1);
|
||||
border-radius: 50%;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.helix-toggle-input:checked::before {
|
||||
transform: translateX(24px);
|
||||
}
|
||||
|
||||
.helix-toggle-label {
|
||||
font-weight: 500;
|
||||
color: var(--helix-color-9);
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.helix-toggle-label-disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Toggle Switch Button */
|
||||
.helix-toggle-switch {
|
||||
position: relative;
|
||||
width: 48px;
|
||||
height: 24px;
|
||||
border-radius: 24px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease-in-out;
|
||||
flex-shrink: 0;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.helix-toggle-switch:focus {
|
||||
box-shadow: 0 0 0 3px var(--helix-color-3);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Switch States */
|
||||
.helix-toggle-switch-off {
|
||||
background-color: var(--helix-color-3);
|
||||
}
|
||||
|
||||
.helix-toggle-switch-off:hover:not(:disabled) {
|
||||
background-color: var(--helix-color-4);
|
||||
}
|
||||
|
||||
.helix-toggle-switch-on {
|
||||
background-color: var(--helix-color-8);
|
||||
}
|
||||
|
||||
.helix-toggle-switch-on:hover:not(:disabled) {
|
||||
background-color: var(--helix-color-9);
|
||||
}
|
||||
|
||||
.helix-toggle-switch-disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Toggle Knob */
|
||||
.helix-toggle-knob {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
transition: transform 0.2s ease-in-out;
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.helix-toggle-knob-on {
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
.helix-toggle-knob-off {
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
/* Notifications */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue