_notched-outline-theme.scss 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. //
  2. // Copyright 2023 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 'sass:list';
  25. @use 'sass:meta';
  26. @use '@material/theme/custom-properties';
  27. @use '@material/theme/theme';
  28. @use '@material/shape/functions' as shape-functions;
  29. @use '@material/shape/mixins' as shape-mixins;
  30. @use '@material/floating-label/mixins' as floating-label-mixins;
  31. @use '@material/feature-targeting/feature-targeting';
  32. @use '@material/rtl/rtl';
  33. // Keep this in sync with constants.numbers.MIN_LEADING_STROKE_EDGE_POSITION
  34. $min-leading-stroke-edge-position: 12px !default;
  35. // The gap between the stroke end and floating label
  36. // Keep this in sync with constants.numbers.NOTCH_GUTTER_SIZE
  37. $notch-gutter-size: 4px !default;
  38. $border-width: 1px !default;
  39. $leading-width: 12px !default;
  40. $padding: 4px !default;
  41. // This variable keeps the before/after JS label centered in the notch when the font-size is changed.
  42. $label-adjust: 14% !default;
  43. /// Label box height when it is floating above for notched upgraded. This value is used to put the label vertically in
  44. /// the middle when it is notched.
  45. $label-box-height: 13.5px !default;
  46. /// Label adjust offset applied to floating label when it is notched. Since notch without upgraded has different font
  47. /// size we add additional offset value.
  48. $label-adjust-absolute: 2.5px !default;
  49. @mixin theme-styles($query: feature-targeting.all()) {
  50. $feat-structure: feature-targeting.create-target($query, structure);
  51. .mdc-notched-outline {
  52. &__leading,
  53. &__notch,
  54. &__trailing {
  55. @include feature-targeting.targets($feat-structure) {
  56. border-top: $border-width solid;
  57. border-bottom: $border-width solid;
  58. }
  59. }
  60. &__leading {
  61. @include feature-targeting.targets($feat-structure) {
  62. @include rtl.reflexive-property(border, $border-width solid, none);
  63. width: $leading-width;
  64. }
  65. }
  66. &__trailing {
  67. @include feature-targeting.targets($feat-structure) {
  68. @include rtl.reflexive-property(border, none, $border-width solid);
  69. }
  70. }
  71. &__notch {
  72. @include feature-targeting.targets($feat-structure) {
  73. max-width: calc(100% - #{$leading-width} * 2);
  74. }
  75. }
  76. }
  77. }
  78. @mixin color($color, $query: feature-targeting.all()) {
  79. $feat-color: feature-targeting.create-target($query, color);
  80. .mdc-notched-outline__leading,
  81. .mdc-notched-outline__notch,
  82. .mdc-notched-outline__trailing {
  83. @include feature-targeting.targets($feat-color) {
  84. @include theme.property(border-color, $color);
  85. }
  86. }
  87. }
  88. @mixin stroke-width($width, $query: feature-targeting.all()) {
  89. $feat-structure: feature-targeting.create-target($query, structure);
  90. .mdc-notched-outline__leading,
  91. .mdc-notched-outline__notch,
  92. .mdc-notched-outline__trailing {
  93. @include feature-targeting.targets($feat-structure) {
  94. @include theme.property(border-width, $width);
  95. }
  96. }
  97. }
  98. ///
  99. /// Adds top offset to compensate for border width box size when it is notched.
  100. /// Use this when floating label is aligned to center to prevent label jump on focus.
  101. /// @param {Number} $stroke-width Stroke width of notched outline that needs to be offset.
  102. ///
  103. @mixin notch-offset($stroke-width, $query: feature-targeting.all()) {
  104. $feat-structure: feature-targeting.create-target($query, structure);
  105. .mdc-notched-outline--notched .mdc-notched-outline__notch {
  106. @include feature-targeting.targets($feat-structure) {
  107. padding-top: $stroke-width;
  108. }
  109. }
  110. }
  111. @mixin shape-radius(
  112. $radius,
  113. $rtl-reflexive: false,
  114. $component-height: null,
  115. $query: feature-targeting.all()
  116. ) {
  117. $feat-structure: feature-targeting.create-target($query, structure);
  118. // Resolve the radius relative to the notched outline component's height. The
  119. // component should provide its current height from its density. The resolved
  120. // radius allows percentage radii to be converted to pixels.
  121. $resolved-radius: shape-functions.resolve-radius(
  122. $radius,
  123. $component-height: $component-height
  124. );
  125. // Grab the top-left radius. We'll need it to adjust the leading for the
  126. // label notch if the resulting radius shape is larger than the default
  127. // leading.
  128. $top-left-radius: list.nth(
  129. shape-functions.unpack-radius($resolved-radius),
  130. 1
  131. );
  132. $top-left-is-custom-prop: custom-properties.is-custom-prop($top-left-radius);
  133. $top-left-radius-px: $top-left-radius;
  134. @if ($top-left-is-custom-prop) {
  135. $top-left-radius-px: custom-properties.get-fallback($top-left-radius);
  136. }
  137. .mdc-notched-outline__leading {
  138. // mask the leading to apply the top-left and bottom-left corners
  139. @include shape-mixins.radius(
  140. shape-functions.mask-radius($radius, 1 0 0 1),
  141. $rtl-reflexive: true,
  142. $component-height: $component-height,
  143. $query: $query
  144. );
  145. @include feature-targeting.targets($feat-structure) {
  146. @if ($top-left-radius-px > $leading-width) {
  147. // If the radius is bigger than the default leading width, we need to
  148. // increase the leading width
  149. width: $top-left-radius-px;
  150. @if ($top-left-is-custom-prop) {
  151. // The radius may be a custom property, in which case the above width
  152. // is the IE11 fallback value.
  153. /* @alternate */
  154. }
  155. }
  156. @if ($top-left-is-custom-prop) {
  157. // If the top-left radius is dynamic, the width of the leading is
  158. // the max of whichever is larger: the default leading width or the
  159. // value of the custom property.
  160. $var: custom-properties.create-var($top-left-radius);
  161. // Interpolation is a workaround for sass/sass#3259.
  162. @supports (top: max(#{0%})) {
  163. width: max(#{$leading-width}, #{$var});
  164. }
  165. }
  166. }
  167. }
  168. // Similar to above, adjust the max-width of the notch if we adjusted the
  169. // leading's width.
  170. .mdc-notched-outline__notch {
  171. @include feature-targeting.targets($feat-structure) {
  172. @if ($top-left-radius-px > $leading-width) {
  173. max-width: calc(100% - #{$top-left-radius-px} * 2);
  174. @if ($top-left-is-custom-prop) {
  175. /* @alternate */
  176. }
  177. }
  178. @if ($top-left-is-custom-prop) {
  179. $var: custom-properties.create-var($top-left-radius);
  180. // Interpolation is a workaround for sass/sass#3259.
  181. @supports (top: max(#{0%})) {
  182. max-width: calc(100% - max(#{$leading-width}, #{$var}) * 2);
  183. }
  184. }
  185. }
  186. }
  187. .mdc-notched-outline__trailing {
  188. // mask the leading to apply the top-right and bottom-right corners
  189. @include shape-mixins.radius(
  190. shape-functions.mask-radius($radius, 0 1 1 0),
  191. $rtl-reflexive: true,
  192. $component-height: $component-height,
  193. $query: $query
  194. );
  195. }
  196. }
  197. @mixin floating-label-float-position(
  198. $positionY,
  199. $positionX: 0%,
  200. $scale: 0.75,
  201. $query: feature-targeting.all()
  202. ) {
  203. $feat-structure: feature-targeting.create-target($query, structure);
  204. @include floating-label-mixins.float-position(
  205. $positionY + $label-adjust,
  206. $positionX,
  207. 1,
  208. $query: $query
  209. );
  210. .mdc-floating-label--float-above {
  211. @include feature-targeting.targets($feat-structure) {
  212. font-size: ($scale * 1rem);
  213. }
  214. }
  215. // Two selectors to ensure we select the appropriate class when applied from this component or a parent component.
  216. &.mdc-notched-outline--upgraded,
  217. .mdc-notched-outline--upgraded {
  218. @include floating-label-mixins.float-position(
  219. $positionY,
  220. $positionX,
  221. $scale,
  222. $query: $query
  223. );
  224. .mdc-floating-label--float-above {
  225. @include feature-targeting.targets($feat-structure) {
  226. font-size: 1rem;
  227. }
  228. }
  229. }
  230. }
  231. ///
  232. /// Sets floating label position in notched outline when label is afloat.
  233. ///
  234. /// @param {Number} $positionY Absolute Y-axis position in `px`.
  235. /// @param {Number} $positionX Absolute X-axis position in `px`. Defaults to `0`.
  236. /// @param {Number} $scale Defaults to `.75`.
  237. ///
  238. /// @todo Replace mixin `mdc-notched-outline-floating-label-float-position` with this mixin when floating label is
  239. /// center aligned in all the places.
  240. ///
  241. @mixin floating-label-float-position-absolute(
  242. $positionY,
  243. $positionX: 0,
  244. $scale: 0.75,
  245. $query: feature-targeting.all()
  246. ) {
  247. $feat-structure: feature-targeting.create-target($query, structure);
  248. $float-positionY: if(
  249. meta.type-of($positionY) == 'calculation',
  250. calc($positionY + $label-adjust-absolute),
  251. $positionY + $label-adjust-absolute
  252. );
  253. @include floating-label-mixins.float-position(
  254. $float-positionY,
  255. $positionX,
  256. $scale: 1,
  257. $query: $query
  258. );
  259. .mdc-floating-label--float-above {
  260. @include feature-targeting.targets($feat-structure) {
  261. font-size: ($scale * 1rem);
  262. }
  263. }
  264. // Two selectors to ensure we select the appropriate class when applied from this component or a parent component.
  265. &.mdc-notched-outline--upgraded,
  266. .mdc-notched-outline--upgraded {
  267. @include floating-label-mixins.float-position(
  268. $positionY,
  269. $positionX,
  270. $scale,
  271. $query: $query
  272. );
  273. .mdc-floating-label--float-above {
  274. @include feature-targeting.targets($feat-structure) {
  275. font-size: 1rem;
  276. }
  277. }
  278. }
  279. }
  280. ///
  281. /// Sets the max-width for the notch
  282. ///
  283. /// @param {Number} $max-width Max-width for the notch
  284. ///
  285. @mixin notch-max-width($max-width, $query: feature-targeting.all()) {
  286. $feat-structure: feature-targeting.create-target($query, structure);
  287. :not(.mdc-notched-outline--notched) .mdc-notched-outline__notch {
  288. @include feature-targeting.targets($feat-structure) {
  289. max-width: $max-width;
  290. }
  291. }
  292. }