diff --git a/apps/backend/API_DOCUMENT.md b/apps/backend/API_DOCUMENT.md index 448cb3d..204b55a 100644 --- a/apps/backend/API_DOCUMENT.md +++ b/apps/backend/API_DOCUMENT.md @@ -3,6 +3,11 @@ ## Overview This service is a Hono API backed by Supabase. +UI note (2026-03): +- Frontend navigation/settings were consolidated into a header User Profile Menu. +- Theme and language are stored client-side (`localStorage`) and do not introduce new backend endpoints. +- Existing auth/item routes remain unchanged. + Base URL example: - http://localhost:10000 diff --git a/apps/desktop/API_DOCUMENT.md b/apps/desktop/API_DOCUMENT.md index e9218df..03762f9 100644 --- a/apps/desktop/API_DOCUMENT.md +++ b/apps/desktop/API_DOCUMENT.md @@ -3,6 +3,11 @@ ## Overview Desktop exposes Rust commands via Tauri invoke. +UI note (2026-03): +- Frontend navigation/settings now use a header User Profile Menu. +- Theme (`light`/`dark`) and language (`en`/`ja`) are local UI preferences persisted in frontend `localStorage`. +- No new Tauri command was added for these settings; command surface below is unchanged. + Frontend command call style: - invoke("command_name", payload) diff --git a/apps/frontend/ARCHITECTURE.md b/apps/frontend/ARCHITECTURE.md index abbc5c3..c52e8cc 100644 --- a/apps/frontend/ARCHITECTURE.md +++ b/apps/frontend/ARCHITECTURE.md @@ -21,6 +21,9 @@ The architecture separates responsibilities into: - Pinia-safe token injection into `HonoClient` via deferred token getter from `main.ts`. - Strong alignment with backend contract fields (`snake_case` item properties like `duration_minutes`, `sync_status`). - Frontend-only guest login: `useAuth` can create a transient guest identity (`isGuest`) without writing auth data to backend. +- Global UI settings via `useSettings`: theme (`light`/`dark`) and language (`en`/`ja`) are shared through a composable singleton and persisted in `localStorage`. +- Header profile consolidation: logout, theme switch, language switch, and sync status are grouped into a single avatar-triggered User Profile Menu. +- i18n foundation: user-facing text in main shell screens is resolved through `t(key)` translation mapping for incremental expansion. - Guest-mode item handling in `useItems`: item CRUD runs in memory only, marks items as `local_only`, and skips sync/network calls. - **Guest seed data**: When guest mode is activated, `useItems` automatically populates the in-memory items array with 5 sample tasks showcasing varied statuses (backlog, todo, inprogress, done) and different Motivation/Duration values to demonstrate the ScatterPlot's visualization capabilities. - **Automated 30-second sync**: Background interval timer synchronizes items automatically when authenticated, with in-flight guard to prevent concurrent syncs. @@ -81,6 +84,13 @@ The architecture separates responsibilities into: 2. Factory returns Tauri or Hono implementation. 3. In Hono mode, `honoClient` attaches bearer token via injected token getter. +### UI settings and localization flow +1. `main.ts` initializes `useSettings().initializeSettings()` before mount. +2. Saved `theme` and `language` are restored from `localStorage`. +3. Theme toggles add/remove `.dark` on the root `html` element. +4. Shared UI strings call `t(key)` and resolve from the active language dictionary. +5. Header User Profile Menu is the single entry point for theme/language toggles, sync indicator, and logout. + ## API Mode Rules (`src/api/config.ts`) Mode selection priority: 1. If Tauri runtime is detected (`window.__TAURI__` or `window.__TAURI_INTERNALS__`), use `tauri`. @@ -119,6 +129,7 @@ apps/frontend/ │ │ ├── useAuth.ts │ │ ├── useGraph.ts │ │ ├── useItems.ts +│ │ ├── useSettings.ts │ │ └── useSyncStatus.ts │ ├── layouts/ │ ├── stores/ diff --git a/apps/frontend/README.md b/apps/frontend/README.md index 6d7f41d..b1c8665 100644 --- a/apps/frontend/README.md +++ b/apps/frontend/README.md @@ -4,6 +4,14 @@ This template should help get you started developing with Vue 3 and TypeScript i Learn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup). +## Recent UI Updates + +- ScatterPlot theme sync now repaints after `nextTick()` on theme changes to avoid dark/light transition lag. +- Canvas background and grid lines now map directly from `useSettings.theme` for stable first-frame rendering. +- Task list status pills use shared CSS variables for instant light/dark readability. +- Special Thanks modal labels are now routed through the i18n `t()` helper. +- Brand badge background remains controlled by `--badge-bg` (kept white in both themes). + ## Directory 以下はGitHub Actionsによって、pushごとに最新のツリーに入れ替わります。 タグを編集しないでください。 diff --git a/apps/frontend/src/components/GraphControl.vue b/apps/frontend/src/components/GraphControl.vue index c947114..7c9c7ee 100644 --- a/apps/frontend/src/components/GraphControl.vue +++ b/apps/frontend/src/components/GraphControl.vue @@ -1,5 +1,8 @@ @@ -26,28 +27,28 @@ const emit = defineEmits<{
- +
- +
- +
- + @@ -55,19 +56,8 @@ const emit = defineEmits<{
- - - - - - + +
@@ -76,8 +66,8 @@ const emit = defineEmits<{ .controls-bar { margin-top: 0.75rem; border-radius: 1rem; - border: 1px solid rgba(226, 232, 240, 0.8); - background-color: rgba(255, 255, 255, 0.9); + border: 1px solid var(--tg-border-muted); + background-color: var(--tg-surface-translucent); padding: 0.625rem 1rem; display: flex; flex-wrap: wrap; @@ -105,16 +95,17 @@ const emit = defineEmits<{ font-weight: 600; text-transform: uppercase; letter-spacing: 0.18em; - color: #94a3b8; + color: var(--text-muted); margin-bottom: 2px; } .input-group select { border-radius: 0.5rem; - border: 1px solid #cbd5e1; - background-color: #fff; + border: 1px solid var(--tg-border-default); + background-color: var(--bg-primary); padding: 0.375rem 0.75rem; font-size: 0.875rem; + color: var(--text-primary); outline: none; cursor: pointer; } @@ -125,45 +116,35 @@ const emit = defineEmits<{ align-items: center; } -.flex-btn { - display: inline-flex; - align-items: center; - gap: 0.4rem; -} - -.icon { - width: 14px; - height: 14px; -} - .primary-btn { - background-color: #2563eb; + background: linear-gradient(135deg, #ef4444 0%, #a855f7 50%, #3b82f6 100%); color: #fff; border: none; padding: 0.375rem 0.75rem; border-radius: 0.5rem; - font-weight: 500; + font-weight: 600; cursor: pointer; - transition: background-color 0.2s; + transition: transform 0.2s ease, filter 0.2s ease; } .primary-btn:hover { - background-color: #1d4ed8; + transform: translateY(-1px); + filter: brightness(1.06); } .secondary-btn { - background-color: #fff; - border: 1px solid #cbd5e1; + background-color: var(--bg-primary); + border: 1px solid var(--tg-border-default); padding: 0.375rem 0.75rem; border-radius: 0.5rem; - color: #334155; + color: var(--text-primary); font-size: 0.875rem; cursor: pointer; transition: all 0.2s; } .secondary-btn:hover { - background-color: #f8fafc; - border-color: #94a3b8; + background-color: var(--bg-secondary); + border-color: var(--tg-border-strong); } \ No newline at end of file diff --git a/apps/frontend/src/components/Header.vue b/apps/frontend/src/components/Header.vue index 92ebc2b..e8d7e8f 100644 --- a/apps/frontend/src/components/Header.vue +++ b/apps/frontend/src/components/Header.vue @@ -1,5 +1,8 @@