fix(a11y): restore missing aria-label attributes on icon buttons (#808)
* fix(a11y): restore missing aria-label attributes on icon buttons Adds aria-label attributes to icon-only buttons for screen reader accessibility: - ChatHistorySidebar: New conversation, save/cancel edit, menu buttons - IdeaDetailPanel: Close panel button - IdeationHeader: Clear selection, select all, show/hide dismissed, configure, add more, dismiss all, regenerate buttons - GitHub/GitLab IssueDetail: External link buttons - GitLab MRDetail: External link button - KanbanBoard: Toggle show archived button - AdvancedSettings: Dismiss downgrade button - DevToolsSettings: Browse folder buttons - IntegrationSettings: Save/cancel rename, refresh, expand/collapse, rename, delete buttons Also adds corresponding i18n translation keys for en and fr locales. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(i18n): use translation keys for tooltip content Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(i18n): use translation keys for IdeaCard and IdeationHeader tooltips Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Plus,
|
||||
MessageSquare,
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
import { Button } from './ui/button';
|
||||
import { Input } from './ui/input';
|
||||
import { ScrollArea } from './ui/scroll-area';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -50,6 +52,7 @@ export function ChatHistorySidebar({
|
||||
onDeleteSession,
|
||||
onRenameSession
|
||||
}: ChatHistorySidebarProps) {
|
||||
const { t } = useTranslation('common');
|
||||
const [editingId, setEditingId] = useState<string | null>(null);
|
||||
const [editTitle, setEditTitle] = useState('');
|
||||
const [deleteSessionId, setDeleteSessionId] = useState<string | null>(null);
|
||||
@@ -111,15 +114,20 @@ export function ChatHistorySidebar({
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between border-b border-border px-3 py-3">
|
||||
<h3 className="text-sm font-medium text-foreground">Chat History</h3>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-7 w-7"
|
||||
onClick={onNewSession}
|
||||
title="New conversation"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-7 w-7"
|
||||
onClick={onNewSession}
|
||||
aria-label={t('accessibility.newConversationAriaLabel')}
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('accessibility.newConversationAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{/* Session list */}
|
||||
@@ -205,6 +213,7 @@ function SessionItem({
|
||||
onEditTitleChange,
|
||||
onDelete
|
||||
}: SessionItemProps) {
|
||||
const { t } = useTranslation('common');
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
@@ -229,6 +238,7 @@ function SessionItem({
|
||||
size="icon"
|
||||
className="h-7 w-7 shrink-0"
|
||||
onClick={onSaveEdit}
|
||||
aria-label={t('accessibility.saveEditAriaLabel')}
|
||||
>
|
||||
<Check className="h-3.5 w-3.5 text-success" />
|
||||
</Button>
|
||||
@@ -237,6 +247,7 @@ function SessionItem({
|
||||
size="icon"
|
||||
className="h-7 w-7 shrink-0"
|
||||
onClick={onCancelEdit}
|
||||
aria-label={t('accessibility.cancelEditAriaLabel')}
|
||||
>
|
||||
<X className="h-3.5 w-3.5 text-muted-foreground" />
|
||||
</Button>
|
||||
@@ -282,6 +293,7 @@ function SessionItem({
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="absolute right-1 top-1/2 -translate-y-1/2 h-6 w-6 opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100 hover:bg-muted-foreground/20 transition-opacity"
|
||||
aria-label={t('accessibility.moreOptionsAriaLabel')}
|
||||
>
|
||||
<MoreVertical className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
|
||||
@@ -261,6 +261,7 @@ const DroppableColumn = memo(function DroppableColumn({ status, tasks, onTaskCli
|
||||
)}
|
||||
onClick={onToggleArchived}
|
||||
aria-pressed={showArchived}
|
||||
aria-label={t('common:accessibility.toggleShowArchivedAriaLabel')}
|
||||
>
|
||||
<Archive className="h-4 w-4" />
|
||||
<span className="absolute -top-1 -right-1 text-[10px] font-medium bg-muted rounded-full min-w-[14px] h-[14px] flex items-center justify-center">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ExternalLink, User, Clock, MessageCircle, Sparkles, CheckCircle2, Eye } from 'lucide-react';
|
||||
import { Badge } from '../../ui/badge';
|
||||
import { Button } from '../../ui/button';
|
||||
@@ -22,6 +23,7 @@ export function IssueDetail({
|
||||
autoFixConfig,
|
||||
autoFixQueueItem,
|
||||
}: IssueDetailProps) {
|
||||
const { t } = useTranslation('common');
|
||||
// Determine which task ID to use - either already linked or just created
|
||||
const taskId = linkedTaskId || (investigationResult?.success ? investigationResult.taskId : undefined);
|
||||
const hasLinkedTask = !!taskId;
|
||||
@@ -47,7 +49,7 @@ export function IssueDetail({
|
||||
</Badge>
|
||||
<span className="text-sm text-muted-foreground">#{issue.number}</span>
|
||||
</div>
|
||||
<Button variant="ghost" size="icon" asChild>
|
||||
<Button variant="ghost" size="icon" asChild aria-label={t('accessibility.openOnGitHubAriaLabel')}>
|
||||
<a href={issue.htmlUrl} target="_blank" rel="noopener noreferrer">
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</a>
|
||||
|
||||
@@ -20,7 +20,7 @@ const GITLAB_COMPLEXITY_COLORS: Record<string, string> = {
|
||||
};
|
||||
|
||||
export function IssueDetail({ issue, onInvestigate, investigationResult, linkedTaskId, onViewTask }: IssueDetailProps) {
|
||||
const { t } = useTranslation('gitlab');
|
||||
const { t } = useTranslation(['gitlab', 'common']);
|
||||
// Determine which task ID to use - either already linked or just created
|
||||
const taskId = linkedTaskId || (investigationResult?.success ? investigationResult.taskId : undefined);
|
||||
const hasLinkedTask = !!taskId;
|
||||
@@ -46,7 +46,7 @@ export function IssueDetail({ issue, onInvestigate, investigationResult, linkedT
|
||||
</Badge>
|
||||
<span className="text-sm text-muted-foreground">#{issue.iid}</span>
|
||||
</div>
|
||||
<Button variant="ghost" size="icon" asChild>
|
||||
<Button variant="ghost" size="icon" asChild aria-label={t('common:accessibility.openOnGitLabAriaLabel')}>
|
||||
<a href={issue.webUrl} target="_blank" rel="noopener noreferrer">
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</a>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useMemo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
ExternalLink,
|
||||
User,
|
||||
@@ -96,6 +97,7 @@ export function MRDetail({
|
||||
onMergeMR,
|
||||
onApproveMR,
|
||||
}: MRDetailProps) {
|
||||
const { t } = useTranslation('common');
|
||||
// Selection state for findings
|
||||
const [selectedFindingIds, setSelectedFindingIds] = useState<Set<string>>(new Set());
|
||||
const [postedFindingIds, setPostedFindingIds] = useState<Set<string>>(new Set());
|
||||
@@ -355,7 +357,7 @@ export function MRDetail({
|
||||
</Badge>
|
||||
<span className="text-sm text-muted-foreground">!{mr.iid}</span>
|
||||
</div>
|
||||
<Button variant="ghost" size="icon" asChild>
|
||||
<Button variant="ghost" size="icon" asChild aria-label={t('accessibility.openOnGitLabAriaLabel')}>
|
||||
<a href={mr.webUrl} target="_blank" rel="noopener noreferrer">
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</a>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ExternalLink, Play, X } from 'lucide-react';
|
||||
import { Button } from '../ui/button';
|
||||
import { Badge } from '../ui/badge';
|
||||
@@ -45,6 +46,7 @@ interface IdeaCardProps {
|
||||
}
|
||||
|
||||
export function IdeaCard({ idea, isSelected, onClick, onConvert, onGoToTask, onDismiss, onToggleSelect }: IdeaCardProps) {
|
||||
const { t } = useTranslation('common');
|
||||
const isDismissed = idea.status === 'dismissed';
|
||||
const isArchived = idea.status === 'archived';
|
||||
const isConverted = idea.status === 'converted';
|
||||
@@ -70,6 +72,7 @@ export function IdeaCard({ idea, isSelected, onClick, onConvert, onGoToTask, onD
|
||||
checked={isSelected}
|
||||
onCheckedChange={() => onToggleSelect(idea.id)}
|
||||
className="data-[state=checked]:bg-primary data-[state=checked]:border-primary"
|
||||
aria-label={t('accessibility.selectIdeaAriaLabel', { title: idea.title })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -134,11 +137,12 @@ export function IdeaCard({ idea, isSelected, onClick, onConvert, onGoToTask, onD
|
||||
e.stopPropagation();
|
||||
onConvert(idea);
|
||||
}}
|
||||
aria-label={t('accessibility.convertToTaskAriaLabel')}
|
||||
>
|
||||
<Play className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Convert to Task</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.convertToTaskAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
@@ -150,11 +154,12 @@ export function IdeaCard({ idea, isSelected, onClick, onConvert, onGoToTask, onD
|
||||
e.stopPropagation();
|
||||
onDismiss(idea);
|
||||
}}
|
||||
aria-label={t('accessibility.dismissAriaLabel')}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Dismiss</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.dismissAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
@@ -171,11 +176,12 @@ export function IdeaCard({ idea, isSelected, onClick, onConvert, onGoToTask, onD
|
||||
e.stopPropagation();
|
||||
onGoToTask(idea.taskId!);
|
||||
}}
|
||||
aria-label={t('accessibility.goToTaskAriaLabel')}
|
||||
>
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Go to Task</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.goToTaskAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
@@ -192,11 +198,12 @@ export function IdeaCard({ idea, isSelected, onClick, onConvert, onGoToTask, onD
|
||||
e.stopPropagation();
|
||||
onGoToTask(idea.taskId!);
|
||||
}}
|
||||
aria-label={t('accessibility.goToTaskAriaLabel')}
|
||||
>
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Go to Task</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.goToTaskAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ChevronRight, ExternalLink, Lightbulb, Play, X } from 'lucide-react';
|
||||
import { Button } from '../ui/button';
|
||||
import { Badge } from '../ui/badge';
|
||||
@@ -32,6 +33,7 @@ interface IdeaDetailPanelProps {
|
||||
}
|
||||
|
||||
export function IdeaDetailPanel({ idea, onClose, onConvert, onGoToTask, onDismiss }: IdeaDetailPanelProps) {
|
||||
const { t } = useTranslation('common');
|
||||
const isDismissed = idea.status === 'dismissed';
|
||||
const isConverted = idea.status === 'converted';
|
||||
|
||||
@@ -54,7 +56,7 @@ export function IdeaDetailPanel({ idea, onClose, onConvert, onGoToTask, onDismis
|
||||
</div>
|
||||
<h2 className="font-semibold">{idea.title}</h2>
|
||||
</div>
|
||||
<Button variant="ghost" size="icon" onClick={onClose}>
|
||||
<Button variant="ghost" size="icon" onClick={onClose} aria-label={t('accessibility.closePanelAriaLabel')}>
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Lightbulb, Eye, EyeOff, Settings2, Plus, Trash2, RefreshCw, CheckSquare, X } from 'lucide-react';
|
||||
import { Button } from '../ui/button';
|
||||
import { Badge } from '../ui/badge';
|
||||
@@ -39,6 +40,7 @@ export function IdeationHeader({
|
||||
hasActiveIdeas,
|
||||
canAddMore
|
||||
}: IdeationHeaderProps) {
|
||||
const { t } = useTranslation('common');
|
||||
const hasSelection = selectedCount > 0;
|
||||
return (
|
||||
<div className="shrink-0 border-b border-border p-4 bg-card/50">
|
||||
@@ -75,11 +77,12 @@ export function IdeationHeader({
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={onClearSelection}
|
||||
aria-label={t('accessibility.clearSelectionAriaLabel')}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Clear selection</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.clearSelectionAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
<div className="w-px h-6 bg-border mx-1" />
|
||||
</>
|
||||
@@ -91,11 +94,12 @@ export function IdeationHeader({
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={onSelectAll}
|
||||
aria-label={t('accessibility.selectAllAriaLabel')}
|
||||
>
|
||||
<CheckSquare className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Select all</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.selectAllAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
)}
|
||||
@@ -107,12 +111,13 @@ export function IdeationHeader({
|
||||
variant={showDismissed ? 'secondary' : 'outline'}
|
||||
size="icon"
|
||||
onClick={onToggleShowDismissed}
|
||||
aria-label={showDismissed ? t('accessibility.hideDismissedAriaLabel') : t('accessibility.showDismissedAriaLabel')}
|
||||
>
|
||||
{showDismissed ? <Eye className="h-4 w-4" /> : <EyeOff className="h-4 w-4" />}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{showDismissed ? 'Hide dismissed' : 'Show dismissed'}
|
||||
{showDismissed ? t('accessibility.hideDismissedAriaLabel') : t('accessibility.showDismissedAriaLabel')}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
@@ -121,11 +126,12 @@ export function IdeationHeader({
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={onOpenConfig}
|
||||
aria-label={t('accessibility.configureAriaLabel')}
|
||||
>
|
||||
<Settings2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Configure</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.configureAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
{canAddMore && (
|
||||
<Tooltip>
|
||||
@@ -133,12 +139,13 @@ export function IdeationHeader({
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={onOpenAddMore}
|
||||
aria-label={t('accessibility.addMoreAriaLabel')}
|
||||
>
|
||||
<Plus className="h-4 w-4 mr-1" />
|
||||
Add More
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Add more ideation types</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.addMoreAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{hasActiveIdeas && !hasSelection && (
|
||||
@@ -149,20 +156,21 @@ export function IdeationHeader({
|
||||
size="icon"
|
||||
className="text-muted-foreground hover:text-destructive"
|
||||
onClick={onDismissAll}
|
||||
aria-label={t('accessibility.dismissAllAriaLabel')}
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Dismiss all ideas</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.dismissAllAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline" size="icon" onClick={onRefresh}>
|
||||
<Button variant="outline" size="icon" onClick={onRefresh} aria-label={t('accessibility.regenerateIdeasAriaLabel')}>
|
||||
<RefreshCw className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Regenerate Ideas</TooltipContent>
|
||||
<TooltipContent>{t('accessibility.regenerateIdeasAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -362,6 +362,7 @@ export function AdvancedSettings({ settings, onSettingsChange, section, version
|
||||
size="icon"
|
||||
className="h-6 w-6"
|
||||
onClick={dismissStableDowngrade}
|
||||
aria-label={t('common:accessibility.dismissAriaLabel')}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
@@ -293,6 +293,7 @@ export function DevToolsSettings({ settings, onSettingsChange }: DevToolsSetting
|
||||
handleCustomIDEPathChange(result);
|
||||
}
|
||||
}}
|
||||
aria-label={t('common:accessibility.browseFilesAriaLabel')}
|
||||
>
|
||||
<FolderOpen className="h-4 w-4" />
|
||||
</Button>
|
||||
@@ -354,6 +355,7 @@ export function DevToolsSettings({ settings, onSettingsChange }: DevToolsSetting
|
||||
handleCustomTerminalPathChange(result);
|
||||
}
|
||||
}}
|
||||
aria-label={t('common:accessibility.browseFilesAriaLabel')}
|
||||
>
|
||||
<FolderOpen className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
@@ -25,6 +25,7 @@ import { Input } from '../ui/input';
|
||||
import { Label } from '../ui/label';
|
||||
import { Switch } from '../ui/switch';
|
||||
import { cn } from '../../lib/utils';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
|
||||
import { SettingsSection } from './SettingsSection';
|
||||
import { loadClaudeProfiles as loadGlobalClaudeProfiles } from '../../stores/claude-profile-store';
|
||||
import { useClaudeLoginTerminal } from '../../hooks/useClaudeLoginTerminal';
|
||||
@@ -358,6 +359,7 @@ export function IntegrationSettings({ settings, onSettingsChange, isOpen }: Inte
|
||||
size="icon"
|
||||
onClick={handleRenameProfile}
|
||||
className="h-7 w-7 text-success hover:text-success hover:bg-success/10"
|
||||
aria-label={t('common:accessibility.saveEditAriaLabel')}
|
||||
>
|
||||
<Check className="h-3 w-3" />
|
||||
</Button>
|
||||
@@ -366,6 +368,7 @@ export function IntegrationSettings({ settings, onSettingsChange, isOpen }: Inte
|
||||
size="icon"
|
||||
onClick={cancelEditingProfile}
|
||||
className="h-7 w-7 text-muted-foreground hover:text-foreground"
|
||||
aria-label={t('common:accessibility.cancelEditAriaLabel')}
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</Button>
|
||||
@@ -422,20 +425,25 @@ export function IntegrationSettings({ settings, onSettingsChange, isOpen }: Inte
|
||||
</Button>
|
||||
) : (
|
||||
/* Re-authenticate button for already authenticated profiles */
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => handleAuthenticateProfile(profile.id)}
|
||||
disabled={authenticatingProfileId === profile.id}
|
||||
className="h-7 w-7 text-muted-foreground hover:text-foreground"
|
||||
title="Re-authenticate profile"
|
||||
>
|
||||
{authenticatingProfileId === profile.id ? (
|
||||
<Loader2 className="h-3 w-3 animate-spin" />
|
||||
) : (
|
||||
<RefreshCw className="h-3 w-3" />
|
||||
)}
|
||||
</Button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => handleAuthenticateProfile(profile.id)}
|
||||
disabled={authenticatingProfileId === profile.id}
|
||||
className="h-7 w-7 text-muted-foreground hover:text-foreground"
|
||||
aria-label={t('common:accessibility.refreshAriaLabel')}
|
||||
>
|
||||
{authenticatingProfileId === profile.id ? (
|
||||
<Loader2 className="h-3 w-3 animate-spin" />
|
||||
) : (
|
||||
<RefreshCw className="h-3 w-3" />
|
||||
)}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('common:accessibility.reAuthenticateProfileAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{profile.id !== activeProfileId && (
|
||||
<Button
|
||||
@@ -449,43 +457,60 @@ export function IntegrationSettings({ settings, onSettingsChange, isOpen }: Inte
|
||||
</Button>
|
||||
)}
|
||||
{/* Toggle token entry button */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => toggleTokenEntry(profile.id)}
|
||||
className="h-7 w-7 text-muted-foreground hover:text-foreground"
|
||||
title={expandedTokenProfileId === profile.id ? "Hide token entry" : "Enter token manually"}
|
||||
>
|
||||
{expandedTokenProfileId === profile.id ? (
|
||||
<ChevronDown className="h-3 w-3" />
|
||||
) : (
|
||||
<ChevronRight className="h-3 w-3" />
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => startEditingProfile(profile)}
|
||||
className="h-7 w-7 text-muted-foreground hover:text-foreground"
|
||||
title="Rename profile"
|
||||
>
|
||||
<Pencil className="h-3 w-3" />
|
||||
</Button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => toggleTokenEntry(profile.id)}
|
||||
className="h-7 w-7 text-muted-foreground hover:text-foreground"
|
||||
aria-label={expandedTokenProfileId === profile.id ? t('common:accessibility.collapseAriaLabel') : t('common:accessibility.expandAriaLabel')}
|
||||
>
|
||||
{expandedTokenProfileId === profile.id ? (
|
||||
<ChevronDown className="h-3 w-3" />
|
||||
) : (
|
||||
<ChevronRight className="h-3 w-3" />
|
||||
)}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{expandedTokenProfileId === profile.id ? t('common:accessibility.hideTokenEntryAriaLabel') : t('common:accessibility.enterTokenManuallyAriaLabel')}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => startEditingProfile(profile)}
|
||||
className="h-7 w-7 text-muted-foreground hover:text-foreground"
|
||||
aria-label={t('common:accessibility.renameAriaLabel')}
|
||||
>
|
||||
<Pencil className="h-3 w-3" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('common:accessibility.renameProfileAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
{!profile.isDefault && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => handleDeleteProfile(profile.id)}
|
||||
disabled={deletingProfileId === profile.id}
|
||||
className="h-7 w-7 text-destructive hover:text-destructive hover:bg-destructive/10"
|
||||
title="Delete profile"
|
||||
>
|
||||
{deletingProfileId === profile.id ? (
|
||||
<Loader2 className="h-3 w-3 animate-spin" />
|
||||
) : (
|
||||
<Trash2 className="h-3 w-3" />
|
||||
)}
|
||||
</Button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => handleDeleteProfile(profile.id)}
|
||||
disabled={deletingProfileId === profile.id}
|
||||
className="h-7 w-7 text-destructive hover:text-destructive hover:bg-destructive/10"
|
||||
aria-label={t('common:accessibility.deleteAriaLabel')}
|
||||
>
|
||||
{deletingProfileId === profile.id ? (
|
||||
<Loader2 className="h-3 w-3 animate-spin" />
|
||||
) : (
|
||||
<Trash2 className="h-3 w-3" />
|
||||
)}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('common:accessibility.deleteProfileAriaLabel')}</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -21,7 +21,38 @@
|
||||
"learnMoreAriaLabel": "Learn more (opens in new window)",
|
||||
"toggleFolder": "Toggle {{name}} folder",
|
||||
"expandFolder": "Expand {{name}} folder",
|
||||
"collapseFolder": "Collapse {{name}} folder"
|
||||
"collapseFolder": "Collapse {{name}} folder",
|
||||
"newConversationAriaLabel": "New conversation",
|
||||
"saveEditAriaLabel": "Save",
|
||||
"cancelEditAriaLabel": "Cancel",
|
||||
"moreOptionsAriaLabel": "More options",
|
||||
"closePanelAriaLabel": "Close panel",
|
||||
"openOnGitHubAriaLabel": "Open on GitHub (opens in new window)",
|
||||
"openOnGitLabAriaLabel": "Open on GitLab (opens in new window)",
|
||||
"toggleShowArchivedAriaLabel": "Toggle show archived tasks",
|
||||
"clearSelectionAriaLabel": "Clear selection",
|
||||
"selectAllAriaLabel": "Select all",
|
||||
"showDismissedAriaLabel": "Show dismissed",
|
||||
"hideDismissedAriaLabel": "Hide dismissed",
|
||||
"configureAriaLabel": "Configure",
|
||||
"addMoreAriaLabel": "Add more",
|
||||
"dismissAllAriaLabel": "Dismiss all ideas",
|
||||
"regenerateIdeasAriaLabel": "Regenerate ideas",
|
||||
"dismissAriaLabel": "Dismiss",
|
||||
"browseFilesAriaLabel": "Browse files",
|
||||
"renameAriaLabel": "Rename",
|
||||
"deleteAriaLabel": "Delete",
|
||||
"refreshAriaLabel": "Refresh",
|
||||
"expandAriaLabel": "Expand",
|
||||
"collapseAriaLabel": "Collapse",
|
||||
"selectIdeaAriaLabel": "Select idea: {{title}}",
|
||||
"convertToTaskAriaLabel": "Convert to task",
|
||||
"goToTaskAriaLabel": "Go to task",
|
||||
"reAuthenticateProfileAriaLabel": "Re-authenticate profile",
|
||||
"hideTokenEntryAriaLabel": "Hide token entry",
|
||||
"enterTokenManuallyAriaLabel": "Enter token manually",
|
||||
"renameProfileAriaLabel": "Rename profile",
|
||||
"deleteProfileAriaLabel": "Delete profile"
|
||||
},
|
||||
"buttons": {
|
||||
"save": "Save",
|
||||
|
||||
@@ -21,7 +21,38 @@
|
||||
"learnMoreAriaLabel": "En savoir plus (s'ouvre dans une nouvelle fenêtre)",
|
||||
"toggleFolder": "Basculer le dossier {{name}}",
|
||||
"expandFolder": "Déplier le dossier {{name}}",
|
||||
"collapseFolder": "Replier le dossier {{name}}"
|
||||
"collapseFolder": "Replier le dossier {{name}}",
|
||||
"newConversationAriaLabel": "Nouvelle conversation",
|
||||
"saveEditAriaLabel": "Enregistrer",
|
||||
"cancelEditAriaLabel": "Annuler",
|
||||
"moreOptionsAriaLabel": "Plus d'options",
|
||||
"closePanelAriaLabel": "Fermer le panneau",
|
||||
"openOnGitHubAriaLabel": "Ouvrir sur GitHub (s'ouvre dans une nouvelle fenêtre)",
|
||||
"openOnGitLabAriaLabel": "Ouvrir sur GitLab (s'ouvre dans une nouvelle fenêtre)",
|
||||
"toggleShowArchivedAriaLabel": "Afficher/masquer les tâches archivées",
|
||||
"clearSelectionAriaLabel": "Effacer la sélection",
|
||||
"selectAllAriaLabel": "Tout sélectionner",
|
||||
"showDismissedAriaLabel": "Afficher les rejetées",
|
||||
"hideDismissedAriaLabel": "Masquer les rejetées",
|
||||
"configureAriaLabel": "Configurer",
|
||||
"addMoreAriaLabel": "Ajouter plus",
|
||||
"dismissAllAriaLabel": "Rejeter toutes les idées",
|
||||
"regenerateIdeasAriaLabel": "Régénérer les idées",
|
||||
"dismissAriaLabel": "Ignorer",
|
||||
"browseFilesAriaLabel": "Parcourir les fichiers",
|
||||
"renameAriaLabel": "Renommer",
|
||||
"deleteAriaLabel": "Supprimer",
|
||||
"refreshAriaLabel": "Actualiser",
|
||||
"expandAriaLabel": "Développer",
|
||||
"collapseAriaLabel": "Réduire",
|
||||
"selectIdeaAriaLabel": "Sélectionner l'idée : {{title}}",
|
||||
"convertToTaskAriaLabel": "Convertir en tâche",
|
||||
"goToTaskAriaLabel": "Aller à la tâche",
|
||||
"reAuthenticateProfileAriaLabel": "Ré-authentifier le profil",
|
||||
"hideTokenEntryAriaLabel": "Masquer la saisie du jeton",
|
||||
"enterTokenManuallyAriaLabel": "Saisir le jeton manuellement",
|
||||
"renameProfileAriaLabel": "Renommer le profil",
|
||||
"deleteProfileAriaLabel": "Supprimer le profil"
|
||||
},
|
||||
"buttons": {
|
||||
"save": "Enregistrer",
|
||||
|
||||
Reference in New Issue
Block a user