refactor(web): use standard sizes for icon actions (#42684)

This commit is contained in:
yyh authored and GitHub committed 2026-09-22 06:20:45 +00:00
1 parent 26d4b9ead8
commit cb044daf60
20 files changed
+55 -33

No files matched your search

@@ -131,7 +131,7 @@ const SnippetInfoDropdown = ({ snippet }: SnippetInfoDropdownProps) => {
render={
<IconButton
aria-label={t(($) => $['operation.more'], { ns: 'common' })}
className="rounded-md data-popup-open:bg-state-base-hover data-popup-open:text-text-secondary"
className="data-popup-open:bg-state-base-hover data-popup-open:text-text-secondary"
>
<span aria-hidden className="i-ri-more-fill size-4" />
</IconButton>
@@ -60,7 +60,7 @@ const ConfigSelect: FC<IConfigSelectProps> = ({ options, onChange, errorMessage,
>
<IconButton
{...getHandleProps(index)}
className="handle size-6 shrink-0 cursor-grab aria-pressed:bg-state-accent-hover"
className="handle shrink-0 cursor-grab aria-pressed:bg-state-accent-hover"
>
<RiDraggable aria-hidden="true" className="size-4 text-text-quaternary" />
</IconButton>
@@ -59,7 +59,7 @@ const VarItem: FC<ItemProps> = ({
<IconButton
{...dragHandleProps}
aria-label={dragHandleProps?.['aria-label'] ?? name}
className="handle pointer-events-none absolute left-1.5 size-6 cursor-grab opacity-0 group-focus-within:pointer-events-auto group-focus-within:opacity-100 group-hover:pointer-events-auto group-hover:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100 aria-pressed:bg-state-accent-hover"
className="handle pointer-events-none absolute left-1.5 cursor-grab opacity-0 group-focus-within:pointer-events-auto group-focus-within:opacity-100 group-hover:pointer-events-auto group-hover:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100 aria-pressed:bg-state-accent-hover"
>
<RiDraggable aria-hidden="true" className="size-4 text-text-tertiary" />
</IconButton>
+1 -1
View File
@@ -160,7 +160,7 @@ const CreatorsFilter = ({ value, onChange }: CreatorsFilterProps) => {
<IconButton
size="sm"
aria-label={resetLabel}
className="absolute top-1/2 right-1 size-5 -translate-y-1/2 text-text-tertiary peer-data-popup-open/creators-trigger:text-text-secondary"
className="absolute top-1/2 right-1 -translate-y-1/2 peer-data-popup-open/creators-trigger:text-text-secondary"
onClick={handleSelectionClear}
>
<span aria-hidden className="i-ri-close-circle-fill h-3.5 w-3.5" />
@@ -119,7 +119,6 @@ export function AccessPointUrl({
) : (
<CopyFeedback
content={value}
className="size-6"
copyLabel={copyLabel}
copiedLabel={copiedLabel}
onCopyError={onCopyError}
@@ -199,7 +199,7 @@ const OpeningSettingModal = ({
>
<IconButton
{...getHandleProps(index)}
className="handle size-6 shrink-0 cursor-grab aria-pressed:bg-state-accent-hover"
className="handle shrink-0 cursor-grab aria-pressed:bg-state-accent-hover"
>
<span aria-hidden="true" className="i-ri-draggable size-4 text-text-quaternary" />
</IconButton>
@@ -7,6 +7,11 @@ import { FormItemValidateStatusEnum, FormTypeEnum } from '@/app/components/base/
import BaseField from '../base-field'
const mockDynamicOptions = vi.fn()
const mockCopy = vi.fn()
vi.mock('foxact/use-clipboard', () => ({
useClipboard: () => ({ copy: mockCopy, copied: false }),
}))
vi.mock('@/hooks/use-i18n', () => ({
useRenderI18nObject: () => (content: Record<string, string>) =>
@@ -74,6 +79,30 @@ describe('BaseField', () => {
})
})
it.each([
{ type: FormTypeEnum.textInput, value: 'server-value', copied: 'server-value' },
{ type: FormTypeEnum.textNumber, value: 0, copied: '0' },
])(
'copies the $type field value through its keyboard-accessible action',
async ({ type, value, copied }) => {
const user = userEvent.setup()
renderBaseField({
formSchema: { type, name: 'value', label: 'Value', required: false, showCopy: true },
defaultValues: { value },
})
await user.click(screen.getByLabelText('Value'))
await user.tab()
const copyButton = screen.getByRole('button', { name: 'common.operation.copy' })
expect(copyButton).toHaveFocus()
await user.keyboard('{Enter}')
expect(mockCopy).toHaveBeenCalledWith(copied)
expect(copyButton).toHaveFocus()
expect(screen.getByLabelText('Value')).toHaveValue(String(value))
},
)
it.each([FormTypeEnum.textInput, FormTypeEnum.secretInput, FormTypeEnum.textNumber])(
'associates the visible label, description and required state for %s',
async (type) => {
@@ -337,11 +337,8 @@ const BaseField = ({
)}
>
<InputGroupInput {...textInputProps} />
<InputGroupAddon align="inline-end" className="pe-0">
<CopyFeedback
content={stringValue ?? ''}
className="size-7 hover:bg-transparent"
/>
<InputGroupAddon align="inline-end" className="pe-0.5">
<CopyFeedback content={stringValue ?? ''} className="hover:bg-transparent" />
</InputGroupAddon>
</InputGroup>
) : (
@@ -385,7 +382,7 @@ const BaseField = ({
{showCopy && (
<CopyFeedback
content={value == null ? '' : String(value)}
className="size-7 shrink-0 hover:bg-transparent"
className="me-0.5 shrink-0 self-center hover:bg-transparent"
/>
)}
</NumberFieldGroup>
@@ -21,10 +21,7 @@ const Card: FC<CardProps> = ({ log }) => {
>
<div className="flex h-8 items-center justify-between">
<div className="font-semibold text-indigo-800">{item.role.toUpperCase()}</div>
<CopyFeedback
className="hidden size-6 group-hover/card:block"
content={item.text}
/>
<CopyFeedback className="hidden group-hover/card:block" content={item.text} />
</div>
<div className="whitespace-pre-line text-text-secondary">{item.text}</div>
</div>
@@ -43,7 +43,7 @@ const PromptLogModal: FC<PromptLogModalProps> = ({ currentLogItem, width, onCanc
<div className="flex items-center">
{currentLogItem.log?.length === 1 && (
<>
<CopyFeedback className="size-6" content={currentLogItem.log[0]!.text} />
<CopyFeedback content={currentLogItem.log[0]!.text} />
<div className="mx-2.5 h-3.5 w-px bg-divider-regular" />
</>
)}
@@ -142,8 +142,8 @@ export default function MarketplaceDetailDialogFrame({
<IconButton
ref={closeButtonRef}
aria-label={t(($) => $['operation.close'], { ns: 'common' })}
size="sm"
className="absolute top-5 right-5 z-10 size-8 rounded-lg"
size="lg"
className="absolute top-5 right-5 z-10"
>
<span aria-hidden className="i-ri-close-line size-4" />
</IconButton>
@@ -30,8 +30,8 @@ export function ReadmeDialog({ detail, open, onOpenChange, triggerId }: ReadmeDi
render={
<IconButton
aria-label={t(($) => $['operation.close'], { ns: 'common' })}
size="sm"
className="static size-8 rounded-lg"
size="lg"
className="static"
>
<span aria-hidden className="i-ri-close-line size-4" />
</IconButton>
@@ -78,7 +78,7 @@ const FieldItem = ({
{!readonly && dragHandleProps && (
<IconButton
{...dragHandleProps}
className="handle pointer-events-none absolute -top-1 -left-1 size-6 cursor-grab opacity-0 group-focus-within:pointer-events-auto group-focus-within:opacity-100 group-hover:pointer-events-auto group-hover:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100 aria-pressed:bg-state-accent-hover"
className="handle pointer-events-none absolute -top-1 -left-1 cursor-grab opacity-0 group-focus-within:pointer-events-auto group-focus-within:opacity-100 group-hover:pointer-events-auto group-hover:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100 aria-pressed:bg-state-accent-hover"
>
<RiDraggable aria-hidden="true" className="size-4 text-text-quaternary" />
</IconButton>
@@ -177,7 +177,7 @@ const VarList: FC<Props> = ({
{canDrag && (
<IconButton
{...keyboardSort.getHandleProps(index)}
className="handle pointer-events-none absolute top-1 -left-6 size-6 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
className="handle pointer-events-none absolute top-1 -left-6 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
>
<span aria-hidden="true" className="i-ri-draggable size-3" />
</IconButton>
@@ -140,7 +140,7 @@ const ConditionWrap: FC<Props> = ({
{!readOnly && casesLength > 1 && (
<IconButton
{...keyboardSort.getHandleProps(index)}
className="handle pointer-events-none absolute top-1 -left-2 z-10 size-6 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
className="handle pointer-events-none absolute top-1 -left-2 z-10 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
>
<span aria-hidden="true" className="i-ri-draggable size-3" />
</IconButton>
@@ -221,7 +221,7 @@ const ConfigPrompt: FC<Props> = ({
{canDrag && (
<IconButton
{...keyboardSort.getHandleProps(index)}
className="handle pointer-events-none absolute top-1 -left-6 size-6 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
className="handle pointer-events-none absolute top-1 -left-6 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
>
<span
aria-hidden="true"
@@ -180,7 +180,7 @@ const ClassList: FC<Props> = ({
{canDrag && (
<IconButton
{...keyboardSort.getHandleProps(index)}
className="handle pointer-events-none absolute top-1.5 left-0.5 z-10 size-6 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
className="handle pointer-events-none absolute top-1.5 left-0.5 z-10 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
>
<span aria-hidden="true" className="i-ri-draggable size-3" />
</IconButton>
@@ -127,7 +127,7 @@ const VarList: FC<Props> = ({ readonly, list, onChange }) => {
{canDrag && (
<IconButton
{...keyboardSort.getHandleProps(index)}
className="handle pointer-events-none absolute top-1 left-1.5 size-6 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
className="handle pointer-events-none absolute top-1 left-1.5 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 focus:pointer-events-auto focus:opacity-100 aria-pressed:pointer-events-auto aria-pressed:opacity-100"
>
<span aria-hidden="true" className="i-ri-draggable size-3" />
</IconButton>
@@ -458,8 +458,8 @@ function AgentKnowledgeRetrievalDialogContent({
render={
<IconButton
aria-label={t(($) => $['operation.close'], { ns: 'common' })}
size="sm"
className="static size-7 shrink-0 rounded-md"
size="lg"
className="-my-0.5 shrink-0"
>
<span aria-hidden className="i-ri-close-line size-4" />
</IconButton>
@@ -392,14 +392,14 @@ export function AgentSkillDetailDialog({
</h2>
)}
</div>
<div className="flex shrink-0 items-center gap-1">
<div className="-my-0.5 flex shrink-0 items-center gap-1">
{detail.onDownloadFile && previewTitle && (
<button
type="button"
aria-label={`${isHeaderDownloadLoading ? tCommon(($) => $['operation.downloading']) : tCommon(($) => $['operation.download'])} ${previewTitle}`}
onClick={() => detail.onDownloadFile?.('header')}
disabled={isHeaderDownloadLoading}
className="flex size-7 shrink-0 items-center justify-center rounded-md text-text-tertiary outline-hidden hover:bg-state-base-hover hover:text-text-secondary focus-visible:bg-state-base-hover focus-visible:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid"
className="flex size-8 shrink-0 items-center justify-center rounded-lg text-text-tertiary outline-hidden hover:bg-state-base-hover hover:text-text-secondary focus-visible:bg-state-base-hover focus-visible:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid"
>
<span
aria-hidden
@@ -416,8 +416,8 @@ export function AgentSkillDetailDialog({
render={
<IconButton
aria-label={tCommon(($) => $['operation.close'])}
size="sm"
className="static size-7 shrink-0 rounded-md"
size="lg"
className="shrink-0"
>
<span aria-hidden className="i-ri-close-line size-4" />
</IconButton>