• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-checkbox {
35  $tick-anim-time-width: 100ms;
36  $tick-anim-time-height: 150ms;
37  $tick-anim-time: $tick-anim-time-width + $tick-anim-time-height;
38  $tick-easing: linear;
39
40  $box-size: 18px;
41  $tick-height: 9px;
42  $tick-width: 5px;
43  $box-label-padding: 6px;
44
45  display: inline-block;
46  position: relative; // Turns this container into a positioned element
47  font-family: $pf-font;
48  font-size: inherit;
49  color: $pf-minimal-foreground;
50  user-select: none;
51  cursor: pointer;
52  padding-left: $box-size + $box-label-padding;
53
54  // Hide the default checkbox
55  input {
56    position: absolute;
57    opacity: 0;
58    pointer-events: none;
59  }
60
61  // The span forms the "box" of the checkbox
62  span {
63    position: absolute;
64    left: 0;
65    top: 0;
66    bottom: 0;
67    margin-top: auto;
68    margin-bottom: auto;
69    height: $box-size;
70    width: $box-size;
71    border-radius: $pf-border-radius;
72    border: solid 2px $pf-minimal-foreground;
73    transition: background $pf-anim-timing;
74    background: none;
75
76    // The :after element forms the "tick" of the checkbox
77    &:after {
78      content: "";
79      display: block;
80      position: absolute;
81      bottom: 7.5px;
82      left: 1px;
83      width: 0px;
84      height: 0px;
85      border-color: $pf-primary-foreground;
86      border-style: solid;
87      border-width: 0;
88      transform-origin: 0% 100%; // Put the origin at the short edge of the tick
89      transform: rotate(45deg);
90      transition: height $tick-anim-time-height $tick-easing,
91        width $tick-anim-time-width $tick-anim-time-height $tick-easing,
92        border-width 0ms $tick-anim-time;
93    }
94  }
95
96  &:hover {
97    span {
98      background: $pf-minimal-background-hover;
99    }
100  }
101
102  input:checked + span {
103    border-color: $pf-primary-background;
104    background: $pf-primary-background;
105  }
106
107  input:focus-visible + span {
108    @include focus;
109  }
110
111  input:checked + span:after {
112    width: $tick-width;
113    height: $tick-height;
114    border-width: 0 2px 2px 0;
115    transition: width $tick-anim-time-height $tick-easing,
116      height $tick-anim-time-height $tick-anim-time-width $tick-easing,
117      border-width 0ms;
118  }
119
120  &.pf-disabled {
121    cursor: not-allowed;
122    color: $pf-minimal-foreground-disabled;
123
124    span {
125      border-color: $pf-minimal-foreground-disabled;
126      background: none;
127      &:after {
128        border-color: $pf-primary-foreground;
129      }
130    }
131
132    input:checked ~ span {
133      border-color: $pf-primary-background-disabled;
134      background: $pf-primary-background-disabled;
135    }
136  }
137}
138