From 5210f2af717441e1d31076870da022d7b37cdd07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E7=86=B1?= Date: Fri, 17 Jul 2026 21:01:24 +0800 Subject: [PATCH] feat: refine sidebar panel layouts (#7285) --- .../__tests__/MoreFunctions.spec.tsx | 63 +++++++- .../select-function/SelectFunction.tsx | 145 +++++++++++++++--- .../src/views/ThreadCommentPanel.tsx | 1 + 3 files changed, 186 insertions(+), 23 deletions(-) diff --git a/packages/sheets-formula-ui/src/views/more-functions/__tests__/MoreFunctions.spec.tsx b/packages/sheets-formula-ui/src/views/more-functions/__tests__/MoreFunctions.spec.tsx index 3223345e13..106b6587ec 100644 --- a/packages/sheets-formula-ui/src/views/more-functions/__tests__/MoreFunctions.spec.tsx +++ b/packages/sheets-formula-ui/src/views/more-functions/__tests__/MoreFunctions.spec.tsx @@ -77,8 +77,16 @@ const averageInfo: IFunctionInfo = { ], }; +const piInfo: IFunctionInfo = { + functionName: 'PI', + functionType: FunctionType.Math, + description: 'Returns pi.', + abstract: 'Pi.', + functionParameter: [], +}; + class TestDescriptionService { - private readonly _items = [sumInfo, averageInfo]; + private readonly _items = [sumInfo, averageInfo, piInfo]; getDescriptions() { return new Map(this._items.map((item) => [item.functionName, item])); @@ -393,6 +401,59 @@ describe('formula function picker views', () => { container.remove(); }); + it('renders selected function details as structured sections', async () => { + const { injector } = createFormulaViewTestBed(); + + await act(async () => { + root.render( + + SelectionState.values.push(value)} /> + + ); + await Promise.resolve(); + }); + + const details = container.querySelector('[data-u-comp="formula-function-details"]'); + expect(details).not.toBeNull(); + expect(details?.querySelector('[data-u-comp="formula-function-syntax"]')?.textContent).toBe('SUM(number1,...)'); + expect(details?.querySelector('[data-u-comp="formula-function-example"]')?.textContent).toBe('SUM(A1)'); + + const parameters = details?.querySelectorAll('[data-u-comp="formula-function-parameter"]'); + expect(parameters).toHaveLength(1); + expect(parameters?.[0].textContent).toContain('number1Required.First value.'); + }); + + it('omits the parameter list when the selected function has no parameters', async () => { + const { injector } = createFormulaViewTestBed(); + + await act(async () => { + root.render( + + SelectionState.values.push(value)} /> + + ); + await Promise.resolve(); + }); + + const input = container.querySelector('input') as HTMLInputElement; + await act(async () => { + writeInput(input, 'PI'); + await Promise.resolve(); + }); + + const item = Array.from(container.querySelectorAll('li')) + .find((node) => node.textContent === 'PI') as HTMLElement | undefined; + expect(item).toBeDefined(); + + await act(async () => { + item!.click(); + await Promise.resolve(); + }); + + const details = container.querySelector('[data-u-comp="formula-function-details"]'); + expect(details?.children).toHaveLength(2); + }); + it('filters functions by typed text and reports the selected function info', async () => { const { injector } = createFormulaViewTestBed(); diff --git a/packages/sheets-formula-ui/src/views/more-functions/select-function/SelectFunction.tsx b/packages/sheets-formula-ui/src/views/more-functions/select-function/SelectFunction.tsx index 48a6894810..8cb0f34c05 100644 --- a/packages/sheets-formula-ui/src/views/more-functions/select-function/SelectFunction.tsx +++ b/packages/sheets-formula-ui/src/views/more-functions/select-function/SelectFunction.tsx @@ -20,14 +20,13 @@ import type { ISidebarMethodOptions } from '@univerjs/ui'; import type { KeyboardEvent } from 'react'; import type { LocaleKey } from '../../../locale/types'; import { IConfigService, LocaleService } from '@univerjs/core'; -import { borderClassName, clsx, Input, scrollbarClassName, Select } from '@univerjs/design'; +import { borderClassName, clsx, divideYClassName, Input, scrollbarClassName, Select } from '@univerjs/design'; import { CheckMarkIcon } from '@univerjs/icons'; import { IDescriptionService, PLUGIN_CONFIG_KEY_BASE } from '@univerjs/sheets-formula'; import { ISidebarService, useDependency, useObservable } from '@univerjs/ui'; import { useEffect, useState } from 'react'; import { getFunctionTypeValues } from '../../../services/utils'; import { FunctionHelp } from '../function-help/FunctionHelp'; -import { FunctionParams } from '../function-params/FunctionParams'; export interface ISelectFunctionProps { onChange: (functionInfo: IFunctionInfo | null) => void; @@ -209,29 +208,131 @@ export function SelectFunction(props: ISelectFunctionProps) { )} {functionInfo && ( -
- +
+
+
+ {functionInfo.functionName} +
+
+ {functionInfo.description} +
+
- ('sheets-formula-ui.moreFunctions.syntax')} - value={} - /> +
+
+
+ {localeService.t('sheets-formula-ui.moreFunctions.syntax')} +
+
+ +
+
- ('sheets-formula-ui.prompt.helpExample')} - value={`${functionInfo.functionName}(${functionInfo.functionParameter - .map((item) => item.example) - .join(',')})`} - /> +
+
+ {localeService.t('sheets-formula-ui.prompt.helpExample')} +
+
+ {`${functionInfo.functionName}(${functionInfo.functionParameter + .map((item) => item.example) + .join(',')})`} +
+
+
- {functionInfo.functionParameter && - functionInfo.functionParameter.map((item: IFunctionParam) => ( - - ))} + {functionInfo.functionParameter.length > 0 && ( +
+ {functionInfo.functionParameter.map((item: IFunctionParam) => ( +
+
+ + {item.name} + + + {item.require ? required : optional} + +
+
+ {item.detail} +
+
+ ))} +
+ )}
)}
diff --git a/packages/thread-comment-ui/src/views/ThreadCommentPanel.tsx b/packages/thread-comment-ui/src/views/ThreadCommentPanel.tsx index f164a839f5..6d8ec94e26 100644 --- a/packages/thread-comment-ui/src/views/ThreadCommentPanel.tsx +++ b/packages/thread-comment-ui/src/views/ThreadCommentPanel.tsx @@ -163,6 +163,7 @@ export const ThreadCommentPanel = (props: IThreadCommentPanelProps) => { const renderComment = (section: ThreadCommentPanelSection) => (comment: IThreadComment, index: number) => (