From b06bdcbe8c6a4afad0202f2bb1ca3a5215466ba4 Mon Sep 17 00:00:00 2001 From: Trevor Burch Date: Mon, 13 Jan 2025 16:18:08 -0500 Subject: [PATCH] feat(components/tabs): tokenize vertical tabset styles (#3015) --- .../src/e2e/vertical-tabs.component.cy.ts | 2 +- .../lib/modules/icon/icon-svg.component.ts | 4 +- .../expansion-indicator.component.ts | 2 + .../expansion-indicator.modern.component.scss | 5 + .../illustration/illustration.component.ts | 4 +- .../vertical-tab.component.html | 3 +- .../vertical-tab.component.scss | 252 ++++++++++++++---- .../vertical-tabset-group.component.html | 5 +- .../vertical-tabset-group.component.scss | 111 +++++--- .../vertical-tabset.component.scss | 87 +++++- .../theme/src/lib/styles/_switch.scss | 6 +- 11 files changed, 367 insertions(+), 114 deletions(-) diff --git a/apps/e2e/tabs-storybook-e2e/src/e2e/vertical-tabs.component.cy.ts b/apps/e2e/tabs-storybook-e2e/src/e2e/vertical-tabs.component.cy.ts index c8de5b0950..2f6dcf404a 100644 --- a/apps/e2e/tabs-storybook-e2e/src/e2e/vertical-tabs.component.cy.ts +++ b/apps/e2e/tabs-storybook-e2e/src/e2e/vertical-tabs.component.cy.ts @@ -87,5 +87,5 @@ describe('tabs-storybook - vertical tabs', () => { ); }); }); - }); + }, true); }); diff --git a/libs/components/icon/src/lib/modules/icon/icon-svg.component.ts b/libs/components/icon/src/lib/modules/icon/icon-svg.component.ts index e98666e988..ffdec87805 100644 --- a/libs/components/icon/src/lib/modules/icon/icon-svg.component.ts +++ b/libs/components/icon/src/lib/modules/icon/icon-svg.component.ts @@ -1,4 +1,4 @@ -import { NgClass, NgStyle } from '@angular/common'; +import { NgClass } from '@angular/common'; import { Component, computed, inject, input } from '@angular/core'; import { toObservable, toSignal } from '@angular/core/rxjs-interop'; @@ -23,7 +23,7 @@ const SIZES = new Map([ */ @Component({ selector: 'sky-icon-svg', - imports: [NgClass, NgStyle], + imports: [NgClass], templateUrl: './icon-svg.component.html', styleUrls: [ './icon-svg.default.component.scss', diff --git a/libs/components/indicators/src/lib/modules/expansion-indicator/expansion-indicator.component.ts b/libs/components/indicators/src/lib/modules/expansion-indicator/expansion-indicator.component.ts index 27be4bdce2..0d1fd66d31 100644 --- a/libs/components/indicators/src/lib/modules/expansion-indicator/expansion-indicator.component.ts +++ b/libs/components/indicators/src/lib/modules/expansion-indicator/expansion-indicator.component.ts @@ -1,4 +1,5 @@ import { Component, Input } from '@angular/core'; +import { SkyThemeComponentClassDirective } from '@skyux/theme'; /** * Displays a chevron icon. @@ -11,6 +12,7 @@ import { Component, Input } from '@angular/core'; './expansion-indicator.modern.component.scss', ], templateUrl: './expansion-indicator.component.html', + hostDirectives: [SkyThemeComponentClassDirective], standalone: false, }) export class SkyExpansionIndicatorComponent { diff --git a/libs/components/indicators/src/lib/modules/expansion-indicator/expansion-indicator.modern.component.scss b/libs/components/indicators/src/lib/modules/expansion-indicator/expansion-indicator.modern.component.scss index 7f244551cb..eff6486bee 100644 --- a/libs/components/indicators/src/lib/modules/expansion-indicator/expansion-indicator.modern.component.scss +++ b/libs/components/indicators/src/lib/modules/expansion-indicator/expansion-indicator.modern.component.scss @@ -7,10 +7,15 @@ --sky-override-expansion-indicator-container-top: 3.5px; --sky-override-expansion-indicator-leg-left-left: 4px; --sky-override-expansion-indicator-leg-right-left: 10.5px; + --sky-override-expansion-indicator-line-height: normal; --sky-override-expansion-indicator-size: 26px; --sky-override-expansion-indicator-size-half: 13px; } +@include mixins.sky-component-host('modern') { + line-height: var(--sky-override-expansion-indicator-line-height, 1); +} + @include mixins.sky-component('modern', '.sky-expansion-indicator') { display: inline-block; border: none; diff --git a/libs/components/indicators/src/lib/modules/illustration/illustration.component.ts b/libs/components/indicators/src/lib/modules/illustration/illustration.component.ts index 91cad8e5fc..ba3a0032e4 100644 --- a/libs/components/indicators/src/lib/modules/illustration/illustration.component.ts +++ b/libs/components/indicators/src/lib/modules/illustration/illustration.component.ts @@ -1,4 +1,4 @@ -import { CommonModule, NgOptimizedImage } from '@angular/common'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, @@ -26,7 +26,7 @@ const pixelSizes: Record = { */ @Component({ selector: 'sky-illustration', - imports: [CommonModule, NgOptimizedImage], + imports: [CommonModule], templateUrl: './illustration.component.html', styleUrls: [ './illustration.default.component.scss', diff --git a/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tab.component.html b/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tab.component.html index 6aa69870f0..b366af4f23 100644 --- a/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tab.component.html +++ b/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tab.component.html @@ -9,8 +9,7 @@ [ngClass]="{ 'sky-vertical-tab-active': active, 'sky-vertical-tabset-button-disabled': disabled, - 'sky-font-deemphasized': disabled, - 'sky-deemphasized': disabled + 'sky-font-deemphasized': disabled }" [tabIndex]="-1" (click)="activateTab()" diff --git a/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tab.component.scss b/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tab.component.scss index 6069640300..d53730aaab 100644 --- a/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tab.component.scss +++ b/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tab.component.scss @@ -1,35 +1,186 @@ @use 'libs/components/theme/src/lib/styles/mixins' as mixins; @use 'libs/components/theme/src/lib/styles/variables' as *; +@use 'libs/components/theme/src/lib/styles/compat-tokens-mixins' as compatMixins; + +@include compatMixins.sky-default-overrides('.sky-vertical-tab') { + --sky-override-vertical-tab-background-color: transparent; + --sky-override-vertical-tab-background-color-active: #{$sky-background-color-neutral-light}; + --sky-override-vertical-tab-background-color-focus: transparent; + --sky-override-vertical-tab-background-color-hover: #{$sky-background-color-neutral-light}; + --sky-override-vertical-tab-background-color-selected: #{$sky-background-color-neutral-light}; + --sky-override-vertical-tab-border-left-active: none; + --sky-override-vertical-tab-border-left-hover: none; + --sky-override-vertical-tab-border-left-selected: #{$sky-nav-selected-border-width} + solid #{$sky-highlight-color-info}; + --sky-override-vertical-tab-box-shadow-focus: none; + --sky-override-vertical-tab-count-margin-left: #{$sky-margin-half}; + --sky-override-vertical-tab-font-color: #{$sky-text-color-default}; + --sky-override-vertical-tab-font-color-disabled: var( + --sky-text-color-deemphasized + ); + --sky-override-vertical-tab-font-selected-color: #{$sky-text-color-default}; + --sky-override-vertical-tab-gap: #{$sky-margin-half}; + --sky-override-vertical-tab-heading-error-padding-left: #{$sky-padding-half}; + --sky-override-vertical-tab-hover-font-color: #{$sky-text-color-default}; + --sky-override-vertical-tab-margin: #{$sky-margin-half} 0 #{$sky-margin-half} + #{$sky-margin}; + --sky-override-vertical-tab-outline-focus: auto; + --sky-override-vertical-tab-padding: #{$sky-padding-3_4} 0 #{$sky-padding-3_4} + #{$sky-padding}; + --sky-override-vertical-tab-padding-left-active: #{$sky-padding}; + --sky-override-vertical-tab-padding-left-selected: 6px; + --sky-override-vertical-tab-padding-left-hover: #{$sky-padding}; +} + +@include compatMixins.sky-modern-overrides('.sky-vertical-tab') { + --sky-override-vertical-tab-background-color-disabled: transparent; + --sky-override-vertical-tab-background-color-selected: transparent; + --sky-override-vertical-tab-border-left-active: var(--modern-size-4) solid + var(--modern-color-blue-50); + --sky-override-vertical-tab-border-left-hover: var(--modern-size-1) solid + var(--modern-color-blue-50); + --sky-override-vertical-tab-content-pane-margin-bottom: 0; + --sky-override-vertical-tab-gap: var(--modern-size-15); + --sky-override-vertical-tab-heading-error-padding-left: var(--modern-size-10); + --sky-override-vertical-tab-margin: var(--modern-size-15) 0 + var(--modern-size-15) var(--modern-size-10); + --sky-override-vertical-tab-padding: var(--modern-size-10) 0 + var(--modern-size-10) var(--modern-size-15); +} + +:host { + &:has(~ sky-vertical-tab) .sky-vertical-tab { + margin-bottom: var( + --sky-override-vertical-tab-gap, + var(--sky-space-gap-action_group-l) + ); + } + + &:has(.sky-vertical-tabset-button-disabled) { + cursor: not-allowed; + } +} .sky-vertical-tab { cursor: pointer; - padding: $sky-padding-3_4 0 $sky-padding-3_4 $sky-padding; - margin: $sky-margin-half 0 $sky-margin-half $sky-margin; + background-color: var( + --sky-override-vertical-tab-background-color, + var(--sky-color-background-nav-base) + ); + padding: var( + --sky-override-vertical-tab-padding, + var(--sky-space-inset-pillarbox-2_3-top-m) + var(--sky-space-inset-pillarbox-2_3-right-m) + var(--sky-space-inset-pillarbox-2_3-bottom-m) + var(--sky-space-inset-pillarbox-2_3-left-m) + ); + margin: var( + --sky-override-vertical-tab-margin, + 0 0 0 var(--sky-space-inline-s) + ); display: flex; text-decoration: none; + color: var( + --sky-override-vertical-tab-font-color, + var(--sky-color-text-deemphasized) + ); + border-radius: var(--sky-border-radius-0); + + &:hover { + color: var( + --sky-override-vertical-tab-hover-font-color, + var(--sky-color-text-default) + ); + background-color: var( + --sky-override-vertical-tab-background-color-hover, + var(--sky-color-background-nav-hover) + ); - &:not(.sky-deemphasized) { - color: $sky-text-color-default; + // TODO: Tokenize with sectioned form + .sky-vertical-tab-right-arrow { + color: darken($sky-text-color-icon-borderless, 20%); + } } - &:hover { - background-color: $sky-background-color-neutral-light; + &:active { + background-color: var( + --sky-override-vertical-tab-background-color-active, + var(--sky-color-background-nav-active) + ); + border-left: var( + --sky-override-vertical-tab-border-left-active, + var(--sky-border-width-selected-l) solid var(--sky-color-border-selected) + ); + color: var( + --sky-override-vertical-tab-active-font-color, + var(--sky-color-text-default) + ); + padding-left: var( + --sky-override-vertical-tab-padding-left-active, + calc( + var(--sky-space-inset-pillarbox-2_3-left-m) - var( + --sky-border-width-selected-l + ) + ) + ); } - &:focus-visible { - @include mixins.sky-focus-outline; + &:not(:active):focus-visible { + background-color: var( + --sky-override-vertical-tab-background-color-focus, + var(--sky-color-background-nav-focus) + ); + outline: var( + --sky-override-vertical-tab-outline-focus, + var(--sky-border-width-selected-m) solid var(--sky-color-border-selected) + ); + outline-offset: var( + --sky-override-vertical-tab-outline-focus-offset, + calc(var(--sky-border-width-selected-m) * -1) + ); + box-shadow: var( + --sky-override-vertical-tab-box-shadow-focus, + var(--sky-elevation-focus) + ); } - &:hover .sky-vertical-tab-right-arrow { - color: darken($sky-text-color-icon-borderless, 20%); + &:not(.sky-vertical-tab-active):not(:active):hover { + padding-left: var( + --sky-override-vertical-tab-padding-left-hover, + calc( + var(--sky-space-inset-pillarbox-2_3-left-m) - var( + --sky-border-width-selected-s + ) + ) + ); + border-left: var( + --sky-override-vertical-tab-border-left-hover, + var(--sky-border-width-selected-s) solid var(--sky-color-border-selected) + ); } } .sky-vertical-tab-active { - background-color: $sky-background-color-neutral-light; - color: $sky-text-color-default; - padding-left: 6px; - border-left: $sky-nav-selected-border-width solid $sky-highlight-color-info; + background-color: var( + --sky-override-vertical-tab-background-color-selected, + var(--sky-color-background-selected-soft) + ); + color: var( + --sky-override-vertical-tab-selected-font-color, + var(--sky-color-text-default) + ); + padding-left: var( + --sky-override-vertical-tab-padding-left-selected, + calc( + var(--sky-space-inset-pillarbox-2_3-left-m) - var( + --sky-border-width-selected-l + ) + ) + ); + border-left: var( + --sky-override-vertical-tab-border-left-selected, + var(--sky-border-width-selected-l) solid var(--sky-color-border-selected) + ); } .sky-vertical-tab-hidden { @@ -43,75 +194,66 @@ } .sky-vertical-tab-heading-error { - padding-left: $sky-padding-half; + padding-left: var( + --sky-override-vertical-tab-heading-error-padding-left, + var(--sky-space-gap-text_action-s) + ); } .sky-vertical-tab-count { - margin-left: $sky-margin-half; + margin-left: var( + --sky-override-vertical-tab-count-margin-left, + var(--sky-space-gap-label-s) + ); } .sky-vertical-tabset-button-disabled { - cursor: not-allowed; + background-color: var( + --sky-override-vertical-tab-background-color-disabled, + var(--sky-color-background-nav-disabled) + ); + // Only needed for default theme. This rule can be removed when that theme is removed. + color: var( + --sky-override-vertical-tab-font-color-disabled, + var(--sky-color-text-deemphasized) + ); pointer-events: none; } +// TODO: Tokenize with sectioned form .sky-vertical-tab-right-arrow { padding: 3px $sky-padding 0 0; color: $sky-text-color-icon-borderless; } .sky-vertical-tab-content-pane { + margin-bottom: 0; + &:focus-visible { outline: none; border: none; } } +// NOTE: Due to the way that this pane is rendered, we can't use the mixins here. +.sky-responsive-container-xs { + .sky-vertical-tab-content-pane { + // NOTE: The overrides here are housed in the tabset component scss file due to view encapsulation issues and where this class ends up rendered. + margin-bottom: var( + --sky-override-vertical-tab-content-pane-margin-bottom, + var(--sky-space-stacked-s) + ); + } +} + @include mixins.sky-theme-modern { .sky-vertical-tab { - color: $sky-text-color-deemphasized; - cursor: pointer; - padding: $sky-theme-modern-space-sm 0 $sky-theme-modern-space-sm - $sky-theme-modern-space-md; - margin: $sky-theme-modern-margin-inline-md 0 - $sky-theme-modern-margin-inline-md $sky-theme-modern-margin-inline-sm; - - &:not(.sky-vertical-tab-active):not(:active):hover { - color: $sky-text-color-default; - background-color: transparent; - padding-left: 14px; - border-left: 1px solid $sky-highlight-color-info; - } - - &:not(:active):focus-visible { - outline: solid 2px $sky-theme-modern-background-color-primary-dark; - outline-offset: -2px; - box-shadow: $sky-theme-modern-elevation-3-shadow-size - $sky-theme-modern-elevation-3-shadow-color; - } - - &:focus:active:hover { - outline: none; - background: none; - } - - &:active { - border-left: 4px solid $sky-highlight-color-info; - color: $sky-text-color-default; - padding-left: 11px; - } + // TODO: This is due to a bug in icons where icon stacks display larger than their inner icons current. .sky-vertical-tab-heading-error { - padding-left: $sky-theme-modern-space-sm; position: relative; top: -2px; } } - .sky-vertical-tab-active { - background: none; - color: $sky-text-color-default; - padding-left: 11px; - border-left: 4px solid $sky-theme-modern-color-blue-74; - } } :host-context(.sky-sectioned-form-tabs-only) { diff --git a/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset-group.component.html b/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset-group.component.html index 21c7c48324..fbac8cda15 100644 --- a/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset-group.component.html +++ b/libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset-group.component.html @@ -5,13 +5,12 @@ [ngClass]="{ 'sky-vertical-tabset-group-header-active sky-font-emphasized': isActive(), 'sky-vertical-tabset-group-header-sub-open': open, - 'sky-font-deemphasized': disabled, - 'sky-deemphasized': disabled + 'sky-font-deemphasized': disabled }" >