Skip to content

feat(color-picker): add placement prop#4088

Open
ourcx wants to merge 4 commits into
opentiny:devfrom
ourcx:fix/ColorPicker
Open

feat(color-picker): add placement prop#4088
ourcx wants to merge 4 commits into
opentiny:devfrom
ourcx:fix/ColorPicker

Conversation

@ourcx

@ourcx ourcx commented Feb 20, 2026

Copy link
Copy Markdown
Contributor

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)

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:

What is the current behavior?

Issue Number:4058

What is the new behavior?

主要是给 colorPicker 加了一个位置选项,这样被遮挡的时候可以调个方向,这样影响也比较小,不用处理 dialogBox 的代码🤔

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Color picker supports configurable dropdown placement (top or bottom), defaulting to bottom.
  • Documentation / Demos

    • Added a demo showcasing the new placement option and updated component docs.
  • Styling

    • Added placement-aware dropdown styles to ensure correct top/bottom positioning.
  • Tests

    • Added end-to-end tests verifying placement behavior.

@coderabbitai

coderabbitai Bot commented Feb 20, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 19f4930f-7e9c-4fe0-a5f7-2d1af42212e3

📥 Commits

Reviewing files that changed from the base of the PR and between 6ceed01 and ecc7394.

📒 Files selected for processing (1)
  • examples/sites/demos/apis/color-picker.js

Walkthrough

Adds a new placement prop (type top | bottom, default bottom) to the ColorPicker, plus docs/demo, E2E test, renderless helper for transition selection, template/stylesheet updates to support placement-aware dropdown rendering, and webdoc registration.

Changes

Cohort / File(s) Summary
API & Webdoc
examples/sites/demos/apis/color-picker.js, examples/sites/demos/pc/app/color-picker/webdoc/color-picker.js
Adds public API entry for placement (type top | bottom, default bottom, localized descriptions, mode: ['pc'], pcDemo: 'placement', meta.stable: '3.30.0') and registers the placement demo in webdoc.
Component (props & template)
packages/vue/src/color-picker/src/index.ts, packages/vue/src/color-picker/src/pc.vue
Introduces placement prop with validator; refactors PC template to wrap the picker in a placement-aware dropdown container, adds dynamic placement CSS class and binds dynamic transition name; component name option added.
Renderless logic
packages/renderless/src/color-picker/vue.ts
Adds and exposes transitionName() which returns 'tiny-zoom-in-bottom' when placement === 'top', otherwise 'tiny-zoom-in-top'.
Styling
packages/theme/src/color-picker/index.less
Adds dropdown positioning styles: &__dropdown, &__dropdown--bottom (top:100% + margin), and &__dropdown--top (bottom:100% + margin).
Demo & Test
examples/sites/demos/pc/app/color-picker/placement.vue, examples/sites/demos/pc/app/color-picker/placement.spec.ts
Adds Vue demo showing placement="top" and default instance; adds Playwright test asserting panel CSS positioning for top vs bottom placements.

Sequence Diagram

sequenceDiagram
    participant User
    participant Component as ColorPicker Component
    participant Renderless as Renderless API
    participant Template as Template Renderer
    participant DOM

    User->>Component: set placement="top" / interact
    Component->>Renderless: provide placement prop
    Renderless->>Renderless: transitionName() computes animation name
    Renderless-->>Component: return transitionName
    Component->>Template: render dropdown with placement class & transition
    Template->>DOM: mount panel with placement styles
    DOM-->>User: panel displayed at configured position
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐇 I nibble at code where placements unfurl,
Top or below — the little panel twirl.
A gentle transition, a hopping delight,
Colors pop neatly, either day or night.
Hooray for the picker — positioned just right!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a 'placement' prop to the color-picker component, which is the primary objective of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/renderless/src/color-picker/vue.ts (1)

6-6: ⚠️ Potential issue | 🔴 Critical

Add transitionName to the exported api array — it's required for the template binding to work.

The api array on line 6 functions as a whitelist. The setup() function in @opentiny/vue-common/src/index.ts iterates through this array and only exposes members from the renderless output (sdk) that are listed in it. Since transitionName (returned from renderless at line 76) is not in the api array, it will not be available in the component's template context, causing the binding :name="transitionName" in pc.vue to be undefined and breaking the transition.

Proposed fix
-export const api = ['state', 'changeVisible', 'onConfirm', 'onCancel', 'onHueUpdate', 'onSVUpdate', 'onColorUpdate']
+export const api = ['state', 'changeVisible', 'onConfirm', 'onCancel', 'onHueUpdate', 'onSVUpdate', 'onColorUpdate', 'transitionName']
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/renderless/src/color-picker/vue.ts` at line 6, The exported api
array (export const api = [...]) is missing the transitionName entry so setup()
only exposes whitelisted renderless fields; add "transitionName" to the api
array so the renderless output's transitionName (returned on the sdk at line 76)
is exposed to the component template and the :name="transitionName" binding
works. Ensure the api array now includes 'transitionName' alongside 'state',
'changeVisible', 'onConfirm', 'onCancel', 'onHueUpdate', 'onSVUpdate', and
'onColorUpdate'.
🧹 Nitpick comments (3)
packages/renderless/src/color-picker/vue.ts (1)

66-70: Inconsistent indentation in the new block.

Line 67 uses 3-space indent and Line 68 uses 4-space indent. The rest of the file uses 2-space indentation.

Proposed fix
-
-   // 根据 placement 决定动画方向
-    const transitionName = () => {
-      return props.placement === 'top' ? 'tiny-zoom-in-bottom' : 'tiny-zoom-in-top'
-    }
+  // 根据 placement 决定动画方向
+  const transitionName = () => {
+    return props.placement === 'top' ? 'tiny-zoom-in-bottom' : 'tiny-zoom-in-top'
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/renderless/src/color-picker/vue.ts` around lines 66 - 70, The new
transitionName arrow function has inconsistent indentation compared to the file
style; update the indentation of the transitionName function body and its return
line to match the project's 2-space indent convention (the function named
transitionName using props.placement should be indented with two spaces for its
block and return statement).
packages/vue/src/color-picker/src/index.ts (1)

55-62: Minor formatting inconsistency: missing space before {.

All other prop definitions in this file use propName: { with a space before the brace. Line 56 has placement:{ without a space.

Proposed fix
-    placement:{
+    placement: {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vue/src/color-picker/src/index.ts` around lines 55 - 62, The
placement prop definition is missing a space before the opening brace (currently
`placement:{`); update the placement property in the props object (the placement
prop in this file) to match the project's prop formatting style by adding a
space so it reads `placement: {`, ensuring consistency with other prop
definitions in this module.
examples/sites/demos/pc/app/color-picker/placement.vue (1)

23-27: Unused scoped CSS class .demo-margin.

The class demo-margin is defined here but no element in the template uses it. Either apply the class to the picker wrappers or remove the style block.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/sites/demos/pc/app/color-picker/placement.vue` around lines 23 - 27,
The stylesheet defines a scoped CSS class .demo-margin that is unused; either
remove the entire <style scoped> block or apply the class to the relevant
elements (e.g., the picker wrapper elements in placement.vue such as the
container(s) around the ColorPicker components or any .picker-wrapper-like divs)
so the margin is applied; update the template to add class="demo-margin" to
those wrapper elements (or delete the .demo-margin rule) to eliminate the unused
style.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/sites/demos/pc/app/color-picker/placement.spec.ts`:
- Around line 4-10: The test "placement" fails because it never navigates to the
demo and uses non-existent selectors and controls; fix it by adding await
page.goto('color-picker#placement') at the start of the test, remove any
interaction with the non-existent '#placement' select, and instead open the
relevant tiny-color-picker instances (e.g., use
page.locator('tiny-color-picker').nth(0) / .nth(1) and click their toggle to
show the dropdown) then assert on the real dropdown selector
'.tiny-color-picker__dropdown' and its placement modifier classes (check for
'.tiny-color-picker__dropdown--top' for the first picker and
'.tiny-color-picker__dropdown--bottom' for the second) rather than expecting
'.t-color-picker__panel' or calling selectOption on '#placement'.

In `@examples/sites/demos/pc/app/color-picker/placement.vue`:
- Around line 1-6: The demo is missing the dynamic <select id="placement"> the
E2E test expects; add a select bound to a placement data property and use that
property for the tiny-color-picker placement prop instead of hard-coding "top".
Specifically, in the component that currently renders <tiny-color-picker
v-model="color" placement="top" /> and <tiny-color-picker v-model="color" />,
replace the static placement with a reactive placement variable (e.g.,
placement) and add a <select id="placement"> with options like "top", "bottom",
"left", "right" bound via v-model="placement"; ensure the component's setup/data
defines and exports the placement variable so the pickers use
:placement="placement" and the test can toggle the select.

In `@examples/sites/demos/pc/app/color-picker/webdoc/color-picker.js`:
- Around line 244-257: The features entry for placement references demos:
['placement'] but there is no matching demos array item with demoId 'placement';
add a demos array object with demoId: 'placement' including name, desc and
codeFiles (similar to existing entries like demoId 'color-mode') placed before
the features array so the docs renderer can find and render the placement demo —
update the demos array (the list where other demo objects live) to include this
new entry referencing the placement demoId and the appropriate code file names.

In `@packages/vue/src/color-picker/src/pc.vue`:
- Line 17: transitionName is currently a function but is being passed as a
function reference to <Transition>, causing the name prop to be a function
instead of a string; fix by returning a string instead of a function: either
invoke transitionName in the template (change :name="transitionName" to
:name="transitionName()" in pc.vue) or (preferred) change the renderless
implementation in renderless/src/color-picker/vue.ts to expose transitionName as
a computed/string-valued property (e.g., make transitionName a computed that
returns props.placement === 'top' ? 'tiny-zoom-in-bottom' : 'tiny-zoom-in-top')
so the existing :name="transitionName" receives a string.
- Around line 70-72: The exported API array for the color-picker component is
missing 'transitionName', so although renderless.vue.ts's renderless function
returns transitionName, it isn't exposed by setup; add 'transitionName' to the
exported api array (the array referenced by setup in pc.vue) so setup({ props,
context, renderless, api }) spreads and exposes transitionName to the template;
update the api export to include the string 'transitionName' alongside the
existing symbols.

---

Outside diff comments:
In `@packages/renderless/src/color-picker/vue.ts`:
- Line 6: The exported api array (export const api = [...]) is missing the
transitionName entry so setup() only exposes whitelisted renderless fields; add
"transitionName" to the api array so the renderless output's transitionName
(returned on the sdk at line 76) is exposed to the component template and the
:name="transitionName" binding works. Ensure the api array now includes
'transitionName' alongside 'state', 'changeVisible', 'onConfirm', 'onCancel',
'onHueUpdate', 'onSVUpdate', and 'onColorUpdate'.

---

Nitpick comments:
In `@examples/sites/demos/pc/app/color-picker/placement.vue`:
- Around line 23-27: The stylesheet defines a scoped CSS class .demo-margin that
is unused; either remove the entire <style scoped> block or apply the class to
the relevant elements (e.g., the picker wrapper elements in placement.vue such
as the container(s) around the ColorPicker components or any
.picker-wrapper-like divs) so the margin is applied; update the template to add
class="demo-margin" to those wrapper elements (or delete the .demo-margin rule)
to eliminate the unused style.

In `@packages/renderless/src/color-picker/vue.ts`:
- Around line 66-70: The new transitionName arrow function has inconsistent
indentation compared to the file style; update the indentation of the
transitionName function body and its return line to match the project's 2-space
indent convention (the function named transitionName using props.placement
should be indented with two spaces for its block and return statement).

In `@packages/vue/src/color-picker/src/index.ts`:
- Around line 55-62: The placement prop definition is missing a space before the
opening brace (currently `placement:{`); update the placement property in the
props object (the placement prop in this file) to match the project's prop
formatting style by adding a space so it reads `placement: {`, ensuring
consistency with other prop definitions in this module.

Comment on lines +4 to +10
test('placement', async ({ page }) => {
// 测试
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.locator('#placement').selectOption('top')
await expect(page.locator('.t-color-picker__panel')).toHaveCSS('top', '0px')
await page.locator('#placement').selectOption('bottom')
await expect(page.locator('.t-color-picker__panel')).toHaveCSS('top', 'auto')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how other color-picker e2e tests are structured (page.goto, selectors)
find examples/sites/demos/pc/app/color-picker -name "*.spec.ts" -type f | head -10

Repository: opentiny/tiny-vue

Length of output: 655


🏁 Script executed:

#!/bin/bash
# Look at a few other spec files for structure
fd 'spec.ts' examples/sites/demos/pc/app/color-picker --exec head -15 {}

Repository: opentiny/tiny-vue

Length of output: 5827


🏁 Script executed:

#!/bin/bash
# Check what CSS classes the color-picker actually uses
rg 't-color-picker__panel' packages/ --type ts --type vue

Repository: opentiny/tiny-vue

Length of output: 88


🏁 Script executed:

#!/bin/bash
# Check for tiny-color-picker__dropdown
rg 'tiny-color-picker__dropdown' packages/ --type ts --type vue

Repository: opentiny/tiny-vue

Length of output: 88


🏁 Script executed:

#!/bin/bash
# Also search more broadly for color-picker panel classes
rg 'color-picker.*panel|__panel' packages/vue/src/color-picker/ -t ts -t vue

Repository: opentiny/tiny-vue

Length of output: 88


🏁 Script executed:

#!/bin/bash
# Search for color-picker panel class definitions in source files
rg 'color-picker.*panel' packages/vue/src/color-picker/ -A 2 -B 2

Repository: opentiny/tiny-vue

Length of output: 43


🏁 Script executed:

#!/bin/bash
# Look for all CSS classes in the color-picker component files
find packages/vue/src/color-picker -type f \( -name "*.ts" -o -name "*.vue" \) | xargs grep -h "class=" | head -20

Repository: opentiny/tiny-vue

Length of output: 218


🏁 Script executed:

#!/bin/bash
# Check the placement.vue demo file to see what it actually contains
cat examples/sites/demos/pc/app/color-picker/placement.vue 2>/dev/null || echo "File not found"

Repository: opentiny/tiny-vue

Length of output: 444


🏁 Script executed:

#!/bin/bash
# Look for any reference to placement-related elements
rg '#placement' examples/sites/demos/pc/app/color-picker/

Repository: opentiny/tiny-vue

Length of output: 295


Test is missing page navigation and uses incorrect selectors—it will fail immediately.

  1. Missing page.goto(): The test never navigates to the demo page. All other color-picker spec files include await page.goto('color-picker#placement'), but this test omits it entirely. Without navigation, the test runs against a blank page.

  2. Wrong CSS class: The test asserts on .t-color-picker__panel, which doesn't exist in the codebase. The actual color-picker uses .tiny-color-picker__dropdown with placement modifiers (e.g., .tiny-color-picker__dropdown--top, .tiny-color-picker__dropdown--bottom).

  3. Missing #placement select element: The placement.vue demo contains no <select id="placement"> element. It only has two hardcoded <tiny-color-picker> components. The selectOption() calls on lines 7 and 9 will fail because the element doesn't exist.

Add await page.goto('color-picker#placement') at the start and update selectors to match the actual component structure.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/sites/demos/pc/app/color-picker/placement.spec.ts` around lines 4 -
10, The test "placement" fails because it never navigates to the demo and uses
non-existent selectors and controls; fix it by adding await
page.goto('color-picker#placement') at the start of the test, remove any
interaction with the non-existent '#placement' select, and instead open the
relevant tiny-color-picker instances (e.g., use
page.locator('tiny-color-picker').nth(0) / .nth(1) and click their toggle to
show the dropdown) then assert on the real dropdown selector
'.tiny-color-picker__dropdown' and its placement modifier classes (check for
'.tiny-color-picker__dropdown--top' for the first picker and
'.tiny-color-picker__dropdown--bottom' for the second) rather than expecting
'.t-color-picker__panel' or calling selectOption on '#placement'.

Comment on lines +1 to +6
<template>
<div>
<tiny-color-picker v-model="color" placement="top" />
<tiny-color-picker v-model="color"/>
</div>
</template>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Search for placement-related files in the color-picker demo directory
fd 'placement' examples/sites/demos/pc/app/color-picker/

Repository: opentiny/tiny-vue

Length of output: 174


🏁 Script executed:

# Find the placement test file
fd 'placement.spec' examples/

Repository: opentiny/tiny-vue

Length of output: 288


🏁 Script executed:

# Check the structure of the color-picker demo directory
ls -la examples/sites/demos/pc/app/color-picker/ 2>/dev/null | head -20

Repository: opentiny/tiny-vue

Length of output: 1408


🏁 Script executed:

# Read the placement test file to see what it expects
cat -n examples/sites/demos/pc/app/color-picker/placement.spec.ts

Repository: opentiny/tiny-vue

Length of output: 591


🏁 Script executed:

# Read the placement demo file
cat -n examples/sites/demos/pc/app/color-picker/placement.vue

Repository: opentiny/tiny-vue

Length of output: 633


Demo is missing required <select> element for E2E test.

The test placement.spec.ts attempts to interact with a #placement select element at lines 7 and 9 to toggle placement values, but the demo provides no such element. The demo statically sets placement="top" on one picker and uses the default on the other, with no mechanism for dynamic toggling.

Add a <select id="placement"> with options for dynamic placement binding, or update the test to match the static demo implementation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/sites/demos/pc/app/color-picker/placement.vue` around lines 1 - 6,
The demo is missing the dynamic <select id="placement"> the E2E test expects;
add a select bound to a placement data property and use that property for the
tiny-color-picker placement prop instead of hard-coding "top". Specifically, in
the component that currently renders <tiny-color-picker v-model="color"
placement="top" /> and <tiny-color-picker v-model="color" />, replace the static
placement with a reactive placement variable (e.g., placement) and add a <select
id="placement"> with options like "top", "bottom", "left", "right" bound via
v-model="placement"; ensure the component's setup/data defines and exports the
placement variable so the pickers use :placement="placement" and the test can
toggle the select.

Comment thread examples/sites/demos/pc/app/color-picker/webdoc/color-picker.js
/>

<!-- 根据 placement 设置弹出位置 -->
<Transition :name="transitionName">

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the specific file and context around line 17
head -30 packages/vue/src/color-picker/src/pc.vue

Repository: opentiny/tiny-vue

Length of output: 865


🏁 Script executed:

# Find the renderless color-picker implementation
find . -path "*/renderless/src/color-picker*" -name "*.ts" | head -5

Repository: opentiny/tiny-vue

Length of output: 267


🏁 Script executed:

# Search for transitionName definition in renderless
rg -n "transitionName\s*=" packages/renderless/src/ -B2 -A2

Repository: opentiny/tiny-vue

Length of output: 447


🏁 Script executed:

# Check what `@opentiny/vue-common` setup returns
rg -n "export.*setup|return.*{" packages/vue-common/src/ -A3 -B1 | head -50

Repository: opentiny/tiny-vue

Length of output: 170


🏁 Script executed:

# See how other color-picker related files use Transition
rg -n "Transition.*:name" packages/vue/src/color-picker/ -B1 -A1

Repository: opentiny/tiny-vue

Length of output: 276


🏁 Script executed:

# Let's look at the full renderless setup function to see how transitionName is returned
cat -n packages/renderless/src/color-picker/vue.ts | sed -n '1,120p'

Repository: opentiny/tiny-vue

Length of output: 2968


🏁 Script executed:

# Check the full pc.vue file to see the setup integration
cat -n packages/vue/src/color-picker/src/pc.vue

Repository: opentiny/tiny-vue

Length of output: 2919


🏁 Script executed:

# Check how `@opentiny/vue-common` handles setup
rg -n "setup\s*\(" packages/vue-common/src/ -A 10 | head -80

Repository: opentiny/tiny-vue

Length of output: 1241


🏁 Script executed:

# Let's check if there are any computed or unwrap mechanisms for functions in the renderless
rg -n "computed\|unref\|isRef" packages/renderless/src/color-picker/vue.ts

Repository: opentiny/tiny-vue

Length of output: 43


🏁 Script executed:

# Let's look at the `@opentiny/vue-common` setup function implementation
find . -path "*/vue-common/src*" -name "*.ts" -o -name "*.js" | grep -v node_modules | head -10

Repository: opentiny/tiny-vue

Length of output: 431


🏁 Script executed:

# Search for the setup function that's imported in pc.vue
rg -n "export.*setup\|function setup" packages/vue-common/src/ -B2 -A15 | head -100

Repository: opentiny/tiny-vue

Length of output: 43


🏁 Script executed:

# Let's check if there's any special handling in how renderless properties are exposed
rg -n "transitionName\|computed" packages/vue-common/src/ -B2 -A2 | head -80

Repository: opentiny/tiny-vue

Length of output: 43


🏁 Script executed:

# Let's test by looking at how similar components handle functions from renderless
rg -n "Transition.*:name" packages/vue/src/ -l | head -5

Repository: opentiny/tiny-vue

Length of output: 101


🏁 Script executed:

# Check the actual vue-common setup function more carefully
cat -n packages/vue-common/src/index.ts | head -100

Repository: opentiny/tiny-vue

Length of output: 3655


🏁 Script executed:

# Continue reading the setup function
cat -n packages/vue-common/src/index.ts | sed -n '100,200p'

Repository: opentiny/tiny-vue

Length of output: 3713


🏁 Script executed:

# Let's look for the setup function specifically
rg -n "^export.*setup|^const setup|^function setup" packages/vue-common/src/index.ts -A 30

Repository: opentiny/tiny-vue

Length of output: 3122


🏁 Script executed:

# Let's search in all files within vue-common
find packages/vue-common/src -name "*.ts" -exec grep -l "export.*setup" {} \;

Repository: opentiny/tiny-vue

Length of output: 93


🏁 Script executed:

# Let's check if there's a setup function that wraps renderless
rg -rn "export.*setup\s*=" packages/vue-common/src/ -A 20 | head -100

Repository: opentiny/tiny-vue

Length of output: 2855


transitionName is a function, but it's bound as a value — the transition name will not resolve to a string.

In the renderless layer, transitionName is defined as () => { return props.placement === 'top' ? 'tiny-zoom-in-bottom' : 'tiny-zoom-in-top' }. Binding it as :name="transitionName" passes the function reference itself to <Transition>, not its return value. Vue's <Transition> expects a string for name, not a function.

Either invoke it in the template or convert it to a computed property in the renderless layer.

Option A: Invoke in template
-    <Transition :name="transitionName">
+    <Transition :name="transitionName()">
Option B: Convert to computed in renderless (preferred)

In packages/renderless/src/color-picker/vue.ts:

-  const transitionName = () => {
-    return props.placement === 'top' ? 'tiny-zoom-in-bottom' : 'tiny-zoom-in-top'
-  }
+  const transitionName = ctx.computed(() => {
+    return props.placement === 'top' ? 'tiny-zoom-in-bottom' : 'tiny-zoom-in-top'
+  })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Transition :name="transitionName">
<Transition :name="transitionName()">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vue/src/color-picker/src/pc.vue` at line 17, transitionName is
currently a function but is being passed as a function reference to
<Transition>, causing the name prop to be a function instead of a string; fix by
returning a string instead of a function: either invoke transitionName in the
template (change :name="transitionName" to :name="transitionName()" in pc.vue)
or (preferred) change the renderless implementation in
renderless/src/color-picker/vue.ts to expose transitionName as a
computed/string-valued property (e.g., make transitionName a computed that
returns props.placement === 'top' ? 'tiny-zoom-in-bottom' : 'tiny-zoom-in-top')
so the existing :name="transitionName" receives a string.

Comment thread packages/vue/src/color-picker/src/pc.vue
@kagol

kagol commented Feb 28, 2026

Copy link
Copy Markdown
Member

@GaoNeng-wWw 有空麻烦帮忙看下哈,目前颜色选择器似乎不会根据是否贴近浏览器边缘而自动翻转,类似 @floating/ui flip 的效果。

@Issues-translate-bot

Copy link
Copy Markdown

Bot detected the issue body's language is not English, translate it automatically.


@GaoNeng-wWw If you have time, please help me take a look.

@GaoNeng-wWw

Copy link
Copy Markdown
Collaborator

@GaoNeng-wWw 有空麻烦帮忙看下哈,目前颜色选择器似乎不会根据是否贴近浏览器边缘而自动翻转,类似 @floating/ui flip 的效果。

是的,目前是直接用的绝对定位,应该用tooltip组件或者其他类似的组件包一下

@Issues-translate-bot

Copy link
Copy Markdown

Bot detected the issue body's language is not English, translate it automatically.


@GaoNeng-wWw Please take a look when you have time. Currently, the color picker does not seem to automatically flip based on whether it is close to the edge of the browser, similar to the effect of @floating/ui flip.

Yes, absolute positioning is currently used directly. It should be wrapped with the tooltip component or other similar components.

@GaoNeng-wWw GaoNeng-wWw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

样式麻烦老师写到theme文件夹下

@ourcx

ourcx commented Feb 28, 2026

Copy link
Copy Markdown
Contributor Author

@GaoNeng-wWw 有空麻烦帮忙看下哈,目前颜色选择器似乎不会根据是否贴近浏览器边缘而自动翻转,类似 @floating/ui flip 的效果。

是的,目前是直接用的绝对定位,应该用tooltip组件或者其他类似的组件包一下

收到,这几天我改一下

@Issues-translate-bot

Copy link
Copy Markdown

Bot detected the issue body's language is not English, translate it automatically.


@GaoNeng-wWw Please help me take a look when you have time. Currently, the color picker does not seem to automatically flip based on whether it is close to the edge of the browser, similar to the effect of @floating/ui flip.

Yes, absolute positioning is currently used directly. It should be wrapped with the tooltip component or other similar components.

Received, I will change it in the next few days

@GaoNeng-wWw

Copy link
Copy Markdown
Collaborator

PR标题也需要改一下
feat(color-picker): pr描述

@Issues-translate-bot

Copy link
Copy Markdown

Bot detected the issue body's language is not English, translate it automatically.


The PR title also needs to be changed.
feat(color-picker): pr description

@ourcx ourcx force-pushed the fix/ColorPicker branch from c5035ac to 6ceed01 Compare March 8, 2026 02:07
@ourcx

ourcx commented Mar 8, 2026

Copy link
Copy Markdown
Contributor Author

PR标题也需要改一下 feat(color-picker): pr描述

已修改

@Issues-translate-bot

Copy link
Copy Markdown

Bot detected the issue body's language is not English, translate it automatically.


The PR title also needs to be changed feat(color-picker): pr description

Modified

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/renderless/src/color-picker/vue.ts`:
- Around line 68-76: The renderless function defines transitionName but it isn't
exported in the renderless API list, so add "transitionName" to the exported api
array/object (the same structure that contains state, changeVisible, onConfirm,
onCancel) so the setup/filter logic will expose transitionName to the component
instance and the template :name binding will receive it.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 227a3038-8bbb-495c-b580-94f559e29a05

📥 Commits

Reviewing files that changed from the base of the PR and between c5035ac and 6ceed01.

📒 Files selected for processing (8)
  • examples/sites/demos/apis/color-picker.js
  • examples/sites/demos/pc/app/color-picker/placement.spec.ts
  • examples/sites/demos/pc/app/color-picker/placement.vue
  • examples/sites/demos/pc/app/color-picker/webdoc/color-picker.js
  • packages/renderless/src/color-picker/vue.ts
  • packages/theme/src/color-picker/index.less
  • packages/vue/src/color-picker/src/index.ts
  • packages/vue/src/color-picker/src/pc.vue
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/vue/src/color-picker/src/index.ts
  • examples/sites/demos/apis/color-picker.js
  • examples/sites/demos/pc/app/color-picker/webdoc/color-picker.js
  • examples/sites/demos/pc/app/color-picker/placement.spec.ts
  • packages/vue/src/color-picker/src/pc.vue
  • examples/sites/demos/pc/app/color-picker/placement.vue

Comment on lines +68 to +76
const transitionName = () => {
return props.placement === 'top' ? 'tiny-zoom-in-bottom' : 'tiny-zoom-in-top'
}
const api = {
state,
changeVisible,
onConfirm,
onCancel
onCancel,
transitionName

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== color-picker renderless module =="
sed -n '1,120p' packages/renderless/src/color-picker/vue.ts

echo
echo "== color-picker component wiring =="
sed -n '1,220p' packages/vue/src/color-picker/src/pc.vue

echo
echo "== usages of transitionName in the color-picker surface =="
rg -n -C2 '\btransitionName\b' \
  packages/renderless/src/color-picker/vue.ts \
  packages/vue/src/color-picker/src/pc.vue \
  packages/vue/src/color-picker/src/index.ts

Repository: opentiny/tiny-vue

Length of output: 5557


🏁 Script executed:

# Search for other renderless modules to understand the api array pattern
fd -t f 'vue\.ts$' packages/renderless/src --exec head -20 {} \; 2>/dev/null | head -100

# Look for setup function usage patterns across renderless modules
rg -A5 'setup\(\{.*renderless.*api' packages/vue/src --type vue --max-count 5

Repository: opentiny/tiny-vue

Length of output: 2814


🏁 Script executed:

# Check if there are other renderless modules with api arrays and returned methods
rg 'export const api = \[' packages/renderless/src

Repository: opentiny/tiny-vue

Length of output: 19504


🏁 Script executed:

# Look for how setup function is defined or documented
fd -t f '(setup|common)' packages/ -name '*.ts' -name '*.vue' | head -20

Repository: opentiny/tiny-vue

Length of output: 291


🏁 Script executed:

# Find the setup function implementation
fd -type f -name '*.ts' -o -name '*.js' packages/vue-common | head -20

Repository: opentiny/tiny-vue

Length of output: 231


🏁 Script executed:

# Search for setup function definition
rg -l 'export.*setup' packages/vue-common --type ts --type js 2>/dev/null | head -5

Repository: opentiny/tiny-vue

Length of output: 93


🏁 Script executed:

# Look in the common package
find packages -type d -name '*common*' 2>/dev/null

Repository: opentiny/tiny-vue

Length of output: 211


🏁 Script executed:

# Find setup function definition in vue-common
rg -n 'export.*setup' packages/vue-common/src --max-count 10

Repository: opentiny/tiny-vue

Length of output: 395


🏁 Script executed:

# Read the vue-common index to see what's exported
cat packages/vue-common/src/index.ts

Repository: opentiny/tiny-vue

Length of output: 14503


Add transitionName to the exported renderless API list.

transitionName is defined and returned from the renderless function but is not included in the exported api array at Line 6. The setup function filters renderless properties based on this array, so transitionName will not be exposed to the component instance and the :name="transitionName" binding in the template will be undefined.

Suggested fix
-export const api = ['state', 'changeVisible', 'onConfirm', 'onCancel', 'onHueUpdate', 'onSVUpdate', 'onColorUpdate']
+export const api = [
+  'state',
+  'changeVisible',
+  'onConfirm',
+  'onCancel',
+  'onHueUpdate',
+  'onSVUpdate',
+  'onColorUpdate',
+  'transitionName'
+]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/renderless/src/color-picker/vue.ts` around lines 68 - 76, The
renderless function defines transitionName but it isn't exported in the
renderless API list, so add "transitionName" to the exported api array/object
(the same structure that contains state, changeVisible, onConfirm, onCancel) so
the setup/filter logic will expose transitionName to the component instance and
the template :name binding will receive it.

@GaoNeng-wWw GaoNeng-wWw changed the title Fix/color picker feat(color-picker): add placement prop Mar 9, 2026
@github-actions github-actions Bot added the enhancement New feature or request (功能增强) label Mar 9, 2026
@GaoNeng-wWw

GaoNeng-wWw commented Mar 9, 2026

Copy link
Copy Markdown
Collaborator

e2e 有一个测试没有通过,麻烦解决下~
@ourcx

@Issues-translate-bot

Copy link
Copy Markdown

Bot detected the issue body's language is not English, translate it automatically.


e2e has a test that failed @ourcx

Comment thread examples/sites/demos/apis/color-picker.js Outdated
@kagol

kagol commented Mar 11, 2026

Copy link
Copy Markdown
Member

@ourcx 有一个测试用例未通过(https://github.com/opentiny/tiny-vue/actions/runs/22939894425/job/66582457819?pr=4088),执行:pnpm site 本地启动项目的情况下,执行:pnpm test:e2e3 color-picker 可以运行测试用例,查看报错信息,从而进行修复

@Issues-translate-bot

Copy link
Copy Markdown

Bot detected the issue body's language is not English, translate it automatically.


@ourcx There is a test case that failed (https://github.com/opentiny/tiny-vue/actions/runs/22939894425/job/66582457819?pr=4088). Execute: pnpm site. When starting the project locally, execute: pnpm test:e2e3 color-picker. You can run the test case, view the error message, and make repairs.

@GaoNeng-wWw GaoNeng-wWw mentioned this pull request Apr 17, 2026
13 tasks
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.

5 participants