Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Modify the theme switching logic and add a new theme template to CLI. #1143

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

xuanlid
Copy link
Contributor

@xuanlid xuanlid commented Feb 25, 2025

English | 简体中文

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • Built its own designer, fully self-validated

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

Background and solution

1.修改主题切换逻辑,默认值改成从注册表中的themes获取。
只有亮色和暗色两种默认主题的情况下,保持原来的逻辑,点击直接切换主题
用户添加了自定义主题,出现选择列表,在列表中切换主题
2.添加新主题模板
在终端中,用命令创建新主题,选择theme类型,添加主题模板,输入主题名称:demo-theme
在demo-theme下可以看到新创建的主题,cd demo-theme && pnpm i
将主题接入设计器

416459656-10d723c7-de92-4c2a-9d9f-e3b989492e21

12

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Introduced a new CLI command for effortless theme creation.
    • Added a demo theme template to support custom theme development.
    • Upgraded the UI theme switcher with a popover for a more intuitive selection experience.
    • Enhanced theme definitions with additional properties for improved metadata.
  • Documentation
    • Provided a README outlining the demo theme template.
  • Refactor
    • Revamped theme management to allow for dynamic loading of themes.
  • Style
    • Implemented new hover styling for the theme selection interface.
    • Added a new CSS class for enhanced theme list styling.
    • Introduced a new CSS variable for dynamic theming based on the custom theme.

Copy link
Contributor

coderabbitai bot commented Feb 25, 2025

Walkthrough

This pull request updates theme definitions across multiple packages by expanding the metadata of themes in the design registry. The CLI now supports a new command for creating themes with an associated template, which includes necessary configuration files and assets. Additionally, the theme switch functionality in the toolbar has been restructured to incorporate a popover for dynamic theme selection. The changes also refactor theme management logic to dynamically populate theme data and update associated CSS variables.

Changes

File(s) Change Summary
packages/design-core/registry.js Updated theme definitions: replaced title with text, label, icon, and oppositeTheme for both light and dark themes.
packages/engine-cli/src/commands/create.js,
packages/engine-cli/src/index.js
Added new createTheme(name) function and CLI command create-theme <name>; updated selection prompt and type mapping to support theme creation.
packages/engine-cli/template/theme/...
(README.md, index.js, meta.js, package.json, src/styles/vars.less, vite.config.js)
Created a new theme template package, including demo README, module exports with metadata and empty API object, package configuration for Vite builds, and custom CSS variable definitions.
packages/toolbars/themeSwitch/src/...
(Main.vue, composable/index.js, styles/vars.less, vite.config.js)
Refactored theme switching: replaced toolbar with a tiny-popover for theme selection, added new methods and reactive properties (themeItemChange, changeThemeType, themeShowType, showpopover), and updated theme state management to include themeIcon.

Sequence Diagram(s)

sequenceDiagram
    participant User as "User"
    participant CLI as "CLI"
    participant FS as "File System"
    
    User->>CLI: Run "create-theme <name>" command
    CLI->>CLI: Invoke createTheme(name)
    CLI->>FS: Copy theme template files
    FS-->>CLI: Confirm copy
    CLI->>User: Log completion message
Loading
sequenceDiagram
    participant User
    participant ThemeSwitch as "Theme Switch Component"
    participant State as "Theme State"
    
    User->>ThemeSwitch: Click toolbar button
    ThemeSwitch->>ThemeSwitch: Execute changeThemeType()
    alt Show Popover
        ThemeSwitch->>User: Display tiny-popover with theme list
        User->>ThemeSwitch: Select a theme
        ThemeSwitch->>State: Invoke themeItemChange(theme)
        State-->>ThemeSwitch: Update theme and themeIcon
        ThemeSwitch->>User: Close popover
    else Direct Change
        ThemeSwitch->>State: Apply theme change directly
    end
Loading

Possibly related PRs

  • feat(refactor/theme): change incorrect css variables to the common variables and delete theme/base.less #1049: The changes in the main PR, which involve updating theme definitions and properties in packages/design-core/registry.js, are related to the modifications in the retrieved PR that standardizes CSS variables and removes the base.less files, as both PRs focus on enhancing the theme structure and consistency in variable usage.
  • feat: Modify css variables #1051: The changes in the main PR, which involve updating theme definitions with new properties in the themes array, are related to the retrieved PR that modifies CSS variables, as both involve enhancements to theme management and styling, specifically through the use of CSS variables for themes.
  • feat:add theme switching plugin #1070: The changes in the main PR, which involve modifications to theme definitions in packages/design-core/registry.js, are related to the retrieved PR that adds a theme switching plugin, as both involve enhancements to theme management and definitions within the application.

Suggested labels

refactor-main

Suggested reviewers

  • lichunn
  • hexqi

Poem

I'm a rabbit hopping with glee,
Celebrating changes both fresh and free.
Themes now sparkle with text and icon,
New commands bloom like a garden at dawn.
In every line of code, a carrot so sweet,
A whimsical journey with every beat.
Hoppity, hoppy—coding can't be beat!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b1c97e and b678fec.

📒 Files selected for processing (3)
  • packages/engine-cli/template/theme/index.js (1 hunks)
  • packages/engine-cli/template/theme/src/common.less (1 hunks)
  • packages/engine-cli/template/theme/src/styles/vars.less (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/engine-cli/template/theme/src/common.less
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/engine-cli/template/theme/src/styles/vars.less
  • packages/engine-cli/template/theme/index.js
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: push-check

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the enhancement New feature or request label Feb 25, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
packages/toolbars/themeSwitch/src/composable/index.js (1)

15-15: Reactive state definition
themeState is defined as an empty reactive object. Consider initializing default properties here for clarity, though this approach also works fine.

packages/toolbars/themeSwitch/src/Main.vue (3)

3-9: Reusable popover width
Consider extracting the hardcoded width="130" into a named constant or prop for easier maintenance. Otherwise, this is a clean setup.


10-19: Dynamically rendered theme list
This is straightforward. Consider adding an aria-label or role for improved accessibility.


21-34: Integration with collapse view
Nice approach to show a radio group only under collapse. For better i18n, consider translating the “主题” text if needed.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d51ad4 and 3de629f.

📒 Files selected for processing (13)
  • packages/design-core/registry.js (1 hunks)
  • packages/engine-cli/src/commands/create.js (1 hunks)
  • packages/engine-cli/src/index.js (4 hunks)
  • packages/engine-cli/template/theme/README.md (1 hunks)
  • packages/engine-cli/template/theme/index.js (1 hunks)
  • packages/engine-cli/template/theme/meta.js (1 hunks)
  • packages/engine-cli/template/theme/package.json (1 hunks)
  • packages/engine-cli/template/theme/src/styles/vars.less (1 hunks)
  • packages/engine-cli/template/theme/vite.config.js (1 hunks)
  • packages/toolbars/themeSwitch/src/Main.vue (3 hunks)
  • packages/toolbars/themeSwitch/src/composable/index.js (3 hunks)
  • packages/toolbars/themeSwitch/src/styles/vars.less (1 hunks)
  • packages/toolbars/themeSwitch/vite.config.js (1 hunks)
✅ Files skipped from review due to trivial changes (6)
  • packages/engine-cli/template/theme/src/styles/vars.less
  • packages/engine-cli/template/theme/README.md
  • packages/engine-cli/template/theme/vite.config.js
  • packages/engine-cli/template/theme/index.js
  • packages/engine-cli/template/theme/package.json
  • packages/engine-cli/template/theme/meta.js
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: push-check
🔇 Additional comments (18)
packages/toolbars/themeSwitch/src/styles/vars.less (1)

4-6: LGTM! Well-structured CSS variable definition.

The new .theme-list class and its variable follow the established naming conventions and properly reuse existing theme variables.

packages/engine-cli/src/index.js (3)

37-42: LGTM! Well-structured command implementation.

The new create-theme command follows the established pattern and includes bilingual descriptions.


61-65: LGTM! Consistent theme option implementation.

The theme option in the selection prompt maintains consistency with other options and includes clear descriptions.


82-83: LGTM! Clean typeMapper update.

The typeMapper update is clean and maintains the object's structure.

packages/design-core/registry.js (2)

73-76: Looks good!
The introduction of text, label, icon, and oppositeTheme clarifies theme metadata. Good job on making the theme definitions more descriptive.


80-83: Consistent approach for dark theme
Mirrors the structure used for the light theme. This ensures uniformity in how themes are defined and referenced.

packages/toolbars/themeSwitch/src/composable/index.js (4)

2-8: Imports are well-structured
All relevant methods from @opentiny/tiny-engine-meta-register are imported cleanly.


11-11: Use of mutable variable for dynamic data
Declaring THEME_DATA with let is reasonable if it needs reassigning at runtime.


13-13: Initializing a null default theme
Setting DEFAULT_THEME to null before loading ensures safe initialization.


27-27: Icon assignment is consistent
Assigning themeIcon here aligns with the rest of the theme properties. This keeps the data flow consistent.

packages/toolbars/themeSwitch/src/Main.vue (8)

41-41: Use of ref
Importing ref is correct for managing showpopover.


43-44: Popover import
Importing Popover from @opentiny/vue aligns with the new usage.


49-50: Component registration
TinyRadioGroup and TinyPopover are properly registered.


75-76: Using themeIcon
Substituting state.theme with state.themeIcon improves clarity.


77-86: Filtering for standard themes
themeShowType relies on checking if only light/dark exist. Confirm that custom themes with label ‘light’ or ‘dark’ won't break the logic.


97-103: Conditional popover logic
If only two themes exist, switch directly; otherwise, open the popover. This is an efficient solution.


105-108: Graceful popover closing
themeItemChange properly closes the popover after switching. Consider a safety check if the provided theme doesn’t exist, though likely not an issue.


126-139: Styling defines readable hover states
The .theme-item hover and .active styles are consistent with typical UI patterns. Looks good.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
packages/toolbars/themeSwitch/src/Main.vue (4)

3-9: Consider adding aria-label for accessibility.

The popover should have an aria-label to improve accessibility for screen readers.

 <tiny-popover
   width="130"
   trigger="manual"
   v-model="showpopover"
   :visible-arrow="false"
   popper-class="theme-popover"
+  aria-label="Theme Selection"
 >

11-18: Add keyboard navigation support.

The theme list should be keyboard navigable for better accessibility.

 <div class="theme-list">
   <div
     v-for="item in THEME_DATA"
     :key="item.label"
     :class="['theme-item', { active: state.theme === item.label }]"
     @click="themeItemChange(item.label)"
+    tabindex="0"
+    role="button"
+    @keyup.enter="themeItemChange(item.label)"
   >
     {{ item.text }}
   </div>

80-87: Simplify theme type detection logic.

The theme type detection can be simplified using array length comparison.

 const themeShowType = computed(() => {
-  let filterList = THEME_DATA.filter((item) => item.label === 'light' || item.label === 'dark') || []
-  if (THEME_DATA.length === filterList.length) {
-    return true
-  } else {
-    return false
-  }
+  const filterList = THEME_DATA.filter((item) => item.label === 'light' || item.label === 'dark')
+  return THEME_DATA.length === filterList.length
 })

127-138: Add transition for hover effect.

Consider adding a smooth transition for the hover effect to improve the user experience.

 .theme-list {
   .theme-item {
     padding: 4px 16px;
     margin: 0 -16px;
+    transition: background-color 0.2s ease;
     &:hover {
       background-color: var(--te-toolbar-theme-popover-list-item-bg-color-hover);
     }
   }
   .active {
     background-color: var(--te-toolbar-theme-popover-list-item-bg-color-hover);
   }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3de629f and 47de899.

📒 Files selected for processing (1)
  • packages/toolbars/themeSwitch/src/Main.vue (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: push-check
🔇 Additional comments (1)
packages/toolbars/themeSwitch/src/Main.vue (1)

89-92:

❓ Verification inconclusive

Add error handling for missing opposite theme.

The oppositeTheme property might be undefined for custom themes.


🏁 Script executed:

#!/bin/bash
# Check if all themes have oppositeTheme defined
ast-grep --pattern $'const theme = {
  $$$
  oppositeTheme: $_,
  $$$
}'

Length of output: 73


Update Error Handling for Missing oppositeTheme

The current implementation in packages/toolbars/themeSwitch/src/Main.vue:

const toChangeTheme = () => {
  const theme = getTheme(state.theme).oppositeTheme
  themeChange(theme)
}

assumes that getTheme(state.theme) always returns an object with a defined oppositeTheme. However, for custom themes that might omit this property, this can lead to runtime errors. Although our initial AST search didn’t return any occurrences (likely due to the structure of theme definitions being different), it's important to proactively verify and handle such cases.

Suggested Action:

  • Introduce a check to confirm that oppositeTheme is defined before calling themeChange(). For example, you could return an error message or fallback to a default value if it’s missing.

Please manually verify that theme definitions across the codebase (e.g., those returned by getTheme) indeed have proper fallbacks or defaults in case oppositeTheme is undefined.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
packages/toolbars/themeSwitch/src/Main.vue (3)

3-9: Consider making the popover width responsive or using min-width instead

The popover width is hardcoded to "130", which might not accommodate all theme names, especially if custom themes with longer names are added.

-      width="130"
+      min-width="130"
+      max-width="200"

24-24: Consider internationalizing the hardcoded text

The text "主题" (theme) is hardcoded in the template, which may cause issues for internationalization.

-              <div class="toolbar-theme-switch-radio-title">主题</div>
+              <div class="toolbar-theme-switch-radio-title">{{ t('theme') }}</div>

You would need to integrate with your i18n solution and import the translation function.


80-87: Avoid hardcoding theme names and consider caching the computation

The filtering logic hardcodes "light" and "dark" theme names, which could make the code less maintainable if theme identifiers change.

const themeShowType = computed(() => {
-  let filterList = THEME_DATA.filter((item) => item.label === 'light' || item.label === 'dark') || []
+  const defaultThemes = ['light', 'dark'] // Consider moving to constants
+  let filterList = THEME_DATA.filter((item) => defaultThemes.includes(item.label)) || []
  if (THEME_DATA.length === filterList.length) {
    return true
  } else {
    return false
  }
})
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 47de899 and 4b1c97e.

📒 Files selected for processing (2)
  • packages/toolbars/themeSwitch/src/Main.vue (3 hunks)
  • packages/toolbars/themeSwitch/src/styles/vars.less (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/toolbars/themeSwitch/src/styles/vars.less
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: push-check
🔇 Additional comments (9)
packages/toolbars/themeSwitch/src/Main.vue (9)

10-19: Good implementation of the theme list with active state tracking

The theme list implementation correctly uses v-for to iterate through available themes and tracks the active state by comparing with the current theme.


28-28: Good use of dynamic binding for vertical layout

Using the themeShowType to determine the layout direction is a smart approach that adapts the UI based on available themes.


42-45: Import updates correctly support new functionality

The addition of ref and Popover imports properly supports the new reactive state and component needs.


77-78: Good transition from theme to themeIcon for icon display

Changing from state.theme to state.themeIcon suggests a better separation of concerns where the theme identifier and its visual representation are decoupled.


94-103: Good decision logic for theme switching based on available themes

The implementation smartly determines whether to directly toggle between themes or show a popover based on the available themes, improving the user experience when multiple themes are available.


105-108: Good implementation of theme item selection with popover management

The themeItemChange method correctly handles both the theme change and popover visibility state.


110-122: Comprehensive return statement with all necessary functions and state

The updated return statement properly includes all the new properties and methods needed by the template.


126-139:

✅ Verification successful

Good use of CSS variables for theme-specific styling

The styles properly use CSS variables for theming hover and active states, which allows for consistent theming across the application.

Make sure these CSS variables are defined in your theme stylesheet:

  • --te-toolbar-theme-popover-list-item-bg-color-hover
  • --te-toolbar-theme-popover-list-item-bg-color-active

🏁 Script executed:

#!/bin/bash
# Check if the CSS variables are defined
rg --type=less "te-toolbar-theme-popover-list-item-bg-color"

Length of output: 335


Final Verification: CSS Variables Defined Correctly

The CSS variables for theming (--te-toolbar-theme-popover-list-item-bg-color-hover and --te-toolbar-theme-popover-list-item-bg-color-active) are correctly defined in packages/toolbars/themeSwitch/src/styles/vars.less, ensuring consistent theming across the application.

  • File: packages/toolbars/themeSwitch/src/styles/vars.less
    • --te-toolbar-theme-popover-list-item-bg-color-hover is set to var(--te-common-bg-container)
    • --te-toolbar-theme-popover-list-item-bg-color-active is similarly defined

No further changes are required.


89-92:

❓ Verification inconclusive

Verify that oppositeTheme is always available

The code now relies on the oppositeTheme property being present in the theme data. Ensure this property is always defined for all themes to prevent runtime errors.


🏁 Script executed:

#!/bin/bash
# Check if all themes have an oppositeTheme property
ast-grep --pattern 'oppositeTheme'

Length of output: 34


Below is a suggested next step. The initial ast‑grep run did not report any instances of “oppositeTheme,” which makes it hard to conclude whether all theme objects include it. Please run additional searches to locate both the theme definitions and the getTheme function to confirm if an oppositeTheme is always set. For example, you can run:

#!/bin/bash
# Search for any mention of "oppositeTheme" in the codebase
rg "oppositeTheme" -n .

# Identify where getTheme is imported/defined to locate its associated theme objects
rg "import.*getTheme" -n .

Once you confirm that every theme configuration (or the return value of getTheme) consistently defines an oppositeTheme property, you can safely assume that the runtime is protected against related errors.

Action Required: Confirm theme consistency regarding oppositeTheme.
Please manually verify (or run similar scripts) that all theme objects include the required oppositeTheme property to ensure no runtime issues occur.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant