Skip to content

Commit

Permalink
Merge pull request #235 from US-CBP/feature/toggle
Browse files Browse the repository at this point in the history
Toggle component
  • Loading branch information
bagrub authored Dec 23, 2024
2 parents c9b4ee9 + b3b26c7 commit 9dcf790
Show file tree
Hide file tree
Showing 5 changed files with 431 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ cbp-form-field {
all: unset;
}

fieldset{
display: block;
}

.cbp-form-field-label {
display: block;
color: var(--cbp-form-field-color-label);
Expand Down
239 changes: 230 additions & 9 deletions packages/web-components/src/components/cbp-toggle/cbp-toggle.scss
Original file line number Diff line number Diff line change
@@ -1,17 +1,238 @@
/**
* @Prop --cbp-toggle-XXX
* @Prop --cbp-toggle-color-bg: var(--cbp-color-interactive-secondary-light);
* @Prop --cbp-toggle-color-bg-dark: var(--cbp-color-interactive-secondary-dark);
* @Prop --cbp-toggle-color-circle: var(--cbp-color-white);
* @Prop --cbp-toggle-color-circle-dark: var(--cbp-color-white);
* @Prop --cbp-toggle-color-circle-border: var(--cbp-toggle-color-circle);
* @Prop --cbp-toggle-color-circle-border-dark: var(--cbp-toggle-color-circle-dark);
* @Prop --cbp-toggle-outline-width: 2px;
* @Prop --cbp-toggle-outline-style: solid;
* @Prop --cbp-toggle-outline-color: transparent;
* @Prop --cbp-toggle-outline: var(--cbp-toggle-outline-width) var(--cbp-toggle-outline-style) var(--cbp-toggle-outline-color);
* @Prop --cbp-toggle-outline-color-dark: 2px solid transparent;
* @Prop --cbp-toggle-outline-dark: var(--cbp-toggle-outline-width) var(--cbp-toggle-outline-style) var(--cbp-toggle-outline-color-dark);
* @Prop --cbp-toggle-color-bg-hover: var(--cbp-color-interactive-secondary-dark);
* @Prop --cbp-toggle-color-bg-hover-dark: var(--cbp-color-interactive-secondary-base);
* @Prop --cbp-toggle-circle-selected-color-hover: var(--cbp-color-interactive-selected-dark);
* @Prop --cbp-toggle-circle-selected-color-hover-dark: var(--cbp-color-interactive-selected-light);
* @Prop --cbp-toggle-circle-selected-border-color-hover: var(--cbp-color-white);
* @Prop --cbp-toggle-circle-selected-border-color-hover-dark: var(--cbp-color-interactive-secondary-darker);
* @Prop --cbp-toggle-color-circle-hover: var(--cbp-color-interactive-secondary-darker);
* @Prop --cbp-toggle-color-circle-hover-dark: var(--cbp-color-interactive-secondary-base);
* @Prop --cbp-toggle-color-circle-border-hover: var(--cbp-color-white);
* @Prop --cbp-toggle-color-circle-border-hover-dark: var(--cbp-color-white);
* @Prop --cbp-toggle-color-bg-focus: var(--cbp-color-interactive-focus-dark);
* @Prop --cbp-toggle-color-bg-focus-dark: var(--cbp-color-interactive-focus-light);
* @Prop --cbp-toggle-outline-focus: 2px solid var(--cbp-color-white);
* @Prop --cbp-toggle-outline-focus-dark: 2px solid var(--cbp-color-black);
* @Prop --cbp-toggle-color-bg-disabled: var(--cbp-color-interactive-disabled-dark);
* @Prop --cbp-toggle-color-bg-disabled-dark: var(--cbp-color-interactive-disabled-light);
* @Prop --cbp-toggle-color-circle-disabled: var(--cbp-color-interactive-disabled-light);
* @Prop --cbp-toggle-color-circle-disabled-dark: var(--cbp-color-interactive-disabled-dark);
* @Prop --cbp-toggle-color-circle-border-disabled: var(--cbp-color-interactive-disabled-light);
* @Prop --cbp-toggle-color-circle-border-disabled-dark: var(--cbp-color-interactive-disabled-dark);
* @Prop --cbp-toggle-control-width: 3.25rem;
* @Prop --cbp-toggle-control-height: 1.75rem;
* @Prop --cbp-toggle-circle-diameter: 1rem;
* @Prop --cbp-toggle-circle-inset: 0.375rem;
* @Prop --cbp-toggle-circle-border-width: 0.25rem;
* @Prop --cbp-toggle-gap: 1rem;
* @Prop --cbp-toggle-margin: 0 0 var(--cbp-space-4x) 0;
*/

// :root{
// --cbp-toggle-XXX: red;
// }
:root{
--cbp-toggle-color-bg: var(--cbp-color-interactive-secondary-light);
--cbp-toggle-color-bg-dark: var(--cbp-color-interactive-secondary-dark);
--cbp-toggle-color-circle: var(--cbp-color-white);
--cbp-toggle-color-circle-dark: var(--cbp-color-white);
--cbp-toggle-color-circle-border: var(--cbp-toggle-color-circle);
--cbp-toggle-color-circle-border-dark: var(--cbp-toggle-color-circle-dark);

--cbp-toggle-outline-width: 2px;
--cbp-toggle-outline-style: solid;
--cbp-toggle-outline-color: transparent;
--cbp-toggle-outline-color-dark: transparent;

// [data-cbp-theme=light] cbp-toggle[context*=dark]:not([context=light-always]),
// [data-cbp-theme=dark] cbp-toggle:not([context=dark-inverts]):not([context=light-always]) {
/** Hover */
--cbp-toggle-color-bg-hover: var(--cbp-color-interactive-secondary-dark);
--cbp-toggle-color-bg-hover-dark: var(--cbp-color-interactive-secondary-base);

--cbp-toggle-circle-selected-color-hover: var(--cbp-color-interactive-selected-dark);
--cbp-toggle-circle-selected-color-hover-dark: var(--cbp-color-interactive-selected-light);
--cbp-toggle-circle-selected-border-color-hover: var(--cbp-color-white);
--cbp-toggle-circle-selected-border-color-hover-dark: var(--cbp-color-interactive-secondary-darker);

// // --cbp-tooltip-color-bg: var(--cbp-tooltip-color-bg-dark);
// }
--cbp-toggle-color-circle-hover: var(--cbp-color-interactive-secondary-darker);
--cbp-toggle-color-circle-hover-dark: var(--cbp-color-interactive-secondary-base);
--cbp-toggle-color-circle-border-hover: var(--cbp-color-white);
--cbp-toggle-color-circle-border-hover-dark: var(--cbp-color-white);

/** Focus */
--cbp-toggle-color-bg-focus: var(--cbp-color-interactive-focus-dark);
--cbp-toggle-color-bg-focus-dark: var(--cbp-color-interactive-focus-light);
--cbp-toggle-outline-color-focus: var(--cbp-color-white);
--cbp-toggle-outline-color-focus-dark: var(--cbp-color-black);

/** Disabled */
--cbp-toggle-color-bg-disabled: var(--cbp-color-interactive-disabled-dark);
--cbp-toggle-color-bg-disabled-dark: var(--cbp-color-interactive-disabled-light);
--cbp-toggle-color-circle-disabled: var(--cbp-color-interactive-disabled-light);
--cbp-toggle-color-circle-disabled-dark: var(--cbp-color-interactive-disabled-dark);
--cbp-toggle-color-circle-border-disabled: var(--cbp-color-interactive-disabled-light);
--cbp-toggle-color-circle-border-disabled-dark: var(--cbp-color-interactive-disabled-dark);

--cbp-toggle-text-color: var(--cbp-color-text-darkest);
--cbp-toggle-text-color-dark: var(--cbp-color-text-lightest);

--cbp-toggle-control-width: 3.25rem;
--cbp-toggle-control-height: 1.75rem;
--cbp-toggle-circle-diameter: 1rem;
--cbp-toggle-circle-inset: 0.375rem;
--cbp-toggle-circle-border-width: 0.25rem;
--cbp-status-text-width: var(--cbp-space-16x);
--cbp-toggle-description-text-width: min-content;

--cbp-toggle-gap: var(--cbp-space-4x);
--cbp-toggle-margin: 0 0 var(--cbp-space-4x) 0;
}

[data-cbp-theme=light] cbp-toggle[context*=dark]:not([context=light-always]),
[data-cbp-theme=dark] cbp-toggle:not([context=dark-inverts]):not([context=light-always]) {

--cbp-toggle-color-bg: var(--cbp-toggle-color-bg-dark);
--cbp-toggle-color-circle: var(--cbp-toggle-color-circle-dark);
--cbp-toggle-color-circle-border: var(--cbp-toggle-color-circle-border-dark);
--cbp-toggle-outline-color: var(--cbp-toggle-outline-color-dark);

--cbp-toggle-color-bg-hover: var(--cbp-toggle-color-bg-hover-dark);
--cbp-toggle-circle-selected-color-hover: var(--cbp-toggle-circle-selected-color-hover-dark);
--cbp-toggle-circle-selected-border-color-hover: var(--cbp-toggle-circle-selected-border-color-hover-dark);
--cbp-toggle-color-circle-hover: var(--cbp-toggle-color-circle-hover-dark);
--cbp-toggle-color-circle-border-hover: var(--cbp-toggle-color-circle-border-hover-dark);

--cbp-toggle-color-bg-focus: var(--cbp-toggle-color-bg-focus-dark);
--cbp-toggle-outline-color-focus: var(--cbp-toggle-outline-color-focus-dark);

--cbp-toggle-color-bg-disabled: var(--cbp-toggle-color-bg-disabled-dark);
--cbp-toggle-color-circle-disabled: var(--cbp-toggle-color-circle-disabled-dark);
--cbp-toggle-color-circle-border-disabled: var(--cbp-toggle-color-circle-border-disabled-dark);

--cbp-toggle-text-color: var(--cbp-toggle-text-color-dark);
}

cbp-toggle {
border: 1px solid red; //TODO: local testing, remove before push
display: flex;
align-items: center;
margin: var(--cbp-toggle-margin);
color: var(--cbp-toggle-text-color);

label{
display: grid;
grid-template-columns: 3fr var(--cbp-toggle-control-width) 1fr;
gap: var(--cbp-toggle-gap);
align-items: center;
width: 100%;
}

input[type='checkbox']{
appearance: none;
height: var(--cbp-toggle-control-height);
min-width: var(--cbp-toggle-control-width);
flex-basis: var(--cbp-toggle-control-width);
border-radius: var(--cbp-border-radius-pill);
background-color: var(--cbp-toggle-color-bg);
outline: var(--cbp-toggle-outline-width) var(--cbp-toggle-outline-style) var(--cbp-toggle-outline-color);
outline-offset: calc( -1 * var(--cbp-space-1x));

&:before{
content: "";
display: block;
margin-top: var(--cbp-toggle-circle-inset);
border-radius: var(--cbp-border-radius-circle);
height: var(--cbp-toggle-circle-diameter);
width: var(--cbp-toggle-circle-diameter);
background-color: var(--cbp-toggle-color-circle);
border: var(--cbp-toggle-circle-border-width) solid var(--cbp-toggle-color-circle-border);
}
}

span:last-child{
flex-basis: var(--cbp-status-text-width);
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}

/** 'On' States */
&[checked] input[type='checkbox']{
--cbp-toggle-color-bg: var(--cbp-toggle-color-bg-hover);
--cbp-toggle-color-bg-dark: var(--cbp-toggle-color-bg-hover-dark);
--cbp-toggle-color-circle: var(--cbp-color-white);
--cbp-toggle-color-circle-dark: var(--cbp-color-interactive-secondary-darker);
--cbp-toggle-color-circle-border-dark: var(--cbp-color-interactive-secondary-darker);

&:before{
margin-left: calc(var(--cbp-toggle-control-width) - var(--cbp-toggle-circle-diameter) - var(--cbp-toggle-circle-inset));
}

&:hover:not([disabled]){
--cbp-toggle-color-circle: var(--cbp-toggle-circle-selected-color-hover);
--cbp-toggle-color-circle-border: var(--cbp-toggle-color-circle-border-hover);

--cbp-toggle-color-circle-dark: var(--cbp-toggle-circle-selected-color-hover-dark);
--cbp-toggle-color-circle-border-dark: var(--cbp-toggle-circle-selected-border-color-hover-dark);
}

&:focus:not([disabled]){

--cbp-toggle-color-bg: var(--cbp-toggle-color-bg-focus);
--cbp-toggle-outline-color: var(--cbp-toggle-outline-color-focus);

--cbp-toggle-color-bg-dark: var(--cbp-toggle-color-bg-focus-dark);
--cbp-toggle-outline-color-dark: var(--cbp-toggle-outline-color-focus-dark);
}
}

/** 'Off' States */
&:not([checked]) input[type='checkbox']{

&:before{
margin-left: var(--cbp-toggle-circle-inset);
}

&:hover:not([disabled]) {
--cbp-toggle-color-bg: var(--cbp-toggle-color-bg-hover);
--cbp-toggle-color-circle: var(--cbp-toggle-color-circle-hover);
--cbp-toggle-color-circle-border: var(--cbp-toggle-color-circle-border-hover);

--cbp-toggle-color-bg-dark: var(--cbp-toggle-color-bg-hover-dark);
--cbp-toggle-color-circle-dark: var(--cbp-toggle-color-circle-hover-dark);
--cbp-toggle-color-circle-border-dark: var(--cbp-toggle-color-circle-border-hover-dark);
}

&:focus:not([disabled]){
--cbp-toggle-color-bg: var(--cbp-toggle-color-bg-focus);
--cbp-toggle-outline-color: var(--cbp-toggle-outline-color-focus);

--cbp-toggle-color-bg-dark: var(--cbp-toggle-color-bg-focus-dark);
--cbp-toggle-outline-color-dark: var(--cbp-toggle-outline-color-focus-dark);
--cbp-toggle-color-circle-dark: var(--cbp-color-interactive-secondary-darker);
--cbp-toggle-color-circle-border-dark: var(--cbp-color-interactive-secondary-darker);;
}
}

/** Disabled*/
&[disabled]{
--cbp-toggle-color-bg: var(--cbp-toggle-color-bg-disabled);
--cbp-toggle-color-bg-dark: var(--cbp-toggle-color-bg-disabled-dark);
--cbp-toggle-color-circle: var(--cbp-toggle-color-circle-disabled);
--cbp-toggle-color-circle-dark: var(--cbp-toggle-color-circle-disabled-dark);
--cbp-toggle-color-circle-border: var(--cbp-toggle-color-circle-border-disabled);
--cbp-toggle-color-circle-border-dark: var(--cbp-toggle-color-circle-border-disabled-dark);
}

// override a browser default
&:focus-visible{
outline: none;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Meta } from '@storybook/addon-docs';

## Functional Requirements

* The Toggle component provides visual styling for a checkbox form control to appear as a toggle switch, including its various states, including hover, focus, disabled, and checked states.
* The Toggle component provides visual styling for a checkbox form control to appear as a toggle switch, including its various states, including hover, focus, disabled, for both checked & unchecked states.
* The Toggle component is a native HTML `input type="checkbox"` under the hood, which is slotted.
* The Toggle component places the label to the left of the control, unlike the Checkbox component.
* The Toggle component requires a label for an accessible name for form control.
Expand Down
Loading

0 comments on commit 9dcf790

Please sign in to comment.