sync: update from private repo (e62f5c7)
CI / build-and-test (push) Has been cancelled

This commit is contained in:
oss-sync
2026-06-11 01:52:48 +00:00
parent 000a2474aa
commit d061ad08d8
237 changed files with 8441 additions and 5549 deletions
+18 -14
View File
@@ -1,9 +1,10 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { DetailTabId } from '../../lib/urlState';
import { shareTask, unshareTask } from '../../api';
interface Tab { id: DetailTabId; label: string; }
interface Tab { id: DetailTabId; labelKey: string; }
interface DetailHeaderProps {
title: string;
@@ -31,6 +32,7 @@ interface DetailHeaderProps {
}
function ShareButton({ taskId, shareToken, onShareChange }: { taskId: number; shareToken: string | null; onShareChange?: () => void }) {
const { t } = useTranslation('detail');
const [copied, setCopied] = useState(false);
const qc = useQueryClient();
@@ -68,8 +70,8 @@ function ShareButton({ taskId, shareToken, onShareChange }: { taskId: number; sh
<button
onClick={() => shareMutation.mutate()}
disabled={shareMutation.isPending}
title={shareMutation.isPending ? '共有中...' : '公開リンクを発行'}
aria-label="公開リンクを発行"
title={shareMutation.isPending ? t('share.sharing') : t('share.publish')}
aria-label={t('share.publish')}
className={`${iconBtnBase} border-hairline bg-canvas text-slate-600 hover:text-slate-900 hover:bg-surface`}
>
{shareMutation.isPending ? (
@@ -100,8 +102,8 @@ function ShareButton({ taskId, shareToken, onShareChange }: { taskId: number; sh
<div className="flex items-center gap-1">
<button
onClick={handleCopy}
title={copied ? 'コピーしました' : '共有リンクをコピー'}
aria-label="共有リンクをコピー"
title={copied ? t('share.copied') : t('share.copy')}
aria-label={t('share.copy')}
className={`${iconBtnBase} ${copied ? 'border-emerald-200 dark:border-emerald-500/30 bg-emerald-50 dark:bg-emerald-500/15 text-emerald-700 dark:text-emerald-300' : 'border-hairline bg-canvas text-slate-600 hover:text-slate-900 hover:bg-surface'}`}
>
{copied ? (
@@ -118,8 +120,8 @@ function ShareButton({ taskId, shareToken, onShareChange }: { taskId: number; sh
<button
onClick={() => unshareMutation.mutate()}
disabled={unshareMutation.isPending}
title="共有を停止"
aria-label="共有を停止"
title={t('share.stop')}
aria-label={t('share.stop')}
className={`${iconBtnBase} border-hairline bg-canvas text-slate-500 hover:text-red-700 dark:hover:text-red-300 hover:border-red-200 hover:bg-red-50 dark:hover:bg-red-500/15`}
>
{unshareMutation.isPending ? (
@@ -138,6 +140,7 @@ function ShareButton({ taskId, shareToken, onShareChange }: { taskId: number; sh
}
function ContinueButton({ latestJobStatus, onClick }: { latestJobStatus: string | null; onClick: () => void }) {
const { t } = useTranslation('detail');
// Mirror the spec/backend TERMINAL list (worker maps abort outcomes to
// 'failed', so 'aborted' is intentionally absent).
const TERMINAL = ['succeeded', 'failed', 'waiting_human', 'cancelled'];
@@ -148,8 +151,8 @@ function ContinueButton({ latestJobStatus, onClick }: { latestJobStatus: string
<button
onClick={onClick}
disabled={!enabled}
title={enabled ? '別 piece で続ける' : 'タスクが進行中のため続行できません'}
aria-label="別 piece で続ける"
title={enabled ? t('continue.label') : t('continue.disabled')}
aria-label={t('continue.label')}
className={`${iconBtnBase} border-hairline bg-canvas text-slate-600 hover:text-slate-900 hover:bg-surface`}
>
{/* arrow → divider: 「次のフェーズへ進む」cue。FileBrowser の refresh
@@ -164,6 +167,7 @@ function ContinueButton({ latestJobStatus, onClick }: { latestJobStatus: string
}
export function DetailHeader({ title, subtitle, tabs, activeTab, tabTransitionPending, onTabChange, onClose, detailWidth, onWidthToggle, taskId, shareToken, onShareChange, latestJobStatus, onContinue }: DetailHeaderProps) {
const { t } = useTranslation('detail');
// Mobile (< sm) hides the close button and tab bar because App.tsx
// renders its own mobile-level top tab bar with the same controls.
// Two close buttons / two tab bars on iPhone was visually redundant.
@@ -194,8 +198,8 @@ export function DetailHeader({ title, subtitle, tabs, activeTab, tabTransitionPe
{onWidthToggle && detailWidth && (
<button
onClick={onWidthToggle}
title={detailWidth === 'focused' ? '標準表示に戻る' : '集中モード (TASK 列を細い rail に / Chat と Workspace を可変分割)'}
aria-label={detailWidth === 'focused' ? '標準表示に戻る' : '集中モードに切替'}
title={detailWidth === 'focused' ? t('focus.toStandard') : t('focus.toFocused')}
aria-label={detailWidth === 'focused' ? t('focus.toStandard') : t('focus.toFocusedShort')}
aria-pressed={detailWidth === 'focused'}
className="hidden sm:inline-flex items-center justify-center w-7 h-7 rounded-md text-slate-500 hover:text-slate-700 hover:bg-surface-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-ring"
>
@@ -214,7 +218,7 @@ export function DetailHeader({ title, subtitle, tabs, activeTab, tabTransitionPe
)}
<button
onClick={onClose}
aria-label="詳細パネルを閉じる"
aria-label={t('panel.close')}
className="hidden sm:inline-flex items-center justify-center w-7 h-7 rounded-md text-slate-400 hover:text-slate-700 hover:bg-surface-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-ring"
>
<svg className="w-4 h-4" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round">
@@ -223,7 +227,7 @@ export function DetailHeader({ title, subtitle, tabs, activeTab, tabTransitionPe
</button>
</div>
</div>
<div role="tablist" aria-label="詳細タブ" className="hidden sm:flex gap-4 -mb-px">
<div role="tablist" aria-label={t('panel.tabsLabel')} className="hidden sm:flex gap-4 -mb-px">
{tabs.map(tab => {
const active = activeTab === tab.id;
const pending = active && tabTransitionPending;
@@ -239,7 +243,7 @@ export function DetailHeader({ title, subtitle, tabs, activeTab, tabTransitionPe
: 'border-transparent text-slate-500 font-medium hover:text-slate-800'
}`}
>
{tab.label}
{t(tab.labelKey)}
{pending && (
<span
aria-hidden="true"