mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-12 21:37:32 -08:00
refactor(editor): Unify Callout components (#3798)
* ✨ Implemented a single Callout component * ✔️ Updating test snapshots and fixing lint warnings
This commit is contained in:
parent
0ecbb4a19d
commit
ad8d662976
|
@ -4,14 +4,26 @@
|
|||
<component :is="$options.components.N8nHeading" size="xlarge" align="center">{{ props.heading }}</component>
|
||||
</div>
|
||||
<div :class="$style.description" @click="(e) => listeners.descriptionClick && listeners.descriptionClick(e)">
|
||||
<n8n-text color="text-base"><span v-html="props.description"></span></n8n-text>
|
||||
<component :is="$options.components.N8nText" color="text-base">
|
||||
<span v-html="props.description"></span>
|
||||
</component>
|
||||
</div>
|
||||
<component v-if="props.buttonText" :is="$options.components.N8nButton" :label="props.buttonText" size="large"
|
||||
@click="(e) => listeners.click && listeners.click(e)"
|
||||
/>
|
||||
<component v-if="props.calloutText" :is="$options.components.N8nCallout"
|
||||
:theme="props.calloutTheme" :message="props.calloutText" :icon="props.calloutIcon"
|
||||
/>
|
||||
<component
|
||||
v-if="props.calloutText"
|
||||
:is="$options.components.N8nCallout"
|
||||
:theme="props.calloutTheme"
|
||||
:icon="props.calloutIcon"
|
||||
:class="$style.callout"
|
||||
>
|
||||
<template>
|
||||
<component :is="$options.components.N8nText" color="text-base">
|
||||
<span size="small" v-html="props.calloutText"></span>
|
||||
</component>
|
||||
</template>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -23,6 +35,12 @@ import N8nCallout from '../N8nCallout';
|
|||
|
||||
export default {
|
||||
name: 'n8n-action-box',
|
||||
components: {
|
||||
N8nButton,
|
||||
N8nHeading,
|
||||
N8nText,
|
||||
N8nCallout,
|
||||
},
|
||||
props: {
|
||||
heading: {
|
||||
type: String,
|
||||
|
@ -44,12 +62,6 @@ export default {
|
|||
type: String,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
N8nButton,
|
||||
N8nHeading,
|
||||
N8nText,
|
||||
N8nCallout,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -79,4 +91,10 @@ export default {
|
|||
color: var(--color-text-base);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
}
|
||||
|
||||
.callout {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import N8nCallout from './Callout.vue';
|
||||
import N8nLink from '../N8nLink';
|
||||
import N8nText from '../N8nText';
|
||||
import { StoryFn } from '@storybook/vue';
|
||||
|
||||
|
||||
export default {
|
||||
title: 'Atoms/Callout',
|
||||
component: N8nCallout,
|
||||
|
@ -8,7 +11,7 @@ export default {
|
|||
theme: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['info', 'success', 'warning', 'danger', 'custom'],
|
||||
options: ['info', 'secondary', 'success', 'warning', 'danger', 'custom'],
|
||||
},
|
||||
},
|
||||
message: {
|
||||
|
@ -22,19 +25,84 @@ export default {
|
|||
},
|
||||
},
|
||||
},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'figma',
|
||||
url: 'https://www.figma.com/file/tPpJvbrnHbP8C496cYuwyW/Node-pinning?node-id=15%3A5777',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const template : StoryFn = (args, { argTypes }) => ({
|
||||
props: Object.keys(argTypes),
|
||||
components: {
|
||||
N8nLink,
|
||||
N8nText,
|
||||
N8nCallout,
|
||||
},
|
||||
template: `<n8n-callout v-bind="$props"></n8n-callout>`,
|
||||
template: `
|
||||
<n8n-callout v-bind="$props">
|
||||
${args.default}
|
||||
<template #actions v-if="actions">
|
||||
${args.actions}
|
||||
</template>
|
||||
<template #trailingContent v-if="trailingContent">
|
||||
${args.trailingContent}
|
||||
</template>
|
||||
</n8n-callout>
|
||||
`,
|
||||
});
|
||||
|
||||
export const callout = template.bind({});
|
||||
callout.args = {
|
||||
export const defaultCallout = template.bind({});
|
||||
defaultCallout.args = {
|
||||
theme: 'success',
|
||||
default: `
|
||||
<n8n-text size="small" >
|
||||
This is a default callout.
|
||||
</n8n-text>
|
||||
`,
|
||||
};
|
||||
|
||||
export const customCallout = template.bind({});
|
||||
customCallout.args = {
|
||||
theme: 'custom',
|
||||
icon: 'code-branch',
|
||||
message: 'This is a callout. <a href="https://n8n.io" target="_blank">Read more.</a>',
|
||||
default: `
|
||||
<n8n-text size="small" >
|
||||
This is a custom callout.
|
||||
</n8n-text>
|
||||
`,
|
||||
actions: `
|
||||
<n8n-link size="small">
|
||||
Do something!
|
||||
</n8n-link>
|
||||
`,
|
||||
};
|
||||
|
||||
|
||||
export const secondaryCallout = template.bind({});
|
||||
secondaryCallout.args = {
|
||||
theme: 'secondary',
|
||||
icon: 'thumbtack',
|
||||
default: `
|
||||
<n8n-text size="small">
|
||||
This data is pinned.
|
||||
</n8n-text>
|
||||
`,
|
||||
actions: `
|
||||
<n8n-link theme="secondary" size="small" :bold="true" :underline="true">
|
||||
Unpin
|
||||
</n8n-link>
|
||||
`,
|
||||
trailingContent: `
|
||||
<n8n-link
|
||||
theme="secondary"
|
||||
size="small"
|
||||
:bold="true"
|
||||
:underline="true"
|
||||
to="https://n8n.io"
|
||||
>
|
||||
Learn more
|
||||
</n8n-link>
|
||||
`,
|
||||
};
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
<template>
|
||||
<div :class="classes" role="alert">
|
||||
<div :class="$style.icon">
|
||||
<n8n-icon v-bind="$attrs" :icon="getIcon" size="large"/>
|
||||
</div>
|
||||
<div :class="$style.message" >
|
||||
<n8n-text size="small" v-bind="$attrs"><span v-html="message"></span></n8n-text>
|
||||
|
||||
<div :class="$style['message-section']">
|
||||
<div :class="$style.icon">
|
||||
<n8n-icon
|
||||
:icon="getIcon"
|
||||
:size="theme === 'secondary' ? 'medium' : 'large'"
|
||||
/>
|
||||
</div>
|
||||
<slot />
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
|
||||
<slot name="trailingContent" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -14,37 +21,30 @@ import Vue from 'vue';
|
|||
import N8nIcon from '../N8nIcon';
|
||||
import N8nText from '../N8nText';
|
||||
|
||||
const CALLOUT_DEFAULT_ICONS = {
|
||||
info: 'info-circle',
|
||||
success: 'check-circle',
|
||||
warning: 'exclamation-triangle',
|
||||
danger: 'times-circle',
|
||||
};
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'n8n-callout',
|
||||
components: {
|
||||
N8nIcon,
|
||||
N8nText
|
||||
N8nText,
|
||||
},
|
||||
props: {
|
||||
theme: {
|
||||
type: String,
|
||||
required: true,
|
||||
validator: (value: string): boolean =>
|
||||
['info', 'success', 'warning', 'danger', 'custom'].includes(value),
|
||||
},
|
||||
message: {
|
||||
type: String,
|
||||
required: true
|
||||
['info', 'success', 'secondary', 'warning', 'danger', 'custom'].includes(value),
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'info-circle'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultIcons: {
|
||||
'info': 'info-circle',
|
||||
'success': 'check-circle',
|
||||
'warning': 'exclamation-triangle',
|
||||
'danger': 'times-circle',
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
classes(): string[] {
|
||||
|
@ -54,50 +54,65 @@ export default Vue.extend({
|
|||
];
|
||||
},
|
||||
getIcon(): string {
|
||||
if(this.theme === 'custom') {
|
||||
return this.icon;
|
||||
if (Object.keys(CALLOUT_DEFAULT_ICONS).includes(this.theme)) {
|
||||
return CALLOUT_DEFAULT_ICONS[this.theme];
|
||||
}
|
||||
return this.defaultIcons[this.theme];
|
||||
|
||||
return this.icon;
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.callout {
|
||||
display: flex;
|
||||
font-size: var(--font-size-2xs);
|
||||
padding: var(--spacing-xs);
|
||||
border: var(--border-width-base) var(--border-style-base);
|
||||
border-radius: var(--border-radius-base);
|
||||
align-items: center;
|
||||
}
|
||||
.callout {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: var(--font-size-2xs);
|
||||
padding: var(--spacing-xs);
|
||||
border: var(--border-width-base) var(--border-style-base);
|
||||
border-radius: var(--border-radius-base);
|
||||
align-items: center;
|
||||
line-height: var(--font-line-height-loose);
|
||||
}
|
||||
|
||||
.info, .custom {
|
||||
border-color: var(--color-foreground-base);
|
||||
background-color: var(--color-background-light);
|
||||
color: var(--color-info);
|
||||
}
|
||||
.message-section {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.warning {
|
||||
border-color: var(--color-warning-tint-1);
|
||||
background-color: var(--color-warning-tint-2);
|
||||
color: var(--color-warning);
|
||||
}
|
||||
.info, .custom {
|
||||
border-color: var(--color-foreground-base);
|
||||
background-color: var(--color-background-light);
|
||||
color: var(--color-info);
|
||||
}
|
||||
|
||||
.success {
|
||||
border-color: var(--color-success-tint-1);
|
||||
background-color: var(--color-success-tint-2);
|
||||
color: var(--color-success);
|
||||
}
|
||||
.warning {
|
||||
border-color: var(--color-warning-tint-1);
|
||||
background-color: var(--color-warning-tint-2);
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.danger {
|
||||
border-color: var(--color-danger-tint-1);
|
||||
background-color: var(--color-danger-tint-2);
|
||||
color: var(--color-danger);
|
||||
}
|
||||
.success {
|
||||
border-color: var(--color-success-tint-1);
|
||||
background-color: var(--color-success-tint-2);
|
||||
color: var(--color-success);
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: var(--spacing-xs);
|
||||
}
|
||||
.danger {
|
||||
border-color: var(--color-danger-tint-1);
|
||||
background-color: var(--color-danger-tint-2);
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.secondary {
|
||||
font-size: var(--font-size-2xs);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--color-secondary);
|
||||
background-color: var(--color-secondary-tint-2);
|
||||
border-color: var(--color-secondary-tint-1);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
import N8nCallout from './Callout.vue';
|
||||
import { StoryFn } from '@storybook/vue';
|
||||
import N8nLink from '../N8nLink';
|
||||
import N8nText from '../N8nText';
|
||||
|
||||
export default {
|
||||
title: 'Atoms/Callout',
|
||||
component: N8nCallout,
|
||||
argTypes: {
|
||||
theme: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['info', 'secondary', 'success', 'warning', 'danger', 'custom'],
|
||||
},
|
||||
},
|
||||
message: {
|
||||
control: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
icon: {
|
||||
control: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'figma',
|
||||
url: 'https://www.figma.com/file/tPpJvbrnHbP8C496cYuwyW/Node-pinning?node-id=15%3A5777',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const template: StoryFn = (args, { argTypes }) => ({
|
||||
props: Object.keys(argTypes),
|
||||
components: {
|
||||
N8nLink,
|
||||
N8nText,
|
||||
N8nCallout,
|
||||
},
|
||||
template: `
|
||||
<n8n-callout v-bind="$props">
|
||||
${args.default}
|
||||
<template #actions v-if="actions">
|
||||
${args.actions}
|
||||
</template>
|
||||
<template #trailingContent v-if="trailingContent">
|
||||
${args.trailingContent}
|
||||
</template>
|
||||
</n8n-callout>
|
||||
`,
|
||||
});
|
||||
|
||||
export const customCallout = template.bind({});
|
||||
customCallout.args = {
|
||||
theme: 'custom',
|
||||
icon: 'code-branch',
|
||||
default: `
|
||||
<n8n-text
|
||||
size="small"
|
||||
>
|
||||
This is a callout.
|
||||
</n8n-text>
|
||||
`,
|
||||
actions: `
|
||||
<n8n-link
|
||||
size="small"
|
||||
>
|
||||
Do something!
|
||||
</n8n-link>
|
||||
`,
|
||||
};
|
||||
|
||||
export const secondaryCallout = template.bind({});
|
||||
secondaryCallout.args = {
|
||||
theme: 'secondary',
|
||||
icon: 'thumbtack',
|
||||
default: `
|
||||
<n8n-text
|
||||
size="small"
|
||||
:bold="true"
|
||||
>
|
||||
This data is pinned.
|
||||
</n8n-text>
|
||||
`,
|
||||
actions: `
|
||||
<n8n-link
|
||||
theme="secondary"
|
||||
size="small"
|
||||
:bold="true"
|
||||
>
|
||||
Unpin
|
||||
</n8n-link>
|
||||
`,
|
||||
trailingContent: `
|
||||
<n8n-link
|
||||
theme="secondary"
|
||||
size="small"
|
||||
:bold="true"
|
||||
:underline="true"
|
||||
to="https://n8n.io"
|
||||
>
|
||||
Learn more
|
||||
</n8n-link>
|
||||
`,
|
||||
};
|
|
@ -2,106 +2,94 @@ import { render } from '@testing-library/vue';
|
|||
import N8nCallout from '../Callout.vue';
|
||||
|
||||
describe('components', () => {
|
||||
describe('N8NCallout', () => {
|
||||
describe('props', () => {
|
||||
it('should render info theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'info',
|
||||
message: 'This is an info callout.',
|
||||
},
|
||||
stubs: [
|
||||
'n8n-icon',
|
||||
'n8n-text',
|
||||
],
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
it('should render success theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'success',
|
||||
message: 'This is an success callout.',
|
||||
},
|
||||
stubs: [
|
||||
'n8n-icon',
|
||||
'n8n-text',
|
||||
],
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
it('should render warning theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'warning',
|
||||
message: 'This is an warning callout.',
|
||||
},
|
||||
stubs: [
|
||||
'n8n-icon',
|
||||
'n8n-text',
|
||||
],
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
it('should render danger theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'danger',
|
||||
message: 'This is an danger callout.',
|
||||
},
|
||||
stubs: [
|
||||
'n8n-icon',
|
||||
'n8n-text',
|
||||
],
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
it('should render custom theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'custom',
|
||||
message: 'This is an custom callout.',
|
||||
icon: 'code',
|
||||
},
|
||||
stubs: [
|
||||
'n8n-icon',
|
||||
'n8n-text',
|
||||
],
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
describe('N8nCallout', () => {
|
||||
it('should render info theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'info',
|
||||
},
|
||||
stubs: [ 'n8n-icon', 'n8n-text' ],
|
||||
slots: {
|
||||
default: '<n8n-text size="small">This is an info callout.</n8n-text>',
|
||||
},
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
describe('content', () => {
|
||||
it('should render custom HTML content correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'custom',
|
||||
message: 'This is an HTML callout. <a href="#" target="_blank"><b>Read more</b></a>',
|
||||
icon: 'code',
|
||||
},
|
||||
stubs: [
|
||||
'n8n-icon',
|
||||
'n8n-text',
|
||||
],
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
it('should render success theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'success',
|
||||
},
|
||||
stubs: [ 'n8n-icon', 'n8n-text' ],
|
||||
slots: {
|
||||
default: '<n8n-text size="small">This is a success callout.</n8n-text>',
|
||||
},
|
||||
});
|
||||
it('should pass props to text component correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'warning',
|
||||
message: 'This is a callout.',
|
||||
bold: true,
|
||||
align: 'center',
|
||||
tag: 'p',
|
||||
},
|
||||
stubs: [
|
||||
'n8n-icon',
|
||||
'n8n-text',
|
||||
],
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
it('should render warning theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'warning',
|
||||
},
|
||||
stubs: [ 'n8n-icon', 'n8n-text' ],
|
||||
slots: {
|
||||
default: '<n8n-text size="small">This is a warning callout.</n8n-text>',
|
||||
},
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
it('should render danger theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'danger',
|
||||
},
|
||||
stubs: [ 'n8n-icon', 'n8n-text' ],
|
||||
slots: {
|
||||
default: '<n8n-text size="small">This is a danger callout.</n8n-text>',
|
||||
},
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
it('should render secondary theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'secondary',
|
||||
},
|
||||
stubs: [ 'n8n-icon', 'n8n-text' ],
|
||||
slots: {
|
||||
default: '<n8n-text size="small">This is a secondary callout.</n8n-text>',
|
||||
},
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
it('should render custom theme correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'custom',
|
||||
icon: 'code-branch',
|
||||
},
|
||||
stubs: [ 'n8n-icon', 'n8n-text' ],
|
||||
slots: {
|
||||
default: '<n8n-text size="small">This is a secondary callout.</n8n-text>',
|
||||
},
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
it('should render additional slots correctly', () => {
|
||||
const wrapper = render(N8nCallout, {
|
||||
props: {
|
||||
theme: 'custom',
|
||||
icon: 'code-branch',
|
||||
},
|
||||
stubs: [ 'n8n-icon', 'n8n-text', 'n8n-link' ],
|
||||
slots: {
|
||||
default: '<n8n-text size="small">This is a secondary callout.</n8n-text>',
|
||||
actions: '<n8n-link size="small">Do something!</n8n-link>',
|
||||
trailingContent: '<n8n-link theme="secondary" size="small" :bold="true" :underline="true" to="https://n8n.io">Learn more</n8n-link>',
|
||||
},
|
||||
});
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,78 +1,79 @@
|
|||
// Vitest Snapshot v1
|
||||
|
||||
exports[`components > N8NCallout > content > should pass props to text component correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _warning_a6gr6_16\\" bold=\\"true\\" align=\\"center\\" tag=\\"p\\">
|
||||
<div class=\\"_icon_a6gr6_34\\">
|
||||
<n8n-icon-stub icon=\\"exclamation-triangle\\" size=\\"large\\" bold=\\"true\\" align=\\"center\\" tag=\\"p\\"></n8n-icon-stub>
|
||||
exports[`components > N8nCallout > should render additional slots correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_p74de_1 _custom_p74de_16\\">
|
||||
<div class=\\"_message-section_p74de_12\\">
|
||||
<div class=\\"_icon_p74de_40\\">
|
||||
<n8n-icon-stub icon=\\"code-branch\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a secondary callout.</n8n-text-stub> <n8n-link-stub size=\\"small\\">Do something!</n8n-link-stub>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-text-stub bold=\\"true\\" size=\\"small\\" align=\\"center\\" tag=\\"p\\"><span>This is a callout.</span></n8n-text-stub>
|
||||
<n8n-link-stub theme=\\"secondary\\" size=\\"small\\" bold=\\"true\\" underline=\\"true\\" to=\\"https://n8n.io\\">Learn more</n8n-link-stub>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`components > N8nCallout > should render custom theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_p74de_1 _custom_p74de_16\\">
|
||||
<div class=\\"_message-section_p74de_12\\">
|
||||
<div class=\\"_icon_p74de_40\\">
|
||||
<n8n-icon-stub icon=\\"code-branch\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a secondary callout.</n8n-text-stub>
|
||||
</div>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`components > N8NCallout > content > should render custom HTML content correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _custom_a6gr6_10\\">
|
||||
<div class=\\"_icon_a6gr6_34\\">
|
||||
<n8n-icon-stub icon=\\"code\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\"><span>This is an HTML callout. <a href=\\"#\\" target=\\"_blank\\"><b>Read more</b></a></span></n8n-text-stub>
|
||||
exports[`components > N8nCallout > should render danger theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_p74de_1 _danger_p74de_34\\">
|
||||
<div class=\\"_message-section_p74de_12\\">
|
||||
<div class=\\"_icon_p74de_40\\">
|
||||
<n8n-icon-stub icon=\\"times-circle\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a danger callout.</n8n-text-stub>
|
||||
</div>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`components > N8NCallout > props > should render custom theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _custom_a6gr6_10\\">
|
||||
<div class=\\"_icon_a6gr6_34\\">
|
||||
<n8n-icon-stub icon=\\"code\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\"><span>This is an custom callout.</span></n8n-text-stub>
|
||||
exports[`components > N8nCallout > should render info theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_p74de_1 _info_p74de_16\\">
|
||||
<div class=\\"_message-section_p74de_12\\">
|
||||
<div class=\\"_icon_p74de_40\\">
|
||||
<n8n-icon-stub icon=\\"info-circle\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\">This is an info callout.</n8n-text-stub>
|
||||
</div>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`components > N8NCallout > props > should render danger theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _danger_a6gr6_28\\">
|
||||
<div class=\\"_icon_a6gr6_34\\">
|
||||
<n8n-icon-stub icon=\\"times-circle\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\"><span>This is an danger callout.</span></n8n-text-stub>
|
||||
exports[`components > N8nCallout > should render secondary theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_p74de_1 _secondary_p74de_44\\">
|
||||
<div class=\\"_message-section_p74de_12\\">
|
||||
<div class=\\"_icon_p74de_40\\">
|
||||
<n8n-icon-stub icon=\\"info-circle\\" size=\\"medium\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a secondary callout.</n8n-text-stub>
|
||||
</div>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`components > N8NCallout > props > should render info theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _info_a6gr6_10\\">
|
||||
<div class=\\"_icon_a6gr6_34\\">
|
||||
<n8n-icon-stub icon=\\"info-circle\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\"><span>This is an info callout.</span></n8n-text-stub>
|
||||
exports[`components > N8nCallout > should render success theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_p74de_1 _success_p74de_28\\">
|
||||
<div class=\\"_message-section_p74de_12\\">
|
||||
<div class=\\"_icon_p74de_40\\">
|
||||
<n8n-icon-stub icon=\\"check-circle\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a success callout.</n8n-text-stub>
|
||||
</div>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`components > N8NCallout > props > should render success theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _success_a6gr6_22\\">
|
||||
<div class=\\"_icon_a6gr6_34\\">
|
||||
<n8n-icon-stub icon=\\"check-circle\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\"><span>This is an success callout.</span></n8n-text-stub>
|
||||
</div>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`components > N8NCallout > props > should render warning theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _warning_a6gr6_16\\">
|
||||
<div class=\\"_icon_a6gr6_34\\">
|
||||
<n8n-icon-stub icon=\\"exclamation-triangle\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\"><span>This is an warning callout.</span></n8n-text-stub>
|
||||
exports[`components > N8nCallout > should render warning theme correctly 1`] = `
|
||||
"<div role=\\"alert\\" class=\\"_callout_p74de_1 _warning_p74de_22\\">
|
||||
<div class=\\"_message-section_p74de_12\\">
|
||||
<div class=\\"_icon_p74de_40\\">
|
||||
<n8n-icon-stub icon=\\"exclamation-triangle\\" size=\\"large\\"></n8n-icon-stub>
|
||||
</div>
|
||||
<n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a warning callout.</n8n-text-stub>
|
||||
</div>
|
||||
</div>"
|
||||
`;
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
import N8nPanelCallout from './PanelCallout.vue';
|
||||
import { StoryFn } from '@storybook/vue';
|
||||
import N8nLink from '../N8nLink';
|
||||
import N8nText from '../N8nText';
|
||||
|
||||
export default {
|
||||
title: 'Atoms/Callout',
|
||||
component: N8nPanelCallout,
|
||||
argTypes: {
|
||||
theme: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['info', 'secondary', 'success', 'warning', 'danger', 'custom'],
|
||||
},
|
||||
},
|
||||
message: {
|
||||
control: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
icon: {
|
||||
control: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'figma',
|
||||
url: 'https://www.figma.com/file/tPpJvbrnHbP8C496cYuwyW/Node-pinning?node-id=15%3A5777',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const template = (args, { argTypes }) => ({
|
||||
props: Object.keys(argTypes),
|
||||
components: {
|
||||
N8nLink,
|
||||
N8nText,
|
||||
N8nPanelCallout,
|
||||
},
|
||||
template: `
|
||||
<n8n-panel-callout v-bind="$props">
|
||||
${args.default}
|
||||
<template #actions v-if="actions">
|
||||
${args.actions}
|
||||
</template>
|
||||
<template #trailingContent v-if="trailingContent">
|
||||
${args.trailingContent}
|
||||
</template>
|
||||
</n8n-panel-callout>
|
||||
`,
|
||||
});
|
||||
|
||||
export const customCallout = template.bind({});
|
||||
customCallout.args = {
|
||||
theme: 'custom',
|
||||
icon: 'code-branch',
|
||||
default: `
|
||||
<n8n-text
|
||||
size="small"
|
||||
>
|
||||
This is a callout.
|
||||
</n8n-text>
|
||||
`,
|
||||
actions: `
|
||||
<n8n-link
|
||||
size="small"
|
||||
>
|
||||
Do something!
|
||||
</n8n-link>
|
||||
`,
|
||||
};
|
||||
|
||||
export const secondaryCallout = template.bind({});
|
||||
secondaryCallout.args = {
|
||||
theme: 'secondary',
|
||||
icon: 'thumbtack',
|
||||
default: `
|
||||
<n8n-text
|
||||
size="small"
|
||||
:bold="true"
|
||||
>
|
||||
This data is pinned.
|
||||
</n8n-text>
|
||||
`,
|
||||
actions: `
|
||||
<n8n-link
|
||||
theme="secondary"
|
||||
size="small"
|
||||
:bold="true"
|
||||
>
|
||||
Unpin
|
||||
</n8n-link>
|
||||
`,
|
||||
trailingContent: `
|
||||
<n8n-link
|
||||
theme="secondary"
|
||||
size="small"
|
||||
:bold="true"
|
||||
:underline="true"
|
||||
to="https://n8n.io"
|
||||
>
|
||||
Learn more
|
||||
</n8n-link>
|
||||
`,
|
||||
};
|
|
@ -1,115 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes" role="alert">
|
||||
|
||||
<div :class="$style['message-section']">
|
||||
<div :class="$style.icon">
|
||||
<n8n-icon
|
||||
:icon="getIcon"
|
||||
:size="theme === 'secondary' ? 'medium' : 'large'"
|
||||
/>
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<slot name="trailingContent" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import N8nIcon from '../N8nIcon';
|
||||
|
||||
const CALLOUT_DEFAULT_ICONS = {
|
||||
info: 'info-circle',
|
||||
success: 'check-circle',
|
||||
warning: 'exclamation-triangle',
|
||||
danger: 'times-circle',
|
||||
};
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'n8n-panel-callout',
|
||||
components: {
|
||||
N8nIcon,
|
||||
},
|
||||
props: {
|
||||
theme: {
|
||||
type: String,
|
||||
required: true,
|
||||
validator: (value: string): boolean =>
|
||||
['info', 'success', 'secondary', 'warning', 'danger', 'custom'].includes(value),
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'info-circle'
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
classes(): string[] {
|
||||
return [
|
||||
this.$style['callout'],
|
||||
this.$style[this.theme],
|
||||
];
|
||||
},
|
||||
getIcon(): string {
|
||||
if (Object.keys(CALLOUT_DEFAULT_ICONS).includes(this.theme)) {
|
||||
return CALLOUT_DEFAULT_ICONS[this.theme];
|
||||
}
|
||||
|
||||
return this.icon;
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.callout {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: var(--font-size-2xs);
|
||||
padding: var(--spacing-xs);
|
||||
border: var(--border-width-base) var(--border-style-base);
|
||||
border-radius: var(--border-radius-base);
|
||||
align-items: center;
|
||||
line-height: var(--font-line-height-loose);
|
||||
}
|
||||
|
||||
.message-section {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.info, .custom {
|
||||
border-color: var(--color-foreground-base);
|
||||
background-color: var(--color-background-light);
|
||||
color: var(--color-info);
|
||||
}
|
||||
|
||||
.warning {
|
||||
border-color: var(--color-warning-tint-1);
|
||||
background-color: var(--color-warning-tint-2);
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.success {
|
||||
border-color: var(--color-success-tint-1);
|
||||
background-color: var(--color-success-tint-2);
|
||||
color: var(--color-success);
|
||||
}
|
||||
|
||||
.danger {
|
||||
border-color: var(--color-danger-tint-1);
|
||||
background-color: var(--color-danger-tint-2);
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.secondary {
|
||||
font-size: var(--font-size-2xs);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--color-secondary);
|
||||
background-color: var(--color-secondary-tint-2);
|
||||
border-color: var(--color-secondary-tint-1);
|
||||
}
|
||||
</style>
|
|
@ -1,3 +0,0 @@
|
|||
import N8nPanelCallout from './PanelCallout.vue';
|
||||
|
||||
export default N8nPanelCallout;
|
|
@ -41,7 +41,6 @@ import N8nBadge from './N8nBadge';
|
|||
import N8nButton from './N8nButton';
|
||||
import { N8nElButton } from './N8nButton/overrides';
|
||||
import N8nCallout from './N8nCallout';
|
||||
import N8nPanelCallout from './N8nPanelCallout';
|
||||
import N8nCard from './N8nCard';
|
||||
import N8nFormBox from './N8nFormBox';
|
||||
import N8nFormInput from './N8nFormInput';
|
||||
|
@ -86,7 +85,6 @@ export {
|
|||
N8nButton,
|
||||
N8nElButton,
|
||||
N8nCallout,
|
||||
N8nPanelCallout,
|
||||
N8nCard,
|
||||
N8nHeading,
|
||||
N8nFormBox,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div :class="$style.container">
|
||||
<n8n-panel-callout
|
||||
<n8n-callout
|
||||
v-if="canPinData && hasPinData && !editMode.enabled"
|
||||
theme="secondary"
|
||||
icon="thumbtack"
|
||||
|
@ -30,7 +30,7 @@
|
|||
{{ $locale.baseText('runData.pindata.learnMore') }}
|
||||
</n8n-link>
|
||||
</template>
|
||||
</n8n-panel-callout>
|
||||
</n8n-callout>
|
||||
|
||||
<BinaryDataDisplay :windowVisible="binaryDataDisplayVisible" :displayData="binaryDataDisplayData" @close="closeBinaryDataDisplay"/>
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ import {
|
|||
N8nButton,
|
||||
N8nElButton,
|
||||
N8nCallout,
|
||||
N8nPanelCallout,
|
||||
N8nCard,
|
||||
N8nIcon,
|
||||
N8nIconButton,
|
||||
|
@ -94,7 +93,6 @@ Vue.use(N8nAvatar);
|
|||
Vue.component('n8n-button', N8nButton);
|
||||
Vue.component('el-button', N8nElButton);
|
||||
Vue.component('n8n-callout', N8nCallout);
|
||||
Vue.component('n8n-panel-callout', N8nPanelCallout);
|
||||
Vue.component('n8n-card', N8nCard);
|
||||
Vue.component('n8n-form-box', N8nFormBox);
|
||||
Vue.component('n8n-form-inputs', N8nFormInputs);
|
||||
|
|
|
@ -10,15 +10,15 @@
|
|||
@click="openInstallModal"
|
||||
/>
|
||||
</div>
|
||||
<n8n-action-box
|
||||
v-if="isQueueModeEnabled"
|
||||
:heading="$locale.baseText('settings.communityNodes.empty.title')"
|
||||
:description="getEmptyStateDescription"
|
||||
:calloutText="actionBoxConfig.calloutText"
|
||||
:calloutTheme="actionBoxConfig.calloutTheme"
|
||||
@click="openInstallModal"
|
||||
@descriptionClick="onDescriptionTextClick"
|
||||
/>
|
||||
<div v-if="isQueueModeEnabled" :class="$style.actionBoxContainer">
|
||||
<n8n-action-box
|
||||
:heading="$locale.baseText('settings.communityNodes.empty.title')"
|
||||
:description="getEmptyStateDescription"
|
||||
:calloutText="actionBoxConfig.calloutText"
|
||||
:calloutTheme="actionBoxConfig.calloutTheme"
|
||||
@descriptionClick="onDescriptionTextClick"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
:class="$style.cardsContainer"
|
||||
v-else-if="loading"
|
||||
|
|
Loading…
Reference in a new issue