diff --git a/README.md b/README.md index 2a1e5ce8ad3..e03779da487 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,9 @@ If you're targeting modern browsers, start by including the base set of variable + + + @@ -72,13 +75,28 @@ Then, make sure you've included the relevant classes to choose which scale and c ``` -**Note:** If you are importing SVG icon sprite sheets, the `.spectrum--medium`/`.spectrum--large` classes should be added to the `` element so UI icons render in the correct size in IE 11. For browsers that support custom properties, or if you're not using SVG sprite sheets for UI icons and are manually managing icon sizing in your implementation, `.spectrum--medium`/`.spectrum--large` can be added to the `` or other element. +To switch to Express, load vars from `@spectrum-css/expressvars` instead of `@spectrum-css/vars` and add the `.spectrum--express` class to the `` element: + +```html + + + + + + + + + + +``` Then you can use components by copy/pasting their code from [the documentation](http://opensource.adobe.com/spectrum-css/). With the magic of CSS custom properties, you can infinitely nest different color stops and themes, [as illustrated here](https://codepen.io/lazd/pen/axXMRL). -Additionally, you can override variables and customize Spectrum CSS' look and feel by re-defining the custom properties in context, [like so](https://codepen.io/lazd/pen/ROvOPO). See the source in `components/*/index-vars.css` to determine which custom properties you can override. +### Modifying components + +You can override variables and modify Spectrum CSS' look and feel by re-defining the custom properties in context. Look for the **Custom Property API** section in each component to determine which custom properties you can override. See [ActionButton for a complete example](https://opensource.adobe.com/spectrum-css/actionbutton.html#modified). ### Importing UI icons diff --git a/components/actionbutton/actionbutton-generated.css b/components/actionbutton/actionbutton-generated.css deleted file mode 100644 index c591eeef761..00000000000 --- a/components/actionbutton/actionbutton-generated.css +++ /dev/null @@ -1,492 +0,0 @@ -/* -Copyright 2021 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -/* begin generated CSS for actionbutton */ -.spectrum-ActionButton { - &.spectrum-ActionButton--staticBlack { - &:not(.spectrum-ActionButton--quiet) { - &:disabled { - border-color: var(--spectrum-alias-actionbutton-staticBlack-border-color-disabled); - - &.is-selected { - border-color: var(--spectrum-alias-actionbutton-staticBlack-border-color-disabled-selected) - } - - &:not(.is-selected) { - background-color: var(--spectrum-alias-actionbutton-staticBlack-background-color-disabled) - } - } - - &:not(:disabled) { - border-color: var(--spectrum-alias-actionbutton-staticBlack-border-color-default); - - &:hover { - border-color: var(--spectrum-alias-actionbutton-staticBlack-border-color-hover) - } - - &:active { - border-color: var(--spectrum-alias-actionbutton-staticBlack-border-color-down) - } - - &:focus-visible { - border-color: var(--spectrum-alias-actionbutton-staticBlack-border-color-key-focus) - } - - &.is-keyboardFocused { - border-color: var(--spectrum-alias-actionbutton-staticBlack-border-color-key-focus) - } - - &:not(.is-selected) { - background-color: var(--spectrum-alias-actionbutton-staticBlack-background-color-default); - - &:hover { - background-color: var(--spectrum-alias-actionbutton-staticBlack-background-color-hover) - } - - &:active { - background-color: var(--spectrum-alias-actionbutton-staticBlack-background-color-down) - } - - &:focus-visible { - background-color: var(--spectrum-alias-actionbutton-staticBlack-background-color-key-focus) - } - - &.is-keyboardFocused { - background-color: var(--spectrum-alias-actionbutton-staticBlack-background-color-key-focus) - } - } - } - } - - &.spectrum-ActionButton--quiet { - &:disabled { - border-color: transparent; - - &:not(.is-selected) { - background-color: transparent - } - } - - &:not(:disabled) { - border-color: transparent; - - &:not(.is-selected) { - background-color: var(--spectrum-alias-component-background-color-quiet-default); - - &:hover { - background-color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-25)) - } - - &:active { - background-color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-40)) - } - - &:focus-visible { - background-color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-25)) - } - - &.is-keyboardFocused { - background-color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-25)) - } - } - } - } - - &:disabled { - &.is-selected { - background-color: var(--spectrum-alias-actionbutton-staticBlack-background-color-disabled-selected); - - .spectrum-ActionButton-holdIcon { - color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-40)) - } - - .spectrum-ActionButton-label { - color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-40)) - } - - .spectrum-Icon { - color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-40)) - } - } - - .spectrum-ActionButton-holdIcon { - color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-40)) - } - - .spectrum-ActionButton-label { - color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-40)) - } - - .spectrum-Icon { - color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-40)) - } - } - - &.is-selected { - &:not(:disabled) { - background-color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-90)); - - &:hover { - background-color: var(--spectrum-global-color-static-black) - } - - &:active { - background-color: var(--spectrum-global-color-static-black) - } - - &:focus-visible { - background-color: var(--spectrum-global-color-static-black) - } - - &.is-keyboardFocused { - background-color: var(--spectrum-global-color-static-black) - } - - .spectrum-ActionButton-holdIcon { - color: inherit - } - - .spectrum-ActionButton-label { - color: inherit - } - - .spectrum-Icon { - color: inherit - } - } - } - - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-ActionButton-static-black-color) - } - - &:not(:disabled) { - &:not(.is-selected) { - .spectrum-ActionButton-holdIcon { - color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-90)) - } - - &:hover { - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-global-color-static-black) - } - - .spectrum-ActionButton-label { - color: var(--spectrum-global-color-static-black) - } - - .spectrum-Icon { - color: var(--spectrum-global-color-static-black) - } - } - - &:active { - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-global-color-static-black) - } - - .spectrum-ActionButton-label { - color: var(--spectrum-global-color-static-black) - } - - .spectrum-Icon { - color: var(--spectrum-global-color-static-black) - } - } - - &:focus-visible { - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-global-color-static-black) - } - - .spectrum-ActionButton-label { - color: var(--spectrum-global-color-static-black) - } - - .spectrum-Icon { - color: var(--spectrum-global-color-static-black) - } - } - - &.is-keyboardFocused { - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-global-color-static-black) - } - - .spectrum-ActionButton-label { - color: var(--spectrum-global-color-static-black) - } - - .spectrum-Icon { - color: var(--spectrum-global-color-static-black) - } - } - - .spectrum-ActionButton-label { - color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-90)) - } - - .spectrum-Icon { - color: rgba(var(--spectrum-global-color-static-black-rgb), var(--spectrum-global-color-opacity-90)) - } - } - } - - .spectrum-ActionButton-label { - color: var(--spectrum-ActionButton-static-black-color) - } - - .spectrum-Icon { - color: var(--spectrum-ActionButton-static-black-color) - } - } - - &.spectrum-ActionButton--staticWhite { - &:not(.spectrum-ActionButton--quiet) { - &:disabled { - border-color: var(--spectrum-alias-actionbutton-staticWhite-border-color-disabled); - - &.is-selected { - border-color: var(--spectrum-alias-actionbutton-staticWhite-border-color-disabled-selected) - } - - &:not(.is-selected) { - background-color: var(--spectrum-alias-actionbutton-staticWhite-background-color-disabled) - } - } - - &:not(:disabled) { - border-color: var(--spectrum-alias-actionbutton-staticWhite-border-color-default); - - &:hover { - border-color: var(--spectrum-alias-actionbutton-staticWhite-border-color-hover) - } - - &:active { - border-color: var(--spectrum-alias-actionbutton-staticWhite-border-color-down) - } - - &:focus-visible { - border-color: var(--spectrum-alias-actionbutton-staticWhite-border-color-key-focus) - } - - &.is-keyboardFocused { - border-color: var(--spectrum-alias-actionbutton-staticWhite-border-color-key-focus) - } - - &:not(.is-selected) { - background-color: var(--spectrum-alias-actionbutton-staticWhite-background-color-default); - - &:hover { - background-color: var(--spectrum-alias-actionbutton-staticWhite-background-color-hover) - } - - &:active { - background-color: var(--spectrum-alias-actionbutton-staticWhite-background-color-down) - } - - &:focus-visible { - background-color: var(--spectrum-alias-actionbutton-staticWhite-background-color-key-focus) - } - - &.is-keyboardFocused { - background-color: var(--spectrum-alias-actionbutton-staticWhite-background-color-key-focus) - } - } - } - } - - &.spectrum-ActionButton--quiet { - &:disabled { - border-color: transparent; - - &:not(.is-selected) { - background-color: transparent - } - } - - &:not(:disabled) { - border-color: transparent; - - &:not(.is-selected) { - background-color: var(--spectrum-alias-component-background-color-quiet-default); - - &:hover { - background-color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-25)) - } - - &:active { - background-color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-40)) - } - - &:focus-visible { - background-color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-25)) - } - - &.is-keyboardFocused { - background-color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-25)) - } - } - } - } - - &:disabled { - &.is-selected { - background-color: var(--spectrum-alias-actionbutton-staticWhite-background-color-disabled-selected); - - .spectrum-ActionButton-holdIcon { - color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-40)) - } - - .spectrum-ActionButton-label { - color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-40)) - } - - .spectrum-Icon { - color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-40)) - } - } - - .spectrum-ActionButton-holdIcon { - color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-40)) - } - - .spectrum-ActionButton-label { - color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-40)) - } - - .spectrum-Icon { - color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-40)) - } - } - - &.is-selected { - &:not(:disabled) { - background-color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-90)); - - &:hover { - background-color: var(--spectrum-global-color-static-white) - } - - &:active { - background-color: var(--spectrum-global-color-static-white) - } - - &:focus-visible { - background-color: var(--spectrum-global-color-static-white) - } - - &.is-keyboardFocused { - background-color: var(--spectrum-global-color-static-white) - } - - .spectrum-ActionButton-holdIcon { - color: inherit - } - - .spectrum-ActionButton-label { - color: inherit - } - - .spectrum-Icon { - color: inherit - } - } - } - - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-ActionButton-static-white-color) - } - - &:not(:disabled) { - &:not(.is-selected) { - .spectrum-ActionButton-holdIcon { - color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-90)) - } - - &:hover { - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-global-color-static-white) - } - - .spectrum-ActionButton-label { - color: var(--spectrum-global-color-static-white) - } - - .spectrum-Icon { - color: var(--spectrum-global-color-static-white) - } - } - - &:active { - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-global-color-static-white) - } - - .spectrum-ActionButton-label { - color: var(--spectrum-global-color-static-white) - } - - .spectrum-Icon { - color: var(--spectrum-global-color-static-white) - } - } - - &:focus-visible { - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-global-color-static-white) - } - - .spectrum-ActionButton-label { - color: var(--spectrum-global-color-static-white) - } - - .spectrum-Icon { - color: var(--spectrum-global-color-static-white) - } - } - - &.is-keyboardFocused { - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-global-color-static-white) - } - - .spectrum-ActionButton-label { - color: var(--spectrum-global-color-static-white) - } - - .spectrum-Icon { - color: var(--spectrum-global-color-static-white) - } - } - - .spectrum-ActionButton-label { - color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-90)) - } - - .spectrum-Icon { - color: rgba(var(--spectrum-global-color-static-white-rgb), var(--spectrum-global-color-opacity-90)) - } - } - } - - .spectrum-ActionButton-label { - color: var(--spectrum-ActionButton-static-white-color) - } - - .spectrum-Icon { - color: var(--spectrum-ActionButton-static-white-color) - } - } -} - -/* end generated CSS for actionbutton */ diff --git a/components/actionbutton/gulpfile.js b/components/actionbutton/gulpfile.js index 3d2a7fa4e41..f13104999f1 100644 --- a/components/actionbutton/gulpfile.js +++ b/components/actionbutton/gulpfile.js @@ -1 +1 @@ -module.exports = require('@spectrum-css/component-builder'); +module.exports = require('@spectrum-css/component-builder-simple'); diff --git a/components/actionbutton/index.css b/components/actionbutton/index.css index 5bee87f2a3f..45581b4de53 100644 --- a/components/actionbutton/index.css +++ b/components/actionbutton/index.css @@ -10,184 +10,229 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -@import "../commons/basebutton.css"; -@import "../vars/css/components/spectrum-actionbutton.css"; -@import "./actionbutton-generated.css"; +@import "../commons/basebutton-coretokens.css"; -.spectrum-ActionButton--sizeS { - @remapvars { - find: --spectrum-actionbutton-s-; - replace: --spectrum-actionbutton-; - } - - /* todo: remove hardcoded values when we update DNA */ - --spectrum-actionbutton-hold-icon-padding-bottom: var(--spectrum-global-dimension-size-25); - --spectrum-actionbutton-hold-icon-padding-right: var(--spectrum-global-dimension-size-25); +.spectrum-ActionButton { + --spectrum-actionbutton-animation-duration: var(--spectrum-animation-duration-100); + --spectrum-actionbutton-border-radius: var(--spectrum-corner-radius-100); + --spectrum-actionbutton-border-width: var(--spectrum-border-width-100); + + --spectrum-actionbutton-focus-ring-gap: var(--spectrum-focus-ring-gap); + --spectrum-actionbutton-focus-ring-thickness: var(--spectrum-focus-ring-thickness); + --spectrum-actionbutton-focus-ring-color: var(--spectrum-focus-ring-color); + --spectrum-actionbutton-focus-ring-border-radius: calc(var(--spectrum-actionbutton-border-radius) + var(--spectrum-actionbutton-focus-ring-gap)); +} - /* hack to fix the incorrect min-width */ - --spectrum-actionbutton-textonly-min-width: var(--spectrum-global-dimension-size-300); +.spectrum-ActionButton--sizeS { + --spectrum-actionbutton-min-width: var(--spectrum-component-minimum-width-75); + --spectrum-actionbutton-height: var(--spectrum-component-height-75); + + --spectrum-actionbutton-icon-size: var(--spectrum-workflow-icon-size-75); + --spectrum-actionbutton-font-size: var(--spectrum-font-size-75); + --spectrum-actionbutton-text-to-visual: var(--spectrum-text-to-visual-75); + --spectrum-actionbutton-edge-to-hold-icon: var(--spectrum-action-button-edge-to-hold-icon-small); + --spectrum-actionbutton-edge-to-visual: calc(var(--spectrum-edge-to-visual-75) - var(--spectrum-actionbutton-border-width)); + --spectrum-actionbutton-edge-to-text: calc(var(--spectrum-edge-to-text-75) - var(--spectrum-actionbutton-border-width)); + --spectrum-actionbutton-edge-to-visual-only: calc(var(--spectrum-edge-to-visual-only-75) - var(--spectrum-actionbutton-border-width)); } .spectrum-ActionButton--sizeM { - @remapvars { - find: --spectrum-actionbutton-m-; - replace: --spectrum-actionbutton-; - } - - /* todo: remove hardcoded values when we update DNA */ - --spectrum-actionbutton-hold-icon-padding-bottom: var(--spectrum-global-dimension-size-40); - --spectrum-actionbutton-hold-icon-padding-right: var(--spectrum-global-dimension-size-40); + --spectrum-actionbutton-min-width: var(--spectrum-component-minimum-width-100); + --spectrum-actionbutton-height: var(--spectrum-component-height-100); + + --spectrum-actionbutton-icon-size: var(--spectrum-workflow-icon-size-100); + --spectrum-actionbutton-font-size: var(--spectrum-font-size-100); + --spectrum-actionbutton-text-to-visual: var(--spectrum-text-to-visual-100); + --spectrum-actionbutton-edge-to-hold-icon: var(--spectrum-action-button-edge-to-hold-icon-medium); + --spectrum-actionbutton-edge-to-visual: calc(var(--spectrum-edge-to-visual-100) - var(--spectrum-actionbutton-border-width)); + --spectrum-actionbutton-edge-to-text: calc(var(--spectrum-edge-to-text-100) - var(--spectrum-actionbutton-border-width)); + --spectrum-actionbutton-edge-to-visual-only: calc(var(--spectrum-edge-to-visual-only-100) - var(--spectrum-actionbutton-border-width)); } .spectrum-ActionButton--sizeL { - @remapvars { - find: --spectrum-actionbutton-l-; - replace: --spectrum-actionbutton-; - } - - /* todo: remove hardcoded values when we update DNA */ - --spectrum-actionbutton-hold-icon-padding-bottom: var(--spectrum-global-dimension-size-50); - --spectrum-actionbutton-hold-icon-padding-right: var(--spectrum-global-dimension-size-50); + --spectrum-actionbutton-min-width: var(--spectrum-component-minimum-width-200); + --spectrum-actionbutton-height: var(--spectrum-component-height-200); + + --spectrum-actionbutton-icon-size: var(--spectrum-workflow-icon-size-200); + --spectrum-actionbutton-font-size: var(--spectrum-font-size-200); + --spectrum-actionbutton-text-to-visual: var(--spectrum-text-to-visual-200); + --spectrum-actionbutton-edge-to-hold-icon: var(--spectrum-action-button-edge-to-hold-icon-large); + --spectrum-actionbutton-edge-to-visual: calc(var(--spectrum-edge-to-visual-200) - var(--spectrum-actionbutton-border-width)); + --spectrum-actionbutton-edge-to-text: calc(var(--spectrum-edge-to-text-200) - var(--spectrum-actionbutton-border-width)); + --spectrum-actionbutton-edge-to-visual-only: calc(var(--spectrum-edge-to-visual-only-200) - var(--spectrum-actionbutton-border-width)); } .spectrum-ActionButton--sizeXL { - @remapvars { - find: --spectrum-actionbutton-xl-; - replace: --spectrum-actionbutton-; - } - - /* todo: remove hardcoded values when we update DNA */ - --spectrum-actionbutton-hold-icon-padding-bottom: var(--spectrum-global-dimension-size-65); - --spectrum-actionbutton-hold-icon-padding-right: var(--spectrum-global-dimension-size-65); + --spectrum-actionbutton-min-width: var(--spectrum-component-minimum-width-300); + --spectrum-actionbutton-height: var(--spectrum-component-height-300); + + --spectrum-actionbutton-icon-size: var(--spectrum-workflow-icon-size-300); + --spectrum-actionbutton-font-size: var(--spectrum-font-size-300); + --spectrum-actionbutton-text-to-visual: var(--spectrum-text-to-visual-300); + --spectrum-actionbutton-edge-to-hold-icon: var(--spectrum-action-button-edge-to-hold-icon-extra-large); + --spectrum-actionbutton-edge-to-visual: calc(var(--spectrum-edge-to-visual-300) - var(--spectrum-actionbutton-border-width)); + --spectrum-actionbutton-edge-to-text: calc(var(--spectrum-edge-to-text-300) - var(--spectrum-actionbutton-border-width)); + --spectrum-actionbutton-edge-to-visual-only: calc(var(--spectrum-edge-to-visual-only-300) - var(--spectrum-actionbutton-border-width)); } -.spectrum-ActionButton {/* --spectrum-actionbutton-textonly-padding-left 12px */ /* --spectrum-actionbutton-textonly-border-size 1px */ - /* Adjustments for inset/outset padding in DNA */ - --spectrum-actionbutton-padding-left-adjusted: calc(var(--spectrum-actionbutton-texticon-padding-left) - var(--spectrum-actionbutton-texticon-border-size)); - --spectrum-actionbutton-padding-right-adjusted: calc(var(--spectrum-actionbutton-texticon-padding-right) - var(--spectrum-actionbutton-texticon-border-size)); - --spectrum-actionbutton-textonly-padding-left-adjusted: calc(var(--spectrum-actionbutton-textonly-padding-left) - var(--spectrum-actionbutton-textonly-border-size)); - --spectrum-actionbutton-textonly-padding-right-adjusted: calc(var(--spectrum-actionbutton-textonly-padding-right) - var(--spectrum-actionbutton-textonly-border-size)); - --spectrum-actionbutton-icononly-padding-left-adjusted: calc(var(--spectrum-actionbutton-icononly-padding-left) - var(--spectrum-actionbutton-icononly-border-size)); - --spectrum-actionbutton-icononly-padding-right-adjusted: calc(var(--spectrum-actionbutton-icononly-padding-right) - var(--spectrum-actionbutton-icononly-border-size)); - --spectrum-actionbutton-focus-ring-border-radius-adjusted: calc(var(--spectrum-actionbutton-quiet-textonly-border-radius) + var(--spectrum-actionbutton-focus-ring-gap)); -} +@media (forced-colors: active) { + .spectrum-ActionButton { + &:after { + /* make sure focus-ring renders */ + forced-color-adjust: none; + } -a.spectrum-ActionButton { - @inherit: %spectrum-AnchorButton; + /* force a more visible focus-ring color */ + --highcontrast-actionbutton-focus-ring-color: ButtonText; + + &.is-selected { + --highcontrast-actionbutton-background-color-default: Highlight; + --highcontrast-actionbutton-background-color-hover: Highlight; + --highcontrast-actionbutton-background-color-focus: Highlight; + --highcontrast-actionbutton-background-color-down: Highlight; + --highcontrast-actionbutton-background-color-disabled: ButtonFace; + + --highcontrast-actionbutton-border-color-default: HighlightText; + --highcontrast-actionbutton-border-color-hover: HighlightText; + --highcontrast-actionbutton-border-color-focus: HighlightText; + --highcontrast-actionbutton-border-color-down: HighlightText; + --highcontrast-actionbutton-border-color-disabled: GrayText; + + --highcontrast-actionbutton-content-color-default: HighlightText; + --highcontrast-actionbutton-content-color-hover: HighlightText; + --highcontrast-actionbutton-content-color-focus: HighlightText; + --highcontrast-actionbutton-content-color-down: HighlightText; + --highcontrast-actionbutton-content-color-disabled: GrayText; + + .spectrum-ActionButton-icon, + .spectrum-ActionButton-hold, + .spectrum-ActionButton-label { + /* ensure custom text colors from above get applied */ + /* it seems like this shouldn't have to be done, but colors are wrong without it */ + forced-color-adjust: none; + } + } + } } .spectrum-ActionButton { @inherit: %spectrum-BaseButton; position: relative; - block-size: var(--spectrum-actionbutton-textonly-height); - min-inline-size: var(--spectrum-actionbutton-textonly-min-width); + min-inline-size: var(--mod-actionbutton-min-width, var(--spectrum-actionbutton-min-width)); + height: var(--mod-actionbutton-height, var(--spectrum-actionbutton-height)); + + border-radius: var(--mod-actionbutton-border-radius, var(--spectrum-actionbutton-border-radius)); + border-width: var(--mod-actionbutton-border-width, var(--spectrum-actionbutton-border-width)); /* Start with text-only padding */ - padding-inline: var(--spectrum-actionbutton-textonly-padding-left-adjusted) var(--spectrum-actionbutton-textonly-padding-right-adjusted); + padding-inline-start: var(--mod-actionbutton-edge-to-text, var(--spectrum-actionbutton-edge-to-text)); + padding-inline-end: var(--mod-actionbutton-edge-to-text, var(--spectrum-actionbutton-edge-to-text)); - border-width: var(--spectrum-actionbutton-textonly-border-size); - border-radius: var(--spectrum-actionbutton-textonly-border-radius); + background-color: var(--highcontrast-actionbutton-background-color-default, var(--mod-actionbutton-background-color-default, var(--spectrum-actionbutton-background-color-default))); + border-color: var(--highcontrast-actionbutton-border-color-default, var(--mod-actionbutton-border-color-default, var(--spectrum-actionbutton-border-color-default))); + color: var(--highcontrast-actionbutton-content-color-default, var(--mod-actionbutton-content-color-default, var(--spectrum-actionbutton-content-color-default))); - font-size: var(--spectrum-actionbutton-textonly-text-size); - font-weight: var(--spectrum-actionbutton-textonly-text-font-weight); - line-height: var(--spectrum-actionbutton-textonly-text-line-height); + &:hover { + background-color: var(--highcontrast-actionbutton-background-color-hover, var(--mod-actionbutton-background-color-hover, var(--spectrum-actionbutton-background-color-hover))); + border-color: var(--highcontrast-actionbutton-border-color-hover, var(--mod-actionbutton-border-color-hover, var(--spectrum-actionbutton-border-color-hover))); + color: var(--highcontrast-actionbutton-content-color-hover, var(--mod-actionbutton-content-color-hover, var(--spectrum-actionbutton-content-color-hover))); + } - /* Let static variants inherit their color */ - color: inherit; + &:focus-ring { + background-color: var(--highcontrast-actionbutton-background-color-focus, var(--mod-actionbutton-background-color-focus, var(--spectrum-actionbutton-background-color-focus))); + border-color: var(--highcontrast-actionbutton-border-color-focus, var(--mod-actionbutton-border-color-focus, var(--spectrum-actionbutton-border-color-focus))); + color: var(--highcontrast-actionbutton-content-color-focus, var(--mod-actionbutton-content-color-focus, var(--spectrum-actionbutton-content-color-focus))); + } - .spectrum-Icon { - @inherit: %spectrum-ButtonIcon; + &:active { + background-color: var(--highcontrast-actionbutton-background-color-down, var(--mod-actionbutton-background-color-down, var(--spectrum-actionbutton-background-color-down))); + border-color: var(--highcontrast-actionbutton-border-color-down, var(--mod-actionbutton-border-color-down, var(--spectrum-actionbutton-border-color-down))); + color: var(--highcontrast-actionbutton-content-color-down, var(--mod-actionbutton-content-color-down, var(--spectrum-actionbutton-content-color-down))); + } - /* Scoot over, assuming we have both icon and text */ - margin-inline-start: calc(-1 * (var(--spectrum-actionbutton-textonly-padding-left-adjusted) - var(--spectrum-actionbutton-padding-left-adjusted))); + &:disabled, + &.is-disabled { + background-color: var(--highcontrast-actionbutton-background-color-disabled, var(--mod-actionbutton-background-color-disabled, var(--spectrum-actionbutton-background-color-disabled))); + border-color: var(--highcontrast-actionbutton-border-color-disabled, var(--mod-actionbutton-border-color-disabled, var(--spectrum-actionbutton-border-color-disabled))); + color: var(--highcontrast-actionbutton-content-color-disabled, var(--mod-actionbutton-content-color-disabled, var(--spectrum-actionbutton-content-color-disabled))); } +} + +a.spectrum-ActionButton { + @inherit: %spectrum-AnchorButton; +} - .spectrum-Icon + .spectrum-ActionButton-label { +.spectrum-ActionButton-icon { + @inherit: %spectrum-ButtonIcon; + + width: var(--mod-actionbutton-icon-size, var(--spectrum-actionbutton-icon-size)); + height: var(--mod-actionbutton-icon-size, var(--spectrum-actionbutton-icon-size)); + + color: inherit; + + & + .spectrum-ActionButton-label { /* Have gap on on the left */ - padding-inline-start: var(--spectrum-actionbutton-texticon-icon-gap); + padding-inline-start: var(--mod-actionbutton-text-to-visual, var(--spectrum-actionbutton-text-to-visual)); - /* - Have no padding on the right (it's built into the element) - This will fail if --spectrum-actionbutton-textonly-padding-right !== --spectrum-actionbutton-padding-right - */ + /* Have no padding on the right (it's built into the element) */ padding-inline-end: 0; } - .spectrum-ActionButton-hold + .spectrum-Icon, - .spectrum-Icon:only-child { - /* Use icon-only padding, subtracted from the default text-only padding */ - margin-left: calc(-1 * (var(--spectrum-actionbutton-textonly-padding-left-adjusted) - var(--spectrum-actionbutton-icononly-padding-left-adjusted))); - margin-right: calc(-1 * (var(--spectrum-actionbutton-textonly-padding-right-adjusted) - var(--spectrum-actionbutton-icononly-padding-right-adjusted))); - } + padding-inline-start: calc(-1 * (var(--mod-actionbutton-edge-to-text, var(--spectrum-actionbutton-edge-to-text)) - var(--mod-actionbutton-edge-to-visual, var(--spectrum-actionbutton-edge-to-visual)))); +} + +.spectrum-ActionButton-hold + .spectrum-ActionButton-icon, +.spectrum-ActionButton-icon:only-child { + /* Use icon-only padding, subtracted from the default text-only padding */ + margin-inline-start: calc(-1 * (var(--mod-actionbutton-edge-to-text, var(--spectrum-actionbutton-edge-to-text)) - var(--mod-actionbutton-edge-to-visual-only, var(--spectrum-actionbutton-edge-to-visual-only)))); + margin-inline-end: calc(-1 * (var(--mod-actionbutton-edge-to-text, var(--spectrum-actionbutton-edge-to-text)) - var(--mod-actionbutton-edge-to-visual-only, var(--spectrum-actionbutton-edge-to-visual-only)))); } .spectrum-ActionButton-label { @inherit: %spectrum-ButtonLabel; + font-size: var(--mod-actionbutton-font-size, var(--spectrum-actionbutton-font-size)); white-space: nowrap; - overflow: hidden; + color: inherit; + text-overflow: ellipsis; + overflow: hidden; } .spectrum-ActionButton-hold { position: absolute; - inset-inline-end: var(--spectrum-actionbutton-textonly-hold-icon-padding-right); - inset-block-end: var(--spectrum-actionbutton-textonly-hold-icon-padding-bottom); + inset-inline-end: calc(var(--mod-actionbutton-edge-to-hold-icon, var(--spectrum-actionbutton-edge-to-hold-icon)) - var(--mod-actionbutton-border-width, var(--spectrum-actionbutton-border-width))); + inset-block-end: calc(var(--mod-actionbutton-edge-to-hold-icon, var(--spectrum-actionbutton-edge-to-hold-icon)) - var(--mod-actionbutton-border-width, var(--spectrum-actionbutton-border-width))); - transform: logical rotate(0deg); -} - -.spectrum-ActionButton--quiet { - border-width: var(--spectrum-actionbutton-quiet-textonly-border-size); - border-radius: var(--spectrum-actionbutton-quiet-textonly-border-radius); + color: inherit; - font-size: var(--spectrum-actionbutton-quiet-textonly-text-size); - font-weight: var(--spectrum-actionbutton-quiet-textonly-text-font-weight); + transform: logical rotate(0deg); } /* special cases for focus-ring */ .spectrum-ActionButton { - --spectrum-actionbutton-focus-ring-gap: var(--spectrum-alias-component-focusring-gap); - --spectrum-actionbutton-focus-ring-size: var(--spectrum-alias-component-focusring-size); - --spectrum-actionbutton-focus-ring-color: var(--spectrum-actionbutton-m-textonly-focus-ring-border-color-key-focus); - - transition: border-color var(--spectrum-global-animation-duration-100) ease-in-out; + transition: border-color var(--mod-actionbutton-animation-duration, var(--spectrum-actionbutton-animation-duration)) ease-in-out; &:after { + position: absolute; + inset: 0; + + margin: calc((var(--mod-actionbutton-focus-ring-gap, var(--spectrum-actionbutton-focus-ring-gap)) + var(--mod-actionbutton-border-width, var(--spectrum-actionbutton-border-width))) * -1); + + border-radius: var(--mod-actionbutton-focus-ring-border-radius, var(--spectrum-actionbutton-focus-ring-border-radius)); + + transition: box-shadow var(--mod-actionbutton-animation-duration, var(--spectrum-actionbutton-animation-duration)) ease-in-out; + pointer-events: none; content: ''; - position: absolute; - left: 0; - right: 0; - bottom: 0; - top: 0; - margin: calc((var(--spectrum-actionbutton-focus-ring-gap) + var(--spectrum-actionbutton-textonly-border-size)) * -1); - border-radius: var(--spectrum-actionbutton-focus-ring-border-radius-adjusted); - transition: box-shadow var(--spectrum-global-animation-duration-100) ease-in-out; } &:focus-ring { - /* kill the default ring */ box-shadow: none !important; &:after { - box-shadow: 0 0 0 var(--spectrum-actionbutton-focus-ring-size) var(--spectrum-actionbutton-focus-ring-color); + box-shadow: 0 0 0 var(--mod-actionbutton-focus-ring-thickness, var(--spectrum-actionbutton-focus-ring-thickness)) var(--highcontrast-actionbutton-focus-ring-color, var(--mod-actionbutton-focus-ring-color, var(--spectrum-actionbutton-focus-ring-color))); } } } - -.spectrum-ActionButton--staticWhite { - --spectrum-actionbutton-focus-ring-color: var(--spectrum-global-color-static-white); -} - -.spectrum-ActionButton--staticBlack { - --spectrum-actionbutton-focus-ring-color: var(--spectrum-global-color-static-black); -} - -.spectrum-ActionButton--emphasized.is-selected, -.spectrum-ActionButton--staticWhite, -.spectrum-ActionButton--staticBlack { - --spectrum-actionbutton-focus-ring-gap: var(--spectrum-alias-component-focusring-gap-emphasized); - --spectrum-actionbutton-focus-ring-size: var(--spectrum-alias-component-focusring-size-emphasized); -} diff --git a/components/actionbutton/metadata/actionbutton.yml b/components/actionbutton/metadata/actionbutton.yml index 75a07a21325..de154d60cfb 100644 --- a/components/actionbutton/metadata/actionbutton.yml +++ b/components/actionbutton/metadata/actionbutton.yml @@ -5,9 +5,47 @@ description: | - For Action Buttons that only contain an icon with no label, do not include the element with the `.spectrum-ActionButton-label` class in the markup - If an icon and a label are both used, ensure that the element with the `.spectrum-ActionButton-label` class comes after the `.spectrum-Icon` element. - If the hold icon is used, ensure that the element with the `.spectrum-ActionButton-hold` class comes before the `.spectrum-Icon` element. + - When using `.spectrum-ActionButton--staticWhite` or `.spectrum-ActionButton--staticblack`, use the `--mod-actionbutton-static-content-color` custom property to set the text color when selected. sections: + - name: Custom Properties API + description: | + Define a subset of the following properties on your own class, such as `.mod-ActionButton`, to modify ActionButton. + + These properties override all API options, but can be layered on top of them. + + | Custom property | + | ------------------------------------------------- | + | `--mod-actionbutton-background-color-default` | + | `--mod-actionbutton-background-color-hover` | + | `--mod-actionbutton-background-color-down` | + | `--mod-actionbutton-background-color-focus` | + | `--mod-actionbutton-background-color-disabled` | + | `--mod-actionbutton-border-color-default` | + | `--mod-actionbutton-border-color-hover` | + | `--mod-actionbutton-border-color-down` | + | `--mod-actionbutton-border-color-focus` | + | `--mod-actionbutton-border-color-disabled` | + | `--mod-actionbutton-content-color-default` | + | `--mod-actionbutton-content-color-hover` | + | `--mod-actionbutton-content-color-down` | + | `--mod-actionbutton-content-color-focus` | + | `--mod-actionbutton-content-color-disabled` | + | `--mod-actionbutton-focus-ring-color` | + | `--mod-actionbutton-static-content-color` | + | `--mod-actionbutton-min-width` | + | `--mod-actionbutton-height` | + | `--mod-actionbutton-icon-size` | + | `--mod-actionbutton-font-size` | + | `--mod-actionbutton-text-to-visual` | + | `--mod-actionbutton-edge-to-hold-icon` | + | `--mod-actionbutton-edge-to-visual` | + | `--mod-actionbutton-edge-to-text` | + | `--mod-actionbutton-edge-to-visual-only` | - name: Migration Guide description: | + ### Action Button now requires a class on its icon + The `.spectrum-ActionButton-icon` class is now required on the icon. + ### T-shirt sizing Action Button now supports t-shirt sizing and requires that you specify the size by adding a `.spectrum-ActionButton--size*` class. @@ -52,14 +90,14 @@ examples: @@ -68,7 +106,7 @@ examples: - Edit @@ -99,7 +137,7 @@ examples: - Edit @@ -131,7 +169,7 @@ examples: - Edit @@ -163,7 +201,7 @@ examples: - Edit @@ -200,7 +238,7 @@ examples: - Edit @@ -231,7 +269,7 @@ examples: - Edit @@ -262,7 +300,7 @@ examples: - Edit @@ -293,7 +331,7 @@ examples: - Edit @@ -331,7 +369,7 @@ examples: - Edit @@ -362,7 +400,7 @@ examples: - Edit @@ -393,7 +431,7 @@ examples: - Edit @@ -424,7 +462,7 @@ examples: - Edit @@ -462,7 +500,7 @@ examples: - Edit @@ -493,7 +531,7 @@ examples: - Edit @@ -524,7 +562,7 @@ examples: - Edit @@ -555,7 +593,7 @@ examples: - Edit @@ -592,7 +630,7 @@ examples: - Edit @@ -623,7 +661,7 @@ examples: - Edit @@ -654,7 +692,7 @@ examples: - Edit @@ -685,7 +723,7 @@ examples: -
+

Default

@@ -707,14 +745,14 @@ examples: @@ -723,7 +761,7 @@ examples: - Edit @@ -754,7 +792,7 @@ examples: - Edit @@ -785,7 +823,7 @@ examples: - Edit @@ -816,7 +854,7 @@ examples: -
+

Default

@@ -839,14 +877,14 @@ examples: @@ -855,7 +893,7 @@ examples: - Edit @@ -886,7 +924,7 @@ examples: - Edit @@ -917,7 +955,7 @@ examples: - Edit @@ -948,7 +986,7 @@ examples: -
+

Default

@@ -972,14 +1010,14 @@ examples: @@ -988,7 +1026,7 @@ examples: - Edit @@ -1019,7 +1057,7 @@ examples: - Edit @@ -1050,7 +1088,7 @@ examples: - Edit @@ -1081,7 +1119,7 @@ examples: -
+

Default

@@ -1104,14 +1142,14 @@ examples: @@ -1120,7 +1158,7 @@ examples: - Edit @@ -1151,7 +1189,7 @@ examples: - Edit @@ -1182,7 +1220,7 @@ examples: - Edit @@ -1213,7 +1251,7 @@ examples: -
+ + - id: actionbutton-modified + name: Modified + markup: | + + + diff --git a/components/actionbutton/package.json b/components/actionbutton/package.json index 9e4ad75c0c4..1fa560aa54c 100644 --- a/components/actionbutton/package.json +++ b/components/actionbutton/package.json @@ -1,6 +1,6 @@ { "name": "@spectrum-css/actionbutton", - "version": "1.1.14", + "version": "2.0.0-beta.3", "description": "The Spectrum CSS action button component", "license": "Apache-2.0", "main": "dist/index-vars.css", @@ -16,16 +16,17 @@ "build": "gulp" }, "peerDependencies": { - "@spectrum-css/vars": "^8.0.0" + "@spectrum-css/icon": "^3.0.22", + "@spectrum-css/tokens": "^1.0.0-beta.2" }, "devDependencies": { - "@spectrum-css/component-builder": "^3.1.2", + "@spectrum-css/component-builder-simple": "^1.0.0-beta", "@spectrum-css/icon": "^3.0.22", - "@spectrum-css/vars": "^8.0.0", + "@spectrum-css/tokens": "^1.0.0-beta.2", "gulp": "^4.0.0" }, "publishConfig": { "access": "public" }, "homepage": "https://opensource.adobe.com/spectrum-css/" -} \ No newline at end of file +} diff --git a/components/actionbutton/skin.css b/components/actionbutton/skin.css deleted file mode 100644 index 83a1fb36c35..00000000000 --- a/components/actionbutton/skin.css +++ /dev/null @@ -1,404 +0,0 @@ -/* -Copyright 2019 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -.spectrum-ActionButton { - /* Overridden because of the way we draw focus rings */ - --spectrum-actionbutton-m-quiet-textonly-border-size-key-focus: 1px; -} - -.spectrum-ActionButton { - background-color: var(--spectrum-actionbutton-m-textonly-background-color); - border-color: var(--spectrum-actionbutton-m-textonly-border-color); - color: var(--spectrum-actionbutton-m-textonly-text-color); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-texticon-icon-color); - } - - .spectrum-ActionButton-hold { - color: var(--spectrum-actionbutton-m-textonly-hold-icon-color); - } - - &:hover { - background-color: var(--spectrum-actionbutton-m-textonly-background-color-hover); - border-color: var(--spectrum-actionbutton-m-textonly-border-color-hover); - color: var(--spectrum-actionbutton-m-textonly-text-color-hover); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-texticon-icon-color-hover); - } - - .spectrum-ActionButton-hold { - color: var(--spectrum-actionbutton-m-textonly-hold-icon-color-hover); - } - } - - &:focus-ring { - background-color: var(--spectrum-actionbutton-m-textonly-background-color-key-focus); - border-color: var(--spectrum-actionbutton-m-textonly-border-color-key-focus); - color: var(--spectrum-actionbutton-m-textonly-text-color-key-focus); - - &:active { - border-color: var(--spectrum-actionbutton-m-textonly-border-color-key-focus); - } - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-texticon-icon-color-key-focus); - } - - .spectrum-ActionButton-hold { - color: var(--spectrum-actionbutton-m-textonly-hold-icon-color-key-focus); - } - } - - &:active { - background-color: var(--spectrum-actionbutton-m-textonly-background-color-down); - border-color: var(--spectrum-actionbutton-m-textonly-border-color-down); - color: var(--spectrum-actionbutton-m-textonly-text-color-down); - - .spectrum-ActionButton-hold { - color: var(--spectrum-actionbutton-m-textonly-hold-icon-color-down); - } - } - - &:disabled, - &.is-disabled { - background-color: var(--spectrum-actionbutton-m-textonly-background-color-disabled); - border-color: var(--spectrum-actionbutton-m-textonly-border-color-disabled); - color: var(--spectrum-actionbutton-m-textonly-text-color-disabled); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-texticon-icon-color-disabled); - } - - .spectrum-ActionButton-hold { - color: var(--spectrum-actionbutton-m-textonly-hold-icon-color-disabled); - } - } - - &.is-selected { - background-color: var(--spectrum-actionbutton-m-textonly-background-color-selected); - border-color: var(--spectrum-actionbutton-m-textonly-border-color-selected); - color: var(--spectrum-actionbutton-m-textonly-text-color-selected); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-texticon-icon-color-selected); - } - - &:focus-ring { - background-color: var(--spectrum-actionbutton-m-textonly-background-color-selected-key-focus); - border-color: var(--spectrum-actionbutton-m-textonly-border-color-selected-key-focus); - color: var(--spectrum-actionbutton-m-textonly-text-color-selected-key-focus); - - &:active { - border-color: var(--spectrum-actionbutton-m-textonly-border-color-key-focus); - } - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-texticon-icon-color-selected-key-focus); - } - } - - &:hover { - background-color: var(--spectrum-actionbutton-m-textonly-background-color-selected-hover); - border-color: var(--spectrum-actionbutton-m-textonly-border-color-selected-hover); - color: var(--spectrum-actionbutton-m-textonly-text-color-selected-hover); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-texticon-icon-color-selected-hover); - } - } - - &:active { - background-color: var(--spectrum-actionbutton-m-textonly-background-color-selected-down); - border-color: var(--spectrum-actionbutton-m-textonly-border-color-selected-down); - color: var(--spectrum-actionbutton-m-textonly-text-color-selected-down); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-texticon-icon-color-selected-down); - } - } - - &:disabled, - &.is-disabled { - background-color: var(--spectrum-actionbutton-m-textonly-background-color-selected-disabled); - border-color: var(--spectrum-actionbutton-m-textonly-border-color-selected-disabled); - color: var(--spectrum-actionbutton-m-textonly-text-color-selected-disabled); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-texticon-icon-color-selected-disabled); - } - } - } -} - -.spectrum-ActionButton--emphasized { - &.spectrum-ActionButton--quiet.is-selected, - &.is-selected { - background-color: var(--spectrum-actionbutton-m-emphasized-textonly-background-color-selected); - border-color: var(--spectrum-actionbutton-m-emphasized-textonly-border-color-selected); - color: var(--spectrum-actionbutton-m-emphasized-textonly-text-color-selected); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-emphasized-texticon-icon-color-selected); - } - - &:focus-ring { - background-color: var(--spectrum-actionbutton-m-emphasized-textonly-background-color-selected-key-focus); - border-color: var(--spectrum-actionbutton-m-emphasized-textonly-border-color-selected-key-focus); - color: var(--spectrum-actionbutton-m-emphasized-textonly-text-color-selected-key-focus); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-emphasized-texticon-icon-color-selected-key-focus); - } - } - - &:hover { - background-color: var(--spectrum-actionbutton-m-emphasized-textonly-background-color-selected-hover); - border-color: var(--spectrum-actionbutton-m-emphasized-textonly-border-color-selected-hover); - color: var(--spectrum-actionbutton-m-emphasized-textonly-text-color-selected-hover); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-emphasized-texticon-icon-color-selected-hover); - } - } - - &.is-active { - background-color: var(--spectrum-actionbutton-m-emphasized-textonly-background-color-selected-down); - border-color: var(--spectrum-actionbutton-m-emphasized-textonly-border-color-selected-down); - color: var(--spectrum-actionbutton-m-emphasized-textonly-text-color-selected-down); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-emphasized-texticon-icon-color-selected-down); - } - } - - &:disabled, - &.is-disabled { - background-color: var(--spectrum-actionbutton-m-emphasized-textonly-background-color-selected-disabled); - border-color: var(--spectrum-actionbutton-m-emphasized-textonly-border-color-selected-disabled); - color: var(--spectrum-actionbutton-m-emphasized-textonly-text-color-selected-disabled); - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-emphasized-texticon-icon-color-selected-disabled); - } - } - } -} - -.spectrum-ActionButton--quiet { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color); - - &:hover { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-hover); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-hover); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-hover); - } - - &:focus-ring { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-key-focus); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-key-focus); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-key-focus); - } - - &:active { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-down); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-down); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-down); - } - - &:disabled, - &.is-disabled { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-disabled); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-disabled); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-disabled); - } - - &.is-selected { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-selected); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-selected); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected); - - &:focus-ring { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-selected-key-focus); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-selected-key-focus); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected-key-focus); - } - - &:hover { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-selected-hover); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-selected-hover); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected-hover); - } - - &:active { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-selected-down); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-selected-down); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected-down); - } - - &:disabled, - &.is-disabled { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-selected-disabled); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-selected-disabled); - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected-disabled); - } - } -} - -.spectrum-ActionButton--staticBlack, -.spectrum-ActionButton--staticWhite { - /* required to make rgba() work with vars */ - --spectrum-global-color-static-black-rgb: 0, 0, 0; - --spectrum-global-color-static-white-rgb: 255, 255, 255; - --spectrum-ActionButton-static-black-color: var(--spectrum-global-color-static-black); - --spectrum-ActionButton-static-white-color: var(--spectrum-global-color-static-white); - - &.is-selected { - /* let selected styles get their color from parent elements */ - color: inherit !important; - } -} - -@media (forced-colors: active) { - .spectrum-ActionButton { - &:after { - forced-color-adjust: none; - } - &.is-selected { - &:not(.is-disabled) { - .spectrum-ActionButton-label { - forced-color-adjust: none; - } - } - } - &.spectrum-ActionButton--staticBlack, - &.spectrum-ActionButton--staticWhite { - &.is-selected { - &:not(:disabled, .is-disabled) { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected); - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-selected); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-selected); - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected); - } - .spectrum-ActionButton-label { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected) ! important; - } - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected) ! important; - } - &:hover, - &:active, - &:focus-visible, - &.is-keyboardFocused { - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-selected); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-selected); - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected); - } - - .spectrum-ActionButton-label { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected); - } - - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected); - } - } - } - &:disabled, - &.is-disabled { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected-disabled); - background-color: var(--spectrum-actionbutton-m-quiet-textonly-background-color-selected-disabled); - border-color: var(--spectrum-actionbutton-m-quiet-textonly-border-color-selected-disabled); - .spectrum-ActionButton-holdIcon { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected-disabled); - } - .spectrum-ActionButton-label { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected-disabled); - } - .spectrum-Icon { - color: var(--spectrum-actionbutton-m-quiet-textonly-text-color-selected-disabled); - } - } - } - } - --spectrum-actionbutton-focus-ring-gap: var(--spectrum-alias-component-focusring-gap-emphasized); - --spectrum-actionbutton-focus-ring-size: var(--spectrum-alias-component-focusring-size-emphasized); - --spectrum-actionbutton-focus-ring-color: ButtonText; - - --spectrum-actionbutton-m-emphasized-texticon-icon-color-selected: HighlightText; - --spectrum-actionbutton-m-emphasized-texticon-icon-color-selected-disabled: GrayText; - --spectrum-actionbutton-m-emphasized-texticon-icon-color-selected-down: HighlightText; - --spectrum-actionbutton-m-emphasized-texticon-icon-color-selected-hover: HighlightText; - --spectrum-actionbutton-m-emphasized-texticon-icon-color-selected-key-focus: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-background-color-selected: Highlight; - --spectrum-actionbutton-m-emphasized-textonly-background-color-selected-disabled: ButtonFace; - --spectrum-actionbutton-m-emphasized-textonly-background-color-selected-down: Highlight; - --spectrum-actionbutton-m-emphasized-textonly-background-color-selected-hover: Highlight; - --spectrum-actionbutton-m-emphasized-textonly-background-color-selected-key-focus: Highlight; - --spectrum-actionbutton-m-emphasized-textonly-border-color-selected: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-border-color-selected-disabled: GrayText; - --spectrum-actionbutton-m-emphasized-textonly-border-color-selected-down: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-border-color-selected-hover: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-border-color-selected-key-focus: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-hold-icon-color-selected: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-text-color-down: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-text-color-hover: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-text-color-selected: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-text-color-selected-disabled: GrayText; - --spectrum-actionbutton-m-emphasized-textonly-text-color-selected-down: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-text-color-selected-hover: HighlightText; - --spectrum-actionbutton-m-emphasized-textonly-text-color-selected-key-focus: HighlightText; - --spectrum-actionbutton-m-quiet-textonly-background-color-selected: Highlight; - --spectrum-actionbutton-m-quiet-textonly-background-color-selected-disabled: ButtonFace; - --spectrum-actionbutton-m-quiet-textonly-background-color-selected-down: Highlight; - --spectrum-actionbutton-m-quiet-textonly-background-color-selected-hover: Highlight; - --spectrum-actionbutton-m-quiet-textonly-background-color-selected-key-focus: Highlight; - --spectrum-actionbutton-m-quiet-textonly-border-color: ButtonFace; - --spectrum-actionbutton-m-quiet-textonly-border-color-down: Highlight; - --spectrum-actionbutton-m-quiet-textonly-border-color-hover: Highlight; - --spectrum-actionbutton-m-quiet-textonly-border-color-selected: HighlightText; - --spectrum-actionbutton-m-quiet-textonly-border-color-selected-disabled: GrayText; - --spectrum-actionbutton-m-quiet-textonly-border-color-selected-down: HighlightText; - --spectrum-actionbutton-m-quiet-textonly-border-color-selected-hover: HighlightText; - --spectrum-actionbutton-m-quiet-textonly-border-color-selected-key-focus: HighlightText; - --spectrum-actionbutton-m-quiet-textonly-text-color-selected: HighlightText; - --spectrum-actionbutton-m-quiet-textonly-text-color-selected-disabled: GrayText; - --spectrum-actionbutton-m-quiet-textonly-text-color-selected-down: HighlightText; - --spectrum-actionbutton-m-quiet-textonly-text-color-selected-hover: HighlightText; - --spectrum-actionbutton-m-quiet-textonly-text-color-selected-key-focus: HighlightText; - --spectrum-actionbutton-m-texticon-icon-color-selected: HighlightText; - --spectrum-actionbutton-m-texticon-icon-color-selected-disabled: GrayText; - --spectrum-actionbutton-m-texticon-icon-color-selected-down: HighlightText; - --spectrum-actionbutton-m-texticon-icon-color-selected-hover: HighlightText; - --spectrum-actionbutton-m-texticon-icon-color-selected-key-focus: HighlightText; - --spectrum-actionbutton-m-textonly-background-color-selected: Highlight; - --spectrum-actionbutton-m-textonly-background-color-selected-disabled: ButtonFace; - --spectrum-actionbutton-m-textonly-background-color-selected-down: Highlight; - --spectrum-actionbutton-m-textonly-background-color-selected-hover: Highlight; - --spectrum-actionbutton-m-textonly-background-color-selected-key-focus: Highlight; - --spectrum-actionbutton-m-textonly-border-color-selected: HighlightText; - --spectrum-actionbutton-m-textonly-border-color-selected-disabled: GrayText; - --spectrum-actionbutton-m-textonly-border-color-selected-down: HighlightText; - --spectrum-actionbutton-m-textonly-border-color-selected-hover: HighlightText; - --spectrum-actionbutton-m-textonly-border-color-selected-key-focus: HighlightText; - --spectrum-actionbutton-m-textonly-text-color-selected: HighlightText; - --spectrum-actionbutton-m-textonly-text-color-selected-disabled: GrayText; - --spectrum-actionbutton-m-textonly-text-color-selected-down: HighlightText; - --spectrum-actionbutton-m-textonly-text-color-selected-hover: HighlightText; - --spectrum-actionbutton-m-textonly-text-color-selected-key-focus: HighlightText; - } -} diff --git a/components/actionbutton/themes/express.css b/components/actionbutton/themes/express.css new file mode 100644 index 00000000000..807332e555f --- /dev/null +++ b/components/actionbutton/themes/express.css @@ -0,0 +1,57 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +@container (--system: express) { + .spectrum-ActionButton { + --spectrum-actionbutton-background-color-default: var(--spectrum-gray-200); + --spectrum-actionbutton-background-color-hover: var(--spectrum-gray-300); + --spectrum-actionbutton-background-color-down: var(--spectrum-gray-400); + --spectrum-actionbutton-background-color-focus: var(--spectrum-gray-300); + + --spectrum-actionbutton-border-color-default: transparent; + --spectrum-actionbutton-border-color-hover: transparent; + --spectrum-actionbutton-border-color-down: transparent; + --spectrum-actionbutton-border-color-focus: transparent; + + --spectrum-actionbutton-background-color-disabled: var(--spectrum-disabled-background-color); + --spectrum-actionbutton-border-color-disabled: transparent; + + &.is-selected { + --spectrum-actionbutton-background-color-default: var(--spectrum-neutral-background-color-default); + --spectrum-actionbutton-background-color-hover: var(--spectrum-neutral-background-color-hover); + --spectrum-actionbutton-background-color-down: var(--spectrum-neutral-background-color-down); + --spectrum-actionbutton-background-color-focus: var(--spectrum-neutral-background-color-key-focus); + } + + &.spectrum-ActionButton--staticBlack, + &.spectrum-ActionButton--staticWhite { + --spectrum-actionbutton-border-color-default: transparent; + --spectrum-actionbutton-border-color-hover: transparent; + --spectrum-actionbutton-border-color-down: transparent; + --spectrum-actionbutton-border-color-focus: transparent; + } + + &.spectrum-ActionButton--staticBlack { + --spectrum-actionbutton-background-color-default: var(--spectrum-transparent-black-200); + --spectrum-actionbutton-background-color-hover: var(--spectrum-transparent-black-300); + --spectrum-actionbutton-background-color-down: var(--spectrum-transparent-black-400); + --spectrum-actionbutton-background-color-focus: var(--spectrum-transparent-black-300); + } + + &.spectrum-ActionButton--staticWhite { + --spectrum-actionbutton-background-color-default: var(--spectrum-transparent-white-200); + --spectrum-actionbutton-background-color-hover: var(--spectrum-transparent-white-300); + --spectrum-actionbutton-background-color-down: var(--spectrum-transparent-white-400); + --spectrum-actionbutton-background-color-focus: var(--spectrum-transparent-white-300); + } + } +} diff --git a/components/actionbutton/themes/spectrum.css b/components/actionbutton/themes/spectrum.css new file mode 100644 index 00000000000..defe782d74c --- /dev/null +++ b/components/actionbutton/themes/spectrum.css @@ -0,0 +1,165 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +@container (--system: spectrum) { + .spectrum-ActionButton { + --spectrum-actionbutton-background-color-default: var(--spectrum-gray-75); + --spectrum-actionbutton-background-color-hover: var(--spectrum-gray-200); + --spectrum-actionbutton-background-color-down: var(--spectrum-gray-300); + --spectrum-actionbutton-background-color-focus: var(--spectrum-gray-200); + + --spectrum-actionbutton-border-color-default: var(--spectrum-gray-400); + --spectrum-actionbutton-border-color-hover: var(--spectrum-gray-500); + --spectrum-actionbutton-border-color-down: var(--spectrum-gray-600); + --spectrum-actionbutton-border-color-focus: var(--spectrum-gray-500); + + --spectrum-actionbutton-content-color-default: var(--spectrum-neutral-content-color-default); + --spectrum-actionbutton-content-color-hover: var(--spectrum-neutral-content-color-hover); + --spectrum-actionbutton-content-color-down: var(--spectrum-neutral-content-color-down); + --spectrum-actionbutton-content-color-focus: var(--spectrum-neutral-content-color-key-focus); + + --spectrum-actionbutton-background-color-disabled: transparent; + --spectrum-actionbutton-border-color-disabled: var(--spectrum-disabled-border-color); + --spectrum-actionbutton-content-color-disabled: var(--spectrum-disabled-content-color); + + &.spectrum-ActionButton--quiet { + --spectrum-actionbutton-background-color-default: transparent; + --spectrum-actionbutton-background-color-hover: var(--spectrum-gray-200); + --spectrum-actionbutton-background-color-down: var(--spectrum-gray-300); + --spectrum-actionbutton-background-color-focus: var(--spectrum-gray-200); + + --spectrum-actionbutton-border-color-default: transparent; + --spectrum-actionbutton-border-color-hover: transparent; + --spectrum-actionbutton-border-color-down: transparent; + --spectrum-actionbutton-border-color-focus: transparent; + + --spectrum-actionbutton-background-color-disabled: transparent; + --spectrum-actionbutton-border-color-disabled: transparent; + } + + &.is-selected { + --spectrum-actionbutton-background-color-default: var(--spectrum-neutral-subdued-background-color-default); + --spectrum-actionbutton-background-color-hover: var(--spectrum-neutral-subdued-background-color-hover); + --spectrum-actionbutton-background-color-down: var(--spectrum-neutral-subdued-background-color-down); + --spectrum-actionbutton-background-color-focus: var(--spectrum-neutral-subdued-background-color-key-focus); + + --spectrum-actionbutton-border-color-default: transparent; + --spectrum-actionbutton-border-color-hover: transparent; + --spectrum-actionbutton-border-color-down: transparent; + --spectrum-actionbutton-border-color-focus: transparent; + + --spectrum-actionbutton-content-color-default: var(--spectrum-white); + --spectrum-actionbutton-content-color-hover: var(--spectrum-white); + --spectrum-actionbutton-content-color-down: var(--spectrum-white); + --spectrum-actionbutton-content-color-focus: var(--spectrum-white); + + --spectrum-actionbutton-background-color-disabled: var(--spectrum-disabled-background-color); + --spectrum-actionbutton-border-color-disabled: transparent; + + &.spectrum-ActionButton--emphasized { + --spectrum-actionbutton-background-color-default: var(--spectrum-accent-background-color-default); + --spectrum-actionbutton-background-color-hover: var(--spectrum-accent-background-color-hover); + --spectrum-actionbutton-background-color-down: var(--spectrum-accent-background-color-down); + --spectrum-actionbutton-background-color-focus: var(--spectrum-accent-background-color-key-focus); + } + } + + &.spectrum-ActionButton--staticBlack, + &.spectrum-ActionButton--staticWhite { + &.spectrum-ActionButton--quiet { + --spectrum-actionbutton-border-color-default: transparent; + --spectrum-actionbutton-border-color-hover: transparent; + --spectrum-actionbutton-border-color-down: transparent; + --spectrum-actionbutton-border-color-focus: transparent; + + --spectrum-actionbutton-border-color-disabled: transparent; + } + } + + &.spectrum-ActionButton--staticBlack { + --spectrum-actionbutton-background-color-default: transparent; + --spectrum-actionbutton-background-color-hover: var(--spectrum-transparent-black-300); + --spectrum-actionbutton-background-color-down: var(--spectrum-transparent-black-400); + --spectrum-actionbutton-background-color-focus: var(--spectrum-transparent-black-300); + + --spectrum-actionbutton-border-color-default: var(--spectrum-transparent-black-400); + --spectrum-actionbutton-border-color-hover: var(--spectrum-transparent-black-500); + --spectrum-actionbutton-border-color-down: var(--spectrum-transparent-black-600); + --spectrum-actionbutton-border-color-focus: var(--spectrum-transparent-black-500); + + --spectrum-actionbutton-content-color-default: var(--spectrum-black); + --spectrum-actionbutton-content-color-hover: var(--spectrum-black); + --spectrum-actionbutton-content-color-down: var(--spectrum-black); + --spectrum-actionbutton-content-color-focus: var(--spectrum-black); + + --spectrum-actionbutton-focus-ring-color: var(--spectrum-static-black-focus-ring-color); + + --spectrum-actionbutton-background-color-disabled: transparent; + --spectrum-actionbutton-border-color-disabled: var(--spectrum-disabled-static-black-border-color); + --spectrum-actionbutton-content-color-disabled: var(--spectrum-disabled-static-black-content-color); + + &.is-selected { + --spectrum-actionbutton-background-color-default: var(--spectrum-transparent-black-800); + --spectrum-actionbutton-background-color-hover: var(--spectrum-transparent-black-900); + --spectrum-actionbutton-background-color-down: var(--spectrum-transparent-black-900); + --spectrum-actionbutton-background-color-focus: var(--spectrum-transparent-black-900); + + --spectrum-actionbutton-border-color-disabled: transparent; + + --spectrum-actionbutton-content-color-default: var(--mod-actionbutton-static-content-color, var(--spectrum-white)); + --spectrum-actionbutton-content-color-hover: var(--mod-actionbutton-static-content-color, var(--spectrum-white)); + --spectrum-actionbutton-content-color-down: var(--mod-actionbutton-static-content-color, var(--spectrum-white)); + --spectrum-actionbutton-content-color-focus: var(--mod-actionbutton-static-content-color, var(--spectrum-white)); + + --spectrum-actionbutton-background-color-disabled: var(--spectrum-disabled-static-black-background-color); + } + } + + &.spectrum-ActionButton--staticWhite { + --spectrum-actionbutton-background-color-default: transparent; + --spectrum-actionbutton-background-color-hover: var(--spectrum-transparent-white-300); + --spectrum-actionbutton-background-color-down: var(--spectrum-transparent-white-400); + --spectrum-actionbutton-background-color-focus: var(--spectrum-transparent-white-300); + + --spectrum-actionbutton-border-color-default: var(--spectrum-transparent-white-400); + --spectrum-actionbutton-border-color-hover: var(--spectrum-transparent-white-500); + --spectrum-actionbutton-border-color-down: var(--spectrum-transparent-white-600); + --spectrum-actionbutton-border-color-focus: var(--spectrum-transparent-white-500); + + --spectrum-actionbutton-content-color-default: var(--spectrum-white); + --spectrum-actionbutton-content-color-hover: var(--spectrum-white); + --spectrum-actionbutton-content-color-down: var(--spectrum-white); + --spectrum-actionbutton-content-color-focus: var(--spectrum-white); + + --spectrum-actionbutton-focus-ring-color: var(--spectrum-static-white-focus-ring-color); + + --spectrum-actionbutton-background-color-disabled: transparent; + --spectrum-actionbutton-border-color-disabled: var(--spectrum-disabled-static-white-border-color); + --spectrum-actionbutton-content-color-disabled: var(--spectrum-disabled-static-white-content-color); + + &.is-selected { + --spectrum-actionbutton-background-color-default: var(--spectrum-transparent-white-800); + --spectrum-actionbutton-background-color-hover: var(--spectrum-transparent-white-900); + --spectrum-actionbutton-background-color-down: var(--spectrum-transparent-white-900); + --spectrum-actionbutton-background-color-focus: var(--spectrum-transparent-white-900); + + --spectrum-actionbutton-content-color-default: var(--mod-actionbutton-static-content-color, var(--spectrum-black)); + --spectrum-actionbutton-content-color-hover: var(--mod-actionbutton-static-content-color, var(--spectrum-black)); + --spectrum-actionbutton-content-color-down: var(--mod-actionbutton-static-content-color, var(--spectrum-black)); + --spectrum-actionbutton-content-color-focus: var(--mod-actionbutton-static-content-color, var(--spectrum-black)); + + --spectrum-actionbutton-background-color-disabled: var(--spectrum-disabled-static-white-background-color); + --spectrum-actionbutton-border-color-disabled: transparent; + } + } + } +} diff --git a/components/commons/basebutton-coretokens.css b/components/commons/basebutton-coretokens.css new file mode 100644 index 00000000000..16a93d57f2c --- /dev/null +++ b/components/commons/basebutton-coretokens.css @@ -0,0 +1,106 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +%spectrum-BaseButton { + /* Contain halo */ + position: relative; + + display: inline-flex; + box-sizing: border-box; + + align-items: center; + justify-content: center; + + /* Show the button overflow in Edge. */ + overflow: visible; + + /* Remove button the margin in Firefox and Safari. */ + margin: 0; + + border-style: solid; + + /* Remove the inheritance of text transform on button in Edge, Firefox, and IE. */ + text-transform: none; + -webkit-font-smoothing: antialiased; + /* Font smoothing for Firefox */ + -moz-osx-font-smoothing: grayscale; + + /* Correct the inability to style clickable types in iOS and Safari. */ + -webkit-appearance: button; + + /* Adjacent buttons should be aligned correctly */ + vertical-align: top; + + transition: background var(--spectrum-animation-duration-100) ease-out, + border-color var(--spectrum-animation-duration-100) ease-out, + color var(--spectrum-animation-duration-100) ease-out, + box-shadow var(--spectrum-animation-duration-100) ease-out; + + text-decoration: none; + font-family: var(--spectrum-font-family-base); + + line-height: var(--spectrum-line-height-small); + + user-select: none; + -webkit-user-select: none; + + cursor: pointer; + + &:focus { + outline: none; + } + + /* Fix Firefox */ + &::-moz-focus-inner { + border: 0; + + /* Remove the inner border and padding for button in Firefox. */ + border-style: none; + padding: 0; + + /* Use uppercase PX so values don't get converted to rem */ + margin-block-start: -2px; + margin-block-end: -2px; + } + + &:disabled, + &.is-disabled { + cursor: default; + } +} + +%spectrum-ButtonIcon { + max-block-size: 100%; + flex-shrink: 0; +} + +%spectrum-AnchorButton { + /* Remove appearance for clickable types in iOS and Safari. */ + -webkit-appearance: none; + /* Make link text not selectable */ + user-select: none; +} + +%spectrum-ButtonLabel { + align-self: center; + justify-self: center; + + /* Fixes horizontal alignment of text in anchor buttons */ + text-align: center; + + /* @safari10 Workaround for https://bugs.webkit.org/show_bug.cgi?id=169700 */ + /*inline-size: 100%;*/ + + &:empty { + display: none; + } +} diff --git a/components/tokens/README.md b/components/tokens/README.md new file mode 100644 index 00000000000..87aecd2a9a8 --- /dev/null +++ b/components/tokens/README.md @@ -0,0 +1,26 @@ +# @spectrum-css/tokens +> Core tokens builder for Spectrum CSS + +This package uses StyleDictionary to build Spectrum core tokens for CSS. + +## Output + +The output is concatenated into a single `dist/index.css` for use in Spectrum CSS. This entire file should be imported, and the relevant classes should be toggled to swap out core tokens. + +On the `` element, start with `.spectrum`, add in `.spectrum--light`, then `.spectrum--medium`. To switch to Express, add `.spectrum--express`. + +## Overrides and additions + +Overrides and additions to core tokens can be added to `custom.css`. + +Ensure that you correctly scope any added tokens: + +* `.spectrum` - Global, unchanging tokens or tokens specific to the Spectrum flavor +* `.spectrum--express` - Tokens specific to the Express flavor +* `.spectrum--lightest` - Tokens specific to the light color stop (soon to be deprecated) +* `.spectrum--light` - Tokens specific to the light color stop +* `.spectrum--dark` - Tokens specific to the dark color stop +* `.spectrum--darkest` - Tokens specific to the darkest color stop +* `.spectrum--medium` - Tokens specific to the medium (desktop) scale +* `.spectrum--large` - Tokens specific to the large (mobile) scale +* `.spectrum--express.spectrum--*` - Tokens specific to the Express flavor for any of the above color stops and scales diff --git a/components/tokens/config.js b/components/tokens/config.js new file mode 100644 index 00000000000..8258e9ac2e8 --- /dev/null +++ b/components/tokens/config.js @@ -0,0 +1,170 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the 'License'); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const path = require('path'); +const StyleDictionary = require('style-dictionary'); +const CSSSetsFormatter = require('style-dictionary-sets').CSSSetsFormatter; +const NameKebabTransfom = require('style-dictionary-sets').NameKebabTransfom; +const AttributeSetsTransform = require('style-dictionary-sets').AttributeSetsTransform; + +StyleDictionary.registerTransform(NameKebabTransfom); +StyleDictionary.registerTransform(AttributeSetsTransform); +StyleDictionary.registerFormat(CSSSetsFormatter); + +const systemNames = ['express', 'spectrum', 'wireframe']; + +const getSets = (token) => { + return token.path.filter( + (part, index, array) => array[index - 1] == "sets" + ); +} + +const tokenHasSets = (token) => { + return token.path.includes('sets'); +} + +const generateFileConfig = (setName, subSystemName) => { + const sets = [setName, subSystemName]; + + const selectorMap = { + 'desktop': 'medium', + 'mobile': 'large' + }; + + const fileName = selectorMap[setName] ?? setName; + + let selector = `.spectrum--${fileName}`; + if (subSystemName !== 'spectrum') { + selector = `.spectrum--${subSystemName}${selector}`; + } + + return { + destination: `${subSystemName}/${fileName}-vars.css`, + format: CSSSetsFormatter.name, + filter: (token) => { + return ( + tokenHasSets(token) && + getSets(token).includes(subSystemName) && + getSets(token).includes(setName) + ); + }, + options: { + selector, + showFileHeader: false, + outputReferences: true, + sets + }, + } +}; + +const generateGlobalConfig = (subSystemName) => { + const sets = [subSystemName]; + + const selector = subSystemName === 'spectrum' ? '.spectrum' : `.spectrum--${subSystemName}`; + + return { + destination: `${subSystemName}/global-vars.css`, + format: CSSSetsFormatter.name, + filter: (token) => { + return ( + tokenHasSets(token) && + getSets(token).length === 1 && + getSets(token)[0] === subSystemName + ); + }, + options: { + selector, + showFileHeader: false, + outputReferences: true, + sets + }, + } +} + +const generateGlobalSetConfig = (setName) => { + const sets = [setName]; + + const selectorMap = { + 'desktop': 'medium', + 'mobile': 'large' + }; + + const fileName = selectorMap[setName] ?? setName; + + let selectors = [`.spectrum--${fileName}`]; + + // Apply all light colors as lightest for backwards compat + if (setName === 'light') { + selectors.push('.spectrum--lightest'); + } + + return { + destination: `${fileName}-vars.css`, + format: CSSSetsFormatter.name, + filter: (token) => { + return ( + tokenHasSets(token) && + getSets(token).every(set => !systemNames.includes(set)) && + getSets(token).includes(setName) + ); + }, + options: { + selector: selectors.join(', '), + showFileHeader: false, + outputReferences: true, + sets + }, + } +} + +const tokenGlob = path.dirname(require.resolve('@adobe/spectrum-tokens')) + '/src/**/*.json'; +module.exports = { + source: [tokenGlob], + platforms: { + CSS: { + buildPath: 'dist/css/', + transforms: [AttributeSetsTransform.name, NameKebabTransfom.name], + prefix: 'spectrum', + files: [ + { + destination: 'global-vars.css', + format: CSSSetsFormatter.name, + filter: (token) => !tokenHasSets(token), + options: { + showFileHeader: false, + outputReferences: true, + selector: '.spectrum' + }, + }, + generateGlobalSetConfig('desktop'), + generateGlobalSetConfig('mobile'), + generateGlobalSetConfig('light'), + generateGlobalSetConfig('dark'), + generateGlobalSetConfig('darkest'), + + generateGlobalConfig('spectrum'), + generateFileConfig('desktop', 'spectrum'), + generateFileConfig('mobile', 'spectrum'), + generateFileConfig('light', 'spectrum'), + generateFileConfig('dark', 'spectrum'), + generateFileConfig('darkest', 'spectrum'), + + generateGlobalConfig('express'), + generateFileConfig('desktop', 'express'), + generateFileConfig('mobile', 'express'), + generateFileConfig('light', 'express'), + generateFileConfig('dark', 'express'), + generateFileConfig('darkest', 'express'), + ], + }, + }, +}; diff --git a/components/tokens/custom-express/custom-large-vars.css b/components/tokens/custom-express/custom-large-vars.css new file mode 100644 index 00000000000..8ab824cbe90 --- /dev/null +++ b/components/tokens/custom-express/custom-large-vars.css @@ -0,0 +1,17 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/* This file contains overrides and additions to core tokens */ + +.spectrum--express.spectrum--large { + /* */ +} diff --git a/components/tokens/custom-express/custom-medium-vars.css b/components/tokens/custom-express/custom-medium-vars.css new file mode 100644 index 00000000000..68638c7b8cb --- /dev/null +++ b/components/tokens/custom-express/custom-medium-vars.css @@ -0,0 +1,17 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/* This file contains overrides and additions to core tokens */ + +.spectrum--express.spectrum--medium { + /* */ +} diff --git a/components/tokens/custom-express/custom-vars.css b/components/tokens/custom-express/custom-vars.css new file mode 100644 index 00000000000..c03c0dadbba --- /dev/null +++ b/components/tokens/custom-express/custom-vars.css @@ -0,0 +1,17 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/* This file contains overrides and additions to core tokens */ + +.spectrum--express { + --system: express; +} diff --git a/components/tokens/custom-spectrum/custom-large-vars.css b/components/tokens/custom-spectrum/custom-large-vars.css new file mode 100644 index 00000000000..21a9825b923 --- /dev/null +++ b/components/tokens/custom-spectrum/custom-large-vars.css @@ -0,0 +1,21 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/* This file contains overrides and additions to core tokens */ + +.spectrum--large { + /* edge-to-visual-only is used for icon-only buttons */ + --spectrum-edge-to-visual-only-75: 5px; + --spectrum-edge-to-visual-only-100: 9px; + --spectrum-edge-to-visual-only-200: 13px; + --spectrum-edge-to-visual-only-300: 16px; +} diff --git a/components/tokens/custom-spectrum/custom-medium-vars.css b/components/tokens/custom-spectrum/custom-medium-vars.css new file mode 100644 index 00000000000..d1fcf86d0ad --- /dev/null +++ b/components/tokens/custom-spectrum/custom-medium-vars.css @@ -0,0 +1,21 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/* This file contains overrides and additions to core tokens */ + +.spectrum--medium { + /* edge-to-visual-only is used for icon-only buttons */ + --spectrum-edge-to-visual-only-75: 4px; + --spectrum-edge-to-visual-only-100: 7px; + --spectrum-edge-to-visual-only-200: 10px; + --spectrum-edge-to-visual-only-300: 13px; +} diff --git a/components/tokens/custom-spectrum/custom-vars.css b/components/tokens/custom-spectrum/custom-vars.css new file mode 100644 index 00000000000..4bf82b46dda --- /dev/null +++ b/components/tokens/custom-spectrum/custom-vars.css @@ -0,0 +1,28 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/* This file contains overrides and additions to core tokens */ +.spectrum { + --system: spectrum; +} + +.spectrum { + --spectrum-animation-duration-100: 130ms; + + --spectrum-font-family-base: adobe-clean, 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Ubuntu, 'Trebuchet MS', 'Lucida Grande', sans-serif; + --spectrum-font-family-serif: adobe-clean-serif, 'Source Serif Pro', Georgia, serif; + --spectrum-font-family-code: 'Source Code Pro', Monaco, monospace; + + --spectrum-line-height-large: 1.7; + --spectrum-line-height-medium: 1.5; + --spectrum-line-height-small: 1.3; +} diff --git a/components/tokens/gulpfile.js b/components/tokens/gulpfile.js new file mode 100644 index 00000000000..d1356d03f49 --- /dev/null +++ b/components/tokens/gulpfile.js @@ -0,0 +1,51 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const gulp = require('gulp'); +const concat = require('gulp-concat'); +const del = require('del'); +const StyleDictionary = require('style-dictionary').extend('config.js'); + +function clean() { + return del('dist/*'); +} + +function concatIndex() { + return gulp.src([ + 'dist/css/*.css', + 'dist/css/spectrum/*.css', + 'dist/css/express/*.css', + 'custom-spectrum/*.css', + 'custom-express/*.css' + ]) + .pipe(concat('index.css')) + .pipe(gulp.dest('dist/')); +} + +function buildCustoms() { + buildCustomSpectrum = () => gulp.src('custom-spectrum/*.css').pipe(gulp.dest('dist/css/spectrum/')); + buildCustomExpress = () => gulp.src('custom-express/*.css').pipe(gulp.dest('dist/css/express')); + return buildCustomSpectrum() && buildCustomExpress(); +} + +function styleDictionary(cb) { + StyleDictionary.buildAllPlatforms(); + cb(); +} + +exports.clean = clean; +exports.build = exports.buildLite = exports.buildMedium = exports.default = gulp.series( + clean, + styleDictionary, + concatIndex, + buildCustoms +); diff --git a/components/tokens/package.json b/components/tokens/package.json new file mode 100644 index 00000000000..0ce740ff0fa --- /dev/null +++ b/components/tokens/package.json @@ -0,0 +1,29 @@ +{ + "name": "@spectrum-css/tokens", + "version": "1.0.0-beta.2", + "description": "The Spectrum CSS tokens package", + "license": "Apache-2.0", + "main": "dist/index.css", + "scripts": { + "build": "gulp build" + }, + "repository": { + "type": "git", + "url": "https://github.com/adobe/spectrum-css.git", + "directory": "components/tokens" + }, + "bugs": { + "url": "https://github.com/adobe/spectrum-css/issues" + }, + "devDependencies": { + "gulp": "^4.0.0", + "gulp-concat": "^2.6.1", + "@adobe/spectrum-tokens": "^12.0.0-beta.21", + "style-dictionary": "^3.7.0", + "style-dictionary-sets": "^1.4.1" + }, + "publishConfig": { + "access": "public" + }, + "homepage": "https://opensource.adobe.com/spectrum-css/" +} diff --git a/site/includes/dependencies.pug b/site/includes/dependencies.pug index 0b42559aa52..be8e7a4d1fb 100644 --- a/site/includes/dependencies.pug +++ b/site/includes/dependencies.pug @@ -14,6 +14,8 @@ link(rel='stylesheet', type='text/css', href='../components/vars/spectrum-light. link(rel='stylesheet', type='text/css', href='../components/vars/spectrum-medium.css') link(rel='stylesheet', type='text/css', href='../components/vars/spectrum-large.css') +link(rel='stylesheet', type='text/css', href='../components/tokens/index.css') + each dep in dependencyOrder.filter((dep) => dep != 'vars' ) link(rel='stylesheet', type='text/css', href='../components/' + dep + '/index-vars.css', data-dependency=dep ) diff --git a/site/resources/js/SpectrumSwitcher.js b/site/resources/js/SpectrumSwitcher.js index 4ec3705c4cb..4a5c48eedc5 100644 --- a/site/resources/js/SpectrumSwitcher.js +++ b/site/resources/js/SpectrumSwitcher.js @@ -145,6 +145,14 @@ Object.defineProperty(SpectrumSwitcher.prototype, 'varsVersion', { sheet.setAttribute('href', sheet.href.replaceAll(expressName, defaultName)); } }); + + if (varsVersion === 'express') { + document.documentElement.classList.add('spectrum--express'); + } + else { + document.documentElement.classList.remove('spectrum--express'); + } + this._varsVersion = varsVersion; }, get: function() { diff --git a/tools/bundle-builder/lib/depUtils.js b/tools/bundle-builder/lib/depUtils.js index 6cd17c2bf42..b018c1ec94e 100644 --- a/tools/bundle-builder/lib/depUtils.js +++ b/tools/bundle-builder/lib/depUtils.js @@ -29,7 +29,8 @@ async function getDependencies(package) { dependencies = Object.keys(pkg.devDependencies).filter((dep) => { return dep.indexOf('@spectrum-css') === 0 && dep !== '@spectrum-css/bundle-builder' && - dep !== '@spectrum-css/component-builder'; + dep !== '@spectrum-css/component-builder' && + dep !== '@spectrum-css/component-builder-simple'; }); } @@ -96,6 +97,11 @@ async function getFolderDependencyOrder(packagesDir) { // Nobody relies on it, so it gets clipped, weird solution.push('@spectrum-css/expressvars'); + // Build tokens first + // This is because not every package relies on tokens, but the builder needs tokens to bake vars + solution = solution.filter(p => p !== '@spectrum-css/tokens'); + solution.unshift('@spectrum-css/tokens'); + return solution; } diff --git a/tools/bundle-builder/vars/index.js b/tools/bundle-builder/vars/index.js index 3bb570d5ab8..4a33062e1de 100644 --- a/tools/bundle-builder/vars/index.js +++ b/tools/bundle-builder/vars/index.js @@ -48,7 +48,8 @@ function getAllVars() { `${dirs.components}/vars/css/themes/*.css`, `${dirs.components}/vars/css/scales/*.css`, `${dirs.components}/vars/css/components/*.css`, - `${dirs.components}/vars/css/globals/*.css` + `${dirs.components}/vars/css/globals/*.css`, + `${dirs.components}/tokens/dist/index.css` ]) .pipe(concat('everything.css')) .pipe(through.obj(function getAllVars(file, enc, cb) { @@ -157,12 +158,19 @@ const expressVarDir = path.join(dirs.components, 'expressvars', 'dist'); function copyExpressVars() { return gulp.src(path.join(expressVarDir, 'spectrum-*.css')) .pipe(gulp.dest('dist/expressvars/')) - } +} + +const coreTokensDir = path.join(dirs.components, 'tokens', 'dist'); +function copyCoreTokens() { + return gulp.src(path.join(varDir, '**/*.css')) + .pipe(gulp.dest('dist/tokens/')) +} exports.buildUnique = buildUnique; exports.copyVars = gulp.parallel( buildUnique, copyVars, - copyExpressVars + copyExpressVars, + copyCoreTokens ); diff --git a/tools/component-builder-simple/README.md b/tools/component-builder-simple/README.md new file mode 100644 index 00000000000..3d13cb2e42f --- /dev/null +++ b/tools/component-builder-simple/README.md @@ -0,0 +1,15 @@ +# @spectrum-css/component-builder-simple +> Simplified build system for Spectrum CSS components + +This package uses gulp to compile CSS for Spectrum CSS components. + +## CLI + +The following tasks are available: + +* `gulp clean` - Clean everything +* `gulp build` - Build everything + +## Accessing PostCSS preprocessors + +You can pull the list of preprocessors with `require('@spectrum-css/component-builder-simple/css/processors')`. diff --git a/tools/component-builder-simple/css/index.js b/tools/component-builder-simple/css/index.js new file mode 100644 index 00000000000..3345d8dedcc --- /dev/null +++ b/tools/component-builder-simple/css/index.js @@ -0,0 +1,215 @@ +/* +Copyright 2019 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const gulp = require('gulp'); +const path = require('path'); +const through = require('through2'); +const postcss = require('gulp-postcss'); +const rename = require('gulp-rename'); +const concat = require('gulp-concat'); +const postcssReal = require('postcss'); +const fsp = require('fs').promises; +const { parse } = require('postcss-values-parser'); +const processorsFunction = require('./processors').getProcessors; +const processors = processorsFunction(); + +function getTokensUsedInValueNode(node, usedTokens) { + usedTokens = usedTokens ?? []; + if (node.nodes) { + node.nodes.forEach(subNode => { + if (subNode.type === 'word' && subNode.value.startsWith('--')) { + usedTokens.push(subNode.value); + } + else if (subNode.type === 'func') { + getTokensUsedInValueNode(subNode, usedTokens); + } + }); + } + return usedTokens; +} + +function getTokensUsedInCSS(root, coreTokens, componentTokens) { + let usedTokens = []; + let coreTokensUsed = {}; + let componentTokensUsed = {}; + + root.walkRules((rule, ruleIndex) => { + rule.walkDecls((decl) => { + let matches = decl.value.match(/var\(.*?\)/g); + if (matches) { + let parsed = parse(decl.value); + parsed.nodes.forEach(node => { + const usedTokensInValue = getTokensUsedInValueNode(node); + usedTokensInValue.forEach(tokenName => { + if (coreTokens[tokenName]) { + coreTokensUsed[tokenName] = (coreTokensUsed[tokenName] ?? 0) + 1; + } + else if (componentTokens[tokenName]) { + componentTokensUsed[tokenName] = (componentTokensUsed[tokenName] ?? 0) + 1; + } + if (usedTokens.indexOf(tokenName) === -1) { + usedTokens.push(tokenName); + } + }); + }); + } + }); + }); + + return { usedTokens, coreTokensUsed, componentTokensUsed }; +} + +function getTokensDefinedInCSS(root) { + let variables = {}; + + root.walkRules((rule, ruleIndex) => { + rule.walkDecls((decl) => { + if (decl.prop.startsWith('--')) { + variables[decl.prop] = decl.value; + } + }); + }); + + return variables; +} + +async function getCoreTokens() { + const coreTokensFile = require.resolve('@spectrum-css/tokens'); + let contents = await fsp.readFile(coreTokensFile, 'utf8'); + let root = postcssReal.parse(contents); + return getTokensDefinedInCSS(root); +} + +function buildCSS() { + return gulp.src([ + 'index.css', + 'themes/spectrum.css', // spectrum comes first + 'themes/*.css' + ]) + .pipe(concat('index.css')) + .pipe(postcss(processors, { + from: './index.css' // gulp-concat sets the file.path wrong, so override here + })) + .pipe(gulp.dest('dist/')); +} + +function buildCSSWithoutThemes() { + return gulp.src([ + 'index.css', + 'themes/spectrum.css', // spectrum comes first + 'themes/*.css' + ]) + .pipe(concat('index-base.css')) + .pipe(postcss(processorsFunction(false, { noFlatVariables: true }), { + from: './index.css' // gulp-concat sets the file.path wrong, so override here + })) + .pipe(gulp.dest('dist/')); +} + +function buildCSSThemeIndex() { + return gulp.src([ + 'themes/spectrum.css', // spectrum comes first + 'themes/*.css' + ]) + .pipe(concat('index-theme.css')) + .pipe(postcss(processorsFunction(true, { noSelectors: true }))) + .pipe(gulp.dest('dist/')); +} + +function buildCSSThemes() { + return gulp.src([ + 'themes/*.css' + ]) + .pipe(postcss(processorsFunction(true, { noSelectors: true }))) + .pipe(gulp.dest('dist/themes/')); +} + +/** + Special case for express: it needs Spectrum base vars and needs to override them +*/ +function buildExpressTheme() { + return gulp.src([ + 'dist/index-theme.css' + ]) + .pipe(concat('express.css')) + .pipe(postcss(processorsFunction(true).concat(require('postcss-combininator')))) + .pipe(gulp.dest('dist/themes/')); +} + +let coreTokens = null; +function checkCSS(glob) { + return gulp.src(glob) + .pipe(concat('index-combined.css')) + .pipe(through.obj(async function doBake(file, enc, cb) { + // Fetch core tokes once during the build + if (coreTokens === null) { + coreTokens = await getCoreTokens(); + } + + let pkg = JSON.parse(await fsp.readFile(path.join('package.json'))); + + // Parse only once + let root = postcssReal.parse(file.contents); + + // Get tokens defined inside of the component + let componentTokens = getTokensDefinedInCSS(root); + + // Find all tokens used in the component + let { usedTokens, coreTokensUsed, componentTokensUsed } = getTokensUsedInCSS(root, coreTokens, componentTokens); + + // Make sure the component doesn't use any undefined tokens + let errors = []; + usedTokens.forEach(tokenName => { + if (!coreTokens[tokenName] && !componentTokens[tokenName] && !tokenName.startsWith('--mod') && !tokenName.startsWith('--highcontrast')) { + errors.push(`${pkg.name} uses undefined token ${tokenName}`); + } + }); + + // Make sure all tokens defined in the component are used + Object.keys(componentTokens).forEach(tokenName => { + if (!usedTokens.includes(tokenName)) { + errors.push(`${pkg.name} defines ${tokenName}, but never uses it`); + } + }); + + if (errors.length) { + return cb(new Error(errors.join('\n')), file); + } + + cb(null); + })); +} + +function checkSourceCSS() { + return checkCSS([ + 'themes/*.css', + 'index.css' + ]); +} + +function checkBuiltCSS() { + return checkCSS('dist/index.css'); +} + +exports.buildCSS = gulp.series( + checkSourceCSS, + gulp.parallel( + buildCSS, + buildCSSWithoutThemes, + gulp.series( + buildCSSThemes, + buildCSSThemeIndex, + buildExpressTheme + ) + ), + checkBuiltCSS +); diff --git a/tools/component-builder-simple/css/plugins/postcss-custom-properties-passthrough.js b/tools/component-builder-simple/css/plugins/postcss-custom-properties-passthrough.js new file mode 100644 index 00000000000..41ae55b41a6 --- /dev/null +++ b/tools/component-builder-simple/css/plugins/postcss-custom-properties-passthrough.js @@ -0,0 +1,29 @@ +/* +Copyright 2019 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +var postcss = require('postcss'); + +module.exports = postcss.plugin('postcss-custom-properties-passthrough', function (opts) { + opts = opts || {}; + + return function (root, result) { + root.walkRules((rule, ruleIndex) => { + rule.walkDecls((decl) => { + if (decl.value.match('xvar\(.*?\)')) { + decl.value = decl.value.substr(1); + } + if (decl.prop.substr(0,3) === 'x--') { + decl.prop = decl.prop.substr(1); + } + }); + }); + } +}); diff --git a/tools/component-builder-simple/css/plugins/postcss-strip-comments.js b/tools/component-builder-simple/css/plugins/postcss-strip-comments.js new file mode 100644 index 00000000000..5ef63481a01 --- /dev/null +++ b/tools/component-builder-simple/css/plugins/postcss-strip-comments.js @@ -0,0 +1,35 @@ +/* +Copyright 2019 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +const postcss = require('postcss'); + +module.exports = postcss.plugin('postcss-strip-comments', (opts = {}) => { + return css => { + css.walk(node => { + if (node.type === 'comment') { + if (node.text.trim().indexOf('topdoc') === 0 && opts.preserveTopdoc) { + return; + } + + // Get a reference to the parent before the node is removed + let parent = node.parent; + + node.remove(); + + // If the comment was the last thing left in its parent, remove the parent + if (parent && parent.nodes && parent.nodes.length === 0) { + parent.remove(); + } + return; + } + }); + }; +}); \ No newline at end of file diff --git a/tools/component-builder-simple/css/plugins/postcss-transform-logical.js b/tools/component-builder-simple/css/plugins/postcss-transform-logical.js new file mode 100644 index 00000000000..dafc0e7bcd2 --- /dev/null +++ b/tools/component-builder-simple/css/plugins/postcss-transform-logical.js @@ -0,0 +1,86 @@ +/* +Copyright 2019 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +const postcss = require('postcss'); +const { parse } = require('postcss-values-parser'); + +const selectorParser = require('postcss-selector-parser'); +const addDir = selectors => { + selectors.each(selector => { + let dirPseudo = selectorParser.pseudo({value: ':dir(rtl)'}); + selector.append(dirPseudo); + }); +}; + +const matrix = 'matrix(-1, 0, 0, 1, 0, 0)'; + +module.exports = postcss.plugin('postcss-transform-logical', function (opts) { + opts = opts || {}; + + return function (root, result) { + root.walkRules((rule, ruleIndex) => { + rule.walkDecls((decl) => { + if (decl.prop === 'transform') { + let value; + try { + value = parse(decl.value); + } + catch (err) { + console.warn('postcss-transform-logical: could not parse %s', decl.value); + } + + if (value && value.nodes[0].value === 'logical') { + // Drop logical + value.nodes[0].remove(); + + let originalRotation = null; + let rotationNode = null; + value.walkFuncs((node, index, nodes) => { + if (node.name === 'rotate') { + originalRotation = node.nodes[0].value; + rotationNode = node; + } + else if (node.name === 'matrix') { + throw new Error('postcss-transform-logical: logical flips cannot be performed on transforms that use matrix()'); + } + }); + + if (rotationNode !== null) { + // Ignore 0 deg initial rotations for LTR; this means we meant for it to be standard rotation for LTR + if (parseInt(originalRotation, 10) !== 0) { + let ltrRule = postcss.parse(`${rule.selector}:dir(ltr) { transform: ${value}; }`); + root.insertBefore(rule, ltrRule); + + // Use the same rotation, but flip horizontal + let rtlRule = postcss.parse(`${rule.selector}:dir(rtl) { transform: ${matrix} ${value}; }`); + root.insertBefore(rule, rtlRule); + } + else { + // Drop the unnecessary rotation + rotationNode.remove(); + + // Add direction to all matching selectors + let newSelector = selectorParser(addDir).processSync(rule.selector); + + // Just flip horizontal + let rtlRule = postcss.parse(`${newSelector} { transform: ${matrix} ${value}; }`); + root.insertBefore(rule, rtlRule); + } + + // Remove original declaration + decl.remove(); + } + } + } + }); + }); + } +}); diff --git a/tools/component-builder-simple/css/processors.js b/tools/component-builder-simple/css/processors.js new file mode 100644 index 00000000000..87f9d066016 --- /dev/null +++ b/tools/component-builder-simple/css/processors.js @@ -0,0 +1,48 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +function getProcessors(keepUnusedVars = false, splitinatorOptions = {}) { + return [ + require('postcss-import'), + require('postcss-nested'), + require('postcss-splitinator')({ + processIdentifier: (identifier) => { + if (identifier === 'express') { + return 'spectrum--express'; + } + return identifier; + }, + ...splitinatorOptions + }), + require('postcss-inherit'), + require('./plugins/postcss-transform-logical')(), + require('./plugins/postcss-custom-properties-passthrough')(), + require('postcss-calc'), + require('./plugins/postcss-strip-comments')({ preserveTopdoc: false }), + !keepUnusedVars && require('postcss-dropunusedvars'), + require('postcss-dropdupedvars'), + require('postcss-focus-ring'), + require('postcss-discard-empty'), + require('autoprefixer')({ + 'browsers': [ + 'last 2 Edge versions', + 'last 2 Chrome versions', + 'last 2 Firefox versions', + 'last 2 Safari versions', + 'last 2 iOS versions' + ] + }) + ].filter(Boolean); +} + +exports.getProcessors = getProcessors; +exports.processors = getProcessors(); diff --git a/tools/component-builder-simple/index.js b/tools/component-builder-simple/index.js new file mode 100644 index 00000000000..cddd08aa691 --- /dev/null +++ b/tools/component-builder-simple/index.js @@ -0,0 +1,41 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const gulp = require('gulp'); +const rename = require('gulp-rename'); +const del = require('del'); +const css = require('./css'); + +function clean() { + return del('dist/*'); +} + +const build = gulp.series( + clean, + css.buildCSS, + function copyIndex() { + // Just copy index.vars as index.css to maintain backwards compat + return gulp.src('dist/index.css') + .pipe(rename((file) => { + file.basename = 'index-vars'; + })) + .pipe(gulp.dest('dist/')) + } +); + +exports.default = build; +exports.build = build; +exports.buildLite = build; +exports.buildMedium = build; +exports.buildHeavy = build; +exports.clean = clean; +exports.buildCSS = build; diff --git a/tools/component-builder-simple/package.json b/tools/component-builder-simple/package.json new file mode 100644 index 00000000000..a1002c5a2f2 --- /dev/null +++ b/tools/component-builder-simple/package.json @@ -0,0 +1,43 @@ +{ + "name": "@spectrum-css/component-builder-simple", + "version": "1.0.0-beta.0", + "description": "The Spectrum CSS simple component builder", + "repository": { + "type": "git", + "url": "https://github.com/adobe/spectrum-css.git", + "directory": "tools/component-builder" + }, + "bugs": { + "url": "https://github.com/adobe/spectrum-css/issues" + }, + "license": "Apache-2.0", + "peerDependencies": { + "@spectrum-css/tokens": "^1.0.0-beta" + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "autoprefixer": "^6.5.3", + "del": "^5.0.0", + "gulp": "^4.0.0", + "gulp-concat": "^2.6.1", + "gulp-rename": "^1.4.0", + "gulp-postcss": "^7.0.0", + "postcss": "^7.0.36", + "postcss-calc": "^6.0.0", + "postcss-splitinator": "^1.0.0-beta", + "postcss-combininator": "^1.0.0-beta", + "postcss-discard-empty": "^4.0.1", + "postcss-dropdupedvars": "^1.1.2", + "postcss-dropunusedvars": "^1.2.1", + "postcss-focus-ring": "^1.0.0", + "postcss-import": "^10.0.0", + "postcss-inherit": "^4.0.3", + "postcss-mixins": "^6.2.1", + "postcss-nested": "^3.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-values-parser": "^3.1.1", + "through2": "^3.0.1" + } +} diff --git a/tools/component-builder/css/lib/varUtils.js b/tools/component-builder/css/lib/varUtils.js index c508e3ddf84..81e135391fc 100644 --- a/tools/component-builder/css/lib/varUtils.js +++ b/tools/component-builder/css/lib/varUtils.js @@ -125,6 +125,7 @@ function resolveValue(value, vars) { } const varDir = path.join(path.dirname(require.resolve('@spectrum-css/vars')), '..'); +const coreTokensFile = require.resolve('@spectrum-css/tokens'); async function readDNAVariables(file) { let css = await fsp.readFile(path.join(varDir, 'css', file)); @@ -154,7 +155,8 @@ function getAllVars() { `${varDir}/css/scales/*.css`, `${varDir}/css/components/*.css`, `${varDir}/css/globals/*.css`, - `${varDir}/custom.css` + `${varDir}/custom.css`, + coreTokensFile ]) .pipe(concat('everything.css')) .pipe(through.obj(function getAllVars(file, enc, cb) { diff --git a/tools/component-builder/css/vars.js b/tools/component-builder/css/vars.js index 2afdcfea5ff..7a3150ec301 100644 --- a/tools/component-builder/css/vars.js +++ b/tools/component-builder/css/vars.js @@ -60,7 +60,7 @@ function bakeVars() { if (varName.indexOf('spectrum-global') !== -1) { logger.warn(`⚠️ ${pkg.name} directly uses global variable ${varName}`); } - else if (!allVars[varName]) { + else if (!allVars[varName] && !varName.startsWith('--mod') && !varName.startsWith('--highcontrast')) { if (componentVars.indexOf(varName) === -1) { errors.push(`${pkg.name} uses undefined variable ${varName}`); } diff --git a/tools/component-builder/docs/index.js b/tools/component-builder/docs/index.js index ba2e1c21c0e..e74242c9f14 100644 --- a/tools/component-builder/docs/index.js +++ b/tools/component-builder/docs/index.js @@ -40,7 +40,8 @@ async function getDependencies(packagePath = '') { return ( dep.indexOf('@spectrum-css') === 0 && dep !== '@spectrum-css/bundle-builder' && - dep !== '@spectrum-css/component-builder' + dep !== '@spectrum-css/component-builder' && + dep !== '@spectrum-css/component-builder-simple' ); }) .map((dep) => dep.split('/').pop()); diff --git a/tools/component-builder/package.json b/tools/component-builder/package.json index 330ce0c3314..86e5502cf5f 100644 --- a/tools/component-builder/package.json +++ b/tools/component-builder/package.json @@ -12,7 +12,8 @@ }, "license": "Apache-2.0", "peerDependencies": { - "@spectrum-css/vars": "^8.0.0" + "@spectrum-css/vars": "^8.0.0", + "@spectrum-css/tokens": "^1.0.0-beta" }, "dependencies": { "autoprefixer": "^6.5.3", diff --git a/tools/postcss-combininator/README.md b/tools/postcss-combininator/README.md new file mode 100644 index 00000000000..dfdef9cad85 --- /dev/null +++ b/tools/postcss-combininator/README.md @@ -0,0 +1,35 @@ +# postcss-combininator +> Combines multiple blocks of custom properties + +## Installation + +```sh +npm install postcss-combininator +postcss -u postcss-combininator -o dist/index.css src/index.css +``` + +## Usage + +This plugin turns this: + +```css +.spectrum { + --spectrum-actionbutton-background-color: blue; + --spectrum-actionbutton-border-color: transparent; +} + +.spectrum--express { + --spectrum-actionbutton-background-color: purple; +} +``` + +Into this: + +```css +.spectrum--express { + --spectrum-actionbutton-border-color: transparent; + --spectrum-actionbutton-background-color: purple; +} +``` + +The resulting selector comes from the last rule, and all duplicate properties in the subsequent rules override the previous declarations. diff --git a/tools/postcss-combininator/expected/basic.css b/tools/postcss-combininator/expected/basic.css new file mode 100644 index 00000000000..16132380fa6 --- /dev/null +++ b/tools/postcss-combininator/expected/basic.css @@ -0,0 +1,4 @@ +.spectrum--express { + --spectrum-actionbutton-background-color: purple; + --spectrum-actionbutton-border-color: transparent; +} diff --git a/tools/postcss-combininator/fixtures/basic.css b/tools/postcss-combininator/fixtures/basic.css new file mode 100644 index 00000000000..1cffc87a230 --- /dev/null +++ b/tools/postcss-combininator/fixtures/basic.css @@ -0,0 +1,8 @@ +.spectrum { + --spectrum-actionbutton-background-color: blue; + --spectrum-actionbutton-border-color: transparent; +} + +.spectrum--express { + --spectrum-actionbutton-background-color: purple; +} diff --git a/tools/postcss-combininator/index.js b/tools/postcss-combininator/index.js new file mode 100644 index 00000000000..4cc1ef64f8c --- /dev/null +++ b/tools/postcss-combininator/index.js @@ -0,0 +1,44 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const postcss = require('postcss'); + +function process(root, options) { + let rules = []; + let declarations = {}; + root.walkRules(rule => { + rules.push(rule); + rule.walkDecls(decl => { + if (decl.prop.startsWith('--')) { + declarations[decl.prop] = decl; + decl.remove(); + } + }); + }); + + let lastRule = rules[rules.length - 1]; + if (lastRule) { + rules.forEach((rule, index) => { + if (index !== rules.length -1) { + rule.remove(); + } + }); + + for (let decl of Object.values(declarations)) { + lastRule.append(decl); + } + } +} + +module.exports = postcss.plugin('postcss-combininator', function(options) { + return (root, result) => process(root, options) +}); diff --git a/tools/postcss-combininator/package.json b/tools/postcss-combininator/package.json new file mode 100644 index 00000000000..f6436939edf --- /dev/null +++ b/tools/postcss-combininator/package.json @@ -0,0 +1,17 @@ +{ + "name": "postcss-combininator", + "version": "1.0.0-beta.0", + "description": "Combines multiple blocks of custom properties", + "main": "index.js", + "scripts": { + "test": "ava" + }, + "author": "Larry Davis ", + "license": "BSD-2-Clause", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "postcss": "^7.0.32" + } +} diff --git a/tools/postcss-combininator/test.js b/tools/postcss-combininator/test.js new file mode 100644 index 00000000000..04afef235aa --- /dev/null +++ b/tools/postcss-combininator/test.js @@ -0,0 +1,45 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const fs = require('fs'); +const test = require('ava'); +const postcss = require('postcss'); +const plugin = require('./index.js'); + +function compare(t, fixtureFilePath, expectedFilePath, options = { + processIdentifier: (identifier) => { + if (identifier === 'express') { + return 'spectrum--express'; + } + return identifier; + } +}){ + return postcss([ plugin(options) ]) + .process( + readFile(`./fixtures/${fixtureFilePath}`), + { from: fixtureFilePath } + ) + .then(result => { + const actual = result.css; + const expected = readFile(`./expected/${expectedFilePath}`); + t.is(actual, expected); + t.is(result.warnings().length, 0); + }); +} + +function readFile(filename) { + return fs.readFileSync(filename, 'utf8'); +} + +test('create basic output', t => { + return compare(t, 'basic.css', 'basic.css'); +}); diff --git a/tools/postcss-splitinator/README.md b/tools/postcss-splitinator/README.md new file mode 100644 index 00000000000..1a41b6a8fb0 --- /dev/null +++ b/tools/postcss-splitinator/README.md @@ -0,0 +1,80 @@ +# postcss-splitinator +> Splits custom properties organized by classes into named tokens + +## Installation + +```sh +npm install postcss-splitinator +postcss -u postcss-splitinator -o dist/index.css src/index.css +``` + +## Options + +### `options.getName = function(selector, prop)` + +Customize the creation of variable names. By default, as SUIT naming convention is assumed and variable names are created accordingly. + +### `options.processIdentifier = function(identifierValue, identifierName)` + +Customize the selectors that variables are placed in. Passed the value and key of the variable that was passed to the container, i.e. `identifierValue = spectrum` and `identifierName = system` for the example below. By default, `identifierName` is used as-is. + +### `options.noFlatVariables = false` + +Whether to avoid including flat variables in the output. + +### `options.noSelectors = false` + +Whether to avoid including selectors that use the flat variables in the output. + +## Usage + +This plugin turns this: + +```css +@container(--system: spectrum) { + .component { + --background-color: blue; + } + .component.is-selected { + --background-color: darkblue; + } + .component .icon { + --color: gray; + } +} + +@container(--system: express) { + .component { + --background-color: purple; + } + .component.is-selected { + --background-color: darkpurple; + } + .component .icon { + --color: white; + } +} + +``` + +Into this: + +```css +.spectrum { + --system-component-background-color: blue; + --system-component-selected-background-color: darkblue; +} + +.spectrum--express { + --system-component-background-color: purple; + --system-component-selected-background-color: darkpurple; +} + +.component { + --background-color: var(--system-component-background-color); +} + +.component.is-selected { + --background-color: var(--system-component-selected-background-color); +} +``` diff --git a/tools/postcss-splitinator/expected/basic.css b/tools/postcss-splitinator/expected/basic.css new file mode 100644 index 00000000000..e3e1349f65f --- /dev/null +++ b/tools/postcss-splitinator/expected/basic.css @@ -0,0 +1,23 @@ +.spectrum { + --system-component-background-color: blue; + --system-component-selected-background-color: darkblue; + --system-component-icon-color: gray +} + +.spectrum--express { + --system-component-background-color: purple; + --system-component-selected-background-color: darkpurple; + --system-component-icon-color: white +} + +.component { + --background-color: var(--system-component-background-color) +} + +.component.is-selected { + --background-color: var(--system-component-selected-background-color) +} + +.component .icon { + --color: var(--system-component-icon-color) +} diff --git a/tools/postcss-splitinator/fixtures/basic.css b/tools/postcss-splitinator/fixtures/basic.css new file mode 100644 index 00000000000..e7c9a8e5ab8 --- /dev/null +++ b/tools/postcss-splitinator/fixtures/basic.css @@ -0,0 +1,23 @@ +@container(--system: spectrum) { + .component { + --background-color: blue; + } + .component.is-selected { + --background-color: darkblue; + } + .component .icon { + --color: gray; + } +} + +@container(--system: express) { + .component { + --background-color: purple; + } + .component.is-selected { + --background-color: darkpurple; + } + .component .icon { + --color: white; + } +} diff --git a/tools/postcss-splitinator/fixtures/where.css b/tools/postcss-splitinator/fixtures/where.css new file mode 100644 index 00000000000..a150bd77fe4 --- /dev/null +++ b/tools/postcss-splitinator/fixtures/where.css @@ -0,0 +1,23 @@ +@container(--system: spectrum) { + :where(.component) { + --background-color: blue; + } + :where(.component.is-selected) { + --background-color: darkblue; + } + :where(.component .icon) { + --color: gray; + } +} + +@container(--system: express) { + :where(.component) { + --background-color: purple; + } + :where(.component.is-selected) { + --background-color: darkpurple; + } + :where(.component .icon) { + --color: white; + } +} diff --git a/tools/postcss-splitinator/index.js b/tools/postcss-splitinator/index.js new file mode 100644 index 00000000000..86e3d26acfd --- /dev/null +++ b/tools/postcss-splitinator/index.js @@ -0,0 +1,116 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const postcss = require('postcss'); + +function getName(selector, prop) { + selector = selector.replace(/^:where\((.*?)\)$/, '$1'); + + // This regex is designed to pull spectrum-ActionButton out of a selector + let baseSelectorMatch = selector.match(/^\.([a-z]+-[\A-Z][^-. ]+)/); + if (baseSelectorMatch) { + const [, baseSelector] = baseSelectorMatch; + const baseSelectorRegExp = new RegExp(baseSelector, 'gi'); + prop = prop.replace(baseSelectorRegExp, ''); + selector = baseSelector + selector.replace(baseSelectorRegExp, ''); + } + + selector = selector.replace(/is-/g, ''); + + let selectorParts = selector.replace(/\s+/g, '').replace(/,/g, '').split('.'); + + return '--' + (`system-` + `${selectorParts.join('-')}-${prop.substr(2)}`).replace(/-+/g, '-').toLowerCase(); +} + +function process(root, options = {}) { + options.noFlatVariables = options.noFlatVariables ?? false; + options.noSelectors = options.noSelectors ?? false; + const selectorMap = {}; + + root.walkAtRules(container => { + if (container.name === 'container') { + const [, identifierName, identifierValue] = container.params.match(/\(\s*--(.*?)\s*[:=]\s*(.*?)\s*\)/); + + const rule = postcss.rule({ + selector: `.${(options && typeof options.processIdentifier === 'function') ? options.processIdentifier(identifierValue, identifierName) : identifierValue}`, + source: container.source + }); + + if (!options.noFlatVariables) { + container.parent.insertAfter(container, rule); + } + + container.walkDecls(decl => { + if (decl.prop.startsWith('--')) { + // Process rules that match multiple selectors separately to avoid weird var names and edge cases + // note: this doesn't support :where() and is likely brittle! + const selectors = decl.parent.selector.split(/\s*,\s*/); + selectors.forEach(selector => { + const variableName = typeof options.getName === 'function' ? options.getName(selector, decl.prop) : getName(selector, decl.prop); + const newDecl = decl.clone({ + prop: variableName + }); + newDecl.raws.before = '\n '; + + if (!options.noFlatVariables) { + rule.append(newDecl); + } + + const selectorNode = selectorMap[selector] = selectorMap[selector] || {}; + + // Check for fallbacks + // todo: use valueparser instead of a regex + const fallbackMatch = decl.value.match(/var\(\s*(.*?)\s*,\s*var\(\s*(.*?)\s*\)\)/); + if (fallbackMatch) { + const [, override, fallback] = fallbackMatch; + + // The final declaration should have the override present + selectorNode[decl.prop] = `var(${override}, var(${variableName}))`; + + // The system-level declaration should only have the fallback + newDecl.value = `var(${fallback})`; + } + else { + selectorNode[decl.prop] = `var(${variableName})`; + } + }) + } + }); + + container.remove(); + } + }); + + if (!options.noSelectors) { + for (let [selector, props] of Object.entries(selectorMap)) { + const rule = postcss.rule({ + selector + }); + + for (let [prop, value] of Object.entries(props)) { + const decl = postcss.decl({ + prop, + value + }); + decl.raws.before = '\n '; + + rule.append(decl); + } + + root.append(rule); + } + } +} + +module.exports = postcss.plugin('postcss-splitinator', function(options) { + return (root, result) => process(root, options) +}); diff --git a/tools/postcss-splitinator/package.json b/tools/postcss-splitinator/package.json new file mode 100644 index 00000000000..3ea806e199e --- /dev/null +++ b/tools/postcss-splitinator/package.json @@ -0,0 +1,17 @@ +{ + "name": "postcss-splitinator", + "version": "1.0.0-beta.0", + "description": "Turn container queryies into the var hack", + "main": "index.js", + "scripts": { + "test": "ava" + }, + "author": "Larry Davis ", + "license": "BSD-2-Clause", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "postcss": "^7.0.32" + } +} diff --git a/tools/postcss-splitinator/test.js b/tools/postcss-splitinator/test.js new file mode 100644 index 00000000000..04afef235aa --- /dev/null +++ b/tools/postcss-splitinator/test.js @@ -0,0 +1,45 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const fs = require('fs'); +const test = require('ava'); +const postcss = require('postcss'); +const plugin = require('./index.js'); + +function compare(t, fixtureFilePath, expectedFilePath, options = { + processIdentifier: (identifier) => { + if (identifier === 'express') { + return 'spectrum--express'; + } + return identifier; + } +}){ + return postcss([ plugin(options) ]) + .process( + readFile(`./fixtures/${fixtureFilePath}`), + { from: fixtureFilePath } + ) + .then(result => { + const actual = result.css; + const expected = readFile(`./expected/${expectedFilePath}`); + t.is(actual, expected); + t.is(result.warnings().length, 0); + }); +} + +function readFile(filename) { + return fs.readFileSync(filename, 'utf8'); +} + +test('create basic output', t => { + return compare(t, 'basic.css', 'basic.css'); +}); diff --git a/tools/postcss-varfallback/README.md b/tools/postcss-varfallback/README.md index 5b2224cce33..063fb95c835 100644 --- a/tools/postcss-varfallback/README.md +++ b/tools/postcss-varfallback/README.md @@ -18,7 +18,7 @@ Assuming you have some CSS defined that uses fallback variables: } .component { - background-color: var(--custom-background-color, var(--component-background-color)); + background-color: var(--mod-background-color, var(--component-background-color)); } ``` diff --git a/tools/postcss-varfallback/fixtures/basic.css b/tools/postcss-varfallback/fixtures/basic.css index 2a8f64b3019..9de8efd7f60 100644 --- a/tools/postcss-varfallback/fixtures/basic.css +++ b/tools/postcss-varfallback/fixtures/basic.css @@ -3,5 +3,5 @@ } .component { - background-color: var(--custom-background-color, var(--component-background-color)); + background-color: var(--mod-background-color, var(--component-background-color)); } diff --git a/tools/postcss-varfallback/fixtures/functions.css b/tools/postcss-varfallback/fixtures/functions.css index ee97d5c426f..42f7aa02da5 100644 --- a/tools/postcss-varfallback/fixtures/functions.css +++ b/tools/postcss-varfallback/fixtures/functions.css @@ -4,5 +4,5 @@ } .component { - width: calc(var(--custom-width, var(--component-width)) - var(--custom-border-width, var(--component-border-width))); + width: calc(var(--mod-width, var(--component-width)) - var(--mod-border-width, var(--component-border-width))); } diff --git a/tools/postcss-varfallback/fixtures/nested.css b/tools/postcss-varfallback/fixtures/nested.css index d35922d552a..fb9073920b6 100644 --- a/tools/postcss-varfallback/fixtures/nested.css +++ b/tools/postcss-varfallback/fixtures/nested.css @@ -4,5 +4,5 @@ } .component { - background-color: var(--custom-background-color, var(--component-background-color, var(--color-blue))); + background-color: var(--mod-background-color, var(--component-background-color, var(--color-blue))); } diff --git a/yarn.lock b/yarn.lock index 4dec0395343..79680d46e13 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,6 +22,11 @@ resolved "https://registry.yarnpkg.com/@adobe/spectrum-tokens-deprecated/-/spectrum-tokens-deprecated-11.8.0.tgz#7edf6f7b7e3c22581e0732c8de97fa0a68ed66b9" integrity sha512-LW2SA/8VhW868tEcgIcugx7xdtgFG3KiUoEz+4s2nHTdmKj0h2A9pnTNplVTNAMq2uPSfp6wKKvQNNnMSIXqCg== +"@adobe/spectrum-tokens@^12.0.0-beta.21": + version "12.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@adobe/spectrum-tokens/-/spectrum-tokens-12.0.0-beta.21.tgz#0b0257c14b25c4007ca4f14e096c3559e78b2df1" + integrity sha512-72A8/Wf9YlEtpGYYSc1GI1Uu4Nc6ld/o2t1VTGk+6FbArT8LteDVkjr9r1+UROfUEiOmHwOApGsxysKUpM5M8w== + "@babel/code-frame@^7.0.0": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503" @@ -1390,6 +1395,11 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== +"@spectrum-css/actionbutton@^1.1.14": + version "1.1.14" + resolved "https://registry.yarnpkg.com/@spectrum-css/actionbutton/-/actionbutton-1.1.14.tgz#4e12eb7f482fb5944c3d97547591964baebeb1d4" + integrity sha512-ViBjdWi23J6vIR4t8JTRQ6jY/+KgpZgCALj3otgy495zMNG7jPeN7sKoy6i6JZJcdIRJA4MjOTVvcDOGkYWUZg== + "@spectrum-css/spectrum-css-vr-test-assets-essential@^1.0.39": version "1.0.39" resolved "https://registry.yarnpkg.com/@spectrum-css/spectrum-css-vr-test-assets-essential/-/spectrum-css-vr-test-assets-essential-1.0.39.tgz#4b22a22b43f311caa67f0a78708269dff5ee1163" @@ -2548,6 +2558,14 @@ callsites@^3.0.0, callsites@^3.1.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + camelcase-css@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" @@ -2601,6 +2619,15 @@ caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001269.tgz#c6f7b6db8cfe1835017716a6f5204239e0b01eb8" integrity sha512-svC8H/ioT3OcryC1qrO/EHP2opBLiQf8jIJsqIJWS2Qqt1uDO0c4V+Iv7tcpVYbPIx4rzM8AzsXUKKkpZFrEJA== +capital-case@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" + integrity sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -2634,7 +2661,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2642,6 +2669,24 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +change-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" + integrity sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A== + dependencies: + camel-case "^4.1.2" + capital-case "^1.0.4" + constant-case "^3.0.4" + dot-case "^3.0.4" + header-case "^2.0.4" + no-case "^3.0.4" + param-case "^3.0.4" + pascal-case "^3.1.2" + path-case "^3.0.4" + sentence-case "^3.0.4" + snake-case "^3.0.4" + tslib "^2.0.3" + character-parser@^2.1.1, character-parser@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" @@ -3017,6 +3062,11 @@ commander@^2.18.0, commander@^2.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -3149,6 +3199,15 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= +constant-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" + integrity sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case "^2.0.2" + constantinople@^3.0.1, constantinople@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647" @@ -3676,6 +3735,11 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + default-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" @@ -3929,6 +3993,14 @@ domutils@^2.5.2, domutils@^2.6.0, domutils@^2.7.0: domelementtype "^2.2.0" domhandler "^4.2.0" +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + dot-prop@^3.0.0, dot-prop@^5.1.0, dot-prop@^5.2.0, dot-prop@^6.0.1: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -4733,6 +4805,15 @@ fs-extra@3.0.1: jsonfile "^3.0.0" universalify "^0.1.0" +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -5008,7 +5089,7 @@ glob-watcher@^5.0.3: normalize-path "^3.0.0" object.defaults "^1.1.0" -glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -5434,6 +5515,14 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +header-case@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063" + integrity sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q== + dependencies: + capital-case "^1.0.4" + tslib "^2.0.3" + homedir-polyfill@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" @@ -6371,6 +6460,16 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + +jsonc-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" + integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== + jsonfile@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" @@ -6807,6 +6906,13 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -7383,6 +7489,14 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + node-fetch@^2.6.1: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -8021,6 +8135,14 @@ pako@^1.0.5: resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -8147,11 +8269,27 @@ parseurl@~1.3.2, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= +path-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" + integrity sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -9693,6 +9831,15 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" +sentence-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f" + integrity sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + serialize-error@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" @@ -9837,6 +9984,14 @@ smart-buffer@^4.1.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -10304,6 +10459,28 @@ strong-log-transformer@^2.1.0: minimist "^1.2.0" through "^2.3.4" +style-dictionary-sets@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/style-dictionary-sets/-/style-dictionary-sets-1.4.1.tgz#d8c50179879b706e8b84d7707e4b0206acd27d4f" + integrity sha512-9t3E2YEE7kftvVAAnTP1MDQfBj6s2gU7Ox8mEsiQzXXkIOSm1qssthpMWjZ1Gv3cWSzyrAsBiiwnVgt6dM7OxA== + dependencies: + deepmerge "^4.2.2" + +style-dictionary@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/style-dictionary/-/style-dictionary-3.7.0.tgz#02f4b17232cbb1142a3fdc09a17dfb08aafde3b0" + integrity sha512-BL4AQS5kNDBXbFHWJhlCve6+ojnHgHkiwhf2nNByU698elXWdyK5b27OprphT4q0/tJ52zB+lodhqxIxbNOajQ== + dependencies: + chalk "^4.0.0" + change-case "^4.1.2" + commander "^8.3.0" + fs-extra "^10.0.0" + glob "^7.2.0" + json5 "^2.2.0" + jsonc-parser "^3.0.0" + lodash "^4.17.15" + tinycolor2 "^1.4.1" + sugarss@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" @@ -10686,6 +10863,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.0.3: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tslib@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" @@ -10964,6 +11146,20 @@ update-notifier@^5.0.1: semver-diff "^3.1.1" xdg-basedir "^4.0.0" +upper-case-first@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324" + integrity sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg== + dependencies: + tslib "^2.0.3" + +upper-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-2.0.2.tgz#d89810823faab1df1549b7d97a76f8662bae6f7a" + integrity sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg== + dependencies: + tslib "^2.0.3" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"