UNPKG

@wikimedia/codex

Version:

Codex Design System for Wikimedia

292 lines (265 loc) 12.6 kB
@import ( reference ) '@wikimedia/codex-icons/codex-icon-paths.less'; // // To create a CSS-only icon you can do one of the following: // 1. Apply the .cdx-mixin-css-icon() mixin to an empty <span>, passing in at least the icon param. // This method should suffice for any square icon that can exist as a standalone element. This // mixin applies all of the other mixins inside this file. See Message.vue for sample usage. // 2. Apply the individual CSS icon mixins for background, size, alignment, and/or background-image // rules to any element. This can be used to apply an icon within another element, like the // <select> handle. See Select.vue for sample usage. // // These mixins account for icons that vary by reading direction or language. // // Get the associated min-size-icon from a size-icon token. .get-calculated-min-size-icon( @param-size-icon ) { // Fallback: when an unrecognized value is passed in, don't crash, but use the same value // for size and min-size (T367098). This code runs for all values, but for recognized values // it's overridden by one of the lines below. @calculated-min-size-icon: @param-size-icon; } .get-calculated-min-size-icon( @param-size-icon ) when ( @param-size-icon = @size-icon-medium ) { @calculated-min-size-icon: @min-size-icon-medium; } .get-calculated-min-size-icon( @param-size-icon ) when ( @param-size-icon = @size-icon-small ) { @calculated-min-size-icon: @min-size-icon-small; } .get-calculated-min-size-icon( @param-size-icon ) when ( @param-size-icon = @size-icon-x-small ) { @calculated-min-size-icon: @min-size-icon-x-small; } // // Get background rules for a CSS icon (or mask rules for icons in buttons). // // @param {string} size-icon - The size of the icon, used to set background-size // @param {string} background-position - The background position value // @param {boolean} is-button-icon: Whether this icon is inside of a <button> element. // .cdx-mixin-css-icon-background( @param-size-icon: @size-icon-medium, @param-background-position: @background-position-base, @param-is-button-icon: false ) { .get-calculated-min-size-icon( @param-size-icon ); // Support Firefox v39-52: fall back to background rules. // Support Chrome: Chrome requires the `-webkit` prefix so we must use it in all // `@supports` queries. @supports not ( ( -webkit-mask-image: none ) or ( mask-image: none ) ) { background-position: @param-background-position; background-repeat: no-repeat; // Set background size to the relative @param-size-icon or to @calculated-min-size-icon, // whichever is larger. // This ensures that the icon will never appear smaller than @calculated-min-size-icon. // Escape the max() call to prevent older Less versions from trying to do the max() // calculation at compile time. /* stylelint-disable-next-line plugin/no-unsupported-browser-features */ background-size: calc( ~'max( @{param-size-icon}, @{calculated-min-size-icon} )' ); } @supports ( -webkit-mask-image: none ) or ( mask-image: none ) { /* stylelint-disable plugin/no-unsupported-browser-features */ // Support Chrome: set `-webkit` prefixes explicitly for usage without Autoprefixer. // While Codex integrates Autoprefixer, MediaWiki does not. -webkit-mask-position: @param-background-position; mask-position: @param-background-position; // Support Chrome -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; // Support Chrome -webkit-mask-size: calc( ~'max( @{param-size-icon}, @{calculated-min-size-icon} )' ); mask-size: calc( ~'max( @{param-size-icon}, @{calculated-min-size-icon} )' ); /* stylelint-enable plugin/no-unsupported-browser-features */ } } // // Get size styles for a CSS icon. // // This sets min-width, min-height, width, and height for a square icon. // // @param {string} size-icon: The size of the icon (base, small, x-small, or indicator) // .cdx-mixin-css-icon-size( @param-size-icon: @size-icon-medium ) { .get-calculated-min-size-icon( @param-size-icon ); // Set the default icon size. min-width: @calculated-min-size-icon; min-height: @calculated-min-size-icon; // Scale width/height of the span with font size. width: @param-size-icon; height: @param-size-icon; } // // Get alignment styles for a CSS icon. // // @param {string} vertical-align: The vertical-align value // .cdx-mixin-css-icon-alignment( @param-vertical-align: text-bottom ) { display: inline-block; // Vertically align surrounding text in inline, inline-block, and table contexts. vertical-align: @param-vertical-align; } // Set the color of a mask-image-based icon // // @param {hex} fill-color - The fill color of the icon // @param {boolean} is-button-icon - Whether this icon is inside of a <button> element .cdx-mixin-css-icon-mask-image-color( @param-fill-color, @param-is-button-icon ) { // For icons outside of buttons, use background-color to set the icon color. & when not ( @param-is-button-icon ) { background-color: @param-fill-color; } // For icons within buttons, set transition rules. The icon color will be changed in the // Button component depending on props and state. & when ( @param-is-button-icon ) { transition-property: @transition-property-icon-css-only; transition-duration: @transition-duration-base; } } // // Set the icon image, either via mask-image or background-image. // // For browsers that support mask-image, this mixin will apply the background image as a mask, so // that background-color rules in the Button styles can set the icon color. // // For browsers that don't support mask-image, this mixin sets the icon as a background image with // the color set via opacity. // // @param {string} icon - The icon to show // @param {hex} fill-color - The fill color of the icon (defaults to @color-base) // @param {boolean} is-button-icon - Whether this icon is inside of a <button> element // .cdx-mixin-css-icon-try-mask-image( @param-icon, @param-fill-color, @param-is-button-icon ) { @hex-color-black: #000; @escaped-color-black: escape( @hex-color-black ); @image-url: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="@{escaped-color-black}">@{param-icon}</svg>'; // Support Firefox v39-52: fall back to background-image. // Support Chrome: Chrome requires the `-webkit` prefix so we must use it in all // `@supports` queries. @supports not ( ( -webkit-mask-image: none ) or ( mask-image: none ) ) { background-image: url( @image-url ); // Set icon color to white in night mode. filter: invert( @filter-invert-icon ); // Set icon color closer to @color-base. opacity: @opacity-icon-base; // Fallback for @color-inverted icons within buttons. & when ( @param-is-button-icon ) { .cdx-button:not( .cdx-button--weight-quiet ):disabled &, .cdx-button--weight-primary.cdx-button--action-progressive &, .cdx-button--weight-primary.cdx-button--action-destructive & { // Set icon color close to @color-inverted. filter: invert( @filter-invert-primary-button-icon ); } } } // For browsers that support it, use mask-image to set the SVG so we can change the color with // much more granularity. @supports ( -webkit-mask-image: none ) or ( mask-image: none ) { // Support Chrome /* stylelint-disable-next-line plugin/no-unsupported-browser-features */ -webkit-mask-image: url( @image-url ); /* stylelint-disable-next-line plugin/no-unsupported-browser-features */ mask-image: url( @image-url ); // Set background-color to color the icon .cdx-mixin-css-icon-mask-image-color( @param-fill-color, @param-is-button-icon ); } } // // Get rules to set the appropriate image for the icon. // // Note that in RTL contexts, this mixin requires `dir="rtl"` either on the icon element itself // or on the <html> element. // // This mixin takes in an icon, which is really a Less variable generated by the codex-icons // package. These variables are lists of icon data that contain: // 1. The default icon path (a string) // 2. Whether the icon should flip in RTL ('true' or 'false') // 3. Exceptions to the flip rule ('false' or a selector string that will rule out languages) // 4. RTL-specific icon path ('false' or the path string) // 5. Whether the icon has language-specific variants ('true' or 'false') // 6+ If there are language-specific variants, they will be included as string pairs after the other // icon data. The first item in the pair is a lang code and the second is the icon path for that // language. // // @param {string} icon - The icon to show (follows the pattern @cdx-icon-icon-name, e.g. @cdx-icon-info-filled ) // @param {hex} fill-color - The fill color of the icon (defaults to @color-base) // @param {boolean} is-button-icon - Whether this icon is inside of a <button> element // .cdx-mixin-css-icon-background-image( @param-icon, @param-fill-color: @color-base, @param-is-button-icon: false ) { // Extract icon data from the list. @default-icon: extract( @param-icon, 1 ); @should-flip: extract( @param-icon, 2 ); @flip-exceptions: extract( @param-icon, 3 ); @rtl-icon: extract( @param-icon, 4 ); @has-lang-variants: extract( @param-icon, 5 ); // Add default image. .cdx-mixin-css-icon-try-mask-image( @default-icon, @param-fill-color, @param-is-button-icon ); // Flip icons with no shouldFlip exceptions. & when ( @should-flip = 'true' ) and ( @flip-exceptions = 'false' ) { &[ dir='rtl' ], html[ dir='rtl' ] &:not( [ dir='ltr' ] ) { transform: scaleX( -1 ); } } // Flip icons with shouldFlip exceptions. & when ( @should-flip = 'true' ) and not ( @flip-exceptions = 'false' ) { // Create a selector string out of each exception lang code. // Final selector will look like `:not( :lang( he ) ):not( :lang( yi ) )` @exceptions-selector: e( replace( @flip-exceptions, '(^| )([^ ]+)', ':not( :lang( $2 ) )', 'g' ) ); &[ dir='rtl' ], html[ dir='rtl' ] &:not( [ dir='ltr' ] ) { &@{exceptions-selector} { transform: scaleX( -1 ); } } } // If an icon has an RTL-specific icon, apply it. & when not ( @rtl-icon = 'false' ) { &[ dir='rtl' ], html[ dir='rtl' ] &:not( [ dir='ltr' ] ) { .cdx-mixin-css-icon-try-mask-image( @rtl-icon, @param-fill-color, @param-is-button-icon ); } } // Set language-specific icons. & when ( @has-lang-variants = 'true' ) { @icon-list-length: length( @param-icon ); // Language-specific icons are represented by list items in @param-icon. They consist of a // lang code, e.g. ar, and an icon path. // Since we can't use modern Less features in MediaWiki, we need a recursive mixin. .get-lang-rules( @i: 6 ) when ( @i <= @icon-list-length ) { @lang-data: extract( @param-icon, @i ); @lang-code: extract( @lang-data, 1 ); @lang-icon: extract( @lang-data, 2 ); &:lang( @{lang-code} ) { .cdx-mixin-css-icon-try-mask-image( @lang-icon, @param-fill-color, @param-is-button-icon ); } .get-lang-rules( @i + 1 ); } .get-lang-rules(); } } // // Create a square, standalone CSS icon. // // This mixin only supports icons provided by Codex, which will be embedded as data URLs. To provide // a custom icon (either as a data URL or as a regular URL), set @param-icon to 'none', and set // `mask-image` and `-webkit-mask-image` to the URL of the custom icon. // // @param {string} icon - The icon to show (follows the pattern @cdx-icon-icon-name, e.g. @cdx-icon-info-filled), or 'none' // @param {hex} fill-color - The fill color of the icon // @param {string} size-icon: The size of the icon // @param {boolean} is-button-icon: Whether this icon is inside of a <button> element. // @param {string} background-position - The background position value // @param {string} vertical-align: The vertical-align value // /* stylelint-disable @stylistic/indentation */ .cdx-mixin-css-icon( @param-icon, @param-fill-color: @color-base, @param-size-icon: @size-icon-medium, @param-is-button-icon: false, @param-background-position: @background-position-base, @param-vertical-align: text-bottom ) { /* stylelint-enable @stylistic/indentation */ .cdx-mixin-css-icon-background( @param-size-icon, @param-background-position, @param-is-button-icon ); .cdx-mixin-css-icon-size( @param-size-icon ); .cdx-mixin-css-icon-alignment( @param-vertical-align ); & when not ( @param-icon = 'none' ) { .cdx-mixin-css-icon-background-image( @param-icon, @param-fill-color, @param-is-button-icon ); } & when ( @param-icon = 'none' ) { // The caller is going to set mask-image themselves; but we still need to set the color .cdx-mixin-css-icon-mask-image-color( @param-fill-color, @param-is-button-icon ); } }