diff --git a/packages/webview/src/component/dashboard/KubernetesProviderCard.spec.ts b/packages/webview/src/component/dashboard/KubernetesProviderCard.spec.ts
new file mode 100644
index 00000000..a49f68ba
--- /dev/null
+++ b/packages/webview/src/component/dashboard/KubernetesProviderCard.spec.ts
@@ -0,0 +1,69 @@
+/**********************************************************************
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ***********************************************************************/
+
+import '@testing-library/jest-dom/vitest';
+
+import { render, screen } from '@testing-library/svelte';
+import { beforeEach, expect, test, vi } from 'vitest';
+import KubernetesProviderCard from '/@/component/dashboard/KubernetesProviderCard.svelte';
+import { RemoteMocks } from '/@/tests/remote-mocks';
+import { API_NAVIGATION } from '@kubernetes-dashboard/channels';
+import type { NavigationApi } from '@kubernetes-dashboard/channels';
+import userEvent from '@testing-library/user-event';
+
+const remoteMocks = new RemoteMocks();
+
+beforeEach(() => {
+ vi.resetAllMocks();
+ remoteMocks.reset();
+
+ remoteMocks.mock(API_NAVIGATION, {
+ navigateToProviderNewConnection: vi.fn(),
+ } as unknown as NavigationApi);
+});
+
+test('should render with all values passed', async () => {
+ render(KubernetesProviderCard, {
+ provider: {
+ id: 'k8s-provider',
+ creationDisplayName: 'Kubernetes Provider',
+ creationButtonTitle: 'Create Kubernetes Provider',
+ emptyConnectionMarkdownDescription: 'Create a new Kubernetes Provider',
+ },
+ });
+ screen.getByText('Kubernetes Provider');
+ screen.getByText('Create Kubernetes Provider');
+ const btn = screen.getByRole('button', { name: 'Create Kubernetes Provider' });
+ expect(btn).toBeEnabled();
+ await userEvent.click(btn);
+ expect(remoteMocks.get(API_NAVIGATION).navigateToProviderNewConnection).toHaveBeenCalledWith('k8s-provider');
+});
+
+test('should render with minimal values passed', async () => {
+ render(KubernetesProviderCard, {
+ provider: {
+ id: 'k8s-provider',
+ },
+ });
+ screen.getByText('Create');
+ screen.getByText('Create new');
+ const btn = screen.getByRole('button', { name: 'Create new' });
+ expect(btn).toBeEnabled();
+ await userEvent.click(btn);
+ expect(remoteMocks.get(API_NAVIGATION).navigateToProviderNewConnection).toHaveBeenCalledWith('k8s-provider');
+});
diff --git a/packages/webview/src/component/dashboard/KubernetesProviderCard.svelte b/packages/webview/src/component/dashboard/KubernetesProviderCard.svelte
new file mode 100644
index 00000000..e77b7db2
--- /dev/null
+++ b/packages/webview/src/component/dashboard/KubernetesProviderCard.svelte
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+ {provider.creationDisplayName ?? 'Create'}
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/webview/src/component/dashboard/NoContextPage.spec.ts b/packages/webview/src/component/dashboard/NoContextPage.spec.ts
new file mode 100644
index 00000000..f6b14618
--- /dev/null
+++ b/packages/webview/src/component/dashboard/NoContextPage.spec.ts
@@ -0,0 +1,118 @@
+/**********************************************************************
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ***********************************************************************/
+
+import '@testing-library/jest-dom/vitest';
+
+import { render, screen } from '@testing-library/svelte';
+import { beforeEach, expect, test, vi } from 'vitest';
+import NoContextPage from './NoContextPage.svelte';
+import { StatesMocks } from '/@/tests/state-mocks';
+import { FakeStateObject } from '/@/state/util/fake-state-object.svelte';
+import type { KubernetesProvidersInfo } from '@kubernetes-dashboard/channels';
+import KubeIcon from '/@/component/icons/KubeIcon.svelte';
+import KubernetesProviderCard from '/@/component/dashboard/KubernetesProviderCard.svelte';
+import type { Unsubscriber } from 'svelte/store';
+
+vi.mock(import('./KubernetesProviderCard.svelte'));
+vi.mock(import('/@/component/icons/KubeIcon.svelte'));
+
+const statesMocks = new StatesMocks();
+let kubernetesProvidersMock: FakeStateObject;
+
+beforeEach(() => {
+ vi.resetAllMocks();
+ statesMocks.reset();
+
+ kubernetesProvidersMock = new FakeStateObject();
+ statesMocks.mock('stateKubernetesProvidersInfoUI', kubernetesProvidersMock);
+});
+
+test('should render the Kubernetes icon', () => {
+ render(NoContextPage);
+ expect(KubeIcon).toHaveBeenCalledWith(expect.anything(), { size: '80' });
+});
+
+test('should render the main heading', () => {
+ render(NoContextPage);
+
+ const heading = screen.getByRole('heading', { level: 1 });
+ expect(heading).toHaveTextContent('No Kubernetes cluster');
+});
+
+test('should render the description text', () => {
+ render(NoContextPage);
+
+ const description = screen.getByText(/A Kubernetes cluster is a group of nodes/);
+ expect(description).toBeInTheDocument();
+ expect(description).toHaveClass('text-[var(--pd-details-empty-sub-header)]', 'text-balance');
+});
+
+test('should render providers when data is available', () => {
+ const mockProviders: KubernetesProvidersInfo = {
+ providers: [
+ {
+ id: 'provider-1',
+ creationDisplayName: 'Provider 1',
+ creationButtonTitle: 'Create Provider 1',
+ emptyConnectionMarkdownDescription: 'Description 1',
+ },
+ {
+ id: 'provider-2',
+ creationDisplayName: 'Provider 2',
+ creationButtonTitle: 'Create Provider 2',
+ emptyConnectionMarkdownDescription: 'Description 2',
+ },
+ ],
+ };
+
+ kubernetesProvidersMock.setData(mockProviders);
+ render(NoContextPage);
+
+ expect(KubernetesProviderCard).toHaveBeenCalledWith(expect.anything(), { provider: mockProviders.providers[0] });
+ expect(KubernetesProviderCard).toHaveBeenCalledWith(expect.anything(), { provider: mockProviders.providers[1] });
+});
+
+test('should handle providers with minimal data', () => {
+ const mockProviders = {
+ providers: [
+ {
+ id: 'minimal-provider',
+ },
+ ],
+ };
+
+ kubernetesProvidersMock.setData(mockProviders);
+ render(NoContextPage);
+
+ expect(KubernetesProviderCard).toHaveBeenCalledWith(expect.anything(), { provider: mockProviders.providers[0] });
+});
+
+test('should call subscribe on mount', () => {
+ render(NoContextPage);
+
+ expect(kubernetesProvidersMock.subscribe).toHaveBeenCalledTimes(1);
+});
+
+test('should call unsubscribe on unmount', () => {
+ const unsubscribeMock: Unsubscriber = vi.fn();
+ vi.mocked(kubernetesProvidersMock.subscribe).mockReturnValue(unsubscribeMock);
+ const component = render(NoContextPage);
+
+ component.unmount();
+ expect(unsubscribeMock).toHaveBeenCalledTimes(1);
+});
diff --git a/packages/webview/src/component/dashboard/NoContextPage.svelte b/packages/webview/src/component/dashboard/NoContextPage.svelte
index 15984556..cfc5c1d4 100644
--- a/packages/webview/src/component/dashboard/NoContextPage.svelte
+++ b/packages/webview/src/component/dashboard/NoContextPage.svelte
@@ -1,16 +1,38 @@
-
+
No Kubernetes cluster
-
+
A Kubernetes cluster is a group of nodes (virtual or physical) that run Kubernetes, a system for automating the
deployment and management of containerized applications.
+
+ {#each kubernetesProviders.data?.providers as provider (provider.id)}
+
+ {/each}
+