From 13b072adf36574dbff0feabc5911dfee68d040ee Mon Sep 17 00:00:00 2001 From: chennan Date: Tue, 31 Mar 2026 11:10:33 +0800 Subject: [PATCH 01/29] sv --- docs/develop/tailwind-css-migration.md | 509 ++++++++++++++++++ spx-gui/.vscode/extensions.json | 5 +- spx-gui/AGENTS.md | 26 + spx-gui/package-lock.json | 394 +++++++++++++- spx-gui/package.json | 2 + spx-gui/src/App.vue | 4 - spx-gui/src/app.css | 243 +++++++++ .../src/components/common/RouterUILink.vue | 18 +- .../components/community/CenteredWrapper.vue | 40 +- .../components/community/CommunityCard.vue | 3 +- .../components/community/CommunityHeader.vue | 37 +- .../components/community/ProjectsSection.vue | 83 +-- .../community/user/sidebar/UserSidebar.vue | 21 +- .../user/sidebar/UserSidebarItem.vue | 73 +-- .../code-editor/spx-code-editor/CodeLink.vue | 10 +- .../ui/completion/CompletionItem.vue | 47 +- .../editor/map-editor/MapEditor.vue | 69 +-- .../src/components/navbar/NavbarWrapper.vue | 68 +-- .../src/components/project/ProjectItem.vue | 192 +------ .../components/tutorials/CourseSeriesItem.vue | 54 +- .../components/tutorials/TutorialsBanner.vue | 67 +-- spx-gui/src/components/ui/UILink.vue | 26 +- spx-gui/src/components/ui/global.css | 18 + spx-gui/src/components/ui/global.scss | 16 - spx-gui/src/components/ui/link.scss | 24 - spx-gui/src/components/ui/responsive.scss | 22 - spx-gui/src/components/ui/responsive.ts | 2 +- spx-gui/src/main.ts | 1 + spx-gui/src/pages/404/index.vue | 44 +- spx-gui/src/pages/community/explore.vue | 21 +- spx-gui/src/pages/community/home.vue | 14 +- spx-gui/src/pages/community/index.vue | 13 +- spx-gui/src/pages/sign-in/callback.vue | 10 +- spx-gui/src/pages/sign-in/token.vue | 43 +- spx-gui/src/pages/tutorials/course-start.vue | 12 +- spx-gui/src/pages/tutorials/index.vue | 38 +- spx-gui/src/utils/utils.scss | 5 - spx-gui/vercel-output-plugin.ts | 2 +- spx-gui/vite.config.ts | 2 + 39 files changed, 1389 insertions(+), 889 deletions(-) create mode 100644 docs/develop/tailwind-css-migration.md create mode 100644 spx-gui/src/app.css create mode 100644 spx-gui/src/components/ui/global.css delete mode 100644 spx-gui/src/components/ui/global.scss delete mode 100644 spx-gui/src/components/ui/link.scss delete mode 100644 spx-gui/src/components/ui/responsive.scss delete mode 100644 spx-gui/src/utils/utils.scss diff --git a/docs/develop/tailwind-css-migration.md b/docs/develop/tailwind-css-migration.md new file mode 100644 index 000000000..464e56a03 --- /dev/null +++ b/docs/develop/tailwind-css-migration.md @@ -0,0 +1,509 @@ +# Tailwind CSS Migration Assessment for spx-gui + +This document investigates whether XBuilder frontend styling in `spx-gui` should migrate to Tailwind CSS. + +Issue: `goplus/builder#2981` + +## Conclusion + +Tailwind CSS is technically feasible in `spx-gui`, but a full migration is not a good near-term tradeoff. + +The current frontend already has a working design-token layer, a custom UI component library, and deep integration with Naive UI theme overrides. Because of that, Tailwind would mainly change the authoring model for layout and simple component styling. It would not replace major parts of the existing styling system unless the project also commits to a broader UI-layer refactor. + +The recommended direction is an incremental hybrid approach: + +- keep the existing `--ui-*` design tokens and Naive UI theme layer +- add Tailwind only as an optional utility layer +- validate it on a small set of low-risk pages or self-contained components first +- only expand usage if the pilot materially improves development speed and code review quality + +## Current Target + +The current target is not "remove all SCSS from the repo". + +The near-term goal is more specific: + +- in business code outside `src/components/ui/`, use Tailwind as the default styling tool for local layout and surface styling +- if business code still needs local authored styles, prefer plain CSS over SCSS +- remove business-code imports of SCSS helpers from `src/components/ui/` +- remove remaining SCSS files outside `src/components/ui/` as part of this phase +- keep the existing design-system layer in `src/components/ui/` as the source of truth for tokens and Naive UI integration +- allow `src/components/ui/` to keep local SCSS for now when that remains the clearest implementation + +This means the project is pursuing two related but different directions: + +- business code should move toward Tailwind-first plus plain CSS fallback, with SCSS being removed from that layer in this phase +- the component-library layer should move more cautiously, with looser short-term requirements on SCSS removal + +## Current Styling Architecture + +The current frontend styling model is centered around Vue SFC local styles plus shared CSS variables, with Tailwind now added as an optional utility layer. + +- `spx-gui` uses Vite + Vue 3, includes both Tailwind and Sass tooling in [spx-gui/package.json](../../spx-gui/package.json) +- the app loads global styling through [spx-gui/src/main.ts](../../spx-gui/src/main.ts) and [spx-gui/src/app.css](../../spx-gui/src/app.css), which imports [spx-gui/src/components/ui/global.css](../../spx-gui/src/components/ui/global.css) +- design tokens are defined in TypeScript under [spx-gui/src/components/ui/tokens/index.ts](../../spx-gui/src/components/ui/tokens/index.ts) and related files +- the token objects are converted into `--ui-*` CSS variables and injected globally by [spx-gui/src/components/ui/UIConfigProvider.vue](../../spx-gui/src/components/ui/UIConfigProvider.vue) +- Naive UI theme overrides are also defined in [spx-gui/src/components/ui/UIConfigProvider.vue](../../spx-gui/src/components/ui/UIConfigProvider.vue), so the token system serves both custom CSS and third-party components +- most component styles live inside local ` diff --git a/spx-gui/src/app.css b/spx-gui/src/app.css new file mode 100644 index 000000000..6cdbf4247 --- /dev/null +++ b/spx-gui/src/app.css @@ -0,0 +1,243 @@ +@import "./components/ui/global.css"; +@import "tailwindcss"; + +@source "./**/*.{vue,ts,tsx,js,jsx,html}"; + +/* + * Shared UILink component variants. + * + * These classes mirror the public variants used by src/components/ui/UILink.vue. + * Keep the interaction states aligned, but do not treat this file as the source of truth + * for the component implementation under src/components/ui/. + */ +@layer components { + .link-primary { + transition: color 0.1s; + color: var(--ui-color-primary-main); + text-decoration: none; + + &:hover { + color: var(--ui-color-primary-400); + } + + &:active { + color: var(--ui-color-primary-600); + } + } + + .link-boring { + transition: color 0.1s; + color: inherit; + + &:hover { + color: var(--ui-color-primary-main); + } + + &:active { + color: var(--ui-color-primary-600); + } + } +} + +/* + * Tailwind theme bridge for the existing UI token system. + * + * Source of truth: + * - token definitions live in src/components/ui/tokens/ + * - UIConfigProvider exposes them as global --ui-* CSS variables + * + * This file maps those --ui-* variables into Tailwind theme tokens so template + * utilities can use semantic classes such as text-text and bg-primary-100. + */ +@theme { + /* Keep only the project's breakpoint names to avoid a parallel default scale. */ + --breakpoint-*: initial; + --color-*: initial; + --shadow-*: initial; + --font-*: initial; + --text-*: initial; + --radius-*: initial; + --leading-*: initial; + + /* Mirrors src/components/ui/responsive.ts. */ + --breakpoint-tablet: 48rem; + --breakpoint-desktop: 80rem; + --breakpoint-desktop-large: 105rem; + + /* Product palette and semantic color tokens bridged from global --ui-color-* vars. */ + --color-turquoise-100: var(--ui-color-turquoise-100, #f3fcfd); + --color-turquoise-200: var(--ui-color-turquoise-200, #e7f9fa); + --color-turquoise-300: var(--ui-color-turquoise-300, #b5ebf0); + --color-turquoise-400: var(--ui-color-turquoise-400, #3fcdd9); + --color-turquoise-500: var(--ui-color-turquoise-500, #0bc0cf); + --color-turquoise-600: var(--ui-color-turquoise-600, #0eafbc); + --color-turquoise-700: var(--ui-color-turquoise-700, #0b8893); + --color-turquoise-main: var(--ui-color-turquoise-main, #0bc0cf); + + --color-yellow-100: var(--ui-color-yellow-100, #fffaf5); + --color-yellow-200: var(--ui-color-yellow-200, #fff6eb); + --color-yellow-300: var(--ui-color-yellow-300, #fde2c0); + --color-yellow-400: var(--ui-color-yellow-400, #fbb45d); + --color-yellow-500: var(--ui-color-yellow-500, #faa135); + --color-yellow-600: var(--ui-color-yellow-600, #e49330); + --color-yellow-700: var(--ui-color-yellow-700, #b27226); + --color-yellow-main: var(--ui-color-yellow-main, #faa135); + + --color-purple-100: var(--ui-color-purple-100, #faf8ff); + --color-purple-200: var(--ui-color-purple-200, #f6f1ff); + --color-purple-300: var(--ui-color-purple-300, #e2d4ff); + --color-purple-400: var(--ui-color-purple-400, #b390ff); + --color-purple-500: var(--ui-color-purple-500, #a074ff); + --color-purple-600: var(--ui-color-purple-600, #926ae8); + --color-purple-700: var(--ui-color-purple-700, #7252b5); + --color-purple-main: var(--ui-color-purple-main, #a074ff); + + --color-blue-100: var(--ui-color-blue-100, #f4faff); + --color-blue-200: var(--ui-color-blue-200, #e9f5ff); + --color-blue-300: var(--ui-color-blue-300, #bae1fe); + --color-blue-400: var(--ui-color-blue-400, #4db2fd); + --color-blue-500: var(--ui-color-blue-500, #219ffc); + --color-blue-600: var(--ui-color-blue-600, #1e91e5); + --color-blue-700: var(--ui-color-blue-700, #1771b3); + --color-blue-main: var(--ui-color-blue-main, #219ffc); + + --color-red-100: var(--ui-color-red-100, #feefef); + --color-red-200: var(--ui-color-red-200, #fdc7c7); + --color-red-300: var(--ui-color-red-300, #ff97a0); + --color-red-400: var(--ui-color-red-400, #f15d64); + --color-red-500: var(--ui-color-red-500, #ef4149); + --color-red-600: var(--ui-color-red-600, #bc292e); + --color-red-main: var(--ui-color-red-main, #ef4149); + + --color-green-100: var(--ui-color-green-100, #e0f8e3); + --color-green-200: var(--ui-color-green-200, #cbf1cd); + --color-green-300: var(--ui-color-green-300, #b0ea90); + --color-green-400: var(--ui-color-green-400, #90e05a); + --color-green-500: var(--ui-color-green-500, #63ce29); + --color-green-600: var(--ui-color-green-600, #3ca80c); + --color-green-main: var(--ui-color-green-main, #63ce29); + + --color-grey-100: var(--ui-color-grey-100, #ffffff); + --color-grey-200: var(--ui-color-grey-200, #fbfcfd); + --color-grey-300: var(--ui-color-grey-300, #f6f8fa); + --color-grey-400: var(--ui-color-grey-400, #eaeff3); + --color-grey-500: var(--ui-color-grey-500, #d9dfe5); + --color-grey-600: var(--ui-color-grey-600, #cbd2d8); + --color-grey-700: var(--ui-color-grey-700, #a7b1bb); + --color-grey-800: var(--ui-color-grey-800, #6e7781); + --color-grey-900: var(--ui-color-grey-900, #57606a); + --color-grey-1000: var(--ui-color-grey-1000, #24292f); + + --color-primary-100: var(--ui-color-primary-100, #f3fcfd); + --color-primary-200: var(--ui-color-primary-200, #e7f9fa); + --color-primary-300: var(--ui-color-primary-300, #b5ebf0); + --color-primary-400: var(--ui-color-primary-400, #3fcdd9); + --color-primary-500: var(--ui-color-primary-500, #0bc0cf); + --color-primary-600: var(--ui-color-primary-600, #0eafbc); + --color-primary-700: var(--ui-color-primary-700, #0b8893); + --color-primary-main: var(--ui-color-primary-main, #0bc0cf); + + --color-sprite-100: var(--ui-color-sprite-100, #fffaf5); + --color-sprite-200: var(--ui-color-sprite-200, #fff6eb); + --color-sprite-300: var(--ui-color-sprite-300, #fde2c0); + --color-sprite-400: var(--ui-color-sprite-400, #fbb45d); + --color-sprite-500: var(--ui-color-sprite-500, #faa135); + --color-sprite-600: var(--ui-color-sprite-600, #e49330); + --color-sprite-700: var(--ui-color-sprite-700, #b27226); + --color-sprite-main: var(--ui-color-sprite-main, #faa135); + --color-sprite-bg-selected: var(--ui-color-sprite-bg-selected, #fff6eb); + + --color-sound-100: var(--ui-color-sound-100, #f4faff); + --color-sound-200: var(--ui-color-sound-200, #e9f5ff); + --color-sound-300: var(--ui-color-sound-300, #bae1fe); + --color-sound-400: var(--ui-color-sound-400, #4db2fd); + --color-sound-500: var(--ui-color-sound-500, #219ffc); + --color-sound-600: var(--ui-color-sound-600, #1e91e5); + --color-sound-700: var(--ui-color-sound-700, #1771b3); + --color-sound-main: var(--ui-color-sound-main, #219ffc); + --color-sound-bg-selected: var(--ui-color-sound-bg-selected, #e9f5ff); + + --color-stage-100: var(--ui-color-stage-100, #f4faff); + --color-stage-200: var(--ui-color-stage-200, #e9f5ff); + --color-stage-300: var(--ui-color-stage-300, #bae1fe); + --color-stage-400: var(--ui-color-stage-400, #4db2fd); + --color-stage-500: var(--ui-color-stage-500, #219ffc); + --color-stage-600: var(--ui-color-stage-600, #1e91e5); + --color-stage-700: var(--ui-color-stage-700, #1771b3); + --color-stage-main: var(--ui-color-stage-main, #219ffc); + --color-stage-bg-selected: var(--ui-color-stage-bg-selected, #e9f5ff); + + --color-danger-100: var(--ui-color-danger-100, #feefef); + --color-danger-200: var(--ui-color-danger-200, #fdc7c7); + --color-danger-300: var(--ui-color-danger-300, #ff97a0); + --color-danger-400: var(--ui-color-danger-400, #f15d64); + --color-danger-500: var(--ui-color-danger-500, #ef4149); + --color-danger-600: var(--ui-color-danger-600, #bc292e); + --color-danger-main: var(--ui-color-danger-main, #ef4149); + + --color-success-100: var(--ui-color-success-100, #e0f8e3); + --color-success-200: var(--ui-color-success-200, #cbf1cd); + --color-success-300: var(--ui-color-success-300, #b0ea90); + --color-success-400: var(--ui-color-success-400, #90e05a); + --color-success-500: var(--ui-color-success-500, #63ce29); + --color-success-600: var(--ui-color-success-600, #3ca80c); + --color-success-main: var(--ui-color-success-main, #63ce29); + + --color-disabled-bg: var(--ui-color-disabled-bg, #f6f8fa); + --color-disabled-text: var(--ui-color-disabled-text, #cbd2d8); + --color-title: var(--ui-color-title, #24292f); + --color-text: var(--ui-color-text, #57606a); + --color-hint-1: var(--ui-color-hint-1, #6e7781); + --color-hint-2: var(--ui-color-hint-2, #a7b1bb); + --color-dividing-line-1: var(--ui-color-dividing-line-1, #d9dfe5); + --color-dividing-line-2: var(--ui-color-dividing-line-2, #eaeff3); + --color-border: var(--ui-color-border, #cbd2d8); + + /* Typography tokens bridged from the UI token layer. */ + --font-sans: var( + --ui-font-family-main, + AlibabaHealthB, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + 'Helvetica Neue', + Arial, + 'Noto Sans', + sans-serif, + 'Apple Color Emoji', + 'Segoe UI Emoji', + 'Segoe UI Symbol', + 'Noto Color Emoji' + ); + --font-mono: var(--ui-font-family-code, Menlo, Monaco, 'Courier New', monospace); + --font-main: var(--font-sans); + --font-code: var(--font-mono); + + /* Radius and shadow tokens bridged from the UI token layer. */ + --radius-none: 0px; + --radius-full: 9999px; + --radius-1: var(--ui-border-radius-1, 8px); + --radius-2: var(--ui-border-radius-2, 12px); + --radius-3: var(--ui-border-radius-3, 20px); + + --shadow-none: 0 0 #0000; + --shadow-small: var(--ui-box-shadow-small, 0px 2px 8px 0px rgba(51, 51, 51, 0.08)); + --shadow-big: var(--ui-box-shadow-big, 0px 4px 24px 0px rgba(36, 41, 47, 0.08)); + --shadow-diffusion: var(--ui-box-shadow-diffusion, 0px 4px 12px 0px #d0f2f8); + + /* Shared spacing and text-size helpers bridged for utility-class authoring. */ + --leading-1: var(--ui-line-height-1, 26px); + --leading-2: var(--ui-line-height-2, 32px); + --leading-3: var(--ui-line-height-3, 40px); + + --spacing-middle: var(--ui-gap-middle, 16px); + --spacing-large: var(--ui-gap-large, 24px); + + --text-body: var(--ui-font-size-text, 14px); + --text-body--line-height: 1.57143; + --text-15: 15px; + --text-15--line-height: 1.5; + --text-20: 20px; + --text-20--line-height: 1.5; +} diff --git a/spx-gui/src/components/common/RouterUILink.vue b/spx-gui/src/components/common/RouterUILink.vue index d8d653a1b..d1800f025 100644 --- a/spx-gui/src/components/common/RouterUILink.vue +++ b/spx-gui/src/components/common/RouterUILink.vue @@ -1,6 +1,7 @@ - - diff --git a/spx-gui/src/components/community/CenteredWrapper.vue b/spx-gui/src/components/community/CenteredWrapper.vue index 1e3418da7..fb48854b9 100644 --- a/spx-gui/src/components/community/CenteredWrapper.vue +++ b/spx-gui/src/components/community/CenteredWrapper.vue @@ -1,14 +1,10 @@ - - - - + diff --git a/spx-gui/src/components/community/CommunityCard.vue b/spx-gui/src/components/community/CommunityCard.vue index f6b8b9ffc..254043f02 100644 --- a/spx-gui/src/components/community/CommunityCard.vue +++ b/spx-gui/src/components/community/CommunityCard.vue @@ -10,8 +10,9 @@ import { UICard } from '@/components/ui' - diff --git a/spx-gui/src/components/community/CommunityHeader.vue b/spx-gui/src/components/community/CommunityHeader.vue index ad56bed8d..3eadb3a0d 100644 --- a/spx-gui/src/components/community/CommunityHeader.vue +++ b/spx-gui/src/components/community/CommunityHeader.vue @@ -1,12 +1,12 @@ - - diff --git a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/completion/CompletionItem.vue b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/completion/CompletionItem.vue index 419bb5bb0..9d5c4fbea 100644 --- a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/completion/CompletionItem.vue +++ b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/completion/CompletionItem.vue @@ -40,45 +40,14 @@ watchEffect(() => { - - diff --git a/spx-gui/src/components/editor/map-editor/MapEditor.vue b/spx-gui/src/components/editor/map-editor/MapEditor.vue index 6626ccc93..98f8fedfc 100644 --- a/spx-gui/src/components/editor/map-editor/MapEditor.vue +++ b/spx-gui/src/components/editor/map-editor/MapEditor.vue @@ -26,14 +26,14 @@ function handleSpriteSelect(sprite: Sprite | null) { diff --git a/spx-gui/src/components/ui/global.css b/spx-gui/src/components/ui/global.css new file mode 100644 index 000000000..34e65297e --- /dev/null +++ b/spx-gui/src/components/ui/global.css @@ -0,0 +1,18 @@ +@import './reset.css' layer(base); + +@layer base { + *, + ::before, + ::after { + box-sizing: border-box; + } + + button { + font-family: inherit; + } +} + +@font-face { + font-family: 'AlibabaHealthB'; + src: url('./fonts/AlibabaHealthFont2.0CN-85B.ttf') format('truetype'); +} \ No newline at end of file diff --git a/spx-gui/src/components/ui/global.scss b/spx-gui/src/components/ui/global.scss deleted file mode 100644 index 9d922db14..000000000 --- a/spx-gui/src/components/ui/global.scss +++ /dev/null @@ -1,16 +0,0 @@ -@import './reset.css'; - -*, -::before, -::after { - box-sizing: border-box; -} - -button { - font-family: inherit; -} - -@font-face { - font-family: 'AlibabaHealthB'; - src: url('./fonts/AlibabaHealthFont2.0CN-85B.ttf') format('truetype'); -} diff --git a/spx-gui/src/components/ui/link.scss b/spx-gui/src/components/ui/link.scss deleted file mode 100644 index effea58f0..000000000 --- a/spx-gui/src/components/ui/link.scss +++ /dev/null @@ -1,24 +0,0 @@ -@mixin link($type) { - transition: 0.1s; - - @if $type == primary { - color: var(--ui-color-primary-main); - text-decoration: none; - - &:hover { - color: var(--ui-color-primary-400); - } - &:active { - color: var(--ui-color-primary-600); - } - } @else if $type == boring { - color: inherit; - - &:hover { - color: var(--ui-color-primary-main); - } - &:active { - color: var(--ui-color-primary-600); - } - } -} diff --git a/spx-gui/src/components/ui/responsive.scss b/spx-gui/src/components/ui/responsive.scss deleted file mode 100644 index 5ad45a0e1..000000000 --- a/spx-gui/src/components/ui/responsive.scss +++ /dev/null @@ -1,22 +0,0 @@ -// definition for responsive mixin - -@mixin responsive($size) { - // NOTE: remember to keep these values in sync with the breakpoints in ./responsive.ts - @if $size == mobile { - @media (max-width: 767px) { - @content; - } - } @else if $size == tablet { - @media (min-width: 768px) and (max-width: 1279px) { - @content; - } - } @else if $size == desktop { - @media (min-width: 1280px) and (max-width: 1679px) { - @content; - } - } @else if $size == desktop-large { - @media (min-width: 1680px) { - @content; - } - } -} diff --git a/spx-gui/src/components/ui/responsive.ts b/spx-gui/src/components/ui/responsive.ts index 27624afb9..3596844bd 100644 --- a/spx-gui/src/components/ui/responsive.ts +++ b/spx-gui/src/components/ui/responsive.ts @@ -5,7 +5,7 @@ export type ReponsiveSize = 'mobile' | 'tablet' | 'desktop' | 'desktop-large' function getQuery(size: ReponsiveSize) { let query: string switch (size) { - // NOTE: remember to keep these values in sync with the breakpoints in ./responsive.scss + // NOTE: remember to keep these values in sync with the breakpoints in @/app.css case 'mobile': query = '(max-width: 767px)' break diff --git a/spx-gui/src/main.ts b/spx-gui/src/main.ts index a9316e80c..d76881e1c 100644 --- a/spx-gui/src/main.ts +++ b/spx-gui/src/main.ts @@ -1,4 +1,5 @@ import './polyfills' +import './app.css' import { createApp, watchEffect, type App as VueApp } from 'vue' import * as Sentry from '@sentry/vue' import type { Router } from 'vue-router' diff --git a/spx-gui/src/pages/404/index.vue b/spx-gui/src/pages/404/index.vue index 8c5e3fb42..1d2c0c4e2 100644 --- a/spx-gui/src/pages/404/index.vue +++ b/spx-gui/src/pages/404/index.vue @@ -10,15 +10,20 @@ const router = useRouter() - - diff --git a/spx-gui/src/pages/community/explore.vue b/spx-gui/src/pages/community/explore.vue index eddb43af2..0a51e5127 100644 --- a/spx-gui/src/pages/community/explore.vue +++ b/spx-gui/src/pages/community/explore.vue @@ -15,9 +15,9 @@ - + -
    +
    @@ -65,20 +65,3 @@ const queryRet = useQuery( } ) - - diff --git a/spx-gui/src/pages/community/home.vue b/spx-gui/src/pages/community/home.vue index cdacea021..4805fcc01 100644 --- a/spx-gui/src/pages/community/home.vue +++ b/spx-gui/src/pages/community/home.vue @@ -1,6 +1,6 @@ - - diff --git a/spx-gui/src/components/community/ProjectsSection.vue b/spx-gui/src/components/community/ProjectsSection.vue index f02c5cf85..9fa6917b5 100644 --- a/spx-gui/src/components/community/ProjectsSection.vue +++ b/spx-gui/src/components/community/ProjectsSection.vue @@ -13,7 +13,7 @@ :to="linkTo" > - +
    - - diff --git a/spx-gui/src/components/community/footer/CommunityFooter.vue b/spx-gui/src/components/community/footer/CommunityFooter.vue index 6727e29c6..8fd6ec239 100644 --- a/spx-gui/src/components/community/footer/CommunityFooter.vue +++ b/spx-gui/src/components/community/footer/CommunityFooter.vue @@ -4,43 +4,26 @@ import { UILink } from '@/components/ui' - - diff --git a/spx-gui/src/components/community/home/banner/GuestBanner.vue b/spx-gui/src/components/community/home/banner/GuestBanner.vue index 3e1442feb..50f2b6aae 100644 --- a/spx-gui/src/components/community/home/banner/GuestBanner.vue +++ b/spx-gui/src/components/community/home/banner/GuestBanner.vue @@ -2,6 +2,7 @@ import { initiateSignIn } from '@/stores/user' import { UIButton } from '@/components/ui' import CommunityCard from '../../CommunityCard.vue' +import bgSvg from './bg.svg' function handleJoin() { initiateSignIn() @@ -9,17 +10,20 @@ function handleJoin() { - - diff --git a/spx-gui/src/components/community/project/OwnerInfo.vue b/spx-gui/src/components/community/project/OwnerInfo.vue index 9f22363e8..9e724e3e0 100644 --- a/spx-gui/src/components/community/project/OwnerInfo.vue +++ b/spx-gui/src/components/community/project/OwnerInfo.vue @@ -12,46 +12,15 @@ const avatarUrl = useAvatarUrl(() => user.value?.avatar) - - diff --git a/spx-gui/src/components/community/project/ReleaseHistory.vue b/spx-gui/src/components/community/project/ReleaseHistory.vue index bf8207672..ffd6e7a00 100644 --- a/spx-gui/src/components/community/project/ReleaseHistory.vue +++ b/spx-gui/src/components/community/project/ReleaseHistory.vue @@ -28,5 +28,3 @@ defineProps<{ - - diff --git a/spx-gui/src/components/community/user/AvatarZoomSlider.vue b/spx-gui/src/components/community/user/AvatarZoomSlider.vue index 050dfa4dc..567044d94 100644 --- a/spx-gui/src/components/community/user/AvatarZoomSlider.vue +++ b/spx-gui/src/components/community/user/AvatarZoomSlider.vue @@ -31,19 +31,19 @@ function handleValueUpdate(value: number) { - diff --git a/spx-gui/src/components/community/user/EditAvatarModal.vue b/spx-gui/src/components/community/user/EditAvatarModal.vue index 62f165cd6..e082cf4d5 100644 --- a/spx-gui/src/components/community/user/EditAvatarModal.vue +++ b/spx-gui/src/components/community/user/EditAvatarModal.vue @@ -392,21 +392,15 @@ async function handleImageLoad() { >
    - +
    -
    -
    +
    +
    - diff --git a/spx-gui/src/components/community/user/FollowButton.vue b/spx-gui/src/components/community/user/FollowButton.vue index cec3736fe..fefa9c944 100644 --- a/spx-gui/src/components/community/user/FollowButton.vue +++ b/spx-gui/src/components/community/user/FollowButton.vue @@ -40,5 +40,3 @@ const handleClick = useMessageHandle(async () => { {{ $t(following ? { en: 'Unfollow', zh: '取消关注' } : { en: 'Follow', zh: '关注' }) }} - - diff --git a/spx-gui/src/components/community/user/ModifyUsernameModal.vue b/spx-gui/src/components/community/user/ModifyUsernameModal.vue index 93410068b..d9fa0ebe9 100644 --- a/spx-gui/src/components/community/user/ModifyUsernameModal.vue +++ b/spx-gui/src/components/community/user/ModifyUsernameModal.vue @@ -90,7 +90,7 @@ const handleSubmit = useMessageHandle(async () => { autofocus /> -
    +
    { - - diff --git a/spx-gui/src/components/community/user/UserAvatar.vue b/spx-gui/src/components/community/user/UserAvatar.vue index 18ad8a068..580520f46 100644 --- a/spx-gui/src/components/community/user/UserAvatar.vue +++ b/spx-gui/src/components/community/user/UserAvatar.vue @@ -1,7 +1,7 @@ - - diff --git a/spx-gui/src/components/course/management/CourseItem.vue b/spx-gui/src/components/course/management/CourseItem.vue index 67f071974..1a04089ea 100644 --- a/spx-gui/src/components/course/management/CourseItem.vue +++ b/spx-gui/src/components/course/management/CourseItem.vue @@ -16,71 +16,31 @@ const thumbnailUrl = useAsyncComputed(async (onCleanup) => { - diff --git a/spx-gui/src/components/course/management/CourseItemCornerMenu.vue b/spx-gui/src/components/course/management/CourseItemCornerMenu.vue index 1f113bfab..b671d19ee 100644 --- a/spx-gui/src/components/course/management/CourseItemCornerMenu.vue +++ b/spx-gui/src/components/course/management/CourseItemCornerMenu.vue @@ -15,8 +15,11 @@ const emit = defineEmits<{ - - diff --git a/spx-gui/src/components/course/management/CourseItemMini.vue b/spx-gui/src/components/course/management/CourseItemMini.vue index 787cd5f39..c8952cc94 100644 --- a/spx-gui/src/components/course/management/CourseItemMini.vue +++ b/spx-gui/src/components/course/management/CourseItemMini.vue @@ -20,69 +20,20 @@ const thumbnailUrl = useAsyncComputedLegacy(async (onCleanup) => { - - diff --git a/spx-gui/src/components/course/management/CourseManagementModal.vue b/spx-gui/src/components/course/management/CourseManagementModal.vue index 9cf274c60..eea034e81 100644 --- a/spx-gui/src/components/course/management/CourseManagementModal.vue +++ b/spx-gui/src/components/course/management/CourseManagementModal.vue @@ -109,12 +109,15 @@ const handleRemove = useMessageHandle( {{ $t({ en: 'Create course', zh: '创建课程' }) }} -
    +
    -
    -
    +
    +

    {{ $t({ en: 'No courses yet', zh: '还没有课程' }) }}

    -

    +

    {{ $t({ en: 'Click "Create course" to add your first course', @@ -123,60 +126,14 @@ const handleRemove = useMessageHandle( }}

    -
      +
    - +
    - - diff --git a/spx-gui/src/components/course/management/CourseSelector.vue b/spx-gui/src/components/course/management/CourseSelector.vue index b781c160b..937d92436 100644 --- a/spx-gui/src/components/course/management/CourseSelector.vue +++ b/spx-gui/src/components/course/management/CourseSelector.vue @@ -31,8 +31,8 @@ const availableCourses = computed(() => { - - diff --git a/spx-gui/src/components/course/management/CourseSeriesItem.vue b/spx-gui/src/components/course/management/CourseSeriesItem.vue index 2bdf6e539..446225199 100644 --- a/spx-gui/src/components/course/management/CourseSeriesItem.vue +++ b/spx-gui/src/components/course/management/CourseSeriesItem.vue @@ -16,12 +16,33 @@ const thumbnailUrl = useAsyncComputed(async (onCleanup) => { - diff --git a/spx-gui/src/components/course/management/CourseSeriesItemCornerMenu.vue b/spx-gui/src/components/course/management/CourseSeriesItemCornerMenu.vue index 50701dc76..85cecb81d 100644 --- a/spx-gui/src/components/course/management/CourseSeriesItemCornerMenu.vue +++ b/spx-gui/src/components/course/management/CourseSeriesItemCornerMenu.vue @@ -15,8 +15,11 @@ const emit = defineEmits<{ - - diff --git a/spx-gui/src/components/course/management/CourseSeriesManagementModal.vue b/spx-gui/src/components/course/management/CourseSeriesManagementModal.vue index c2390bf7e..518cb5212 100644 --- a/spx-gui/src/components/course/management/CourseSeriesManagementModal.vue +++ b/spx-gui/src/components/course/management/CourseSeriesManagementModal.vue @@ -112,12 +112,15 @@ const handleRemove = useMessageHandle( {{ $t({ en: 'Create course series', zh: '创建课程系列' }) }} -
    +
    -
    -
    +
    +

    {{ $t({ en: 'No course series yet', zh: '还没有课程系列' }) }}

    -

    +

    {{ $t({ en: 'Click "Create course series" to add your first series', @@ -126,7 +129,7 @@ const handleRemove = useMessageHandle( }}

    -
      +
    - +
    - - diff --git a/spx-gui/src/components/course/management/ProjectReferencesInput.vue b/spx-gui/src/components/course/management/ProjectReferencesInput.vue index f699a8223..43d003dcf 100644 --- a/spx-gui/src/components/course/management/ProjectReferencesInput.vue +++ b/spx-gui/src/components/course/management/ProjectReferencesInput.vue @@ -79,7 +79,7 @@ function handleRemove(index: number) { - - diff --git a/spx-gui/src/components/course/management/SelectedCoursesList.vue b/spx-gui/src/components/course/management/SelectedCoursesList.vue index 2f1634395..b8f384e2d 100644 --- a/spx-gui/src/components/course/management/SelectedCoursesList.vue +++ b/spx-gui/src/components/course/management/SelectedCoursesList.vue @@ -75,16 +75,17 @@ function removeCourse(index: number) { - - diff --git a/spx-gui/src/components/course/management/ThumbnailUploader.vue b/spx-gui/src/components/course/management/ThumbnailUploader.vue index 6e265b929..09bdb182b 100644 --- a/spx-gui/src/components/course/management/ThumbnailUploader.vue +++ b/spx-gui/src/components/course/management/ThumbnailUploader.vue @@ -34,45 +34,17 @@ const thumbnailUrl = useAsyncComputed(async (onCleanup) => { - - diff --git a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/completion/CompletionUI.vue b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/completion/CompletionUI.vue index 23246eddd..284017f64 100644 --- a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/completion/CompletionUI.vue +++ b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/completion/CompletionUI.vue @@ -51,5 +51,3 @@ watchEffect(() => { /> - - diff --git a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/context-menu/ContextMenu.vue b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/context-menu/ContextMenu.vue index 59bcf2adf..eb361df18 100644 --- a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/context-menu/ContextMenu.vue +++ b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/context-menu/ContextMenu.vue @@ -34,5 +34,3 @@ const handleItemClick = useMessageHandle((item: InternalMenuItem) => props.contr - - diff --git a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/definition/DefinitionDetail.vue b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/definition/DefinitionDetail.vue index 175dadbed..111b20042 100644 --- a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/definition/DefinitionDetail.vue +++ b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/definition/DefinitionDetail.vue @@ -30,5 +30,3 @@ const hasContent = computed(() => documentation.value != null || childrenText.va - - diff --git a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/markdown/ResourcePreview.vue b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/markdown/ResourcePreview.vue index db2299a19..7ed76e3c3 100644 --- a/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/markdown/ResourcePreview.vue +++ b/spx-gui/src/components/editor/code-editor/xgo-code-editor/ui/markdown/ResourcePreview.vue @@ -19,5 +19,3 @@ const resourceIdentifier = computed(() => ({ - - diff --git a/spx-gui/src/components/editor/common/PlayControl.vue b/spx-gui/src/components/editor/common/PlayControl.vue index 680aa0a02..dc2a76e89 100644 --- a/spx-gui/src/components/editor/common/PlayControl.vue +++ b/spx-gui/src/components/editor/common/PlayControl.vue @@ -1,7 +1,7 @@ - - diff --git a/spx-gui/src/components/project/ProjectSharingLinkModal.vue b/spx-gui/src/components/project/ProjectSharingLinkModal.vue index f981f489e..d7b6cd378 100644 --- a/spx-gui/src/components/project/ProjectSharingLinkModal.vue +++ b/spx-gui/src/components/project/ProjectSharingLinkModal.vue @@ -6,7 +6,7 @@ :auto-focus="false" @update:visible="emit('cancelled')" > -
    +
    {{ $t({ en: 'A sharing link to the project has been created. Feel free to copy it below to share the project with others.', @@ -14,7 +14,7 @@ }) }}
    -
- + - - diff --git a/spx-gui/src/pages/community/user/index.vue b/spx-gui/src/pages/community/user/index.vue index 8316e1e41..c42a52353 100644 --- a/spx-gui/src/pages/community/user/index.vue +++ b/spx-gui/src/pages/community/user/index.vue @@ -29,50 +29,18 @@ watch(user, (currentUser) => { - - diff --git a/spx-gui/src/pages/community/user/likes.vue b/spx-gui/src/pages/community/user/likes.vue index de68fde61..ac3cd7783 100644 --- a/spx-gui/src/pages/community/user/likes.vue +++ b/spx-gui/src/pages/community/user/likes.vue @@ -53,30 +53,13 @@ const queryRet = useQuery( -
+
-
    +
    - +
- - diff --git a/spx-gui/src/pages/community/user/overview.vue b/spx-gui/src/pages/community/user/overview.vue index 8c8e3d2f3..e132a4b1e 100644 --- a/spx-gui/src/pages/community/user/overview.vue +++ b/spx-gui/src/pages/community/user/overview.vue @@ -73,8 +73,8 @@ const likesRet = useQuery( - - diff --git a/spx-gui/src/pages/community/user/projects.vue b/spx-gui/src/pages/community/user/projects.vue index 2a77a6186..410fbdce2 100644 --- a/spx-gui/src/pages/community/user/projects.vue +++ b/spx-gui/src/pages/community/user/projects.vue @@ -91,7 +91,7 @@ const handleNewProject = useMessageHandle( {{ $t({ en: 'My projects', zh: '我的项目' }) }} -
+
-
    +
    - +
- - diff --git a/spx-gui/src/pages/tutorials/course-series.vue b/spx-gui/src/pages/tutorials/course-series.vue index acf217d98..0775d26a7 100644 --- a/spx-gui/src/pages/tutorials/course-series.vue +++ b/spx-gui/src/pages/tutorials/course-series.vue @@ -18,6 +18,8 @@ import { useRouteQueryParamInt } from '@/utils/route' import { useAsyncComputed, usePageTitle } from '@/utils/utils' import { useMessageHandle } from '@/utils/exception' import CommunityFooter from '@/components/community/footer/CommunityFooter.vue' +// TODO: Temporary background, replace with the latest assets +import stageBg from '@/assets/images/stage-bg.svg' const coursePadding = 20 const numInColumn = 2 @@ -96,29 +98,34 @@ const { fn: handleCourseClick } = useMessageHandle( - diff --git a/spx-gui/src/components/asset/gen/backdrop/BackdropGenItem.vue b/spx-gui/src/components/asset/gen/backdrop/BackdropGenItem.vue index 88a0863dd..e36e1eb2d 100644 --- a/spx-gui/src/components/asset/gen/backdrop/BackdropGenItem.vue +++ b/spx-gui/src/components/asset/gen/backdrop/BackdropGenItem.vue @@ -36,5 +36,3 @@ const highlight = computed(() => props.gen.imagesGenState.status === 'finished') {{ gen.settings.name }} - - diff --git a/spx-gui/src/components/asset/gen/backdrop/BackdropGenModal.vue b/spx-gui/src/components/asset/gen/backdrop/BackdropGenModal.vue index 8119e50b2..d37ac99ba 100644 --- a/spx-gui/src/components/asset/gen/backdrop/BackdropGenModal.vue +++ b/spx-gui/src/components/asset/gen/backdrop/BackdropGenModal.vue @@ -61,38 +61,17 @@ const handleModalClose = useMessageHandle( mask-closable @update:visible="handleModalClose" > -
-

{{ $t({ zh: '生成背景', en: 'Backdrop Generator' }) }}

+
+

{{ $t({ zh: '生成背景', en: 'Backdrop Generator' }) }}

- - diff --git a/spx-gui/src/components/asset/gen/backdrop/BackdropImageItem.vue b/spx-gui/src/components/asset/gen/backdrop/BackdropImageItem.vue index 8a8954cfb..c5a3d9a52 100644 --- a/spx-gui/src/components/asset/gen/backdrop/BackdropImageItem.vue +++ b/spx-gui/src/components/asset/gen/backdrop/BackdropImageItem.vue @@ -31,69 +31,16 @@ const loading = computed(() => props.loading || fileLoading.value) name: 'Backdrop image item', desc: 'Click to select this image as the backdrop' }" - class="backdrop-image-item" - :class="{ active, compact, loading, disabled }" + class="flex items-center justify-center overflow-hidden border-2 border-transparent bg-grey-300 p-1 transition-[width,height,border-radius] duration-200 ease-in-out" + :class="[ + compact ? 'h-17 w-22 rounded-1' : 'h-27 w-35 rounded-2', + active ? 'border-turquoise-500 bg-turquoise-200 cursor-default' : '', + disabled ? 'cursor-not-allowed opacity-50' : '', + loading ? 'cursor-default pointer-events-none' : '', + !active && !disabled && !loading ? 'cursor-pointer' : '' + ]" > - +
- - diff --git a/spx-gui/src/components/asset/gen/backdrop/BackdropSettingsInput.vue b/spx-gui/src/components/asset/gen/backdrop/BackdropSettingsInput.vue index 611f474eb..be9d54ff9 100644 --- a/spx-gui/src/components/asset/gen/backdrop/BackdropSettingsInput.vue +++ b/spx-gui/src/components/asset/gen/backdrop/BackdropSettingsInput.vue @@ -80,5 +80,3 @@ const submitText = computed(() => { - - diff --git a/spx-gui/src/components/asset/gen/common/AssetSuggestions.vue b/spx-gui/src/components/asset/gen/common/AssetSuggestions.vue index c99bad064..c551c678f 100644 --- a/spx-gui/src/components/asset/gen/common/AssetSuggestions.vue +++ b/spx-gui/src/components/asset/gen/common/AssetSuggestions.vue @@ -29,14 +29,14 @@ const entityMessage = computed(() => entityMessages[props.type]) - - diff --git a/spx-gui/src/components/asset/gen/common/GenItem.vue b/spx-gui/src/components/asset/gen/common/GenItem.vue index 804de5d80..a3d10a9d4 100644 --- a/spx-gui/src/components/asset/gen/common/GenItem.vue +++ b/spx-gui/src/components/asset/gen/common/GenItem.vue @@ -62,76 +62,71 @@ const style = computed(() => { - diff --git a/spx-gui/src/components/asset/gen/common/GenLoading.vue b/spx-gui/src/components/asset/gen/common/GenLoading.vue index a87b47dbf..5a00bb8b5 100644 --- a/spx-gui/src/components/asset/gen/common/GenLoading.vue +++ b/spx-gui/src/components/asset/gen/common/GenLoading.vue @@ -41,7 +41,7 @@ const slots = useSlots()
- diff --git a/spx-gui/src/components/asset/gen/common/GenPreview.vue b/spx-gui/src/components/asset/gen/common/GenPreview.vue index a4a5306d3..633b55eb0 100644 --- a/spx-gui/src/components/asset/gen/common/GenPreview.vue +++ b/spx-gui/src/components/asset/gen/common/GenPreview.vue @@ -19,75 +19,26 @@ const emit = defineEmits<{ name: `Preview for '${name}'`, desc: `Preview for the generation item '${name}'` }" - class="gen-preview" + class="flex flex-1 flex-col gap-5 px-5 py-6" > -
-
+
+
{{ name }}
-
+
-
+
- - diff --git a/spx-gui/src/components/asset/gen/common/ImagePreview.vue b/spx-gui/src/components/asset/gen/common/ImagePreview.vue index e9ef04aed..91d373ecb 100644 --- a/spx-gui/src/components/asset/gen/common/ImagePreview.vue +++ b/spx-gui/src/components/asset/gen/common/ImagePreview.vue @@ -12,28 +12,11 @@ const [fileUrl, fileUrlLoading] = useFileUrl(() => props.file) - - diff --git a/spx-gui/src/components/asset/gen/common/ImageSelector.vue b/spx-gui/src/components/asset/gen/common/ImageSelector.vue index 78b1c32ee..71eeaf5ce 100644 --- a/spx-gui/src/components/asset/gen/common/ImageSelector.vue +++ b/spx-gui/src/components/asset/gen/common/ImageSelector.vue @@ -67,9 +67,9 @@ function handleSelect(index: number) { v-if="state.status !== 'initial'" ref="wrapperRef" v-radar="{ name: 'Image selector', desc: 'Selector for choosing from generated images' }" - class="image-selector" + class="flex flex-col items-center gap-3" > -
    +
      - - diff --git a/spx-gui/src/components/asset/gen/common/LayoutWithPreview.vue b/spx-gui/src/components/asset/gen/common/LayoutWithPreview.vue index de6785f3b..2e21eb557 100644 --- a/spx-gui/src/components/asset/gen/common/LayoutWithPreview.vue +++ b/spx-gui/src/components/asset/gen/common/LayoutWithPreview.vue @@ -10,8 +10,11 @@ defineProps<{ - diff --git a/spx-gui/src/components/asset/gen/common/PreviewWithCheckerboardBg.vue b/spx-gui/src/components/asset/gen/common/PreviewWithCheckerboardBg.vue index 9435a41e1..aec96ed8a 100644 --- a/spx-gui/src/components/asset/gen/common/PreviewWithCheckerboardBg.vue +++ b/spx-gui/src/components/asset/gen/common/PreviewWithCheckerboardBg.vue @@ -8,10 +8,10 @@ import CheckerboardBackground from '@/components/editor/sprite/CheckerboardBackg - - diff --git a/spx-gui/src/components/asset/gen/common/SettingsInput.vue b/spx-gui/src/components/asset/gen/common/SettingsInput.vue index 71fef9c34..bcfb2c1ad 100644 --- a/spx-gui/src/components/asset/gen/common/SettingsInput.vue +++ b/spx-gui/src/components/asset/gen/common/SettingsInput.vue @@ -150,7 +150,7 @@ provide(settingsInputCtxKey, ctx) - diff --git a/spx-gui/src/components/asset/gen/common/param-settings/ParamSelector.vue b/spx-gui/src/components/asset/gen/common/param-settings/ParamSelector.vue index f4409848b..249e8db84 100644 --- a/spx-gui/src/components/asset/gen/common/param-settings/ParamSelector.vue +++ b/spx-gui/src/components/asset/gen/common/param-settings/ParamSelector.vue @@ -63,13 +63,13 @@ const iconOnly = computed(() => settingsInputCtx.iconOnly) name: $t(name), desc: `Click to select '${$t(name)}' (e.g., ${optionsText})` }" - class="param-button" - :class="[{ 'icon-only': iconOnly }]" + class="flex h-8 items-center justify-center gap-1 rounded-2 border border-grey-400 bg-grey-100 pr-2 pl-1 text-13/5 text-grey-900 cursor-pointer hover:bg-grey-300 disabled:cursor-not-allowed disabled:bg-grey-300 disabled:text-grey-600" + :class="[{ 'aspect-square px-0': iconOnly }]" :disabled="disabled" > @@ -82,9 +82,9 @@ const iconOnly = computed(() => settingsInputCtx.iconOnly) {{ $t(tooltipText) }} - diff --git a/spx-gui/src/components/asset/gen/costume/CostumeGenPreview.vue b/spx-gui/src/components/asset/gen/costume/CostumeGenPreview.vue index ea1f69898..cbde86d0d 100644 --- a/spx-gui/src/components/asset/gen/costume/CostumeGenPreview.vue +++ b/spx-gui/src/components/asset/gen/costume/CostumeGenPreview.vue @@ -43,7 +43,7 @@ const [imgSrc, imgLoading] = useFileUrl(() => props.gen.image) - - diff --git a/spx-gui/src/components/asset/gen/sprite/SpriteGenModal.vue b/spx-gui/src/components/asset/gen/sprite/SpriteGenModal.vue index bd743a8cd..ed75d888d 100644 --- a/spx-gui/src/components/asset/gen/sprite/SpriteGenModal.vue +++ b/spx-gui/src/components/asset/gen/sprite/SpriteGenModal.vue @@ -80,14 +80,14 @@ const handleModalClose = useMessageHandle( mask-closable @update:visible="handleModalClose" > -
      -

      {{ $t({ zh: '生成精灵', en: 'Sprite Generator' }) }}

      +
      +

      {{ $t({ zh: '生成精灵', en: 'Sprite Generator' }) }}

      - - diff --git a/spx-gui/src/components/asset/gen/sprite/SpriteGenPhaseContent.vue b/spx-gui/src/components/asset/gen/sprite/SpriteGenPhaseContent.vue index 77bba979e..4cdd0bd8a 100644 --- a/spx-gui/src/components/asset/gen/sprite/SpriteGenPhaseContent.vue +++ b/spx-gui/src/components/asset/gen/sprite/SpriteGenPhaseContent.vue @@ -191,11 +191,11 @@ const handleSubmit = useMessageHandle( - - diff --git a/spx-gui/src/components/asset/gen/sprite/SpriteGenPhaseSettings.vue b/spx-gui/src/components/asset/gen/sprite/SpriteGenPhaseSettings.vue index e9aa678d4..c4a9e4117 100644 --- a/spx-gui/src/components/asset/gen/sprite/SpriteGenPhaseSettings.vue +++ b/spx-gui/src/components/asset/gen/sprite/SpriteGenPhaseSettings.vue @@ -85,16 +85,16 @@ const handleUseAsset = useMessageHandle( name: 'Sprite generation settings phase', desc: 'Generate default costume for the sprite based on settings' }" - class="phase-settings" + class="phase-settings flex h-full flex-col items-stretch" > -
      + +
      -
      +
      + diff --git a/spx-gui/src/components/asset/gen/sprite/SpriteImageItem.vue b/spx-gui/src/components/asset/gen/sprite/SpriteImageItem.vue index 579ee90c0..9714f5a59 100644 --- a/spx-gui/src/components/asset/gen/sprite/SpriteImageItem.vue +++ b/spx-gui/src/components/asset/gen/sprite/SpriteImageItem.vue @@ -31,70 +31,16 @@ const loading = computed(() => props.loading || fileLoading.value) name: 'Sprite image item', desc: 'Click to select this image as the default costume for the sprite' }" - class="sprite-image-item" - :class="{ active, compact, loading, disabled }" + class="flex items-center justify-center overflow-hidden border-2 border-transparent bg-grey-300 p-1 transition-[width,height,border-radius] duration-200 ease-in-out" + :class="[ + compact ? 'h-22 w-22 rounded-1' : 'h-35 w-35 rounded-2', + active ? 'border-turquoise-500 bg-turquoise-200 cursor-default' : '', + disabled ? 'cursor-not-allowed opacity-50' : '', + loading ? 'cursor-default pointer-events-none' : '', + !active && !disabled && !loading ? 'cursor-pointer hover:bg-grey-400' : '' + ]" > - +
      - - diff --git a/spx-gui/src/components/asset/library/AssetLibraryModal.vue b/spx-gui/src/components/asset/library/AssetLibraryModal.vue index d6b2535da..12701bea9 100644 --- a/spx-gui/src/components/asset/library/AssetLibraryModal.vue +++ b/spx-gui/src/components/asset/library/AssetLibraryModal.vue @@ -346,41 +346,45 @@ const title = computed(() => { mask-closable @update:visible="handleModalClose" > -
      -
      +
      +
      -

      {{ $t(title) }}

      +

      {{ $t(title) }}

      - +
      - - diff --git a/spx-gui/src/components/asset/library/AssetSaveModal.vue b/spx-gui/src/components/asset/library/AssetSaveModal.vue index 7522f4dba..961218e08 100644 --- a/spx-gui/src/components/asset/library/AssetSaveModal.vue +++ b/spx-gui/src/components/asset/library/AssetSaveModal.vue @@ -207,13 +207,13 @@ async function addAssetWithPartialData({ {{ $t(error.userMessage) }} -
      -
      - - - +
      +
      + + +
      -
      +
      -