diff --git a/src/elements/button/common/button-common.scss b/src/elements/button/common/button-common.scss index be4cbc4fc2..a598dbd6a6 100644 --- a/src/elements/button/common/button-common.scss +++ b/src/elements/button/common/button-common.scss @@ -13,51 +13,11 @@ $icon-only: ':where([data-slot-names~=icon], [icon-name]):not([data-slot-names~= outline: none !important; --sbb-button-icon-size: var(--sbb-size-icon-ui-small); - --sbb-button-color-disabled-background: var(--sbb-color-milk); - --sbb-button-color-disabled-border: var(--sbb-color-smoke); - --sbb-button-color-disabled-text: var(--sbb-color-granite); - --sbb-button-shadow-1-offset-y: var(--sbb-shadow-elevation-level-3-shadow-1-offset-y); - --sbb-button-shadow-2-offset-y: var(--sbb-shadow-elevation-level-3-shadow-2-offset-y); - --sbb-button-shadow-1-blur: var(--sbb-shadow-elevation-level-3-shadow-1-blur); - --sbb-button-shadow-2-blur: var(--sbb-shadow-elevation-level-3-shadow-2-blur); - --sbb-button-shadow-1-color: var(--sbb-color-red-alpha-20); - --sbb-button-shadow-2-color: var(--sbb-color-red125-alpha-20); - --sbb-button-border-style: solid; - --sbb-button-border-disabled-style: dashed; - --sbb-button-border-width: var(--sbb-border-width-2x); - --sbb-button-border-disabled-width: var(--sbb-border-width-1x); - --sbb-button-border-radius: var(--sbb-border-radius-infinity); - --sbb-button-min-height: var(--sbb-size-element-m); - --sbb-button-transition-duration: var( - --sbb-disable-animation-zero-time, - var(--sbb-animation-duration-2x) - ); - --sbb-button-transition-easing-function: var(--sbb-animation-easing); - --sbb-button-padding-block-min: var(--sbb-spacing-fixed-1x); - --sbb-button-padding-inline: var(--sbb-spacing-fixed-8x); --sbb-button-gap: var(--sbb-spacing-fixed-2x); - --sbb-button-inset: 0; - --sbb-button-box-shadow: transparent; - --sbb-button-box-shadow-definition: var(--sbb-shadow-elevation-level-3-shadow-2-offset-x) - var(--sbb-button-shadow-2-offset-y) var(--sbb-button-shadow-2-blur) - var(--sbb-shadow-elevation-level-3-shadow-2-spread) var(--sbb-button-shadow-2-color), - var(--sbb-shadow-elevation-level-3-shadow-1-offset-x) var(--sbb-button-shadow-1-offset-y) - var(--sbb-button-shadow-1-blur) var(--sbb-shadow-elevation-level-3-shadow-1-spread) - var(--sbb-button-shadow-1-color); - - @include sbb.mq($from: medium) { - --sbb-button-padding-inline: var(--sbb-spacing-fixed-10x); - } - @include sbb.if-forced-colors { - --sbb-button-color-default-border: CanvasText !important; - --sbb-button-color-active-border: Highlight !important; - --sbb-button-color-default-background: Canvas !important; - --sbb-button-color-hover-background: Canvas !important; - --sbb-button-color-active-background: Canvas !important; - --sbb-button-color-disabled-background: Canvas !important; - --sbb-button-color-disabled-text: GrayText !important; + @include sbb.button-variables; + @include sbb.if-forced-colors { // For static cases, button and link roles will override it. --sbb-button-color-default-text: CanvasText !important; --sbb-button-color-hover-text: CanvasText !important; @@ -87,22 +47,11 @@ $icon-only: ':where([data-slot-names~=icon], [icon-name]):not([data-slot-names~= } :host([size='m']) { - --sbb-button-min-height: var(--sbb-size-element-s); - --sbb-button-padding-inline: var(--sbb-spacing-fixed-5x); - - @include sbb.mq($from: medium) { - --sbb-button-padding-inline: var(--sbb-spacing-fixed-8x); - } + @include sbb.button-size-m; } :host([size='s']) { - --sbb-button-min-height: var(--sbb-size-element-xs); - --sbb-button-padding-inline: var(--sbb-spacing-fixed-4x); - --sbb-button-gap: var(--sbb-spacing-fixed-1x); - - @include sbb.mq($from: medium) { - --sbb-button-padding-inline: var(--sbb-spacing-fixed-5x); - } + @include sbb.button-size-s; } :host(#{$icon-only}) { @@ -110,81 +59,35 @@ $icon-only: ':where([data-slot-names~=icon], [icon-name]):not([data-slot-names~= } :host(:not([disabled], :active, [data-active]):hover) { - @include sbb.hover-mq($hover: true) { - --sbb-button-translate-y-content-hover: #{sbb.px-to-rem-build(-1)}; - --sbb-button-shadow-1-offset-y: calc( - 0.5 * var(--sbb-shadow-elevation-level-3-shadow-1-offset-y) - ); - --sbb-button-shadow-1-blur: calc(0.5 * var(--sbb-shadow-elevation-level-3-shadow-1-blur)); - --sbb-button-shadow-2-blur: calc(0.5 * var(--sbb-shadow-elevation-level-3-shadow-2-blur)); - } - - @include sbb.if-forced-colors { - --sbb-button-color-hover-border: Highlight !important; - } + @include sbb.button-hover; } .sbb-action-base { @include sbb.text-xs--bold; + @include sbb.button-base; // Reset for link variant text-decoration: none; width: 100%; - position: relative; - display: flex; gap: var(--sbb-button-gap); - align-items: center; - justify-content: center; - text-align: left; transition-duration: var(--sbb-button-transition-duration); transition-timing-function: var(--sbb-button-transition-easing-function); transition-property: color; - min-height: var(--sbb-button-min-height); - border-radius: var(--sbb-button-border-radius); - - // The padding block value is only a minimal padding to preserve a padding if the content becomes larger than intended. - // Positioning of the content is made by flexbox vertical centering. - // The real padding displayed is larger than the defined value below. - padding-block: var(--sbb-button-padding-block-min); - padding-inline: var(--sbb-button-padding-inline); - color: var(--sbb-button-color-default-text); - cursor: pointer; - user-select: none; - outline: none; // Renders background and border in the background absolute to enable the hover animation &::before { - position: absolute; - content: ''; - inset: var(--sbb-button-inset); - border: var(--sbb-button-border-width) var(--sbb-button-border-style) - var(--sbb-button-color-default-border); - border-radius: var(--sbb-button-border-radius); - background-color: var(--sbb-button-color-default-background); - transition-duration: var(--sbb-button-transition-duration); - transition-timing-function: var(--sbb-button-transition-easing-function); - transition-property: inset, background-color, border-color, box-shadow; - box-shadow: var(--sbb-button-box-shadow); + @include sbb.button-base-before; :host([disabled]) & { - background-color: var(--sbb-button-color-disabled-background); - border-width: var(--sbb-button-border-disabled-width); - border-color: var(--sbb-button-color-disabled-border); - border-style: var(--sbb-button-border-disabled-style); + @include sbb.button-disabled-before; } :host(:not([disabled], :active, [data-active]):hover) & { - @include sbb.hover-mq($hover: true) { - inset: calc(var(--sbb-button-border-width) * -1); - background-color: var(--sbb-button-color-hover-background); - border-color: var(--sbb-button-color-hover-border); - } + @include sbb.button-hover-before; } :host(:not([disabled]):is(:active, [data-active])) & { - color: var(--sbb-button-color-active-text); - background-color: var(--sbb-button-color-active-background); - border-color: var(--sbb-button-color-active-border); + @include sbb.button-active; } } @@ -194,9 +97,7 @@ $icon-only: ':where([data-slot-names~=icon], [icon-name]):not([data-slot-names~= } :host([disabled]) & { - color: var(--sbb-button-color-disabled-text); - cursor: default; - pointer-events: none; + @include sbb.button-disabled; } :host(:not([disabled], :active, [data-active]):hover) & { diff --git a/src/elements/core/styles/mixins/buttons.scss b/src/elements/core/styles/mixins/buttons.scss index 96f3d2dcf9..3c0eba0f42 100644 --- a/src/elements/core/styles/mixins/buttons.scss +++ b/src/elements/core/styles/mixins/buttons.scss @@ -178,3 +178,261 @@ background-color: var(--sbb-button-color-active-background); } } + +@mixin button-variables { + --sbb-button-color-disabled-background: var(--sbb-color-milk); + --sbb-button-color-disabled-border: var(--sbb-color-smoke); + --sbb-button-color-disabled-text: var(--sbb-color-granite); + --sbb-button-shadow-1-offset-y: var(--sbb-shadow-elevation-level-3-shadow-1-offset-y); + --sbb-button-shadow-2-offset-y: var(--sbb-shadow-elevation-level-3-shadow-2-offset-y); + --sbb-button-shadow-1-blur: var(--sbb-shadow-elevation-level-3-shadow-1-blur); + --sbb-button-shadow-2-blur: var(--sbb-shadow-elevation-level-3-shadow-2-blur); + --sbb-button-shadow-1-color: var(--sbb-color-red-alpha-20); + --sbb-button-shadow-2-color: var(--sbb-color-red125-alpha-20); + --sbb-button-box-shadow: transparent; + --sbb-button-box-shadow-definition: var(--sbb-shadow-elevation-level-3-shadow-2-offset-x) + var(--sbb-button-shadow-2-offset-y) var(--sbb-button-shadow-2-blur) + var(--sbb-shadow-elevation-level-3-shadow-2-spread) var(--sbb-button-shadow-2-color), + var(--sbb-shadow-elevation-level-3-shadow-1-offset-x) var(--sbb-button-shadow-1-offset-y) + var(--sbb-button-shadow-1-blur) var(--sbb-shadow-elevation-level-3-shadow-1-spread) + var(--sbb-button-shadow-1-color); + --sbb-button-border-style: solid; + --sbb-button-border-disabled-style: dashed; + --sbb-button-border-width: var(--sbb-border-width-2x); + --sbb-button-border-disabled-width: var(--sbb-border-width-1x); + --sbb-button-border-radius: var(--sbb-border-radius-infinity); + --sbb-button-min-height: var(--sbb-size-element-m); + --sbb-button-padding-block-min: var(--sbb-spacing-fixed-1x); + --sbb-button-padding-inline: var(--sbb-spacing-fixed-8x); + --sbb-button-inset: 0; + --sbb-button-transition-duration: var( + --sbb-disable-animation-zero-time, + var(--sbb-animation-duration-2x) + ); + --sbb-button-transition-easing-function: var(--sbb-animation-easing); + + // breaks scss rules + @include mediaqueries.mq($from: medium) { + --sbb-button-padding-inline: var(--sbb-spacing-fixed-10x); + } + + @include a11y.if-forced-colors { + --sbb-button-color-default-border: CanvasText !important; + --sbb-button-color-active-border: Highlight !important; + --sbb-button-color-default-background: Canvas !important; + --sbb-button-color-hover-background: Canvas !important; + --sbb-button-color-active-background: Canvas !important; + --sbb-button-color-disabled-background: Canvas !important; + --sbb-button-color-disabled-text: GrayText !important; + --sbb-button-color-default-text: ButtonText !important; + --sbb-button-color-hover-text: ButtonText !important; + --sbb-button-color-active-text: ButtonText !important; + } +} + +@mixin button-disabled { + color: var(--sbb-button-color-disabled-text); + cursor: default; + pointer-events: none; +} + +@mixin button-disabled-before { + border-width: var(--sbb-button-border-disabled-width); + border-color: var(--sbb-button-color-disabled-border); + border-style: var(--sbb-button-border-disabled-style); + background-color: var(--sbb-button-color-disabled-background); +} + +@mixin button-hover { + @include mediaqueries.hover-mq($hover: true) { + --sbb-button-translate-y-content-hover: #{functions.px-to-rem-build(-1)}; + --sbb-button-shadow-1-offset-y: calc( + 0.5 * var(--sbb-shadow-elevation-level-3-shadow-1-offset-y) + ); + --sbb-button-shadow-1-blur: calc(0.5 * var(--sbb-shadow-elevation-level-3-shadow-1-blur)); + --sbb-button-shadow-2-blur: calc(0.5 * var(--sbb-shadow-elevation-level-3-shadow-2-blur)); + + @include a11y.if-forced-colors { + --sbb-button-color-hover-border: Highlight !important; + } + } +} + +@mixin button-hover-before { + @include mediaqueries.hover-mq($hover: true) { + inset: calc(var(--sbb-button-border-width) * -1); + background-color: var(--sbb-button-color-hover-background); + border-color: var(--sbb-button-color-hover-border); + } +} + +@mixin button-active { + color: var(--sbb-button-color-active-text); + background-color: var(--sbb-button-color-active-background); + border-color: var(--sbb-button-color-active-border); +} + +@mixin button-focus-visible { + &::before { + @include a11y.focus-outline; + } +} + +@mixin button-size-s { + --sbb-button-min-height: var(--sbb-size-element-xs); + --sbb-button-padding-inline: var(--sbb-spacing-fixed-4x); + --sbb-button-gap: var(--sbb-spacing-fixed-1x); + + @include mediaqueries.mq($from: medium) { + --sbb-button-padding-inline: var(--sbb-spacing-fixed-5x); + } +} + +@mixin button-size-m { + --sbb-button-min-height: var(--sbb-size-element-s); + --sbb-button-padding-inline: var(--sbb-spacing-fixed-5x); + + @include mediaqueries.mq($from: medium) { + --sbb-button-padding-inline: var(--sbb-spacing-fixed-8x); + } +} + +@mixin button-base { + @include typo.text-xs--bold; + + position: relative; + display: flex; + align-items: center; + justify-content: center; + text-align: left; + min-height: var(--sbb-button-min-height); + border-radius: var(--sbb-button-border-radius); + + // The padding block value is only a minimal padding to preserve a padding if the content becomes larger than intended. + // Positioning of the content is made by flexbox vertical centering. + // The real padding displayed is larger than the defined value below. + padding-block: var(--sbb-button-padding-block-min); + padding-inline: var(--sbb-button-padding-inline); + color: var(--sbb-button-color-default-text); + cursor: pointer; + user-select: none; + outline: none; +} + +@mixin button-base-before { + position: absolute; + content: ''; + inset: var(--sbb-button-inset); + border: var(--sbb-button-border-width) var(--sbb-button-border-style) + var(--sbb-button-color-default-border); + border-radius: var(--sbb-button-border-radius); + background-color: var(--sbb-button-color-default-background); + transition-duration: var(--sbb-button-transition-duration); + transition-timing-function: var(--sbb-button-transition-easing-function); + transition-property: inset, background-color, border-color, box-shadow; + box-shadow: var(--sbb-button-box-shadow); +} + +@mixin button-primary { + --sbb-button-color-active-background: var(--sbb-color-red150); + --sbb-button-color-active-border: var(--sbb-color-red150); + --sbb-button-color-active-text: var(--sbb-color-cloud); + --sbb-button-color-default-background: var(--sbb-color-red); + --sbb-button-color-default-border: var(--sbb-color-red); + --sbb-button-color-default-text: var(--sbb-color-white); + --sbb-button-color-hover-background: var(--sbb-color-red125); + --sbb-button-color-hover-border: var(--sbb-color-red125); + --sbb-button-color-hover-text: var(--sbb-color-milk); +} + +@mixin button-primary-negative { + --sbb-button-color-active-background: var(--sbb-color-cloud); + --sbb-button-color-active-border: var(--sbb-color-cloud); + --sbb-button-color-active-text: var(--sbb-color-red150); + --sbb-button-color-default-background: var(--sbb-color-white); + --sbb-button-color-default-border: var(--sbb-color-white); + --sbb-button-color-default-text: var(--sbb-color-red); + --sbb-button-color-disabled-background: var(--sbb-color-anthracite); + --sbb-button-color-disabled-text: var(--sbb-color-aluminium); + --sbb-button-color-hover-background: var(--sbb-color-milk); + --sbb-button-color-hover-border: var(--sbb-color-milk); + --sbb-button-color-hover-text: var(--sbb-color-red125); + --sbb-button-shadow-1-color: var(--sbb-color-smoke-alpha-20); + --sbb-button-shadow-2-color: var(--sbb-color-metal-alpha-20); +} + +@mixin button-primary-shadow { + --sbb-button-box-shadow: var(--sbb-button-box-shadow-definition); +} + +/** + * FIXME + * An example of a mixin that can be applied on a native button (using dataset attributes for size and negative) + * in order to be rendered as a `sbb-button` in primary variant. + * In a similar way the other variants can be obtained. + */ +@mixin button { + @include button-reset; + @include button-primary; + @include button-base; + @include button-variables; + + & { + transition: { + duration: var(--sbb-button-transition-duration); + timing-function: var(--sbb-button-transition-easing-function); + property: color, transform; + } + + transform: translateY( + var(--sbb-button-translate-y-content-hover, #{functions.px-to-rem-build(0)}) + ); + } + + // Renders background and border in the background absolute to enable the hover animation + &::before { + @include button-base-before; + + z-index: -1; + } + + &[data-negative] { + @include button-primary-negative; + } + + &[disabled] { + @include button-disabled; + + &::before { + @include button-disabled-before; + } + } + + &:not([disabled], :active, [data-active]) { + @include button-primary-shadow; + + &:hover { + @include button-hover; + + &::before { + @include button-hover-before; + } + } + } + + &:not([disabled]):is(:active, [data-active]) { + @include button-active; + } + + &:focus-visible { + @include button-focus-visible; + } + + &[data-size='s'] { + @include button-size-s; + } + + &[data-size='m'] { + @include button-size-m; + } +}