From 3dadc84179b46a3856e0800e89ab5bc688201fca Mon Sep 17 00:00:00 2001 From: pa Date: Mon, 9 Mar 2026 16:28:05 +0900 Subject: [PATCH] refactor css and add UI Standards class --- src/App.vue | 1 - src/app.css | 32 ---- src/styles/fonts.css | 36 +++++ src/styles/globals.css | 138 ++++++++++-------- src/views/Favorites/FavoritesAvatar.vue | 12 +- src/views/Favorites/FavoritesFriend.vue | 8 +- src/views/Favorites/FavoritesWorld.vue | 10 +- .../Favorites/components/favorites-card.css | 2 +- src/views/Favorites/favorites-layout.css | 2 +- .../components/FriendsLocationsCard.vue | 11 +- .../MyAvatars/components/MyAvatarCard.vue | 2 +- src/views/Tools/Tools.vue | 8 +- .../components/GroupCalendarEventCard.vue | 8 +- 13 files changed, 141 insertions(+), 129 deletions(-) delete mode 100644 src/app.css diff --git a/src/App.vue b/src/App.vue index b63883ca..a8e2cf09 100644 --- a/src/App.vue +++ b/src/App.vue @@ -34,7 +34,6 @@ import VRCXUpdateDialog from './components/dialogs/VRCXUpdateDialog.vue'; import '@/styles/globals.css'; - import '@/app.css'; console.log(`isLinux: ${LINUX}`); diff --git a/src/app.css b/src/app.css deleted file mode 100644 index 640e908e..00000000 --- a/src/app.css +++ /dev/null @@ -1,32 +0,0 @@ -html { - overflow: hidden; -} - -.lucide.is-loading { - animation: rotating 2s linear infinite; -} - -.x-container { - position: relative; - padding: 8px; - overflow: hidden auto; - box-sizing: border-box; - min-width: 0; - background: var(--background); - height: calc(100% - 20px); - margin: 8px 0 8px 0; - border-radius: var(--radius); - border: 1px solid var(--border); -} - -.aside-collapsed .x-container { - margin-right: 8px; -} - -html.dark .x-container { - background: var(--sidebar); -} - -[data-sonner-toast] [data-content] [data-description] { - white-space: pre-line; -} diff --git a/src/styles/fonts.css b/src/styles/fonts.css index a24560de..a3d5b71f 100644 --- a/src/styles/fonts.css +++ b/src/styles/fonts.css @@ -10,3 +10,39 @@ src: local('Times New Roman'); unicode-range: U+2026; } + +:root { + --font-western-primary: 'Inter Variable'; + --font-western: + 'ellipsis-font', -apple-system, var(--font-western-primary), 'Segoe UI', + 'Roboto', 'Ubuntu', 'Cantarell', 'DejaVu Sans', sans-serif; + --font-symbol: 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; + --font-fallback-cjk: sans-serif; + --font-primary-cjk: + 'Noto Sans JP Variable', 'Noto Sans SC Variable', + 'Noto Sans KR Variable', 'Noto Sans TC Variable'; +} + +:root[lang='zh-CN'] { + --font-primary-cjk: + 'Noto Sans SC Variable', 'Noto Sans JP Variable', + 'Noto Sans KR Variable', 'Noto Sans TC Variable'; +} + +:root[lang='ja'] { + --font-primary-cjk: + 'Noto Sans JP Variable', 'Noto Sans KR Variable', + 'Noto Sans TC Variable', 'Noto Sans SC Variable'; +} + +:root[lang='ko'] { + --font-primary-cjk: + 'Noto Sans KR Variable', 'Noto Sans JP Variable', + 'Noto Sans TC Variable', 'Noto Sans SC Variable'; +} + +:root[lang='zh-TW'] { + --font-primary-cjk: + 'Noto Sans TC Variable', 'Noto Sans JP Variable', + 'Noto Sans KR Variable', 'Noto Sans SC Variable'; +} diff --git a/src/styles/globals.css b/src/styles/globals.css index baa05683..f9299d4b 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -16,30 +16,6 @@ @custom-variant dark (&:is(.dark *)); -:root[lang='zh-CN'] { - --font-primary-cjk: - 'Noto Sans SC Variable', 'Noto Sans JP Variable', - 'Noto Sans KR Variable', 'Noto Sans TC Variable'; -} - -:root[lang='ja'] { - --font-primary-cjk: - 'Noto Sans JP Variable', 'Noto Sans KR Variable', - 'Noto Sans TC Variable', 'Noto Sans SC Variable'; -} - -:root[lang='ko'] { - --font-primary-cjk: - 'Noto Sans KR Variable', 'Noto Sans JP Variable', - 'Noto Sans TC Variable', 'Noto Sans SC Variable'; -} - -:root[lang='zh-TW'] { - --font-primary-cjk: - 'Noto Sans TC Variable', 'Noto Sans JP Variable', - 'Noto Sans KR Variable', 'Noto Sans SC Variable'; -} - :root { --background: oklch(1 0 0); --foreground: oklch(0.145 0 0); @@ -95,16 +71,6 @@ --visibility-public: #22c55e; --visibility-friends: #0ea5e9; --visibility-private: #ef4444; - - --font-western-primary: 'Inter Variable'; - --font-western: - 'ellipsis-font', -apple-system, var(--font-western-primary), 'Segoe UI', - 'Roboto', 'Ubuntu', 'Cantarell', 'DejaVu Sans', sans-serif; - --font-symbol: 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; - --font-fallback-cjk: sans-serif; - --font-primary-cjk: - 'Noto Sans JP Variable', 'Noto Sans SC Variable', - 'Noto Sans KR Variable', 'Noto Sans TC Variable'; } .dark { @@ -202,19 +168,51 @@ --color-visibility-private: var(--visibility-private); } -@layer base { - * { - @apply border-border outline-ring/50; - scrollbar-width: thin; - scrollbar-color: var(--border) transparent; - } - body { - @apply bg-background text-foreground; - font-family: - var(--font-western), var(--font-symbol), var(--font-primary-cjk), - var(--font-fallback-cjk); - margin: 0; - } +html { + overflow: hidden; +} + +.lucide.is-loading { + animation: rotating 2s linear infinite; +} + +.x-container { + position: relative; + padding: 8px; + overflow: hidden auto; + box-sizing: border-box; + min-width: 0; + background: var(--background); + height: calc(100% - 20px); + margin: 8px 0 8px 0; + border-radius: var(--radius); + border: 1px solid var(--border); +} + +.aside-collapsed .x-container { + margin-right: 8px; +} + +html.dark .x-container { + background: var(--sidebar); +} + +[data-sonner-toast] [data-content] [data-description] { + white-space: pre-line; +} + +* { + @apply border-border outline-ring/50; + scrollbar-width: thin; + scrollbar-color: var(--border) transparent; +} + +body { + @apply bg-background text-foreground; + font-family: + var(--font-western), var(--font-symbol), var(--font-primary-cjk), + var(--font-fallback-cjk); + margin: 0; } ::-webkit-scrollbar { @@ -233,17 +231,15 @@ background-clip: content-box; } -@layer utilities { - .scrollbar-hidden { - scrollbar-width: none; - -ms-overflow-style: none; - } +.scrollbar-hidden { + scrollbar-width: none; + -ms-overflow-style: none; +} - .scrollbar-hidden::-webkit-scrollbar { - width: 0; - height: 0; - display: none; - } +.scrollbar-hidden::-webkit-scrollbar { + width: 0; + height: 0; + display: none; } [data-slot='table-header'], @@ -255,3 +251,31 @@ width: 1em; height: 1em; } + +/* ========================================================================== + * VRCX UI Standards + * These are project-wide conventions. + * Use them when building new components. + * ==========================================================================*/ + +/* Hover Transitions + * Smooth hover state changes to avoid harsh flickering. + * x-hover-card — Cards & panels (0.2s, bg + shadow) + * x-hover-list — List items (0.15s, bg). Skip for high-density lists (e.g. friend sidebar). + * x-hover-icon — Icon buttons (0.1s, bg + color) + */ +.x-hover-card { + transition: + background-color 0.2s ease, + box-shadow 0.2s ease; +} + +.x-hover-list { + transition: background-color 0.15s ease; +} + +.x-hover-icon { + transition: + background-color 0.1s ease, + color 0.1s ease; +} diff --git a/src/views/Favorites/FavoritesAvatar.vue b/src/views/Favorites/FavoritesAvatar.vue index 2a655c69..9a8ae755 100644 --- a/src/views/Favorites/FavoritesAvatar.vue +++ b/src/views/Favorites/FavoritesAvatar.vue @@ -51,7 +51,7 @@ v-for="group in favoriteAvatarGroups" :key="group.key" :class="[ - 'group-item hover:shadow-sm', + 'group-item x-hover-card hover:shadow-sm', `group-item--${group.visibility}`, { 'is-active': !hasSearchInput && isGroupActive('remote', group.key) } ]" @@ -123,7 +123,7 @@ v-for="group in avatarGroupPlaceholders" :key="group.key" :class="[ - 'group-item hover:shadow-sm', + 'group-item x-hover-card hover:shadow-sm', 'pointer-events-none opacity-70', { 'is-active': !hasSearchInput && isGroupActive('remote', group.key) } ]"> @@ -162,7 +162,7 @@ v-for="group in localAvatarFavoriteGroups" :key="group" :class="[ - 'group-item hover:shadow-sm', + 'group-item x-hover-card hover:shadow-sm', { 'is-active': !hasSearchInput && isGroupActive('local', group) } ]" @click="handleGroupClick('local', group)"> @@ -211,7 +211,7 @@ :content="t('view.favorite.avatars.local_favorites')">
@@ -314,7 +314,7 @@
@@ -184,7 +184,7 @@
{{ t('view.favorite.worlds.new_group') }} @@ -289,7 +289,7 @@
diff --git a/src/views/Favorites/FavoritesWorld.vue b/src/views/Favorites/FavoritesWorld.vue index 4c6c2e47..34c9c38e 100644 --- a/src/views/Favorites/FavoritesWorld.vue +++ b/src/views/Favorites/FavoritesWorld.vue @@ -51,7 +51,7 @@ v-for="group in favoriteWorldGroups" :key="group.key" :class="[ - 'group-item hover:shadow-sm', + 'group-item x-hover-card hover:shadow-sm', `group-item--${group.visibility}`, { 'is-active': !hasSearchInput && isGroupActive('remote', group.key) } ]" @@ -123,7 +123,7 @@ v-for="group in worldGroupPlaceholders" :key="group.key" :class="[ - 'group-item hover:shadow-sm', + 'group-item x-hover-card hover:shadow-sm', 'pointer-events-none opacity-70', { 'is-active': !hasSearchInput && isGroupActive('remote', group.key) } ]"> @@ -160,7 +160,7 @@ v-for="group in localWorldFavoriteGroups" :key="group" :class="[ - 'group-item hover:shadow-sm', + 'group-item x-hover-card hover:shadow-sm', { 'is-active': !hasSearchInput && isGroupActive('local', group) } ]" @click="handleGroupClick('local', group)"> @@ -204,7 +204,7 @@
{{ t('view.favorite.worlds.new_group') }} @@ -262,7 +262,7 @@
- +
{{ t('view.tools.pictures.header') }}
- +
@@ -554,18 +554,12 @@ } .tool-card { - transition: background-color 0.15s ease; position: relative; overflow: visible; border-radius: var(--radius-lg); cursor: pointer; width: 100%; - &:hover { - background-color: var(--accent); - box-shadow: var(--shadow-sm); - } - .tool-content { display: flex; align-items: center; diff --git a/src/views/Tools/components/GroupCalendarEventCard.vue b/src/views/Tools/components/GroupCalendarEventCard.vue index cb21b521..491ce594 100644 --- a/src/views/Tools/components/GroupCalendarEventCard.vue +++ b/src/views/Tools/components/GroupCalendarEventCard.vue @@ -2,7 +2,7 @@ @@ -275,18 +275,12 @@