perf(ui): migrate icons to SVG sprite system
Replace @remixicon/react with a shared Icon component that renders via <use href> references to a single hidden SVG sprite. This reduces DOM node count by replacing inline SVGs with lightweight references. - Create Icon component with sprite injection (packages/ui/src/components/icon/) - Migrate all 164 files from @remixicon/react to Icon component - Auto-generate sprite data from remixicon bundle (scripts/generate-icon-sprite.mjs) - Add bun run icons:generate to package.json - Move @remixicon/react to devDependencies - Add icon usage instructions to theme-system skill
This commit is contained in:
@@ -16,7 +16,6 @@ import {
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { SortableTabsStrip, type SortableTabsStripItem } from '@/components/ui/sortable-tabs-strip';
|
||||
|
||||
import { RiArrowLeftSLine, RiChat4Line, RiChatNewLine, RiCheckLine, RiCloseLine, RiCommandLine, RiFileTextLine, RiFolder6Line, RiGitBranchLine, RiGithubFill, RiLayoutLeftLine, RiLayoutRightLine, RiPictureInPicture2Line, RiPlayListAddLine, RiRefreshLine, RiServerLine, RiStackLine, RiTerminalBoxLine, RiTimerLine, RiAlertLine, type RemixiconComponentType } from '@remixicon/react';
|
||||
import { DiffIcon } from '@/components/icons/DiffIcon';
|
||||
import { useUIStore, type MainTab } from '@/stores/useUIStore';
|
||||
import { useConfigStore } from '@/stores/useConfigStore';
|
||||
@@ -56,7 +55,6 @@ import {
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from '@/components/ui/collapsible';
|
||||
import { RiArrowDownSLine, RiArrowRightSLine } from '@remixicon/react';
|
||||
import type { UsageWindow } from '@/types';
|
||||
import type { GitHubAuthStatus } from '@/lib/api/types';
|
||||
import type { SessionContextUsage } from '@/stores/types/sessionTypes';
|
||||
@@ -68,8 +66,10 @@ import { ProjectActionsButton } from '@/components/layout/ProjectActionsButton';
|
||||
import { canUseElectronDesktopIPC, invokeDesktop, isDesktopShell, isVSCodeRuntime, startDesktopWindowDrag } from '@/lib/desktop';
|
||||
import { desktopHostsGet, locationMatchesHost, redactSensitiveUrl } from '@/lib/desktopHosts';
|
||||
import { resolveSessionDiffStats } from '@/components/session/sidebar/utils';
|
||||
import { Icon } from "@/components/icon/Icon";
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import type { Session } from '@opencode-ai/sdk/v2/client';
|
||||
import type { IconName } from "@/components/icon/icons";
|
||||
|
||||
const DESKTOP_HEADER_ICON_BUTTON_CLASS = 'app-region-no-drag inline-flex h-8 w-8 items-center justify-center gap-2 rounded-md typography-ui-label font-medium text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary disabled:pointer-events-none disabled:opacity-50 hover:bg-interactive-hover transition-colors';
|
||||
const MOBILE_HEADER_ICON_BUTTON_CLASS = 'app-region-no-drag inline-flex h-9 w-9 items-center justify-center gap-2 p-2 rounded-md typography-ui-label font-medium text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary disabled:pointer-events-none disabled:opacity-50 hover:text-foreground hover:bg-interactive-hover transition-colors';
|
||||
@@ -80,7 +80,7 @@ type HeaderIconActionButtonProps = {
|
||||
ariaLabel: string;
|
||||
onClick: () => void;
|
||||
className?: string;
|
||||
Icon: RemixiconComponentType;
|
||||
Icon: IconName;
|
||||
iconClassName?: string;
|
||||
};
|
||||
|
||||
@@ -90,7 +90,7 @@ const HeaderIconActionButton = React.memo(function HeaderIconActionButton({
|
||||
ariaLabel,
|
||||
onClick,
|
||||
className,
|
||||
Icon,
|
||||
Icon: iconName,
|
||||
iconClassName,
|
||||
}: HeaderIconActionButtonProps) {
|
||||
if (!visible) {
|
||||
@@ -106,7 +106,7 @@ const HeaderIconActionButton = React.memo(function HeaderIconActionButton({
|
||||
aria-label={ariaLabel}
|
||||
className={className ?? DESKTOP_HEADER_ICON_BUTTON_CLASS}
|
||||
>
|
||||
<Icon className={iconClassName ?? 'h-[18px] w-[18px]'} />
|
||||
<Icon name={iconName} className={iconClassName ?? 'h-[18px] w-[18px]'} />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
@@ -162,7 +162,7 @@ const DesktopGitHubControl = React.memo(function DesktopGitHubControl({
|
||||
referrerPolicy="no-referrer"
|
||||
/>
|
||||
) : (
|
||||
<RiGithubFill className="h-3.5 w-3.5 text-foreground" />
|
||||
<Icon name="github-fill" className="h-3.5 w-3.5 text-foreground" />
|
||||
)}
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
@@ -195,7 +195,7 @@ const DesktopGitHubControl = React.memo(function DesktopGitHubControl({
|
||||
/>
|
||||
) : (
|
||||
<div className="flex h-6 w-6 items-center justify-center rounded-full border border-border/60 bg-muted">
|
||||
<RiGithubFill className="h-3 w-3 text-muted-foreground" />
|
||||
<Icon name="github-fill" className="h-3 w-3 text-muted-foreground" />
|
||||
</div>
|
||||
)}
|
||||
<span className="flex min-w-0 flex-1 flex-col">
|
||||
@@ -208,7 +208,7 @@ const DesktopGitHubControl = React.memo(function DesktopGitHubControl({
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
{isCurrent ? <RiCheckLine className="h-4 w-4 text-primary" /> : null}
|
||||
{isCurrent ? <Icon name="check" className="h-4 w-4 text-primary" /> : null}
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
})}
|
||||
@@ -231,7 +231,7 @@ const DesktopGitHubControl = React.memo(function DesktopGitHubControl({
|
||||
referrerPolicy="no-referrer"
|
||||
/>
|
||||
) : (
|
||||
<RiGithubFill className="h-3.5 w-3.5 text-foreground" />
|
||||
<Icon name="github-fill" className="h-3.5 w-3.5 text-foreground" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@@ -321,7 +321,7 @@ const DesktopServicesMenu = React.memo(function DesktopServicesMenu({
|
||||
isDesktopApp ? 'w-auto max-w-[14rem] justify-start gap-1.5 px-2.5' : 'h-8 w-8'
|
||||
)}
|
||||
>
|
||||
<RiStackLine className="h-[18px] w-[18px]" />
|
||||
<Icon name="stack" className="h-[18px] w-[18px]" />
|
||||
{isDesktopApp ? (
|
||||
<span className="truncate typography-ui-label font-medium text-foreground">{compactCurrentInstanceLabel}</span>
|
||||
) : null}
|
||||
@@ -411,7 +411,7 @@ const DesktopServicesMenu = React.memo(function DesktopServicesMenu({
|
||||
disabled={isQuotaLoading || isUsageRefreshSpinning}
|
||||
aria-label={t('header.services.refreshRateLimitsAria')}
|
||||
>
|
||||
<RiRefreshLine className={cn('h-4 w-4', isUsageRefreshSpinning && 'animate-spin')} />
|
||||
<Icon name="refresh" className={cn('h-4 w-4', isUsageRefreshSpinning && 'animate-spin')} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -485,7 +485,7 @@ const DesktopServicesMenu = React.memo(function DesktopServicesMenu({
|
||||
>
|
||||
<CollapsibleTrigger className="flex w-full items-center justify-between rounded-md px-1 py-1.5 text-left hover:bg-[var(--interactive-hover)]/50 transition-colors">
|
||||
<span className="typography-ui-label font-medium text-foreground">{family.familyLabel}</span>
|
||||
{isExpanded ? <RiArrowDownSLine className="h-4 w-4 text-muted-foreground" /> : <RiArrowRightSLine className="h-4 w-4 text-muted-foreground" />}
|
||||
{isExpanded ? <Icon name="arrow-down-s" className="h-4 w-4 text-muted-foreground" /> : <Icon name="arrow-right-s" className="h-4 w-4 text-muted-foreground" />}
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<div className="space-y-2.5 pb-1 pl-1 pt-1">
|
||||
@@ -552,7 +552,6 @@ const DesktopServicesMenu = React.memo(function DesktopServicesMenu({
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
const isSameContextUsage = (
|
||||
a: SessionContextUsage | null,
|
||||
b: SessionContextUsage | null,
|
||||
@@ -623,7 +622,7 @@ const getActiveContextMode = (panelState: {
|
||||
interface TabConfig {
|
||||
id: MainTab;
|
||||
label: string;
|
||||
icon: RemixiconComponentType | 'diff';
|
||||
icon: IconName | 'diff';
|
||||
badge?: number;
|
||||
showDot?: boolean;
|
||||
}
|
||||
@@ -1179,7 +1178,6 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
return lastProjectActionsContextRef.current;
|
||||
}, [actionDirectory, activeProjectRef]);
|
||||
|
||||
|
||||
const planModeEnabled = useFeatureFlagsStore((state) => state.planModeEnabled);
|
||||
const isSessionPlanAvailable = useSessionUIStore((state) => state.isSessionPlanAvailable);
|
||||
const planTabAvailable = planModeEnabled && currentSessionId ? isSessionPlanAvailable(currentSessionId) : false;
|
||||
@@ -1508,17 +1506,17 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
const tabs: TabConfig[] = React.useMemo(() => {
|
||||
if (isMobile) {
|
||||
const base: TabConfig[] = [
|
||||
{ id: 'chat', label: t('layout.mainTab.chat'), icon: RiChat4Line },
|
||||
{ id: 'chat', label: t('layout.mainTab.chat'), icon: "chat-4" },
|
||||
];
|
||||
|
||||
if (showPlanTab) {
|
||||
base.push({ id: 'plan', label: t('layout.mainTab.plan'), icon: RiFileTextLine });
|
||||
base.push({ id: 'plan', label: t('layout.mainTab.plan'), icon: "file-text" });
|
||||
}
|
||||
|
||||
base.push(
|
||||
{ id: 'diff', label: t('layout.mainTab.diff'), icon: 'diff' },
|
||||
{ id: 'files', label: t('layout.mainTab.files'), icon: RiFolder6Line },
|
||||
{ id: 'terminal', label: t('layout.mainTab.terminal'), icon: RiTerminalBoxLine },
|
||||
{ id: 'files', label: t('layout.mainTab.files'), icon: "folder-6" },
|
||||
{ id: 'terminal', label: t('layout.mainTab.terminal'), icon: "terminal-box" },
|
||||
);
|
||||
|
||||
return base;
|
||||
@@ -1539,13 +1537,13 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
}, [activeMainTab, isMobile, setActiveMainTab]);
|
||||
|
||||
const servicesTabs = React.useMemo(() => {
|
||||
const base: Array<{ value: 'instance' | 'usage' | 'mcp'; label: string; icon: RemixiconComponentType }> = [];
|
||||
const base: Array<{ value: 'instance' | 'usage' | 'mcp'; label: string; icon: IconName }> = [];
|
||||
if (isDesktopApp) {
|
||||
base.push({ value: 'instance', label: t('layout.services.instance'), icon: RiServerLine });
|
||||
base.push({ value: 'instance', label: t('layout.services.instance'), icon: "server" });
|
||||
}
|
||||
base.push(
|
||||
{ value: 'usage', label: t('layout.services.usage'), icon: RiTimerLine },
|
||||
{ value: 'mcp', label: 'MCP', icon: McpIcon as unknown as RemixiconComponentType }
|
||||
{ value: 'usage', label: t('layout.services.usage'), icon: "timer" },
|
||||
{ value: 'mcp', label: 'MCP', icon: McpIcon as unknown as IconName }
|
||||
);
|
||||
return base;
|
||||
}, [isDesktopApp, t]);
|
||||
@@ -1554,7 +1552,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
return servicesTabs.map((tab) => ({
|
||||
id: tab.value,
|
||||
label: tab.label,
|
||||
icon: <tab.icon className="h-3.5 w-3.5" />,
|
||||
icon: <Icon name={tab.icon} className="h-3.5 w-3.5" />,
|
||||
}));
|
||||
}, [servicesTabs]);
|
||||
|
||||
@@ -1628,8 +1626,8 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
|
||||
const mobileServicesTabItems = React.useMemo<SortableTabsStripItem[]>(() => {
|
||||
return [
|
||||
{ id: 'usage', label: t('layout.services.usage'), icon: <RiTimerLine className="h-3.5 w-3.5" /> },
|
||||
{ id: 'mcp', label: 'MCP', icon: <RiCommandLine className="h-3.5 w-3.5" /> },
|
||||
{ id: 'usage', label: t('layout.services.usage'), icon: <Icon name="timer" className="h-3.5 w-3.5" /> },
|
||||
{ id: 'mcp', label: 'MCP', icon: <Icon name="command" className="h-3.5 w-3.5" /> },
|
||||
];
|
||||
}, [t]);
|
||||
|
||||
@@ -1709,14 +1707,14 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
const renderTab = (tab: TabConfig) => {
|
||||
const isActive = activeMainTab === tab.id;
|
||||
const isDiffTab = tab.icon === 'diff';
|
||||
const Icon = isDiffTab ? null : (tab.icon as RemixiconComponentType);
|
||||
const tabIconName = isDiffTab ? null : (tab.icon as IconName);
|
||||
const isChatTab = tab.id === 'chat';
|
||||
|
||||
const renderIcon = (iconSize: number) => {
|
||||
if (isDiffTab) {
|
||||
return <DiffIcon size={iconSize} />;
|
||||
}
|
||||
return Icon ? <Icon size={iconSize} /> : null;
|
||||
return tabIconName ? <Icon name={tabIconName} className={`h-${iconSize/4} w-${iconSize/4}`} /> : null;
|
||||
};
|
||||
|
||||
const tabButton = (
|
||||
@@ -1766,7 +1764,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
onClick={handleOpenContextPlan}
|
||||
className={cn(desktopHeaderIconButtonClass, isContextPlanActive && 'bg-[var(--interactive-hover)]')}
|
||||
>
|
||||
<RiFileTextLine className="h-[18px] w-[18px]" />
|
||||
<Icon name="file-text" className="h-[18px] w-[18px]" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
@@ -1807,13 +1805,13 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
title={t('header.actions.terminalPanelWithShortcut', { shortcut: shortcutLabel('toggle_terminal') })}
|
||||
ariaLabel={t('header.actions.toggleTerminalPanelAria')}
|
||||
onClick={toggleBottomTerminal}
|
||||
Icon={RiTerminalBoxLine}
|
||||
Icon={'terminal-box'}
|
||||
/>
|
||||
<HeaderIconActionButton
|
||||
title={t('header.actions.rightSidebarWithShortcut', { shortcut: shortcutLabel('toggle_right_sidebar') })}
|
||||
ariaLabel={t('header.actions.toggleRightSidebarAria')}
|
||||
onClick={toggleRightSidebar}
|
||||
Icon={RiLayoutRightLine}
|
||||
Icon={'layout-right'}
|
||||
/>
|
||||
<DesktopGitHubControl
|
||||
isMobile={isMobile}
|
||||
@@ -1848,7 +1846,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
ariaLabel={t('header.actions.openSessionsAria')}
|
||||
onClick={handleOpenSessionSwitcher}
|
||||
className={`${desktopHeaderIconButtonClass} shrink-0`}
|
||||
Icon={RiLayoutLeftLine}
|
||||
Icon={'layout-left'}
|
||||
/>
|
||||
|
||||
<div className={cn('flex min-w-0 flex-1 items-center', !isSidebarOpen && 'pl-3')}>
|
||||
@@ -1861,7 +1859,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
onClick={handleHeaderNewSession}
|
||||
className={cn(desktopHeaderIconButtonClass, 'mr-6 shrink-0')}
|
||||
>
|
||||
<RiChatNewLine className="h-[18px] w-[18px]" />
|
||||
<Icon name="chat-new" className="h-[18px] w-[18px]" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
@@ -1886,7 +1884,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
{activeProjectLabel ? <span className="truncate">{activeProjectLabel}</span> : null}
|
||||
{currentBranchLabel ? (
|
||||
<span className="inline-flex min-w-0 items-center gap-0.5">
|
||||
<RiGitBranchLine className="h-3 w-3 flex-shrink-0 text-muted-foreground/70" />
|
||||
<Icon name="git-branch" className="h-3 w-3 flex-shrink-0 text-muted-foreground/70" />
|
||||
<span className="truncate">{currentBranchLabel}</span>
|
||||
</span>
|
||||
) : null}
|
||||
@@ -1902,7 +1900,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
"inline-flex min-w-0 items-center gap-0.5",
|
||||
worktreeBadgeKind === 'attention' || worktreeBadgeKind === 'invalid' || worktreeBadgeKind === 'missing' ? 'text-status-warning' : 'text-muted-foreground/60'
|
||||
)}>
|
||||
<RiAlertLine className="h-3 w-3 flex-shrink-0" />
|
||||
<Icon name="alert" className="h-3 w-3 flex-shrink-0" />
|
||||
<span className="truncate">{worktreeBadge}</span>
|
||||
</span>
|
||||
) : null}
|
||||
@@ -1943,7 +1941,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
ariaLabel={isNewSessionDraftOpen ? t('header.actions.newMiniChatAria') : t('header.actions.openSessionMiniChatAria')}
|
||||
onClick={handleOpenCurrentMiniChat}
|
||||
className={cn(desktopHeaderIconButtonClass, desktopSidebarActionsInline && showDesktopHeaderContextUsage ? 'mr-3.5' : 'mr-1')}
|
||||
Icon={RiPictureInPicture2Line}
|
||||
Icon={'picture-in-picture-2'}
|
||||
/>
|
||||
{desktopSidebarActionsInline ? desktopSidebarActions : null}
|
||||
{!desktopSidebarActionsInline && desktopRightSidebarActionsHost
|
||||
@@ -1968,7 +1966,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
)}
|
||||
aria-label={leftDrawerOpen ? t('header.actions.closeSessionsAria') : t('header.actions.openSessionsAria')}
|
||||
>
|
||||
<RiLayoutLeftLine className="h-5 w-5" />
|
||||
<Icon name="layout-left" className="h-5 w-5" />
|
||||
</button>
|
||||
) : isSessionSwitcherOpen ? (
|
||||
<button
|
||||
@@ -1977,7 +1975,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
className="app-region-no-drag h-9 w-9 p-2 text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded-md active:bg-interactive-active"
|
||||
aria-label={t('header.actions.backAria')}
|
||||
>
|
||||
<RiArrowLeftSLine className="h-5 w-5" />
|
||||
<Icon name="arrow-left-s" className="h-5 w-5" />
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
@@ -1986,7 +1984,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
className="app-region-no-drag h-9 w-9 p-2 text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded-md active:bg-interactive-active"
|
||||
aria-label={t('header.actions.openSessionsAria')}
|
||||
>
|
||||
<RiPlayListAddLine className="h-5 w-5" />
|
||||
<Icon name="play-list-add" className="h-5 w-5" />
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -2009,7 +2007,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
{tabs.map((tab) => {
|
||||
const isActive = activeMainTab === tab.id;
|
||||
const isDiffTab = tab.icon === 'diff';
|
||||
const Icon = isDiffTab ? null : (tab.icon as RemixiconComponentType);
|
||||
const tabIconName = isDiffTab ? null : (tab.icon as IconName);
|
||||
return (
|
||||
<Tooltip key={tab.id}>
|
||||
<TooltipTrigger asChild>
|
||||
@@ -2032,8 +2030,8 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
>
|
||||
{isDiffTab ? (
|
||||
<DiffIcon className="h-5 w-5" />
|
||||
) : Icon ? (
|
||||
<Icon className="h-5 w-5" />
|
||||
) : tabIconName ? (
|
||||
<Icon name={tabIconName} className="h-5 w-5" />
|
||||
) : null}
|
||||
{tab.badge !== undefined && tab.badge > 0 && (
|
||||
<span className="absolute -top-1 -right-1 text-[10px] font-semibold text-primary">
|
||||
@@ -2088,7 +2086,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
aria-label={t('header.services.viewAria')}
|
||||
className={mobileHeaderIconButtonClass}
|
||||
>
|
||||
<RiStackLine className="h-5 w-5" />
|
||||
<Icon name="stack" className="h-5 w-5" />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
</TooltipTrigger>
|
||||
@@ -2128,7 +2126,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
className="inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-interactive-hover"
|
||||
aria-label={t('header.services.closeAria')}
|
||||
>
|
||||
<RiCloseLine className="h-5 w-5" />
|
||||
<Icon name="close" className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2187,7 +2185,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
disabled={isQuotaLoading || isUsageRefreshSpinning}
|
||||
aria-label={t('header.services.refreshRateLimitsAria')}
|
||||
>
|
||||
<RiRefreshLine className={cn('h-4 w-4', isUsageRefreshSpinning && 'animate-spin')} />
|
||||
<Icon name="refresh" className={cn('h-4 w-4', isUsageRefreshSpinning && 'animate-spin')} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2279,9 +2277,9 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
{family.familyLabel}
|
||||
</span>
|
||||
{isExpanded ? (
|
||||
<RiArrowDownSLine className="h-4 w-4 text-muted-foreground" />
|
||||
<Icon name="arrow-down-s" className="h-4 w-4 text-muted-foreground" />
|
||||
) : (
|
||||
<RiArrowRightSLine className="h-4 w-4 text-muted-foreground" />
|
||||
<Icon name="arrow-right-s" className="h-4 w-4 text-muted-foreground" />
|
||||
)}
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
@@ -2348,7 +2346,7 @@ export const Header: React.FC<HeaderProps> = ({
|
||||
)}
|
||||
aria-label={rightDrawerOpen ? 'Close git sidebar' : 'Open git sidebar'}
|
||||
>
|
||||
<RiLayoutRightLine className="h-5 w-5" />
|
||||
<Icon name="layout-right" className="h-5 w-5" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
|
||||
Reference in New Issue
Block a user