mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
Improve fork and rewind actions (#1336)
This commit is contained in:
@@ -140,6 +140,23 @@ describe('MessageActions', () => {
|
|||||||
expect(screen.queryByRole('button', { name: 'Rewind' })).toBeNull()
|
expect(screen.queryByRole('button', { name: 'Rewind' })).toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('renders Fork and Rewind as compact icon actions', () => {
|
||||||
|
renderActions({
|
||||||
|
align: 'end',
|
||||||
|
copyText: 'body',
|
||||||
|
showFork: true,
|
||||||
|
showRewind: true,
|
||||||
|
onFork: async () => {},
|
||||||
|
onRewind: async () => {}
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const name of ['Fork', 'Rewind']) {
|
||||||
|
const button = screen.getByRole('button', { name })
|
||||||
|
expect(button.className.split(' ')).toContain('w-5')
|
||||||
|
expect(button.querySelector('svg')).not.toBeNull()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('shows Fork confirm dialog and calls onFork only after confirm', async () => {
|
it('shows Fork confirm dialog and calls onFork only after confirm', async () => {
|
||||||
const onFork = vi.fn(async () => {})
|
const onFork = vi.fn(async () => {})
|
||||||
renderActions({ align: 'start', copyText: 'body', showFork: true, onFork })
|
renderActions({ align: 'start', copyText: 'body', showFork: true, onFork })
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as Popover from '@radix-ui/react-popover'
|
import * as Popover from '@radix-ui/react-popover'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useAuiState } from '@assistant-ui/react'
|
import { useAuiState } from '@assistant-ui/react'
|
||||||
import { CheckIcon, CopyIcon, InfoIcon } from '@/components/icons'
|
import { CheckIcon, CopyIcon, ForkIcon, InfoIcon, RewindIcon } from '@/components/icons'
|
||||||
import { useCopyToClipboard } from '@/hooks/useCopyToClipboard'
|
import { useCopyToClipboard } from '@/hooks/useCopyToClipboard'
|
||||||
import { useTranslation } from '@/lib/use-translation'
|
import { useTranslation } from '@/lib/use-translation'
|
||||||
import { MessageMetadata, buildMessageMetadataLabels, type MessageMetadataProps } from './MessageMetadata'
|
import { MessageMetadata, buildMessageMetadataLabels, type MessageMetadataProps } from './MessageMetadata'
|
||||||
@@ -65,10 +65,10 @@ export function MessageActions({
|
|||||||
title={t('message.fork')}
|
title={t('message.fork')}
|
||||||
aria-label={t('message.fork')}
|
aria-label={t('message.fork')}
|
||||||
disabled={actionsLocked}
|
disabled={actionsLocked}
|
||||||
className="flex h-5 items-center rounded px-1 text-[11px] text-[var(--app-hint)] transition-colors hover:bg-[var(--app-subtle-bg)] hover:text-[var(--app-fg)] disabled:opacity-40"
|
className="flex h-5 w-5 items-center justify-center rounded text-[var(--app-hint)] transition-colors hover:bg-[var(--app-subtle-bg)] hover:text-[var(--app-fg)] disabled:opacity-40"
|
||||||
onClick={() => setForkOpen(true)}
|
onClick={() => setForkOpen(true)}
|
||||||
>
|
>
|
||||||
{t('message.fork')}
|
<ForkIcon className="h-3.5 w-3.5" />
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
) : null}
|
||||||
{showRewind && onRewind ? (
|
{showRewind && onRewind ? (
|
||||||
@@ -77,10 +77,10 @@ export function MessageActions({
|
|||||||
title={t('message.rewind')}
|
title={t('message.rewind')}
|
||||||
aria-label={t('message.rewind')}
|
aria-label={t('message.rewind')}
|
||||||
disabled={actionsLocked}
|
disabled={actionsLocked}
|
||||||
className="flex h-5 items-center rounded px-1 text-[11px] text-[var(--app-hint)] transition-colors hover:bg-[var(--app-subtle-bg)] hover:text-[var(--app-fg)] disabled:opacity-40"
|
className="flex h-5 w-5 items-center justify-center rounded text-[var(--app-hint)] transition-colors hover:bg-[var(--app-subtle-bg)] hover:text-[var(--app-fg)] disabled:opacity-40"
|
||||||
onClick={() => setRewindOpen(true)}
|
onClick={() => setRewindOpen(true)}
|
||||||
>
|
>
|
||||||
{t('message.rewind')}
|
<RewindIcon className="h-3.5 w-3.5" />
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -73,6 +73,31 @@ export function InfoIcon(props: IconProps) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ForkIcon(props: IconProps) {
|
||||||
|
return createIcon(
|
||||||
|
<>
|
||||||
|
<circle cx="6" cy="4" r="1.5" />
|
||||||
|
<circle cx="18" cy="4" r="1.5" />
|
||||||
|
<circle cx="18" cy="20" r="1.5" />
|
||||||
|
<path d="M6 5.5v4.75A5.75 5.75 0 0 0 11.75 16H16.5" />
|
||||||
|
<path d="M12 16a5.75 5.75 0 0 0 5.75-5.75V5.5" />
|
||||||
|
</>,
|
||||||
|
props,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RewindIcon(props: IconProps) {
|
||||||
|
return createIcon(
|
||||||
|
<>
|
||||||
|
<path d="M3 12a9 9 0 1 0 3-6.7" />
|
||||||
|
<polyline points="3 4 3 10 9 10" />
|
||||||
|
</>,
|
||||||
|
props,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/** Composer schedule-send clock — circle + hands (matches ComposerButtons). */
|
/** Composer schedule-send clock — circle + hands (matches ComposerButtons). */
|
||||||
export function ScheduleIcon(props: IconProps) {
|
export function ScheduleIcon(props: IconProps) {
|
||||||
return createIcon(
|
return createIcon(
|
||||||
|
|||||||
Reference in New Issue
Block a user