Skip to content

Commit 58deb85

Browse files
authored
chore(editor): Support new props in TabOptions (#17822)
1 parent b8b8507 commit 58deb85

File tree

3 files changed

+128
-14
lines changed

3 files changed

+128
-14
lines changed

packages/frontend/@n8n/design-system/src/components/N8nTabs/Tabs.stories.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { action } from '@storybook/addon-actions';
22
import type { StoryFn } from '@storybook/vue3';
33

44
import N8nTabs from './Tabs.vue';
5+
import type { TabOptions } from '../../types/tabs';
56

67
export default {
78
title: 'Atoms/Tabs',
@@ -56,3 +57,71 @@ Example.args = {
5657
},
5758
],
5859
};
60+
61+
const options: Array<TabOptions<string>> = [
62+
{
63+
label: 'First',
64+
value: 'first',
65+
},
66+
{
67+
label: 'Second',
68+
value: 'second',
69+
},
70+
{
71+
label: 'External Link',
72+
value: 'external',
73+
href: 'https://github.com/',
74+
},
75+
{
76+
label: 'Danger',
77+
value: 'danger',
78+
variant: 'danger',
79+
icon: 'triangle-alert',
80+
},
81+
{
82+
label: 'Right Icon',
83+
value: 'rightIcon',
84+
icon: 'circle',
85+
iconPosition: 'right',
86+
},
87+
{
88+
value: 'iconOnly',
89+
tooltip: 'Icon only tab',
90+
icon: 'circle',
91+
},
92+
{
93+
label: 'Notification',
94+
value: 'notification',
95+
notification: true,
96+
},
97+
{
98+
label: 'Settings',
99+
value: 'settings',
100+
icon: 'cog',
101+
align: 'right',
102+
},
103+
];
104+
105+
export const TabVariants = Template.bind({});
106+
TabVariants.args = {
107+
options,
108+
};
109+
110+
export const WithSmallSize = Template.bind({});
111+
WithSmallSize.args = {
112+
options,
113+
size: 'small',
114+
};
115+
116+
export const WithModernVariant = Template.bind({});
117+
WithModernVariant.args = {
118+
variant: 'modern',
119+
options,
120+
};
121+
122+
export const WithSmallAndModern = Template.bind({});
123+
WithSmallAndModern.args = {
124+
variant: 'modern',
125+
options,
126+
size: 'small',
127+
};

packages/frontend/@n8n/design-system/src/components/N8nTabs/Tabs.vue

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,43 +92,65 @@ const scrollRight = () => scroll(50);
9292
:key="option.value"
9393
:class="{ [$style.alignRight]: option.align === 'right' }"
9494
>
95-
<N8nTooltip :disabled="!option.tooltip" placement="bottom">
95+
<N8nTooltip :disabled="!option.tooltip" placement="bottom" :show-after="100">
9696
<template #content>
9797
<div v-n8n-html="option.tooltip" @click="handleTooltipClick(option.value, $event)" />
9898
</template>
9999
<a
100100
v-if="option.href"
101101
target="_blank"
102102
:href="option.href"
103-
:class="[$style.link, $style.tab]"
103+
rel="noopener noreferrer"
104+
:class="[$style.link, $style.tab, option.label ? '' : $style.noText]"
104105
@click="() => handleTabClick(option.value)"
105106
>
106107
<div>
107108
{{ option.label }}
108-
<span :class="$style.external">
109-
<N8nIcon icon="external-link" size="small" />
110-
</span>
109+
<N8nIcon
110+
:class="$style.external"
111+
:icon="option.icon ?? 'external-link'"
112+
size="small"
113+
/>
111114
</div>
112115
</a>
113116
<RouterLink
114117
v-else-if="option.to"
115118
:to="option.to"
116-
:class="[$style.tab, { [$style.activeTab]: modelValue === option.value }]"
119+
:class="[
120+
$style.tab,
121+
{ [$style.activeTab]: modelValue === option.value, [$style.noText]: !option.label },
122+
]"
117123
>
118124
<N8nIcon v-if="option.icon" :icon="option.icon" size="medium" />
119125
<span v-if="option.label">{{ option.label }}</span>
120126
</RouterLink>
121127
<div
122128
v-else
123-
:class="{ [$style.tab]: true, [$style.activeTab]: modelValue === option.value }"
129+
:class="{
130+
[$style.tab]: true,
131+
[$style.activeTab]: modelValue === option.value,
132+
[$style.noText]: !option.label,
133+
[$style.dangerTab]: option.variant === 'danger',
134+
}"
124135
:data-test-id="`tab-${option.value}`"
125136
@click="() => handleTabClick(option.value)"
126137
>
127-
<N8nIcon v-if="option.icon" :icon="option.icon" size="small" />
128-
<span v-if="option.label" :class="$style.notificationContainer"
129-
>{{ option.label }}
130-
<div v-if="option.notification" :class="$style.notification"><div></div></div
131-
></span>
138+
<N8nIcon
139+
v-if="option.icon && option.iconPosition !== 'right'"
140+
:icon="option.icon"
141+
:class="$style.icon"
142+
size="small"
143+
/>
144+
<span v-if="option.label" :class="$style.notificationContainer">
145+
{{ option.label }}
146+
<div v-if="option.notification" :class="$style.notification" />
147+
</span>
148+
<N8nIcon
149+
v-if="option.icon && option.iconPosition === 'right'"
150+
:icon="option.icon"
151+
:class="$style.icon"
152+
size="small"
153+
/>
132154
</div>
133155
</N8nTooltip>
134156
</div>
@@ -170,7 +192,9 @@ const scrollRight = () => scroll(50);
170192
171193
.tab {
172194
--active-tab-border-width: 2px;
173-
display: block;
195+
display: flex;
196+
align-items: center;
197+
gap: var(--spacing-4xs);
174198
padding: 0 var(--spacing-s);
175199
padding-bottom: calc(var(--spacing-2xs) + var(--active-tab-border-width));
176200
font-size: var(--font-size-s);
@@ -223,6 +247,23 @@ const scrollRight = () => scroll(50);
223247
.external {
224248
display: inline-block;
225249
margin-left: var(--spacing-5xs);
250+
251+
.noText & {
252+
display: block;
253+
margin-left: 0;
254+
}
255+
}
256+
257+
.noText .icon {
258+
display: block;
259+
}
260+
261+
.dangerTab {
262+
color: var(--color-danger);
263+
264+
&:hover {
265+
color: var(--color-danger);
266+
}
226267
}
227268
228269
.button {
@@ -248,7 +289,9 @@ const scrollRight = () => scroll(50);
248289
align-items: center;
249290
justify-content: center;
250291
251-
div {
292+
&:after {
293+
content: '';
294+
display: block;
252295
height: 0.3em;
253296
width: 0.3em;
254297
background-color: var(--color-primary);

packages/frontend/@n8n/design-system/src/types/tabs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ export interface TabOptions<Value extends string | number> {
66
value: Value;
77
label?: string;
88
icon?: IconName;
9+
iconPosition?: 'left' | 'right';
10+
variant?: 'default' | 'danger';
911
href?: string;
1012
tooltip?: string;
1113
align?: 'left' | 'right';

0 commit comments

Comments
 (0)