1// Copyright (C) 2023 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15@import "theme"; 16 17// This checkbox element is expected to contain a checkbox type input followed 18// by an empty span element. 19// The input is completely hidden and an entirely new checkbox is drawn inside 20// the span element. This allows us to style it how we like, and also add some 21// fancy transitions. 22// The box of the checkbox is a fixed sized span element. The tick is also a 23// fixed sized rectange rotated 45 degrees with only the bottom and right 24// borders visible. 25// When unchecked, the tick size and border width is 0, so the tick is 26// completely invsible. When we transition to checked, the border size on the 27// bottom and right sides is immmdiately set to full width, and the tick morphs 28// into view first by expanding along the x axis first, then expanding up the 29// y-axis. This has the effect of making the tick look like it's being drawn 30// onto the page with a pen. 31// When transitioning from checked to unchecked, the animation plays in reverse, 32// and the border width is set to 0 right at the end in order to make the tick 33// completely invisible again. 34.pf-switch { 35 display: inline-block; 36 position: relative; // Turns this container into a positioned element 37 font-family: $pf-font; 38 font-size: inherit; 39 color: $pf-minimal-foreground; 40 user-select: none; 41 cursor: pointer; 42 padding-left: 32px + 6px; 43 44 // Hide the default checkbox 45 input { 46 position: absolute; 47 opacity: 0; 48 pointer-events: none; 49 } 50 51 // The span forms the "box" of the checkbox 52 span { 53 position: absolute; 54 left: 0; 55 top: 0; 56 bottom: 0; 57 margin-top: auto; 58 margin-bottom: auto; 59 height: 16px; 60 width: 32px; 61 border-radius: 8px; 62 transition: background $pf-anim-timing; 63 background: grey; 64 vertical-align: middle; 65 66 // The :after element forms the "tick" of the checkbox 67 &:after { 68 content: ""; 69 display: block; 70 position: absolute; 71 left: 2px; 72 top: 0; 73 bottom: 0; 74 margin-top: auto; 75 margin-bottom: auto; 76 width: 12px; 77 height: 12px; 78 background: $pf-primary-foreground; 79 box-sizing: border-box; 80 border-radius: 50%; 81 transition: left $pf-anim-timing; 82 } 83 } 84 85 input:checked + span { 86 background: $pf-primary-background; 87 } 88 89 input:checked + span:after { 90 left: 18px; 91 } 92 93 input:focus-visible + span { 94 @include focus; 95 } 96 97 &.pf-disabled { 98 cursor: not-allowed; 99 color: $pf-minimal-foreground-disabled; 100 101 span { 102 border-color: $pf-minimal-foreground-disabled; 103 background: $pf-minimal-foreground-disabled; 104 &:after { 105 border-color: $pf-minimal-foreground-disabled; 106 } 107 } 108 109 input:checked ~ span { 110 border-color: $pf-primary-background-disabled; 111 background: $pf-primary-background-disabled; 112 } 113 } 114} 115