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),