| 2026-10-10 |

webclient: the small UI components in en, uk and ru
...
The sixth and last area of the interface translation. The components in
components/ui/ now build their text through t(): the login screen, the welcome
screen, the confirmation dialog, the offline banner, the image lightbox, the
selection toolbar, the card grid and the form, plus the sidebar's close button,
which is one of the strings that moved.
24 new slugs in all three dictionaries, and one moved:
- 24 in ui.* — the login and welcome screens (the heading, the tagline they
both show, the GNEXUS button), the confirmation dialog, the offline banner,
the lightbox (its heading, its close button, the failed-to-load message), the
selection toolbar's Reply and its tooltip, the card grid's three section
headings and its "+{n} more", and the form's submit button, its submitted
note and its ten validation messages;
- common.close, moved out of sidebar.*: the sidebar's close button and the
lightbox's say the same word, so it sits in the vocabulary area now.
Four details worth knowing:
- OfflineBanner's sentence was hard-coded Russian inside an otherwise English
file — for a reader in English or Ukrainian it was the one Russian sentence
in the app. It is a slug now, and the Russian value is that same sentence
verbatim, so nothing changes for the reader who could already read it.
- The form's validation messages interpolate: "{field} is required" carries the
field's own label, and the numeric limits carry {n}. The two length messages
are dictionary plurals now, so English says "Minimum length is 1 character"
where it used to say "1 characters", and Russian and Ukrainian get the three
forms a numeral needs — "1 символ", "2 символа", "5 символов".
- The card grid's "+4 more" is one slug with a count, not a sentence glued
together in the template.
- ui.tagline is written once and read by both the login and the welcome screen,
which show the same words.
The English values are verbatim the literals the code hard-coded, so the
English interface is unchanged and no test needed editing.
Checked live in Chromium against the built bundle on the dev backend, all three
languages: the login screen (reached with no account at all, its language
coming from navi.locale), the offline banner with the context put offline under
it, the selection toolbar over a real selection in a message, and the
confirmation dialog opened from a session row's Delete. Two further passes open
a session whose tool output carries a card grid and one that carries images, for
the card grid's section headings and the lightbox's heading and close button.
The form is the one component no saved session renders — nothing in the dev
database carries a form payload — so its messages were printed through t()
instead, including the plural ones: "Поле «Email» обязательно", "Минимальная
длина — 2 символа", "Мінімальна довжина — 5 символів", "Minimum length is 1
character".
Eugene Sukhodolskiy
committed
1 day ago
|
| 2026-10-09 |

i18n: en/uk/ru, and the interface language of the account
...
The client hard-coded English in every template. It now goes through t() from
src/i18n/ — a locale ref, {param} interpolation, plural dictionaries driven by
n, and flat per-area dictionaries in src/i18n/messages/ carrying the same slugs
in all three languages. vue-i18n is deliberately not pulled in: the platform
handbook rules it out, and what it would buy — plural forms, a reactive locale,
an English fallback — is about eighty lines here. A slug nobody carries falls
back to English, so a screen already translated and one still speaking
hard-coded English can coexist while the work goes area by area.
The language comes from locale_effective in GET /auth/me: the choice made in
Settings (navi_users.locale_override, a new column) over the gnexus-auth
account locale (navi_users.locale, a straight mirror the user.profile_updated
webhook keeps writing — the override sits in its own column precisely so that
mirror cannot wipe it), over en. PATCH /auth/me writes the override, and null
means "follow the account" again. With NAVI_AUTH_ENABLED=false there is no
account to follow, so the choice is kept in localStorage under navi.locale.
The picker is the first block of Settings → Account. Each language is named in
its own language, which is why those three strings are identical in all three
dictionaries. Lists of labels are computed rather than module-level constants:
one built at import would keep the language that was active then and ignore a
switch.
Checked in Chromium against the built bundle: choosing Русский rewrites
<html lang> and the document title, survives a reload, and Auto brings the
account's own language back.
Eugene Sukhodolskiy
committed
1 day ago
|
| 2026-10-06 |
webclient: revert LoginScreen to the custom card
...
The kit login-card markup read heavier (uppercase header, wide chrome
border) than the original centered card — restoring the previous
version per user preference.
Eugene Sukhodolskiy
committed
4 days ago
|
webclient: LoginScreen rebuilt on kit markup
...
The SSO-only login doesn't fit GnLoginCard's username/password form (the
adapter always renders both fields), so the escape-hatch card is replaced
with the kit's own login-card markup (article.card.login-card + header +
card-content + GnButton) — the same contract kit.css ships for
GnLoginCard, minus the form. Custom card border/title/subtitle styles are
gone; overlay keeps positioning only.
Eugene Sukhodolskiy
committed
4 days ago
|
| 2026-10-05 |

webclient: retokenize styles onto gn-ui-kit v1.0 CSS variables
...
All ~165 legacy var() usages (--color-*, --surface*, --accent*, --border,
--text*) with hex fallbacks and ~150 raw hex literals across app.scss and
24 scoped style blocks are swapped to the kit's --gn-* tokens per the
intent of the old fallback values:
- accent/primary/teal (#7aa2f7/#4ec9b0) -> --gn-color-secondary
- amber/orange highlights -> --gn-color-accent
- text greys -> --gn-color-text-{light,medium,dark}
- panels -> --gn-surface-panel; elevated tints -> color-mix over panel
- translucent overlays -> color-mix(in srgb, ..., transparent)
Deliberately literal: terminal deep bg #0f0f14 (darker than any token)
and the content-card image badge teal #89dceb (kit has no teal). File
type badges keep a categorical palette via nearest kit tokens.
Dead "UI kit overrides" block halved: kit 1.0 dropped hover icon
rotation, so only the app-owned chevron open-state flip remains.
Verified: vitest 111 passed, build OK, dev render matches W1 baseline
Eugene Sukhodolskiy
committed
5 days ago
|
| 2026-05-12 |
Rename login button text from gnexus-auth to GNEXUS.
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 12 May
|
Fix Phosphor icon class on GnButton/GnIconButton usages.
...
gnexus-ui-kit's iconNode() does not prepend the base `ph` class
when the icon string starts with `ph-`; it only keeps the string
as-is. All icon props must include the base class explicitly:
`icon="ph ph-sidebar"` instead of `icon="ph-sidebar"`.
Updated 15 icon bindings across 9 components.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 12 May
|
Wire gnexus-ui-kit v0.2.0 Vue 3 adapter and migrate Wave 1 components.
...
- Update vendor/gnexus-ui-kit to v0.2.0 (Vue components + composables)
- Add Vite aliases for gnexus-ui-kit/vue and gnexus-ui-kit/css
- Install GnexusUiVue plugin in main.js + GnToastProvider in App.vue
- Migrate ProfileBadge → GnBadge
- Migrate ErrorMessage → GnAlert
- Migrate ConfirmDialog → GnConfirmDialog
- Migrate raw <button> elements → GnButton / GnIconButton in:
WelcomeScreen, LoginScreen, ChatArea, ChatHeader, AppSidebar,
ArtifactsPanel, UserMessage, AssistantMessage, SelectionToolbar
Build and tests pass (51/51).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 12 May
|
| 2026-05-04 |
Dark login screen: #111 overlay, transparent card
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 4 May
|
Add full-screen login overlay for unauthenticated users
...
- Backend: new endpoint GET /auth/status returns {configured: bool}
- Webclient auth store: add authConfigured ref + fetchStatus()
- LoginScreen.vue: centered card with logo, title, and login button
- App.vue: show LoginScreen overlay when auth is configured but
user is not authenticated (z-index 9999, blocks all UI)
- App.vue onMounted: fetch auth status before trying to resolve user
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 4 May
|