From 182faf96de6bcf8a641a0ff33c169e8d0ff2128a Mon Sep 17 00:00:00 2001 From: chennan Date: Tue, 31 Mar 2026 11:10:33 +0800 Subject: [PATCH 01/10] 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 0000000000..464e56a036 --- /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 0000000000..6cdbf42474 --- /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 d8d653a1b6..d1800f0256 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 1e3418da71..fb48854b96 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 f6b8b9ffcd..254043f02e 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 ad56bed8de..3eadb3a0d2 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 419bb5bb03..9d5c4fbeab 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 6626ccc93f..98f8fedfc4 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 0000000000..34e65297e0 --- /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 9d922db141..0000000000 --- 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 effea58f0f..0000000000 --- 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 5ad45a0e18..0000000000 --- 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 27624afb91..3596844bda 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 a9316e80ca..d76881e1cf 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 8c5e3fb427..1d2c0c4e25 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 b03bfd21f2..6f9e44f8d8 100644 --- a/spx-gui/src/pages/community/explore.vue +++ b/spx-gui/src/pages/community/explore.vue @@ -15,9 +15,9 @@ - + -
    +
    @@ -64,20 +64,3 @@ const queryRet = useQuery( } ) - - diff --git a/spx-gui/src/pages/community/home.vue b/spx-gui/src/pages/community/home.vue index 94950b8af9..a123691fe6 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 f02c5cf853..9fa6917b58 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 6727e29c69..8fd6ec2391 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 3e1442febc..50f2b6aae9 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 9f22363e8e..9e724e3e06 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 bf82076720..ffd6e7a009 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 050dfa4dc0..567044d94a 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 62f165cd61..e082cf4d5a 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 cec3736fe0..fefa9c9446 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 2199903f22..44021d50e4 100644 --- a/spx-gui/src/components/community/user/ModifyUsernameModal.vue +++ b/spx-gui/src/components/community/user/ModifyUsernameModal.vue @@ -95,7 +95,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 18ad8a0680..580520f46d 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 67f071974b..1a04089ea5 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 1f113bfabd..b671d19ee0 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 787cd5f390..c8952cc942 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 9cf274c600..eea034e81c 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 b781c160b1..937d92436c 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 2bdf6e539d..4462251995 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 50701dc76a..85cecb81d8 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 c2390bf7ee..518cb52126 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 f699a82230..43d003dcf2 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 2f16343958..b8f384e2de 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 6e265b9296..09bdb182bb 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 23246eddd2..284017f641 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 59bcf2adfe..eb361df180 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 175dadbed4..111b200422 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 db2299a19c..7ed76e3c3d 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 680aa0a020..dc2a76e89e 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 f981f489e6..d7b6cd3788 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 e22d609e12..78ce218eec 100644 --- a/spx-gui/src/pages/community/user/index.vue +++ b/spx-gui/src/pages/community/user/index.vue @@ -13,50 +13,18 @@ const { data: user, error, refetch } = useUser(() => props.nameInput) - - diff --git a/spx-gui/src/pages/community/user/likes.vue b/spx-gui/src/pages/community/user/likes.vue index 82876a5cb2..99971d2abc 100644 --- a/spx-gui/src/pages/community/user/likes.vue +++ b/spx-gui/src/pages/community/user/likes.vue @@ -52,30 +52,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 c09c8cfd19..775db6593d 100644 --- a/spx-gui/src/pages/community/user/overview.vue +++ b/spx-gui/src/pages/community/user/overview.vue @@ -71,8 +71,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 4a6cb5494e..e7c474a891 100644 --- a/spx-gui/src/pages/community/user/projects.vue +++ b/spx-gui/src/pages/community/user/projects.vue @@ -90,7 +90,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 acf217d980..0775d26a75 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 88a0863ddf..e36e1eb2d5 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 8119e50b2f..d37ac99baf 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 8a8954cfbf..c5a3d9a52d 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 611f474eb1..be9d54ff9d 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 c99bad064f..c551c678f3 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 804de5d80e..a3d10a9d4a 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 a87b47dbf8..5a00bb8b56 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 a4a5306d3b..633b55eb08 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 e9ef04aed0..91d373ecb7 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 78b1c32ee9..71eeaf5cea 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 de6785f3b5..2e21eb5571 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 9435a41e1e..aec96ed8ae 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 71fef9c34f..bcfb2c1ad9 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 f4409848b7..249e8db84d 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 ea1f698983..cbde86d0d4 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 bd743a8cd2..ed75d888dd 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 77bba979ec..4cdd0bd8a2 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 e9aa678d4c..c4a9e4117b 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 579ee90c04..9714f5a598 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 de85e6339d..1a1def64c7 100644 --- a/spx-gui/src/components/asset/library/AssetLibraryModal.vue +++ b/spx-gui/src/components/asset/library/AssetLibraryModal.vue @@ -328,41 +328,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 7522f4dba5..961218e088 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) }} -
      -
      - - - +
      +
      + + +
      -
      +
      -