xref: /aosp_15_r20/external/perfetto/ui/src/assets/widgets/checkbox.scss (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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:
91        height $tick-anim-time-height $tick-easing,
92        width $tick-anim-time-width $tick-anim-time-height $tick-easing,
93        border-width 0ms $tick-anim-time;
94    }
95  }
96
97  &:hover {
98    span {
99      background: $pf-minimal-background-hover;
100    }
101  }
102
103  input:checked + span {
104    border-color: $pf-primary-background;
105    background: $pf-primary-background;
106  }
107
108  input:focus-visible + span {
109    @include focus;
110  }
111
112  input:checked + span:after {
113    width: $tick-width;
114    height: $tick-height;
115    border-width: 0 2px 2px 0;
116    transition:
117      width $tick-anim-time-height $tick-easing,
118      height $tick-anim-time-height $tick-anim-time-width $tick-easing,
119      border-width 0ms;
120  }
121
122  &.pf-disabled {
123    cursor: not-allowed;
124    color: $pf-minimal-foreground-disabled;
125
126    span {
127      border-color: $pf-minimal-foreground-disabled;
128      background: none;
129      &:after {
130        border-color: $pf-primary-foreground;
131      }
132    }
133
134    input:checked ~ span {
135      border-color: $pf-primary-background-disabled;
136      background: $pf-primary-background-disabled;
137    }
138  }
139}
140