From 8329624ccab1ce3b48302a353dc9254d788ad420 Mon Sep 17 00:00:00 2001 From: Jouni Koivuviita Date: Tue, 7 Oct 2025 12:10:02 +0300 Subject: [PATCH] feat: aura tabs theme --- dev/aura.html | 9 ++ packages/aura/aura.css | 1 + packages/aura/src/color.css | 3 +- packages/aura/src/components/tabs.css | 125 ++++++++++++++++++++++++++ packages/aura/src/surface.css | 1 + 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 packages/aura/src/components/tabs.css diff --git a/dev/aura.html b/dev/aura.html index 5d20e593ee..7d271a9740 100644 --- a/dev/aura.html +++ b/dev/aura.html @@ -43,6 +43,7 @@ import '@vaadin/select'; import '@vaadin/scroller'; import '@vaadin/side-nav'; + import '@vaadin/tabs'; import '@vaadin/text-field'; import '@vaadin/vertical-layout'; import { html, render } from 'lit'; @@ -597,6 +598,14 @@

Components

+
+ + Details2 + Preferences + Settings + +
+
diff --git a/packages/aura/aura.css b/packages/aura/aura.css index 60436afaf2..3d90d41d07 100644 --- a/packages/aura/aura.css +++ b/packages/aura/aura.css @@ -30,6 +30,7 @@ @import './src/components/rich-text-editor.css'; @import './src/components/select.css'; @import './src/components/side-nav.css'; +@import './src/components/tabs.css'; @import './src/components/upload.css'; :where(:root, :host) { diff --git a/packages/aura/src/color.css b/packages/aura/src/color.css index 152161e32b..322d56003d 100644 --- a/packages/aura/src/color.css +++ b/packages/aura/src/color.css @@ -89,7 +89,8 @@ vaadin-menu-bar-button, vaadin-menu-bar-item, vaadin-checkbox::part(checkbox), vaadin-radio-button::part(radio), -vaadin-side-nav-item::part(content) { +vaadin-side-nav-item::part(content), +vaadin-tab { --aura-accent-contrast-light: oklch( from var(--aura-accent-light) clamp(0, (0.62 - l) * 1000, 1) 0 0 / clamp(0.8, (0.62 - l) * 1000, 1) ); diff --git a/packages/aura/src/components/tabs.css b/packages/aura/src/components/tabs.css new file mode 100644 index 0000000000..ffff10fe71 --- /dev/null +++ b/packages/aura/src/components/tabs.css @@ -0,0 +1,125 @@ +:where(:root, :host) { + --vaadin-tab-font-weight: var(--aura-font-weight-medium); + --vaadin-tabs-gap: 2px; +} + +vaadin-tabs { + background: var(--vaadin-background-container); + border-radius: calc(var(--vaadin-radius-m) + 3px); + padding: 3px; + contain: paint; +} + +vaadin-tabs:not([theme~='accent']) { + --aura-accent-light: var(--aura-text-light); + --aura-accent-dark: var(--aura-text-dark); +} + +vaadin-tabs::part(tabs) { + padding: 3px; + margin: -3px; + --_mask-fade-start: 0.5lh; + --_mask-fade-size: 2lh; + mask-image: linear-gradient( + var(--_mask-dir, to right), + var(--_mask-start, black) var(--_mask-fade-start), + black var(--_mask-fade-size), + black calc(100% - var(--_mask-fade-size)), + var(--_mask-end, black) calc(100% - var(--_mask-fade-start)) + ); +} + +vaadin-tabs[dir='rtl']::part(tabs) { + --_mask-dir: to left; +} + +vaadin-tabs[orientation='vertical']::part(tabs) { + --_mask-dir: to bottom; + --_mask-fade-start: 0px; + --_mask-fade-size: 0.5lh; +} + +vaadin-tabs[overflow~='start'] { + --_mask-start: transparent; +} + +vaadin-tabs[overflow~='end'] { + --_mask-end: transparent; +} + +vaadin-tabs::part(back-button), +vaadin-tabs::part(forward-button) { + background: var(--aura-surface-solid) padding-box; + border: 1px solid var(--vaadin-border-color); + border-radius: var(--vaadin-radius-m); + padding: var(--vaadin-padding-xs); + height: auto; + align-self: center; + box-shadow: 0 1px 4px -1px var(--aura-shadow-color); + transition: opacity 120ms; +} + +vaadin-tabs::part(back-button) { + inset-inline-start: 5px; +} + +vaadin-tabs::part(forward-button) { + inset-inline-end: 5px; +} + +vaadin-tab { + transition: + color 120ms, + border-color 120ms, + background-color 120ms; + --aura-surface-level: 8; + --aura-surface-opacity: 0.7; + border: 1px solid transparent; +} + +vaadin-tab:not([disabled], [selected]):hover { + --vaadin-tab-color: var(--vaadin-text-color); +} + +vaadin-tab[selected] { + --_accent: light-dark( + oklch(from var(--aura-accent-light) calc(l + 0.2) c h / min(0.3, c / 2)), + oklch(from var(--aura-accent-dark) calc(l - 0.2) c h / min(0.3, c / 2)) + ); + --_accent-border: light-dark( + oklch(from var(--aura-accent-light) l calc(c / 2) h / calc(min(0.15, 0.05 + c / 2) + 0.1 * var(--aura-contrast))), + oklch(from var(--aura-accent-dark) l calc(c / 2) h / calc(min(0.15, 0.05 + c / 2) + 0.1 * var(--aura-contrast))) + ); + --vaadin-tab-background: linear-gradient(var(--_accent), var(--_accent)) var(--aura-surface) padding-box; + --vaadin-tab-color: var(--aura-accent-text); + border-color: var(--_accent-border); + box-shadow: 0 1px 4px -1px var(--aura-shadow-color); +} + +/* Filled variant */ + +vaadin-tabs[theme~='filled'] vaadin-tab[selected] { + --vaadin-tab-background: var(--aura-accent-color) border-box; + --vaadin-tab-color: var(--aura-accent-contrast); + outline-offset: 1px; +} + +/* Badges and other content that uses the palette inside a filled nav item */ +vaadin-tabs[theme~='filled'] vaadin-tab[selected] > :not([slot='tooltip']) { + --vaadin-text-color: var(--vaadin-tab-color); + --vaadin-text-color-secondary: var(--vaadin-tab-color); + --aura-accent-color: var(--vaadin-tab-color); + --aura-accent-text: var(--vaadin-tab-color); + --aura-red: var(--vaadin-tab-color); + --aura-red-text: var(--vaadin-tab-color); + --aura-orange: var(--vaadin-tab-color); + --aura-orange-text: var(--vaadin-tab-color); + --aura-yellow: var(--vaadin-tab-color); + --aura-yellow-text: var(--vaadin-tab-color); + --aura-green: var(--vaadin-tab-color); + --aura-green-text: var(--vaadin-tab-color); + --aura-blue: var(--vaadin-tab-color); + --aura-blue-text: var(--vaadin-tab-color); + --aura-purple: var(--vaadin-tab-color); + --aura-purple-text: var(--vaadin-tab-color); +} diff --git a/packages/aura/src/surface.css b/packages/aura/src/surface.css index ebf2fb028f..896500de89 100644 --- a/packages/aura/src/surface.css +++ b/packages/aura/src/surface.css @@ -19,6 +19,7 @@ vaadin-message-input, vaadin-radio-button::part(radio), vaadin-rich-text-editor, vaadin-side-nav-item::part(content), +vaadin-tab, vaadin-upload, vaadin-upload-file, ::part(input-field),