diff --git a/app/portainer/react/components/index.ts b/app/portainer/react/components/index.ts index 3433f10ef..793ff68ce 100644 --- a/app/portainer/react/components/index.ts +++ b/app/portainer/react/components/index.ts @@ -34,6 +34,7 @@ import { BadgeIcon } from '@@/BadgeIcon'; import { TeamsSelector } from '@@/TeamsSelector'; import { PortainerSelect } from '@@/form-components/PortainerSelect'; import { Slider } from '@@/form-components/Slider'; +import { TagButton } from '@@/TagButton'; import { fileUploadField } from './file-upload-field'; import { switchField } from './switch-field'; @@ -45,6 +46,10 @@ export const componentsModule = angular 'tagSelector', r2a(withReactQuery(TagSelector), ['allowCreate', 'onChange', 'value']) ) + .component( + 'tagButton', + r2a(TagButton, ['value', 'label', 'title', 'onRemove']) + ) .component( 'portainerTooltip', r2a(Tooltip, ['message', 'position', 'className']) diff --git a/app/react/components/TagSelector/TagSelector.module.css b/app/react/components/TagButton/TagButton.module.css similarity index 100% rename from app/react/components/TagSelector/TagSelector.module.css rename to app/react/components/TagButton/TagButton.module.css diff --git a/app/react/components/TagButton/TagButton.tsx b/app/react/components/TagButton/TagButton.tsx new file mode 100644 index 000000000..e649e98c7 --- /dev/null +++ b/app/react/components/TagButton/TagButton.tsx @@ -0,0 +1,33 @@ +import clsx from 'clsx'; +import { Trash2 } from 'lucide-react'; + +import { Icon } from '@/react/components/Icon'; + +import styles from './TagButton.module.css'; + +interface Props { + value: number; + label: string; + title: string; + onRemove(): void; +} + +export function TagButton({ value, label, title, onRemove }: Props) { + return ( + + ); +} diff --git a/app/react/components/TagButton/index.ts b/app/react/components/TagButton/index.ts new file mode 100644 index 000000000..ed32cb1ec --- /dev/null +++ b/app/react/components/TagButton/index.ts @@ -0,0 +1 @@ +export { TagButton } from './TagButton'; diff --git a/app/react/components/TagSelector/TagSelector.tsx b/app/react/components/TagSelector/TagSelector.tsx index 2dafeaffc..d50b44a1c 100644 --- a/app/react/components/TagSelector/TagSelector.tsx +++ b/app/react/components/TagSelector/TagSelector.tsx @@ -1,16 +1,13 @@ -import clsx from 'clsx'; import _ from 'lodash'; -import { Trash2 } from 'lucide-react'; import { TagId } from '@/portainer/tags/types'; -import { Icon } from '@/react/components/Icon'; import { useCreateTagMutation, useTags } from '@/portainer/tags/queries'; import { Creatable, Select } from '@@/form-components/ReactSelect'; import { FormControl } from '@@/form-components/FormControl'; import { Link } from '@@/Link'; -import styles from './TagSelector.module.css'; +import { TagButton } from '../TagButton'; interface Props { value: TagId[]; @@ -62,21 +59,12 @@ export function TagSelector({ value, allowCreate = false, onChange }: Props) { {value.length > 0 && ( {selectedTags.map((tag) => ( - + value={tag.value} + label={tag.label} + onRemove={() => handleRemove(tag.value)} + /> ))} )} @@ -112,6 +100,12 @@ export function TagSelector({ value, allowCreate = false, onChange }: Props) { if (!allowCreate) { return; } + + // Prevent the new tag composed of space from being added + if (!inputValue.replace(/\s/g, '').length) { + return; + } + createTagMutation.mutate(inputValue, { onSuccess(tag) { handleAdd({ label: tag.Name, value: tag.ID });