-
{{ activeCard.title }}
-
{{ activeCard.subtitle }}
+
+
+ {{ activeCard?.title }}
+
+
+
![]()
+
+
{{ activeCard.subtitle }}
-
-
-
-
Description
-
{{ activeCard.description }}
-
-
-
-
Details
-
-
-
- {{ d.label }}
- - {{ d.value }}
-
-
-
-
-
-
- {{ a.label }}
-
+
+
+
+
Description
+
{{ activeCard.description }}
+
+
+
+
Details
+
+
+
- {{ d.label }}
+ - {{ d.value }}
+
+
+
+
+
-
+
@@ -243,55 +234,6 @@
color: var(--gn-color-text-dark);
}
-.card-modal-overlay {
- position: fixed;
- inset: 0;
- z-index: 1000;
- background: rgba(0, 0, 0, 0.6);
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 16px;
-}
-
-.card-modal {
- position: relative;
- width: 100%;
- max-width: 560px;
- max-height: 90vh;
- background: var(--gn-surface-panel);
- border: 1px solid var(--gn-border-color-muted);
- overflow: hidden;
- display: flex;
- flex-direction: column;
-}
-
-.card-modal-close {
- position: absolute;
- top: 12px;
- right: 12px;
- width: 32px;
- height: 32px;
- display: flex;
- align-items: center;
- justify-content: center;
- background: color-mix(in srgb, var(--gn-color-grey) 12%, var(--gn-surface-panel));
- border: 1px solid var(--gn-border-color-muted);
- color: var(--gn-color-text-light);
- cursor: pointer;
- z-index: 2;
-}
-
-.card-modal-close:hover {
- border-color: var(--gn-color-secondary);
- color: var(--gn-color-secondary);
-}
-
-.card-modal-scroll {
- overflow-y: auto;
- max-height: 90vh;
-}
-
.card-modal-image {
width: 100%;
max-height: 320px;
@@ -308,9 +250,10 @@
.card-modal-title {
margin: 0;
- font-size: 1.3rem;
+ font-size: 1.15rem;
font-weight: 600;
color: var(--gn-color-text-light);
+ text-transform: none;
}
.card-modal-subtitle {
diff --git a/webclient/src/styles/app.scss b/webclient/src/styles/app.scss
index 4ac998b..5bc7e9e 100644
--- a/webclient/src/styles/app.scss
+++ b/webclient/src/styles/app.scss
@@ -1502,15 +1502,14 @@
img { width: 64px; height: 64px; }
h1 {
- font-size: 32px;
- font-weight: 700;
- letter-spacing: -0.5px;
+ font-size: 30px; // kit h1 (typography tokens are not exported by kit-deps)
+ font-weight: 600;
color: $color-text-light;
margin: 0;
}
p {
- font-size: 15px;
+ font-size: var(--gn-font-size-base);
color: $color-text-medium;
margin: 0;
}
@@ -1556,6 +1555,7 @@
padding: $space-md;
background: $surface-panel-muted;
border: $border-width-base $border-style-base $border-color-muted;
+ border-radius: $border-radius-md;
cursor: pointer;
transition: border-color $motion-fast $motion-ease, background $motion-fast $motion-ease;
width: 160px;
@@ -1570,11 +1570,6 @@
border-color: $color-secondary;
}
- .profile-icon {
- font-size: $icon-size-xl;
- color: $color-secondary;
- }
-
.profile-name {
font-size: 14px;
font-weight: 600;
@@ -1592,7 +1587,6 @@
padding: 10px;
gap: 6px;
- .profile-icon { font-size: 22px; }
.profile-name { font-size: 13px; }
.profile-desc {
font-size: 11px;
@@ -1605,25 +1599,13 @@
}
// ─── Empty state ───────────────────────────────────────────────────────────
+// Centers the GnEmptyState card inside the chat area.
.empty-chat {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
- gap: $space-md;
- color: $color-text-dark;
- padding: $space-xl;
-
- .empty-icon {
- font-size: $icon-size-display;
- opacity: 0.4;
- }
-
- p {
- font-size: 15px;
- margin: 0;
- }
}
// ─── Spinner ───────────────────────────────────────────────────────────────
diff --git a/webclient/tests/unit/components/ui/CardGrid.test.js b/webclient/tests/unit/components/ui/CardGrid.test.js
index ce00beb..af69c59 100644
--- a/webclient/tests/unit/components/ui/CardGrid.test.js
+++ b/webclient/tests/unit/components/ui/CardGrid.test.js
@@ -1,6 +1,7 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount } from '@vue/test-utils'
import { nextTick } from 'vue'
+import { GnexusUiVue } from 'gnexus-ui-kit/vue'
import CardGrid from '@/components/ui/CardGrid.vue'
describe('CardGrid', () => {
@@ -56,9 +57,12 @@
})
it('opens modal on card click', async () => {
- const wrapper = mount(CardGrid, { props: { data: sample } })
+ const wrapper = mount(CardGrid, { props: { data: sample }, global: { plugins: [GnexusUiVue] } })
const firstCard = wrapper.find('.card-grid-item')
await firstCard.trigger('click')
+ // GnModal renders on the post-flush watcher: parent update -> watcher sets
+ // visible -> modal render (two ticks).
+ await nextTick()
await nextTick()
expect(document.querySelector('.card-modal')).not.toBeNull()
expect(document.querySelector('.card-modal-title')?.textContent).toBe('Card one')