+
+
+
diff --git a/packages/sit-onyx/src/components/OnyxFlyoutMenu/future/readme.md b/packages/sit-onyx/src/components/OnyxFlyoutMenu/future/readme.md
new file mode 100644
index 0000000000..fa892cfa3b
--- /dev/null
+++ b/packages/sit-onyx/src/components/OnyxFlyoutMenu/future/readme.md
@@ -0,0 +1,3 @@
+# OnyxFlyoutMenu
+
+This is the new (future) version of OnyxFlyoutMenu component. The strucuture of the component is optimized and it will replace the current OnyxFlyoutMenu in the future.
diff --git a/packages/sit-onyx/src/components/OnyxListItem/OnyxListItem.vue b/packages/sit-onyx/src/components/OnyxListItem/OnyxListItem.vue
index 3412567f8e..614ce60fd5 100644
--- a/packages/sit-onyx/src/components/OnyxListItem/OnyxListItem.vue
+++ b/packages/sit-onyx/src/components/OnyxListItem/OnyxListItem.vue
@@ -92,4 +92,3 @@ const props = defineProps & { active?: boolean }>();
}
}
-../OnyxSelect/types
diff --git a/packages/sit-onyx/src/components/OnyxNavButton/OnyxNavButton.ct.tsx b/packages/sit-onyx/src/components/OnyxNavButton/OnyxNavButton.ct.tsx
new file mode 100644
index 0000000000..d6cf03059e
--- /dev/null
+++ b/packages/sit-onyx/src/components/OnyxNavButton/OnyxNavButton.ct.tsx
@@ -0,0 +1,81 @@
+import type { Locator } from "@playwright/test";
+import { expect, test } from "../../playwright/a11y";
+import { executeMatrixScreenshotTest } from "../../playwright/screenshots";
+import OnyxListItem from "../OnyxListItem/OnyxListItem.vue";
+import OnyxNavButton from "./OnyxNavButton.vue";
+
+test.describe("Screenshot tests", () => {
+ executeMatrixScreenshotTest({
+ name: "NavButton",
+ columns: ["default", "active"],
+ rows: ["default", "hover", "focus-visible", "external-link"],
+ /**
+ * This component represents only the child (menuitem) of the overall menu.
+ * "aria-required-parent" test is disabled because it requires a child with role="menuitem"
+ * to have a parent with role="menu".
+ *
+ * TODO: remove when contrast issues are fixed in https://github.com/SchwarzIT/onyx/issues/410
+ */
+ disabledAccessibilityRules: ["aria-required-parent", "color-contrast"],
+ component: (column, row) => (
+
+ ),
+ beforeScreenshot: async (component, page, _column, row) => {
+ await expect(component).toContainText("Nav Button");
+ if (row === "hover") await component.hover();
+ if (row === "focus-visible") await page.keyboard.press("Tab");
+ },
+ });
+});
+
+test.describe("Screenshot tests with nested children", () => {
+ const isFlyoutVisible = async (flyout: Locator) => {
+ await expect(flyout).toBeVisible();
+ };
+
+ executeMatrixScreenshotTest({
+ name: "NavButton with nested children",
+ columns: ["inactive", "active"],
+ rows: ["hover", "focus-visible"],
+ /**
+ * This component represents only the child (menuitem) of the overall menu.
+ * "aria-required-parent" test is disabled because it requires a child with role="menuitem"
+ * to have a parent with role="menu".
+ *
+ * "aria-required-children" test is disabled because it's a slot based component
+ *
+ * TODO: remove when contrast issues are fixed in https://github.com/SchwarzIT/onyx/issues/410
+ */
+ disabledAccessibilityRules: [
+ "aria-required-parent",
+ "color-contrast",
+ "aria-required-children",
+ ],
+ component: (column) => (
+
+
+ Nested Item 1
+ Nested Item 2
+ Nested Item 3
+
+
+ ),
+ beforeScreenshot: async (component, page, _column, row) => {
+ const flyout = page.getByLabel("Navigation");
+ await component.hover();
+ if (row === "focus-visible") await page.keyboard.press("Tab");
+ // since the flyout is positioned absolute, we need to set the component size accordingly
+ // so the screenshot contains the whole component
+ await component.evaluate((element) => {
+ element.style.height = "200px";
+ element.style.width = "100px";
+ });
+
+ await isFlyoutVisible(flyout);
+ },
+ });
+});
diff --git a/packages/sit-onyx/src/components/OnyxNavButton/OnyxNavButton.stories.ts b/packages/sit-onyx/src/components/OnyxNavButton/OnyxNavButton.stories.ts
new file mode 100644
index 0000000000..53985987b3
--- /dev/null
+++ b/packages/sit-onyx/src/components/OnyxNavButton/OnyxNavButton.stories.ts
@@ -0,0 +1,90 @@
+import { defineStorybookActionsAndVModels } from "@sit-onyx/storybook-utils";
+import type { Meta, StoryObj } from "@storybook/vue3";
+import { h } from "vue";
+import OnyxNavButton from "./OnyxNavButton.vue";
+import OnyxListItem from "../OnyxListItem/OnyxListItem.vue";
+import OnyxBadge from "../OnyxBadge/OnyxBadge.vue";
+
+/**
+ * The nav button is used internally to build the main navigation bar component and is not intended to be used individually.
+ */
+const meta: Meta = {
+ title: "support/NavButton",
+ ...defineStorybookActionsAndVModels({
+ component: OnyxNavButton,
+ events: ["click"],
+ argTypes: {
+ default: {
+ control: { type: "text" },
+ },
+ },
+ }),
+};
+
+const nestedChildren = [
+ { label: "Nested Item 1", href: "#", active: true },
+ { label: "Nested Item 2", href: "https://onyx.schwarz" },
+ { label: "Nested Item 3", href: "#3" },
+ { label: "Nested Item 4", href: "#4" },
+ { label: "Nested Item 5", href: "#5" },
+];
+
+export default meta;
+type Story = StoryObj;
+
+/**
+ * This example shows a default nav button.
+ */
+export const Default = {
+ args: {
+ label: "Nav Button",
+ default: "Item",
+ },
+} satisfies Story;
+
+/**
+ * This example shows an active nav button.
+ */
+export const Active = {
+ args: {
+ ...Default.args,
+ active: true,
+ },
+} satisfies Story;
+
+/**
+ * This example shows the nav button with nested children.
+ */
+export const WithChildren: Story = {
+ args: {
+ ...Default.args,
+ active: true,
+ children: () => nestedChildren.map(({ label }) => h(OnyxListItem, label)),
+ },
+ decorators: [
+ (story) => ({
+ components: { story },
+ template: `
`,
+ }),
+ ],
+};
+
+/**
+ * This example shows the nav button with additional content (a dot badge in this case).
+ */
+export const WithCustomContent = {
+ args: {
+ ...Default.args,
+ default: ["Custom label", h(OnyxBadge, { dot: true, color: "warning" })],
+ },
+} satisfies Story;
+
+/**
+ * This example shows the nav item with external link.
+ */
+export const WithExternalLink = {
+ args: {
+ label: "onyx",
+ href: "https://onyx.schwarz/",
+ },
+} satisfies Story;
diff --git a/packages/sit-onyx/src/components/OnyxNavButton/OnyxNavButton.vue b/packages/sit-onyx/src/components/OnyxNavButton/OnyxNavButton.vue
new file mode 100644
index 0000000000..0c05b98f5f
--- /dev/null
+++ b/packages/sit-onyx/src/components/OnyxNavButton/OnyxNavButton.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/sit-onyx/src/components/OnyxNavButton/types.ts b/packages/sit-onyx/src/components/OnyxNavButton/types.ts
new file mode 100644
index 0000000000..acbe8369a0
--- /dev/null
+++ b/packages/sit-onyx/src/components/OnyxNavButton/types.ts
@@ -0,0 +1,21 @@
+export type OnyxNavButtonProps = {
+ /**
+ * Label to show inside the Nav item.
+ */
+ label: string;
+ /**
+ * The href of the nav item.
+ */
+ href?: string;
+ /**
+ * Whether the nav item is currently active.
+ * If any nested option is active, the parent nav item will also be marked as active.
+ */
+ active?: boolean;
+ /**
+ * Whether to show the external link icon.
+ * If set to `auto`, it will be shown when the `href` leads to another website
+ * (starting with "http://" or "https://") and will be hidden otherwise.
+ */
+ withExternalIcon?: boolean | "auto";
+};
diff --git a/packages/sit-onyx/src/components/OnyxNavItem/OnyxNavItem.stories.ts b/packages/sit-onyx/src/components/OnyxNavItem/OnyxNavItem.stories.ts
index a387ce3f52..0de0c115d3 100644
--- a/packages/sit-onyx/src/components/OnyxNavItem/OnyxNavItem.stories.ts
+++ b/packages/sit-onyx/src/components/OnyxNavItem/OnyxNavItem.stories.ts
@@ -46,7 +46,7 @@ export const Active = {
/**
* This example shows the nav item with nested options.
*/
-export const WithOptions = {
+export const WithOptions: Story = {
args: {
...Default.args,
options: [
@@ -57,7 +57,13 @@ export const WithOptions = {
{ label: "Nested Item 5", href: "#5" },
],
},
-} satisfies Story;
+ decorators: [
+ (story) => ({
+ components: { story },
+ template: `
`,
+ }),
+ ],
+};
/**
* This example shows the nav item with additional content (a dot badge in this case).
diff --git a/packages/sit-onyx/src/components/OnyxNavItem/OnyxNavItem.vue b/packages/sit-onyx/src/components/OnyxNavItem/OnyxNavItem.vue
index 9580a16d2e..c9667305ff 100644
--- a/packages/sit-onyx/src/components/OnyxNavItem/OnyxNavItem.vue
+++ b/packages/sit-onyx/src/components/OnyxNavItem/OnyxNavItem.vue
@@ -1,3 +1,10 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ props.username }}
+
+
+ {{ props.description }}
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/sit-onyx/src/components/OnyxUserMenu/future/readme.md b/packages/sit-onyx/src/components/OnyxUserMenu/future/readme.md
new file mode 100644
index 0000000000..2b42bbcbae
--- /dev/null
+++ b/packages/sit-onyx/src/components/OnyxUserMenu/future/readme.md
@@ -0,0 +1,3 @@
+# OnyxUserMenu
+
+This is the new (future) version of OnyxUserMenu component. The strucuture of the component is optimized and it will replace the current OnyxUserMenu in the future.
diff --git a/packages/sit-onyx/src/index.ts b/packages/sit-onyx/src/index.ts
index eceaac4a1e..7c9191a243 100644
--- a/packages/sit-onyx/src/index.ts
+++ b/packages/sit-onyx/src/index.ts
@@ -64,6 +64,9 @@ export * from "./components/OnyxNavAppArea/types";
export { default as OnyxNavBar } from "./components/OnyxNavBar/OnyxNavBar.vue";
export * from "./components/OnyxNavBar/types";
+export { default as OnyxNavButton } from "./components/OnyxNavButton/OnyxNavButton.vue";
+export * from "./components/OnyxNavButton/types";
+
export { default as OnyxNavItem } from "./components/OnyxNavItem/OnyxNavItem.vue";
export * from "./components/OnyxNavItem/types";