Skip to content

Commit

Permalink
⚡️ Using model value for IconPicker
Browse files Browse the repository at this point in the history
  • Loading branch information
MiloradFilipovic committed Dec 24, 2024
1 parent 6b591fc commit 0483fb4
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,61 @@ export default {
argTypes: {},
};

const Template: StoryFn = (args, { argTypes }) => ({
const DefaultTemplate: StoryFn = (args, { argTypes }) => ({
components: { N8nIconPicker },
props: Object.keys(argTypes),
setup: () => ({ args }),
data: () => ({
icon: { type: 'icon', value: 'smile' },
}),
template:
'<div style="height: 500px"><n8n-icon-picker v-bind="args" @iconSelected="onIconSelected" /></div>',
'<div style="height: 500px"><n8n-icon-picker v-model="icon" v-bind="args" @update:model-value="onIconSelected" /></div>',
methods: {
onIconSelected: action('iconSelected'),
},
});

export const Default = Template.bind({});
export const Default = DefaultTemplate.bind({});
Default.args = {
defaultIcon: { type: 'icon', value: 'smile' },
buttonTooltip: 'Select an icon',
availableIcons: TEST_ICONS,
};

export const WithCustomIconAndTooltip = Template.bind({});
const CustomTooltipTemplate: StoryFn = (args, { argTypes }) => ({
components: { N8nIconPicker },
props: Object.keys(argTypes),
setup: () => ({ args }),
data: () => ({
icon: { type: 'icon', value: 'layer-group' },
}),
template:
'<div style="height: 500px"><n8n-icon-picker v-model="icon" v-bind="args" @update:model-value="onIconSelected" /></div>',
methods: {
onIconSelected: action('iconSelected'),
},
});

export const WithCustomIconAndTooltip = CustomTooltipTemplate.bind({});
WithCustomIconAndTooltip.args = {
defaultIcon: { type: 'icon', value: 'layer-group' },
availableIcons: [...TEST_ICONS],
buttonTooltip: 'Select something...',
};

export const OnlyEmojis = Template.bind({});
const OnlyEmojiTemplate: StoryFn = (args, { argTypes }) => ({
components: { N8nIconPicker },
props: Object.keys(argTypes),
setup: () => ({ args }),
data: () => ({
icon: { type: 'emoji', value: '🔥' },
}),
template:
'<div style="height: 500px"><n8n-icon-picker v-model="icon" v-bind="args" @update:model-value="onIconSelected" /></div>',
methods: {
onIconSelected: action('iconSelected'),
},
});
export const OnlyEmojis = OnlyEmojiTemplate.bind({});
OnlyEmojis.args = {
defaultIcon: { type: 'emoji', value: '😁' },
buttonTooltip: 'Select an emoji',
availableIcons: [],
};
21 changes: 10 additions & 11 deletions packages/design-system/src/components/N8nIconPicker/IconPicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,24 @@ const { t } = useI18n();
defineOptions({ name: 'N8nIconPicker' });
// TODO: Extract to type
// TODO: Add comments about emoji library and search
const props = withDefaults(
defineProps<{
defaultIcon: Icon;
modelValue: Icon;
buttonTooltip: string;
availableIcons: string[];
}>(),
{
defaultIcon: () => ({ type: 'icon', value: 'smile' }),
modelValue: () => ({ type: 'icon', value: 'smile' }),
buttonTooltip: 'Select an icon',
availableIcons: () => [],
},
);
const emit = defineEmits<{
iconSelected: [value: Icon];
// eslint-disable-next-line @typescript-eslint/naming-convention
'update:modelValue': [value: Icon];
}>();
const hasAvailableIcons = computed(() => props.availableIcons.length > 0);
Expand All @@ -57,15 +60,12 @@ const tabs = ref<Array<{ value: string; label: string }>>(
: [{ value: 'emojis', label: t('iconPicker.tabs.emojis') }],
);
const selectedTab = ref<string>(tabs.value[0].value);
const selectedIcon = ref<Icon>(props.defaultIcon);
const emojis = ref<string[]>([]);
watch(
() => props.defaultIcon,
(newValue) => {
selectedIcon.value = newValue;
},
);
const selectedIcon = computed({
get: () => props.modelValue,
set: (value: Icon) => emit('update:modelValue', value),
});
onMounted(() => {
generateEmojis();
Expand All @@ -91,7 +91,6 @@ onClickOutside(container, () => {
const selectIcon = (value: Icon) => {
selectedIcon.value = value;
popupVisible.value = false;
emit('iconSelected', selectedIcon.value);
};
</script>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,12 @@ export const TEST_ICONS = [
'user-circle',
'user-friends',
'users',
'variable',
'vault',
'vector-square',
'video',
'tree',
'user-lock',
'gem',
'xmark',
'download',
'power-off',
'paper-plane',
'refresh',
];
7 changes: 3 additions & 4 deletions packages/editor-ui/src/views/ProjectSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,7 @@ const selectProjectNameIfMatchesDefault = () => {
}
};
const onIconUpdated = async (icon: ProjectIcon) => {
projectIcon.value = icon;
const onIconUpdated = async () => {
await updateProject();
toast.showMessage({
title: i18n.baseText('projects.settings.icon.update.successful.title'),
Expand Down Expand Up @@ -298,10 +297,10 @@ onMounted(() => {
<label for="projectName">{{ i18n.baseText('projects.settings.name') }}</label>
<div :class="$style['project-name']">
<N8nIconPicker
:default-icon="projectIcon"
v-model="projectIcon"
:button-tooltip="i18n.baseText('projects.settings.iconPicker.button.tooltip')"
:available-icons="availableProjectIcons"
@icon-selected="onIconUpdated"
@update:model-value="onIconUpdated"
/>
<N8nFormInput
id="projectName"
Expand Down

0 comments on commit 0483fb4

Please sign in to comment.