_switch.scss 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. //
  2. // Copyright 2021 Google Inc.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. // stylelint-disable selector-class-pattern --
  23. // Selector '.mdc-*' should only be used in this project.
  24. @use '@material/animation/animation';
  25. @use '@material/dom/dom';
  26. @use '@material/elevation/elevation';
  27. @use '@material/ripple/ripple-theme';
  28. @use '@material/ripple/ripple';
  29. @use '@material/focus-ring/focus-ring';
  30. @use '@material/rtl/rtl';
  31. @use '@material/theme/gss';
  32. $animation-duration: 75ms;
  33. $icon-exit-duration: 0.4 * $animation-duration;
  34. $icon-enter-duration: $animation-duration - $icon-exit-duration;
  35. $ripple-target: '.mdc-switch__ripple';
  36. @mixin static-styles() {
  37. @include static-styles-without-ripple();
  38. .mdc-switch {
  39. @include ripple.common; // COPYBARA_COMMENT_THIS_LINE
  40. @include ripple.surface($ripple-target: $ripple-target);
  41. @include ripple.radius-unbounded($ripple-target: $ripple-target);
  42. .mdc-switch__focus-ring-wrapper {
  43. width: 100%;
  44. position: absolute;
  45. // IE11 hacks
  46. top: 50%;
  47. @include rtl.ignore-next-line();
  48. left: 50%;
  49. @include rtl.ignore-next-line();
  50. transform: translate(-50%, -50%);
  51. // end IE11 hacks
  52. }
  53. @include ripple-theme.focus {
  54. .mdc-switch__focus-ring {
  55. @include focus-ring.focus-ring();
  56. }
  57. }
  58. }
  59. }
  60. @mixin static-styles-without-ripple() {
  61. @include elevation.overlay-common; // COPYBARA_COMMENT_THIS_LINE
  62. .mdc-switch {
  63. @include root;
  64. &:disabled {
  65. @include disabled;
  66. }
  67. }
  68. .mdc-switch__track {
  69. @include track;
  70. @include track-off;
  71. .mdc-switch--selected & {
  72. @include track-on;
  73. }
  74. }
  75. .mdc-switch__handle-track {
  76. @include handle-track;
  77. @include handle-track-off;
  78. .mdc-switch--selected & {
  79. @include handle-track-on;
  80. }
  81. }
  82. .mdc-switch__handle {
  83. @include handle;
  84. }
  85. .mdc-switch__shadow {
  86. @include shadow;
  87. }
  88. .mdc-elevation-overlay {
  89. @include overlay;
  90. }
  91. .mdc-switch__ripple {
  92. @include ripple;
  93. .mdc-switch:disabled & {
  94. @include ripple-disabled;
  95. }
  96. }
  97. .mdc-switch__icons {
  98. @include icons;
  99. }
  100. .mdc-switch__icon {
  101. @include icon;
  102. @include icon-hidden;
  103. }
  104. .mdc-switch--selected .mdc-switch__icon--on,
  105. .mdc-switch--unselected .mdc-switch__icon--off {
  106. @include icon-visible;
  107. }
  108. }
  109. @mixin root() {
  110. align-items: center;
  111. background: none;
  112. border: none;
  113. cursor: pointer;
  114. display: inline-flex;
  115. flex-shrink: 0; // Stop from collapsing in flex containers
  116. margin: 0;
  117. outline: none;
  118. overflow: visible;
  119. padding: 0;
  120. position: relative;
  121. &[hidden] {
  122. display: none;
  123. }
  124. }
  125. @mixin disabled() {
  126. cursor: default;
  127. pointer-events: none;
  128. }
  129. @mixin track() {
  130. overflow: hidden;
  131. position: relative;
  132. width: 100%;
  133. &::before,
  134. &::after {
  135. border: 1px solid transparent; // high contrast mode
  136. border-radius: inherit;
  137. box-sizing: border-box;
  138. content: '';
  139. height: 100%;
  140. @include gss.annotate($noflip: true);
  141. left: 0;
  142. position: absolute;
  143. width: 100%;
  144. // Added for Firefox 94 which broke transparent borders in Windows HCM.
  145. // See https://bugzilla.mozilla.org/show_bug.cgi?id=1740924.
  146. @include dom.forced-colors-mode($exclude-ie11: true) {
  147. border-color: currentColor;
  148. }
  149. }
  150. }
  151. @mixin track-on() {
  152. &::before {
  153. transition: animation.exit-temporary(transform, $animation-duration);
  154. transform: translateX(100%);
  155. @include rtl.rtl {
  156. transform: translateX(-100%);
  157. }
  158. }
  159. &::after {
  160. transition: animation.enter(transform, $animation-duration);
  161. transform: translateX(0);
  162. }
  163. }
  164. @mixin track-off() {
  165. &::before {
  166. transition: animation.enter(transform, $animation-duration);
  167. transform: translateX(0);
  168. }
  169. &::after {
  170. transition: animation.exit-temporary(transform, $animation-duration);
  171. transform: translateX(-100%);
  172. @include rtl.rtl {
  173. transform: translateX(100%);
  174. }
  175. }
  176. }
  177. @mixin handle-track() {
  178. height: 100%;
  179. // The handle track is used to move the handle across the width of the switch
  180. // and may overflow the bounds of the component. It should not be used for
  181. // pointer events.
  182. pointer-events: none;
  183. position: absolute;
  184. top: 0; // Needed for IE11
  185. transition: animation.standard(transform, $animation-duration);
  186. // IE11 needs explicit left/right
  187. @include rtl.reflexive(left, 0, right, auto);
  188. }
  189. @mixin handle-track-on() {
  190. transform: translateX(100%);
  191. @include rtl.rtl {
  192. transform: translateX(-100%);
  193. }
  194. }
  195. @mixin handle-track-off() {
  196. transform: translateX(0);
  197. }
  198. @mixin handle() {
  199. display: flex;
  200. pointer-events: auto;
  201. position: absolute;
  202. top: 50%;
  203. transform: translateY(-50%);
  204. // IE11 needs explicit left/right
  205. @include rtl.reflexive(left, 0, right, auto);
  206. &::before,
  207. &::after {
  208. border: 1px solid transparent; // high contrast mode
  209. border-radius: inherit;
  210. box-sizing: border-box;
  211. content: '';
  212. width: 100%;
  213. height: 100%;
  214. @include gss.annotate($noflip: true);
  215. left: 0;
  216. position: absolute;
  217. top: 0; // IE11 fix
  218. transition: animation.standard(background-color, $animation-duration),
  219. animation.standard(border-color, $animation-duration);
  220. // Move the handle background colors beneath the shadow overlay color,
  221. // rather than move the overlay on top of the handle with a positive
  222. // z-index, which would require moving all other content on top of the
  223. // overlay with an even greater z-index.
  224. z-index: -1;
  225. // Added for Firefox 94 which broke transparent borders in Windows HCM.
  226. // See https://bugzilla.mozilla.org/show_bug.cgi?id=1740924.
  227. @include dom.forced-colors-mode($exclude-ie11: true) {
  228. border-color: currentColor;
  229. }
  230. }
  231. }
  232. @mixin shadow() {
  233. border-radius: inherit;
  234. bottom: 0;
  235. @include gss.annotate($noflip: true);
  236. left: 0;
  237. position: absolute;
  238. @include gss.annotate($noflip: true);
  239. right: 0;
  240. top: 0;
  241. }
  242. @mixin overlay() {
  243. bottom: 0;
  244. @include gss.annotate($noflip: true);
  245. left: 0;
  246. @include gss.annotate($noflip: true);
  247. right: 0;
  248. top: 0;
  249. }
  250. @mixin ripple() {
  251. @include gss.annotate($noflip: true);
  252. left: 50%;
  253. position: absolute;
  254. top: 50%;
  255. @include rtl.ignore-next-line();
  256. transform: translate(-50%, -50%);
  257. // Move ripple beneath shadow overlay and handle background colors (see
  258. // handle() mixin for explanation).
  259. z-index: -1;
  260. }
  261. @mixin ripple-disabled {
  262. display: none;
  263. }
  264. @mixin icons() {
  265. height: 100%;
  266. position: relative;
  267. width: 100%;
  268. z-index: 1;
  269. }
  270. @mixin icon() {
  271. bottom: 0;
  272. @include gss.annotate($noflip: true);
  273. left: 0;
  274. // IE11 needs top/right/bottom/left + margin instead of translate(-50%, -50%)
  275. // because of SVG centering issues
  276. margin: auto;
  277. position: absolute;
  278. @include gss.annotate($noflip: true);
  279. right: 0;
  280. top: 0;
  281. }
  282. @mixin icon-hidden() {
  283. opacity: 0;
  284. transition: animation.exit-permanent(opacity, $icon-exit-duration);
  285. }
  286. @mixin icon-visible() {
  287. opacity: 1;
  288. transition: animation.enter(
  289. opacity,
  290. $icon-enter-duration,
  291. $delay: $icon-exit-duration
  292. );
  293. }