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

193 lines
3.8 KiB
Vue
Raw Normal View History

fix(editor): Fix i18n issues (#3072) * :bug: Fix `defaultLocale` watcher * :zap: Improve error handling for headers * :pencil2: Improve naming * :bug: Fix hiring banner check * :zap: Flatten base text keys * :zap: Fix miscorrected key * :zap: Implement pluralization * :pencil2: Update docs * :truck: Move headers fetching to `App.vue` * fix hiring banner * :zap: Fix missing import * :pencil2: Alphabetize translations * :zap: Switch to async check * feat(editor): Refactor Output Panel + fix i18n issues (#3097) * update main panel * finish up tabs * fix docs link * add icon * update node settings * clean up settings * add rename modal * fix component styles * fix spacing * truncate name * remove mixin * fix spacing * fix spacing * hide docs url * fix bug * fix renaming * refactor tabs out * refactor execute button * refactor header * add more views * fix error view * fix workflow rename bug * rename component * fix small screen bug * move items, fix positions * add hover state * show selector on empty state * add empty run state * fix binary view * 1 item * add vjs styles * show empty row for every item * refactor tabs * add branch names * fix spacing * fix up spacing * add run selector * fix positioning * clean up * increase width of selector * fix up spacing * fix copy button * fix branch naming; type issues * fix docs in custom nodes * add type * hide items when run selector is shown * increase selector size * add select prepend * clean up a bit * Add pagination * add stale icon * enable stale data in execution run * Revert "enable stale data in execution run" 8edb68dbffa0aa0d8189117e1a53381cb2c27608 * move metadata to its own state * fix smaller size * add scroll buttons * update tabs on resize * update stale data on rename * remove metadata on delete * hide x * change title colors * binary data classes * remove duplicate css * add colors * delete unused keys * use event bus * update styles of pagination * fix ts issues * fix ts issues * use chevron icons * fix design with download button * add back to canvas button * add trigger warning disabled * show trigger warning tooltip * update button labels for triggers * update node output message * fix add-option bug * add page selector * fix pagination selector bug * fix executions bug * remove hint * add json colors * add colors for json * add color json keys * fix select options bug * update keys * address comments * update name limit * align pencil * update icon size * update radio buttons height * address comments * fix pencil bug * change buttons alignment * fully center * change order of buttons * add no output message in branch * scroll to top * change active state * fix page size * all items * update expression background * update naming * align pencil * update modal background * add schedule group * update schedule nodes messages * use ellpises for last chars * fix spacing * fix tabs issue * fix too far data bug * fix executions bug * fix table wrapping * fix rename bug * add padding * handle unkown errors * add sticky header * ignore empty input, trim node name * nudge lightness of color * center buttons * update pagination * set colors of title * increase table font, fix alignment * fix pencil bug * fix spacing * use date now * address pagination issues * delete unused keys * update keys sort * fix prepend * fix radio button position * Revert "fix radio button position" ae42781786f2e6dcfb00d1be770b19a67f533bdf Co-authored-by: Mutasem <mutdmour@gmail.com> Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com>
2022-04-11 06:12:13 -07:00
<template>
<div :class="$style.container">
<div :class="$style.back" v-if="scrollPosition > 0" @click="scrollLeft">
<n8n-icon icon="chevron-left" size="small" />
</div>
<div :class="$style.next" v-if="canScrollRight" @click="scrollRight">
<n8n-icon icon="chevron-right" size="small" />
</div>
<div ref="tabs" :class="$style.tabs">
<div v-for="option in options" :key="option.value" :class="{ [$style.alignRight]: option.align === 'right' }">
<a
v-if="option.href"
target="_blank"
:href="option.href"
:class="[$style.link, $style.tab]"
@click="handleTabClick"
>
<div>
{{ option.label }}
<span :class="$style.external"><n8n-icon icon="external-link-alt" size="small" /></span>
</div>
</a>
<div
v-else
:class="{ [$style.tab]: true, [$style.activeTab]: value === option.value }"
@click="() => handleTabClick(option.value)"
>
<n8n-icon v-if="option.icon" :icon="option.icon" size="medium" />
<span v-if="option.label">{{ option.label }}</span>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import N8nIcon from '../N8nIcon';
export default Vue.extend({
name: 'N8nTabs',
components: {
N8nIcon,
},
mounted() {
const container = this.$refs.tabs;
if (container) {
container.addEventListener('scroll', (e) => {
const width = container.clientWidth;
const scrollWidth = container.scrollWidth;
this.scrollPosition = e.srcElement.scrollLeft;
this.canScrollRight = scrollWidth - width > this.scrollPosition;
});
this.resizeObserver = new ResizeObserver(() => {
const width = container.clientWidth;
const scrollWidth = container.scrollWidth;
this.canScrollRight = scrollWidth - width > this.scrollPosition;
});
this.resizeObserver.observe(container);
const width = container.clientWidth;
const scrollWidth = container.scrollWidth;
this.canScrollRight = scrollWidth - width > this.scrollPosition;
}
},
destroyed() {
this.resizeObserver.disconnect();
},
data() {
return {
scrollPosition: 0,
canScrollRight: false,
resizeObserver: null,
};
},
props: {
value: {
},
options: {
},
},
methods: {
handleTabClick(tab: string) {
this.$emit('input', tab);
},
scrollLeft() {
this.scroll(-50);
},
scrollRight() {
this.scroll(50);
},
scroll(left: number) {
const container = this.$refs.tabs;
if (container) {
container.scrollBy({ left, top: 0, behavior: 'smooth' });
}
},
},
});
</script>
<style lang="scss" module>
.container {
position: relative;
height: 24px;
min-height: 24px;
width: 100%;
}
.tabs {
color: var(--color-text-base);
font-weight: var(--font-weight-bold);
display: flex;
width: 100%;
position: absolute;
overflow-x: scroll;
/* Hide scrollbar for Chrome, Safari and Opera */
&::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.tab {
display: block;
padding: 0 var(--spacing-s) var(--spacing-2xs) var(--spacing-s);
padding-bottom: var(--spacing-2xs);
font-size: var(--font-size-s);
cursor: pointer;
white-space: nowrap;
&:hover {
color: var(--color-primary);
}
}
.activeTab {
color: var(--color-primary);
border-bottom: var(--color-primary) 2px solid;
}
.alignRight {
margin-left: auto;
}
.link {
cursor: pointer;
color: var(--color-text-base);
&:hover {
color: var(--color-primary);
.external {
display: inline-block;
}
}
}
.external {
display: none;
}
.button {
position: absolute;
background-color: var(--color-background-light);
z-index: 1;
height: 24px;
width: 10px;
display: flex;
align-items: center;
font-weight: var(--font-weight-bold);
}
.back {
composes: tab;
composes: button;
left: 0;
}
.next {
composes: tab;
composes: button;
right: 0;
}
</style>