mirror of
https://github.com/stablyai/orca.git
synced 2026-09-29 16:02:50 +00:00
refactor(activity): indicate active scope filters
Display visual indicator and updated aria-label in the options menu when scope filters are applied. Improves visibility of the current filter state and enhances pointer event handling for action buttons.
This commit is contained in:
@@ -5,6 +5,7 @@ import { createRoot, type Root } from 'react-dom/client'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { TooltipProvider } from '@/components/ui/tooltip'
|
||||
import { useAppStore } from '@/store'
|
||||
import { ActivityThreadOptionsMenu } from './ActivityPrototypePage'
|
||||
import type { ActivityGroupBy } from './activity-thread-types'
|
||||
|
||||
@@ -46,6 +47,7 @@ describe('ActivityThreadOptionsMenu', () => {
|
||||
let root: Root
|
||||
|
||||
beforeEach(() => {
|
||||
useAppStore.setState({ agentsVisibleHostIds: null, agentsFilterRepoIds: [] })
|
||||
container = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
root = createRoot(container)
|
||||
@@ -57,6 +59,20 @@ describe('ActivityThreadOptionsMenu', () => {
|
||||
document.body.replaceChildren()
|
||||
})
|
||||
|
||||
it('exposes an active persisted scope visually and in the trigger label', async () => {
|
||||
useAppStore.setState({ agentsVisibleHostIds: ['local'] })
|
||||
|
||||
await act(async () => {
|
||||
root.render(<Harness />)
|
||||
})
|
||||
|
||||
const trigger = container.querySelector<HTMLButtonElement>(
|
||||
'button[aria-label="Thread list options, filters active"]'
|
||||
)
|
||||
expect(trigger).not.toBeNull()
|
||||
expect(trigger?.querySelector('[data-scope-filter-dot]')).not.toBeNull()
|
||||
})
|
||||
|
||||
it('opens without recursively updating composed Radix trigger refs', async () => {
|
||||
await act(async () => {
|
||||
root.render(<Harness />)
|
||||
@@ -191,7 +207,7 @@ describe('ActivityThreadOptionsMenu', () => {
|
||||
expect(document.body.textContent).toContain(
|
||||
'Filters the activity list to show only threads with unread updates.'
|
||||
)
|
||||
expect(unreadItem?.querySelector('svg.lucide-check')).toBeNull()
|
||||
expect(document.querySelector('[data-unread-dot]')).toBeNull()
|
||||
})
|
||||
|
||||
it('renders show child agents checkbox when onShowChildAgentsChange is provided', async () => {
|
||||
|
||||
@@ -96,9 +96,7 @@ function evictPersistedStatuses(identities: readonly AgentStatusCacheIdentity[])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a single activity thread silently (no toast notification).
|
||||
*/
|
||||
/** Clear one completed thread immediately; bulk clearing owns the undo toast. */
|
||||
export function clearActivityThread(thread: AgentPaneThread): boolean {
|
||||
const state = useAppStore.getState()
|
||||
const plan = planClearCompletedActivity([thread], state)
|
||||
|
||||
@@ -165,6 +165,8 @@ describe('ActivityThreadHoverCard and ActivityThreadRow', () => {
|
||||
)
|
||||
expect(clearButton).not.toBeNull()
|
||||
expect(clearButton?.className).toContain('focus-visible:opacity-100')
|
||||
expect(clearButton?.className).toContain('can-hover:pointer-events-none')
|
||||
expect(clearButton?.className).toContain('can-hover:group-hover:pointer-events-auto')
|
||||
expect(clearButton?.className).not.toContain('invisible')
|
||||
|
||||
act(() => clearButton?.click())
|
||||
|
||||
@@ -80,6 +80,12 @@ export function ActivityThreadOptionsMenu({
|
||||
}): React.JSX.Element {
|
||||
const skipCloseAutoFocusRef = React.useRef(false)
|
||||
const scopeFilterActive = useActivityScopeFilterActive()
|
||||
const optionsLabel = scopeFilterActive
|
||||
? translate(
|
||||
'auto.components.activity.ActivityPrototypePage.threadListOptionsFiltered',
|
||||
'Thread list options, filters active'
|
||||
)
|
||||
: translate('auto.components.activity.ActivityPrototypePage.db8a1878b5', 'Thread list options')
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
@@ -93,10 +99,7 @@ export function ActivityThreadOptionsMenu({
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="relative text-muted-foreground"
|
||||
aria-label={translate(
|
||||
'auto.components.activity.ActivityPrototypePage.db8a1878b5',
|
||||
'Thread list options'
|
||||
)}
|
||||
aria-label={optionsLabel}
|
||||
>
|
||||
<ListFilter className="size-3.5" strokeWidth={2.25} />
|
||||
{scopeFilterActive ? (
|
||||
|
||||
@@ -29,7 +29,7 @@ function ActivityThreadRowAction({
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="size-4 p-0 text-muted-foreground opacity-100 transition-opacity hover:text-foreground can-hover:opacity-0 group-hover:opacity-100 focus-visible:opacity-100"
|
||||
className="size-4 p-0 text-muted-foreground transition-opacity hover:text-foreground can-hover:pointer-events-none can-hover:opacity-0 can-hover:group-hover:pointer-events-auto can-hover:group-hover:opacity-100 focus-visible:opacity-100"
|
||||
aria-label={label}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
|
||||
@@ -16161,7 +16161,8 @@
|
||||
"search": "Search",
|
||||
"showUnreadOnly": "Show unread only",
|
||||
"showChildAgents": "Show child agents",
|
||||
"activityOptions": "Activity options"
|
||||
"activityOptions": "Activity options",
|
||||
"threadListOptionsFiltered": "Thread list options, filters active"
|
||||
},
|
||||
"clearCompleted": {
|
||||
"clearedOne": "Cleared 1 completed agent",
|
||||
|
||||
@@ -14180,6 +14180,7 @@
|
||||
"770d458144": "Agrupar por",
|
||||
"795cbf26e2": "Filtrar...",
|
||||
"4616ea39fd": "Ir al workspace",
|
||||
"threadListOptionsFiltered": "Opciones de lista de hilos, filtros activos",
|
||||
"markThreadRead": "Marcar hilo como leído",
|
||||
"59b131fbd9": "Marcar hilo como no leído",
|
||||
"beb2c19173": "No leído",
|
||||
@@ -14187,6 +14188,9 @@
|
||||
"22b22034bc": "Terminal independiente no disponible en Actividad.",
|
||||
"afdc2139a8": "Terminal de Agent cerrada. Abre una nueva terminal en este workspace para continuar."
|
||||
},
|
||||
"ActivityThreadRow": {
|
||||
"clearNotification": "Borrar notificación"
|
||||
},
|
||||
"ActivityTitlebarControls": {
|
||||
"f915168c8e": "no leído",
|
||||
"d6a8de3934": "agentes",
|
||||
|
||||
@@ -15462,12 +15462,16 @@
|
||||
"770d458144": "Grouper l'activité des agents par",
|
||||
"795cbf26e2": "Filtrer...",
|
||||
"4616ea39fd": "Aller à l'espace de travail",
|
||||
"threadListOptionsFiltered": "Options de la liste des fils, filtres actifs",
|
||||
"59b131fbd9": "Marquer le fil comme non lu",
|
||||
"beb2c19173": "Non lus",
|
||||
"5651b216c6": "Projet inconnu",
|
||||
"22b22034bc": "Terminal autonome indisponible dans Activité.",
|
||||
"afdc2139a8": "Terminal de l'agent fermé. Ouvrez un nouveau terminal dans cet espace de travail pour continuer."
|
||||
},
|
||||
"ActivityThreadRow": {
|
||||
"clearNotification": "Effacer la notification"
|
||||
},
|
||||
"ActivityTitlebarControls": {
|
||||
"f915168c8e": "non lu",
|
||||
"d6a8de3934": "agents",
|
||||
|
||||
@@ -14180,6 +14180,7 @@
|
||||
"770d458144": "グループ化",
|
||||
"795cbf26e2": "フィルター…",
|
||||
"4616ea39fd": "ワークスペースにジャンプ",
|
||||
"threadListOptionsFiltered": "スレッドリストのオプション、フィルター適用中",
|
||||
"markThreadRead": "スレッドを既読としてマーク",
|
||||
"59b131fbd9": "スレッドを未読としてマークする",
|
||||
"beb2c19173": "未読",
|
||||
@@ -14187,6 +14188,9 @@
|
||||
"22b22034bc": "スタンドアロンターミナルはアクティビティでは使用できません。",
|
||||
"afdc2139a8": "Agent ターミナルが閉じられました。続行するには、このワークスペースで新規ターミナルを開いてください。"
|
||||
},
|
||||
"ActivityThreadRow": {
|
||||
"clearNotification": "通知を消去"
|
||||
},
|
||||
"ActivityTitlebarControls": {
|
||||
"f915168c8e": "未読",
|
||||
"d6a8de3934": "Agent",
|
||||
|
||||
@@ -14258,6 +14258,7 @@
|
||||
"770d458144": "그룹화 기준",
|
||||
"795cbf26e2": "필터...",
|
||||
"4616ea39fd": "워크스페이스로 이동",
|
||||
"threadListOptionsFiltered": "스레드 목록 옵션, 필터 활성화됨",
|
||||
"markThreadRead": "스레드를 읽은 것으로 표시",
|
||||
"59b131fbd9": "스레드를 읽지 않은 것으로 표시",
|
||||
"beb2c19173": "읽지 않음",
|
||||
@@ -14265,6 +14266,9 @@
|
||||
"22b22034bc": "활동에서는 독립형 terminal을 사용할 수 없습니다.",
|
||||
"afdc2139a8": "Agent terminal이 닫혔습니다. 계속하려면 이 워크스페이스에서 새 terminal을 여세요."
|
||||
},
|
||||
"ActivityThreadRow": {
|
||||
"clearNotification": "알림 지우기"
|
||||
},
|
||||
"ActivityTitlebarControls": {
|
||||
"f915168c8e": "읽지 않음",
|
||||
"d6a8de3934": "에이전트",
|
||||
|
||||
@@ -14236,6 +14236,7 @@
|
||||
"770d458144": "分组方式",
|
||||
"795cbf26e2": "筛选...",
|
||||
"4616ea39fd": "跳转到工作区",
|
||||
"threadListOptionsFiltered": "线程列表选项,筛选器已启用",
|
||||
"markThreadRead": "将话题标记为已读",
|
||||
"59b131fbd9": "将话题标记为未读",
|
||||
"beb2c19173": "未读",
|
||||
@@ -14243,6 +14244,9 @@
|
||||
"22b22034bc": "独立终端在活动中不可用。",
|
||||
"afdc2139a8": "智能体终端关闭。在此工作区中打开一个新终端以继续。"
|
||||
},
|
||||
"ActivityThreadRow": {
|
||||
"clearNotification": "清除通知"
|
||||
},
|
||||
"ActivityTitlebarControls": {
|
||||
"f915168c8e": "未读",
|
||||
"d6a8de3934": "智能体",
|
||||
|
||||
Reference in New Issue
Block a user