From 7a0f3ffad982d6d5476e5c86f57ef9fd48f43e33 Mon Sep 17 00:00:00 2001 From: aveline Date: Wed, 9 Feb 2022 09:43:09 -0800 Subject: [PATCH 1/6] Create polaris-v8-public-api.scss --- .../guides/polaris-v8-public-api.scss | 2162 +++++++++++++++++ 1 file changed, 2162 insertions(+) create mode 100644 documentation/guides/polaris-v8-public-api.scss diff --git a/documentation/guides/polaris-v8-public-api.scss b/documentation/guides/polaris-v8-public-api.scss new file mode 100644 index 00000000000..8535a471cf1 --- /dev/null +++ b/documentation/guides/polaris-v8-public-api.scss @@ -0,0 +1,2162 @@ +// Deprecated public scss API + +/** + * Polaris Tokens: colors.color-map + */ + +$polaris-colors: ( + 'purple': ( + 'text': rgb(80, 73, 90), + 'darker': rgb(35, 0, 81), + 'dark': rgb(80, 36, 143), + 'base': rgb(156, 106, 222), + 'light': rgb(227, 208, 255), + 'lighter': rgb(246, 240, 253), + ), + 'indigo': ( + 'text': rgb(62, 65, 85), + 'darker': rgb(0, 6, 57), + 'dark': rgb(32, 46, 120), + 'base': rgb(92, 106, 196), + 'light': rgb(179, 188, 245), + 'lighter': rgb(244, 245, 250), + ), + 'blue': ( + 'text': rgb(62, 78, 87), + 'darker': rgb(0, 20, 41), + 'dark': rgb(8, 78, 138), + 'base': rgb(0, 111, 187), + 'light': rgb(180, 225, 250), + 'lighter': rgb(235, 245, 250), + ), + 'teal': ( + 'text': rgb(64, 83, 82), + 'darker': rgb(0, 49, 53), + 'dark': rgb(0, 132, 142), + 'base': rgb(71, 193, 191), + 'light': rgb(183, 236, 236), + 'lighter': rgb(224, 245, 245), + ), + 'green': ( + 'text': rgb(65, 79, 62), + 'darker': rgb(23, 54, 48), + 'dark': rgb(16, 128, 67), + 'base': rgb(80, 184, 60), + 'light': rgb(187, 229, 179), + 'lighter': rgb(227, 241, 223), + ), + 'yellow': ( + 'text': rgb(89, 81, 48), + 'darker': rgb(87, 59, 0), + 'dark': rgb(138, 97, 22), + 'base': rgb(238, 194, 0), + 'light': rgb(255, 234, 138), + 'lighter': rgb(252, 241, 205), + ), + 'orange': ( + 'text': rgb(89, 68, 48), + 'darker': rgb(74, 21, 4), + 'dark': rgb(192, 87, 23), + 'base': rgb(244, 147, 66), + 'light': rgb(255, 197, 139), + 'lighter': rgb(252, 235, 219), + ), + 'red': ( + 'text': rgb(88, 60, 53), + 'darker': rgb(51, 1, 1), + 'dark': rgb(191, 7, 17), + 'base': rgb(222, 54, 24), + 'light': rgb(254, 173, 154), + 'lighter': rgb(251, 234, 229), + ), + 'ink': ( + 'base': rgb(33, 43, 54), + 'light': rgb(69, 79, 91), + 'lighter': rgb(99, 115, 129), + 'lightest': rgb(145, 158, 171), + ), + 'sky': ( + 'dark': rgb(196, 205, 213), + 'base': rgb(223, 227, 232), + 'light': rgb(244, 246, 248), + 'lighter': rgb(249, 250, 251), + ), + 'black': ( + 'base': rgb(0, 0, 0), + ), + 'white': ( + 'base': rgb(255, 255, 255), + ), +); + +/** + * Polaris Tokens: color-filters.color-map + */ + +$polaris-color-filters: ( + 'purple': ( + 'text': brightness(0) saturate(100%) invert(29%) sepia(3%) saturate(2843%) + hue-rotate(223deg) brightness(92%) contrast(86%), + 'darker': brightness(0) saturate(100%) invert(8%) sepia(38%) saturate(6605%) + hue-rotate(265deg) brightness(99%) contrast(124%), + 'dark': brightness(0) saturate(100%) invert(12%) sepia(46%) saturate(4964%) + hue-rotate(258deg) brightness(101%) contrast(93%), + 'base': brightness(0) saturate(100%) invert(49%) sepia(77%) saturate(1864%) + hue-rotate(229deg) brightness(91%) contrast(91%), + 'light': brightness(0) saturate(100%) invert(82%) sepia(13%) saturate(1535%) + hue-rotate(203deg) brightness(103%) contrast(104%), + 'lighter': brightness(0) saturate(100%) invert(84%) sepia(15%) + saturate(135%) hue-rotate(219deg) brightness(110%) contrast(98%), + ), + 'indigo': ( + 'text': brightness(0) saturate(100%) invert(24%) sepia(11%) saturate(1035%) + hue-rotate(195deg) brightness(97%) contrast(94%), + 'darker': brightness(0) saturate(100%) invert(5%) sepia(81%) saturate(5060%) + hue-rotate(229deg) brightness(72%) contrast(111%), + 'dark': brightness(0) saturate(100%) invert(17%) sepia(28%) saturate(4409%) + hue-rotate(218deg) brightness(87%) contrast(98%), + 'base': brightness(0) saturate(100%) invert(45%) sepia(17%) saturate(1966%) + hue-rotate(194deg) brightness(88%) contrast(84%), + 'light': brightness(0) saturate(100%) invert(82%) sepia(37%) saturate(4261%) + hue-rotate(194deg) brightness(111%) contrast(92%), + 'lighter': brightness(0) saturate(100%) invert(100%) sepia(25%) + saturate(1090%) hue-rotate(179deg) brightness(100%) contrast(96%), + ), + 'blue': ( + 'text': brightness(0) saturate(100%) invert(27%) sepia(13%) saturate(709%) + hue-rotate(158deg) brightness(96%) contrast(89%), + 'darker': brightness(0) saturate(100%) invert(5%) sepia(33%) saturate(5606%) + hue-rotate(195deg) brightness(97%) contrast(102%), + 'dark': brightness(0) saturate(100%) invert(22%) sepia(70%) saturate(1308%) + hue-rotate(182deg) brightness(94%) contrast(101%), + 'base': brightness(0) saturate(100%) invert(19%) sepia(98%) saturate(2885%) + hue-rotate(190deg) brightness(99%) contrast(101%), + 'light': brightness(0) saturate(100%) invert(80%) sepia(7%) saturate(1832%) + hue-rotate(178deg) brightness(108%) contrast(96%), + 'lighter': brightness(0) saturate(100%) invert(100%) sepia(94%) + saturate(686%) hue-rotate(175deg) brightness(103%) contrast(96%), + ), + 'teal': ( + 'text': brightness(0) saturate(100%) invert(31%) sepia(11%) saturate(665%) + hue-rotate(128deg) brightness(94%) contrast(93%), + 'darker': brightness(0) saturate(100%) invert(15%) sepia(23%) + saturate(2237%) hue-rotate(141deg) brightness(96%) contrast(104%), + 'dark': brightness(0) saturate(100%) invert(28%) sepia(83%) saturate(3919%) + hue-rotate(168deg) brightness(93%) contrast(101%), + 'base': brightness(0) saturate(100%) invert(72%) sepia(8%) saturate(2838%) + hue-rotate(130deg) brightness(92%) contrast(87%), + 'light': brightness(0) saturate(100%) invert(95%) sepia(12%) saturate(683%) + hue-rotate(122deg) brightness(97%) contrast(91%), + 'lighter': brightness(0) saturate(100%) invert(87%) sepia(5%) + saturate(1124%) hue-rotate(173deg) brightness(114%) contrast(92%), + ), + 'green': ( + 'text': brightness(0) saturate(100%) invert(30%) sepia(8%) saturate(1010%) + hue-rotate(63deg) brightness(91%) contrast(91%), + 'darker': brightness(0) saturate(100%) invert(15%) sepia(32%) saturate(727%) + hue-rotate(118deg) brightness(93%) contrast(91%), + 'dark': brightness(0) saturate(100%) invert(18%) sepia(75%) saturate(6649%) + hue-rotate(155deg) brightness(97%) contrast(87%), + 'base': brightness(0) saturate(100%) invert(56%) sepia(10%) saturate(2637%) + hue-rotate(64deg) brightness(106%) contrast(91%), + 'light': brightness(0) saturate(100%) invert(93%) sepia(15%) saturate(599%) + hue-rotate(52deg) brightness(93%) contrast(93%), + 'lighter': brightness(0) saturate(100%) invert(92%) sepia(51%) + saturate(187%) hue-rotate(46deg) brightness(108%) contrast(89%), + ), + 'yellow': ( + 'text': brightness(0) saturate(100%) invert(28%) sepia(42%) saturate(413%) + hue-rotate(11deg) brightness(97%) contrast(91%), + 'darker': brightness(0) saturate(100%) invert(19%) sepia(75%) saturate(981%) + hue-rotate(17deg) brightness(103%) contrast(103%), + 'dark': brightness(0) saturate(100%) invert(37%) sepia(51%) saturate(709%) + hue-rotate(0deg) brightness(93%) contrast(89%), + 'base': brightness(0) saturate(100%) invert(65%) sepia(91%) saturate(530%) + hue-rotate(5deg) brightness(100%) contrast(100%), + 'light': brightness(0) saturate(100%) invert(77%) sepia(72%) saturate(246%) + hue-rotate(355deg) brightness(103%) contrast(107%), + 'lighter': brightness(0) saturate(100%) invert(88%) sepia(27%) + saturate(234%) hue-rotate(357deg) brightness(103%) contrast(98%), + ), + 'orange': ( + 'text': brightness(0) saturate(100%) invert(23%) sepia(18%) saturate(1092%) + hue-rotate(348deg) brightness(99%) contrast(84%), + 'darker': brightness(0) saturate(100%) invert(9%) sepia(83%) saturate(1926%) + hue-rotate(356deg) brightness(98%) contrast(99%), + 'dark': brightness(0) saturate(100%) invert(29%) sepia(94%) saturate(1431%) + hue-rotate(5deg) brightness(96%) contrast(82%), + 'base': brightness(0) saturate(100%) invert(54%) sepia(86%) saturate(416%) + hue-rotate(340deg) brightness(105%) contrast(91%), + 'light': brightness(0) saturate(100%) invert(77%) sepia(39%) saturate(483%) + hue-rotate(335deg) brightness(101%) contrast(103%), + 'lighter': brightness(0) saturate(100%) invert(93%) sepia(11%) + saturate(918%) hue-rotate(312deg) brightness(107%) contrast(98%), + ), + 'red': ( + 'text': brightness(0) saturate(100%) invert(22%) sepia(9%) saturate(2068%) + hue-rotate(325deg) brightness(92%) contrast(83%), + 'darker': brightness(0) saturate(100%) invert(12%) sepia(100%) + saturate(5699%) hue-rotate(353deg) brightness(75%) contrast(101%), + 'dark': brightness(0) saturate(100%) invert(12%) sepia(100%) saturate(5699%) + hue-rotate(353deg) brightness(75%) contrast(101%), + 'base': brightness(0) saturate(100%) invert(28%) sepia(67%) saturate(3622%) + hue-rotate(353deg) brightness(89%) contrast(95%), + 'light': brightness(0) saturate(100%) invert(80%) sepia(9%) saturate(2561%) + hue-rotate(313deg) brightness(101%) contrast(99%), + 'lighter': brightness(0) saturate(100%) invert(89%) sepia(21%) + saturate(137%) hue-rotate(324deg) brightness(102%) contrast(97%), + ), + 'ink': ( + 'base': brightness(0) saturate(100%) invert(10%) sepia(10%) saturate(2259%) + hue-rotate(171deg) brightness(99%) contrast(84%), + 'light': brightness(0) saturate(100%) invert(32%) sepia(9%) saturate(1069%) + hue-rotate(173deg) brightness(83%) contrast(84%), + 'lighter': brightness(0) saturate(100%) invert(45%) sepia(8%) saturate(825%) + hue-rotate(166deg) brightness(95%) contrast(90%), + 'lightest': brightness(0) saturate(100%) invert(68%) sepia(18%) + saturate(246%) hue-rotate(169deg) brightness(88%) contrast(90%), + ), + 'sky': ( + 'dark': brightness(0) saturate(100%) invert(86%) sepia(4%) saturate(502%) + hue-rotate(167deg) brightness(96%) contrast(91%), + 'base': brightness(0) saturate(100%) invert(100%) sepia(95%) saturate(336%) + hue-rotate(175deg) brightness(97%) contrast(87%), + 'light': brightness(0) saturate(100%) invert(99%) sepia(12%) saturate(467%) + hue-rotate(174deg) brightness(99%) contrast(96%), + 'lighter': brightness(0) saturate(100%) invert(99%) sepia(1%) saturate(159%) + hue-rotate(170deg) brightness(99%) contrast(99%), + ), + 'black': ( + 'base': brightness(0) saturate(100%), + ), + 'white': ( + 'base': brightness(0) saturate(100%) invert(100%), + ), + 'icon': ( + 'base': brightness(0) saturate(100%) invert(36%) sepia(13%) saturate(137%) + hue-rotate(169deg) brightness(95%) contrast(87%), + ), + 'action': ( + 'base': brightness(0) saturate(100%) invert(20%) sepia(59%) saturate(5557%) + hue-rotate(162deg) brightness(95%) contrast(101%), + ), +); + +/** + * Polaris Tokens: duration.map + */ + +$polaris-duration-map: ( + 'duration-none': ( + 0, + ), + 'duration-fast': ( + 100ms, + ), + 'duration-base': ( + 200ms, + ), + 'duration-slow': ( + 300ms, + ), + 'duration-slower': ( + 400ms, + ), + 'duration-slowest': ( + 500ms, + ), +); + +/** + * Polaris Tokens: spacing.spacing-map + */ + +$polaris-spacing: ( + 'none': 0, + 'extra-tight': 4px, + 'tight': 8px, + 'base-tight': 12px, + 'base': 16px, + 'loose': 20px, + 'extra-loose': 32px, +); + +/** + * FOUNDATION: accessibility + */ + +@mixin high-contrast-outline($border-width: border-width()) { + outline: $border-width solid transparent; + @content; +} + +@mixin high-contrast-border($border-width: border-width()) { + border: $border-width solid transparent; + @content; +} + +/** + * FOUNDATION: utilities + */ + +$default-browser-font-size: 16px; +$base-font-size: 16px; + +/// Returns the value in rem for a given pixel value. +/// @param {Number} $value - The pixel value to be converted. +/// @return {Number} The converted value in rem. + +@function rem($value) { + $unit: unit($value); + + @if $value == 0 { + @return 0; + } @else if $unit == 'rem' { + @return $value; + } @else if $unit == 'px' { + @return $value / $base-font-size * 1rem; + } @else if $unit == 'em' { + @return $unit / 1em * 1rem; + } @else { + @error 'Value must be in px, em, or rem.'; + } +} + +/// Returns the value in pixels for a given rem value. +/// @param {Number} $value - The rem value to be converted. +/// @return {Number} The converted value in pixels. + +@function px($value) { + $unit: unit($value); + + @if $value == 0 { + @return 0; + } @else if $unit == 'px' { + @return $value; + } @else if $unit == 'em' { + @return ($value / 1em) * $base-font-size; + } @else if $unit == 'rem' { + @return ($value / 1rem) * $base-font-size; + } @else { + @error 'Value must be in rem, em, or px.'; + } +} + +/// Returns the value in ems for a given pixel value. Note that this +/// only works for elements that have had no font-size changes. +/// @param {Number} $value - The pixel value to be converted. +/// @return {Number} The converted value in ems. + +@function em($value) { + $unit: unit($value); + + @if $value == 0 { + @return 0; + } @else if $unit == 'em' { + @return $value; + } @else if $unit == 'rem' { + @return $value / 1rem * 1em * ($base-font-size / $default-browser-font-size); + } @else if $unit == 'px' { + @return $value / $default-browser-font-size * 1em; + } @else { + @error 'Value must be in px, rem, or em.'; + } +} + +/// Returns the list of available names in a given map. +/// @param {Map} $map - The map of data to list the names from. +/// @param {Number} $map - The level of depth to get names from. +/// @return {String} The list of names in the map. + +@function available-names($map, $level: 1) { + @if type-of($map) != 'map' { + @return null; + } + + $output: ''; + $newline: '\A '; + + @if $level == 1 { + @each $key, $value in $map { + $output: $output + + '#{$newline}- #{$key} #{available-names($value, $level + 1)}'; + } + } @else { + $output: '('; + $i: 1; + + @each $key, $value in $map { + $sep: if($i < length($map), ', ', ''); + $output: $output + '#{$key}#{$sep}#{available-names($value, $level + 1)}'; + $i: $i + 1; + } + + $output: $output + ')'; + } + + @return $output; +} + +// Merge multiple maps into one. +// @param {Map} $map - Initial default map. +// @param {ArgList} $maps - Other maps to merge. +// @return {Map} The final merged map. +@function map-extend($map, $maps...) { + @for $i from 1 through length($maps) { + @each $key, $value in nth($maps, $i) { + $map: map-merge( + $map, + ( + $key: $value, + ) + ); + + @if type-of($value) == map and type-of(map-get($map, $key)) == map { + $value: map-extend(map-get($map, $key), $value); + } + } + } + + @return $map; +} + +/** + * FOUNDATION: colors + */ + +/// +/// Color data +/// +/// Shopify color palette, extended specifically for polaris-react. +/// +/// @type map +$color-palette-data: $polaris-colors; + +// Add state colors to the palette +$color-palette-data: map-extend( + $color-palette-data, + ( + 'state': ( + 'hover': rgba(223, 227, 232, 0.3), + 'focused': rgba(223, 227, 232, 0.3), + 'active': rgba(179, 188, 245, 0.1), + 'selected': rgba(179, 188, 245, 0.15), + 'subdued': rgba(249, 250, 251, 1), + 'disabled': rgba(249, 250, 251, 1), + 'hover-destructive': rgba(251, 234, 229, 0.4), + 'focused-destructive': rgba(251, 234, 229, 0.4), + 'active-destructive': rgba(220, 56, 37, 0.03), + ), + ) +); + +/// Returns the color value for a given color name and group. +/// +/// @param {String} $hue - The color’s hue. +/// @param {String} $value - The darkness/lightness of the color. Defaults to +/// base. +/// @param {Color} $for-background - The background color on which this color +/// will appear. Applies a multiply filter to ensure appropriate contrast. +/// @return {Color} The color value. + +@function color($hue, $value: base, $for-background: null) { + $fetched-color: map-get(map-get($color-palette-data, $hue), $value); + + @if map-has-key($color-palette-data, $fetched-color) { + $fetched-color: map-get( + map-get($color-palette-data, $fetched-color), + $value + ); + } + + @if $for-background { + $fetched-color: color-multiply($fetched-color, $for-background); + } + + @if type-of($fetched-color) == color { + @return $fetched-color; + } @else { + @error "Color `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `color('yellow')`.\a BAD: `color(yellow)`.\a\a Available options: #{available-names($color-palette-data)}"; + } +} + +/// Darkens the foreground color by the background color. This is the same as +/// the "multiply" filter in graphics apps. +/// +/// @param {Color} $foreground - The color to darken. +/// @param {Color} $background - The background to base darkening on. +/// @return {Color} The modified color. + +@function color-multiply($foreground, $background: null) { + @if $background { + $background: rgb(255, 255, 255); + } + + $red: red($background) * red($foreground) / 255; + $green: green($background) * green($foreground) / 255; + $blue: blue($background) * blue($foreground) / 255; + + $opacity: opacity($foreground); + $background-opacity: opacity($background); + + // calculate opacity + $bm-red: $red * $opacity + red($background) * $background-opacity * + (1 - $opacity); + $bm-green: $green * $opacity + green($background) * $background-opacity * + (1 - $opacity); + $bm-blue: $blue * $opacity + blue($background) * $background-opacity * + (1 - $opacity); + + @return rgb($bm-red, $bm-green, $bm-blue); +} + +/// +/// Color palette for Windows high-contrast mode +/// See https://bit.ly/2vN9aGO +/// +/// @type map + +$ms-high-contrast-color-data: ( + 'text': windowText, + 'disabled-text': grayText, + 'selected-text': highlightText, + 'selected-text-background': highlight, + 'button-text': buttonText, + 'button-text-background': buttonFace, + 'background': window, +); + +/// +/// Returns the color value for Windows high contrast mode +/// +/// @param {String} $color - The name of the high-contrast color. +/// @return {Color} The color value. + +@function ms-high-contrast-color($color) { + $fetched-color: map-get($ms-high-contrast-color-data, $color); + + @if $fetched-color { + @return $fetched-color; + } @else { + @error "Color `#{$color}` not found.\a Make sure argument is a string.\a GOOD: ms-high-contrast-color('selected-text').\a BAD: ms-high-contrast-color(selected-text).\a\a Available options: #{available-names($ms-high-contrast-color-data)}"; + } +} + +/** + * FOUNDATION: filters + */ + +/// +/// Color filter data +/// +/// Shopify color filter palette, extended specifically for polaris-react. +/// +/// @type map +$color-filter-palette-data: $polaris-color-filters; + +/// Returns the filter list for a given color name and group. +/// +/// @param {String} $hue - The color’s hue. +/// @param {String} $value - The darkness/lightness of the color. Defaults to +/// base. +/// @return {List} The filter list. + +@function filter($hue, $value: base) { + $fetched-color: map-get(map-get($color-filter-palette-data, $hue), $value); + + @if map-has-key($color-filter-palette-data, $fetched-color) { + $fetched-color: map-get( + map-get($color-filter-palette-data, $fetched-color), + $value + ); + } + + @if type-of($fetched-color) == list { + @return $fetched-color; + } @else { + @error "Filter `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `filter('yellow')`.\a BAD: `filter(yellow)`.\a\a Available options: #{available-names($color-filter-palette-data)}"; + } +} + +/** + * FOUNDATION: spacing + */ + +$spacing-data: $polaris-spacing; + +/// Returns the spacing value for a given variant. +/// +/// @param {String} $variant - The key for the given variant. +/// @return {Number} The spacing for the variant. + +@function spacing($variant: base) { + $fetched-value: map-get($spacing-data, $variant); + + @if type-of($fetched-value) == number { + @return rem($fetched-value); + } @else { + @error 'Spacing variant `#{$variant}` not found. Available variants: #{available-names($spacing-data)}'; + } +} + +/** + * FOUNDATION: border-width + */ + +$border-width-data: ( + base: rem(1px), + thick: rem(2px), + thicker: rem(3px), +); + +/// Returns the width of the specified border type. +/// @param {String} $variant [base] - The border variant key. +/// @return {Number} The width for the border. + +@function border-width($variant: base) { + $fetched-value: map-get($border-width-data, $variant); + + @if type-of($fetched-value) == number { + @return $fetched-value; + } @else { + @error 'Border width variant `#{$variant}` not found. Available variants: #{available-names($border-width-data)}'; + } +} + +/** + * FOUNDATION: borders + */ + +$borders-data: ( + base: border-width() solid var(--p-border-subdued), + dark: border-width() solid var(--p-border), + transparent: border-width() solid transparent, + divider: border-width() solid var(--p-divider), +); + +/// Returns the default border. +/// @param {String} $variant [base] - The border variant key. +/// @return {List} The border value. + +@function border($variant: base) { + $fetched-value: map-get($borders-data, $variant); + + @if $fetched-value { + @return $fetched-value; + } @else { + @error 'Border variant `#{$variant}` not found. Available variants: #{available-names($borders-data)}'; + } +} + +/** + * FOUNDATION: border-radius + */ + +$border-radius-data: ( + base: 3px, + large: 6px, +); + +/// Returns the border radius of the specified size. +/// @param {String} $size - The border radius’s size. +/// @return {Number} The border radius value. + +@function border-radius($size: base) { + @return map-get($border-radius-data, $size); +} + +/** + * FOUNDATION: duration + */ + +$duration-data: $polaris-duration-map; + +/// Returns the duration value for a given variant. +/// +/// @param {String} $variant - The key for the given variant. +/// @return {Number} The duration for the variant (in milliseconds). + +@function duration($variant: base) { + $interpolated-value: 'duration-' + $variant; + $fetched-value: nth(map-get($duration-data, $interpolated-value), 1); + + @if type-of($fetched-value) == number { + @return $fetched-value; + } @else { + @error 'Duration variant `#{$interpolated-value}` not found. Available variants: #{available-names($duration-data)}'; + } +} + +/** + * FOUNDATION: easing + */ + +$easing-data: ( + base: cubic-bezier(0.25, 0.1, 0.25, 1), + in: cubic-bezier(0.36, 0, 1, 1), + out: cubic-bezier(0, 0, 0.42, 1), + excite: cubic-bezier(0.18, 0.67, 0.6, 1.22), + overshoot: cubic-bezier(0.07, 0.28, 0.32, 1.22), + anticipate: cubic-bezier(0.38, -0.4, 0.88, 0.65), +); + +/// Returns the timing-function value for a given variant. +/// +/// @param {String} $variant - The key for the given variant. +/// @return {String} The cubic-bezier function (string) for the variant. + +@function easing($variant: base) { + $fetched-value: map-get($easing-data, $variant); + + @if type-of($fetched-value) == string { + @return $fetched-value; + } @else { + @error 'Easing variant `#{$variant}` not found. Available variants: #{available-names($easing-data)}'; + } +} + +/** + * FOUNDATION: layout + */ + +$navigation-width: 240px !default; + +//// +/// Layout +/// @group foundation/layout +//// + +$layout-width-data: ( + primary: ( + min: rem(480px), + max: rem(662px), + ), + secondary: ( + min: rem(240px), + max: rem(320px), + ), + one-half-width: ( + base: rem(450px), + ), + one-third-width: ( + base: rem(240px), + ), + nav: ( + base: rem($navigation-width), + ), + page-with-nav: ( + base: rem(769px), + ), + page-content: ( + not-condensed: rem(680px), + partially-condensed: rem(450px), + ), + inner-spacing: ( + base: spacing(), + ), + outer-spacing: ( + min: spacing(loose), + max: spacing(extra-loose), + ), +); + +/// Returns the widths of the specified column. +/// @param {String} $name - The column name. +/// @return {Number} The width for the column. + +@function layout-width($name, $value: base) { + $fetched-value: map-get(map-get($layout-width-data, $name), $value); + + @if type-of($fetched-value) { + @return $fetched-value; + } @else { + @error 'Column `#{$name} - #{$value}` not found. Available columns: #{available-names($layout-width-data)}'; + } +} + +$dismiss-icon-size: 32px; + +@function top-bar-height() { + @return rem(56px); +} + +@function mobile-nav-width() { + @return calc(100vw - #{rem($dismiss-icon-size) + spacing() * 2}); +} + +@function nav-min-window-corrected() { + @return rem(769px); +} + +/** + * FOUNDATION: shadows + */ + +// Shadows are intentionally very subtle gradiations. +$shadows-data: ( + faint: ( + 0 1px 0 0 rgba(22, 29, 37, 0.05), + ), + base: ( + 0 0 0 1px rgba(63, 63, 68, 0.05), + 0 1px 3px 0 rgba(63, 63, 68, 0.15), + ), + deep: ( + 0 0 0 1px rgba(6, 44, 82, 0.1), + 0 2px 16px rgba(33, 43, 54, 0.08), + ), + layer: ( + 0 31px 41px 0 rgba(32, 42, 53, 0.2), + 0 2px 16px 0 rgba(32, 42, 54, 0.08), + ), + transparent: 0 0 0 0 transparent, +); + +/// Returns the shadow for the specified depth +/// @param {String} $depth [base] - The shadow’s depth. +/// @return {List} The shadow value. + +@function shadow($depth: base) { + $fetched-value: map-get($shadows-data, $depth); + + @if type-of($fetched-value) == list { + @return $fetched-value; + } @else { + @error 'Shadow variant `#{$depth}` not found. Available variants: #{available-names($shadows-data)}'; + } +} + +/** + * FOUNDATION: typography + */ + +$typography-condensed: em(640px); + +$font-family-data: ( + base: #{-apple-system, + 'BlinkMacSystemFont', + 'San Francisco', + 'Segoe UI', + 'Roboto', + 'Helvetica Neue', + sans-serif}, + monospace: #{ui-monospace, + SFMono-Regular, + SF Mono, + Consolas, + Liberation Mono, + Menlo, + monospace}, +); + +$line-height-data: ( + caption: ( + base: rem(20px), + large-screen: rem(16px), + ), + heading: ( + base: rem(24px), + ), + subheading: ( + base: rem(16px), + ), + input: ( + base: rem(24px), + ), + body: ( + base: rem(20px), + ), + button: ( + base: rem(16px), + ), + button-large: ( + base: rem(20px), + ), + display-x-large: ( + base: rem(36px), + large-screen: rem(44px), + ), + display-large: ( + base: rem(28px), + large-screen: rem(32px), + ), + display-medium: ( + base: rem(28px), + large-screen: rem(32px), + ), + display-small: ( + base: rem(24px), + large-screen: rem(28px), + ), +); + +$font-size-data: ( + caption: ( + base: rem(13px), + large-screen: rem(12px), + ), + heading: ( + base: rem(17px), + large-screen: rem(16px), + ), + subheading: ( + base: rem(13px), + large-screen: rem(12px), + ), + input: ( + base: rem(16px), + large-screen: rem(14px), + ), + body: ( + base: rem(15px), + large-screen: rem(14px), + ), + button: ( + base: rem(15px), + large-screen: rem(14px), + ), + button-large: ( + base: rem(17px), + large-screen: rem(16px), + ), + display-x-large: ( + base: rem(27px), + large-screen: rem(42px), + ), + display-large: ( + base: rem(24px), + large-screen: rem(28px), + ), + display-medium: ( + base: rem(21px), + large-screen: rem(26px), + ), + display-small: ( + base: rem(16px), + large-screen: rem(20px), + ), +); + +/// Returns the font stack for a given family. +/// +/// @param {String} $family - The key for the given family. +/// @return {Number} The font stack for the family. + +@function font-family($family: base) { + $fetched-value: map-get($font-family-data, $family); + + @if $fetched-value { + @return $fetched-value; + } @else { + @error 'Font family `#{$family}` not found. Available font families: #{available-names($font-family-data)}'; + } +} + +/// Returns the line height for a given text style and variant. +/// +/// @param {String} $style - The font style. +/// @param {String} $variant [base] - The variant on the font-size. +/// @return {Number} The line-height for the text-style. + +@function line-height($style, $variant: base) { + $fetched-line-height: map-get(map-get($line-height-data, $style), $variant); + + @if type-of($fetched-line-height) { + @return $fetched-line-height; + } @else { + @error 'Line height `#{$style} - #{$variant}` not found. Available line heights: #{available-names($line-height-data)}'; + } +} + +/// Returns the font size for a given text style and variant. +/// +/// @param {String} $style - The font style. +/// @param {String} $variant [base] - The variant on the font-size. +/// @return {Number} The font-size for the text-style. + +@function font-size($style, $variant: base) { + $fetched-font-size: map-get(map-get($font-size-data, $style), $variant); + + @if type-of($fetched-font-size) { + @return $fetched-font-size; + } @else { + @error 'Font size `#{$style} - #{$variant}` not found. Available font sizes: #{available-names($line-height-data)}'; + } +} + +/** + * FOUNDATION: z-index + */ + +$global-elements: ( + content: 100, + overlay: 400, +); + +// We're matching that here and relatively stacking other fixed components. +$fixed-element-stacking-order: ( + global-ribbon: 510, + loading-bar: 511, + top-bar: 512, + context-bar: 513, + small-screen-loading-bar: 514, + nav-backdrop: 515, + nav: 516, + skip-to-content: 517, + backdrop: 518, + modal: 519, + toast: 520, + dev-ui: 521, +); + +/// Returns the z-index of the specified element. +/// @param {String} $element - The key for the element. +/// @param {Map} $context - The map in which to search for the element. +/// @return {Number} The z-index for the element. + +@function z-index($element, $context: $global-elements) { + $index: map-get($context, $element); + + @if $index { + @return $index; + } @else { + @error 'z-index `#{$element}` in `#{$context}` not found.'; + } +} + +/** + * FOUNDATION: focus-ring + */ + +/// Sets the focus ring for an interactive element +/// @param {String} $size - The size of the border radius on the focus ring. +/// @param {String} $style - Focus ring state. +/// @param {Number} $border-width - The border width of your element in rems. +/// + +@mixin focus-ring($size: 'base', $border-width: 0, $style: 'base') { + $stroke: rem(2px); + // calc does not like performing addition with a unitless number (`0`, NOT `0px`) + // This is a problem because `rem(0px)` returns `0`, not `0px`. + // Make sure that we can handle unitless zeros by not trying to do math with them + $offset: if( + $border-width == 0, + rem(1px), + calc(#{$border-width} + #{rem(1px)}) + ); + $border-radius: if( + $size == 'wide', + var(--p-border-radius-wide), + var(--p-border-radius-base) + ); + $negative-offset: calc(-1 * #{$offset}); + + @if $style == 'base' { + position: relative; + + &::after { + content: ''; + position: absolute; + z-index: 1; + top: $negative-offset; + right: $negative-offset; + bottom: $negative-offset; + left: $negative-offset; + display: block; + pointer-events: none; + box-shadow: 0 0 0 $negative-offset var(--p-focused); + transition: box-shadow duration(fast) var(--p-ease); + border-radius: calc(#{$border-radius} + #{rem(1px)}); + } + } @else if $style == 'focused' { + &::after { + box-shadow: 0 0 0 $stroke var(--p-focused); + @include high-contrast-outline; + } + } +} + +@mixin no-focus-ring { + &::after { + content: none; + } +} + +/** + * SHARED: accessibility + */ + +/// Used to hide an element visually, but keeping it accessible for +/// accessibility tools. + +/// styles referenced from GOV.UK design system +/// https://github.com/h5bp/main.css/issues/12#issuecomment-451965809 +@mixin visually-hidden { + // Need to make sure we override any existing styles. + // stylelint-disable declaration-no-important + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + clip-path: inset(50%) !important; + border: 0 !important; + white-space: nowrap !important; + // stylelint-enable declaration-no-important +} + +/** + * SHARED: breakpoints + */ + +$page-max-width: layout-width(primary, max) + layout-width(secondary, max) + + layout-width(inner-spacing); +$frame-with-nav-max-width: layout-width(nav) + $page-max-width; + +$stacked-content: em( + layout-width(primary, min) + layout-width(secondary, min) + + layout-width(inner-spacing) +); +$not-condensed-content: em(layout-width(page-content, not-condensed)); +$partially-condensed-content: em( + layout-width(page-content, partially-condensed) +); + +$not-condensed-outer-spacing: em(2 * layout-width(outer-spacing, max)); +$partially-condensed-outer-spacing: em(2 * layout-width(outer-spacing, min)); + +$not-condensed-min-page: $not-condensed-content + $not-condensed-outer-spacing; +$partially-condensed-min-page: $partially-condensed-content + + $partially-condensed-outer-spacing; + +$nav-size: em(layout-width(nav)); +$nav-min-window: em(layout-width(page-with-nav)); + +@function breakpoint($value, $adjustment: 0) { + $adjusted-value: em($adjustment); + + // Reduces chances to have a style void + // between two media queries + // See https://github.com/sass-mq/sass-mq/issues/6 + @if $adjustment == -1px { + $adjusted-value: -0.01em; + } @else if $adjustment == 1px { + $adjusted-value: 0.01em; + } + + @return em($value) + $adjusted-value; +} + +@mixin page-content-breakpoint-before($size) { + $size: breakpoint($size); + + @if $size < $partially-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{min($nav-min-window, $size)}), + (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size}) { + @content; + } + } + + @media (max-width: #{$size}) { + @content; + } + } @else if $size < $not-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{min($nav-min-window, $size + $partially-condensed-outer-spacing)}), + (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { + @content; + } + } + + @media (max-width: #{$size + $partially-condensed-outer-spacing}) { + @content; + } + } @else { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{min($nav-min-window, $size + $partially-condensed-outer-spacing)}), + (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { + @content; + } + } + + @media (max-width: #{$size + $not-condensed-outer-spacing}) { + @content; + } + } +} + +@mixin page-content-breakpoint-after($size) { + $size: breakpoint($size); + + @if $size < $partially-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{$nav-min-window}) and (min-width: #{$size}), + (min-width: #{$nav-size + $size}) { + @content; + } + } + + @media (min-width: #{$size}) { + @content; + } + } @else if $size < $not-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{$nav-min-window}) and (min-width: #{$size + $partially-condensed-outer-spacing}), + (min-width: #{$nav-size + $size + $partially-condensed-outer-spacing}) { + @content; + } + } + + @media (min-width: #{$size + $partially-condensed-outer-spacing}) { + @content; + } + } @else { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{$nav-min-window}) and (min-width: #{$size + $not-condensed-outer-spacing}), + (min-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { + @content; + } + } + + @media (min-width: #{$size + $not-condensed-outer-spacing}) { + @content; + } + } +} + +@mixin breakpoint-after($breakpoint, $inclusive: true) { + @media (min-width: #{breakpoint($breakpoint, if($inclusive, 0, 1px))}) { + @content; + } +} + +@mixin breakpoint-before($breakpoint, $inclusive: true) { + @media (max-width: #{breakpoint($breakpoint, if($inclusive, 0, -1px))}) { + @content; + } +} + +@mixin frame-with-nav-when-not-max-width() { + @include breakpoint-before($frame-with-nav-max-width) { + @content; + } +} + +@mixin page-when-not-max-width() { + @include breakpoint-before($page-max-width) { + @content; + } +} + +@mixin page-content-when-layout-stacked() { + @include page-content-breakpoint-before($stacked-content) { + @content; + } +} + +@mixin page-content-when-layout-not-stacked() { + @include page-content-breakpoint-after($stacked-content) { + @content; + } +} + +@mixin page-content-when-partially-condensed() { + @include page-content-breakpoint-before($not-condensed-content) { + @content; + } +} + +@mixin page-content-when-not-partially-condensed() { + @include page-content-breakpoint-after($not-condensed-content) { + @content; + } +} + +@mixin page-content-when-fully-condensed() { + @include page-content-breakpoint-before($partially-condensed-content) { + @content; + } +} + +@mixin page-content-when-not-fully-condensed() { + @include page-content-breakpoint-after($partially-condensed-content) { + @content; + } +} + +@mixin frame-when-nav-displayed() { + @include breakpoint-after(layout-width(page-with-nav)) { + @content; + } +} + +@mixin frame-when-nav-hidden() { + @include breakpoint-before(layout-width(page-with-nav), false) { + @content; + } +} + +/** + * SHARED: buttons + */ + +@mixin high-contrast-button-outline($outline: 2px dotted) { + @media (-ms-high-contrast: active) { + outline: $outline; + } +} + +@mixin button-base { + $min-height: control-height(); + $vertical-padding: ($min-height - line-height(body) - rem(2px)) / 2; + + @include recolor-icon(var(--p-icon)); + @include focus-ring($border-width: border-width('base')); + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + min-height: $min-height; + min-width: $min-height; + margin: 0; + padding: $vertical-padding spacing(); + background: var(--p-surface); + box-shadow: var(--p-button-drop-shadow); + border-radius: var(--p-border-radius-base); + color: var(--p-text); + border: 1px solid var(--p-border-neutral-subdued); + border-top-color: var(--p-border-subdued); + border-bottom-color: var(--p-border-shadow-subdued); + line-height: 1; + text-align: center; + cursor: pointer; + user-select: none; + text-decoration: none; + -webkit-tap-highlight-color: transparent; + + &:hover { + background: var(--p-action-secondary-hovered); + @include high-contrast-outline; + } + + &:focus { + box-shadow: var(--p-button-drop-shadow); + outline: 0; + + @include focus-ring($style: 'focused'); + } + + &:active { + background: var(--p-action-secondary-pressed); + box-shadow: var(--p-button-drop-shadow); + + &::after { + border: none; + box-shadow: none; + } + } + + &.pressed { + background: var(--p-action-secondary-depressed); + box-shadow: var(--p-button-pressed-inner-shadow); + color: var(--p-text-on-primary); + border-color: var(--p-border-depressed); + @include recolor-icon(currentColor); + } + + @media (-ms-high-contrast: active) { + border: 1px solid ms-high-contrast-color('text'); + } +} + +@mixin base-button-disabled { + @include recolor-icon(var(--p-icon-disabled)); + transition: none; + box-shadow: none; + border-color: var(--p-border-disabled); + background: var(--p-surface-disabled); + color: var(--p-text-disabled); +} + +@mixin button-filled() { + @include focus-ring($border-width: 0); + background: var(--p-button-color); + border-width: 0; + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + color: var(--p-button-text); + + &:hover { + background: var(--p-button-color-hover); + border-color: transparent; + color: var(--p-button-text); + } + + &:focus { + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + } + + &:active { + background: var(--p-button-color-active); + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + } + + &.pressed { + color: var(--p-button-text); + background: var(--p-button-color-depressed); + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + + &:hover, + &:focus { + background: var(--p-button-color-depressed); + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + } + } +} + +@mixin button-outline($outline-color, $background-color: transparent) { + background: transparent; + border: border-width() solid var(--p-border); + box-shadow: none; + color: var(--p-text); + @include focus-ring($border-width: border-width('base')); + + &:hover { + border: border-width() solid var(--p-border); + box-shadow: none; + background: var(--p-surface-hovered); + } + + &:focus { + border: border-width() solid var(--p-border); + box-shadow: none; + @include focus-ring($style: 'focused'); + } + + &:active { + border: border-width() solid var(--p-border); + box-shadow: none; + background: var(--p-surface-pressed); + + &::after { + box-shadow: none; + } + } + + &.pressed { + background: var(--p-action-secondary-pressed); + border: border-width() solid var(--p-border); + box-shadow: none; + color: var(--p-button-text); + } + + &.disabled { + border: border-width('base') solid var(--p-border-disabled); + box-shadow: none; + background: transparent; + color: var(--p-text-disabled); + } + + &.destructive { + background: transparent; + border: border-width('base') solid var(--p-border-critical); + box-shadow: none; + color: var(--p-interactive-critical); + @include recolor-icon(var(--p-icon-critical)); + + &:hover { + border: border-width('base') solid var(--p-border-critical); + background: var(--p-surface-critical-subdued); + } + + &:focus { + border: border-width('base') solid var(--p-border-critical); + @include focus-ring($style: 'focused'); + } + + &:active { + border: border-width('base') solid var(--p-border-critical); + background: var(--p-surface-critical-subdued); + } + + &.disabled { + border: border-width('base') solid var(--p-border-critical-disabled); + background: transparent; + color: var(--p-interactive-critical-disabled); + } + + &.pressed { + background: var(--p-surface-critical-subdued); + box-shadow: border-width('base') solid var(--p-border-critical); + color: var(--p-interactive-critical); + } + } +} + +@mixin button-outline-disabled($outline-color) { + background: transparent; + box-shadow: none; +} + +@mixin button-full-width { + display: flex; + width: 100%; +} + +@mixin plain-button-backdrop { + padding: 2px 5px; + margin: -2px -5px; + background: var(--p-action-secondary-hovered); + border-radius: border-radius(); +} + +@mixin unstyled-button() { + appearance: none; + margin: 0; + padding: 0; + background: none; + border: none; + font-size: inherit; + line-height: inherit; + color: inherit; + cursor: pointer; + + &:focus { + outline: none; + } +} + +/** + * SHARED: controls + */ + +@function control-height() { + @return rem(36px); +} + +@function control-slim-height() { + @return rem(28px); +} + +@function control-vertical-padding() { + @return (control-height() - line-height(input) - rem(2px)) / 2; +} + +@function control-icon-transition() { + @return transform duration(fast) easing(in); +} + +@mixin control-backdrop($style: base) { + @if $style == base { + position: relative; + border: var(--p-control-border-width) solid var(--p-border); + background-color: var(--p-surface); + border-radius: var(--p-border-radius-base); + + &::before { + content: ''; + position: absolute; + top: calc(-1 * var(--p-control-border-width)); + right: calc(-1 * var(--p-control-border-width)); + bottom: calc(-1 * var(--p-control-border-width)); + left: calc(-1 * var(--p-control-border-width)); + border-radius: var(--p-border-radius-base); + background-color: var(--p-interactive); + opacity: 0; + transform: scale(0.25); + transition: opacity duration(fast) var(--p-ease), + transform duration(fast) var(--p-ease); + } + + &.hover, + &:hover { + cursor: pointer; + border-color: var(--p-border-hovered); + } + } @else if $style == active { + border-color: var(--p-interactive); + + &::before { + opacity: 1; + transform: scale(1); + @media (-ms-high-contrast: active) { + border: 2px solid ms-high-contrast-color('text'); + } + } + } @else if $style == disabled { + border-color: var(--p-border-disabled); + + &::before { + background-color: var(--p-action-secondary-disabled); + } + + &:hover { + cursor: default; + } + } @else if $style == error { + border-color: var(--p-border-critical); + background-color: var(--p-surface-critical); + + &.hover, + &:hover { + border-color: var(--p-border-critical); + } + + &::before { + background-color: var(--p-border-critical); + } + } +} + +/** + * SHARED: forms + */ + +@mixin unstyled-input { + margin: 0; + padding: 0; + width: 100%; + background-color: transparent; + appearance: none; + + &:focus { + outline: 0; + } + + &::-moz-focus-outer { + border: 0; + } +} + +@mixin range-track-selectors { + &::-ms-track { + @include high-contrast-outline; + @content; + } + + &::-moz-range-track { + @content; + } + + &::-webkit-slider-runnable-track { + @content; + } +} + +@mixin range-thumb-selectors { + &::-ms-thumb { + @content; + } + + &::-moz-range-thumb { + @content; + } + + &::-webkit-slider-thumb { + @content; + } +} + +/** + * SHARED: icons + */ + +@function icon-size() { + @return rem(20px); +} + +@mixin recolor-icon( + $fill-color: null, + $secondary-color: null, + $filter-color: null +) { + svg { + fill: $fill-color; + color: $secondary-color; + } + + img { + filter: $filter-color; + } +} + +@mixin color-icon($value, $hue: base) { + svg { + fill: color($value, $hue); + } + + img { + filter: filter($value, $hue); + } +} + +/** + * SHARED: layout + */ + +/// To be used on flex items. Resolves some common layout issues, such as +/// text truncation not respecting padding or breaking out of container. +/// https://css-tricks.com/flexbox-truncated-text/ + +@mixin layout-flex-fix { + min-width: 0; + max-width: 100%; +} + +/// Returns a safe-area-inset for iPhone X screen obtrusions. +/// +/// @param {String} $property - The property name i.e. padding-left. +/// @param {Space} $spacing - The spacing value to be added to the safe-area +/// value. i.e. spacing(). +/// @param {string} $area - The area where the inset is to be added. i.e. left +/// +/// If overriding an existing padding / margin that value should be used as +/// $spacing. +@mixin safe-area-for($property, $spacing, $area) { + // stylelint-disable-next-line scss/dimension-no-non-numeric-values + $spacing: if($spacing == 0, #{$spacing}px, $spacing); + #{$property}: #{$spacing}; + #{$property}: calc(#{$spacing} + constant(safe-area-inset-#{$area})); + #{$property}: calc(#{$spacing} + env(safe-area-inset-#{$area})); +} + +@mixin after-topbar-sheet { + @include breakpoint-after(450px) { + @content; + } +} + +/** + * SHARED: links + */ + +@mixin unstyled-link() { + color: inherit; + text-decoration: none; + + &:visited { + color: inherit; + } +} + +/** + * SHARED: lists + */ + +@mixin unstyled-list { + margin: 0; + padding: 0; + list-style: none; +} + +/** + * SHARED: page + */ + +$actions-vertical-spacing: spacing(tight); + +@mixin page-padding-not-fully-condensed { + padding: 0 spacing(loose); +} + +@mixin page-padding-not-partially-condensed { + padding: 0 spacing(extra-loose); +} + +@mixin page-layout { + margin: 0 auto; + padding: 0; + max-width: $page-max-width; + + @include page-content-when-not-fully-condensed { + @include page-padding-not-fully-condensed; + } + + @include page-content-when-not-partially-condensed { + @include page-padding-not-partially-condensed; + } +} + +@mixin page-content-layout { + margin: spacing(tight) 0; + + @include page-content-when-not-partially-condensed { + margin-top: spacing(loose); + } +} + +@mixin page-title-layout { + @include layout-flex-fix; + @include text-breakword; + display: flex; + align-items: baseline; + flex-wrap: wrap; + margin-top: -1 * spacing(tight); + margin-left: -1 * spacing(tight); + + > * { + margin-top: spacing(tight); + margin-left: spacing(tight); + } +} + +@mixin page-header-layout { + padding: spacing(); + + @include page-content-when-not-fully-condensed { + padding-left: 0; + padding-right: 0; + } + + @include page-content-when-not-partially-condensed { + padding: spacing(loose) 0; + } +} + +@mixin page-header-has-navigation { + padding-top: spacing(); +} + +@mixin page-header-without-navigation { + margin-top: unset; +} + +@mixin page-header-has-secondary-actions { + padding-top: spacing(); +} + +@mixin page-actions-layout { + display: flex; + justify-content: flex-start; + align-items: center; + margin-top: 2 * $actions-vertical-spacing; + + @include page-content-when-not-fully-condensed { + margin-top: $actions-vertical-spacing; + } +} + +/** + * SHARED: typography + */ + +$typography-condensed: em(640px); + +@mixin when-typography-not-condensed { + @include breakpoint-after($typography-condensed) { + @content; + } +} + +@mixin when-typography-condensed { + @include breakpoint-before($typography-condensed) { + @content; + } +} + +@mixin text-style-caption { + font-size: font-size(caption); + font-weight: 400; + line-height: line-height(caption); + + @include when-typography-not-condensed { + font-size: font-size(caption, large-screen); + line-height: line-height(caption, large-screen); + } +} + +@mixin text-style-heading { + font-size: font-size(heading); + font-weight: 600; + line-height: line-height(heading); + + @include when-typography-not-condensed { + font-size: font-size(heading, large-screen); + } +} + +@mixin text-style-subheading { + font-size: font-size(subheading); + font-weight: 600; + line-height: line-height(subheading); + text-transform: uppercase; + + @include when-typography-not-condensed { + font-size: font-size(subheading, large-screen); + } +} + +@mixin text-style-input { + font-size: font-size(input); + font-weight: 400; + line-height: line-height(input); + border: none; + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(input, large-screen); + } +} + +@mixin text-style-body { + font-size: font-size(body); + font-weight: 400; + line-height: line-height(body); + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(body, large-screen); + } +} + +@mixin text-style-button { + font-size: font-size(button); + font-weight: var(--p-button-font-weight); + line-height: line-height(button); + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(button, large-screen); + } +} + +@mixin text-style-button-large { + font-size: font-size(button-large); + font-weight: var(--p-button-font-weight); + line-height: line-height(button-large); + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(button-large, large-screen); + } +} + +@mixin text-style-display-x-large { + font-size: font-size(display-x-large); + font-weight: 600; + line-height: line-height(display-x-large); + + @include when-typography-not-condensed { + font-size: font-size(display-x-large, large-screen); + line-height: line-height(display-x-large, large-screen); + } +} + +@mixin text-style-display-large { + font-size: font-size(display-large); + font-weight: 600; + line-height: line-height(display-large); + + @include when-typography-not-condensed { + font-size: font-size(display-large, large-screen); + line-height: line-height(display-large, large-screen); + } +} + +@mixin text-style-display-medium { + font-size: font-size(display-medium); + font-weight: 400; + line-height: line-height(display-medium); + + @include when-typography-not-condensed { + font-size: font-size(display-medium, large-screen); + line-height: line-height(display-medium, large-screen); + } +} + +@mixin text-style-display-small { + font-size: font-size(display-small); + font-weight: 400; + line-height: line-height(display-small); + + @include when-typography-not-condensed { + font-size: font-size(display-small, large-screen); + line-height: line-height(display-small, large-screen); + } +} + +@mixin text-emphasis-subdued($for-background: null) { + color: var(--p-text-subdued); +} + +@mixin text-emphasis-strong { + font-weight: 600; +} + +@mixin text-emphasis-normal($for-background: null) { + font-weight: 400; + color: var(--p-text); +} + +@mixin text-breakword { + word-wrap: break-word; + word-break: break-word; + overflow-wrap: break-word; +} + +@mixin truncate { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +@mixin print-hidden { + @media print { + // stylelint-disable-next-line declaration-no-important + display: none !important; + } +} + +/** + * SHARED: skeleton + */ + +/// Used to create the shimmer effect of skeleton components +$skeleton-shimmer-duration: duration(slower) * 2; + +// Used by both Thumbnail and SkeletonThumbnail +$small-thumbnail-size: rem(40px); +$medium-thumbnail-size: rem(60px); +$large-thumbnail-size: rem(80px); + +$thumbnail-sizes: ( + small: $small-thumbnail-size, + medium: $medium-thumbnail-size, + large: $large-thumbnail-size, +); + +@function thumbnail-size($size) { + @return map-get($thumbnail-sizes, $size); +} + +@mixin skeleton-shimmer { + // This is a global animation, defined in /src/components/AppProvider/AppProvider.scss + // See that file for why this is referenced as a custom property instead of + // by name + animation: var(--polaris-animation-skeleton-shimmer) + $skeleton-shimmer-duration linear infinite alternate; + will-change: opacity; + + @media (prefers-reduced-motion) { + animation: none; + } +} + +@mixin skeleton-content { + position: relative; + + &::after { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: block; + background-color: var(--p-surface-neutral); + border-radius: border-radius(); + + @media screen and (-ms-high-contrast: active) { + background-color: ms-high-contrast-color('disabled-text'); + } + } +} + +@mixin skeleton-page-secondary-actions-layout { + margin-top: spacing(tight); + display: flex; + flex-direction: row-reverse; + justify-content: flex-end; + align-items: center; +} + +@mixin skeleton-page-header-layout { + padding-bottom: spacing(tight); +} + +/** + * SHARED: interaction-state + */ + +/// Sets the background-image and box-shadow for single or multiple given +/// interaction states. +/// +/// @param {argList} $interaction-states... - Accepts single or multiple +/// interactions states. +@mixin state($interaction-states...) { + $backgrounds: (); + + @each $state in $interaction-states { + $colors: color(state, $state); + $backgrounds: append( + $backgrounds, + linear-gradient($colors, $colors), + comma + ); + + @if $state == 'focused' { + box-shadow: inset rem(2px) 0 0 var(--p-focused); + } + + @if $state == 'focused-destructive' { + box-shadow: inset rem(2px) 0 0 var(--p-focused); + } + } + background-image: $backgrounds; +} + +@mixin list-selected-indicator($offset: spacing(tight)) { + content: ''; + background-color: var(--p-interactive); + position: absolute; + top: 0; + left: -1 * $offset; + height: 100%; + display: block; + width: border-width(thicker); + border-top-right-radius: var(--p-border-radius-base); + border-bottom-right-radius: var(--p-border-radius-base); +} + +/** + * SHARED: printing + */ + +@mixin when-printing { + @media print { + @content; + } +} + +@mixin when-not-printing { + @media not print { + @content; + } +} + +@mixin hidden-when-printing { + @include when-printing { + // We really, really don't want to see this thing when it is printed. + // stylelint-disable-next-line declaration-no-important + display: none !important; + } +} From ab2bbc92b92f0a127824faf2aea6a237541d228e Mon Sep 17 00:00:00 2001 From: aveline Date: Wed, 9 Feb 2022 09:48:06 -0800 Subject: [PATCH 2/6] Update documentation/guides/polaris-v8-public-api.scss Co-authored-by: Aaron Casanova <32409546+aaronccasanova@users.noreply.github.com> --- documentation/guides/polaris-v8-public-api.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/guides/polaris-v8-public-api.scss b/documentation/guides/polaris-v8-public-api.scss index 8535a471cf1..8044315c678 100644 --- a/documentation/guides/polaris-v8-public-api.scss +++ b/documentation/guides/polaris-v8-public-api.scss @@ -90,8 +90,8 @@ $polaris-colors: ( ); /** - * Polaris Tokens: color-filters.color-map - */ + * Polaris Tokens: color-filters.color-map + */ $polaris-color-filters: ( 'purple': ( From af4508a71a964b1a722d7113858470f04c03a64e Mon Sep 17 00:00:00 2001 From: aveline Date: Wed, 9 Feb 2022 09:57:49 -0800 Subject: [PATCH 3/6] Fix formatting --- .../guides/polaris-v8-public-api.scss | 3922 ++++++++--------- 1 file changed, 1960 insertions(+), 1962 deletions(-) diff --git a/documentation/guides/polaris-v8-public-api.scss b/documentation/guides/polaris-v8-public-api.scss index 8535a471cf1..34411e005c5 100644 --- a/documentation/guides/polaris-v8-public-api.scss +++ b/documentation/guides/polaris-v8-public-api.scss @@ -1,2162 +1,2160 @@ -// Deprecated public scss API - /** * Polaris Tokens: colors.color-map */ -$polaris-colors: ( - 'purple': ( - 'text': rgb(80, 73, 90), - 'darker': rgb(35, 0, 81), - 'dark': rgb(80, 36, 143), - 'base': rgb(156, 106, 222), - 'light': rgb(227, 208, 255), - 'lighter': rgb(246, 240, 253), - ), - 'indigo': ( - 'text': rgb(62, 65, 85), - 'darker': rgb(0, 6, 57), - 'dark': rgb(32, 46, 120), - 'base': rgb(92, 106, 196), - 'light': rgb(179, 188, 245), - 'lighter': rgb(244, 245, 250), - ), - 'blue': ( - 'text': rgb(62, 78, 87), - 'darker': rgb(0, 20, 41), - 'dark': rgb(8, 78, 138), - 'base': rgb(0, 111, 187), - 'light': rgb(180, 225, 250), - 'lighter': rgb(235, 245, 250), - ), - 'teal': ( - 'text': rgb(64, 83, 82), - 'darker': rgb(0, 49, 53), - 'dark': rgb(0, 132, 142), - 'base': rgb(71, 193, 191), - 'light': rgb(183, 236, 236), - 'lighter': rgb(224, 245, 245), - ), - 'green': ( - 'text': rgb(65, 79, 62), - 'darker': rgb(23, 54, 48), - 'dark': rgb(16, 128, 67), - 'base': rgb(80, 184, 60), - 'light': rgb(187, 229, 179), - 'lighter': rgb(227, 241, 223), - ), - 'yellow': ( - 'text': rgb(89, 81, 48), - 'darker': rgb(87, 59, 0), - 'dark': rgb(138, 97, 22), - 'base': rgb(238, 194, 0), - 'light': rgb(255, 234, 138), - 'lighter': rgb(252, 241, 205), - ), - 'orange': ( - 'text': rgb(89, 68, 48), - 'darker': rgb(74, 21, 4), - 'dark': rgb(192, 87, 23), - 'base': rgb(244, 147, 66), - 'light': rgb(255, 197, 139), - 'lighter': rgb(252, 235, 219), - ), - 'red': ( - 'text': rgb(88, 60, 53), - 'darker': rgb(51, 1, 1), - 'dark': rgb(191, 7, 17), - 'base': rgb(222, 54, 24), - 'light': rgb(254, 173, 154), - 'lighter': rgb(251, 234, 229), - ), - 'ink': ( - 'base': rgb(33, 43, 54), - 'light': rgb(69, 79, 91), - 'lighter': rgb(99, 115, 129), - 'lightest': rgb(145, 158, 171), - ), - 'sky': ( - 'dark': rgb(196, 205, 213), - 'base': rgb(223, 227, 232), - 'light': rgb(244, 246, 248), - 'lighter': rgb(249, 250, 251), - ), - 'black': ( - 'base': rgb(0, 0, 0), - ), - 'white': ( - 'base': rgb(255, 255, 255), - ), -); - -/** + $polaris-colors: ( + 'purple': ( + 'text': rgb(80, 73, 90), + 'darker': rgb(35, 0, 81), + 'dark': rgb(80, 36, 143), + 'base': rgb(156, 106, 222), + 'light': rgb(227, 208, 255), + 'lighter': rgb(246, 240, 253), + ), + 'indigo': ( + 'text': rgb(62, 65, 85), + 'darker': rgb(0, 6, 57), + 'dark': rgb(32, 46, 120), + 'base': rgb(92, 106, 196), + 'light': rgb(179, 188, 245), + 'lighter': rgb(244, 245, 250), + ), + 'blue': ( + 'text': rgb(62, 78, 87), + 'darker': rgb(0, 20, 41), + 'dark': rgb(8, 78, 138), + 'base': rgb(0, 111, 187), + 'light': rgb(180, 225, 250), + 'lighter': rgb(235, 245, 250), + ), + 'teal': ( + 'text': rgb(64, 83, 82), + 'darker': rgb(0, 49, 53), + 'dark': rgb(0, 132, 142), + 'base': rgb(71, 193, 191), + 'light': rgb(183, 236, 236), + 'lighter': rgb(224, 245, 245), + ), + 'green': ( + 'text': rgb(65, 79, 62), + 'darker': rgb(23, 54, 48), + 'dark': rgb(16, 128, 67), + 'base': rgb(80, 184, 60), + 'light': rgb(187, 229, 179), + 'lighter': rgb(227, 241, 223), + ), + 'yellow': ( + 'text': rgb(89, 81, 48), + 'darker': rgb(87, 59, 0), + 'dark': rgb(138, 97, 22), + 'base': rgb(238, 194, 0), + 'light': rgb(255, 234, 138), + 'lighter': rgb(252, 241, 205), + ), + 'orange': ( + 'text': rgb(89, 68, 48), + 'darker': rgb(74, 21, 4), + 'dark': rgb(192, 87, 23), + 'base': rgb(244, 147, 66), + 'light': rgb(255, 197, 139), + 'lighter': rgb(252, 235, 219), + ), + 'red': ( + 'text': rgb(88, 60, 53), + 'darker': rgb(51, 1, 1), + 'dark': rgb(191, 7, 17), + 'base': rgb(222, 54, 24), + 'light': rgb(254, 173, 154), + 'lighter': rgb(251, 234, 229), + ), + 'ink': ( + 'base': rgb(33, 43, 54), + 'light': rgb(69, 79, 91), + 'lighter': rgb(99, 115, 129), + 'lightest': rgb(145, 158, 171), + ), + 'sky': ( + 'dark': rgb(196, 205, 213), + 'base': rgb(223, 227, 232), + 'light': rgb(244, 246, 248), + 'lighter': rgb(249, 250, 251), + ), + 'black': ( + 'base': rgb(0, 0, 0), + ), + 'white': ( + 'base': rgb(255, 255, 255), + ), + ); + + /** * Polaris Tokens: color-filters.color-map */ - -$polaris-color-filters: ( - 'purple': ( - 'text': brightness(0) saturate(100%) invert(29%) sepia(3%) saturate(2843%) - hue-rotate(223deg) brightness(92%) contrast(86%), - 'darker': brightness(0) saturate(100%) invert(8%) sepia(38%) saturate(6605%) - hue-rotate(265deg) brightness(99%) contrast(124%), - 'dark': brightness(0) saturate(100%) invert(12%) sepia(46%) saturate(4964%) - hue-rotate(258deg) brightness(101%) contrast(93%), - 'base': brightness(0) saturate(100%) invert(49%) sepia(77%) saturate(1864%) - hue-rotate(229deg) brightness(91%) contrast(91%), - 'light': brightness(0) saturate(100%) invert(82%) sepia(13%) saturate(1535%) - hue-rotate(203deg) brightness(103%) contrast(104%), - 'lighter': brightness(0) saturate(100%) invert(84%) sepia(15%) - saturate(135%) hue-rotate(219deg) brightness(110%) contrast(98%), - ), - 'indigo': ( - 'text': brightness(0) saturate(100%) invert(24%) sepia(11%) saturate(1035%) - hue-rotate(195deg) brightness(97%) contrast(94%), - 'darker': brightness(0) saturate(100%) invert(5%) sepia(81%) saturate(5060%) - hue-rotate(229deg) brightness(72%) contrast(111%), - 'dark': brightness(0) saturate(100%) invert(17%) sepia(28%) saturate(4409%) - hue-rotate(218deg) brightness(87%) contrast(98%), - 'base': brightness(0) saturate(100%) invert(45%) sepia(17%) saturate(1966%) - hue-rotate(194deg) brightness(88%) contrast(84%), - 'light': brightness(0) saturate(100%) invert(82%) sepia(37%) saturate(4261%) - hue-rotate(194deg) brightness(111%) contrast(92%), - 'lighter': brightness(0) saturate(100%) invert(100%) sepia(25%) - saturate(1090%) hue-rotate(179deg) brightness(100%) contrast(96%), - ), - 'blue': ( - 'text': brightness(0) saturate(100%) invert(27%) sepia(13%) saturate(709%) - hue-rotate(158deg) brightness(96%) contrast(89%), - 'darker': brightness(0) saturate(100%) invert(5%) sepia(33%) saturate(5606%) - hue-rotate(195deg) brightness(97%) contrast(102%), - 'dark': brightness(0) saturate(100%) invert(22%) sepia(70%) saturate(1308%) - hue-rotate(182deg) brightness(94%) contrast(101%), - 'base': brightness(0) saturate(100%) invert(19%) sepia(98%) saturate(2885%) - hue-rotate(190deg) brightness(99%) contrast(101%), - 'light': brightness(0) saturate(100%) invert(80%) sepia(7%) saturate(1832%) - hue-rotate(178deg) brightness(108%) contrast(96%), - 'lighter': brightness(0) saturate(100%) invert(100%) sepia(94%) - saturate(686%) hue-rotate(175deg) brightness(103%) contrast(96%), - ), - 'teal': ( - 'text': brightness(0) saturate(100%) invert(31%) sepia(11%) saturate(665%) - hue-rotate(128deg) brightness(94%) contrast(93%), - 'darker': brightness(0) saturate(100%) invert(15%) sepia(23%) - saturate(2237%) hue-rotate(141deg) brightness(96%) contrast(104%), - 'dark': brightness(0) saturate(100%) invert(28%) sepia(83%) saturate(3919%) - hue-rotate(168deg) brightness(93%) contrast(101%), - 'base': brightness(0) saturate(100%) invert(72%) sepia(8%) saturate(2838%) - hue-rotate(130deg) brightness(92%) contrast(87%), - 'light': brightness(0) saturate(100%) invert(95%) sepia(12%) saturate(683%) - hue-rotate(122deg) brightness(97%) contrast(91%), - 'lighter': brightness(0) saturate(100%) invert(87%) sepia(5%) - saturate(1124%) hue-rotate(173deg) brightness(114%) contrast(92%), - ), - 'green': ( - 'text': brightness(0) saturate(100%) invert(30%) sepia(8%) saturate(1010%) - hue-rotate(63deg) brightness(91%) contrast(91%), - 'darker': brightness(0) saturate(100%) invert(15%) sepia(32%) saturate(727%) - hue-rotate(118deg) brightness(93%) contrast(91%), - 'dark': brightness(0) saturate(100%) invert(18%) sepia(75%) saturate(6649%) - hue-rotate(155deg) brightness(97%) contrast(87%), - 'base': brightness(0) saturate(100%) invert(56%) sepia(10%) saturate(2637%) - hue-rotate(64deg) brightness(106%) contrast(91%), - 'light': brightness(0) saturate(100%) invert(93%) sepia(15%) saturate(599%) - hue-rotate(52deg) brightness(93%) contrast(93%), - 'lighter': brightness(0) saturate(100%) invert(92%) sepia(51%) - saturate(187%) hue-rotate(46deg) brightness(108%) contrast(89%), - ), - 'yellow': ( - 'text': brightness(0) saturate(100%) invert(28%) sepia(42%) saturate(413%) - hue-rotate(11deg) brightness(97%) contrast(91%), - 'darker': brightness(0) saturate(100%) invert(19%) sepia(75%) saturate(981%) - hue-rotate(17deg) brightness(103%) contrast(103%), - 'dark': brightness(0) saturate(100%) invert(37%) sepia(51%) saturate(709%) - hue-rotate(0deg) brightness(93%) contrast(89%), - 'base': brightness(0) saturate(100%) invert(65%) sepia(91%) saturate(530%) - hue-rotate(5deg) brightness(100%) contrast(100%), - 'light': brightness(0) saturate(100%) invert(77%) sepia(72%) saturate(246%) - hue-rotate(355deg) brightness(103%) contrast(107%), - 'lighter': brightness(0) saturate(100%) invert(88%) sepia(27%) - saturate(234%) hue-rotate(357deg) brightness(103%) contrast(98%), - ), - 'orange': ( - 'text': brightness(0) saturate(100%) invert(23%) sepia(18%) saturate(1092%) - hue-rotate(348deg) brightness(99%) contrast(84%), - 'darker': brightness(0) saturate(100%) invert(9%) sepia(83%) saturate(1926%) - hue-rotate(356deg) brightness(98%) contrast(99%), - 'dark': brightness(0) saturate(100%) invert(29%) sepia(94%) saturate(1431%) - hue-rotate(5deg) brightness(96%) contrast(82%), - 'base': brightness(0) saturate(100%) invert(54%) sepia(86%) saturate(416%) - hue-rotate(340deg) brightness(105%) contrast(91%), - 'light': brightness(0) saturate(100%) invert(77%) sepia(39%) saturate(483%) - hue-rotate(335deg) brightness(101%) contrast(103%), - 'lighter': brightness(0) saturate(100%) invert(93%) sepia(11%) - saturate(918%) hue-rotate(312deg) brightness(107%) contrast(98%), - ), - 'red': ( - 'text': brightness(0) saturate(100%) invert(22%) sepia(9%) saturate(2068%) - hue-rotate(325deg) brightness(92%) contrast(83%), - 'darker': brightness(0) saturate(100%) invert(12%) sepia(100%) - saturate(5699%) hue-rotate(353deg) brightness(75%) contrast(101%), - 'dark': brightness(0) saturate(100%) invert(12%) sepia(100%) saturate(5699%) - hue-rotate(353deg) brightness(75%) contrast(101%), - 'base': brightness(0) saturate(100%) invert(28%) sepia(67%) saturate(3622%) - hue-rotate(353deg) brightness(89%) contrast(95%), - 'light': brightness(0) saturate(100%) invert(80%) sepia(9%) saturate(2561%) - hue-rotate(313deg) brightness(101%) contrast(99%), - 'lighter': brightness(0) saturate(100%) invert(89%) sepia(21%) - saturate(137%) hue-rotate(324deg) brightness(102%) contrast(97%), - ), - 'ink': ( - 'base': brightness(0) saturate(100%) invert(10%) sepia(10%) saturate(2259%) - hue-rotate(171deg) brightness(99%) contrast(84%), - 'light': brightness(0) saturate(100%) invert(32%) sepia(9%) saturate(1069%) - hue-rotate(173deg) brightness(83%) contrast(84%), - 'lighter': brightness(0) saturate(100%) invert(45%) sepia(8%) saturate(825%) - hue-rotate(166deg) brightness(95%) contrast(90%), - 'lightest': brightness(0) saturate(100%) invert(68%) sepia(18%) - saturate(246%) hue-rotate(169deg) brightness(88%) contrast(90%), - ), - 'sky': ( - 'dark': brightness(0) saturate(100%) invert(86%) sepia(4%) saturate(502%) - hue-rotate(167deg) brightness(96%) contrast(91%), - 'base': brightness(0) saturate(100%) invert(100%) sepia(95%) saturate(336%) - hue-rotate(175deg) brightness(97%) contrast(87%), - 'light': brightness(0) saturate(100%) invert(99%) sepia(12%) saturate(467%) - hue-rotate(174deg) brightness(99%) contrast(96%), - 'lighter': brightness(0) saturate(100%) invert(99%) sepia(1%) saturate(159%) - hue-rotate(170deg) brightness(99%) contrast(99%), - ), - 'black': ( - 'base': brightness(0) saturate(100%), - ), - 'white': ( - 'base': brightness(0) saturate(100%) invert(100%), - ), - 'icon': ( - 'base': brightness(0) saturate(100%) invert(36%) sepia(13%) saturate(137%) - hue-rotate(169deg) brightness(95%) contrast(87%), - ), - 'action': ( - 'base': brightness(0) saturate(100%) invert(20%) sepia(59%) saturate(5557%) - hue-rotate(162deg) brightness(95%) contrast(101%), - ), -); - -/** + + $polaris-color-filters: ( + 'purple': ( + 'text': brightness(0) saturate(100%) invert(29%) sepia(3%) saturate(2843%) + hue-rotate(223deg) brightness(92%) contrast(86%), + 'darker': brightness(0) saturate(100%) invert(8%) sepia(38%) saturate(6605%) + hue-rotate(265deg) brightness(99%) contrast(124%), + 'dark': brightness(0) saturate(100%) invert(12%) sepia(46%) saturate(4964%) + hue-rotate(258deg) brightness(101%) contrast(93%), + 'base': brightness(0) saturate(100%) invert(49%) sepia(77%) saturate(1864%) + hue-rotate(229deg) brightness(91%) contrast(91%), + 'light': brightness(0) saturate(100%) invert(82%) sepia(13%) saturate(1535%) + hue-rotate(203deg) brightness(103%) contrast(104%), + 'lighter': brightness(0) saturate(100%) invert(84%) sepia(15%) + saturate(135%) hue-rotate(219deg) brightness(110%) contrast(98%), + ), + 'indigo': ( + 'text': brightness(0) saturate(100%) invert(24%) sepia(11%) saturate(1035%) + hue-rotate(195deg) brightness(97%) contrast(94%), + 'darker': brightness(0) saturate(100%) invert(5%) sepia(81%) saturate(5060%) + hue-rotate(229deg) brightness(72%) contrast(111%), + 'dark': brightness(0) saturate(100%) invert(17%) sepia(28%) saturate(4409%) + hue-rotate(218deg) brightness(87%) contrast(98%), + 'base': brightness(0) saturate(100%) invert(45%) sepia(17%) saturate(1966%) + hue-rotate(194deg) brightness(88%) contrast(84%), + 'light': brightness(0) saturate(100%) invert(82%) sepia(37%) saturate(4261%) + hue-rotate(194deg) brightness(111%) contrast(92%), + 'lighter': brightness(0) saturate(100%) invert(100%) sepia(25%) + saturate(1090%) hue-rotate(179deg) brightness(100%) contrast(96%), + ), + 'blue': ( + 'text': brightness(0) saturate(100%) invert(27%) sepia(13%) saturate(709%) + hue-rotate(158deg) brightness(96%) contrast(89%), + 'darker': brightness(0) saturate(100%) invert(5%) sepia(33%) saturate(5606%) + hue-rotate(195deg) brightness(97%) contrast(102%), + 'dark': brightness(0) saturate(100%) invert(22%) sepia(70%) saturate(1308%) + hue-rotate(182deg) brightness(94%) contrast(101%), + 'base': brightness(0) saturate(100%) invert(19%) sepia(98%) saturate(2885%) + hue-rotate(190deg) brightness(99%) contrast(101%), + 'light': brightness(0) saturate(100%) invert(80%) sepia(7%) saturate(1832%) + hue-rotate(178deg) brightness(108%) contrast(96%), + 'lighter': brightness(0) saturate(100%) invert(100%) sepia(94%) + saturate(686%) hue-rotate(175deg) brightness(103%) contrast(96%), + ), + 'teal': ( + 'text': brightness(0) saturate(100%) invert(31%) sepia(11%) saturate(665%) + hue-rotate(128deg) brightness(94%) contrast(93%), + 'darker': brightness(0) saturate(100%) invert(15%) sepia(23%) + saturate(2237%) hue-rotate(141deg) brightness(96%) contrast(104%), + 'dark': brightness(0) saturate(100%) invert(28%) sepia(83%) saturate(3919%) + hue-rotate(168deg) brightness(93%) contrast(101%), + 'base': brightness(0) saturate(100%) invert(72%) sepia(8%) saturate(2838%) + hue-rotate(130deg) brightness(92%) contrast(87%), + 'light': brightness(0) saturate(100%) invert(95%) sepia(12%) saturate(683%) + hue-rotate(122deg) brightness(97%) contrast(91%), + 'lighter': brightness(0) saturate(100%) invert(87%) sepia(5%) + saturate(1124%) hue-rotate(173deg) brightness(114%) contrast(92%), + ), + 'green': ( + 'text': brightness(0) saturate(100%) invert(30%) sepia(8%) saturate(1010%) + hue-rotate(63deg) brightness(91%) contrast(91%), + 'darker': brightness(0) saturate(100%) invert(15%) sepia(32%) saturate(727%) + hue-rotate(118deg) brightness(93%) contrast(91%), + 'dark': brightness(0) saturate(100%) invert(18%) sepia(75%) saturate(6649%) + hue-rotate(155deg) brightness(97%) contrast(87%), + 'base': brightness(0) saturate(100%) invert(56%) sepia(10%) saturate(2637%) + hue-rotate(64deg) brightness(106%) contrast(91%), + 'light': brightness(0) saturate(100%) invert(93%) sepia(15%) saturate(599%) + hue-rotate(52deg) brightness(93%) contrast(93%), + 'lighter': brightness(0) saturate(100%) invert(92%) sepia(51%) + saturate(187%) hue-rotate(46deg) brightness(108%) contrast(89%), + ), + 'yellow': ( + 'text': brightness(0) saturate(100%) invert(28%) sepia(42%) saturate(413%) + hue-rotate(11deg) brightness(97%) contrast(91%), + 'darker': brightness(0) saturate(100%) invert(19%) sepia(75%) saturate(981%) + hue-rotate(17deg) brightness(103%) contrast(103%), + 'dark': brightness(0) saturate(100%) invert(37%) sepia(51%) saturate(709%) + hue-rotate(0deg) brightness(93%) contrast(89%), + 'base': brightness(0) saturate(100%) invert(65%) sepia(91%) saturate(530%) + hue-rotate(5deg) brightness(100%) contrast(100%), + 'light': brightness(0) saturate(100%) invert(77%) sepia(72%) saturate(246%) + hue-rotate(355deg) brightness(103%) contrast(107%), + 'lighter': brightness(0) saturate(100%) invert(88%) sepia(27%) + saturate(234%) hue-rotate(357deg) brightness(103%) contrast(98%), + ), + 'orange': ( + 'text': brightness(0) saturate(100%) invert(23%) sepia(18%) saturate(1092%) + hue-rotate(348deg) brightness(99%) contrast(84%), + 'darker': brightness(0) saturate(100%) invert(9%) sepia(83%) saturate(1926%) + hue-rotate(356deg) brightness(98%) contrast(99%), + 'dark': brightness(0) saturate(100%) invert(29%) sepia(94%) saturate(1431%) + hue-rotate(5deg) brightness(96%) contrast(82%), + 'base': brightness(0) saturate(100%) invert(54%) sepia(86%) saturate(416%) + hue-rotate(340deg) brightness(105%) contrast(91%), + 'light': brightness(0) saturate(100%) invert(77%) sepia(39%) saturate(483%) + hue-rotate(335deg) brightness(101%) contrast(103%), + 'lighter': brightness(0) saturate(100%) invert(93%) sepia(11%) + saturate(918%) hue-rotate(312deg) brightness(107%) contrast(98%), + ), + 'red': ( + 'text': brightness(0) saturate(100%) invert(22%) sepia(9%) saturate(2068%) + hue-rotate(325deg) brightness(92%) contrast(83%), + 'darker': brightness(0) saturate(100%) invert(12%) sepia(100%) + saturate(5699%) hue-rotate(353deg) brightness(75%) contrast(101%), + 'dark': brightness(0) saturate(100%) invert(12%) sepia(100%) saturate(5699%) + hue-rotate(353deg) brightness(75%) contrast(101%), + 'base': brightness(0) saturate(100%) invert(28%) sepia(67%) saturate(3622%) + hue-rotate(353deg) brightness(89%) contrast(95%), + 'light': brightness(0) saturate(100%) invert(80%) sepia(9%) saturate(2561%) + hue-rotate(313deg) brightness(101%) contrast(99%), + 'lighter': brightness(0) saturate(100%) invert(89%) sepia(21%) + saturate(137%) hue-rotate(324deg) brightness(102%) contrast(97%), + ), + 'ink': ( + 'base': brightness(0) saturate(100%) invert(10%) sepia(10%) saturate(2259%) + hue-rotate(171deg) brightness(99%) contrast(84%), + 'light': brightness(0) saturate(100%) invert(32%) sepia(9%) saturate(1069%) + hue-rotate(173deg) brightness(83%) contrast(84%), + 'lighter': brightness(0) saturate(100%) invert(45%) sepia(8%) saturate(825%) + hue-rotate(166deg) brightness(95%) contrast(90%), + 'lightest': brightness(0) saturate(100%) invert(68%) sepia(18%) + saturate(246%) hue-rotate(169deg) brightness(88%) contrast(90%), + ), + 'sky': ( + 'dark': brightness(0) saturate(100%) invert(86%) sepia(4%) saturate(502%) + hue-rotate(167deg) brightness(96%) contrast(91%), + 'base': brightness(0) saturate(100%) invert(100%) sepia(95%) saturate(336%) + hue-rotate(175deg) brightness(97%) contrast(87%), + 'light': brightness(0) saturate(100%) invert(99%) sepia(12%) saturate(467%) + hue-rotate(174deg) brightness(99%) contrast(96%), + 'lighter': brightness(0) saturate(100%) invert(99%) sepia(1%) saturate(159%) + hue-rotate(170deg) brightness(99%) contrast(99%), + ), + 'black': ( + 'base': brightness(0) saturate(100%), + ), + 'white': ( + 'base': brightness(0) saturate(100%) invert(100%), + ), + 'icon': ( + 'base': brightness(0) saturate(100%) invert(36%) sepia(13%) saturate(137%) + hue-rotate(169deg) brightness(95%) contrast(87%), + ), + 'action': ( + 'base': brightness(0) saturate(100%) invert(20%) sepia(59%) saturate(5557%) + hue-rotate(162deg) brightness(95%) contrast(101%), + ), + ); + + /** * Polaris Tokens: duration.map */ - -$polaris-duration-map: ( - 'duration-none': ( - 0, - ), - 'duration-fast': ( - 100ms, - ), - 'duration-base': ( - 200ms, - ), - 'duration-slow': ( - 300ms, - ), - 'duration-slower': ( - 400ms, - ), - 'duration-slowest': ( - 500ms, - ), -); - -/** + + $polaris-duration-map: ( + 'duration-none': ( + 0, + ), + 'duration-fast': ( + 100ms, + ), + 'duration-base': ( + 200ms, + ), + 'duration-slow': ( + 300ms, + ), + 'duration-slower': ( + 400ms, + ), + 'duration-slowest': ( + 500ms, + ), + ); + + /** * Polaris Tokens: spacing.spacing-map */ - -$polaris-spacing: ( - 'none': 0, - 'extra-tight': 4px, - 'tight': 8px, - 'base-tight': 12px, - 'base': 16px, - 'loose': 20px, - 'extra-loose': 32px, -); - -/** + + $polaris-spacing: ( + 'none': 0, + 'extra-tight': 4px, + 'tight': 8px, + 'base-tight': 12px, + 'base': 16px, + 'loose': 20px, + 'extra-loose': 32px, + ); + + /** * FOUNDATION: accessibility */ - -@mixin high-contrast-outline($border-width: border-width()) { - outline: $border-width solid transparent; - @content; -} - -@mixin high-contrast-border($border-width: border-width()) { - border: $border-width solid transparent; - @content; -} - -/** + + @mixin high-contrast-outline($border-width: border-width()) { + outline: $border-width solid transparent; + @content; + } + + @mixin high-contrast-border($border-width: border-width()) { + border: $border-width solid transparent; + @content; + } + + /** * FOUNDATION: utilities */ - -$default-browser-font-size: 16px; -$base-font-size: 16px; - -/// Returns the value in rem for a given pixel value. -/// @param {Number} $value - The pixel value to be converted. -/// @return {Number} The converted value in rem. - -@function rem($value) { - $unit: unit($value); - - @if $value == 0 { - @return 0; - } @else if $unit == 'rem' { - @return $value; - } @else if $unit == 'px' { - @return $value / $base-font-size * 1rem; - } @else if $unit == 'em' { - @return $unit / 1em * 1rem; - } @else { - @error 'Value must be in px, em, or rem.'; - } -} - -/// Returns the value in pixels for a given rem value. -/// @param {Number} $value - The rem value to be converted. -/// @return {Number} The converted value in pixels. - -@function px($value) { - $unit: unit($value); - - @if $value == 0 { - @return 0; - } @else if $unit == 'px' { - @return $value; - } @else if $unit == 'em' { - @return ($value / 1em) * $base-font-size; - } @else if $unit == 'rem' { - @return ($value / 1rem) * $base-font-size; - } @else { - @error 'Value must be in rem, em, or px.'; - } -} - -/// Returns the value in ems for a given pixel value. Note that this -/// only works for elements that have had no font-size changes. -/// @param {Number} $value - The pixel value to be converted. -/// @return {Number} The converted value in ems. - -@function em($value) { - $unit: unit($value); - - @if $value == 0 { - @return 0; - } @else if $unit == 'em' { - @return $value; - } @else if $unit == 'rem' { - @return $value / 1rem * 1em * ($base-font-size / $default-browser-font-size); - } @else if $unit == 'px' { - @return $value / $default-browser-font-size * 1em; - } @else { - @error 'Value must be in px, rem, or em.'; - } -} - -/// Returns the list of available names in a given map. -/// @param {Map} $map - The map of data to list the names from. -/// @param {Number} $map - The level of depth to get names from. -/// @return {String} The list of names in the map. - -@function available-names($map, $level: 1) { - @if type-of($map) != 'map' { - @return null; + + $default-browser-font-size: 16px; + $base-font-size: 16px; + + /// Returns the value in rem for a given pixel value. + /// @param {Number} $value - The pixel value to be converted. + /// @return {Number} The converted value in rem. + + @function rem($value) { + $unit: unit($value); + + @if $value == 0 { + @return 0; + } @else if $unit == 'rem' { + @return $value; + } @else if $unit == 'px' { + @return $value / $base-font-size * 1rem; + } @else if $unit == 'em' { + @return $unit / 1em * 1rem; + } @else { + @error 'Value must be in px, em, or rem.'; + } } - - $output: ''; - $newline: '\A '; - - @if $level == 1 { - @each $key, $value in $map { - $output: $output + - '#{$newline}- #{$key} #{available-names($value, $level + 1)}'; - } - } @else { - $output: '('; - $i: 1; - - @each $key, $value in $map { - $sep: if($i < length($map), ', ', ''); - $output: $output + '#{$key}#{$sep}#{available-names($value, $level + 1)}'; - $i: $i + 1; + + /// Returns the value in pixels for a given rem value. + /// @param {Number} $value - The rem value to be converted. + /// @return {Number} The converted value in pixels. + + @function px($value) { + $unit: unit($value); + + @if $value == 0 { + @return 0; + } @else if $unit == 'px' { + @return $value; + } @else if $unit == 'em' { + @return ($value / 1em) * $base-font-size; + } @else if $unit == 'rem' { + @return ($value / 1rem) * $base-font-size; + } @else { + @error 'Value must be in rem, em, or px.'; } - - $output: $output + ')'; } - - @return $output; -} - -// Merge multiple maps into one. -// @param {Map} $map - Initial default map. -// @param {ArgList} $maps - Other maps to merge. -// @return {Map} The final merged map. -@function map-extend($map, $maps...) { - @for $i from 1 through length($maps) { - @each $key, $value in nth($maps, $i) { - $map: map-merge( - $map, - ( - $key: $value, - ) - ); - - @if type-of($value) == map and type-of(map-get($map, $key)) == map { - $value: map-extend(map-get($map, $key), $value); + + /// Returns the value in ems for a given pixel value. Note that this + /// only works for elements that have had no font-size changes. + /// @param {Number} $value - The pixel value to be converted. + /// @return {Number} The converted value in ems. + + @function em($value) { + $unit: unit($value); + + @if $value == 0 { + @return 0; + } @else if $unit == 'em' { + @return $value; + } @else if $unit == 'rem' { + @return $value / 1rem * 1em * ($base-font-size / $default-browser-font-size); + } @else if $unit == 'px' { + @return $value / $default-browser-font-size * 1em; + } @else { + @error 'Value must be in px, rem, or em.'; + } + } + + /// Returns the list of available names in a given map. + /// @param {Map} $map - The map of data to list the names from. + /// @param {Number} $map - The level of depth to get names from. + /// @return {String} The list of names in the map. + + @function available-names($map, $level: 1) { + @if type-of($map) != 'map' { + @return null; + } + + $output: ''; + $newline: '\A '; + + @if $level == 1 { + @each $key, $value in $map { + $output: $output + + '#{$newline}- #{$key} #{available-names($value, $level + 1)}'; + } + } @else { + $output: '('; + $i: 1; + + @each $key, $value in $map { + $sep: if($i < length($map), ', ', ''); + $output: $output + '#{$key}#{$sep}#{available-names($value, $level + 1)}'; + $i: $i + 1; + } + + $output: $output + ')'; + } + + @return $output; + } + + // Merge multiple maps into one. + // @param {Map} $map - Initial default map. + // @param {ArgList} $maps - Other maps to merge. + // @return {Map} The final merged map. + @function map-extend($map, $maps...) { + @for $i from 1 through length($maps) { + @each $key, $value in nth($maps, $i) { + $map: map-merge( + $map, + ( + $key: $value, + ) + ); + + @if type-of($value) == map and type-of(map-get($map, $key)) == map { + $value: map-extend(map-get($map, $key), $value); + } } } + + @return $map; } - - @return $map; -} - -/** + + /** * FOUNDATION: colors */ - -/// -/// Color data -/// -/// Shopify color palette, extended specifically for polaris-react. -/// -/// @type map -$color-palette-data: $polaris-colors; - -// Add state colors to the palette -$color-palette-data: map-extend( - $color-palette-data, - ( - 'state': ( - 'hover': rgba(223, 227, 232, 0.3), - 'focused': rgba(223, 227, 232, 0.3), - 'active': rgba(179, 188, 245, 0.1), - 'selected': rgba(179, 188, 245, 0.15), - 'subdued': rgba(249, 250, 251, 1), - 'disabled': rgba(249, 250, 251, 1), - 'hover-destructive': rgba(251, 234, 229, 0.4), - 'focused-destructive': rgba(251, 234, 229, 0.4), - 'active-destructive': rgba(220, 56, 37, 0.03), - ), - ) -); - -/// Returns the color value for a given color name and group. -/// -/// @param {String} $hue - The color’s hue. -/// @param {String} $value - The darkness/lightness of the color. Defaults to -/// base. -/// @param {Color} $for-background - The background color on which this color -/// will appear. Applies a multiply filter to ensure appropriate contrast. -/// @return {Color} The color value. - -@function color($hue, $value: base, $for-background: null) { - $fetched-color: map-get(map-get($color-palette-data, $hue), $value); - - @if map-has-key($color-palette-data, $fetched-color) { - $fetched-color: map-get( - map-get($color-palette-data, $fetched-color), - $value - ); - } - - @if $for-background { - $fetched-color: color-multiply($fetched-color, $for-background); - } - - @if type-of($fetched-color) == color { - @return $fetched-color; - } @else { - @error "Color `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `color('yellow')`.\a BAD: `color(yellow)`.\a\a Available options: #{available-names($color-palette-data)}"; - } -} - -/// Darkens the foreground color by the background color. This is the same as -/// the "multiply" filter in graphics apps. -/// -/// @param {Color} $foreground - The color to darken. -/// @param {Color} $background - The background to base darkening on. -/// @return {Color} The modified color. - -@function color-multiply($foreground, $background: null) { - @if $background { - $background: rgb(255, 255, 255); + + /// + /// Color data + /// + /// Shopify color palette, extended specifically for polaris-react. + /// + /// @type map + $color-palette-data: $polaris-colors; + + // Add state colors to the palette + $color-palette-data: map-extend( + $color-palette-data, + ( + 'state': ( + 'hover': rgba(223, 227, 232, 0.3), + 'focused': rgba(223, 227, 232, 0.3), + 'active': rgba(179, 188, 245, 0.1), + 'selected': rgba(179, 188, 245, 0.15), + 'subdued': rgba(249, 250, 251, 1), + 'disabled': rgba(249, 250, 251, 1), + 'hover-destructive': rgba(251, 234, 229, 0.4), + 'focused-destructive': rgba(251, 234, 229, 0.4), + 'active-destructive': rgba(220, 56, 37, 0.03), + ), + ) + ); + + /// Returns the color value for a given color name and group. + /// + /// @param {String} $hue - The color’s hue. + /// @param {String} $value - The darkness/lightness of the color. Defaults to + /// base. + /// @param {Color} $for-background - The background color on which this color + /// will appear. Applies a multiply filter to ensure appropriate contrast. + /// @return {Color} The color value. + + @function color($hue, $value: base, $for-background: null) { + $fetched-color: map-get(map-get($color-palette-data, $hue), $value); + + @if map-has-key($color-palette-data, $fetched-color) { + $fetched-color: map-get( + map-get($color-palette-data, $fetched-color), + $value + ); + } + + @if $for-background { + $fetched-color: color-multiply($fetched-color, $for-background); + } + + @if type-of($fetched-color) == color { + @return $fetched-color; + } @else { + @error "Color `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `color('yellow')`.\a BAD: `color(yellow)`.\a\a Available options: #{available-names($color-palette-data)}"; + } } - - $red: red($background) * red($foreground) / 255; - $green: green($background) * green($foreground) / 255; - $blue: blue($background) * blue($foreground) / 255; - - $opacity: opacity($foreground); - $background-opacity: opacity($background); - - // calculate opacity - $bm-red: $red * $opacity + red($background) * $background-opacity * - (1 - $opacity); - $bm-green: $green * $opacity + green($background) * $background-opacity * - (1 - $opacity); - $bm-blue: $blue * $opacity + blue($background) * $background-opacity * - (1 - $opacity); - - @return rgb($bm-red, $bm-green, $bm-blue); -} - -/// -/// Color palette for Windows high-contrast mode -/// See https://bit.ly/2vN9aGO -/// -/// @type map - -$ms-high-contrast-color-data: ( - 'text': windowText, - 'disabled-text': grayText, - 'selected-text': highlightText, - 'selected-text-background': highlight, - 'button-text': buttonText, - 'button-text-background': buttonFace, - 'background': window, -); - -/// -/// Returns the color value for Windows high contrast mode -/// -/// @param {String} $color - The name of the high-contrast color. -/// @return {Color} The color value. - -@function ms-high-contrast-color($color) { - $fetched-color: map-get($ms-high-contrast-color-data, $color); - - @if $fetched-color { - @return $fetched-color; - } @else { - @error "Color `#{$color}` not found.\a Make sure argument is a string.\a GOOD: ms-high-contrast-color('selected-text').\a BAD: ms-high-contrast-color(selected-text).\a\a Available options: #{available-names($ms-high-contrast-color-data)}"; + + /// Darkens the foreground color by the background color. This is the same as + /// the "multiply" filter in graphics apps. + /// + /// @param {Color} $foreground - The color to darken. + /// @param {Color} $background - The background to base darkening on. + /// @return {Color} The modified color. + + @function color-multiply($foreground, $background: null) { + @if $background { + $background: rgb(255, 255, 255); + } + + $red: red($background) * red($foreground) / 255; + $green: green($background) * green($foreground) / 255; + $blue: blue($background) * blue($foreground) / 255; + + $opacity: opacity($foreground); + $background-opacity: opacity($background); + + // calculate opacity + $bm-red: $red * $opacity + red($background) * $background-opacity * + (1 - $opacity); + $bm-green: $green * $opacity + green($background) * $background-opacity * + (1 - $opacity); + $bm-blue: $blue * $opacity + blue($background) * $background-opacity * + (1 - $opacity); + + @return rgb($bm-red, $bm-green, $bm-blue); + } + + /// + /// Color palette for Windows high-contrast mode + /// See https://bit.ly/2vN9aGO + /// + /// @type map + + $ms-high-contrast-color-data: ( + 'text': windowText, + 'disabled-text': grayText, + 'selected-text': highlightText, + 'selected-text-background': highlight, + 'button-text': buttonText, + 'button-text-background': buttonFace, + 'background': window, + ); + + /// + /// Returns the color value for Windows high contrast mode + /// + /// @param {String} $color - The name of the high-contrast color. + /// @return {Color} The color value. + + @function ms-high-contrast-color($color) { + $fetched-color: map-get($ms-high-contrast-color-data, $color); + + @if $fetched-color { + @return $fetched-color; + } @else { + @error "Color `#{$color}` not found.\a Make sure argument is a string.\a GOOD: ms-high-contrast-color('selected-text').\a BAD: ms-high-contrast-color(selected-text).\a\a Available options: #{available-names($ms-high-contrast-color-data)}"; + } } -} - -/** + + /** * FOUNDATION: filters */ - -/// -/// Color filter data -/// -/// Shopify color filter palette, extended specifically for polaris-react. -/// -/// @type map -$color-filter-palette-data: $polaris-color-filters; - -/// Returns the filter list for a given color name and group. -/// -/// @param {String} $hue - The color’s hue. -/// @param {String} $value - The darkness/lightness of the color. Defaults to -/// base. -/// @return {List} The filter list. - -@function filter($hue, $value: base) { - $fetched-color: map-get(map-get($color-filter-palette-data, $hue), $value); - - @if map-has-key($color-filter-palette-data, $fetched-color) { - $fetched-color: map-get( - map-get($color-filter-palette-data, $fetched-color), - $value - ); - } - - @if type-of($fetched-color) == list { - @return $fetched-color; - } @else { - @error "Filter `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `filter('yellow')`.\a BAD: `filter(yellow)`.\a\a Available options: #{available-names($color-filter-palette-data)}"; + + /// + /// Color filter data + /// + /// Shopify color filter palette, extended specifically for polaris-react. + /// + /// @type map + $color-filter-palette-data: $polaris-color-filters; + + /// Returns the filter list for a given color name and group. + /// + /// @param {String} $hue - The color’s hue. + /// @param {String} $value - The darkness/lightness of the color. Defaults to + /// base. + /// @return {List} The filter list. + + @function filter($hue, $value: base) { + $fetched-color: map-get(map-get($color-filter-palette-data, $hue), $value); + + @if map-has-key($color-filter-palette-data, $fetched-color) { + $fetched-color: map-get( + map-get($color-filter-palette-data, $fetched-color), + $value + ); + } + + @if type-of($fetched-color) == list { + @return $fetched-color; + } @else { + @error "Filter `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `filter('yellow')`.\a BAD: `filter(yellow)`.\a\a Available options: #{available-names($color-filter-palette-data)}"; + } } -} - -/** + + /** * FOUNDATION: spacing */ - -$spacing-data: $polaris-spacing; - -/// Returns the spacing value for a given variant. -/// -/// @param {String} $variant - The key for the given variant. -/// @return {Number} The spacing for the variant. - -@function spacing($variant: base) { - $fetched-value: map-get($spacing-data, $variant); - - @if type-of($fetched-value) == number { - @return rem($fetched-value); - } @else { - @error 'Spacing variant `#{$variant}` not found. Available variants: #{available-names($spacing-data)}'; + + $spacing-data: $polaris-spacing; + + /// Returns the spacing value for a given variant. + /// + /// @param {String} $variant - The key for the given variant. + /// @return {Number} The spacing for the variant. + + @function spacing($variant: base) { + $fetched-value: map-get($spacing-data, $variant); + + @if type-of($fetched-value) == number { + @return rem($fetched-value); + } @else { + @error 'Spacing variant `#{$variant}` not found. Available variants: #{available-names($spacing-data)}'; + } } -} - -/** + + /** * FOUNDATION: border-width */ - -$border-width-data: ( - base: rem(1px), - thick: rem(2px), - thicker: rem(3px), -); - -/// Returns the width of the specified border type. -/// @param {String} $variant [base] - The border variant key. -/// @return {Number} The width for the border. - -@function border-width($variant: base) { - $fetched-value: map-get($border-width-data, $variant); - - @if type-of($fetched-value) == number { - @return $fetched-value; - } @else { - @error 'Border width variant `#{$variant}` not found. Available variants: #{available-names($border-width-data)}'; + + $border-width-data: ( + base: rem(1px), + thick: rem(2px), + thicker: rem(3px), + ); + + /// Returns the width of the specified border type. + /// @param {String} $variant [base] - The border variant key. + /// @return {Number} The width for the border. + + @function border-width($variant: base) { + $fetched-value: map-get($border-width-data, $variant); + + @if type-of($fetched-value) == number { + @return $fetched-value; + } @else { + @error 'Border width variant `#{$variant}` not found. Available variants: #{available-names($border-width-data)}'; + } } -} - -/** + + /** * FOUNDATION: borders */ - -$borders-data: ( - base: border-width() solid var(--p-border-subdued), - dark: border-width() solid var(--p-border), - transparent: border-width() solid transparent, - divider: border-width() solid var(--p-divider), -); - -/// Returns the default border. -/// @param {String} $variant [base] - The border variant key. -/// @return {List} The border value. - -@function border($variant: base) { - $fetched-value: map-get($borders-data, $variant); - - @if $fetched-value { - @return $fetched-value; - } @else { - @error 'Border variant `#{$variant}` not found. Available variants: #{available-names($borders-data)}'; + + $borders-data: ( + base: border-width() solid var(--p-border-subdued), + dark: border-width() solid var(--p-border), + transparent: border-width() solid transparent, + divider: border-width() solid var(--p-divider), + ); + + /// Returns the default border. + /// @param {String} $variant [base] - The border variant key. + /// @return {List} The border value. + + @function border($variant: base) { + $fetched-value: map-get($borders-data, $variant); + + @if $fetched-value { + @return $fetched-value; + } @else { + @error 'Border variant `#{$variant}` not found. Available variants: #{available-names($borders-data)}'; + } } -} - -/** + + /** * FOUNDATION: border-radius */ - -$border-radius-data: ( - base: 3px, - large: 6px, -); - -/// Returns the border radius of the specified size. -/// @param {String} $size - The border radius’s size. -/// @return {Number} The border radius value. - -@function border-radius($size: base) { - @return map-get($border-radius-data, $size); -} - -/** + + $border-radius-data: ( + base: 3px, + large: 6px, + ); + + /// Returns the border radius of the specified size. + /// @param {String} $size - The border radius’s size. + /// @return {Number} The border radius value. + + @function border-radius($size: base) { + @return map-get($border-radius-data, $size); + } + + /** * FOUNDATION: duration */ - -$duration-data: $polaris-duration-map; - -/// Returns the duration value for a given variant. -/// -/// @param {String} $variant - The key for the given variant. -/// @return {Number} The duration for the variant (in milliseconds). - -@function duration($variant: base) { - $interpolated-value: 'duration-' + $variant; - $fetched-value: nth(map-get($duration-data, $interpolated-value), 1); - - @if type-of($fetched-value) == number { - @return $fetched-value; - } @else { - @error 'Duration variant `#{$interpolated-value}` not found. Available variants: #{available-names($duration-data)}'; + + $duration-data: $polaris-duration-map; + + /// Returns the duration value for a given variant. + /// + /// @param {String} $variant - The key for the given variant. + /// @return {Number} The duration for the variant (in milliseconds). + + @function duration($variant: base) { + $interpolated-value: 'duration-' + $variant; + $fetched-value: nth(map-get($duration-data, $interpolated-value), 1); + + @if type-of($fetched-value) == number { + @return $fetched-value; + } @else { + @error 'Duration variant `#{$interpolated-value}` not found. Available variants: #{available-names($duration-data)}'; + } } -} - -/** + + /** * FOUNDATION: easing */ - -$easing-data: ( - base: cubic-bezier(0.25, 0.1, 0.25, 1), - in: cubic-bezier(0.36, 0, 1, 1), - out: cubic-bezier(0, 0, 0.42, 1), - excite: cubic-bezier(0.18, 0.67, 0.6, 1.22), - overshoot: cubic-bezier(0.07, 0.28, 0.32, 1.22), - anticipate: cubic-bezier(0.38, -0.4, 0.88, 0.65), -); - -/// Returns the timing-function value for a given variant. -/// -/// @param {String} $variant - The key for the given variant. -/// @return {String} The cubic-bezier function (string) for the variant. - -@function easing($variant: base) { - $fetched-value: map-get($easing-data, $variant); - - @if type-of($fetched-value) == string { - @return $fetched-value; - } @else { - @error 'Easing variant `#{$variant}` not found. Available variants: #{available-names($easing-data)}'; + + $easing-data: ( + base: cubic-bezier(0.25, 0.1, 0.25, 1), + in: cubic-bezier(0.36, 0, 1, 1), + out: cubic-bezier(0, 0, 0.42, 1), + excite: cubic-bezier(0.18, 0.67, 0.6, 1.22), + overshoot: cubic-bezier(0.07, 0.28, 0.32, 1.22), + anticipate: cubic-bezier(0.38, -0.4, 0.88, 0.65), + ); + + /// Returns the timing-function value for a given variant. + /// + /// @param {String} $variant - The key for the given variant. + /// @return {String} The cubic-bezier function (string) for the variant. + + @function easing($variant: base) { + $fetched-value: map-get($easing-data, $variant); + + @if type-of($fetched-value) == string { + @return $fetched-value; + } @else { + @error 'Easing variant `#{$variant}` not found. Available variants: #{available-names($easing-data)}'; + } } -} - -/** + + /** * FOUNDATION: layout */ - -$navigation-width: 240px !default; - -//// -/// Layout -/// @group foundation/layout -//// - -$layout-width-data: ( - primary: ( - min: rem(480px), - max: rem(662px), - ), - secondary: ( - min: rem(240px), - max: rem(320px), - ), - one-half-width: ( - base: rem(450px), - ), - one-third-width: ( - base: rem(240px), - ), - nav: ( - base: rem($navigation-width), - ), - page-with-nav: ( - base: rem(769px), - ), - page-content: ( - not-condensed: rem(680px), - partially-condensed: rem(450px), - ), - inner-spacing: ( - base: spacing(), - ), - outer-spacing: ( - min: spacing(loose), - max: spacing(extra-loose), - ), -); - -/// Returns the widths of the specified column. -/// @param {String} $name - The column name. -/// @return {Number} The width for the column. - -@function layout-width($name, $value: base) { - $fetched-value: map-get(map-get($layout-width-data, $name), $value); - - @if type-of($fetched-value) { - @return $fetched-value; - } @else { - @error 'Column `#{$name} - #{$value}` not found. Available columns: #{available-names($layout-width-data)}'; + + $navigation-width: 240px !default; + + //// + /// Layout + /// @group foundation/layout + //// + + $layout-width-data: ( + primary: ( + min: rem(480px), + max: rem(662px), + ), + secondary: ( + min: rem(240px), + max: rem(320px), + ), + one-half-width: ( + base: rem(450px), + ), + one-third-width: ( + base: rem(240px), + ), + nav: ( + base: rem($navigation-width), + ), + page-with-nav: ( + base: rem(769px), + ), + page-content: ( + not-condensed: rem(680px), + partially-condensed: rem(450px), + ), + inner-spacing: ( + base: spacing(), + ), + outer-spacing: ( + min: spacing(loose), + max: spacing(extra-loose), + ), + ); + + /// Returns the widths of the specified column. + /// @param {String} $name - The column name. + /// @return {Number} The width for the column. + + @function layout-width($name, $value: base) { + $fetched-value: map-get(map-get($layout-width-data, $name), $value); + + @if type-of($fetched-value) { + @return $fetched-value; + } @else { + @error 'Column `#{$name} - #{$value}` not found. Available columns: #{available-names($layout-width-data)}'; + } } -} - -$dismiss-icon-size: 32px; - -@function top-bar-height() { - @return rem(56px); -} - -@function mobile-nav-width() { - @return calc(100vw - #{rem($dismiss-icon-size) + spacing() * 2}); -} - -@function nav-min-window-corrected() { - @return rem(769px); -} - -/** + + $dismiss-icon-size: 32px; + + @function top-bar-height() { + @return rem(56px); + } + + @function mobile-nav-width() { + @return calc(100vw - #{rem($dismiss-icon-size) + spacing() * 2}); + } + + @function nav-min-window-corrected() { + @return rem(769px); + } + + /** * FOUNDATION: shadows */ - -// Shadows are intentionally very subtle gradiations. -$shadows-data: ( - faint: ( - 0 1px 0 0 rgba(22, 29, 37, 0.05), - ), - base: ( - 0 0 0 1px rgba(63, 63, 68, 0.05), - 0 1px 3px 0 rgba(63, 63, 68, 0.15), - ), - deep: ( - 0 0 0 1px rgba(6, 44, 82, 0.1), - 0 2px 16px rgba(33, 43, 54, 0.08), - ), - layer: ( - 0 31px 41px 0 rgba(32, 42, 53, 0.2), - 0 2px 16px 0 rgba(32, 42, 54, 0.08), - ), - transparent: 0 0 0 0 transparent, -); - -/// Returns the shadow for the specified depth -/// @param {String} $depth [base] - The shadow’s depth. -/// @return {List} The shadow value. - -@function shadow($depth: base) { - $fetched-value: map-get($shadows-data, $depth); - - @if type-of($fetched-value) == list { - @return $fetched-value; - } @else { - @error 'Shadow variant `#{$depth}` not found. Available variants: #{available-names($shadows-data)}'; + + // Shadows are intentionally very subtle gradiations. + $shadows-data: ( + faint: ( + 0 1px 0 0 rgba(22, 29, 37, 0.05), + ), + base: ( + 0 0 0 1px rgba(63, 63, 68, 0.05), + 0 1px 3px 0 rgba(63, 63, 68, 0.15), + ), + deep: ( + 0 0 0 1px rgba(6, 44, 82, 0.1), + 0 2px 16px rgba(33, 43, 54, 0.08), + ), + layer: ( + 0 31px 41px 0 rgba(32, 42, 53, 0.2), + 0 2px 16px 0 rgba(32, 42, 54, 0.08), + ), + transparent: 0 0 0 0 transparent, + ); + + /// Returns the shadow for the specified depth + /// @param {String} $depth [base] - The shadow’s depth. + /// @return {List} The shadow value. + + @function shadow($depth: base) { + $fetched-value: map-get($shadows-data, $depth); + + @if type-of($fetched-value) == list { + @return $fetched-value; + } @else { + @error 'Shadow variant `#{$depth}` not found. Available variants: #{available-names($shadows-data)}'; + } } -} - -/** + + /** * FOUNDATION: typography */ - -$typography-condensed: em(640px); - -$font-family-data: ( - base: #{-apple-system, - 'BlinkMacSystemFont', - 'San Francisco', - 'Segoe UI', - 'Roboto', - 'Helvetica Neue', - sans-serif}, - monospace: #{ui-monospace, - SFMono-Regular, - SF Mono, - Consolas, - Liberation Mono, - Menlo, - monospace}, -); - -$line-height-data: ( - caption: ( - base: rem(20px), - large-screen: rem(16px), - ), - heading: ( - base: rem(24px), - ), - subheading: ( - base: rem(16px), - ), - input: ( - base: rem(24px), - ), - body: ( - base: rem(20px), - ), - button: ( - base: rem(16px), - ), - button-large: ( - base: rem(20px), - ), - display-x-large: ( - base: rem(36px), - large-screen: rem(44px), - ), - display-large: ( - base: rem(28px), - large-screen: rem(32px), - ), - display-medium: ( - base: rem(28px), - large-screen: rem(32px), - ), - display-small: ( - base: rem(24px), - large-screen: rem(28px), - ), -); - -$font-size-data: ( - caption: ( - base: rem(13px), - large-screen: rem(12px), - ), - heading: ( - base: rem(17px), - large-screen: rem(16px), - ), - subheading: ( - base: rem(13px), - large-screen: rem(12px), - ), - input: ( - base: rem(16px), - large-screen: rem(14px), - ), - body: ( - base: rem(15px), - large-screen: rem(14px), - ), - button: ( - base: rem(15px), - large-screen: rem(14px), - ), - button-large: ( - base: rem(17px), - large-screen: rem(16px), - ), - display-x-large: ( - base: rem(27px), - large-screen: rem(42px), - ), - display-large: ( - base: rem(24px), - large-screen: rem(28px), - ), - display-medium: ( - base: rem(21px), - large-screen: rem(26px), - ), - display-small: ( - base: rem(16px), - large-screen: rem(20px), - ), -); - -/// Returns the font stack for a given family. -/// -/// @param {String} $family - The key for the given family. -/// @return {Number} The font stack for the family. - -@function font-family($family: base) { - $fetched-value: map-get($font-family-data, $family); - - @if $fetched-value { - @return $fetched-value; - } @else { - @error 'Font family `#{$family}` not found. Available font families: #{available-names($font-family-data)}'; + + $typography-condensed: em(640px); + + $font-family-data: ( + base: #{-apple-system, + 'BlinkMacSystemFont', + 'San Francisco', + 'Segoe UI', + 'Roboto', + 'Helvetica Neue', + sans-serif}, + monospace: #{ui-monospace, + SFMono-Regular, + SF Mono, + Consolas, + Liberation Mono, + Menlo, + monospace}, + ); + + $line-height-data: ( + caption: ( + base: rem(20px), + large-screen: rem(16px), + ), + heading: ( + base: rem(24px), + ), + subheading: ( + base: rem(16px), + ), + input: ( + base: rem(24px), + ), + body: ( + base: rem(20px), + ), + button: ( + base: rem(16px), + ), + button-large: ( + base: rem(20px), + ), + display-x-large: ( + base: rem(36px), + large-screen: rem(44px), + ), + display-large: ( + base: rem(28px), + large-screen: rem(32px), + ), + display-medium: ( + base: rem(28px), + large-screen: rem(32px), + ), + display-small: ( + base: rem(24px), + large-screen: rem(28px), + ), + ); + + $font-size-data: ( + caption: ( + base: rem(13px), + large-screen: rem(12px), + ), + heading: ( + base: rem(17px), + large-screen: rem(16px), + ), + subheading: ( + base: rem(13px), + large-screen: rem(12px), + ), + input: ( + base: rem(16px), + large-screen: rem(14px), + ), + body: ( + base: rem(15px), + large-screen: rem(14px), + ), + button: ( + base: rem(15px), + large-screen: rem(14px), + ), + button-large: ( + base: rem(17px), + large-screen: rem(16px), + ), + display-x-large: ( + base: rem(27px), + large-screen: rem(42px), + ), + display-large: ( + base: rem(24px), + large-screen: rem(28px), + ), + display-medium: ( + base: rem(21px), + large-screen: rem(26px), + ), + display-small: ( + base: rem(16px), + large-screen: rem(20px), + ), + ); + + /// Returns the font stack for a given family. + /// + /// @param {String} $family - The key for the given family. + /// @return {Number} The font stack for the family. + + @function font-family($family: base) { + $fetched-value: map-get($font-family-data, $family); + + @if $fetched-value { + @return $fetched-value; + } @else { + @error 'Font family `#{$family}` not found. Available font families: #{available-names($font-family-data)}'; + } } -} - -/// Returns the line height for a given text style and variant. -/// -/// @param {String} $style - The font style. -/// @param {String} $variant [base] - The variant on the font-size. -/// @return {Number} The line-height for the text-style. - -@function line-height($style, $variant: base) { - $fetched-line-height: map-get(map-get($line-height-data, $style), $variant); - - @if type-of($fetched-line-height) { - @return $fetched-line-height; - } @else { - @error 'Line height `#{$style} - #{$variant}` not found. Available line heights: #{available-names($line-height-data)}'; + + /// Returns the line height for a given text style and variant. + /// + /// @param {String} $style - The font style. + /// @param {String} $variant [base] - The variant on the font-size. + /// @return {Number} The line-height for the text-style. + + @function line-height($style, $variant: base) { + $fetched-line-height: map-get(map-get($line-height-data, $style), $variant); + + @if type-of($fetched-line-height) { + @return $fetched-line-height; + } @else { + @error 'Line height `#{$style} - #{$variant}` not found. Available line heights: #{available-names($line-height-data)}'; + } } -} - -/// Returns the font size for a given text style and variant. -/// -/// @param {String} $style - The font style. -/// @param {String} $variant [base] - The variant on the font-size. -/// @return {Number} The font-size for the text-style. - -@function font-size($style, $variant: base) { - $fetched-font-size: map-get(map-get($font-size-data, $style), $variant); - - @if type-of($fetched-font-size) { - @return $fetched-font-size; - } @else { - @error 'Font size `#{$style} - #{$variant}` not found. Available font sizes: #{available-names($line-height-data)}'; + + /// Returns the font size for a given text style and variant. + /// + /// @param {String} $style - The font style. + /// @param {String} $variant [base] - The variant on the font-size. + /// @return {Number} The font-size for the text-style. + + @function font-size($style, $variant: base) { + $fetched-font-size: map-get(map-get($font-size-data, $style), $variant); + + @if type-of($fetched-font-size) { + @return $fetched-font-size; + } @else { + @error 'Font size `#{$style} - #{$variant}` not found. Available font sizes: #{available-names($line-height-data)}'; + } } -} - -/** + + /** * FOUNDATION: z-index */ - -$global-elements: ( - content: 100, - overlay: 400, -); - -// We're matching that here and relatively stacking other fixed components. -$fixed-element-stacking-order: ( - global-ribbon: 510, - loading-bar: 511, - top-bar: 512, - context-bar: 513, - small-screen-loading-bar: 514, - nav-backdrop: 515, - nav: 516, - skip-to-content: 517, - backdrop: 518, - modal: 519, - toast: 520, - dev-ui: 521, -); - -/// Returns the z-index of the specified element. -/// @param {String} $element - The key for the element. -/// @param {Map} $context - The map in which to search for the element. -/// @return {Number} The z-index for the element. - -@function z-index($element, $context: $global-elements) { - $index: map-get($context, $element); - - @if $index { - @return $index; - } @else { - @error 'z-index `#{$element}` in `#{$context}` not found.'; + + $global-elements: ( + content: 100, + overlay: 400, + ); + + // We're matching that here and relatively stacking other fixed components. + $fixed-element-stacking-order: ( + global-ribbon: 510, + loading-bar: 511, + top-bar: 512, + context-bar: 513, + small-screen-loading-bar: 514, + nav-backdrop: 515, + nav: 516, + skip-to-content: 517, + backdrop: 518, + modal: 519, + toast: 520, + dev-ui: 521, + ); + + /// Returns the z-index of the specified element. + /// @param {String} $element - The key for the element. + /// @param {Map} $context - The map in which to search for the element. + /// @return {Number} The z-index for the element. + + @function z-index($element, $context: $global-elements) { + $index: map-get($context, $element); + + @if $index { + @return $index; + } @else { + @error 'z-index `#{$element}` in `#{$context}` not found.'; + } } -} - -/** + + /** * FOUNDATION: focus-ring */ - -/// Sets the focus ring for an interactive element -/// @param {String} $size - The size of the border radius on the focus ring. -/// @param {String} $style - Focus ring state. -/// @param {Number} $border-width - The border width of your element in rems. -/// - -@mixin focus-ring($size: 'base', $border-width: 0, $style: 'base') { - $stroke: rem(2px); - // calc does not like performing addition with a unitless number (`0`, NOT `0px`) - // This is a problem because `rem(0px)` returns `0`, not `0px`. - // Make sure that we can handle unitless zeros by not trying to do math with them - $offset: if( - $border-width == 0, - rem(1px), - calc(#{$border-width} + #{rem(1px)}) - ); - $border-radius: if( - $size == 'wide', - var(--p-border-radius-wide), - var(--p-border-radius-base) - ); - $negative-offset: calc(-1 * #{$offset}); - - @if $style == 'base' { - position: relative; - - &::after { - content: ''; - position: absolute; - z-index: 1; - top: $negative-offset; - right: $negative-offset; - bottom: $negative-offset; - left: $negative-offset; - display: block; - pointer-events: none; - box-shadow: 0 0 0 $negative-offset var(--p-focused); - transition: box-shadow duration(fast) var(--p-ease); - border-radius: calc(#{$border-radius} + #{rem(1px)}); + + /// Sets the focus ring for an interactive element + /// @param {String} $size - The size of the border radius on the focus ring. + /// @param {String} $style - Focus ring state. + /// @param {Number} $border-width - The border width of your element in rems. + /// + + @mixin focus-ring($size: 'base', $border-width: 0, $style: 'base') { + $stroke: rem(2px); + // calc does not like performing addition with a unitless number (`0`, NOT `0px`) + // This is a problem because `rem(0px)` returns `0`, not `0px`. + // Make sure that we can handle unitless zeros by not trying to do math with them + $offset: if( + $border-width == 0, + rem(1px), + calc(#{$border-width} + #{rem(1px)}) + ); + $border-radius: if( + $size == 'wide', + var(--p-border-radius-wide), + var(--p-border-radius-base) + ); + $negative-offset: calc(-1 * #{$offset}); + + @if $style == 'base' { + position: relative; + + &::after { + content: ''; + position: absolute; + z-index: 1; + top: $negative-offset; + right: $negative-offset; + bottom: $negative-offset; + left: $negative-offset; + display: block; + pointer-events: none; + box-shadow: 0 0 0 $negative-offset var(--p-focused); + transition: box-shadow duration(fast) var(--p-ease); + border-radius: calc(#{$border-radius} + #{rem(1px)}); + } + } @else if $style == 'focused' { + &::after { + box-shadow: 0 0 0 $stroke var(--p-focused); + @include high-contrast-outline; + } } - } @else if $style == 'focused' { + } + + @mixin no-focus-ring { &::after { - box-shadow: 0 0 0 $stroke var(--p-focused); - @include high-contrast-outline; + content: none; } } -} - -@mixin no-focus-ring { - &::after { - content: none; - } -} - -/** + + /** * SHARED: accessibility */ - -/// Used to hide an element visually, but keeping it accessible for -/// accessibility tools. - -/// styles referenced from GOV.UK design system -/// https://github.com/h5bp/main.css/issues/12#issuecomment-451965809 -@mixin visually-hidden { - // Need to make sure we override any existing styles. - // stylelint-disable declaration-no-important - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: 0 !important; - padding: 0 !important; - overflow: hidden !important; - clip-path: inset(50%) !important; - border: 0 !important; - white-space: nowrap !important; - // stylelint-enable declaration-no-important -} - -/** + + /// Used to hide an element visually, but keeping it accessible for + /// accessibility tools. + + /// styles referenced from GOV.UK design system + /// https://github.com/h5bp/main.css/issues/12#issuecomment-451965809 + @mixin visually-hidden { + // Need to make sure we override any existing styles. + // stylelint-disable declaration-no-important + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + clip-path: inset(50%) !important; + border: 0 !important; + white-space: nowrap !important; + // stylelint-enable declaration-no-important + } + + /** * SHARED: breakpoints */ - -$page-max-width: layout-width(primary, max) + layout-width(secondary, max) + - layout-width(inner-spacing); -$frame-with-nav-max-width: layout-width(nav) + $page-max-width; - -$stacked-content: em( - layout-width(primary, min) + layout-width(secondary, min) + - layout-width(inner-spacing) -); -$not-condensed-content: em(layout-width(page-content, not-condensed)); -$partially-condensed-content: em( - layout-width(page-content, partially-condensed) -); - -$not-condensed-outer-spacing: em(2 * layout-width(outer-spacing, max)); -$partially-condensed-outer-spacing: em(2 * layout-width(outer-spacing, min)); - -$not-condensed-min-page: $not-condensed-content + $not-condensed-outer-spacing; -$partially-condensed-min-page: $partially-condensed-content + - $partially-condensed-outer-spacing; - -$nav-size: em(layout-width(nav)); -$nav-min-window: em(layout-width(page-with-nav)); - -@function breakpoint($value, $adjustment: 0) { - $adjusted-value: em($adjustment); - - // Reduces chances to have a style void - // between two media queries - // See https://github.com/sass-mq/sass-mq/issues/6 - @if $adjustment == -1px { - $adjusted-value: -0.01em; - } @else if $adjustment == 1px { - $adjusted-value: 0.01em; - } - - @return em($value) + $adjusted-value; -} - -@mixin page-content-breakpoint-before($size) { - $size: breakpoint($size); - - @if $size < $partially-condensed-content { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { + + $page-max-width: layout-width(primary, max) + layout-width(secondary, max) + + layout-width(inner-spacing); + $frame-with-nav-max-width: layout-width(nav) + $page-max-width; + + $stacked-content: em( + layout-width(primary, min) + layout-width(secondary, min) + + layout-width(inner-spacing) + ); + $not-condensed-content: em(layout-width(page-content, not-condensed)); + $partially-condensed-content: em( + layout-width(page-content, partially-condensed) + ); + + $not-condensed-outer-spacing: em(2 * layout-width(outer-spacing, max)); + $partially-condensed-outer-spacing: em(2 * layout-width(outer-spacing, min)); + + $not-condensed-min-page: $not-condensed-content + $not-condensed-outer-spacing; + $partially-condensed-min-page: $partially-condensed-content + + $partially-condensed-outer-spacing; + + $nav-size: em(layout-width(nav)); + $nav-min-window: em(layout-width(page-with-nav)); + + @function breakpoint($value, $adjustment: 0) { + $adjusted-value: em($adjustment); + + // Reduces chances to have a style void + // between two media queries + // See https://github.com/sass-mq/sass-mq/issues/6 + @if $adjustment == -1px { + $adjusted-value: -0.01em; + } @else if $adjustment == 1px { + $adjusted-value: 0.01em; + } + + @return em($value) + $adjusted-value; + } + + @mixin page-content-breakpoint-before($size) { + $size: breakpoint($size); + + @if $size < $partially-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { @media (max-width: #{min($nav-min-window, $size)}), (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size}) { @content; } } - - @media (max-width: #{$size}) { - @content; - } - } @else if $size < $not-condensed-content { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { + + @media (max-width: #{$size}) { + @content; + } + } @else if $size < $not-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { @media (max-width: #{min($nav-min-window, $size + $partially-condensed-outer-spacing)}), (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { @content; } } - - @media (max-width: #{$size + $partially-condensed-outer-spacing}) { - @content; - } - } @else { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { + + @media (max-width: #{$size + $partially-condensed-outer-spacing}) { + @content; + } + } @else { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { @media (max-width: #{min($nav-min-window, $size + $partially-condensed-outer-spacing)}), (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { @content; } } - - @media (max-width: #{$size + $not-condensed-outer-spacing}) { - @content; + + @media (max-width: #{$size + $not-condensed-outer-spacing}) { + @content; + } } } -} - -@mixin page-content-breakpoint-after($size) { - $size: breakpoint($size); - - @if $size < $partially-condensed-content { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { + + @mixin page-content-breakpoint-after($size) { + $size: breakpoint($size); + + @if $size < $partially-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { @media (max-width: #{$nav-min-window}) and (min-width: #{$size}), (min-width: #{$nav-size + $size}) { @content; } } - - @media (min-width: #{$size}) { - @content; - } - } @else if $size < $not-condensed-content { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { + + @media (min-width: #{$size}) { + @content; + } + } @else if $size < $not-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { @media (max-width: #{$nav-min-window}) and (min-width: #{$size + $partially-condensed-outer-spacing}), (min-width: #{$nav-size + $size + $partially-condensed-outer-spacing}) { @content; } } - - @media (min-width: #{$size + $partially-condensed-outer-spacing}) { - @content; - } - } @else { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { + + @media (min-width: #{$size + $partially-condensed-outer-spacing}) { + @content; + } + } @else { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { @media (max-width: #{$nav-min-window}) and (min-width: #{$size + $not-condensed-outer-spacing}), (min-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { @content; } } - - @media (min-width: #{$size + $not-condensed-outer-spacing}) { - @content; + + @media (min-width: #{$size + $not-condensed-outer-spacing}) { + @content; + } } } -} - -@mixin breakpoint-after($breakpoint, $inclusive: true) { - @media (min-width: #{breakpoint($breakpoint, if($inclusive, 0, 1px))}) { - @content; + + @mixin breakpoint-after($breakpoint, $inclusive: true) { + @media (min-width: #{breakpoint($breakpoint, if($inclusive, 0, 1px))}) { + @content; + } } -} - -@mixin breakpoint-before($breakpoint, $inclusive: true) { - @media (max-width: #{breakpoint($breakpoint, if($inclusive, 0, -1px))}) { - @content; + + @mixin breakpoint-before($breakpoint, $inclusive: true) { + @media (max-width: #{breakpoint($breakpoint, if($inclusive, 0, -1px))}) { + @content; + } } -} - -@mixin frame-with-nav-when-not-max-width() { - @include breakpoint-before($frame-with-nav-max-width) { - @content; + + @mixin frame-with-nav-when-not-max-width() { + @include breakpoint-before($frame-with-nav-max-width) { + @content; + } } -} - -@mixin page-when-not-max-width() { - @include breakpoint-before($page-max-width) { - @content; + + @mixin page-when-not-max-width() { + @include breakpoint-before($page-max-width) { + @content; + } } -} - -@mixin page-content-when-layout-stacked() { - @include page-content-breakpoint-before($stacked-content) { - @content; + + @mixin page-content-when-layout-stacked() { + @include page-content-breakpoint-before($stacked-content) { + @content; + } } -} - -@mixin page-content-when-layout-not-stacked() { - @include page-content-breakpoint-after($stacked-content) { - @content; + + @mixin page-content-when-layout-not-stacked() { + @include page-content-breakpoint-after($stacked-content) { + @content; + } } -} - -@mixin page-content-when-partially-condensed() { - @include page-content-breakpoint-before($not-condensed-content) { - @content; + + @mixin page-content-when-partially-condensed() { + @include page-content-breakpoint-before($not-condensed-content) { + @content; + } } -} - -@mixin page-content-when-not-partially-condensed() { - @include page-content-breakpoint-after($not-condensed-content) { - @content; + + @mixin page-content-when-not-partially-condensed() { + @include page-content-breakpoint-after($not-condensed-content) { + @content; + } } -} - -@mixin page-content-when-fully-condensed() { - @include page-content-breakpoint-before($partially-condensed-content) { - @content; + + @mixin page-content-when-fully-condensed() { + @include page-content-breakpoint-before($partially-condensed-content) { + @content; + } } -} - -@mixin page-content-when-not-fully-condensed() { - @include page-content-breakpoint-after($partially-condensed-content) { - @content; + + @mixin page-content-when-not-fully-condensed() { + @include page-content-breakpoint-after($partially-condensed-content) { + @content; + } } -} - -@mixin frame-when-nav-displayed() { - @include breakpoint-after(layout-width(page-with-nav)) { - @content; + + @mixin frame-when-nav-displayed() { + @include breakpoint-after(layout-width(page-with-nav)) { + @content; + } } -} - -@mixin frame-when-nav-hidden() { - @include breakpoint-before(layout-width(page-with-nav), false) { - @content; + + @mixin frame-when-nav-hidden() { + @include breakpoint-before(layout-width(page-with-nav), false) { + @content; + } } -} - -/** + + /** * SHARED: buttons */ - -@mixin high-contrast-button-outline($outline: 2px dotted) { - @media (-ms-high-contrast: active) { - outline: $outline; - } -} - -@mixin button-base { - $min-height: control-height(); - $vertical-padding: ($min-height - line-height(body) - rem(2px)) / 2; - - @include recolor-icon(var(--p-icon)); - @include focus-ring($border-width: border-width('base')); - position: relative; - display: inline-flex; - align-items: center; - justify-content: center; - min-height: $min-height; - min-width: $min-height; - margin: 0; - padding: $vertical-padding spacing(); - background: var(--p-surface); - box-shadow: var(--p-button-drop-shadow); - border-radius: var(--p-border-radius-base); - color: var(--p-text); - border: 1px solid var(--p-border-neutral-subdued); - border-top-color: var(--p-border-subdued); - border-bottom-color: var(--p-border-shadow-subdued); - line-height: 1; - text-align: center; - cursor: pointer; - user-select: none; - text-decoration: none; - -webkit-tap-highlight-color: transparent; - - &:hover { - background: var(--p-action-secondary-hovered); - @include high-contrast-outline; - } - - &:focus { - box-shadow: var(--p-button-drop-shadow); - outline: 0; - - @include focus-ring($style: 'focused'); + + @mixin high-contrast-button-outline($outline: 2px dotted) { + @media (-ms-high-contrast: active) { + outline: $outline; + } } - - &:active { - background: var(--p-action-secondary-pressed); + + @mixin button-base { + $min-height: control-height(); + $vertical-padding: ($min-height - line-height(body) - rem(2px)) / 2; + + @include recolor-icon(var(--p-icon)); + @include focus-ring($border-width: border-width('base')); + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + min-height: $min-height; + min-width: $min-height; + margin: 0; + padding: $vertical-padding spacing(); + background: var(--p-surface); box-shadow: var(--p-button-drop-shadow); - - &::after { - border: none; - box-shadow: none; + border-radius: var(--p-border-radius-base); + color: var(--p-text); + border: 1px solid var(--p-border-neutral-subdued); + border-top-color: var(--p-border-subdued); + border-bottom-color: var(--p-border-shadow-subdued); + line-height: 1; + text-align: center; + cursor: pointer; + user-select: none; + text-decoration: none; + -webkit-tap-highlight-color: transparent; + + &:hover { + background: var(--p-action-secondary-hovered); + @include high-contrast-outline; } - } - - &.pressed { - background: var(--p-action-secondary-depressed); - box-shadow: var(--p-button-pressed-inner-shadow); - color: var(--p-text-on-primary); - border-color: var(--p-border-depressed); - @include recolor-icon(currentColor); - } - - @media (-ms-high-contrast: active) { - border: 1px solid ms-high-contrast-color('text'); - } -} - -@mixin base-button-disabled { - @include recolor-icon(var(--p-icon-disabled)); - transition: none; - box-shadow: none; - border-color: var(--p-border-disabled); - background: var(--p-surface-disabled); - color: var(--p-text-disabled); -} - -@mixin button-filled() { - @include focus-ring($border-width: 0); - background: var(--p-button-color); - border-width: 0; - border-color: transparent; - box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); - color: var(--p-button-text); - - &:hover { - background: var(--p-button-color-hover); - border-color: transparent; - color: var(--p-button-text); - } - - &:focus { - border-color: transparent; - box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); - } - - &:active { - background: var(--p-button-color-active); - border-color: transparent; - box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); - } - - &.pressed { - color: var(--p-button-text); - background: var(--p-button-color-depressed); - border-color: transparent; - box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); - - &:hover, + &:focus { - background: var(--p-button-color-depressed); - box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + box-shadow: var(--p-button-drop-shadow); + outline: 0; + + @include focus-ring($style: 'focused'); } - } -} - -@mixin button-outline($outline-color, $background-color: transparent) { - background: transparent; - border: border-width() solid var(--p-border); - box-shadow: none; - color: var(--p-text); - @include focus-ring($border-width: border-width('base')); - - &:hover { - border: border-width() solid var(--p-border); - box-shadow: none; - background: var(--p-surface-hovered); - } - - &:focus { - border: border-width() solid var(--p-border); - box-shadow: none; - @include focus-ring($style: 'focused'); - } - - &:active { - border: border-width() solid var(--p-border); - box-shadow: none; - background: var(--p-surface-pressed); - - &::after { - box-shadow: none; + + &:active { + background: var(--p-action-secondary-pressed); + box-shadow: var(--p-button-drop-shadow); + + &::after { + border: none; + box-shadow: none; + } + } + + &.pressed { + background: var(--p-action-secondary-depressed); + box-shadow: var(--p-button-pressed-inner-shadow); + color: var(--p-text-on-primary); + border-color: var(--p-border-depressed); + @include recolor-icon(currentColor); + } + + @media (-ms-high-contrast: active) { + border: 1px solid ms-high-contrast-color('text'); } } - - &.pressed { - background: var(--p-action-secondary-pressed); - border: border-width() solid var(--p-border); - box-shadow: none; - color: var(--p-button-text); - } - - &.disabled { - border: border-width('base') solid var(--p-border-disabled); + + @mixin base-button-disabled { + @include recolor-icon(var(--p-icon-disabled)); + transition: none; box-shadow: none; - background: transparent; + border-color: var(--p-border-disabled); + background: var(--p-surface-disabled); color: var(--p-text-disabled); } - - &.destructive { - background: transparent; - border: border-width('base') solid var(--p-border-critical); - box-shadow: none; - color: var(--p-interactive-critical); - @include recolor-icon(var(--p-icon-critical)); - + + @mixin button-filled() { + @include focus-ring($border-width: 0); + background: var(--p-button-color); + border-width: 0; + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + color: var(--p-button-text); + &:hover { - border: border-width('base') solid var(--p-border-critical); - background: var(--p-surface-critical-subdued); + background: var(--p-button-color-hover); + border-color: transparent; + color: var(--p-button-text); } - + &:focus { - border: border-width('base') solid var(--p-border-critical); - @include focus-ring($style: 'focused'); + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); } - + &:active { - border: border-width('base') solid var(--p-border-critical); - background: var(--p-surface-critical-subdued); - } - - &.disabled { - border: border-width('base') solid var(--p-border-critical-disabled); - background: transparent; - color: var(--p-interactive-critical-disabled); + background: var(--p-button-color-active); + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); } - + &.pressed { - background: var(--p-surface-critical-subdued); - box-shadow: border-width('base') solid var(--p-border-critical); - color: var(--p-interactive-critical); + color: var(--p-button-text); + background: var(--p-button-color-depressed); + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + + &:hover, + &:focus { + background: var(--p-button-color-depressed); + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + } } } -} - -@mixin button-outline-disabled($outline-color) { - background: transparent; - box-shadow: none; -} - -@mixin button-full-width { - display: flex; - width: 100%; -} - -@mixin plain-button-backdrop { - padding: 2px 5px; - margin: -2px -5px; - background: var(--p-action-secondary-hovered); - border-radius: border-radius(); -} - -@mixin unstyled-button() { - appearance: none; - margin: 0; - padding: 0; - background: none; - border: none; - font-size: inherit; - line-height: inherit; - color: inherit; - cursor: pointer; - - &:focus { - outline: none; - } -} - -/** - * SHARED: controls - */ - -@function control-height() { - @return rem(36px); -} - -@function control-slim-height() { - @return rem(28px); -} - -@function control-vertical-padding() { - @return (control-height() - line-height(input) - rem(2px)) / 2; -} - -@function control-icon-transition() { - @return transform duration(fast) easing(in); -} - -@mixin control-backdrop($style: base) { - @if $style == base { - position: relative; - border: var(--p-control-border-width) solid var(--p-border); - background-color: var(--p-surface); - border-radius: var(--p-border-radius-base); - - &::before { - content: ''; - position: absolute; - top: calc(-1 * var(--p-control-border-width)); - right: calc(-1 * var(--p-control-border-width)); - bottom: calc(-1 * var(--p-control-border-width)); - left: calc(-1 * var(--p-control-border-width)); - border-radius: var(--p-border-radius-base); - background-color: var(--p-interactive); - opacity: 0; - transform: scale(0.25); - transition: opacity duration(fast) var(--p-ease), - transform duration(fast) var(--p-ease); - } - - &.hover, + + @mixin button-outline($outline-color, $background-color: transparent) { + background: transparent; + border: border-width() solid var(--p-border); + box-shadow: none; + color: var(--p-text); + @include focus-ring($border-width: border-width('base')); + &:hover { - cursor: pointer; - border-color: var(--p-border-hovered); + border: border-width() solid var(--p-border); + box-shadow: none; + background: var(--p-surface-hovered); } - } @else if $style == active { - border-color: var(--p-interactive); - - &::before { - opacity: 1; - transform: scale(1); - @media (-ms-high-contrast: active) { - border: 2px solid ms-high-contrast-color('text'); - } + + &:focus { + border: border-width() solid var(--p-border); + box-shadow: none; + @include focus-ring($style: 'focused'); } - } @else if $style == disabled { - border-color: var(--p-border-disabled); - - &::before { - background-color: var(--p-action-secondary-disabled); + + &:active { + border: border-width() solid var(--p-border); + box-shadow: none; + background: var(--p-surface-pressed); + + &::after { + box-shadow: none; + } } - - &:hover { - cursor: default; + + &.pressed { + background: var(--p-action-secondary-pressed); + border: border-width() solid var(--p-border); + box-shadow: none; + color: var(--p-button-text); } - } @else if $style == error { - border-color: var(--p-border-critical); - background-color: var(--p-surface-critical); - - &.hover, - &:hover { - border-color: var(--p-border-critical); + + &.disabled { + border: border-width('base') solid var(--p-border-disabled); + box-shadow: none; + background: transparent; + color: var(--p-text-disabled); } - - &::before { - background-color: var(--p-border-critical); + + &.destructive { + background: transparent; + border: border-width('base') solid var(--p-border-critical); + box-shadow: none; + color: var(--p-interactive-critical); + @include recolor-icon(var(--p-icon-critical)); + + &:hover { + border: border-width('base') solid var(--p-border-critical); + background: var(--p-surface-critical-subdued); + } + + &:focus { + border: border-width('base') solid var(--p-border-critical); + @include focus-ring($style: 'focused'); + } + + &:active { + border: border-width('base') solid var(--p-border-critical); + background: var(--p-surface-critical-subdued); + } + + &.disabled { + border: border-width('base') solid var(--p-border-critical-disabled); + background: transparent; + color: var(--p-interactive-critical-disabled); + } + + &.pressed { + background: var(--p-surface-critical-subdued); + box-shadow: border-width('base') solid var(--p-border-critical); + color: var(--p-interactive-critical); + } } } -} - -/** - * SHARED: forms - */ - -@mixin unstyled-input { - margin: 0; - padding: 0; - width: 100%; - background-color: transparent; - appearance: none; - - &:focus { - outline: 0; + + @mixin button-outline-disabled($outline-color) { + background: transparent; + box-shadow: none; } - - &::-moz-focus-outer { - border: 0; + + @mixin button-full-width { + display: flex; + width: 100%; } -} - -@mixin range-track-selectors { - &::-ms-track { - @include high-contrast-outline; - @content; + + @mixin plain-button-backdrop { + padding: 2px 5px; + margin: -2px -5px; + background: var(--p-action-secondary-hovered); + border-radius: border-radius(); } - - &::-moz-range-track { - @content; + + @mixin unstyled-button() { + appearance: none; + margin: 0; + padding: 0; + background: none; + border: none; + font-size: inherit; + line-height: inherit; + color: inherit; + cursor: pointer; + + &:focus { + outline: none; + } } - - &::-webkit-slider-runnable-track { - @content; + + /** + * SHARED: controls + */ + + @function control-height() { + @return rem(36px); + } + + @function control-slim-height() { + @return rem(28px); + } + + @function control-vertical-padding() { + @return (control-height() - line-height(input) - rem(2px)) / 2; + } + + @function control-icon-transition() { + @return transform duration(fast) easing(in); + } + + @mixin control-backdrop($style: base) { + @if $style == base { + position: relative; + border: var(--p-control-border-width) solid var(--p-border); + background-color: var(--p-surface); + border-radius: var(--p-border-radius-base); + + &::before { + content: ''; + position: absolute; + top: calc(-1 * var(--p-control-border-width)); + right: calc(-1 * var(--p-control-border-width)); + bottom: calc(-1 * var(--p-control-border-width)); + left: calc(-1 * var(--p-control-border-width)); + border-radius: var(--p-border-radius-base); + background-color: var(--p-interactive); + opacity: 0; + transform: scale(0.25); + transition: opacity duration(fast) var(--p-ease), + transform duration(fast) var(--p-ease); + } + + &.hover, + &:hover { + cursor: pointer; + border-color: var(--p-border-hovered); + } + } @else if $style == active { + border-color: var(--p-interactive); + + &::before { + opacity: 1; + transform: scale(1); + @media (-ms-high-contrast: active) { + border: 2px solid ms-high-contrast-color('text'); + } + } + } @else if $style == disabled { + border-color: var(--p-border-disabled); + + &::before { + background-color: var(--p-action-secondary-disabled); + } + + &:hover { + cursor: default; + } + } @else if $style == error { + border-color: var(--p-border-critical); + background-color: var(--p-surface-critical); + + &.hover, + &:hover { + border-color: var(--p-border-critical); + } + + &::before { + background-color: var(--p-border-critical); + } + } } -} - -@mixin range-thumb-selectors { - &::-ms-thumb { - @content; + + /** + * SHARED: forms + */ + + @mixin unstyled-input { + margin: 0; + padding: 0; + width: 100%; + background-color: transparent; + appearance: none; + + &:focus { + outline: 0; + } + + &::-moz-focus-outer { + border: 0; + } } - - &::-moz-range-thumb { - @content; + + @mixin range-track-selectors { + &::-ms-track { + @include high-contrast-outline; + @content; + } + + &::-moz-range-track { + @content; + } + + &::-webkit-slider-runnable-track { + @content; + } } - - &::-webkit-slider-thumb { - @content; + + @mixin range-thumb-selectors { + &::-ms-thumb { + @content; + } + + &::-moz-range-thumb { + @content; + } + + &::-webkit-slider-thumb { + @content; + } } -} - -/** + + /** * SHARED: icons */ - -@function icon-size() { - @return rem(20px); -} - -@mixin recolor-icon( - $fill-color: null, - $secondary-color: null, - $filter-color: null -) { - svg { - fill: $fill-color; - color: $secondary-color; - } - - img { - filter: $filter-color; - } -} - -@mixin color-icon($value, $hue: base) { - svg { - fill: color($value, $hue); + + @function icon-size() { + @return rem(20px); + } + + @mixin recolor-icon( + $fill-color: null, + $secondary-color: null, + $filter-color: null + ) { + svg { + fill: $fill-color; + color: $secondary-color; + } + + img { + filter: $filter-color; + } } - - img { - filter: filter($value, $hue); + + @mixin color-icon($value, $hue: base) { + svg { + fill: color($value, $hue); + } + + img { + filter: filter($value, $hue); + } } -} - -/** + + /** * SHARED: layout */ - -/// To be used on flex items. Resolves some common layout issues, such as -/// text truncation not respecting padding or breaking out of container. -/// https://css-tricks.com/flexbox-truncated-text/ - -@mixin layout-flex-fix { - min-width: 0; - max-width: 100%; -} - -/// Returns a safe-area-inset for iPhone X screen obtrusions. -/// -/// @param {String} $property - The property name i.e. padding-left. -/// @param {Space} $spacing - The spacing value to be added to the safe-area -/// value. i.e. spacing(). -/// @param {string} $area - The area where the inset is to be added. i.e. left -/// -/// If overriding an existing padding / margin that value should be used as -/// $spacing. -@mixin safe-area-for($property, $spacing, $area) { - // stylelint-disable-next-line scss/dimension-no-non-numeric-values - $spacing: if($spacing == 0, #{$spacing}px, $spacing); - #{$property}: #{$spacing}; - #{$property}: calc(#{$spacing} + constant(safe-area-inset-#{$area})); - #{$property}: calc(#{$spacing} + env(safe-area-inset-#{$area})); -} - -@mixin after-topbar-sheet { - @include breakpoint-after(450px) { - @content; + + /// To be used on flex items. Resolves some common layout issues, such as + /// text truncation not respecting padding or breaking out of container. + /// https://css-tricks.com/flexbox-truncated-text/ + + @mixin layout-flex-fix { + min-width: 0; + max-width: 100%; + } + + /// Returns a safe-area-inset for iPhone X screen obtrusions. + /// + /// @param {String} $property - The property name i.e. padding-left. + /// @param {Space} $spacing - The spacing value to be added to the safe-area + /// value. i.e. spacing(). + /// @param {string} $area - The area where the inset is to be added. i.e. left + /// + /// If overriding an existing padding / margin that value should be used as + /// $spacing. + @mixin safe-area-for($property, $spacing, $area) { + // stylelint-disable-next-line scss/dimension-no-non-numeric-values + $spacing: if($spacing == 0, #{$spacing}px, $spacing); + #{$property}: #{$spacing}; + #{$property}: calc(#{$spacing} + constant(safe-area-inset-#{$area})); + #{$property}: calc(#{$spacing} + env(safe-area-inset-#{$area})); + } + + @mixin after-topbar-sheet { + @include breakpoint-after(450px) { + @content; + } } -} - -/** + + /** * SHARED: links */ - -@mixin unstyled-link() { - color: inherit; - text-decoration: none; - - &:visited { + + @mixin unstyled-link() { color: inherit; + text-decoration: none; + + &:visited { + color: inherit; + } } -} - -/** + + /** * SHARED: lists */ - -@mixin unstyled-list { - margin: 0; - padding: 0; - list-style: none; -} - -/** + + @mixin unstyled-list { + margin: 0; + padding: 0; + list-style: none; + } + + /** * SHARED: page */ - -$actions-vertical-spacing: spacing(tight); - -@mixin page-padding-not-fully-condensed { - padding: 0 spacing(loose); -} - -@mixin page-padding-not-partially-condensed { - padding: 0 spacing(extra-loose); -} - -@mixin page-layout { - margin: 0 auto; - padding: 0; - max-width: $page-max-width; - - @include page-content-when-not-fully-condensed { - @include page-padding-not-fully-condensed; - } - - @include page-content-when-not-partially-condensed { - @include page-padding-not-partially-condensed; - } -} - -@mixin page-content-layout { - margin: spacing(tight) 0; - - @include page-content-when-not-partially-condensed { - margin-top: spacing(loose); + + $actions-vertical-spacing: spacing(tight); + + @mixin page-padding-not-fully-condensed { + padding: 0 spacing(loose); + } + + @mixin page-padding-not-partially-condensed { + padding: 0 spacing(extra-loose); + } + + @mixin page-layout { + margin: 0 auto; + padding: 0; + max-width: $page-max-width; + + @include page-content-when-not-fully-condensed { + @include page-padding-not-fully-condensed; + } + + @include page-content-when-not-partially-condensed { + @include page-padding-not-partially-condensed; + } } -} - -@mixin page-title-layout { - @include layout-flex-fix; - @include text-breakword; - display: flex; - align-items: baseline; - flex-wrap: wrap; - margin-top: -1 * spacing(tight); - margin-left: -1 * spacing(tight); - - > * { - margin-top: spacing(tight); - margin-left: spacing(tight); + + @mixin page-content-layout { + margin: spacing(tight) 0; + + @include page-content-when-not-partially-condensed { + margin-top: spacing(loose); + } } -} - -@mixin page-header-layout { - padding: spacing(); - - @include page-content-when-not-fully-condensed { - padding-left: 0; - padding-right: 0; + + @mixin page-title-layout { + @include layout-flex-fix; + @include text-breakword; + display: flex; + align-items: baseline; + flex-wrap: wrap; + margin-top: -1 * spacing(tight); + margin-left: -1 * spacing(tight); + + > * { + margin-top: spacing(tight); + margin-left: spacing(tight); + } } - - @include page-content-when-not-partially-condensed { - padding: spacing(loose) 0; + + @mixin page-header-layout { + padding: spacing(); + + @include page-content-when-not-fully-condensed { + padding-left: 0; + padding-right: 0; + } + + @include page-content-when-not-partially-condensed { + padding: spacing(loose) 0; + } } -} - -@mixin page-header-has-navigation { - padding-top: spacing(); -} - -@mixin page-header-without-navigation { - margin-top: unset; -} - -@mixin page-header-has-secondary-actions { - padding-top: spacing(); -} - -@mixin page-actions-layout { - display: flex; - justify-content: flex-start; - align-items: center; - margin-top: 2 * $actions-vertical-spacing; - - @include page-content-when-not-fully-condensed { - margin-top: $actions-vertical-spacing; + + @mixin page-header-has-navigation { + padding-top: spacing(); + } + + @mixin page-header-without-navigation { + margin-top: unset; + } + + @mixin page-header-has-secondary-actions { + padding-top: spacing(); + } + + @mixin page-actions-layout { + display: flex; + justify-content: flex-start; + align-items: center; + margin-top: 2 * $actions-vertical-spacing; + + @include page-content-when-not-fully-condensed { + margin-top: $actions-vertical-spacing; + } } -} - -/** + + /** * SHARED: typography */ - -$typography-condensed: em(640px); - -@mixin when-typography-not-condensed { - @include breakpoint-after($typography-condensed) { - @content; + + $typography-condensed: em(640px); + + @mixin when-typography-not-condensed { + @include breakpoint-after($typography-condensed) { + @content; + } } -} - -@mixin when-typography-condensed { - @include breakpoint-before($typography-condensed) { - @content; + + @mixin when-typography-condensed { + @include breakpoint-before($typography-condensed) { + @content; + } } -} - -@mixin text-style-caption { - font-size: font-size(caption); - font-weight: 400; - line-height: line-height(caption); - - @include when-typography-not-condensed { - font-size: font-size(caption, large-screen); - line-height: line-height(caption, large-screen); + + @mixin text-style-caption { + font-size: font-size(caption); + font-weight: 400; + line-height: line-height(caption); + + @include when-typography-not-condensed { + font-size: font-size(caption, large-screen); + line-height: line-height(caption, large-screen); + } } -} - -@mixin text-style-heading { - font-size: font-size(heading); - font-weight: 600; - line-height: line-height(heading); - - @include when-typography-not-condensed { - font-size: font-size(heading, large-screen); + + @mixin text-style-heading { + font-size: font-size(heading); + font-weight: 600; + line-height: line-height(heading); + + @include when-typography-not-condensed { + font-size: font-size(heading, large-screen); + } } -} - -@mixin text-style-subheading { - font-size: font-size(subheading); - font-weight: 600; - line-height: line-height(subheading); - text-transform: uppercase; - - @include when-typography-not-condensed { - font-size: font-size(subheading, large-screen); + + @mixin text-style-subheading { + font-size: font-size(subheading); + font-weight: 600; + line-height: line-height(subheading); + text-transform: uppercase; + + @include when-typography-not-condensed { + font-size: font-size(subheading, large-screen); + } } -} - -@mixin text-style-input { - font-size: font-size(input); - font-weight: 400; - line-height: line-height(input); - border: none; - - text-transform: initial; - letter-spacing: initial; - - @include when-typography-not-condensed { - font-size: font-size(input, large-screen); + + @mixin text-style-input { + font-size: font-size(input); + font-weight: 400; + line-height: line-height(input); + border: none; + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(input, large-screen); + } } -} - -@mixin text-style-body { - font-size: font-size(body); - font-weight: 400; - line-height: line-height(body); - - text-transform: initial; - letter-spacing: initial; - - @include when-typography-not-condensed { - font-size: font-size(body, large-screen); + + @mixin text-style-body { + font-size: font-size(body); + font-weight: 400; + line-height: line-height(body); + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(body, large-screen); + } } -} - -@mixin text-style-button { - font-size: font-size(button); - font-weight: var(--p-button-font-weight); - line-height: line-height(button); - - text-transform: initial; - letter-spacing: initial; - - @include when-typography-not-condensed { - font-size: font-size(button, large-screen); + + @mixin text-style-button { + font-size: font-size(button); + font-weight: var(--p-button-font-weight); + line-height: line-height(button); + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(button, large-screen); + } } -} - -@mixin text-style-button-large { - font-size: font-size(button-large); - font-weight: var(--p-button-font-weight); - line-height: line-height(button-large); - - text-transform: initial; - letter-spacing: initial; - - @include when-typography-not-condensed { - font-size: font-size(button-large, large-screen); + + @mixin text-style-button-large { + font-size: font-size(button-large); + font-weight: var(--p-button-font-weight); + line-height: line-height(button-large); + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(button-large, large-screen); + } } -} - -@mixin text-style-display-x-large { - font-size: font-size(display-x-large); - font-weight: 600; - line-height: line-height(display-x-large); - - @include when-typography-not-condensed { - font-size: font-size(display-x-large, large-screen); - line-height: line-height(display-x-large, large-screen); + + @mixin text-style-display-x-large { + font-size: font-size(display-x-large); + font-weight: 600; + line-height: line-height(display-x-large); + + @include when-typography-not-condensed { + font-size: font-size(display-x-large, large-screen); + line-height: line-height(display-x-large, large-screen); + } } -} - -@mixin text-style-display-large { - font-size: font-size(display-large); - font-weight: 600; - line-height: line-height(display-large); - - @include when-typography-not-condensed { - font-size: font-size(display-large, large-screen); - line-height: line-height(display-large, large-screen); + + @mixin text-style-display-large { + font-size: font-size(display-large); + font-weight: 600; + line-height: line-height(display-large); + + @include when-typography-not-condensed { + font-size: font-size(display-large, large-screen); + line-height: line-height(display-large, large-screen); + } } -} - -@mixin text-style-display-medium { - font-size: font-size(display-medium); - font-weight: 400; - line-height: line-height(display-medium); - - @include when-typography-not-condensed { - font-size: font-size(display-medium, large-screen); - line-height: line-height(display-medium, large-screen); + + @mixin text-style-display-medium { + font-size: font-size(display-medium); + font-weight: 400; + line-height: line-height(display-medium); + + @include when-typography-not-condensed { + font-size: font-size(display-medium, large-screen); + line-height: line-height(display-medium, large-screen); + } } -} - -@mixin text-style-display-small { - font-size: font-size(display-small); - font-weight: 400; - line-height: line-height(display-small); - - @include when-typography-not-condensed { - font-size: font-size(display-small, large-screen); - line-height: line-height(display-small, large-screen); + + @mixin text-style-display-small { + font-size: font-size(display-small); + font-weight: 400; + line-height: line-height(display-small); + + @include when-typography-not-condensed { + font-size: font-size(display-small, large-screen); + line-height: line-height(display-small, large-screen); + } } -} - -@mixin text-emphasis-subdued($for-background: null) { - color: var(--p-text-subdued); -} - -@mixin text-emphasis-strong { - font-weight: 600; -} - -@mixin text-emphasis-normal($for-background: null) { - font-weight: 400; - color: var(--p-text); -} - -@mixin text-breakword { - word-wrap: break-word; - word-break: break-word; - overflow-wrap: break-word; -} - -@mixin truncate { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -@mixin print-hidden { - @media print { - // stylelint-disable-next-line declaration-no-important - display: none !important; + + @mixin text-emphasis-subdued($for-background: null) { + color: var(--p-text-subdued); + } + + @mixin text-emphasis-strong { + font-weight: 600; + } + + @mixin text-emphasis-normal($for-background: null) { + font-weight: 400; + color: var(--p-text); + } + + @mixin text-breakword { + word-wrap: break-word; + word-break: break-word; + overflow-wrap: break-word; + } + + @mixin truncate { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + @mixin print-hidden { + @media print { + // stylelint-disable-next-line declaration-no-important + display: none !important; + } } -} - -/** + + /** * SHARED: skeleton */ - -/// Used to create the shimmer effect of skeleton components -$skeleton-shimmer-duration: duration(slower) * 2; - -// Used by both Thumbnail and SkeletonThumbnail -$small-thumbnail-size: rem(40px); -$medium-thumbnail-size: rem(60px); -$large-thumbnail-size: rem(80px); - -$thumbnail-sizes: ( - small: $small-thumbnail-size, - medium: $medium-thumbnail-size, - large: $large-thumbnail-size, -); - -@function thumbnail-size($size) { - @return map-get($thumbnail-sizes, $size); -} - -@mixin skeleton-shimmer { - // This is a global animation, defined in /src/components/AppProvider/AppProvider.scss - // See that file for why this is referenced as a custom property instead of - // by name - animation: var(--polaris-animation-skeleton-shimmer) - $skeleton-shimmer-duration linear infinite alternate; - will-change: opacity; - - @media (prefers-reduced-motion) { - animation: none; + + /// Used to create the shimmer effect of skeleton components + $skeleton-shimmer-duration: duration(slower) * 2; + + // Used by both Thumbnail and SkeletonThumbnail + $small-thumbnail-size: rem(40px); + $medium-thumbnail-size: rem(60px); + $large-thumbnail-size: rem(80px); + + $thumbnail-sizes: ( + small: $small-thumbnail-size, + medium: $medium-thumbnail-size, + large: $large-thumbnail-size, + ); + + @function thumbnail-size($size) { + @return map-get($thumbnail-sizes, $size); + } + + @mixin skeleton-shimmer { + // This is a global animation, defined in /src/components/AppProvider/AppProvider.scss + // See that file for why this is referenced as a custom property instead of + // by name + animation: var(--polaris-animation-skeleton-shimmer) + $skeleton-shimmer-duration linear infinite alternate; + will-change: opacity; + + @media (prefers-reduced-motion) { + animation: none; + } } -} - -@mixin skeleton-content { - position: relative; - - &::after { - content: ''; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: block; - background-color: var(--p-surface-neutral); - border-radius: border-radius(); - - @media screen and (-ms-high-contrast: active) { - background-color: ms-high-contrast-color('disabled-text'); + + @mixin skeleton-content { + position: relative; + + &::after { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: block; + background-color: var(--p-surface-neutral); + border-radius: border-radius(); + + @media screen and (-ms-high-contrast: active) { + background-color: ms-high-contrast-color('disabled-text'); + } } } -} - -@mixin skeleton-page-secondary-actions-layout { - margin-top: spacing(tight); - display: flex; - flex-direction: row-reverse; - justify-content: flex-end; - align-items: center; -} - -@mixin skeleton-page-header-layout { - padding-bottom: spacing(tight); -} - -/** + + @mixin skeleton-page-secondary-actions-layout { + margin-top: spacing(tight); + display: flex; + flex-direction: row-reverse; + justify-content: flex-end; + align-items: center; + } + + @mixin skeleton-page-header-layout { + padding-bottom: spacing(tight); + } + + /** * SHARED: interaction-state */ - -/// Sets the background-image and box-shadow for single or multiple given -/// interaction states. -/// -/// @param {argList} $interaction-states... - Accepts single or multiple -/// interactions states. -@mixin state($interaction-states...) { - $backgrounds: (); - - @each $state in $interaction-states { - $colors: color(state, $state); - $backgrounds: append( - $backgrounds, - linear-gradient($colors, $colors), - comma - ); - - @if $state == 'focused' { - box-shadow: inset rem(2px) 0 0 var(--p-focused); - } - - @if $state == 'focused-destructive' { - box-shadow: inset rem(2px) 0 0 var(--p-focused); + + /// Sets the background-image and box-shadow for single or multiple given + /// interaction states. + /// + /// @param {argList} $interaction-states... - Accepts single or multiple + /// interactions states. + @mixin state($interaction-states...) { + $backgrounds: (); + + @each $state in $interaction-states { + $colors: color(state, $state); + $backgrounds: append( + $backgrounds, + linear-gradient($colors, $colors), + comma + ); + + @if $state == 'focused' { + box-shadow: inset rem(2px) 0 0 var(--p-focused); + } + + @if $state == 'focused-destructive' { + box-shadow: inset rem(2px) 0 0 var(--p-focused); + } } + background-image: $backgrounds; } - background-image: $backgrounds; -} - -@mixin list-selected-indicator($offset: spacing(tight)) { - content: ''; - background-color: var(--p-interactive); - position: absolute; - top: 0; - left: -1 * $offset; - height: 100%; - display: block; - width: border-width(thicker); - border-top-right-radius: var(--p-border-radius-base); - border-bottom-right-radius: var(--p-border-radius-base); -} - -/** + + @mixin list-selected-indicator($offset: spacing(tight)) { + content: ''; + background-color: var(--p-interactive); + position: absolute; + top: 0; + left: -1 * $offset; + height: 100%; + display: block; + width: border-width(thicker); + border-top-right-radius: var(--p-border-radius-base); + border-bottom-right-radius: var(--p-border-radius-base); + } + + /** * SHARED: printing */ - -@mixin when-printing { - @media print { - @content; - } -} - -@mixin when-not-printing { - @media not print { - @content; + + @mixin when-printing { + @media print { + @content; + } } -} - -@mixin hidden-when-printing { - @include when-printing { - // We really, really don't want to see this thing when it is printed. - // stylelint-disable-next-line declaration-no-important - display: none !important; + + @mixin when-not-printing { + @media not print { + @content; + } } -} + + @mixin hidden-when-printing { + @include when-printing { + // We really, really don't want to see this thing when it is printed. + // stylelint-disable-next-line declaration-no-important + display: none !important; + } + } \ No newline at end of file From b6050df61757cae39c546ffc5fabf54e3bd903b0 Mon Sep 17 00:00:00 2001 From: aveline Date: Wed, 9 Feb 2022 09:59:31 -0800 Subject: [PATCH 4/6] Prefix file name with legacy --- ...laris-v8-public-api.scss => legacy-polaris-v8-public-api.scss} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename documentation/guides/{polaris-v8-public-api.scss => legacy-polaris-v8-public-api.scss} (100%) diff --git a/documentation/guides/polaris-v8-public-api.scss b/documentation/guides/legacy-polaris-v8-public-api.scss similarity index 100% rename from documentation/guides/polaris-v8-public-api.scss rename to documentation/guides/legacy-polaris-v8-public-api.scss From 2e3bd57a1af7d52a84a85ebb168f23ab1703a036 Mon Sep 17 00:00:00 2001 From: aveline Date: Wed, 9 Feb 2022 10:42:11 -0800 Subject: [PATCH 5/6] Update legacy-polaris-v8-public-api.scss --- .../guides/legacy-polaris-v8-public-api.scss | 4027 ++++++++--------- 1 file changed, 1989 insertions(+), 2038 deletions(-) diff --git a/documentation/guides/legacy-polaris-v8-public-api.scss b/documentation/guides/legacy-polaris-v8-public-api.scss index 34411e005c5..02ce7ea4ca5 100644 --- a/documentation/guides/legacy-polaris-v8-public-api.scss +++ b/documentation/guides/legacy-polaris-v8-public-api.scss @@ -1,2160 +1,2111 @@ -/** - * Polaris Tokens: colors.color-map - */ - - $polaris-colors: ( - 'purple': ( - 'text': rgb(80, 73, 90), - 'darker': rgb(35, 0, 81), - 'dark': rgb(80, 36, 143), - 'base': rgb(156, 106, 222), - 'light': rgb(227, 208, 255), - 'lighter': rgb(246, 240, 253), - ), - 'indigo': ( - 'text': rgb(62, 65, 85), - 'darker': rgb(0, 6, 57), - 'dark': rgb(32, 46, 120), - 'base': rgb(92, 106, 196), - 'light': rgb(179, 188, 245), - 'lighter': rgb(244, 245, 250), - ), - 'blue': ( - 'text': rgb(62, 78, 87), - 'darker': rgb(0, 20, 41), - 'dark': rgb(8, 78, 138), - 'base': rgb(0, 111, 187), - 'light': rgb(180, 225, 250), - 'lighter': rgb(235, 245, 250), - ), - 'teal': ( - 'text': rgb(64, 83, 82), - 'darker': rgb(0, 49, 53), - 'dark': rgb(0, 132, 142), - 'base': rgb(71, 193, 191), - 'light': rgb(183, 236, 236), - 'lighter': rgb(224, 245, 245), - ), - 'green': ( - 'text': rgb(65, 79, 62), - 'darker': rgb(23, 54, 48), - 'dark': rgb(16, 128, 67), - 'base': rgb(80, 184, 60), - 'light': rgb(187, 229, 179), - 'lighter': rgb(227, 241, 223), - ), - 'yellow': ( - 'text': rgb(89, 81, 48), - 'darker': rgb(87, 59, 0), - 'dark': rgb(138, 97, 22), - 'base': rgb(238, 194, 0), - 'light': rgb(255, 234, 138), - 'lighter': rgb(252, 241, 205), - ), - 'orange': ( - 'text': rgb(89, 68, 48), - 'darker': rgb(74, 21, 4), - 'dark': rgb(192, 87, 23), - 'base': rgb(244, 147, 66), - 'light': rgb(255, 197, 139), - 'lighter': rgb(252, 235, 219), - ), - 'red': ( - 'text': rgb(88, 60, 53), - 'darker': rgb(51, 1, 1), - 'dark': rgb(191, 7, 17), - 'base': rgb(222, 54, 24), - 'light': rgb(254, 173, 154), - 'lighter': rgb(251, 234, 229), - ), - 'ink': ( - 'base': rgb(33, 43, 54), - 'light': rgb(69, 79, 91), - 'lighter': rgb(99, 115, 129), - 'lightest': rgb(145, 158, 171), - ), - 'sky': ( - 'dark': rgb(196, 205, 213), - 'base': rgb(223, 227, 232), - 'light': rgb(244, 246, 248), - 'lighter': rgb(249, 250, 251), - ), - 'black': ( - 'base': rgb(0, 0, 0), - ), - 'white': ( - 'base': rgb(255, 255, 255), - ), - ); - - /** - * Polaris Tokens: color-filters.color-map - */ - - $polaris-color-filters: ( - 'purple': ( - 'text': brightness(0) saturate(100%) invert(29%) sepia(3%) saturate(2843%) - hue-rotate(223deg) brightness(92%) contrast(86%), - 'darker': brightness(0) saturate(100%) invert(8%) sepia(38%) saturate(6605%) - hue-rotate(265deg) brightness(99%) contrast(124%), - 'dark': brightness(0) saturate(100%) invert(12%) sepia(46%) saturate(4964%) - hue-rotate(258deg) brightness(101%) contrast(93%), - 'base': brightness(0) saturate(100%) invert(49%) sepia(77%) saturate(1864%) - hue-rotate(229deg) brightness(91%) contrast(91%), - 'light': brightness(0) saturate(100%) invert(82%) sepia(13%) saturate(1535%) - hue-rotate(203deg) brightness(103%) contrast(104%), - 'lighter': brightness(0) saturate(100%) invert(84%) sepia(15%) - saturate(135%) hue-rotate(219deg) brightness(110%) contrast(98%), - ), - 'indigo': ( - 'text': brightness(0) saturate(100%) invert(24%) sepia(11%) saturate(1035%) - hue-rotate(195deg) brightness(97%) contrast(94%), - 'darker': brightness(0) saturate(100%) invert(5%) sepia(81%) saturate(5060%) - hue-rotate(229deg) brightness(72%) contrast(111%), - 'dark': brightness(0) saturate(100%) invert(17%) sepia(28%) saturate(4409%) - hue-rotate(218deg) brightness(87%) contrast(98%), - 'base': brightness(0) saturate(100%) invert(45%) sepia(17%) saturate(1966%) - hue-rotate(194deg) brightness(88%) contrast(84%), - 'light': brightness(0) saturate(100%) invert(82%) sepia(37%) saturate(4261%) - hue-rotate(194deg) brightness(111%) contrast(92%), - 'lighter': brightness(0) saturate(100%) invert(100%) sepia(25%) - saturate(1090%) hue-rotate(179deg) brightness(100%) contrast(96%), - ), - 'blue': ( - 'text': brightness(0) saturate(100%) invert(27%) sepia(13%) saturate(709%) - hue-rotate(158deg) brightness(96%) contrast(89%), - 'darker': brightness(0) saturate(100%) invert(5%) sepia(33%) saturate(5606%) - hue-rotate(195deg) brightness(97%) contrast(102%), - 'dark': brightness(0) saturate(100%) invert(22%) sepia(70%) saturate(1308%) - hue-rotate(182deg) brightness(94%) contrast(101%), - 'base': brightness(0) saturate(100%) invert(19%) sepia(98%) saturate(2885%) - hue-rotate(190deg) brightness(99%) contrast(101%), - 'light': brightness(0) saturate(100%) invert(80%) sepia(7%) saturate(1832%) - hue-rotate(178deg) brightness(108%) contrast(96%), - 'lighter': brightness(0) saturate(100%) invert(100%) sepia(94%) - saturate(686%) hue-rotate(175deg) brightness(103%) contrast(96%), - ), - 'teal': ( - 'text': brightness(0) saturate(100%) invert(31%) sepia(11%) saturate(665%) - hue-rotate(128deg) brightness(94%) contrast(93%), - 'darker': brightness(0) saturate(100%) invert(15%) sepia(23%) - saturate(2237%) hue-rotate(141deg) brightness(96%) contrast(104%), - 'dark': brightness(0) saturate(100%) invert(28%) sepia(83%) saturate(3919%) - hue-rotate(168deg) brightness(93%) contrast(101%), - 'base': brightness(0) saturate(100%) invert(72%) sepia(8%) saturate(2838%) - hue-rotate(130deg) brightness(92%) contrast(87%), - 'light': brightness(0) saturate(100%) invert(95%) sepia(12%) saturate(683%) - hue-rotate(122deg) brightness(97%) contrast(91%), - 'lighter': brightness(0) saturate(100%) invert(87%) sepia(5%) - saturate(1124%) hue-rotate(173deg) brightness(114%) contrast(92%), - ), - 'green': ( - 'text': brightness(0) saturate(100%) invert(30%) sepia(8%) saturate(1010%) - hue-rotate(63deg) brightness(91%) contrast(91%), - 'darker': brightness(0) saturate(100%) invert(15%) sepia(32%) saturate(727%) - hue-rotate(118deg) brightness(93%) contrast(91%), - 'dark': brightness(0) saturate(100%) invert(18%) sepia(75%) saturate(6649%) - hue-rotate(155deg) brightness(97%) contrast(87%), - 'base': brightness(0) saturate(100%) invert(56%) sepia(10%) saturate(2637%) - hue-rotate(64deg) brightness(106%) contrast(91%), - 'light': brightness(0) saturate(100%) invert(93%) sepia(15%) saturate(599%) - hue-rotate(52deg) brightness(93%) contrast(93%), - 'lighter': brightness(0) saturate(100%) invert(92%) sepia(51%) - saturate(187%) hue-rotate(46deg) brightness(108%) contrast(89%), - ), - 'yellow': ( - 'text': brightness(0) saturate(100%) invert(28%) sepia(42%) saturate(413%) - hue-rotate(11deg) brightness(97%) contrast(91%), - 'darker': brightness(0) saturate(100%) invert(19%) sepia(75%) saturate(981%) - hue-rotate(17deg) brightness(103%) contrast(103%), - 'dark': brightness(0) saturate(100%) invert(37%) sepia(51%) saturate(709%) - hue-rotate(0deg) brightness(93%) contrast(89%), - 'base': brightness(0) saturate(100%) invert(65%) sepia(91%) saturate(530%) - hue-rotate(5deg) brightness(100%) contrast(100%), - 'light': brightness(0) saturate(100%) invert(77%) sepia(72%) saturate(246%) - hue-rotate(355deg) brightness(103%) contrast(107%), - 'lighter': brightness(0) saturate(100%) invert(88%) sepia(27%) - saturate(234%) hue-rotate(357deg) brightness(103%) contrast(98%), - ), - 'orange': ( - 'text': brightness(0) saturate(100%) invert(23%) sepia(18%) saturate(1092%) - hue-rotate(348deg) brightness(99%) contrast(84%), - 'darker': brightness(0) saturate(100%) invert(9%) sepia(83%) saturate(1926%) - hue-rotate(356deg) brightness(98%) contrast(99%), - 'dark': brightness(0) saturate(100%) invert(29%) sepia(94%) saturate(1431%) - hue-rotate(5deg) brightness(96%) contrast(82%), - 'base': brightness(0) saturate(100%) invert(54%) sepia(86%) saturate(416%) - hue-rotate(340deg) brightness(105%) contrast(91%), - 'light': brightness(0) saturate(100%) invert(77%) sepia(39%) saturate(483%) - hue-rotate(335deg) brightness(101%) contrast(103%), - 'lighter': brightness(0) saturate(100%) invert(93%) sepia(11%) - saturate(918%) hue-rotate(312deg) brightness(107%) contrast(98%), - ), - 'red': ( - 'text': brightness(0) saturate(100%) invert(22%) sepia(9%) saturate(2068%) - hue-rotate(325deg) brightness(92%) contrast(83%), - 'darker': brightness(0) saturate(100%) invert(12%) sepia(100%) - saturate(5699%) hue-rotate(353deg) brightness(75%) contrast(101%), - 'dark': brightness(0) saturate(100%) invert(12%) sepia(100%) saturate(5699%) - hue-rotate(353deg) brightness(75%) contrast(101%), - 'base': brightness(0) saturate(100%) invert(28%) sepia(67%) saturate(3622%) - hue-rotate(353deg) brightness(89%) contrast(95%), - 'light': brightness(0) saturate(100%) invert(80%) sepia(9%) saturate(2561%) - hue-rotate(313deg) brightness(101%) contrast(99%), - 'lighter': brightness(0) saturate(100%) invert(89%) sepia(21%) - saturate(137%) hue-rotate(324deg) brightness(102%) contrast(97%), - ), - 'ink': ( - 'base': brightness(0) saturate(100%) invert(10%) sepia(10%) saturate(2259%) - hue-rotate(171deg) brightness(99%) contrast(84%), - 'light': brightness(0) saturate(100%) invert(32%) sepia(9%) saturate(1069%) - hue-rotate(173deg) brightness(83%) contrast(84%), - 'lighter': brightness(0) saturate(100%) invert(45%) sepia(8%) saturate(825%) - hue-rotate(166deg) brightness(95%) contrast(90%), - 'lightest': brightness(0) saturate(100%) invert(68%) sepia(18%) - saturate(246%) hue-rotate(169deg) brightness(88%) contrast(90%), - ), - 'sky': ( - 'dark': brightness(0) saturate(100%) invert(86%) sepia(4%) saturate(502%) - hue-rotate(167deg) brightness(96%) contrast(91%), - 'base': brightness(0) saturate(100%) invert(100%) sepia(95%) saturate(336%) - hue-rotate(175deg) brightness(97%) contrast(87%), - 'light': brightness(0) saturate(100%) invert(99%) sepia(12%) saturate(467%) - hue-rotate(174deg) brightness(99%) contrast(96%), - 'lighter': brightness(0) saturate(100%) invert(99%) sepia(1%) saturate(159%) - hue-rotate(170deg) brightness(99%) contrast(99%), - ), - 'black': ( - 'base': brightness(0) saturate(100%), - ), - 'white': ( - 'base': brightness(0) saturate(100%) invert(100%), - ), - 'icon': ( - 'base': brightness(0) saturate(100%) invert(36%) sepia(13%) saturate(137%) - hue-rotate(169deg) brightness(95%) contrast(87%), - ), - 'action': ( - 'base': brightness(0) saturate(100%) invert(20%) sepia(59%) saturate(5557%) - hue-rotate(162deg) brightness(95%) contrast(101%), - ), - ); - - /** - * Polaris Tokens: duration.map - */ - - $polaris-duration-map: ( - 'duration-none': ( - 0, - ), - 'duration-fast': ( - 100ms, - ), - 'duration-base': ( - 200ms, - ), - 'duration-slow': ( - 300ms, - ), - 'duration-slower': ( - 400ms, - ), - 'duration-slowest': ( - 500ms, - ), - ); - - /** - * Polaris Tokens: spacing.spacing-map - */ - - $polaris-spacing: ( - 'none': 0, - 'extra-tight': 4px, - 'tight': 8px, - 'base-tight': 12px, - 'base': 16px, - 'loose': 20px, - 'extra-loose': 32px, - ); - - /** - * FOUNDATION: accessibility - */ - - @mixin high-contrast-outline($border-width: border-width()) { - outline: $border-width solid transparent; - @content; - } - - @mixin high-contrast-border($border-width: border-width()) { - border: $border-width solid transparent; - @content; +// Deprecated scss functions and mixins + +/* Polaris Tokens: colors.color-map */ + +$polaris-colors: ( + 'purple': ( + 'text': rgb(80, 73, 90), + 'darker': rgb(35, 0, 81), + 'dark': rgb(80, 36, 143), + 'base': rgb(156, 106, 222), + 'light': rgb(227, 208, 255), + 'lighter': rgb(246, 240, 253), + ), + 'indigo': ( + 'text': rgb(62, 65, 85), + 'darker': rgb(0, 6, 57), + 'dark': rgb(32, 46, 120), + 'base': rgb(92, 106, 196), + 'light': rgb(179, 188, 245), + 'lighter': rgb(244, 245, 250), + ), + 'blue': ( + 'text': rgb(62, 78, 87), + 'darker': rgb(0, 20, 41), + 'dark': rgb(8, 78, 138), + 'base': rgb(0, 111, 187), + 'light': rgb(180, 225, 250), + 'lighter': rgb(235, 245, 250), + ), + 'teal': ( + 'text': rgb(64, 83, 82), + 'darker': rgb(0, 49, 53), + 'dark': rgb(0, 132, 142), + 'base': rgb(71, 193, 191), + 'light': rgb(183, 236, 236), + 'lighter': rgb(224, 245, 245), + ), + 'green': ( + 'text': rgb(65, 79, 62), + 'darker': rgb(23, 54, 48), + 'dark': rgb(16, 128, 67), + 'base': rgb(80, 184, 60), + 'light': rgb(187, 229, 179), + 'lighter': rgb(227, 241, 223), + ), + 'yellow': ( + 'text': rgb(89, 81, 48), + 'darker': rgb(87, 59, 0), + 'dark': rgb(138, 97, 22), + 'base': rgb(238, 194, 0), + 'light': rgb(255, 234, 138), + 'lighter': rgb(252, 241, 205), + ), + 'orange': ( + 'text': rgb(89, 68, 48), + 'darker': rgb(74, 21, 4), + 'dark': rgb(192, 87, 23), + 'base': rgb(244, 147, 66), + 'light': rgb(255, 197, 139), + 'lighter': rgb(252, 235, 219), + ), + 'red': ( + 'text': rgb(88, 60, 53), + 'darker': rgb(51, 1, 1), + 'dark': rgb(191, 7, 17), + 'base': rgb(222, 54, 24), + 'light': rgb(254, 173, 154), + 'lighter': rgb(251, 234, 229), + ), + 'ink': ( + 'base': rgb(33, 43, 54), + 'light': rgb(69, 79, 91), + 'lighter': rgb(99, 115, 129), + 'lightest': rgb(145, 158, 171), + ), + 'sky': ( + 'dark': rgb(196, 205, 213), + 'base': rgb(223, 227, 232), + 'light': rgb(244, 246, 248), + 'lighter': rgb(249, 250, 251), + ), + 'black': ( + 'base': rgb(0, 0, 0), + ), + 'white': ( + 'base': rgb(255, 255, 255), + ), +); + +/* Polaris Tokens: color-filters.color-map */ + +$polaris-color-filters: ( + 'purple': ( + 'text': brightness(0) saturate(100%) invert(29%) sepia(3%) saturate(2843%) + hue-rotate(223deg) brightness(92%) contrast(86%), + 'darker': brightness(0) saturate(100%) invert(8%) sepia(38%) saturate(6605%) + hue-rotate(265deg) brightness(99%) contrast(124%), + 'dark': brightness(0) saturate(100%) invert(12%) sepia(46%) saturate(4964%) + hue-rotate(258deg) brightness(101%) contrast(93%), + 'base': brightness(0) saturate(100%) invert(49%) sepia(77%) saturate(1864%) + hue-rotate(229deg) brightness(91%) contrast(91%), + 'light': brightness(0) saturate(100%) invert(82%) sepia(13%) saturate(1535%) + hue-rotate(203deg) brightness(103%) contrast(104%), + 'lighter': brightness(0) saturate(100%) invert(84%) sepia(15%) + saturate(135%) hue-rotate(219deg) brightness(110%) contrast(98%), + ), + 'indigo': ( + 'text': brightness(0) saturate(100%) invert(24%) sepia(11%) saturate(1035%) + hue-rotate(195deg) brightness(97%) contrast(94%), + 'darker': brightness(0) saturate(100%) invert(5%) sepia(81%) saturate(5060%) + hue-rotate(229deg) brightness(72%) contrast(111%), + 'dark': brightness(0) saturate(100%) invert(17%) sepia(28%) saturate(4409%) + hue-rotate(218deg) brightness(87%) contrast(98%), + 'base': brightness(0) saturate(100%) invert(45%) sepia(17%) saturate(1966%) + hue-rotate(194deg) brightness(88%) contrast(84%), + 'light': brightness(0) saturate(100%) invert(82%) sepia(37%) saturate(4261%) + hue-rotate(194deg) brightness(111%) contrast(92%), + 'lighter': brightness(0) saturate(100%) invert(100%) sepia(25%) + saturate(1090%) hue-rotate(179deg) brightness(100%) contrast(96%), + ), + 'blue': ( + 'text': brightness(0) saturate(100%) invert(27%) sepia(13%) saturate(709%) + hue-rotate(158deg) brightness(96%) contrast(89%), + 'darker': brightness(0) saturate(100%) invert(5%) sepia(33%) saturate(5606%) + hue-rotate(195deg) brightness(97%) contrast(102%), + 'dark': brightness(0) saturate(100%) invert(22%) sepia(70%) saturate(1308%) + hue-rotate(182deg) brightness(94%) contrast(101%), + 'base': brightness(0) saturate(100%) invert(19%) sepia(98%) saturate(2885%) + hue-rotate(190deg) brightness(99%) contrast(101%), + 'light': brightness(0) saturate(100%) invert(80%) sepia(7%) saturate(1832%) + hue-rotate(178deg) brightness(108%) contrast(96%), + 'lighter': brightness(0) saturate(100%) invert(100%) sepia(94%) + saturate(686%) hue-rotate(175deg) brightness(103%) contrast(96%), + ), + 'teal': ( + 'text': brightness(0) saturate(100%) invert(31%) sepia(11%) saturate(665%) + hue-rotate(128deg) brightness(94%) contrast(93%), + 'darker': brightness(0) saturate(100%) invert(15%) sepia(23%) + saturate(2237%) hue-rotate(141deg) brightness(96%) contrast(104%), + 'dark': brightness(0) saturate(100%) invert(28%) sepia(83%) saturate(3919%) + hue-rotate(168deg) brightness(93%) contrast(101%), + 'base': brightness(0) saturate(100%) invert(72%) sepia(8%) saturate(2838%) + hue-rotate(130deg) brightness(92%) contrast(87%), + 'light': brightness(0) saturate(100%) invert(95%) sepia(12%) saturate(683%) + hue-rotate(122deg) brightness(97%) contrast(91%), + 'lighter': brightness(0) saturate(100%) invert(87%) sepia(5%) + saturate(1124%) hue-rotate(173deg) brightness(114%) contrast(92%), + ), + 'green': ( + 'text': brightness(0) saturate(100%) invert(30%) sepia(8%) saturate(1010%) + hue-rotate(63deg) brightness(91%) contrast(91%), + 'darker': brightness(0) saturate(100%) invert(15%) sepia(32%) saturate(727%) + hue-rotate(118deg) brightness(93%) contrast(91%), + 'dark': brightness(0) saturate(100%) invert(18%) sepia(75%) saturate(6649%) + hue-rotate(155deg) brightness(97%) contrast(87%), + 'base': brightness(0) saturate(100%) invert(56%) sepia(10%) saturate(2637%) + hue-rotate(64deg) brightness(106%) contrast(91%), + 'light': brightness(0) saturate(100%) invert(93%) sepia(15%) saturate(599%) + hue-rotate(52deg) brightness(93%) contrast(93%), + 'lighter': brightness(0) saturate(100%) invert(92%) sepia(51%) + saturate(187%) hue-rotate(46deg) brightness(108%) contrast(89%), + ), + 'yellow': ( + 'text': brightness(0) saturate(100%) invert(28%) sepia(42%) saturate(413%) + hue-rotate(11deg) brightness(97%) contrast(91%), + 'darker': brightness(0) saturate(100%) invert(19%) sepia(75%) saturate(981%) + hue-rotate(17deg) brightness(103%) contrast(103%), + 'dark': brightness(0) saturate(100%) invert(37%) sepia(51%) saturate(709%) + hue-rotate(0deg) brightness(93%) contrast(89%), + 'base': brightness(0) saturate(100%) invert(65%) sepia(91%) saturate(530%) + hue-rotate(5deg) brightness(100%) contrast(100%), + 'light': brightness(0) saturate(100%) invert(77%) sepia(72%) saturate(246%) + hue-rotate(355deg) brightness(103%) contrast(107%), + 'lighter': brightness(0) saturate(100%) invert(88%) sepia(27%) + saturate(234%) hue-rotate(357deg) brightness(103%) contrast(98%), + ), + 'orange': ( + 'text': brightness(0) saturate(100%) invert(23%) sepia(18%) saturate(1092%) + hue-rotate(348deg) brightness(99%) contrast(84%), + 'darker': brightness(0) saturate(100%) invert(9%) sepia(83%) saturate(1926%) + hue-rotate(356deg) brightness(98%) contrast(99%), + 'dark': brightness(0) saturate(100%) invert(29%) sepia(94%) saturate(1431%) + hue-rotate(5deg) brightness(96%) contrast(82%), + 'base': brightness(0) saturate(100%) invert(54%) sepia(86%) saturate(416%) + hue-rotate(340deg) brightness(105%) contrast(91%), + 'light': brightness(0) saturate(100%) invert(77%) sepia(39%) saturate(483%) + hue-rotate(335deg) brightness(101%) contrast(103%), + 'lighter': brightness(0) saturate(100%) invert(93%) sepia(11%) + saturate(918%) hue-rotate(312deg) brightness(107%) contrast(98%), + ), + 'red': ( + 'text': brightness(0) saturate(100%) invert(22%) sepia(9%) saturate(2068%) + hue-rotate(325deg) brightness(92%) contrast(83%), + 'darker': brightness(0) saturate(100%) invert(12%) sepia(100%) + saturate(5699%) hue-rotate(353deg) brightness(75%) contrast(101%), + 'dark': brightness(0) saturate(100%) invert(12%) sepia(100%) saturate(5699%) + hue-rotate(353deg) brightness(75%) contrast(101%), + 'base': brightness(0) saturate(100%) invert(28%) sepia(67%) saturate(3622%) + hue-rotate(353deg) brightness(89%) contrast(95%), + 'light': brightness(0) saturate(100%) invert(80%) sepia(9%) saturate(2561%) + hue-rotate(313deg) brightness(101%) contrast(99%), + 'lighter': brightness(0) saturate(100%) invert(89%) sepia(21%) + saturate(137%) hue-rotate(324deg) brightness(102%) contrast(97%), + ), + 'ink': ( + 'base': brightness(0) saturate(100%) invert(10%) sepia(10%) saturate(2259%) + hue-rotate(171deg) brightness(99%) contrast(84%), + 'light': brightness(0) saturate(100%) invert(32%) sepia(9%) saturate(1069%) + hue-rotate(173deg) brightness(83%) contrast(84%), + 'lighter': brightness(0) saturate(100%) invert(45%) sepia(8%) saturate(825%) + hue-rotate(166deg) brightness(95%) contrast(90%), + 'lightest': brightness(0) saturate(100%) invert(68%) sepia(18%) + saturate(246%) hue-rotate(169deg) brightness(88%) contrast(90%), + ), + 'sky': ( + 'dark': brightness(0) saturate(100%) invert(86%) sepia(4%) saturate(502%) + hue-rotate(167deg) brightness(96%) contrast(91%), + 'base': brightness(0) saturate(100%) invert(100%) sepia(95%) saturate(336%) + hue-rotate(175deg) brightness(97%) contrast(87%), + 'light': brightness(0) saturate(100%) invert(99%) sepia(12%) saturate(467%) + hue-rotate(174deg) brightness(99%) contrast(96%), + 'lighter': brightness(0) saturate(100%) invert(99%) sepia(1%) saturate(159%) + hue-rotate(170deg) brightness(99%) contrast(99%), + ), + 'black': ( + 'base': brightness(0) saturate(100%), + ), + 'white': ( + 'base': brightness(0) saturate(100%) invert(100%), + ), + 'icon': ( + 'base': brightness(0) saturate(100%) invert(36%) sepia(13%) saturate(137%) + hue-rotate(169deg) brightness(95%) contrast(87%), + ), + 'action': ( + 'base': brightness(0) saturate(100%) invert(20%) sepia(59%) saturate(5557%) + hue-rotate(162deg) brightness(95%) contrast(101%), + ), +); + +/* Polaris Tokens: duration.map */ + +$polaris-duration-map: ( + 'duration-none': ( + 0, + ), + 'duration-fast': ( + 100ms, + ), + 'duration-base': ( + 200ms, + ), + 'duration-slow': ( + 300ms, + ), + 'duration-slower': ( + 400ms, + ), + 'duration-slowest': ( + 500ms, + ), +); + +/* Polaris Tokens: spacing.spacing-map */ + +$polaris-spacing: ( + 'none': 0, + 'extra-tight': 4px, + 'tight': 8px, + 'base-tight': 12px, + 'base': 16px, + 'loose': 20px, + 'extra-loose': 32px, +); + +/* FOUNDATION: accessibility */ + +@mixin high-contrast-outline($border-width: border-width()) { + outline: $border-width solid transparent; + @content; +} + +@mixin high-contrast-border($border-width: border-width()) { + border: $border-width solid transparent; + @content; +} + +/* FOUNDATION: utilities */ + +$default-browser-font-size: 16px; +$base-font-size: 16px; + +/// Returns the value in rem for a given pixel value. +/// @param {Number} $value - The pixel value to be converted. +/// @return {Number} The converted value in rem. + +@function rem($value) { + $unit: unit($value); + + @if $value == 0 { + @return 0; + } @else if $unit == 'rem' { + @return $value; + } @else if $unit == 'px' { + @return $value / $base-font-size * 1rem; + } @else if $unit == 'em' { + @return $unit / 1em * 1rem; + } @else { + @error 'Value must be in px, em, or rem.'; + } +} + +/// Returns the value in pixels for a given rem value. +/// @param {Number} $value - The rem value to be converted. +/// @return {Number} The converted value in pixels. + +@function px($value) { + $unit: unit($value); + + @if $value == 0 { + @return 0; + } @else if $unit == 'px' { + @return $value; + } @else if $unit == 'em' { + @return ($value / 1em) * $base-font-size; + } @else if $unit == 'rem' { + @return ($value / 1rem) * $base-font-size; + } @else { + @error 'Value must be in rem, em, or px.'; + } +} + +/// Returns the value in ems for a given pixel value. Note that this +/// only works for elements that have had no font-size changes. +/// @param {Number} $value - The pixel value to be converted. +/// @return {Number} The converted value in ems. + +@function em($value) { + $unit: unit($value); + + @if $value == 0 { + @return 0; + } @else if $unit == 'em' { + @return $value; + } @else if $unit == 'rem' { + @return $value / 1rem * 1em * ($base-font-size / $default-browser-font-size); + } @else if $unit == 'px' { + @return $value / $default-browser-font-size * 1em; + } @else { + @error 'Value must be in px, rem, or em.'; + } +} + +/// Returns the list of available names in a given map. +/// @param {Map} $map - The map of data to list the names from. +/// @param {Number} $map - The level of depth to get names from. +/// @return {String} The list of names in the map. + +@function available-names($map, $level: 1) { + @if type-of($map) != 'map' { + @return null; } - - /** - * FOUNDATION: utilities - */ - - $default-browser-font-size: 16px; - $base-font-size: 16px; - - /// Returns the value in rem for a given pixel value. - /// @param {Number} $value - The pixel value to be converted. - /// @return {Number} The converted value in rem. - - @function rem($value) { - $unit: unit($value); - - @if $value == 0 { - @return 0; - } @else if $unit == 'rem' { - @return $value; - } @else if $unit == 'px' { - @return $value / $base-font-size * 1rem; - } @else if $unit == 'em' { - @return $unit / 1em * 1rem; - } @else { - @error 'Value must be in px, em, or rem.'; + + $output: ''; + $newline: '\A '; + + @if $level == 1 { + @each $key, $value in $map { + $output: $output + + '#{$newline}- #{$key} #{available-names($value, $level + 1)}'; + } + } @else { + $output: '('; + $i: 1; + + @each $key, $value in $map { + $sep: if($i < length($map), ', ', ''); + $output: $output + '#{$key}#{$sep}#{available-names($value, $level + 1)}'; + $i: $i + 1; } + + $output: $output + ')'; } - - /// Returns the value in pixels for a given rem value. - /// @param {Number} $value - The rem value to be converted. - /// @return {Number} The converted value in pixels. - - @function px($value) { - $unit: unit($value); - - @if $value == 0 { - @return 0; - } @else if $unit == 'px' { - @return $value; - } @else if $unit == 'em' { - @return ($value / 1em) * $base-font-size; - } @else if $unit == 'rem' { - @return ($value / 1rem) * $base-font-size; - } @else { - @error 'Value must be in rem, em, or px.'; + + @return $output; +} + +// Merge multiple maps into one. +// @param {Map} $map - Initial default map. +// @param {ArgList} $maps - Other maps to merge. +// @return {Map} The final merged map. +@function map-extend($map, $maps...) { + @for $i from 1 through length($maps) { + @each $key, $value in nth($maps, $i) { + $map: map-merge( + $map, + ( + $key: $value, + ) + ); + + @if type-of($value) == map and type-of(map-get($map, $key)) == map { + $value: map-extend(map-get($map, $key), $value); + } } } - - /// Returns the value in ems for a given pixel value. Note that this - /// only works for elements that have had no font-size changes. - /// @param {Number} $value - The pixel value to be converted. - /// @return {Number} The converted value in ems. - - @function em($value) { - $unit: unit($value); - - @if $value == 0 { - @return 0; - } @else if $unit == 'em' { - @return $value; - } @else if $unit == 'rem' { - @return $value / 1rem * 1em * ($base-font-size / $default-browser-font-size); - } @else if $unit == 'px' { - @return $value / $default-browser-font-size * 1em; - } @else { - @error 'Value must be in px, rem, or em.'; - } + + @return $map; +} + +/* FOUNDATION: colors */ + +// stylelint-disable-next-line scss/partial-no-import +@import '../polaris-tokens/colors.color-map'; + +/// +/// Color data +/// +/// Shopify color palette, extended specifically for polaris-react. +/// +/// @type map +$color-palette-data: $polaris-colors; + +// Add state colors to the palette +$color-palette-data: map-extend( + $color-palette-data, + ( + 'state': ( + 'hover': rgba(223, 227, 232, 0.3), + 'focused': rgba(223, 227, 232, 0.3), + 'active': rgba(179, 188, 245, 0.1), + 'selected': rgba(179, 188, 245, 0.15), + 'subdued': rgba(249, 250, 251, 1), + 'disabled': rgba(249, 250, 251, 1), + 'hover-destructive': rgba(251, 234, 229, 0.4), + 'focused-destructive': rgba(251, 234, 229, 0.4), + 'active-destructive': rgba(220, 56, 37, 0.03), + ), + ) +); + +/// Returns the color value for a given color name and group. +/// +/// @param {String} $hue - The color’s hue. +/// @param {String} $value - The darkness/lightness of the color. Defaults to +/// base. +/// @param {Color} $for-background - The background color on which this color +/// will appear. Applies a multiply filter to ensure appropriate contrast. +/// @return {Color} The color value. + +@function color($hue, $value: base, $for-background: null) { + $fetched-color: map-get(map-get($color-palette-data, $hue), $value); + + @if map-has-key($color-palette-data, $fetched-color) { + $fetched-color: map-get( + map-get($color-palette-data, $fetched-color), + $value + ); } - - /// Returns the list of available names in a given map. - /// @param {Map} $map - The map of data to list the names from. - /// @param {Number} $map - The level of depth to get names from. - /// @return {String} The list of names in the map. - - @function available-names($map, $level: 1) { - @if type-of($map) != 'map' { - @return null; - } - - $output: ''; - $newline: '\A '; - - @if $level == 1 { - @each $key, $value in $map { - $output: $output + - '#{$newline}- #{$key} #{available-names($value, $level + 1)}'; - } - } @else { - $output: '('; - $i: 1; - - @each $key, $value in $map { - $sep: if($i < length($map), ', ', ''); - $output: $output + '#{$key}#{$sep}#{available-names($value, $level + 1)}'; - $i: $i + 1; - } - - $output: $output + ')'; - } - - @return $output; - } - - // Merge multiple maps into one. - // @param {Map} $map - Initial default map. - // @param {ArgList} $maps - Other maps to merge. - // @return {Map} The final merged map. - @function map-extend($map, $maps...) { - @for $i from 1 through length($maps) { - @each $key, $value in nth($maps, $i) { - $map: map-merge( - $map, - ( - $key: $value, - ) - ); - - @if type-of($value) == map and type-of(map-get($map, $key)) == map { - $value: map-extend(map-get($map, $key), $value); - } - } - } - - @return $map; - } - - /** - * FOUNDATION: colors - */ - - /// - /// Color data - /// - /// Shopify color palette, extended specifically for polaris-react. - /// - /// @type map - $color-palette-data: $polaris-colors; - - // Add state colors to the palette - $color-palette-data: map-extend( - $color-palette-data, - ( - 'state': ( - 'hover': rgba(223, 227, 232, 0.3), - 'focused': rgba(223, 227, 232, 0.3), - 'active': rgba(179, 188, 245, 0.1), - 'selected': rgba(179, 188, 245, 0.15), - 'subdued': rgba(249, 250, 251, 1), - 'disabled': rgba(249, 250, 251, 1), - 'hover-destructive': rgba(251, 234, 229, 0.4), - 'focused-destructive': rgba(251, 234, 229, 0.4), - 'active-destructive': rgba(220, 56, 37, 0.03), - ), - ) - ); - - /// Returns the color value for a given color name and group. - /// - /// @param {String} $hue - The color’s hue. - /// @param {String} $value - The darkness/lightness of the color. Defaults to - /// base. - /// @param {Color} $for-background - The background color on which this color - /// will appear. Applies a multiply filter to ensure appropriate contrast. - /// @return {Color} The color value. - - @function color($hue, $value: base, $for-background: null) { - $fetched-color: map-get(map-get($color-palette-data, $hue), $value); - - @if map-has-key($color-palette-data, $fetched-color) { - $fetched-color: map-get( - map-get($color-palette-data, $fetched-color), - $value - ); - } - - @if $for-background { - $fetched-color: color-multiply($fetched-color, $for-background); - } - - @if type-of($fetched-color) == color { - @return $fetched-color; - } @else { - @error "Color `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `color('yellow')`.\a BAD: `color(yellow)`.\a\a Available options: #{available-names($color-palette-data)}"; - } + + @if $for-background { + $fetched-color: color-multiply($fetched-color, $for-background); } - - /// Darkens the foreground color by the background color. This is the same as - /// the "multiply" filter in graphics apps. - /// - /// @param {Color} $foreground - The color to darken. - /// @param {Color} $background - The background to base darkening on. - /// @return {Color} The modified color. - - @function color-multiply($foreground, $background: null) { - @if $background { - $background: rgb(255, 255, 255); - } - - $red: red($background) * red($foreground) / 255; - $green: green($background) * green($foreground) / 255; - $blue: blue($background) * blue($foreground) / 255; - - $opacity: opacity($foreground); - $background-opacity: opacity($background); - - // calculate opacity - $bm-red: $red * $opacity + red($background) * $background-opacity * - (1 - $opacity); - $bm-green: $green * $opacity + green($background) * $background-opacity * - (1 - $opacity); - $bm-blue: $blue * $opacity + blue($background) * $background-opacity * - (1 - $opacity); - - @return rgb($bm-red, $bm-green, $bm-blue); - } - - /// - /// Color palette for Windows high-contrast mode - /// See https://bit.ly/2vN9aGO - /// - /// @type map - - $ms-high-contrast-color-data: ( - 'text': windowText, - 'disabled-text': grayText, - 'selected-text': highlightText, - 'selected-text-background': highlight, - 'button-text': buttonText, - 'button-text-background': buttonFace, - 'background': window, - ); - - /// - /// Returns the color value for Windows high contrast mode - /// - /// @param {String} $color - The name of the high-contrast color. - /// @return {Color} The color value. - - @function ms-high-contrast-color($color) { - $fetched-color: map-get($ms-high-contrast-color-data, $color); - - @if $fetched-color { - @return $fetched-color; - } @else { - @error "Color `#{$color}` not found.\a Make sure argument is a string.\a GOOD: ms-high-contrast-color('selected-text').\a BAD: ms-high-contrast-color(selected-text).\a\a Available options: #{available-names($ms-high-contrast-color-data)}"; - } + + @if type-of($fetched-color) == color { + @return $fetched-color; + } @else { + @error "Color `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `color('yellow')`.\a BAD: `color(yellow)`.\a\a Available options: #{available-names($color-palette-data)}"; } - - /** - * FOUNDATION: filters - */ - - /// - /// Color filter data - /// - /// Shopify color filter palette, extended specifically for polaris-react. - /// - /// @type map - $color-filter-palette-data: $polaris-color-filters; - - /// Returns the filter list for a given color name and group. - /// - /// @param {String} $hue - The color’s hue. - /// @param {String} $value - The darkness/lightness of the color. Defaults to - /// base. - /// @return {List} The filter list. - - @function filter($hue, $value: base) { - $fetched-color: map-get(map-get($color-filter-palette-data, $hue), $value); - - @if map-has-key($color-filter-palette-data, $fetched-color) { - $fetched-color: map-get( - map-get($color-filter-palette-data, $fetched-color), - $value - ); - } - - @if type-of($fetched-color) == list { - @return $fetched-color; - } @else { - @error "Filter `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `filter('yellow')`.\a BAD: `filter(yellow)`.\a\a Available options: #{available-names($color-filter-palette-data)}"; - } +} + +/// Darkens the foreground color by the background color. This is the same as +/// the "multiply" filter in graphics apps. +/// +/// @param {Color} $foreground - The color to darken. +/// @param {Color} $background - The background to base darkening on. +/// @return {Color} The modified color. + +@function color-multiply($foreground, $background: null) { + @if $background { + $background: rgb(255, 255, 255); } - - /** - * FOUNDATION: spacing - */ - - $spacing-data: $polaris-spacing; - - /// Returns the spacing value for a given variant. - /// - /// @param {String} $variant - The key for the given variant. - /// @return {Number} The spacing for the variant. - - @function spacing($variant: base) { - $fetched-value: map-get($spacing-data, $variant); - - @if type-of($fetched-value) == number { - @return rem($fetched-value); - } @else { - @error 'Spacing variant `#{$variant}` not found. Available variants: #{available-names($spacing-data)}'; - } + + $red: red($background) * red($foreground) / 255; + $green: green($background) * green($foreground) / 255; + $blue: blue($background) * blue($foreground) / 255; + + $opacity: opacity($foreground); + $background-opacity: opacity($background); + + // calculate opacity + $bm-red: $red * $opacity + red($background) * $background-opacity * + (1 - $opacity); + $bm-green: $green * $opacity + green($background) * $background-opacity * + (1 - $opacity); + $bm-blue: $blue * $opacity + blue($background) * $background-opacity * + (1 - $opacity); + + @return rgb($bm-red, $bm-green, $bm-blue); +} + +/// +/// Color palette for Windows high-contrast mode +/// See https://bit.ly/2vN9aGO +/// +/// @type map + +$ms-high-contrast-color-data: ( + 'text': windowText, + 'disabled-text': grayText, + 'selected-text': highlightText, + 'selected-text-background': highlight, + 'button-text': buttonText, + 'button-text-background': buttonFace, + 'background': window, +); + +/// +/// Returns the color value for Windows high contrast mode +/// +/// @param {String} $color - The name of the high-contrast color. +/// @return {Color} The color value. + +@function ms-high-contrast-color($color) { + $fetched-color: map-get($ms-high-contrast-color-data, $color); + + @if $fetched-color { + @return $fetched-color; + } @else { + @error "Color `#{$color}` not found.\a Make sure argument is a string.\a GOOD: ms-high-contrast-color('selected-text').\a BAD: ms-high-contrast-color(selected-text).\a\a Available options: #{available-names($ms-high-contrast-color-data)}"; } - - /** - * FOUNDATION: border-width - */ - - $border-width-data: ( - base: rem(1px), - thick: rem(2px), - thicker: rem(3px), - ); - - /// Returns the width of the specified border type. - /// @param {String} $variant [base] - The border variant key. - /// @return {Number} The width for the border. - - @function border-width($variant: base) { - $fetched-value: map-get($border-width-data, $variant); - - @if type-of($fetched-value) == number { - @return $fetched-value; - } @else { - @error 'Border width variant `#{$variant}` not found. Available variants: #{available-names($border-width-data)}'; - } +} + +/* FOUNDATION: filters */ + +// stylelint-disable-next-line scss/partial-no-import +@import '../polaris-tokens/color-filters.color-map'; + +/// +/// Color filter data +/// +/// Shopify color filter palette, extended specifically for polaris-react. +/// +/// @type map +$color-filter-palette-data: $polaris-color-filters; + +/// Returns the filter list for a given color name and group. +/// +/// @param {String} $hue - The color’s hue. +/// @param {String} $value - The darkness/lightness of the color. Defaults to +/// base. +/// @return {List} The filter list. + +@function filter($hue, $value: base) { + $fetched-color: map-get(map-get($color-filter-palette-data, $hue), $value); + + @if map-has-key($color-filter-palette-data, $fetched-color) { + $fetched-color: map-get( + map-get($color-filter-palette-data, $fetched-color), + $value + ); } - - /** - * FOUNDATION: borders - */ - - $borders-data: ( - base: border-width() solid var(--p-border-subdued), - dark: border-width() solid var(--p-border), - transparent: border-width() solid transparent, - divider: border-width() solid var(--p-divider), - ); - - /// Returns the default border. - /// @param {String} $variant [base] - The border variant key. - /// @return {List} The border value. - - @function border($variant: base) { - $fetched-value: map-get($borders-data, $variant); - - @if $fetched-value { - @return $fetched-value; - } @else { - @error 'Border variant `#{$variant}` not found. Available variants: #{available-names($borders-data)}'; - } + + @if type-of($fetched-color) == list { + @return $fetched-color; + } @else { + @error "Filter `#{$hue}, #{$value}` not found.\a Make sure arguments are strings.\a GOOD: `filter('yellow')`.\a BAD: `filter(yellow)`.\a\a Available options: #{available-names($color-filter-palette-data)}"; } - - /** - * FOUNDATION: border-radius - */ - - $border-radius-data: ( - base: 3px, - large: 6px, - ); - - /// Returns the border radius of the specified size. - /// @param {String} $size - The border radius’s size. - /// @return {Number} The border radius value. - - @function border-radius($size: base) { - @return map-get($border-radius-data, $size); - } - - /** - * FOUNDATION: duration - */ - - $duration-data: $polaris-duration-map; - - /// Returns the duration value for a given variant. - /// - /// @param {String} $variant - The key for the given variant. - /// @return {Number} The duration for the variant (in milliseconds). - - @function duration($variant: base) { - $interpolated-value: 'duration-' + $variant; - $fetched-value: nth(map-get($duration-data, $interpolated-value), 1); - - @if type-of($fetched-value) == number { - @return $fetched-value; - } @else { - @error 'Duration variant `#{$interpolated-value}` not found. Available variants: #{available-names($duration-data)}'; - } +} + +/* FOUNDATION: spacing */ + +// stylelint-disable-next-line scss/partial-no-import +@import '../polaris-tokens/spacing.spacing-map'; + +$spacing-data: $polaris-spacing; + +/// Returns the spacing value for a given variant. +/// +/// @param {String} $variant - The key for the given variant. +/// @return {Number} The spacing for the variant. + +@function spacing($variant: base) { + $fetched-value: map-get($spacing-data, $variant); + + @if type-of($fetched-value) == number { + @return rem($fetched-value); + } @else { + @error 'Spacing variant `#{$variant}` not found. Available variants: #{available-names($spacing-data)}'; } - - /** - * FOUNDATION: easing - */ - - $easing-data: ( - base: cubic-bezier(0.25, 0.1, 0.25, 1), - in: cubic-bezier(0.36, 0, 1, 1), - out: cubic-bezier(0, 0, 0.42, 1), - excite: cubic-bezier(0.18, 0.67, 0.6, 1.22), - overshoot: cubic-bezier(0.07, 0.28, 0.32, 1.22), - anticipate: cubic-bezier(0.38, -0.4, 0.88, 0.65), - ); - - /// Returns the timing-function value for a given variant. - /// - /// @param {String} $variant - The key for the given variant. - /// @return {String} The cubic-bezier function (string) for the variant. - - @function easing($variant: base) { - $fetched-value: map-get($easing-data, $variant); - - @if type-of($fetched-value) == string { - @return $fetched-value; - } @else { - @error 'Easing variant `#{$variant}` not found. Available variants: #{available-names($easing-data)}'; - } +} + +/* FOUNDATION: border-width */ + +$border-width-data: ( + base: rem(1px), + thick: rem(2px), + thicker: rem(3px), +); + +/// Returns the width of the specified border type. +/// @param {String} $variant [base] - The border variant key. +/// @return {Number} The width for the border. + +@function border-width($variant: base) { + $fetched-value: map-get($border-width-data, $variant); + + @if type-of($fetched-value) == number { + @return $fetched-value; + } @else { + @error 'Border width variant `#{$variant}` not found. Available variants: #{available-names($border-width-data)}'; } - - /** - * FOUNDATION: layout - */ - - $navigation-width: 240px !default; - - //// - /// Layout - /// @group foundation/layout - //// - - $layout-width-data: ( - primary: ( - min: rem(480px), - max: rem(662px), - ), - secondary: ( - min: rem(240px), - max: rem(320px), - ), - one-half-width: ( - base: rem(450px), - ), - one-third-width: ( - base: rem(240px), - ), - nav: ( - base: rem($navigation-width), - ), - page-with-nav: ( - base: rem(769px), - ), - page-content: ( - not-condensed: rem(680px), - partially-condensed: rem(450px), - ), - inner-spacing: ( - base: spacing(), - ), - outer-spacing: ( - min: spacing(loose), - max: spacing(extra-loose), - ), - ); - - /// Returns the widths of the specified column. - /// @param {String} $name - The column name. - /// @return {Number} The width for the column. - - @function layout-width($name, $value: base) { - $fetched-value: map-get(map-get($layout-width-data, $name), $value); - - @if type-of($fetched-value) { - @return $fetched-value; - } @else { - @error 'Column `#{$name} - #{$value}` not found. Available columns: #{available-names($layout-width-data)}'; - } +} + +/* FOUNDATION: borders */ + +$borders-data: ( + base: border-width() solid var(--p-border-subdued), + dark: border-width() solid var(--p-border), + transparent: border-width() solid transparent, + divider: border-width() solid var(--p-divider), +); + +/// Returns the default border. +/// @param {String} $variant [base] - The border variant key. +/// @return {List} The border value. + +@function border($variant: base) { + $fetched-value: map-get($borders-data, $variant); + + @if $fetched-value { + @return $fetched-value; + } @else { + @error 'Border variant `#{$variant}` not found. Available variants: #{available-names($borders-data)}'; } - - $dismiss-icon-size: 32px; - - @function top-bar-height() { - @return rem(56px); - } - - @function mobile-nav-width() { - @return calc(100vw - #{rem($dismiss-icon-size) + spacing() * 2}); - } - - @function nav-min-window-corrected() { - @return rem(769px); - } - - /** - * FOUNDATION: shadows - */ - - // Shadows are intentionally very subtle gradiations. - $shadows-data: ( - faint: ( - 0 1px 0 0 rgba(22, 29, 37, 0.05), - ), - base: ( - 0 0 0 1px rgba(63, 63, 68, 0.05), - 0 1px 3px 0 rgba(63, 63, 68, 0.15), - ), - deep: ( - 0 0 0 1px rgba(6, 44, 82, 0.1), - 0 2px 16px rgba(33, 43, 54, 0.08), - ), - layer: ( - 0 31px 41px 0 rgba(32, 42, 53, 0.2), - 0 2px 16px 0 rgba(32, 42, 54, 0.08), - ), - transparent: 0 0 0 0 transparent, - ); - - /// Returns the shadow for the specified depth - /// @param {String} $depth [base] - The shadow’s depth. - /// @return {List} The shadow value. - - @function shadow($depth: base) { - $fetched-value: map-get($shadows-data, $depth); - - @if type-of($fetched-value) == list { - @return $fetched-value; - } @else { - @error 'Shadow variant `#{$depth}` not found. Available variants: #{available-names($shadows-data)}'; - } +} + +/* FOUNDATION: border-radius */ + +$border-radius-data: ( + base: 3px, + large: 6px, +); + +/// Returns the border radius of the specified size. +/// @param {String} $size - The border radius’s size. +/// @return {Number} The border radius value. + +@function border-radius($size: base) { + @return map-get($border-radius-data, $size); +} + +/* FOUNDATION: duration */ + +// stylelint-disable-next-line scss/partial-no-import +@import '../polaris-tokens/duration.map'; + +$duration-data: $polaris-duration-map; + +/// Returns the duration value for a given variant. +/// +/// @param {String} $variant - The key for the given variant. +/// @return {Number} The duration for the variant (in milliseconds). + +@function duration($variant: base) { + $interpolated-value: 'duration-' + $variant; + $fetched-value: nth(map-get($duration-data, $interpolated-value), 1); + + @if type-of($fetched-value) == number { + @return $fetched-value; + } @else { + @error 'Duration variant `#{$interpolated-value}` not found. Available variants: #{available-names($duration-data)}'; } - - /** - * FOUNDATION: typography - */ - - $typography-condensed: em(640px); - - $font-family-data: ( - base: #{-apple-system, - 'BlinkMacSystemFont', - 'San Francisco', - 'Segoe UI', - 'Roboto', - 'Helvetica Neue', - sans-serif}, - monospace: #{ui-monospace, - SFMono-Regular, - SF Mono, - Consolas, - Liberation Mono, - Menlo, - monospace}, - ); - - $line-height-data: ( - caption: ( - base: rem(20px), - large-screen: rem(16px), - ), - heading: ( - base: rem(24px), - ), - subheading: ( - base: rem(16px), - ), - input: ( - base: rem(24px), - ), - body: ( - base: rem(20px), - ), - button: ( - base: rem(16px), - ), - button-large: ( - base: rem(20px), - ), - display-x-large: ( - base: rem(36px), - large-screen: rem(44px), - ), - display-large: ( - base: rem(28px), - large-screen: rem(32px), - ), - display-medium: ( - base: rem(28px), - large-screen: rem(32px), - ), - display-small: ( - base: rem(24px), - large-screen: rem(28px), - ), - ); - - $font-size-data: ( - caption: ( - base: rem(13px), - large-screen: rem(12px), - ), - heading: ( - base: rem(17px), - large-screen: rem(16px), - ), - subheading: ( - base: rem(13px), - large-screen: rem(12px), - ), - input: ( - base: rem(16px), - large-screen: rem(14px), - ), - body: ( - base: rem(15px), - large-screen: rem(14px), - ), - button: ( - base: rem(15px), - large-screen: rem(14px), - ), - button-large: ( - base: rem(17px), - large-screen: rem(16px), - ), - display-x-large: ( - base: rem(27px), - large-screen: rem(42px), - ), - display-large: ( - base: rem(24px), - large-screen: rem(28px), - ), - display-medium: ( - base: rem(21px), - large-screen: rem(26px), - ), - display-small: ( - base: rem(16px), - large-screen: rem(20px), - ), - ); - - /// Returns the font stack for a given family. - /// - /// @param {String} $family - The key for the given family. - /// @return {Number} The font stack for the family. - - @function font-family($family: base) { - $fetched-value: map-get($font-family-data, $family); - - @if $fetched-value { - @return $fetched-value; - } @else { - @error 'Font family `#{$family}` not found. Available font families: #{available-names($font-family-data)}'; - } +} + +/* FOUNDATION: easing */ + +$easing-data: ( + base: cubic-bezier(0.25, 0.1, 0.25, 1), + in: cubic-bezier(0.36, 0, 1, 1), + out: cubic-bezier(0, 0, 0.42, 1), + excite: cubic-bezier(0.18, 0.67, 0.6, 1.22), + overshoot: cubic-bezier(0.07, 0.28, 0.32, 1.22), + anticipate: cubic-bezier(0.38, -0.4, 0.88, 0.65), +); + +/// Returns the timing-function value for a given variant. +/// +/// @param {String} $variant - The key for the given variant. +/// @return {String} The cubic-bezier function (string) for the variant. + +@function easing($variant: base) { + $fetched-value: map-get($easing-data, $variant); + + @if type-of($fetched-value) == string { + @return $fetched-value; + } @else { + @error 'Easing variant `#{$variant}` not found. Available variants: #{available-names($easing-data)}'; } - - /// Returns the line height for a given text style and variant. - /// - /// @param {String} $style - The font style. - /// @param {String} $variant [base] - The variant on the font-size. - /// @return {Number} The line-height for the text-style. - - @function line-height($style, $variant: base) { - $fetched-line-height: map-get(map-get($line-height-data, $style), $variant); - - @if type-of($fetched-line-height) { - @return $fetched-line-height; - } @else { - @error 'Line height `#{$style} - #{$variant}` not found. Available line heights: #{available-names($line-height-data)}'; - } +} + +/* FOUNDATION: layout */ + +$navigation-width: 240px !default; + +//// +/// Layout +/// @group foundation/layout +//// + +$layout-width-data: ( + primary: ( + min: rem(480px), + max: rem(662px), + ), + secondary: ( + min: rem(240px), + max: rem(320px), + ), + one-half-width: ( + base: rem(450px), + ), + one-third-width: ( + base: rem(240px), + ), + nav: ( + base: rem($navigation-width), + ), + page-with-nav: ( + base: rem(769px), + ), + page-content: ( + not-condensed: rem(680px), + partially-condensed: rem(450px), + ), + inner-spacing: ( + base: spacing(), + ), + outer-spacing: ( + min: spacing(loose), + max: spacing(extra-loose), + ), +); + +/// Returns the widths of the specified column. +/// @param {String} $name - The column name. +/// @return {Number} The width for the column. + +@function layout-width($name, $value: base) { + $fetched-value: map-get(map-get($layout-width-data, $name), $value); + + @if type-of($fetched-value) { + @return $fetched-value; + } @else { + @error 'Column `#{$name} - #{$value}` not found. Available columns: #{available-names($layout-width-data)}'; } - - /// Returns the font size for a given text style and variant. - /// - /// @param {String} $style - The font style. - /// @param {String} $variant [base] - The variant on the font-size. - /// @return {Number} The font-size for the text-style. - - @function font-size($style, $variant: base) { - $fetched-font-size: map-get(map-get($font-size-data, $style), $variant); - - @if type-of($fetched-font-size) { - @return $fetched-font-size; - } @else { - @error 'Font size `#{$style} - #{$variant}` not found. Available font sizes: #{available-names($line-height-data)}'; - } +} + +$dismiss-icon-size: 32px; + +@function top-bar-height() { + @return rem(56px); +} + +@function mobile-nav-width() { + @return calc(100vw - #{rem($dismiss-icon-size) + spacing() * 2}); +} + +@function nav-min-window-corrected() { + @return rem(769px); +} + +/* FOUNDATION: shadows */ + +// Shadows are intentionally very subtle gradiations. +$shadows-data: ( + faint: ( + 0 1px 0 0 rgba(22, 29, 37, 0.05), + ), + base: ( + 0 0 0 1px rgba(63, 63, 68, 0.05), + 0 1px 3px 0 rgba(63, 63, 68, 0.15), + ), + deep: ( + 0 0 0 1px rgba(6, 44, 82, 0.1), + 0 2px 16px rgba(33, 43, 54, 0.08), + ), + layer: ( + 0 31px 41px 0 rgba(32, 42, 53, 0.2), + 0 2px 16px 0 rgba(32, 42, 54, 0.08), + ), + transparent: 0 0 0 0 transparent, +); + +/// Returns the shadow for the specified depth +/// @param {String} $depth [base] - The shadow’s depth. +/// @return {List} The shadow value. + +@function shadow($depth: base) { + $fetched-value: map-get($shadows-data, $depth); + + @if type-of($fetched-value) == list { + @return $fetched-value; + } @else { + @error 'Shadow variant `#{$depth}` not found. Available variants: #{available-names($shadows-data)}'; } - - /** - * FOUNDATION: z-index - */ - - $global-elements: ( - content: 100, - overlay: 400, - ); - - // We're matching that here and relatively stacking other fixed components. - $fixed-element-stacking-order: ( - global-ribbon: 510, - loading-bar: 511, - top-bar: 512, - context-bar: 513, - small-screen-loading-bar: 514, - nav-backdrop: 515, - nav: 516, - skip-to-content: 517, - backdrop: 518, - modal: 519, - toast: 520, - dev-ui: 521, - ); - - /// Returns the z-index of the specified element. - /// @param {String} $element - The key for the element. - /// @param {Map} $context - The map in which to search for the element. - /// @return {Number} The z-index for the element. - - @function z-index($element, $context: $global-elements) { - $index: map-get($context, $element); - - @if $index { - @return $index; - } @else { - @error 'z-index `#{$element}` in `#{$context}` not found.'; - } +} + +/* FOUNDATION: typography */ + +$typography-condensed: em(640px); + +$font-family-data: ( + base: #{-apple-system, + 'BlinkMacSystemFont', + 'San Francisco', + 'Segoe UI', + 'Roboto', + 'Helvetica Neue', + sans-serif}, + monospace: #{ui-monospace, + SFMono-Regular, + SF Mono, + Consolas, + Liberation Mono, + Menlo, + monospace}, +); + +$line-height-data: ( + caption: ( + base: rem(20px), + large-screen: rem(16px), + ), + heading: ( + base: rem(24px), + ), + subheading: ( + base: rem(16px), + ), + input: ( + base: rem(24px), + ), + body: ( + base: rem(20px), + ), + button: ( + base: rem(16px), + ), + button-large: ( + base: rem(20px), + ), + display-x-large: ( + base: rem(36px), + large-screen: rem(44px), + ), + display-large: ( + base: rem(28px), + large-screen: rem(32px), + ), + display-medium: ( + base: rem(28px), + large-screen: rem(32px), + ), + display-small: ( + base: rem(24px), + large-screen: rem(28px), + ), +); + +$font-size-data: ( + caption: ( + base: rem(13px), + large-screen: rem(12px), + ), + heading: ( + base: rem(17px), + large-screen: rem(16px), + ), + subheading: ( + base: rem(13px), + large-screen: rem(12px), + ), + input: ( + base: rem(16px), + large-screen: rem(14px), + ), + body: ( + base: rem(15px), + large-screen: rem(14px), + ), + button: ( + base: rem(15px), + large-screen: rem(14px), + ), + button-large: ( + base: rem(17px), + large-screen: rem(16px), + ), + display-x-large: ( + base: rem(27px), + large-screen: rem(42px), + ), + display-large: ( + base: rem(24px), + large-screen: rem(28px), + ), + display-medium: ( + base: rem(21px), + large-screen: rem(26px), + ), + display-small: ( + base: rem(16px), + large-screen: rem(20px), + ), +); + +/// Returns the font stack for a given family. +/// +/// @param {String} $family - The key for the given family. +/// @return {Number} The font stack for the family. + +@function font-family($family: base) { + $fetched-value: map-get($font-family-data, $family); + + @if $fetched-value { + @return $fetched-value; + } @else { + @error 'Font family `#{$family}` not found. Available font families: #{available-names($font-family-data)}'; } - - /** - * FOUNDATION: focus-ring - */ - - /// Sets the focus ring for an interactive element - /// @param {String} $size - The size of the border radius on the focus ring. - /// @param {String} $style - Focus ring state. - /// @param {Number} $border-width - The border width of your element in rems. - /// - - @mixin focus-ring($size: 'base', $border-width: 0, $style: 'base') { - $stroke: rem(2px); - // calc does not like performing addition with a unitless number (`0`, NOT `0px`) - // This is a problem because `rem(0px)` returns `0`, not `0px`. - // Make sure that we can handle unitless zeros by not trying to do math with them - $offset: if( - $border-width == 0, - rem(1px), - calc(#{$border-width} + #{rem(1px)}) - ); - $border-radius: if( - $size == 'wide', - var(--p-border-radius-wide), - var(--p-border-radius-base) - ); - $negative-offset: calc(-1 * #{$offset}); - - @if $style == 'base' { - position: relative; - - &::after { - content: ''; - position: absolute; - z-index: 1; - top: $negative-offset; - right: $negative-offset; - bottom: $negative-offset; - left: $negative-offset; - display: block; - pointer-events: none; - box-shadow: 0 0 0 $negative-offset var(--p-focused); - transition: box-shadow duration(fast) var(--p-ease); - border-radius: calc(#{$border-radius} + #{rem(1px)}); - } - } @else if $style == 'focused' { - &::after { - box-shadow: 0 0 0 $stroke var(--p-focused); - @include high-contrast-outline; - } - } +} + +/// Returns the line height for a given text style and variant. +/// +/// @param {String} $style - The font style. +/// @param {String} $variant [base] - The variant on the font-size. +/// @return {Number} The line-height for the text-style. + +@function line-height($style, $variant: base) { + $fetched-line-height: map-get(map-get($line-height-data, $style), $variant); + + @if type-of($fetched-line-height) { + @return $fetched-line-height; + } @else { + @error 'Line height `#{$style} - #{$variant}` not found. Available line heights: #{available-names($line-height-data)}'; } - - @mixin no-focus-ring { - &::after { - content: none; - } +} + +/// Returns the font size for a given text style and variant. +/// +/// @param {String} $style - The font style. +/// @param {String} $variant [base] - The variant on the font-size. +/// @return {Number} The font-size for the text-style. + +@function font-size($style, $variant: base) { + $fetched-font-size: map-get(map-get($font-size-data, $style), $variant); + + @if type-of($fetched-font-size) { + @return $fetched-font-size; + } @else { + @error 'Font size `#{$style} - #{$variant}` not found. Available font sizes: #{available-names($line-height-data)}'; + } +} + +/* FOUNDATION: z-index */ + +$global-elements: ( + content: 100, + overlay: 400, +); + +// We're matching that here and relatively stacking other fixed components. +$fixed-element-stacking-order: ( + global-ribbon: 510, + loading-bar: 511, + top-bar: 512, + context-bar: 513, + small-screen-loading-bar: 514, + nav-backdrop: 515, + nav: 516, + skip-to-content: 517, + backdrop: 518, + modal: 519, + toast: 520, + dev-ui: 521, +); + +/// Returns the z-index of the specified element. +/// @param {String} $element - The key for the element. +/// @param {Map} $context - The map in which to search for the element. +/// @return {Number} The z-index for the element. + +@function z-index($element, $context: $global-elements) { + $index: map-get($context, $element); + + @if $index { + @return $index; + } @else { + @error 'z-index `#{$element}` in `#{$context}` not found.'; } - - /** - * SHARED: accessibility - */ - - /// Used to hide an element visually, but keeping it accessible for - /// accessibility tools. - - /// styles referenced from GOV.UK design system - /// https://github.com/h5bp/main.css/issues/12#issuecomment-451965809 - @mixin visually-hidden { - // Need to make sure we override any existing styles. - // stylelint-disable declaration-no-important - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: 0 !important; - padding: 0 !important; - overflow: hidden !important; - clip-path: inset(50%) !important; - border: 0 !important; - white-space: nowrap !important; - // stylelint-enable declaration-no-important - } - - /** - * SHARED: breakpoints - */ - - $page-max-width: layout-width(primary, max) + layout-width(secondary, max) + - layout-width(inner-spacing); - $frame-with-nav-max-width: layout-width(nav) + $page-max-width; - - $stacked-content: em( - layout-width(primary, min) + layout-width(secondary, min) + - layout-width(inner-spacing) +} + +/* FOUNDATION: focus-ring */ + +// stylelint-disable-next-line scss/partial-no-import +@import './accessibility'; + +/// Sets the focus ring for an interactive element +/// @param {String} $size - The size of the border radius on the focus ring. +/// @param {String} $style - Focus ring state. +/// @param {Number} $border-width - The border width of your element in rems. +/// + +@mixin focus-ring($size: 'base', $border-width: 0, $style: 'base') { + $stroke: rem(2px); + // calc does not like performing addition with a unitless number (`0`, NOT `0px`) + // This is a problem because `rem(0px)` returns `0`, not `0px`. + // Make sure that we can handle unitless zeros by not trying to do math with them + $offset: if( + $border-width == 0, + rem(1px), + calc(#{$border-width} + #{rem(1px)}) ); - $not-condensed-content: em(layout-width(page-content, not-condensed)); - $partially-condensed-content: em( - layout-width(page-content, partially-condensed) + $border-radius: if( + $size == 'wide', + var(--p-border-radius-wide), + var(--p-border-radius-base) ); - - $not-condensed-outer-spacing: em(2 * layout-width(outer-spacing, max)); - $partially-condensed-outer-spacing: em(2 * layout-width(outer-spacing, min)); - - $not-condensed-min-page: $not-condensed-content + $not-condensed-outer-spacing; - $partially-condensed-min-page: $partially-condensed-content + - $partially-condensed-outer-spacing; - - $nav-size: em(layout-width(nav)); - $nav-min-window: em(layout-width(page-with-nav)); - - @function breakpoint($value, $adjustment: 0) { - $adjusted-value: em($adjustment); - - // Reduces chances to have a style void - // between two media queries - // See https://github.com/sass-mq/sass-mq/issues/6 - @if $adjustment == -1px { - $adjusted-value: -0.01em; - } @else if $adjustment == 1px { - $adjusted-value: 0.01em; + $negative-offset: calc(-1 * #{$offset}); + + @if $style == 'base' { + position: relative; + + &::after { + content: ''; + position: absolute; + z-index: 1; + top: $negative-offset; + right: $negative-offset; + bottom: $negative-offset; + left: $negative-offset; + display: block; + pointer-events: none; + box-shadow: 0 0 0 $negative-offset var(--p-focused); + transition: box-shadow duration(fast) var(--p-ease); + border-radius: calc(#{$border-radius} + #{rem(1px)}); } - - @return em($value) + $adjusted-value; - } - - @mixin page-content-breakpoint-before($size) { - $size: breakpoint($size); - - @if $size < $partially-condensed-content { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { - @media (max-width: #{min($nav-min-window, $size)}), - (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size}) { - @content; - } - } - - @media (max-width: #{$size}) { - @content; - } - } @else if $size < $not-condensed-content { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { - @media (max-width: #{min($nav-min-window, $size + $partially-condensed-outer-spacing)}), - (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { - @content; - } - } - - @media (max-width: #{$size + $partially-condensed-outer-spacing}) { - @content; - } - } @else { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { - @media (max-width: #{min($nav-min-window, $size + $partially-condensed-outer-spacing)}), - (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { - @content; - } - } - - @media (max-width: #{$size + $not-condensed-outer-spacing}) { - @content; - } + } @else if $style == 'focused' { + &::after { + box-shadow: 0 0 0 $stroke var(--p-focused); + @include high-contrast-outline; } } - - @mixin page-content-breakpoint-after($size) { - $size: breakpoint($size); - - @if $size < $partially-condensed-content { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { - @media (max-width: #{$nav-min-window}) and (min-width: #{$size}), - (min-width: #{$nav-size + $size}) { - @content; - } - } - - @media (min-width: #{$size}) { - @content; - } - } @else if $size < $not-condensed-content { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { - @media (max-width: #{$nav-min-window}) and (min-width: #{$size + $partially-condensed-outer-spacing}), - (min-width: #{$nav-size + $size + $partially-condensed-outer-spacing}) { - @content; - } - } - - @media (min-width: #{$size + $partially-condensed-outer-spacing}) { - @content; - } - } @else { - // prettier-ignore - [data-has-navigation] #{if(&, "&", "*")} { - @media (max-width: #{$nav-min-window}) and (min-width: #{$size + $not-condensed-outer-spacing}), - (min-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { - @content; - } - } - - @media (min-width: #{$size + $not-condensed-outer-spacing}) { - @content; +} + +@mixin no-focus-ring { + &::after { + content: none; + } +} + +/* SHARED: accessibility */ + +/// Used to hide an element visually, but keeping it accessible for +/// accessibility tools. + +/// styles referenced from GOV.UK design system +/// https://github.com/h5bp/main.css/issues/12#issuecomment-451965809 +@mixin visually-hidden { + // Need to make sure we override any existing styles. + // stylelint-disable declaration-no-important + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + clip-path: inset(50%) !important; + border: 0 !important; + white-space: nowrap !important; + // stylelint-enable declaration-no-important +} + +/* SHARED: breakpoints */ + +$page-max-width: layout-width(primary, max) + layout-width(secondary, max) + + layout-width(inner-spacing); +$frame-with-nav-max-width: layout-width(nav) + $page-max-width; + +$stacked-content: em( + layout-width(primary, min) + layout-width(secondary, min) + + layout-width(inner-spacing) +); +$not-condensed-content: em(layout-width(page-content, not-condensed)); +$partially-condensed-content: em( + layout-width(page-content, partially-condensed) +); + +$not-condensed-outer-spacing: em(2 * layout-width(outer-spacing, max)); +$partially-condensed-outer-spacing: em(2 * layout-width(outer-spacing, min)); + +$not-condensed-min-page: $not-condensed-content + $not-condensed-outer-spacing; +$partially-condensed-min-page: $partially-condensed-content + + $partially-condensed-outer-spacing; + +$nav-size: em(layout-width(nav)); +$nav-min-window: em(layout-width(page-with-nav)); + +@function breakpoint($value, $adjustment: 0) { + $adjusted-value: em($adjustment); + + // Reduces chances to have a style void + // between two media queries + // See https://github.com/sass-mq/sass-mq/issues/6 + @if $adjustment == -1px { + $adjusted-value: -0.01em; + } @else if $adjustment == 1px { + $adjusted-value: 0.01em; + } + + @return em($value) + $adjusted-value; +} + +@mixin page-content-breakpoint-before($size) { + $size: breakpoint($size); + + @if $size < $partially-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{min($nav-min-window, $size)}), + (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size}) { + @content; } } - } - - @mixin breakpoint-after($breakpoint, $inclusive: true) { - @media (min-width: #{breakpoint($breakpoint, if($inclusive, 0, 1px))}) { + + @media (max-width: #{$size}) { @content; } - } - - @mixin breakpoint-before($breakpoint, $inclusive: true) { - @media (max-width: #{breakpoint($breakpoint, if($inclusive, 0, -1px))}) { - @content; + } @else if $size < $not-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{min($nav-min-window, $size + $partially-condensed-outer-spacing)}), + (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { + @content; + } } - } - - @mixin frame-with-nav-when-not-max-width() { - @include breakpoint-before($frame-with-nav-max-width) { + + @media (max-width: #{$size + $partially-condensed-outer-spacing}) { @content; } - } - - @mixin page-when-not-max-width() { - @include breakpoint-before($page-max-width) { - @content; + } @else { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{min($nav-min-window, $size + $partially-condensed-outer-spacing)}), + (min-width: #{$nav-min-window}) and (max-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { + @content; + } } - } - - @mixin page-content-when-layout-stacked() { - @include page-content-breakpoint-before($stacked-content) { + + @media (max-width: #{$size + $not-condensed-outer-spacing}) { @content; } } - - @mixin page-content-when-layout-not-stacked() { - @include page-content-breakpoint-after($stacked-content) { - @content; +} + +@mixin page-content-breakpoint-after($size) { + $size: breakpoint($size); + + @if $size < $partially-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{$nav-min-window}) and (min-width: #{$size}), + (min-width: #{$nav-size + $size}) { + @content; + } } - } - - @mixin page-content-when-partially-condensed() { - @include page-content-breakpoint-before($not-condensed-content) { + + @media (min-width: #{$size}) { @content; } - } - - @mixin page-content-when-not-partially-condensed() { - @include page-content-breakpoint-after($not-condensed-content) { - @content; + } @else if $size < $not-condensed-content { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{$nav-min-window}) and (min-width: #{$size + $partially-condensed-outer-spacing}), + (min-width: #{$nav-size + $size + $partially-condensed-outer-spacing}) { + @content; + } } - } - - @mixin page-content-when-fully-condensed() { - @include page-content-breakpoint-before($partially-condensed-content) { + + @media (min-width: #{$size + $partially-condensed-outer-spacing}) { @content; } - } - - @mixin page-content-when-not-fully-condensed() { - @include page-content-breakpoint-after($partially-condensed-content) { - @content; + } @else { + // prettier-ignore + [data-has-navigation] #{if(&, "&", "*")} { + @media (max-width: #{$nav-min-window}) and (min-width: #{$size + $not-condensed-outer-spacing}), + (min-width: #{$nav-size + $size + $not-condensed-outer-spacing}) { + @content; + } } - } - - @mixin frame-when-nav-displayed() { - @include breakpoint-after(layout-width(page-with-nav)) { + + @media (min-width: #{$size + $not-condensed-outer-spacing}) { @content; } } - - @mixin frame-when-nav-hidden() { - @include breakpoint-before(layout-width(page-with-nav), false) { - @content; - } +} + +@mixin breakpoint-after($breakpoint, $inclusive: true) { + @media (min-width: #{breakpoint($breakpoint, if($inclusive, 0, 1px))}) { + @content; } - - /** - * SHARED: buttons - */ - - @mixin high-contrast-button-outline($outline: 2px dotted) { - @media (-ms-high-contrast: active) { - outline: $outline; - } +} + +@mixin breakpoint-before($breakpoint, $inclusive: true) { + @media (max-width: #{breakpoint($breakpoint, if($inclusive, 0, -1px))}) { + @content; } - - @mixin button-base { - $min-height: control-height(); - $vertical-padding: ($min-height - line-height(body) - rem(2px)) / 2; - - @include recolor-icon(var(--p-icon)); - @include focus-ring($border-width: border-width('base')); - position: relative; - display: inline-flex; - align-items: center; - justify-content: center; - min-height: $min-height; - min-width: $min-height; - margin: 0; - padding: $vertical-padding spacing(); - background: var(--p-surface); +} + +@mixin frame-with-nav-when-not-max-width() { + @include breakpoint-before($frame-with-nav-max-width) { + @content; + } +} + +@mixin page-when-not-max-width() { + @include breakpoint-before($page-max-width) { + @content; + } +} + +@mixin page-content-when-layout-stacked() { + @include page-content-breakpoint-before($stacked-content) { + @content; + } +} + +@mixin page-content-when-layout-not-stacked() { + @include page-content-breakpoint-after($stacked-content) { + @content; + } +} + +@mixin page-content-when-partially-condensed() { + @include page-content-breakpoint-before($not-condensed-content) { + @content; + } +} + +@mixin page-content-when-not-partially-condensed() { + @include page-content-breakpoint-after($not-condensed-content) { + @content; + } +} + +@mixin page-content-when-fully-condensed() { + @include page-content-breakpoint-before($partially-condensed-content) { + @content; + } +} + +@mixin page-content-when-not-fully-condensed() { + @include page-content-breakpoint-after($partially-condensed-content) { + @content; + } +} + +@mixin frame-when-nav-displayed() { + @include breakpoint-after(layout-width(page-with-nav)) { + @content; + } +} + +@mixin frame-when-nav-hidden() { + @include breakpoint-before(layout-width(page-with-nav), false) { + @content; + } +} + +/* SHARED: buttons */ + +@mixin high-contrast-button-outline($outline: 2px dotted) { + @media (-ms-high-contrast: active) { + outline: $outline; + } +} + +@mixin button-base { + $min-height: control-height(); + $vertical-padding: ($min-height - line-height(body) - rem(2px)) / 2; + + @include recolor-icon(var(--p-icon)); + @include focus-ring($border-width: border-width('base')); + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + min-height: $min-height; + min-width: $min-height; + margin: 0; + padding: $vertical-padding spacing(); + background: var(--p-surface); + box-shadow: var(--p-button-drop-shadow); + border-radius: var(--p-border-radius-base); + color: var(--p-text); + border: 1px solid var(--p-border-neutral-subdued); + border-top-color: var(--p-border-subdued); + border-bottom-color: var(--p-border-shadow-subdued); + line-height: 1; + text-align: center; + cursor: pointer; + user-select: none; + text-decoration: none; + -webkit-tap-highlight-color: transparent; + + &:hover { + background: var(--p-action-secondary-hovered); + @include high-contrast-outline; + } + + &:focus { box-shadow: var(--p-button-drop-shadow); - border-radius: var(--p-border-radius-base); - color: var(--p-text); - border: 1px solid var(--p-border-neutral-subdued); - border-top-color: var(--p-border-subdued); - border-bottom-color: var(--p-border-shadow-subdued); - line-height: 1; - text-align: center; - cursor: pointer; - user-select: none; - text-decoration: none; - -webkit-tap-highlight-color: transparent; - - &:hover { - background: var(--p-action-secondary-hovered); - @include high-contrast-outline; - } - - &:focus { - box-shadow: var(--p-button-drop-shadow); - outline: 0; - - @include focus-ring($style: 'focused'); - } - - &:active { - background: var(--p-action-secondary-pressed); - box-shadow: var(--p-button-drop-shadow); - - &::after { - border: none; - box-shadow: none; - } - } - - &.pressed { - background: var(--p-action-secondary-depressed); - box-shadow: var(--p-button-pressed-inner-shadow); - color: var(--p-text-on-primary); - border-color: var(--p-border-depressed); - @include recolor-icon(currentColor); - } - - @media (-ms-high-contrast: active) { - border: 1px solid ms-high-contrast-color('text'); + outline: 0; + + @include focus-ring($style: 'focused'); + } + + &:active { + background: var(--p-action-secondary-pressed); + box-shadow: var(--p-button-drop-shadow); + + &::after { + border: none; + box-shadow: none; } } - - @mixin base-button-disabled { - @include recolor-icon(var(--p-icon-disabled)); - transition: none; - box-shadow: none; - border-color: var(--p-border-disabled); - background: var(--p-surface-disabled); - color: var(--p-text-disabled); + + &.pressed { + background: var(--p-action-secondary-depressed); + box-shadow: var(--p-button-pressed-inner-shadow); + color: var(--p-text-on-primary); + border-color: var(--p-border-depressed); + @include recolor-icon(currentColor); + } + + @media (-ms-high-contrast: active) { + border: 1px solid ms-high-contrast-color('text'); } - - @mixin button-filled() { - @include focus-ring($border-width: 0); - background: var(--p-button-color); - border-width: 0; +} + +@mixin base-button-disabled { + @include recolor-icon(var(--p-icon-disabled)); + transition: none; + box-shadow: none; + border-color: var(--p-border-disabled); + background: var(--p-surface-disabled); + color: var(--p-text-disabled); +} + +@mixin button-filled() { + @include focus-ring($border-width: 0); + background: var(--p-button-color); + border-width: 0; + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + color: var(--p-button-text); + + &:hover { + background: var(--p-button-color-hover); + border-color: transparent; + color: var(--p-button-text); + } + + &:focus { + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + } + + &:active { + background: var(--p-button-color-active); border-color: transparent; box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + } + + &.pressed { color: var(--p-button-text); - - &:hover { - background: var(--p-button-color-hover); - border-color: transparent; - color: var(--p-button-text); - } - + background: var(--p-button-color-depressed); + border-color: transparent; + box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); + + &:hover, &:focus { - border-color: transparent; - box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); - } - - &:active { - background: var(--p-button-color-active); - border-color: transparent; - box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); - } - - &.pressed { - color: var(--p-button-text); background: var(--p-button-color-depressed); - border-color: transparent; box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); - - &:hover, - &:focus { - background: var(--p-button-color-depressed); - box-shadow: var(--p-button-drop-shadow), var(--p-button-inner-shadow); - } } } - - @mixin button-outline($outline-color, $background-color: transparent) { - background: transparent; +} + +@mixin button-outline($outline-color, $background-color: transparent) { + background: transparent; + border: border-width() solid var(--p-border); + box-shadow: none; + color: var(--p-text); + @include focus-ring($border-width: border-width('base')); + + &:hover { border: border-width() solid var(--p-border); box-shadow: none; - color: var(--p-text); - @include focus-ring($border-width: border-width('base')); - - &:hover { - border: border-width() solid var(--p-border); + background: var(--p-surface-hovered); + } + + &:focus { + border: border-width() solid var(--p-border); + box-shadow: none; + @include focus-ring($style: 'focused'); + } + + &:active { + border: border-width() solid var(--p-border); + box-shadow: none; + background: var(--p-surface-pressed); + + &::after { box-shadow: none; - background: var(--p-surface-hovered); } - + } + + &.pressed { + background: var(--p-action-secondary-pressed); + border: border-width() solid var(--p-border); + box-shadow: none; + color: var(--p-button-text); + } + + &.disabled { + border: border-width('base') solid var(--p-border-disabled); + box-shadow: none; + background: transparent; + color: var(--p-text-disabled); + } + + &.destructive { + background: transparent; + border: border-width('base') solid var(--p-border-critical); + box-shadow: none; + color: var(--p-interactive-critical); + @include recolor-icon(var(--p-icon-critical)); + + &:hover { + border: border-width('base') solid var(--p-border-critical); + background: var(--p-surface-critical-subdued); + } + &:focus { - border: border-width() solid var(--p-border); - box-shadow: none; + border: border-width('base') solid var(--p-border-critical); @include focus-ring($style: 'focused'); } - + &:active { - border: border-width() solid var(--p-border); - box-shadow: none; - background: var(--p-surface-pressed); - - &::after { - box-shadow: none; - } - } - - &.pressed { - background: var(--p-action-secondary-pressed); - border: border-width() solid var(--p-border); - box-shadow: none; - color: var(--p-button-text); + border: border-width('base') solid var(--p-border-critical); + background: var(--p-surface-critical-subdued); } - + &.disabled { - border: border-width('base') solid var(--p-border-disabled); - box-shadow: none; + border: border-width('base') solid var(--p-border-critical-disabled); background: transparent; - color: var(--p-text-disabled); + color: var(--p-interactive-critical-disabled); } - - &.destructive { - background: transparent; - border: border-width('base') solid var(--p-border-critical); - box-shadow: none; + + &.pressed { + background: var(--p-surface-critical-subdued); + box-shadow: border-width('base') solid var(--p-border-critical); color: var(--p-interactive-critical); - @include recolor-icon(var(--p-icon-critical)); - - &:hover { - border: border-width('base') solid var(--p-border-critical); - background: var(--p-surface-critical-subdued); - } - - &:focus { - border: border-width('base') solid var(--p-border-critical); - @include focus-ring($style: 'focused'); - } - - &:active { - border: border-width('base') solid var(--p-border-critical); - background: var(--p-surface-critical-subdued); - } - - &.disabled { - border: border-width('base') solid var(--p-border-critical-disabled); - background: transparent; - color: var(--p-interactive-critical-disabled); - } - - &.pressed { - background: var(--p-surface-critical-subdued); - box-shadow: border-width('base') solid var(--p-border-critical); - color: var(--p-interactive-critical); - } } } - - @mixin button-outline-disabled($outline-color) { - background: transparent; - box-shadow: none; - } - - @mixin button-full-width { - display: flex; - width: 100%; - } - - @mixin plain-button-backdrop { - padding: 2px 5px; - margin: -2px -5px; - background: var(--p-action-secondary-hovered); - border-radius: border-radius(); - } - - @mixin unstyled-button() { - appearance: none; - margin: 0; - padding: 0; - background: none; - border: none; - font-size: inherit; - line-height: inherit; - color: inherit; - cursor: pointer; - - &:focus { - outline: none; - } +} + +@mixin button-outline-disabled($outline-color) { + background: transparent; + box-shadow: none; +} + +@mixin button-full-width { + display: flex; + width: 100%; +} + +@mixin plain-button-backdrop { + padding: 2px 5px; + margin: -2px -5px; + background: var(--p-action-secondary-hovered); + border-radius: border-radius(); +} + +@mixin unstyled-button() { + appearance: none; + margin: 0; + padding: 0; + background: none; + border: none; + font-size: inherit; + line-height: inherit; + color: inherit; + cursor: pointer; + + &:focus { + outline: none; } - - /** - * SHARED: controls - */ - - @function control-height() { - @return rem(36px); - } - - @function control-slim-height() { - @return rem(28px); - } - - @function control-vertical-padding() { - @return (control-height() - line-height(input) - rem(2px)) / 2; - } - - @function control-icon-transition() { - @return transform duration(fast) easing(in); - } - - @mixin control-backdrop($style: base) { - @if $style == base { - position: relative; - border: var(--p-control-border-width) solid var(--p-border); - background-color: var(--p-surface); +} + +/* SHARED: controls */ + +@function control-height() { + @return rem(36px); +} + +@function control-slim-height() { + @return rem(28px); +} + +@function control-vertical-padding() { + @return (control-height() - line-height(input) - rem(2px)) / 2; +} + +@function control-icon-transition() { + @return transform duration(fast) easing(in); +} + +@mixin control-backdrop($style: base) { + @if $style == base { + position: relative; + border: var(--p-control-border-width) solid var(--p-border); + background-color: var(--p-surface); + border-radius: var(--p-border-radius-base); + + &::before { + content: ''; + position: absolute; + top: calc(-1 * var(--p-control-border-width)); + right: calc(-1 * var(--p-control-border-width)); + bottom: calc(-1 * var(--p-control-border-width)); + left: calc(-1 * var(--p-control-border-width)); border-radius: var(--p-border-radius-base); - - &::before { - content: ''; - position: absolute; - top: calc(-1 * var(--p-control-border-width)); - right: calc(-1 * var(--p-control-border-width)); - bottom: calc(-1 * var(--p-control-border-width)); - left: calc(-1 * var(--p-control-border-width)); - border-radius: var(--p-border-radius-base); - background-color: var(--p-interactive); - opacity: 0; - transform: scale(0.25); - transition: opacity duration(fast) var(--p-ease), - transform duration(fast) var(--p-ease); - } - - &.hover, - &:hover { - cursor: pointer; - border-color: var(--p-border-hovered); - } - } @else if $style == active { - border-color: var(--p-interactive); - - &::before { - opacity: 1; - transform: scale(1); - @media (-ms-high-contrast: active) { - border: 2px solid ms-high-contrast-color('text'); - } - } - } @else if $style == disabled { - border-color: var(--p-border-disabled); - - &::before { - background-color: var(--p-action-secondary-disabled); - } - - &:hover { - cursor: default; - } - } @else if $style == error { - border-color: var(--p-border-critical); - background-color: var(--p-surface-critical); - - &.hover, - &:hover { - border-color: var(--p-border-critical); - } - - &::before { - background-color: var(--p-border-critical); - } - } - } - - /** - * SHARED: forms - */ - - @mixin unstyled-input { - margin: 0; - padding: 0; - width: 100%; - background-color: transparent; - appearance: none; - - &:focus { - outline: 0; + background-color: var(--p-interactive); + opacity: 0; + transform: scale(0.25); + transition: opacity duration(fast) var(--p-ease), + transform duration(fast) var(--p-ease); } - - &::-moz-focus-outer { - border: 0; - } - } - - @mixin range-track-selectors { - &::-ms-track { - @include high-contrast-outline; - @content; + + &.hover, + &:hover { + cursor: pointer; + border-color: var(--p-border-hovered); } - - &::-moz-range-track { - @content; + } @else if $style == active { + border-color: var(--p-interactive); + + &::before { + opacity: 1; + transform: scale(1); + @media (-ms-high-contrast: active) { + border: 2px solid ms-high-contrast-color('text'); + } } - - &::-webkit-slider-runnable-track { - @content; + } @else if $style == disabled { + border-color: var(--p-border-disabled); + + &::before { + background-color: var(--p-action-secondary-disabled); } - } - - @mixin range-thumb-selectors { - &::-ms-thumb { - @content; + + &:hover { + cursor: default; } - - &::-moz-range-thumb { - @content; + } @else if $style == error { + border-color: var(--p-border-critical); + background-color: var(--p-surface-critical); + + &.hover, + &:hover { + border-color: var(--p-border-critical); } - - &::-webkit-slider-thumb { - @content; + + &::before { + background-color: var(--p-border-critical); } } - - /** - * SHARED: icons - */ - - @function icon-size() { - @return rem(20px); - } - - @mixin recolor-icon( - $fill-color: null, - $secondary-color: null, - $filter-color: null - ) { - svg { - fill: $fill-color; - color: $secondary-color; - } - - img { - filter: $filter-color; - } +} + +/* SHARED: forms */ + +@mixin unstyled-input { + margin: 0; + padding: 0; + width: 100%; + background-color: transparent; + appearance: none; + + &:focus { + outline: 0; } - - @mixin color-icon($value, $hue: base) { - svg { - fill: color($value, $hue); - } - - img { - filter: filter($value, $hue); - } + + &::-moz-focus-outer { + border: 0; } - - /** - * SHARED: layout - */ - - /// To be used on flex items. Resolves some common layout issues, such as - /// text truncation not respecting padding or breaking out of container. - /// https://css-tricks.com/flexbox-truncated-text/ - - @mixin layout-flex-fix { - min-width: 0; - max-width: 100%; - } - - /// Returns a safe-area-inset for iPhone X screen obtrusions. - /// - /// @param {String} $property - The property name i.e. padding-left. - /// @param {Space} $spacing - The spacing value to be added to the safe-area - /// value. i.e. spacing(). - /// @param {string} $area - The area where the inset is to be added. i.e. left - /// - /// If overriding an existing padding / margin that value should be used as - /// $spacing. - @mixin safe-area-for($property, $spacing, $area) { - // stylelint-disable-next-line scss/dimension-no-non-numeric-values - $spacing: if($spacing == 0, #{$spacing}px, $spacing); - #{$property}: #{$spacing}; - #{$property}: calc(#{$spacing} + constant(safe-area-inset-#{$area})); - #{$property}: calc(#{$spacing} + env(safe-area-inset-#{$area})); - } - - @mixin after-topbar-sheet { - @include breakpoint-after(450px) { - @content; - } +} + +@mixin range-track-selectors { + &::-ms-track { + @include high-contrast-outline; + @content; + } + + &::-moz-range-track { + @content; + } + + &::-webkit-slider-runnable-track { + @content; } - - /** - * SHARED: links - */ - - @mixin unstyled-link() { +} + +@mixin range-thumb-selectors { + &::-ms-thumb { + @content; + } + + &::-moz-range-thumb { + @content; + } + + &::-webkit-slider-thumb { + @content; + } +} + +/* SHARED: icons */ + +@function icon-size() { + @return rem(20px); +} + +@mixin recolor-icon( + $fill-color: null, + $secondary-color: null, + $filter-color: null +) { + svg { + fill: $fill-color; + color: $secondary-color; + } + + img { + filter: $filter-color; + } +} + +@mixin color-icon($value, $hue: base) { + svg { + fill: color($value, $hue); + } + + img { + filter: filter($value, $hue); + } +} + +/* SHARED: layout */ + +/// To be used on flex items. Resolves some common layout issues, such as +/// text truncation not respecting padding or breaking out of container. +/// https://css-tricks.com/flexbox-truncated-text/ + +@mixin layout-flex-fix { + min-width: 0; + max-width: 100%; +} + +/// Returns a safe-area-inset for iPhone X screen obtrusions. +/// +/// @param {String} $property - The property name i.e. padding-left. +/// @param {Space} $spacing - The spacing value to be added to the safe-area +/// value. i.e. spacing(). +/// @param {string} $area - The area where the inset is to be added. i.e. left +/// +/// If overriding an existing padding / margin that value should be used as +/// $spacing. +@mixin safe-area-for($property, $spacing, $area) { + // stylelint-disable-next-line scss/dimension-no-non-numeric-values + $spacing: if($spacing == 0, #{$spacing}px, $spacing); + #{$property}: #{$spacing}; + #{$property}: calc(#{$spacing} + constant(safe-area-inset-#{$area})); + #{$property}: calc(#{$spacing} + env(safe-area-inset-#{$area})); +} + +@mixin after-topbar-sheet { + @include breakpoint-after(450px) { + @content; + } +} + +/* SHARED: links */ + +@mixin unstyled-link() { + color: inherit; + text-decoration: none; + + &:visited { color: inherit; - text-decoration: none; - - &:visited { - color: inherit; - } } - - /** - * SHARED: lists - */ - - @mixin unstyled-list { - margin: 0; - padding: 0; - list-style: none; - } - - /** - * SHARED: page - */ - - $actions-vertical-spacing: spacing(tight); - - @mixin page-padding-not-fully-condensed { - padding: 0 spacing(loose); - } - - @mixin page-padding-not-partially-condensed { - padding: 0 spacing(extra-loose); - } - - @mixin page-layout { - margin: 0 auto; - padding: 0; - max-width: $page-max-width; - - @include page-content-when-not-fully-condensed { - @include page-padding-not-fully-condensed; - } - - @include page-content-when-not-partially-condensed { - @include page-padding-not-partially-condensed; - } +} + +/* SHARED: lists */ + +@mixin unstyled-list { + margin: 0; + padding: 0; + list-style: none; +} + +/* SHARED: page */ + +$actions-vertical-spacing: spacing(tight); + +@mixin page-padding-not-fully-condensed { + padding: 0 spacing(loose); +} + +@mixin page-padding-not-partially-condensed { + padding: 0 spacing(extra-loose); +} + +@mixin page-layout { + margin: 0 auto; + padding: 0; + max-width: $page-max-width; + + @include page-content-when-not-fully-condensed { + @include page-padding-not-fully-condensed; } - - @mixin page-content-layout { - margin: spacing(tight) 0; - - @include page-content-when-not-partially-condensed { - margin-top: spacing(loose); - } + + @include page-content-when-not-partially-condensed { + @include page-padding-not-partially-condensed; } - - @mixin page-title-layout { - @include layout-flex-fix; - @include text-breakword; - display: flex; - align-items: baseline; - flex-wrap: wrap; - margin-top: -1 * spacing(tight); - margin-left: -1 * spacing(tight); - - > * { - margin-top: spacing(tight); - margin-left: spacing(tight); - } +} + +@mixin page-content-layout { + margin: spacing(tight) 0; + + @include page-content-when-not-partially-condensed { + margin-top: spacing(loose); } - - @mixin page-header-layout { - padding: spacing(); - - @include page-content-when-not-fully-condensed { - padding-left: 0; - padding-right: 0; - } - - @include page-content-when-not-partially-condensed { - padding: spacing(loose) 0; - } +} + +@mixin page-title-layout { + @include layout-flex-fix; + @include text-breakword; + display: flex; + align-items: baseline; + flex-wrap: wrap; + margin-top: -1 * spacing(tight); + margin-left: -1 * spacing(tight); + + > * { + margin-top: spacing(tight); + margin-left: spacing(tight); } - - @mixin page-header-has-navigation { - padding-top: spacing(); - } - - @mixin page-header-without-navigation { - margin-top: unset; - } - - @mixin page-header-has-secondary-actions { - padding-top: spacing(); - } - - @mixin page-actions-layout { - display: flex; - justify-content: flex-start; - align-items: center; - margin-top: 2 * $actions-vertical-spacing; - - @include page-content-when-not-fully-condensed { - margin-top: $actions-vertical-spacing; - } +} + +@mixin page-header-layout { + padding: spacing(); + + @include page-content-when-not-fully-condensed { + padding-left: 0; + padding-right: 0; } - - /** - * SHARED: typography - */ - - $typography-condensed: em(640px); - - @mixin when-typography-not-condensed { - @include breakpoint-after($typography-condensed) { - @content; - } + + @include page-content-when-not-partially-condensed { + padding: spacing(loose) 0; } - - @mixin when-typography-condensed { - @include breakpoint-before($typography-condensed) { - @content; - } +} + +@mixin page-header-has-navigation { + padding-top: spacing(); +} + +@mixin page-header-without-navigation { + margin-top: unset; +} + +@mixin page-header-has-secondary-actions { + padding-top: spacing(); +} + +@mixin page-actions-layout { + display: flex; + justify-content: flex-start; + align-items: center; + margin-top: 2 * $actions-vertical-spacing; + + @include page-content-when-not-fully-condensed { + margin-top: $actions-vertical-spacing; } - - @mixin text-style-caption { - font-size: font-size(caption); - font-weight: 400; - line-height: line-height(caption); - - @include when-typography-not-condensed { - font-size: font-size(caption, large-screen); - line-height: line-height(caption, large-screen); - } +} + +/* SHARED: typography */ + +$typography-condensed: em(640px); + +@mixin when-typography-not-condensed { + @include breakpoint-after($typography-condensed) { + @content; } - - @mixin text-style-heading { - font-size: font-size(heading); - font-weight: 600; - line-height: line-height(heading); - - @include when-typography-not-condensed { - font-size: font-size(heading, large-screen); - } +} + +@mixin when-typography-condensed { + @include breakpoint-before($typography-condensed) { + @content; } - - @mixin text-style-subheading { - font-size: font-size(subheading); - font-weight: 600; - line-height: line-height(subheading); - text-transform: uppercase; - - @include when-typography-not-condensed { - font-size: font-size(subheading, large-screen); - } +} + +@mixin text-style-caption { + font-size: font-size(caption); + font-weight: 400; + line-height: line-height(caption); + + @include when-typography-not-condensed { + font-size: font-size(caption, large-screen); + line-height: line-height(caption, large-screen); } - - @mixin text-style-input { - font-size: font-size(input); - font-weight: 400; - line-height: line-height(input); - border: none; - - text-transform: initial; - letter-spacing: initial; - - @include when-typography-not-condensed { - font-size: font-size(input, large-screen); - } +} + +@mixin text-style-heading { + font-size: font-size(heading); + font-weight: 600; + line-height: line-height(heading); + + @include when-typography-not-condensed { + font-size: font-size(heading, large-screen); } - - @mixin text-style-body { - font-size: font-size(body); - font-weight: 400; - line-height: line-height(body); - - text-transform: initial; - letter-spacing: initial; - - @include when-typography-not-condensed { - font-size: font-size(body, large-screen); - } +} + +@mixin text-style-subheading { + font-size: font-size(subheading); + font-weight: 600; + line-height: line-height(subheading); + text-transform: uppercase; + + @include when-typography-not-condensed { + font-size: font-size(subheading, large-screen); } - - @mixin text-style-button { - font-size: font-size(button); - font-weight: var(--p-button-font-weight); - line-height: line-height(button); - - text-transform: initial; - letter-spacing: initial; - - @include when-typography-not-condensed { - font-size: font-size(button, large-screen); - } +} + +@mixin text-style-input { + font-size: font-size(input); + font-weight: 400; + line-height: line-height(input); + border: none; + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(input, large-screen); } - - @mixin text-style-button-large { - font-size: font-size(button-large); - font-weight: var(--p-button-font-weight); - line-height: line-height(button-large); - - text-transform: initial; - letter-spacing: initial; - - @include when-typography-not-condensed { - font-size: font-size(button-large, large-screen); - } +} + +@mixin text-style-body { + font-size: font-size(body); + font-weight: 400; + line-height: line-height(body); + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(body, large-screen); } - - @mixin text-style-display-x-large { - font-size: font-size(display-x-large); - font-weight: 600; - line-height: line-height(display-x-large); - - @include when-typography-not-condensed { - font-size: font-size(display-x-large, large-screen); - line-height: line-height(display-x-large, large-screen); - } +} + +@mixin text-style-button { + font-size: font-size(button); + font-weight: var(--p-button-font-weight); + line-height: line-height(button); + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(button, large-screen); } - - @mixin text-style-display-large { - font-size: font-size(display-large); - font-weight: 600; - line-height: line-height(display-large); - - @include when-typography-not-condensed { - font-size: font-size(display-large, large-screen); - line-height: line-height(display-large, large-screen); - } +} + +@mixin text-style-button-large { + font-size: font-size(button-large); + font-weight: var(--p-button-font-weight); + line-height: line-height(button-large); + + text-transform: initial; + letter-spacing: initial; + + @include when-typography-not-condensed { + font-size: font-size(button-large, large-screen); } - - @mixin text-style-display-medium { - font-size: font-size(display-medium); - font-weight: 400; - line-height: line-height(display-medium); - - @include when-typography-not-condensed { - font-size: font-size(display-medium, large-screen); - line-height: line-height(display-medium, large-screen); - } +} + +@mixin text-style-display-x-large { + font-size: font-size(display-x-large); + font-weight: 600; + line-height: line-height(display-x-large); + + @include when-typography-not-condensed { + font-size: font-size(display-x-large, large-screen); + line-height: line-height(display-x-large, large-screen); } - - @mixin text-style-display-small { - font-size: font-size(display-small); - font-weight: 400; - line-height: line-height(display-small); - - @include when-typography-not-condensed { - font-size: font-size(display-small, large-screen); - line-height: line-height(display-small, large-screen); - } +} + +@mixin text-style-display-large { + font-size: font-size(display-large); + font-weight: 600; + line-height: line-height(display-large); + + @include when-typography-not-condensed { + font-size: font-size(display-large, large-screen); + line-height: line-height(display-large, large-screen); } - - @mixin text-emphasis-subdued($for-background: null) { - color: var(--p-text-subdued); - } - - @mixin text-emphasis-strong { - font-weight: 600; - } - - @mixin text-emphasis-normal($for-background: null) { - font-weight: 400; - color: var(--p-text); - } - - @mixin text-breakword { - word-wrap: break-word; - word-break: break-word; - overflow-wrap: break-word; - } - - @mixin truncate { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - - @mixin print-hidden { - @media print { - // stylelint-disable-next-line declaration-no-important - display: none !important; - } +} + +@mixin text-style-display-medium { + font-size: font-size(display-medium); + font-weight: 400; + line-height: line-height(display-medium); + + @include when-typography-not-condensed { + font-size: font-size(display-medium, large-screen); + line-height: line-height(display-medium, large-screen); } - - /** - * SHARED: skeleton - */ - - /// Used to create the shimmer effect of skeleton components - $skeleton-shimmer-duration: duration(slower) * 2; - - // Used by both Thumbnail and SkeletonThumbnail - $small-thumbnail-size: rem(40px); - $medium-thumbnail-size: rem(60px); - $large-thumbnail-size: rem(80px); - - $thumbnail-sizes: ( - small: $small-thumbnail-size, - medium: $medium-thumbnail-size, - large: $large-thumbnail-size, - ); - - @function thumbnail-size($size) { - @return map-get($thumbnail-sizes, $size); - } - - @mixin skeleton-shimmer { - // This is a global animation, defined in /src/components/AppProvider/AppProvider.scss - // See that file for why this is referenced as a custom property instead of - // by name - animation: var(--polaris-animation-skeleton-shimmer) - $skeleton-shimmer-duration linear infinite alternate; - will-change: opacity; - - @media (prefers-reduced-motion) { - animation: none; - } +} + +@mixin text-style-display-small { + font-size: font-size(display-small); + font-weight: 400; + line-height: line-height(display-small); + + @include when-typography-not-condensed { + font-size: font-size(display-small, large-screen); + line-height: line-height(display-small, large-screen); } - - @mixin skeleton-content { - position: relative; - - &::after { - content: ''; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: block; - background-color: var(--p-surface-neutral); - border-radius: border-radius(); - - @media screen and (-ms-high-contrast: active) { - background-color: ms-high-contrast-color('disabled-text'); - } - } +} + +@mixin text-emphasis-subdued($for-background: null) { + color: var(--p-text-subdued); +} + +@mixin text-emphasis-strong { + font-weight: 600; +} + +@mixin text-emphasis-normal($for-background: null) { + font-weight: 400; + color: var(--p-text); +} + +@mixin text-breakword { + word-wrap: break-word; + word-break: break-word; + overflow-wrap: break-word; +} + +@mixin truncate { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +@mixin print-hidden { + @media print { + // stylelint-disable-next-line declaration-no-important + display: none !important; } - - @mixin skeleton-page-secondary-actions-layout { - margin-top: spacing(tight); - display: flex; - flex-direction: row-reverse; - justify-content: flex-end; - align-items: center; - } - - @mixin skeleton-page-header-layout { - padding-bottom: spacing(tight); - } - - /** - * SHARED: interaction-state - */ - - /// Sets the background-image and box-shadow for single or multiple given - /// interaction states. - /// - /// @param {argList} $interaction-states... - Accepts single or multiple - /// interactions states. - @mixin state($interaction-states...) { - $backgrounds: (); - - @each $state in $interaction-states { - $colors: color(state, $state); - $backgrounds: append( - $backgrounds, - linear-gradient($colors, $colors), - comma - ); - - @if $state == 'focused' { - box-shadow: inset rem(2px) 0 0 var(--p-focused); - } - - @if $state == 'focused-destructive' { - box-shadow: inset rem(2px) 0 0 var(--p-focused); - } - } - background-image: $backgrounds; +} + +/* SHARED: skeleton */ + +/// Used to create the shimmer effect of skeleton components +$skeleton-shimmer-duration: duration(slower) * 2; + +// Used by both Thumbnail and SkeletonThumbnail +$small-thumbnail-size: rem(40px); +$medium-thumbnail-size: rem(60px); +$large-thumbnail-size: rem(80px); + +$thumbnail-sizes: ( + small: $small-thumbnail-size, + medium: $medium-thumbnail-size, + large: $large-thumbnail-size, +); + +@function thumbnail-size($size) { + @return map-get($thumbnail-sizes, $size); +} + +@mixin skeleton-shimmer { + // This is a global animation, defined in /src/components/AppProvider/AppProvider.scss + // See that file for why this is referenced as a custom property instead of + // by name + animation: var(--polaris-animation-skeleton-shimmer) + $skeleton-shimmer-duration linear infinite alternate; + will-change: opacity; + + @media (prefers-reduced-motion) { + animation: none; } - - @mixin list-selected-indicator($offset: spacing(tight)) { +} + +@mixin skeleton-content { + position: relative; + + &::after { content: ''; - background-color: var(--p-interactive); position: absolute; top: 0; - left: -1 * $offset; - height: 100%; + right: 0; + bottom: 0; + left: 0; display: block; - width: border-width(thicker); - border-top-right-radius: var(--p-border-radius-base); - border-bottom-right-radius: var(--p-border-radius-base); - } - - /** - * SHARED: printing - */ - - @mixin when-printing { - @media print { - @content; + background-color: var(--p-surface-neutral); + border-radius: border-radius(); + + @media screen and (-ms-high-contrast: active) { + background-color: ms-high-contrast-color('disabled-text'); } } - - @mixin when-not-printing { - @media not print { - @content; +} + +@mixin skeleton-page-secondary-actions-layout { + margin-top: spacing(tight); + display: flex; + flex-direction: row-reverse; + justify-content: flex-end; + align-items: center; +} + +@mixin skeleton-page-header-layout { + padding-bottom: spacing(tight); +} + +/* SHARED: interaction-state */ + +/// Sets the background-image and box-shadow for single or multiple given +/// interaction states. +/// +/// @param {argList} $interaction-states... - Accepts single or multiple +/// interactions states. +@mixin state($interaction-states...) { + $backgrounds: (); + + @each $state in $interaction-states { + $colors: color(state, $state); + $backgrounds: append( + $backgrounds, + linear-gradient($colors, $colors), + comma + ); + + @if $state == 'focused' { + box-shadow: inset rem(2px) 0 0 var(--p-focused); } - } - - @mixin hidden-when-printing { - @include when-printing { - // We really, really don't want to see this thing when it is printed. - // stylelint-disable-next-line declaration-no-important - display: none !important; + + @if $state == 'focused-destructive' { + box-shadow: inset rem(2px) 0 0 var(--p-focused); } - } \ No newline at end of file + } + background-image: $backgrounds; +} + +@mixin list-selected-indicator($offset: spacing(tight)) { + content: ''; + background-color: var(--p-interactive); + position: absolute; + top: 0; + left: -1 * $offset; + height: 100%; + display: block; + width: border-width(thicker); + border-top-right-radius: var(--p-border-radius-base); + border-bottom-right-radius: var(--p-border-radius-base); +} + +/* SHARED: printing */ + +@mixin when-printing { + @media print { + @content; + } +} + +@mixin when-not-printing { + @media not print { + @content; + } +} + +@mixin hidden-when-printing { + @include when-printing { + // We really, really don't want to see this thing when it is printed. + // stylelint-disable-next-line declaration-no-important + display: none !important; + } +} From e180fd39ed0a09b0a9671754acbdf16bf78cd15b Mon Sep 17 00:00:00 2001 From: aveline Date: Wed, 9 Feb 2022 11:00:44 -0800 Subject: [PATCH 6/6] Add to stylelintignore --- .stylelintignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.stylelintignore b/.stylelintignore index 8df1d914d87..64abe0037bc 100644 --- a/.stylelintignore +++ b/.stylelintignore @@ -2,3 +2,4 @@ node_modules /.loom /build /build-internal +/documentation/guides/legacy-polaris-v8-public-api.scss