diff --git a/js-packages/web-console/src/lib/components/pipelines/table/Tags.svelte b/js-packages/web-console/src/lib/components/pipelines/table/Tags.svelte
index d88f3df6322..8d8ef0c5dd9 100644
--- a/js-packages/web-console/src/lib/components/pipelines/table/Tags.svelte
+++ b/js-packages/web-console/src/lib/components/pipelines/table/Tags.svelte
@@ -284,6 +284,9 @@
{#snippet trigger(toggle)}
{@const open = () => {
closeForm()
+ if (knownTags.size === 0) {
+ openCreate('')
+ }
toggle()
}}
@@ -331,9 +334,11 @@
{#snippet listPage()}
-
-
-
+ {#if knownTags.size > 0}
+
+
+
+ {/if}
{#each selectedTags as tag (tag)}
{@render tagRow(tag, true)}
@@ -470,7 +475,15 @@
{/if}
-
+
@@ -520,5 +533,5 @@
The tag “{newTagName.trim()}” already exists.
{/if}
-
+
{/snippet}
diff --git a/js-packages/web-console/src/lib/components/pipelines/table/Tags.svelte.spec.ts b/js-packages/web-console/src/lib/components/pipelines/table/Tags.svelte.spec.ts
index afe19b14ba4..7391ec20ad2 100644
--- a/js-packages/web-console/src/lib/components/pipelines/table/Tags.svelte.spec.ts
+++ b/js-packages/web-console/src/lib/components/pipelines/table/Tags.svelte.spec.ts
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from 'vitest'
-import { page } from 'vitest/browser'
+import { page, userEvent } from 'vitest/browser'
import { render } from 'vitest-browser-svelte'
import type { PipelineManagerApi } from '$lib/compositions/usePipelineManager.svelte'
import Tags from './Tags.svelte'
@@ -90,13 +90,30 @@ describe('Tags.svelte', () => {
tags: ['prod|ef4444']
})
})
+
+ it('opens the create form directly when no known tags exist yet', async () => {
+ renderTags({ tags: [], knownTags: [] })
+ await page.getByRole('button', { name: 'Tag' }).click()
+
+ // Empty pool skips the search list and lands on create immediately.
+ await expect.element(page.getByPlaceholder('Tag name')).toBeVisible()
+ await expect.element(page.getByRole('button', { name: 'Create' })).toBeVisible()
+ expect(page.getByPlaceholder('Search').elements()).toHaveLength(0)
+ })
+
+ it('shows search when known tags exist', async () => {
+ renderTags({ tags: [], knownTags: ['dev'] })
+ await page.getByRole('button', { name: 'Tag' }).click()
+
+ await expect.element(page.getByPlaceholder('Search')).toBeVisible()
+ })
})
- describe('create form validation', () => {
+ describe('create form', () => {
it('blocks an invalid name and surfaces the reason; a valid name is color-encoded', async () => {
- const { patchPipeline } = renderTags({ tags: [] })
+ const { patchPipeline } = renderTags({ tags: [], knownTags: [] })
+ // Empty knownTags opens create directly — no "Create a new tag" list click.
await page.getByRole('button', { name: 'Tag' }).click()
- await page.getByRole('button', { name: 'Create a new tag' }).click()
const nameInput = page.getByPlaceholder('Tag name')
const createButton = page.getByRole('button', { name: 'Create' })
@@ -117,5 +134,61 @@ describe('Tags.svelte', () => {
tags: ['qa|ef4444']
})
})
+
+ it('submits the create form when Enter is pressed in the name field', async () => {
+ const { patchPipeline } = renderTags({ tags: [], knownTags: [] })
+ await page.getByRole('button', { name: 'Tag' }).click()
+
+ const nameInput = page.getByPlaceholder('Tag name')
+ await nameInput.fill('qa')
+ // `fill` leaves the input focused; Enter submits the surrounding