refactor(editor): Unify Callout components (#3798)

*  Implemented a single Callout component

* ✔️ Updating test snapshots and fixing lint warnings
This commit is contained in:
Milorad FIlipović
2022-08-02 10:36:11 +02:00
committed by GitHub
parent 0ecbb4a19d
commit ad8d662976
13 changed files with 320 additions and 566 deletions

View File

@@ -4,14 +4,26 @@
<component :is="$options.components.N8nHeading" size="xlarge" align="center">{{ props.heading }}</component> <component :is="$options.components.N8nHeading" size="xlarge" align="center">{{ props.heading }}</component>
</div> </div>
<div :class="$style.description" @click="(e) => listeners.descriptionClick && listeners.descriptionClick(e)"> <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> </div>
<component v-if="props.buttonText" :is="$options.components.N8nButton" :label="props.buttonText" size="large" <component v-if="props.buttonText" :is="$options.components.N8nButton" :label="props.buttonText" size="large"
@click="(e) => listeners.click && listeners.click(e)" @click="(e) => listeners.click && listeners.click(e)"
/> />
<component v-if="props.calloutText" :is="$options.components.N8nCallout" <component
:theme="props.calloutTheme" :message="props.calloutText" :icon="props.calloutIcon" 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> </div>
</template> </template>
@@ -23,6 +35,12 @@ import N8nCallout from '../N8nCallout';
export default { export default {
name: 'n8n-action-box', name: 'n8n-action-box',
components: {
N8nButton,
N8nHeading,
N8nText,
N8nCallout,
},
props: { props: {
heading: { heading: {
type: String, type: String,
@@ -44,12 +62,6 @@ export default {
type: String, type: String,
}, },
}, },
components: {
N8nButton,
N8nHeading,
N8nText,
N8nCallout,
},
}; };
</script> </script>
@@ -79,4 +91,10 @@ export default {
color: var(--color-text-base); color: var(--color-text-base);
margin-bottom: var(--spacing-xl); margin-bottom: var(--spacing-xl);
} }
.callout {
width: 100%;
text-align: left;
}
</style> </style>

View File

@@ -1,6 +1,9 @@
import N8nCallout from './Callout.vue'; import N8nCallout from './Callout.vue';
import N8nLink from '../N8nLink';
import N8nText from '../N8nText';
import { StoryFn } from '@storybook/vue'; import { StoryFn } from '@storybook/vue';
export default { export default {
title: 'Atoms/Callout', title: 'Atoms/Callout',
component: N8nCallout, component: N8nCallout,
@@ -8,7 +11,7 @@ export default {
theme: { theme: {
control: { control: {
type: 'select', type: 'select',
options: ['info', 'success', 'warning', 'danger', 'custom'], options: ['info', 'secondary', 'success', 'warning', 'danger', 'custom'],
}, },
}, },
message: { 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 }) => ({ const template : StoryFn = (args, { argTypes }) => ({
props: Object.keys(argTypes), props: Object.keys(argTypes),
components: { components: {
N8nLink,
N8nText,
N8nCallout, 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({}); export const defaultCallout = template.bind({});
callout.args = { 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', theme: 'custom',
icon: 'code-branch', 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>
`,
}; };

View File

@@ -1,11 +1,18 @@
<template> <template>
<div :class="classes" role="alert"> <div :class="classes" role="alert">
<div :class="$style.icon">
<n8n-icon v-bind="$attrs" :icon="getIcon" size="large"/> <div :class="$style['message-section']">
</div> <div :class="$style.icon">
<div :class="$style.message" > <n8n-icon
<n8n-text size="small" v-bind="$attrs"><span v-html="message"></span></n8n-text> :icon="getIcon"
:size="theme === 'secondary' ? 'medium' : 'large'"
/>
</div>
<slot />&nbsp;
<slot name="actions" />
</div> </div>
<slot name="trailingContent" />
</div> </div>
</template> </template>
@@ -14,37 +21,30 @@ import Vue from 'vue';
import N8nIcon from '../N8nIcon'; import N8nIcon from '../N8nIcon';
import N8nText from '../N8nText'; import N8nText from '../N8nText';
const CALLOUT_DEFAULT_ICONS = {
info: 'info-circle',
success: 'check-circle',
warning: 'exclamation-triangle',
danger: 'times-circle',
};
export default Vue.extend({ export default Vue.extend({
name: 'n8n-callout', name: 'n8n-callout',
components: { components: {
N8nIcon, N8nIcon,
N8nText N8nText,
}, },
props: { props: {
theme: { theme: {
type: String, type: String,
required: true, required: true,
validator: (value: string): boolean => validator: (value: string): boolean =>
['info', 'success', 'warning', 'danger', 'custom'].includes(value), ['info', 'success', 'secondary', 'warning', 'danger', 'custom'].includes(value),
},
message: {
type: String,
required: true
}, },
icon: { icon: {
type: String, type: String,
default: 'info-circle' default: 'info-circle'
} },
},
data() {
return {
defaultIcons: {
'info': 'info-circle',
'success': 'check-circle',
'warning': 'exclamation-triangle',
'danger': 'times-circle',
}
}
}, },
computed: { computed: {
classes(): string[] { classes(): string[] {
@@ -54,50 +54,65 @@ export default Vue.extend({
]; ];
}, },
getIcon(): string { getIcon(): string {
if(this.theme === 'custom') { if (Object.keys(CALLOUT_DEFAULT_ICONS).includes(this.theme)) {
return this.icon; return CALLOUT_DEFAULT_ICONS[this.theme];
} }
return this.defaultIcons[this.theme];
return this.icon;
}, },
} }
}); });
</script> </script>
<style lang="scss" module> <style lang="scss" module>
.callout { .callout {
display: flex; display: flex;
font-size: var(--font-size-2xs); justify-content: space-between;
padding: var(--spacing-xs); font-size: var(--font-size-2xs);
border: var(--border-width-base) var(--border-style-base); padding: var(--spacing-xs);
border-radius: var(--border-radius-base); border: var(--border-width-base) var(--border-style-base);
align-items: center; border-radius: var(--border-radius-base);
} align-items: center;
line-height: var(--font-line-height-loose);
}
.info, .custom { .message-section {
border-color: var(--color-foreground-base); display: flex;
background-color: var(--color-background-light); }
color: var(--color-info);
}
.warning { .info, .custom {
border-color: var(--color-warning-tint-1); border-color: var(--color-foreground-base);
background-color: var(--color-warning-tint-2); background-color: var(--color-background-light);
color: var(--color-warning); color: var(--color-info);
} }
.success { .warning {
border-color: var(--color-success-tint-1); border-color: var(--color-warning-tint-1);
background-color: var(--color-success-tint-2); background-color: var(--color-warning-tint-2);
color: var(--color-success); color: var(--color-warning);
} }
.danger { .success {
border-color: var(--color-danger-tint-1); border-color: var(--color-success-tint-1);
background-color: var(--color-danger-tint-2); background-color: var(--color-success-tint-2);
color: var(--color-danger); color: var(--color-success);
} }
.icon { .danger {
margin-right: var(--spacing-xs); 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> </style>

View File

@@ -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>
`,
};

View File

@@ -2,106 +2,94 @@ import { render } from '@testing-library/vue';
import N8nCallout from '../Callout.vue'; import N8nCallout from '../Callout.vue';
describe('components', () => { describe('components', () => {
describe('N8NCallout', () => { describe('N8nCallout', () => {
describe('props', () => { it('should render info theme correctly', () => {
it('should render info theme correctly', () => { const wrapper = render(N8nCallout, {
const wrapper = render(N8nCallout, { props: {
props: { theme: 'info',
theme: 'info', },
message: 'This is an info callout.', stubs: [ 'n8n-icon', 'n8n-text' ],
}, slots: {
stubs: [ default: '<n8n-text size="small">This is an info callout.</n8n-text>',
'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();
}); });
expect(wrapper.html()).toMatchSnapshot();
}); });
describe('content', () => { it('should render success theme correctly', () => {
it('should render custom HTML content correctly', () => { const wrapper = render(N8nCallout, {
const wrapper = render(N8nCallout, { props: {
props: { theme: 'success',
theme: 'custom', },
message: 'This is an HTML callout. <a href="#" target="_blank"><b>Read more</b></a>', stubs: [ 'n8n-icon', 'n8n-text' ],
icon: 'code', slots: {
}, default: '<n8n-text size="small">This is a success callout.</n8n-text>',
stubs: [ },
'n8n-icon',
'n8n-text',
],
});
expect(wrapper.html()).toMatchSnapshot();
}); });
it('should pass props to text component correctly', () => { expect(wrapper.html()).toMatchSnapshot();
const wrapper = render(N8nCallout, { });
props: { it('should render warning theme correctly', () => {
theme: 'warning', const wrapper = render(N8nCallout, {
message: 'This is a callout.', props: {
bold: true, theme: 'warning',
align: 'center', },
tag: 'p', stubs: [ 'n8n-icon', 'n8n-text' ],
}, slots: {
stubs: [ default: '<n8n-text size="small">This is a warning callout.</n8n-text>',
'n8n-icon', },
'n8n-text',
],
});
expect(wrapper.html()).toMatchSnapshot();
}); });
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();
}); });
}); });
}); });

View File

@@ -1,78 +1,79 @@
// Vitest Snapshot v1 // Vitest Snapshot v1
exports[`components > N8NCallout > content > should pass props to text component correctly 1`] = ` exports[`components > N8nCallout > should render additional slots correctly 1`] = `
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _warning_a6gr6_16\\" bold=\\"true\\" align=\\"center\\" tag=\\"p\\"> "<div role=\\"alert\\" class=\\"_callout_p74de_1 _custom_p74de_16\\">
<div class=\\"_icon_a6gr6_34\\"> <div class=\\"_message-section_p74de_12\\">
<n8n-icon-stub icon=\\"exclamation-triangle\\" size=\\"large\\" bold=\\"true\\" align=\\"center\\" tag=\\"p\\"></n8n-icon-stub> <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>&nbsp; <n8n-link-stub size=\\"small\\">Do something!</n8n-link-stub>
</div> </div>
<div> <n8n-link-stub theme=\\"secondary\\" size=\\"small\\" bold=\\"true\\" underline=\\"true\\" to=\\"https://n8n.io\\">Learn more</n8n-link-stub>
<n8n-text-stub bold=\\"true\\" size=\\"small\\" align=\\"center\\" tag=\\"p\\"><span>This is a callout.</span></n8n-text-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>&nbsp;
</div> </div>
</div>" </div>"
`; `;
exports[`components > N8NCallout > content > should render custom HTML content correctly 1`] = ` exports[`components > N8nCallout > should render danger theme correctly 1`] = `
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _custom_a6gr6_10\\"> "<div role=\\"alert\\" class=\\"_callout_p74de_1 _danger_p74de_34\\">
<div class=\\"_icon_a6gr6_34\\"> <div class=\\"_message-section_p74de_12\\">
<n8n-icon-stub icon=\\"code\\" size=\\"large\\"></n8n-icon-stub> <div class=\\"_icon_p74de_40\\">
</div> <n8n-icon-stub icon=\\"times-circle\\" 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> <n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a danger callout.</n8n-text-stub>&nbsp;
</div> </div>
</div>" </div>"
`; `;
exports[`components > N8NCallout > props > should render custom theme correctly 1`] = ` exports[`components > N8nCallout > should render info theme correctly 1`] = `
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _custom_a6gr6_10\\"> "<div role=\\"alert\\" class=\\"_callout_p74de_1 _info_p74de_16\\">
<div class=\\"_icon_a6gr6_34\\"> <div class=\\"_message-section_p74de_12\\">
<n8n-icon-stub icon=\\"code\\" size=\\"large\\"></n8n-icon-stub> <div class=\\"_icon_p74de_40\\">
</div> <n8n-icon-stub icon=\\"info-circle\\" size=\\"large\\"></n8n-icon-stub>
<div> </div>
<n8n-text-stub size=\\"small\\" tag=\\"span\\"><span>This is an custom callout.</span></n8n-text-stub> <n8n-text-stub size=\\"small\\" tag=\\"span\\">This is an info callout.</n8n-text-stub>&nbsp;
</div> </div>
</div>" </div>"
`; `;
exports[`components > N8NCallout > props > should render danger theme correctly 1`] = ` exports[`components > N8nCallout > should render secondary theme correctly 1`] = `
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _danger_a6gr6_28\\"> "<div role=\\"alert\\" class=\\"_callout_p74de_1 _secondary_p74de_44\\">
<div class=\\"_icon_a6gr6_34\\"> <div class=\\"_message-section_p74de_12\\">
<n8n-icon-stub icon=\\"times-circle\\" size=\\"large\\"></n8n-icon-stub> <div class=\\"_icon_p74de_40\\">
</div> <n8n-icon-stub icon=\\"info-circle\\" size=\\"medium\\"></n8n-icon-stub>
<div> </div>
<n8n-text-stub size=\\"small\\" tag=\\"span\\"><span>This is an danger callout.</span></n8n-text-stub> <n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a secondary callout.</n8n-text-stub>&nbsp;
</div> </div>
</div>" </div>"
`; `;
exports[`components > N8NCallout > props > should render info theme correctly 1`] = ` exports[`components > N8nCallout > should render success theme correctly 1`] = `
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _info_a6gr6_10\\"> "<div role=\\"alert\\" class=\\"_callout_p74de_1 _success_p74de_28\\">
<div class=\\"_icon_a6gr6_34\\"> <div class=\\"_message-section_p74de_12\\">
<n8n-icon-stub icon=\\"info-circle\\" size=\\"large\\"></n8n-icon-stub> <div class=\\"_icon_p74de_40\\">
</div> <n8n-icon-stub icon=\\"check-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> <n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a success callout.</n8n-text-stub>&nbsp;
</div> </div>
</div>" </div>"
`; `;
exports[`components > N8NCallout > props > should render success theme correctly 1`] = ` exports[`components > N8nCallout > should render warning theme correctly 1`] = `
"<div role=\\"alert\\" class=\\"_callout_a6gr6_1 _success_a6gr6_22\\"> "<div role=\\"alert\\" class=\\"_callout_p74de_1 _warning_p74de_22\\">
<div class=\\"_icon_a6gr6_34\\"> <div class=\\"_message-section_p74de_12\\">
<n8n-icon-stub icon=\\"check-circle\\" size=\\"large\\"></n8n-icon-stub> <div class=\\"_icon_p74de_40\\">
</div> <n8n-icon-stub icon=\\"exclamation-triangle\\" size=\\"large\\"></n8n-icon-stub>
<div> </div>
<n8n-text-stub size=\\"small\\" tag=\\"span\\"><span>This is an success callout.</span></n8n-text-stub> <n8n-text-stub size=\\"small\\" tag=\\"span\\">This is a warning callout.</n8n-text-stub>&nbsp;
</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>
</div> </div>
</div>" </div>"
`; `;

View File

@@ -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>
`,
};

View File

@@ -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>

View File

@@ -1,3 +0,0 @@
import N8nPanelCallout from './PanelCallout.vue';
export default N8nPanelCallout;

View File

@@ -41,7 +41,6 @@ import N8nBadge from './N8nBadge';
import N8nButton from './N8nButton'; import N8nButton from './N8nButton';
import { N8nElButton } from './N8nButton/overrides'; import { N8nElButton } from './N8nButton/overrides';
import N8nCallout from './N8nCallout'; import N8nCallout from './N8nCallout';
import N8nPanelCallout from './N8nPanelCallout';
import N8nCard from './N8nCard'; import N8nCard from './N8nCard';
import N8nFormBox from './N8nFormBox'; import N8nFormBox from './N8nFormBox';
import N8nFormInput from './N8nFormInput'; import N8nFormInput from './N8nFormInput';
@@ -86,7 +85,6 @@ export {
N8nButton, N8nButton,
N8nElButton, N8nElButton,
N8nCallout, N8nCallout,
N8nPanelCallout,
N8nCard, N8nCard,
N8nHeading, N8nHeading,
N8nFormBox, N8nFormBox,

View File

@@ -1,6 +1,6 @@
<template> <template>
<div :class="$style.container"> <div :class="$style.container">
<n8n-panel-callout <n8n-callout
v-if="canPinData && hasPinData && !editMode.enabled" v-if="canPinData && hasPinData && !editMode.enabled"
theme="secondary" theme="secondary"
icon="thumbtack" icon="thumbtack"
@@ -30,7 +30,7 @@
{{ $locale.baseText('runData.pindata.learnMore') }} {{ $locale.baseText('runData.pindata.learnMore') }}
</n8n-link> </n8n-link>
</template> </template>
</n8n-panel-callout> </n8n-callout>
<BinaryDataDisplay :windowVisible="binaryDataDisplayVisible" :displayData="binaryDataDisplayData" @close="closeBinaryDataDisplay"/> <BinaryDataDisplay :windowVisible="binaryDataDisplayVisible" :displayData="binaryDataDisplayData" @close="closeBinaryDataDisplay"/>

View File

@@ -51,7 +51,6 @@ import {
N8nButton, N8nButton,
N8nElButton, N8nElButton,
N8nCallout, N8nCallout,
N8nPanelCallout,
N8nCard, N8nCard,
N8nIcon, N8nIcon,
N8nIconButton, N8nIconButton,
@@ -94,7 +93,6 @@ Vue.use(N8nAvatar);
Vue.component('n8n-button', N8nButton); Vue.component('n8n-button', N8nButton);
Vue.component('el-button', N8nElButton); Vue.component('el-button', N8nElButton);
Vue.component('n8n-callout', N8nCallout); Vue.component('n8n-callout', N8nCallout);
Vue.component('n8n-panel-callout', N8nPanelCallout);
Vue.component('n8n-card', N8nCard); Vue.component('n8n-card', N8nCard);
Vue.component('n8n-form-box', N8nFormBox); Vue.component('n8n-form-box', N8nFormBox);
Vue.component('n8n-form-inputs', N8nFormInputs); Vue.component('n8n-form-inputs', N8nFormInputs);

View File

@@ -10,15 +10,15 @@
@click="openInstallModal" @click="openInstallModal"
/> />
</div> </div>
<n8n-action-box <div v-if="isQueueModeEnabled" :class="$style.actionBoxContainer">
v-if="isQueueModeEnabled" <n8n-action-box
:heading="$locale.baseText('settings.communityNodes.empty.title')" :heading="$locale.baseText('settings.communityNodes.empty.title')"
:description="getEmptyStateDescription" :description="getEmptyStateDescription"
:calloutText="actionBoxConfig.calloutText" :calloutText="actionBoxConfig.calloutText"
:calloutTheme="actionBoxConfig.calloutTheme" :calloutTheme="actionBoxConfig.calloutTheme"
@click="openInstallModal" @descriptionClick="onDescriptionTextClick"
@descriptionClick="onDescriptionTextClick" />
/> </div>
<div <div
:class="$style.cardsContainer" :class="$style.cardsContainer"
v-else-if="loading" v-else-if="loading"