Skip to content

feat(desktop): expand prompt composer inline#174

Open
JUk1-GH wants to merge 1 commit intoOpenCoworkAI:mainfrom
JUk1-GH:feat/expandable-prompt-input
Open

feat(desktop): expand prompt composer inline#174
JUk1-GH wants to merge 1 commit intoOpenCoworkAI:mainfrom
JUk1-GH:feat/expandable-prompt-input

Conversation

@JUk1-GH
Copy link
Copy Markdown

@JUk1-GH JUk1-GH commented Apr 22, 2026

Summary

  • Add inline expand/collapse controls for the desktop prompt composer once prompt text grows beyond a few lines.
  • Smoothly expand the left panel width by moving the draggable divider to the right, giving the composer more horizontal space.
  • Animate the prompt textarea upward from the bottom in expanded mode, and smoothly restore the original layout on collapse.
  • Add localized labels for the expand/collapse affordance.

Validation

  • pnpm lint -- apps/desktop/src/renderer/src/App.tsx apps/desktop/src/renderer/src/components/chat/PromptInput.tsx apps/desktop/src/renderer/src/store.ts packages/i18n/src/locales/en.json packages/i18n/src/locales/zh-CN.json packages/i18n/src/locales/pt-BR.json
  • pnpm --filter @open-codesign/desktop typecheck
  • pnpm --filter @open-codesign/i18n test
  • pnpm --filter @open-codesign/desktop test
  • pre-commit turbo run test
  • pre-push typecheck + lint
Signed-off-by: juki <chinahujunkai@gmail.com>
@github-actions github-actions Bot added the area:desktop apps/desktop (Electron shell, renderer) label Apr 22, 2026
@hqhq1025 hqhq1025 closed this Apr 23, 2026
@hqhq1025 hqhq1025 reopened this Apr 23, 2026
@JUk1-GH JUk1-GH marked this pull request as ready for review April 23, 2026 06:17
@JUk1-GH
Copy link
Copy Markdown
Author

JUk1-GH commented Apr 23, 2026

原来的输入框太小了,没有自适应变化和展开功能,现在我加了点击外扩角标后,左右面板的可拖拽分割线平滑右移,左侧输入区获得更多宽度,同时输入框从底部向上扩展;点击收起再平滑回到原布局。

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Findings

  • [Major] Escape handling leaks to global shortcuts while composer is expanded — pressing Escape in expanded composer also bubbles to app-level escape bindings (close dialog/view mode changes), causing unintended UI state changes beyond collapse. Evidence: apps/desktop/src/renderer/src/components/chat/PromptInput.tsx:180, apps/desktop/src/renderer/src/App.tsx:164
    Suggested fix:

    const handleDocKeyDown = (e: globalThis.KeyboardEvent) => {
      if (e.key !== 'Escape') return;
      e.preventDefault();
      e.stopPropagation();
      setIsExpanded(false);
    };
  • [Minor] Forced synchronous layout on every textarea change risks typing jank — resizeTextarea performs offsetHeight reflow and is called from onChange, which can degrade input responsiveness as prompt length grows. Evidence: apps/desktop/src/renderer/src/components/chat/PromptInput.tsx:79, apps/desktop/src/renderer/src/components/chat/PromptInput.tsx:229
    Suggested fix:

    function resizeTextarea(el: HTMLTextAreaElement, isExpanded: boolean): boolean {
      const rowHeight = getTextareaLineHeight(el);
      el.style.height = 'auto';
      const trueScrollHeight = el.scrollHeight;
      const nextHeight = isExpanded
        ? Math.min(Math.max(trueScrollHeight, window.innerHeight * 0.4), window.innerHeight * 0.6)
        : Math.min(trueScrollHeight, rowHeight * MAX_TEXTAREA_ROWS);
      el.style.height = `${nextHeight}px`;
      return trueScrollHeight > rowHeight * 2.5;
    }

Summary

  • Review mode: initial
  • Two issues found in the latest diff: one behavioral regression in Escape handling and one input-path performance risk.
  • Required context docs docs/VISION.md and docs/PRINCIPLES.md were not found in this checkout (Not found in repo/docs).
  • Test coverage for the new expand/collapse keyboard interaction and textarea resizing path is missing in this diff.

Testing

  • Not run (automation)

open-codesign Bot

}, []);
if (!isExpanded) return;
const handleDocKeyDown = (e: globalThis.KeyboardEvent) => {
if (e.key === 'Escape') {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Escape here collapses the prompt but still bubbles to window-level escape bindings in App, which can also close dialogs/switch modes. Please consume the event (preventDefault + stopPropagation) when expanded composer handles Escape.


el.style.height = cachedHeight;
// Force a layout recalc so the browser commits the origin height before transitioning
void el.offsetHeight;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

void el.offsetHeight forces sync layout, and this function is called from onChange on each keystroke. This can cause typing jank for long prompts; prefer a non-forced measurement/update path.

@hqhq1025
Copy link
Copy Markdown
Collaborator

感谢您的贡献和反馈 请您看看bot的回复 再修一修bug 谢谢!

@hqhq1025 hqhq1025 added bot-rerun Temporary label to rerun automation and removed bot-rerun Temporary label to rerun automation labels May 1, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Review mode: initial

Findings

  • [Minor] Expand button is focusable via Tab key when visually hidden (opacity-0 + pointer-events-none). Keyboard users may navigate to an invisible control, causing confusion.
    Suggested fix:

    <div
      className={...}
      inert={!showExpandIcon && !isExpanded ? true : undefined}
    >

    Or set tabIndex={-1} on the button when hidden.

  • [Minor] The useEffect resize callback at PromptInput.tsx:167 checks textarea.value === prompt before proceeding, but this condition is always true in a controlled component where prompt is the source of truth. The check adds no value and could confuse readers.
    Suggested fix:

    useEffect(() => {
      const textarea = taRef.current;
      if (textarea) {
        const isOver = resizeTextarea(textarea, isExpanded);
        setShowExpandIcon(isOver);
        if (isExpanded) {
          textarea.focus();
        }
      }
    }, [prompt, isExpanded]);
  • [Minor] No new tests added for the expand/collapse interactions. The PR description mentions pnpm test as validation but does not include unit or integration tests for the new state (isPromptExpanded), resize logic, or Escape key behavior. Consider adding Vitest tests for resizeTextarea and a Playwright interaction test for the expand button.

  • [Minor] The component uses several hardcoded sizing values (h-[14px], w-[14px], p-1.5, text-[14px], leading-[1.55], pl-[14px], pr-[36px], pt-[12px], pb-[44px]) instead of tokens from packages/ui. The existing codebase already has many such values, so this is consistent with current practice, but note that the project hard constraint "Every UI value via packages/ui tokens" is not fully satisfied. Ideally, these values should be defined as CSS custom properties or design tokens.

Questions

  • None

Summary
Review mode: initial. The PR adds a clean inline expand/collapse mechanism for the prompt composer with smooth transitions, i18n labels, and correct store wiring. The changes are scoped and follow existing patterns. No blockers or majors found. The main concerns are the focusable-but-invisible expand button (accessibility), the unnecessary condition in the resize effect, missing test coverage, and partial non-compliance with the UI token constraint (pre-existing pattern). Address the accessibility issue before merging.

Testing

  • Not run (automation).
  • Suggested: Vitest unit test for resizeTextarea edge cases (zero height, overflow threshold). Playwright test to verify expand/collapse click interaction and Escape key collapse.

Open-CoDesign Bot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:desktop apps/desktop (Electron shell, renderer)

2 participants