From a8351ca4f6262c002af4bea9ae7150af9cef30d1 Mon Sep 17 00:00:00 2001 From: martascorreia Date: Tue, 2 Jun 2026 18:09:37 +0100 Subject: [PATCH 1/8] feat: icon placed vertically and horizontally --- .../navigation-item/navigation-item.ts | 22 +++++++++++++++++-- .../components/navigation-item.stories.ts | 17 ++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/navigation-item/navigation-item.ts b/packages/components/src/components/navigation-item/navigation-item.ts index caec64efb9..8043c1e83e 100644 --- a/packages/components/src/components/navigation-item/navigation-item.ts +++ b/packages/components/src/components/navigation-item/navigation-item.ts @@ -254,8 +254,22 @@ export default class SdNavigationItem extends SolidElement { >` : '' } - - + + ${ this.chevron || (slots['children'] && this.vertical && !this.separated) @@ -352,6 +366,10 @@ export default class SdNavigationItem extends SolidElement { @apply block; } + ::slotted(sd-icon) { + @apply w-6 h-6; + } + /* TODO clean sd-navigation-item--current-color-text and delete this class from line 210 (breaking change) */ .sd-navigation-item--current-color-text { color: rgb(var(--sd-navigation-item--current-color-text, var(--sd-navigation-item-color-text))); diff --git a/packages/docs/src/stories/components/navigation-item.stories.ts b/packages/docs/src/stories/components/navigation-item.stories.ts index 724381d9f8..7920886ea7 100644 --- a/packages/docs/src/stories/components/navigation-item.stories.ts +++ b/packages/docs/src/stories/components/navigation-item.stories.ts @@ -53,6 +53,23 @@ export const Orientation = { Vertical Navigation` }; +/** + * TO DO + */ + +export const Icon = { + render: () => html` + + + Navigation + + + + Navigation + + ` +}; + /** * - Use the `href`attribute to change the navigation item to a link. Allows to set the URL to navigate to. * - Use the `target` attribute to specify where to open the link. Can assume the values `_blank`, `_parent`, `_self`, or `_top`. From ce942ce040974f5bf4ea0797bb2a39f40fe194e0 Mon Sep 17 00:00:00 2001 From: martascorreia Date: Wed, 3 Jun 2026 15:58:05 +0100 Subject: [PATCH 2/8] feat: added stack attribute to navigation item --- .../navigation-item/navigation-item.ts | 50 +++++++++++++++---- .../stories/components/navigation-item.mdx | 1 + .../components/navigation-item.stories.ts | 42 +++++++++------- .../navigation-item.test.stories.ts | 45 +++++++++++++++++ 4 files changed, 110 insertions(+), 28 deletions(-) diff --git a/packages/components/src/components/navigation-item/navigation-item.ts b/packages/components/src/components/navigation-item/navigation-item.ts index 8043c1e83e..94ecebfd52 100644 --- a/packages/components/src/components/navigation-item/navigation-item.ts +++ b/packages/components/src/components/navigation-item/navigation-item.ts @@ -71,6 +71,9 @@ export default class SdNavigationItem extends SolidElement { /** Disables the navigation item. */ @property({ type: Boolean, reflect: true }) disabled = false; + /** Stacks the navigation-item in a vertical layout. Only used if `vertical` is false. */ + @property({ type: Boolean, reflect: true }) stacked = false; + /** Appends a chevron to the right side of a navigation item. Only used if `vertical` is true. */ @property({ type: Boolean, reflect: true }) chevron = false; @@ -122,6 +125,10 @@ export default class SdNavigationItem extends SolidElement { ); } + private get isStackedHorizontal(): boolean { + return !this.vertical && this.stacked; + } + private handleClickButton(event: MouseEvent) { if (this.disabled) { event.preventDefault(); @@ -197,7 +204,7 @@ export default class SdNavigationItem extends SolidElement { children: this.hasSlotController.test('children') }; - const horizontalPadding = this.vertical ? 'py-3' : 'py-2'; + const horizontalPadding = this.vertical ? 'py-3' : this.isStackedHorizontal ? 'py-1' : 'py-2'; /* eslint-disable lit/no-invalid-html */ /* eslint-disable lit/binding-positions */ @@ -206,12 +213,19 @@ export default class SdNavigationItem extends SolidElement { part="base" class=${cx( 'flex items-center cursor-pointer relative focus-visible:focus-outline group hover:bg-neutral-200 transition-colors duration-fast ease-in-out min-h-[48px] navigable-border-radius', - { md: 'navigable-font-size', lg: 'text-lg', sm: 'text-[14px]' }[this.size], + this.isStackedHorizontal + ? 'text-xs leading-4.5' + : { md: 'navigable-font-size', lg: 'text-lg', sm: 'text-[14px]' }[this.size], this.disabled ? 'text-neutral-500 pointer-events-none' : 'sd-navigation-item-color-text', - this.current ? 'font-bold sd-navigation-item--current-color-text' : 'choice-control-font-weight', + this.current && this.isStackedHorizontal + ? 'font-bold sd-navigation-item--current-color-text' + : 'choice-control-font-weight', !isAccordion && 'w-full', this.divider && this.vertical && 'mt-0.25', - !this.vertical && 'inline-flex items-center', + !this.vertical && + (this.isStackedHorizontal + ? 'inline-flex flex-col items-center justify-center text-center min-w-[96px]' + : 'inline-flex items-center'), !this.separated && 'hover:bg-neutral-200 group transition-colors duration-fast ease-in-out min-h-[48px]', isIconOnly ? 'justify-center aspect-square p-3' : 'px-4' )} @@ -233,15 +247,25 @@ export default class SdNavigationItem extends SolidElement { 'absolute bg-accent left-0 pointer-events-none navigable__current-indicator-border-radius', this.vertical ? 'navigable__current-indicator-width h-[calc(100%-16px)] top-2 group-hover:h-full group-hover:top-0' - : 'navigable__current-indicator-height w-[calc(100%-16px)] bottom-0 left-2 group-hover:w-full group-hover:left-0 transition-all', + : cx( + 'bottom-0 group-hover:w-full group-hover:left-0 transition-all', + this.isStackedHorizontal + ? 'h-[2px] w-16 left-4' + : 'navigable__current-indicator-height w-[calc(100%-16px)] left-2' + ), this.disabled && 'bg-neutral-500' )}> -
+
` : '' } - Vertical Navigation` }; -/** - * TO DO - */ - -export const Icon = { - render: () => html` - - - Navigation - - - - Navigation - - ` -}; - /** * - Use the `href`attribute to change the navigation item to a link. Allows to set the URL to navigate to. * - Use the `target` attribute to specify where to open the link. Can assume the values `_blank`, `_parent`, `_self`, or `_top`. @@ -101,6 +84,31 @@ export const Disabled = { render: () => html` Disabled Navigation ` }; +/** + * Use the ”stacked” attribute to create a stacked layout of the navigation item with icon. + */ + +export const Stacked = { + render: () => html` + + + Navigation + + + + Navigation + + + + Navigation + + + + Navigation + + ` +}; + /** * Use the `divider` attribute to add a divider above the navigation item. * diff --git a/packages/docs/src/stories/components/navigation-item.test.stories.ts b/packages/docs/src/stories/components/navigation-item.test.stories.ts index e945de363f..346ba8f234 100644 --- a/packages/docs/src/stories/components/navigation-item.test.stories.ts +++ b/packages/docs/src/stories/components/navigation-item.test.stories.ts @@ -147,6 +147,42 @@ export const Disabled = { } }; +export const Stacked = { + name: 'Stacked', + render: (args: any) => { + return html` + ${generateTemplate({ + axis: { + x: { type: 'attribute', name: 'current', values: [false, true] }, + y: [{ type: 'attribute', name: 'stacked', values: [false, true] }] + }, + constants: [ + { + type: 'slot', + name: 'default', + value: 'Navigation' + } + ], + args + })} + ${generateTemplate({ + axis: { + x: { type: 'attribute', name: 'vertical', values: [false, true] }, + y: [{ type: 'attribute', name: 'stacked', values: [false, true] }] + }, + constants: [ + { + type: 'slot', + name: 'default', + value: 'Navigation' + } + ], + args + })} + `; + } +}; + export const VerticalAndCurrent = { name: 'Vertical × Current', render: (args: any) => { @@ -156,6 +192,14 @@ export const VerticalAndCurrent = { x: { type: 'attribute', name: 'vertical' }, y: { type: 'attribute', name: 'current' } }, + constants: [ + { type: 'attribute', name: 'stacked', value: true }, + { + type: 'slot', + name: 'default', + value: 'Navigation' + } + ], args })} `; @@ -423,6 +467,7 @@ export const Combination = generateScreenshotStory([ Current, Variants, Disabled, + Stacked, Parts, Chevron, IndentedRelaxed, From eefda37d8736f4defdeda2f45348c79b5c59f9fe Mon Sep 17 00:00:00 2001 From: martascorreia Date: Mon, 8 Jun 2026 15:54:41 +0100 Subject: [PATCH 3/8] feat: pill hover background + more style ajustments --- .../navigation-item/navigation-item.ts | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/packages/components/src/components/navigation-item/navigation-item.ts b/packages/components/src/components/navigation-item/navigation-item.ts index 94ecebfd52..90d2ebf51e 100644 --- a/packages/components/src/components/navigation-item/navigation-item.ts +++ b/packages/components/src/components/navigation-item/navigation-item.ts @@ -204,7 +204,7 @@ export default class SdNavigationItem extends SolidElement { children: this.hasSlotController.test('children') }; - const horizontalPadding = this.vertical ? 'py-3' : this.isStackedHorizontal ? 'py-1' : 'py-2'; + const horizontalPadding = this.vertical ? 'py-3' : this.isStackedHorizontal ? 'pt-1 pb-1.5' : 'py-2'; /* eslint-disable lit/no-invalid-html */ /* eslint-disable lit/binding-positions */ @@ -217,17 +217,17 @@ export default class SdNavigationItem extends SolidElement { ? 'text-xs leading-4.5' : { md: 'navigable-font-size', lg: 'text-lg', sm: 'text-[14px]' }[this.size], this.disabled ? 'text-neutral-500 pointer-events-none' : 'sd-navigation-item-color-text', - this.current && this.isStackedHorizontal - ? 'font-bold sd-navigation-item--current-color-text' - : 'choice-control-font-weight', + this.current && 'sd-navigation-item--current-color-text', + this.current && !this.isStackedHorizontal && 'font-bold', + !this.current && !this.isStackedHorizontal && 'choice-control-font-weight', !isAccordion && 'w-full', this.divider && this.vertical && 'mt-0.25', !this.vertical && (this.isStackedHorizontal - ? 'inline-flex flex-col items-center justify-center text-center min-w-[96px]' + ? 'inline-flex flex-col items-center justify-center text-center min-w-[125px] rounded-full' : 'inline-flex items-center'), !this.separated && 'hover:bg-neutral-200 group transition-colors duration-fast ease-in-out min-h-[48px]', - isIconOnly ? 'justify-center aspect-square p-3' : 'px-4' + isIconOnly ? 'justify-center aspect-square p-3' : this.isStackedHorizontal ? 'px-8' : 'px-4' )} aria-current=${ifDefined(this.current ? 'page' : undefined)} aria-disabled=${this.disabled} @@ -244,15 +244,12 @@ export default class SdNavigationItem extends SolidElement {
Date: Mon, 8 Jun 2026 15:59:35 +0100 Subject: [PATCH 4/8] chore: changeset --- .changeset/empty-bikes-pay.md | 5 +++++ .changeset/rich-cases-sleep.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/empty-bikes-pay.md create mode 100644 .changeset/rich-cases-sleep.md diff --git a/.changeset/empty-bikes-pay.md b/.changeset/empty-bikes-pay.md new file mode 100644 index 0000000000..0e2c0e6bc1 --- /dev/null +++ b/.changeset/empty-bikes-pay.md @@ -0,0 +1,5 @@ +--- +'@solid-design-system/components': minor +--- + +Added a new attribute `stacked` to the `sd-navigation-item` component that enables a new vertical stacked variant to the horizontal layout. \ No newline at end of file diff --git a/.changeset/rich-cases-sleep.md b/.changeset/rich-cases-sleep.md new file mode 100644 index 0000000000..58c947e0c8 --- /dev/null +++ b/.changeset/rich-cases-sleep.md @@ -0,0 +1,5 @@ +--- +'@solid-design-system/docs': minor +--- + +Added documentation for the new `stacked` attribute for the `sd-navigation-item` component. \ No newline at end of file From 34f4966933b07e8d181343c83164108101977acb Mon Sep 17 00:00:00 2001 From: martascorreia Date: Mon, 8 Jun 2026 16:04:05 +0100 Subject: [PATCH 5/8] fix: removing unecessary screenshot tests --- .../stories/components/navigation-item.test.stories.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/docs/src/stories/components/navigation-item.test.stories.ts b/packages/docs/src/stories/components/navigation-item.test.stories.ts index 346ba8f234..1d4e2f69c4 100644 --- a/packages/docs/src/stories/components/navigation-item.test.stories.ts +++ b/packages/docs/src/stories/components/navigation-item.test.stories.ts @@ -192,14 +192,6 @@ export const VerticalAndCurrent = { x: { type: 'attribute', name: 'vertical' }, y: { type: 'attribute', name: 'current' } }, - constants: [ - { type: 'attribute', name: 'stacked', value: true }, - { - type: 'slot', - name: 'default', - value: 'Navigation' - } - ], args })} `; From 32b439b20d3e1f3c2731836e2ca1f8da22b85ea9 Mon Sep 17 00:00:00 2001 From: martascorreia Date: Thu, 11 Jun 2026 09:26:42 +0100 Subject: [PATCH 6/8] fix: removing extra use cases --- .../stories/components/navigation-item.stories.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/docs/src/stories/components/navigation-item.stories.ts b/packages/docs/src/stories/components/navigation-item.stories.ts index 3550905e73..01d5a571ec 100644 --- a/packages/docs/src/stories/components/navigation-item.stories.ts +++ b/packages/docs/src/stories/components/navigation-item.stories.ts @@ -94,18 +94,6 @@ export const Stacked = { Navigation - - - Navigation - - - - Navigation - - - - Navigation - ` }; From 58c409aa3c203685aa58516dd903ed04fec58fdc Mon Sep 17 00:00:00 2001 From: martascorreia Date: Thu, 11 Jun 2026 11:29:57 +0100 Subject: [PATCH 7/8] fix: current indicator adapting to text width --- .../src/components/navigation-item/navigation-item.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/navigation-item/navigation-item.ts b/packages/components/src/components/navigation-item/navigation-item.ts index 90d2ebf51e..b8b78c794b 100644 --- a/packages/components/src/components/navigation-item/navigation-item.ts +++ b/packages/components/src/components/navigation-item/navigation-item.ts @@ -224,7 +224,7 @@ export default class SdNavigationItem extends SolidElement { this.divider && this.vertical && 'mt-0.25', !this.vertical && (this.isStackedHorizontal - ? 'inline-flex flex-col items-center justify-center text-center min-w-[125px] rounded-full' + ? 'inline-flex flex-col items-center justify-center text-center rounded-full wrap' : 'inline-flex items-center'), !this.separated && 'hover:bg-neutral-200 group transition-colors duration-fast ease-in-out min-h-[48px]', isIconOnly ? 'justify-center aspect-square p-3' : this.isStackedHorizontal ? 'px-8' : 'px-4' @@ -248,7 +248,7 @@ export default class SdNavigationItem extends SolidElement { this.vertical ? 'navigable__current-indicator-width h-[calc(100%-16px)] top-2 left-0 group-hover:h-full group-hover:top-0' : this.isStackedHorizontal - ? 'h-[2px] w-16 left-1/2 -translate-x-1/2 bottom-0' + ? 'h-[2px] left-6 right-6 bottom-0' : 'navigable__current-indicator-height w-[calc(100%-16px)] left-2 bottom-0 group-hover:w-full group-hover:left-0 transition-all', this.disabled && 'bg-neutral-500' )}>
From 5c2cde5895154e55153fdd13300b0f43bc5fe327 Mon Sep 17 00:00:00 2001 From: martascorreia Date: Thu, 11 Jun 2026 13:50:32 +0100 Subject: [PATCH 8/8] fix: better screenshot tests + fixing some styling --- .../navigation-item/navigation-item.ts | 4 +- .../navigation-item.test.stories.ts | 163 +++++++++++------- 2 files changed, 98 insertions(+), 69 deletions(-) diff --git a/packages/components/src/components/navigation-item/navigation-item.ts b/packages/components/src/components/navigation-item/navigation-item.ts index b8b78c794b..1ea7ba8a4c 100644 --- a/packages/components/src/components/navigation-item/navigation-item.ts +++ b/packages/components/src/components/navigation-item/navigation-item.ts @@ -204,7 +204,7 @@ export default class SdNavigationItem extends SolidElement { children: this.hasSlotController.test('children') }; - const horizontalPadding = this.vertical ? 'py-3' : this.isStackedHorizontal ? 'pt-1 pb-1.5' : 'py-2'; + const horizontalPadding = this.vertical ? 'py-3' : this.isStackedHorizontal ? 'pt-1 pb-1' : 'py-2'; /* eslint-disable lit/no-invalid-html */ /* eslint-disable lit/binding-positions */ @@ -217,7 +217,7 @@ export default class SdNavigationItem extends SolidElement { ? 'text-xs leading-4.5' : { md: 'navigable-font-size', lg: 'text-lg', sm: 'text-[14px]' }[this.size], this.disabled ? 'text-neutral-500 pointer-events-none' : 'sd-navigation-item-color-text', - this.current && 'sd-navigation-item--current-color-text', + this.current && !this.disabled && 'sd-navigation-item--current-color-text', this.current && !this.isStackedHorizontal && 'font-bold', !this.current && !this.isStackedHorizontal && 'choice-control-font-weight', !isAccordion && 'w-full', diff --git a/packages/docs/src/stories/components/navigation-item.test.stories.ts b/packages/docs/src/stories/components/navigation-item.test.stories.ts index 1d4e2f69c4..12759672ea 100644 --- a/packages/docs/src/stories/components/navigation-item.test.stories.ts +++ b/packages/docs/src/stories/components/navigation-item.test.stories.ts @@ -52,20 +52,33 @@ export const Default = { } }; -export const Current = { - name: 'Variant x Current', - render: (args: any) => - generateTemplate({ - args, - axis: { - x: { type: 'attribute', name: 'vertical' }, - y: { type: 'attribute', name: 'current' } - } - }) +export const OrientationAndCurrent = { + name: 'Orientation x Current', + render: (args: any) => { + return html` + ${generateTemplate({ + args, + axis: { + x: { type: 'attribute', name: 'vertical' }, + y: { type: 'attribute', name: 'current' } + } + })} + ${generateTemplate({ + axis: { + y: { type: 'attribute', name: 'current' } + }, + constants: [ + { type: 'attribute', name: 'stacked', value: true }, + { type: 'slot', name: 'default', value: 'Navigation' } + ], + args + })} + `; + } }; -export const Variants = { - name: 'Variant × Size', +export const OrientationAndSize = { + name: 'Orientation × Size', render: (args: any) => { return html` ${generateTemplate({ @@ -110,6 +123,31 @@ export const Variants = { } }; +export const OrientationAndLink = { + name: 'Orientation × Link', + render: (args: any) => { + return html` + ${generateTemplate({ + axis: { + x: { type: 'attribute', name: 'href', values: ['', '#'] }, + y: { type: 'attribute', name: 'vertical' } + }, + args + })} + ${generateTemplate({ + axis: { + y: { type: 'attribute', name: 'href', values: ['', '#'] } + }, + constants: [ + { type: 'attribute', name: 'stacked', value: true }, + { type: 'slot', name: 'default', value: 'Navigation' } + ], + args + })} + `; + } +}; + export const Disabled = { name: 'Disabled', render: (args: any) => { @@ -143,39 +181,17 @@ export const Disabled = { ], args })} - `; - } -}; - -export const Stacked = { - name: 'Stacked', - render: (args: any) => { - return html` ${generateTemplate({ axis: { - x: { type: 'attribute', name: 'current', values: [false, true] }, - y: [{ type: 'attribute', name: 'stacked', values: [false, true] }] + y: { type: 'attribute', name: 'current' } }, - constants: [ - { - type: 'slot', - name: 'default', - value: 'Navigation' - } - ], - args - })} - ${generateTemplate({ - axis: { - x: { type: 'attribute', name: 'vertical', values: [false, true] }, - y: [{ type: 'attribute', name: 'stacked', values: [false, true] }] + options: { + title: 'Stacked (Horizontal)' }, constants: [ - { - type: 'slot', - name: 'default', - value: 'Navigation' - } + { type: 'attribute', name: 'disabled', value: true }, + { type: 'attribute', name: 'stacked', value: true }, + { type: 'slot', name: 'default', value: 'Navigation' } ], args })} @@ -183,32 +199,46 @@ export const Stacked = { } }; -export const VerticalAndCurrent = { - name: 'Vertical × Current', +export const Stacked = { + name: 'Stacked', render: (args: any) => { - return html` - ${generateTemplate({ - axis: { - x: { type: 'attribute', name: 'vertical' }, - y: { type: 'attribute', name: 'current' } - }, - args - })} - `; - } -}; + const cases = [ + { + title: 'Default', + slot: 'Navigation' + }, + { + title: 'Short Navigation', + slot: 'Nav' + }, + { + title: 'Large Navigation', + slot: 'Large Navigation' + } + ]; -export const VerticalAndLink = { - name: 'Vertical × Link', - render: (args: any) => { return html` - ${generateTemplate({ - axis: { - x: { type: 'attribute', name: 'href', values: ['', '#'] }, - y: { type: 'attribute', name: 'vertical' } - }, - args - })} + ${cases.map( + c => html` + ${generateTemplate({ + axis: { + y: { type: 'attribute', name: 'current' } + }, + options: { + title: c.title + }, + constants: [ + { type: 'attribute', name: 'stacked', value: true }, + { + type: 'slot', + name: 'default', + value: c.slot + } + ], + args + })} + ` + )} `; } }; @@ -456,15 +486,14 @@ export const Mouseless = { export const Combination = generateScreenshotStory([ Default, - Current, - Variants, + OrientationAndCurrent, + OrientationAndSize, + OrientationAndLink, Disabled, Stacked, Parts, Chevron, IndentedRelaxed, - VerticalAndCurrent, - VerticalAndLink, Separated, Slots, Mouseless