Skip to content

Commit 8c7a4c7

Browse files
committed
sv
1 parent e75e672 commit 8c7a4c7

File tree

18 files changed

+741
-266
lines changed

18 files changed

+741
-266
lines changed

docs/develop/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ See `package.json` or `go.mod` files in subdirectories for details.
1414

1515
### Architecture Design
1616

17-
TODO.
17+
- [Tailwind CSS Migration Assessment for spx-gui](./tailwind-css-migration.md)
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
# Tailwind CSS Migration Assessment for spx-gui
2+
3+
This document investigates whether XBuilder frontend styling in `spx-gui` should migrate to Tailwind CSS.
4+
5+
Issue: `goplus/builder#2981`
6+
7+
## Conclusion
8+
9+
Tailwind CSS is technically feasible in `spx-gui`, but a full migration is not a good near-term tradeoff.
10+
11+
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.
12+
13+
The recommended direction is an incremental hybrid approach:
14+
15+
- keep the existing `--ui-*` design tokens and Naive UI theme layer
16+
- add Tailwind only as an optional utility layer
17+
- validate it on a small set of low-risk pages or self-contained components first
18+
- only expand usage if the pilot materially improves development speed and code review quality
19+
20+
## Current Styling Architecture
21+
22+
The current frontend styling model is centered around Vue SFC scoped SCSS plus shared CSS variables.
23+
24+
- `spx-gui` uses Vite + Vue 3 and already includes `sass`, but has no Tailwind or PostCSS setup in [spx-gui/package.json](../../spx-gui/package.json)
25+
- the app loads global styling through [spx-gui/src/App.vue](../../spx-gui/src/App.vue) and [spx-gui/src/components/ui/global.scss](../../spx-gui/src/components/ui/global.scss)
26+
- 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
27+
- 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)
28+
- 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
29+
- most component styles live inside local `<style scoped lang="scss">` blocks, for example [spx-gui/src/components/ui/UIButton.vue](../../spx-gui/src/components/ui/UIButton.vue) and [spx-gui/src/components/editor/navbar/EditorNavbar.vue](../../spx-gui/src/components/editor/navbar/EditorNavbar.vue)
30+
31+
Measured footprint in `spx-gui/src`:
32+
33+
- 411 Vue files total
34+
- 325 Vue files contain a `<style>` block
35+
- 322 Vue files use SCSS in the SFC
36+
- 115 `:deep(...)` usages override descendants or third-party internals
37+
- 22 direct imports from `naive-ui`
38+
- 5 standalone stylesheet files under `src`, with most styling still embedded in Vue SFCs
39+
40+
Representative styling patterns:
41+
42+
- token-driven custom components: [spx-gui/src/components/ui/UIButton.vue](../../spx-gui/src/components/ui/UIButton.vue)
43+
- app-wide token and theme bridge: [spx-gui/src/components/ui/UIConfigProvider.vue](../../spx-gui/src/components/ui/UIConfigProvider.vue)
44+
- responsive SCSS mixins: [spx-gui/src/components/ui/responsive.scss](../../spx-gui/src/components/ui/responsive.scss) and [spx-gui/src/components/community/CenteredWrapper.vue](../../spx-gui/src/components/community/CenteredWrapper.vue)
45+
- complex page-level nested styling: [spx-gui/src/pages/community/project.vue](../../spx-gui/src/pages/community/project.vue)
46+
- content-renderer deep selectors: [spx-gui/src/components/copilot/MarkdownView.vue](../../spx-gui/src/components/copilot/MarkdownView.vue)
47+
48+
## Tailwind Fit Assessment
49+
50+
Tailwind fits part of the project well, but not all of it.
51+
52+
Good fit:
53+
54+
- layout-heavy pages using flex, grid, spacing, width, and alignment utilities
55+
- simple presentational components with limited state combinations
56+
- new pages or isolated features where templates are already the main source of UI structure
57+
- responsive layout rules, because the current breakpoint usage is limited and can be mapped into a custom Tailwind config
58+
59+
Weak fit:
60+
61+
- components with many styling states encoded through local CSS variables and nested selectors
62+
- custom wrappers around Naive UI that rely on theme overrides plus `:deep(...)` selectors
63+
- content renderers and editor surfaces that style generated DOM, not just authored template nodes
64+
- components with runtime geometry or inline styles, such as sliders, image previews, waveform editors, or draggable/resizable panes
65+
66+
Poor or no fit:
67+
68+
- Monaco editor integration and other third-party DOM that already depends on custom CSS
69+
- Konva or canvas-rendered surfaces where styling is not driven by CSS utility classes
70+
71+
## Migration Cost Estimate
72+
73+
Estimated cost if the goal is only to introduce Tailwind as an optional utility layer:
74+
75+
- setup and token mapping: 1 to 2 engineer-days
76+
- pilot migration for 1 small feature area: 2 to 5 engineer-days
77+
- documentation and team conventions: 1 engineer-day
78+
79+
Estimated cost for a meaningful incremental rollout across layout-heavy areas:
80+
81+
- 2 to 4 engineer-weeks
82+
- includes Tailwind setup, token mapping, conventions, 10 to 20 component/page migrations, and cleanup of duplicated styling patterns
83+
84+
Estimated cost for a broad migration that tries to make Tailwind the dominant styling approach in `spx-gui`:
85+
86+
- 6 to 10 engineer-weeks at minimum
87+
- likely more if the scope includes reworking Naive UI wrappers, complex editor surfaces, and duplicated `:deep(...)` customizations
88+
89+
Estimated cost for a true full migration away from the current SCSS-plus-token approach:
90+
91+
- high risk and not currently justified
92+
- would effectively become a UI architecture refactor, not just a styling migration
93+
94+
## Major Risks And Constraints
95+
96+
### 1. Existing token system already solves part of the problem
97+
98+
The project already has a centralized token system and shared CSS variables. Tailwind would not replace that cleanly unless the team rewrites token consumption across both custom components and Naive UI overrides.
99+
100+
### 2. Tailwind does not remove the Naive UI dependency
101+
102+
Naive UI is embedded in the app theme model via [spx-gui/src/components/ui/UIConfigProvider.vue](../../spx-gui/src/components/ui/UIConfigProvider.vue). Even after adding Tailwind, the project would still need to maintain Naive UI theming and style overrides.
103+
104+
### 3. Scoped SCSS is currently aligned with component boundaries
105+
106+
A large share of the codebase keeps style logic close to each Vue component. Tailwind can improve speed for simple cases, but moving every component to class-heavy templates would be noisy and produce uneven code style if done inconsistently.
107+
108+
### 4. `:deep(...)` usage is a real migration brake
109+
110+
There are 115 `:deep(...)` usages. These target generated content, child internals, or third-party component markup. Tailwind utilities do not eliminate that category of styling work.
111+
112+
### 5. Complex editor UI gets limited value from utility classes
113+
114+
Several editor surfaces rely on runtime positions, inline CSS variables, drag behavior, SVG, or canvas-like rendering. Those areas already need custom CSS or programmatic styling, so Tailwind adds little leverage there.
115+
116+
### 6. Design consistency can regress during mixed migration
117+
118+
If the team starts using raw Tailwind classes without a token bridge and a small set of conventions, the result will drift away from the existing `--ui-*` design language.
119+
120+
### 7. Maintenance cost can increase before it decreases
121+
122+
During the transition, the project would have to maintain:
123+
124+
- scoped SCSS
125+
- CSS variables
126+
- Naive UI theme overrides
127+
- Tailwind config and utilities
128+
129+
That is acceptable only if the migration remains intentionally narrow at first.
130+
131+
## Strategy Comparison
132+
133+
### Full Migration
134+
135+
Pros:
136+
137+
- one dominant styling model after the migration finishes
138+
- potentially faster AI-assisted markup styling in the long run
139+
140+
Cons:
141+
142+
- high rewrite cost
143+
- high risk of regressions in editor surfaces and custom UI components
144+
- still does not remove the need for custom CSS in several critical areas
145+
- poor short-term return on effort
146+
147+
Assessment: not recommended.
148+
149+
### Incremental Migration
150+
151+
Pros:
152+
153+
- low risk
154+
- easy to stop if the benefits are smaller than expected
155+
- preserves current design tokens and Naive UI integration
156+
- lets the team learn where Tailwind actually helps
157+
158+
Cons:
159+
160+
- mixed styling models for some time
161+
- requires discipline to avoid ad hoc utility usage
162+
163+
Assessment: viable.
164+
165+
### Hybrid Approach With Guardrails
166+
167+
This means Tailwind is introduced only for selected categories of work while SCSS remains the default for the rest.
168+
169+
Recommended usage boundaries:
170+
171+
- use Tailwind for page layout, spacing, simple cards, and simple wrappers
172+
- keep SCSS for complex stateful widgets, `:deep(...)` overrides, editor internals, animation-heavy UI, and third-party DOM styling
173+
- keep the existing token system as the source of truth
174+
175+
Assessment: best option.
176+
177+
## Recommended Plan
178+
179+
### Phase 1: Proof Of Fit
180+
181+
- add Tailwind to `spx-gui` without changing existing styling
182+
- map Tailwind theme values to the current `--ui-*` tokens where practical
183+
- define custom breakpoints that match current responsive behavior
184+
- document when Tailwind is allowed and when local SCSS should remain the default
185+
186+
Success criteria:
187+
188+
- build works cleanly with Vite
189+
- no conflicts with current global styles or Naive UI theme overrides
190+
- a pilot page can use Tailwind without introducing duplicated design values
191+
192+
### Phase 2: Pilot Migration
193+
194+
Choose one small, layout-oriented area first. Good candidates are community or tutorial pages, not the editor core.
195+
196+
Suggested pilot targets:
197+
198+
- [spx-gui/src/components/community/CenteredWrapper.vue](../../spx-gui/src/components/community/CenteredWrapper.vue)
199+
- community listing or detail sections with mostly layout styling
200+
- simple UI wrappers that do not depend heavily on `:deep(...)`
201+
202+
Avoid as first pilots:
203+
204+
- editor navbar and editor panels
205+
- Monaco-related UI
206+
- waveform, drag-and-drop, or resize-heavy components
207+
- components that mainly customize Naive UI internals
208+
209+
Success criteria:
210+
211+
- the converted code is shorter or clearer than the current SCSS
212+
- design stays visually identical
213+
- AI-assisted edits become easier in practice, not just in theory
214+
215+
### Phase 3: Decide Whether To Expand
216+
217+
After the pilot, compare:
218+
219+
- implementation speed
220+
- readability in code review
221+
- consistency with existing design tokens
222+
- regression rate
223+
- amount of residual SCSS still required
224+
225+
If the pilot does not show a clear gain, stop and keep the current styling model.
226+
227+
If the pilot is successful, expand only into other layout-heavy areas.
228+
229+
## Recommendation
230+
231+
Tailwind CSS is worth evaluating in `spx-gui`, but only as a constrained utility layer.
232+
233+
It is not worth pursuing as a near-term full migration target because the project already has:
234+
235+
- a functioning token system
236+
- a custom UI component layer
237+
- Naive UI theme integration
238+
- many component-local scoped SCSS blocks
239+
- a meaningful number of deep selectors and complex editor surfaces
240+
241+
The practical recommendation for issue `#2981` is:
242+
243+
- conclude that Tailwind is feasible
244+
- reject full migration for now
245+
- recommend a hybrid incremental pilot
246+
- make the pilot target a simple community or tutorial area before touching editor internals
247+
248+
## Suggested Next Step
249+
250+
If the team wants to continue after this assessment, the next task should be a small proof-of-concept PR that:
251+
252+
- installs Tailwind in `spx-gui`
253+
- defines the minimal theme bridge to current tokens
254+
- converts one low-risk page or wrapper component
255+
- records what became simpler and what still required SCSS

0 commit comments

Comments
 (0)