fix(shell): compact communications header and theme sidebar
|
Before Width: | Height: | Size: 254 KiB After Width: | Height: | Size: 255 KiB |
|
Before Width: | Height: | Size: 219 KiB After Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 214 KiB After Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"generatedAt": "2026-09-11T12:29:57.828Z",
|
||||
"generatedAt": "2026-09-12T05:25:45.504Z",
|
||||
"module": "communications",
|
||||
"version": "v3.0",
|
||||
"referenceMockups": [
|
||||
|
|
@ -68,13 +68,13 @@
|
|||
"filename": "desktop-with-krona-ai.png",
|
||||
"theme": "state-capture",
|
||||
"viewport": "desktop-with-krona-ai",
|
||||
"capturedAt": "2026-09-11T12:29:50.764Z"
|
||||
"capturedAt": "2026-09-12T05:25:45.132Z"
|
||||
},
|
||||
{
|
||||
"filename": "desktop-without-krona-ai.png",
|
||||
"theme": "state-capture",
|
||||
"viewport": "desktop-without-krona-ai",
|
||||
"capturedAt": "2026-09-11T12:29:49.887Z"
|
||||
"capturedAt": "2026-09-12T05:25:44.475Z"
|
||||
},
|
||||
{
|
||||
"filename": "graphite-forest-dark-desktop-1280.png",
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
"filename": "graphite-forest-dark-desktop-1440.png",
|
||||
"theme": "graphite-forest-dark",
|
||||
"viewport": "desktop-1440",
|
||||
"capturedAt": "2026-09-11T12:22:07.332Z"
|
||||
"capturedAt": "2026-09-12T05:25:42.065Z"
|
||||
},
|
||||
{
|
||||
"filename": "graphite-forest-dark-desktop-1920.png",
|
||||
|
|
@ -104,7 +104,7 @@
|
|||
"filename": "graphite-forest-dark-mobile-390.png",
|
||||
"theme": "graphite-forest-dark",
|
||||
"viewport": "mobile-390",
|
||||
"capturedAt": "2026-09-11T12:21:02.940Z"
|
||||
"capturedAt": "2026-09-12T05:25:33.933Z"
|
||||
},
|
||||
{
|
||||
"filename": "graphite-forest-dark-mobile-430.png",
|
||||
|
|
@ -128,19 +128,19 @@
|
|||
"filename": "mobile-chat.png",
|
||||
"theme": "state-capture",
|
||||
"viewport": "mobile-chat",
|
||||
"capturedAt": "2026-09-11T12:29:13.147Z"
|
||||
"capturedAt": "2026-09-12T05:25:36.209Z"
|
||||
},
|
||||
{
|
||||
"filename": "mobile-contact.png",
|
||||
"theme": "state-capture",
|
||||
"viewport": "mobile-contact",
|
||||
"capturedAt": "2026-09-11T12:29:13.337Z"
|
||||
"capturedAt": "2026-09-12T05:25:36.390Z"
|
||||
},
|
||||
{
|
||||
"filename": "mobile-list.png",
|
||||
"theme": "state-capture",
|
||||
"viewport": "mobile-list",
|
||||
"capturedAt": "2026-09-11T12:29:12.902Z"
|
||||
"capturedAt": "2026-09-12T05:25:35.998Z"
|
||||
},
|
||||
{
|
||||
"filename": "noble-green-desktop-1280.png",
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
"filename": "noble-green-desktop-1440.png",
|
||||
"theme": "noble-green",
|
||||
"viewport": "desktop-1440",
|
||||
"capturedAt": "2026-09-11T12:22:06.701Z"
|
||||
"capturedAt": "2026-09-12T05:25:41.554Z"
|
||||
},
|
||||
{
|
||||
"filename": "noble-green-desktop-1920.png",
|
||||
|
|
@ -170,7 +170,7 @@
|
|||
"filename": "noble-green-mobile-390.png",
|
||||
"theme": "noble-green",
|
||||
"viewport": "mobile-390",
|
||||
"capturedAt": "2026-09-11T12:21:02.534Z"
|
||||
"capturedAt": "2026-09-12T05:25:33.543Z"
|
||||
},
|
||||
{
|
||||
"filename": "noble-green-mobile-430.png",
|
||||
|
|
@ -200,7 +200,7 @@
|
|||
"filename": "parchment-light-desktop-1440.png",
|
||||
"theme": "parchment-light",
|
||||
"viewport": "desktop-1440",
|
||||
"capturedAt": "2026-09-11T12:22:06.120Z"
|
||||
"capturedAt": "2026-09-12T05:25:41.001Z"
|
||||
},
|
||||
{
|
||||
"filename": "parchment-light-desktop-1920.png",
|
||||
|
|
@ -218,7 +218,7 @@
|
|||
"filename": "parchment-light-mobile-390.png",
|
||||
"theme": "parchment-light",
|
||||
"viewport": "mobile-390",
|
||||
"capturedAt": "2026-09-11T12:21:02.124Z"
|
||||
"capturedAt": "2026-09-12T05:25:33.154Z"
|
||||
},
|
||||
{
|
||||
"filename": "parchment-light-mobile-430.png",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 214 KiB After Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 215 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
|
@ -43,23 +43,16 @@ test.describe('Scenario 13: Communications Visual & Responsive Design System V3
|
|||
}
|
||||
});
|
||||
|
||||
test('2. Header, Slogan Watermark, and Channel Switcher validation', async ({ page }) => {
|
||||
test('2. Compact header and channel switcher validation', async ({ page }) => {
|
||||
const vp = page.viewportSize();
|
||||
const isMobile = (vp?.width ?? 1200) < 640;
|
||||
const isDesktop = (vp?.width ?? 1200) >= 1024;
|
||||
|
||||
// Check main header
|
||||
await expect(page.locator('h1', { hasText: 'Коммуникации' })).toBeVisible();
|
||||
|
||||
if (!isMobile) {
|
||||
await expect(
|
||||
page.locator('text=Все сообщения, почта и каналы компании в одном пространстве')
|
||||
).toBeVisible();
|
||||
}
|
||||
|
||||
if (isDesktop) {
|
||||
await expect(page.locator('text=Больше, чем общение с поддержкой')).toBeVisible();
|
||||
}
|
||||
await expect(page.getByText('Все сообщения, почта и каналы компании в одном пространстве')).toHaveCount(0);
|
||||
await expect(page.getByText('Больше, чем общение с поддержкой')).toHaveCount(0);
|
||||
await expect(page.getByRole('button', { name: /добавить канал/i })).toHaveCount(0);
|
||||
|
||||
// Check all 5 tabs
|
||||
await expect(page.getByRole('tab', { name: /мессенджеры/i })).toBeVisible();
|
||||
|
|
|
|||
|
|
@ -66,12 +66,12 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
return (
|
||||
<aside
|
||||
data-testid="sidebar"
|
||||
className={`relative h-screen bg-[#252722] text-[#D8D8D0] hidden md:flex flex-col border-r border-[#3A3D35] transition-all duration-200 z-20 select-none ${
|
||||
className={`relative h-screen bg-[var(--sidebar-bg)] text-[var(--sidebar-text)] hidden md:flex flex-col border-r border-[var(--sidebar-border)] transition-[width,background-color,color,border-color] duration-300 z-20 select-none ${
|
||||
collapsed ? 'w-16' : 'w-56'
|
||||
}`}
|
||||
>
|
||||
{/* Brand Header */}
|
||||
<div className="h-14 px-3.5 flex items-center justify-between border-b border-[#3A3D35] bg-[#20221E]">
|
||||
<div className="h-14 px-3.5 flex items-center justify-between border-b border-[var(--sidebar-border)] bg-[var(--sidebar-deep)] transition-colors duration-300">
|
||||
<div className="flex items-center gap-2.5 overflow-hidden">
|
||||
{/* Logo asset from public/branding/krona-symbol.png */}
|
||||
<img
|
||||
|
|
@ -81,10 +81,10 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
/>
|
||||
{!collapsed && (
|
||||
<div className="flex flex-col min-w-0 leading-tight select-none">
|
||||
<span className="text-sm font-bold tracking-wider text-[#E5B842] uppercase truncate">
|
||||
<span className="text-sm font-bold tracking-wider text-[var(--krona-gold)] uppercase truncate">
|
||||
Крона
|
||||
</span>
|
||||
<span className="text-[9px] uppercase tracking-widest text-[#B78335] font-semibold">
|
||||
<span className="text-[9px] uppercase tracking-widest text-[var(--krona-gold)] font-semibold">
|
||||
Бизнес-платформа
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -93,7 +93,7 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
|
||||
<button
|
||||
onClick={() => setUserCollapsed(!collapsed)}
|
||||
className="p-1 rounded text-[#858980] hover:text-[#D8D8D0] hover:bg-[#30332C] transition-colors"
|
||||
className="p-1 rounded text-[var(--sidebar-text-muted)] hover:text-[var(--sidebar-text)] hover:bg-[var(--sidebar-hover)] transition-colors"
|
||||
title={collapsed ? 'Развернуть меню' : 'Свернуть меню'}
|
||||
>
|
||||
{collapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
|
||||
|
|
@ -110,8 +110,8 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
className={({ isActive }) =>
|
||||
`group relative flex items-center gap-2.5 px-2.5 py-2 rounded-md text-xs font-medium transition-all ${
|
||||
isActive
|
||||
? 'bg-[#34382F] text-[#F5F0E5] font-semibold'
|
||||
: 'text-[#BFC1B9] hover:text-[#F5F0E5] hover:bg-[#30332C]'
|
||||
? 'bg-[var(--sidebar-active)] text-[var(--sidebar-text-active)] font-semibold'
|
||||
: 'text-[var(--sidebar-text-secondary)] hover:text-[var(--sidebar-text)] hover:bg-[var(--sidebar-hover)]'
|
||||
}`
|
||||
}
|
||||
title={collapsed ? item.label : undefined}
|
||||
|
|
@ -120,10 +120,10 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
<>
|
||||
{/* Active indicator bar */}
|
||||
{isActive && (
|
||||
<div className="absolute left-0 top-1.5 bottom-1.5 w-1 bg-[#B78335] rounded-r" />
|
||||
<div className="absolute left-0 top-1.5 bottom-1.5 w-1 bg-[var(--sidebar-indicator)] rounded-r" />
|
||||
)}
|
||||
|
||||
<div className={`shrink-0 ${isActive ? 'text-[#D4B16D]' : 'text-[#BFC1B9]'}`}>
|
||||
<div className={`shrink-0 ${isActive ? 'text-[var(--sidebar-icon-active)]' : 'text-[var(--sidebar-icon)]'}`}>
|
||||
{ICON_MAP[item.iconName] || <LayoutDashboard className="w-4 h-4 shrink-0" />}
|
||||
</div>
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
<div className="flex-1 flex items-center justify-between truncate">
|
||||
<span className="truncate">{item.label}</span>
|
||||
{item.badge && (
|
||||
<span className="text-[10px] px-1.5 py-0.5 rounded-full bg-[#3A3D35] text-[#D8D8D0] font-mono">
|
||||
<span className="text-[10px] px-1.5 py-0.5 rounded-full bg-[var(--sidebar-surface)] text-[var(--sidebar-text)] font-mono">
|
||||
{item.badge}
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -144,9 +144,9 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
|
||||
{/* Custom Entities Section */}
|
||||
{customEntities.length > 0 && (
|
||||
<div className="pt-2 mt-2 border-t border-[#3A3D35]/80">
|
||||
<div className="pt-2 mt-2 border-t border-[var(--sidebar-border)]">
|
||||
{!collapsed && (
|
||||
<div className="px-2 pb-1 text-[10px] font-semibold uppercase tracking-wider text-[#858980]">
|
||||
<div className="px-2 pb-1 text-[10px] font-semibold uppercase tracking-wider text-[var(--sidebar-text-muted)]">
|
||||
Пользовательские модули
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -157,8 +157,8 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
className={({ isActive }) =>
|
||||
`group relative flex items-center gap-2.5 px-2.5 py-1.5 rounded-md text-xs font-medium transition-all ${
|
||||
isActive
|
||||
? 'bg-[#34382F] text-[#F5F0E5] font-semibold'
|
||||
: 'text-[#BFC1B9] hover:text-[#F5F0E5] hover:bg-[#30332C]'
|
||||
? 'bg-[var(--sidebar-active)] text-[var(--sidebar-text-active)] font-semibold'
|
||||
: 'text-[var(--sidebar-text-secondary)] hover:text-[var(--sidebar-text)] hover:bg-[var(--sidebar-hover)]'
|
||||
}`
|
||||
}
|
||||
title={collapsed ? ent.name : undefined}
|
||||
|
|
@ -166,7 +166,7 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
{({ isActive }) => (
|
||||
<>
|
||||
{isActive && (
|
||||
<div className="absolute left-0 top-1.5 bottom-1.5 w-1 bg-[#B78335] rounded-r" />
|
||||
<div className="absolute left-0 top-1.5 bottom-1.5 w-1 bg-[var(--sidebar-indicator)] rounded-r" />
|
||||
)}
|
||||
<div className="shrink-0 text-krona-gold">
|
||||
<Sparkles className="w-3.5 h-3.5" />
|
||||
|
|
@ -188,8 +188,8 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
className={({ isActive }) =>
|
||||
`group relative flex items-center gap-2.5 px-2.5 py-1.5 rounded-md text-xs font-medium transition-all ${
|
||||
isActive
|
||||
? 'bg-[#34382F] text-[#F5F0E5] font-semibold'
|
||||
: 'text-[#BFC1B9] hover:text-[#F5F0E5] hover:bg-[#30332C]'
|
||||
? 'bg-[var(--sidebar-active)] text-[var(--sidebar-text-active)] font-semibold'
|
||||
: 'text-[var(--sidebar-text-secondary)] hover:text-[var(--sidebar-text)] hover:bg-[var(--sidebar-hover)]'
|
||||
}`
|
||||
}
|
||||
title={collapsed ? 'Конструктор сущностей' : undefined}
|
||||
|
|
@ -197,7 +197,7 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
{({ isActive }) => (
|
||||
<>
|
||||
{isActive && (
|
||||
<div className="absolute left-0 top-1.5 bottom-1.5 w-1 bg-[#B78335] rounded-r" />
|
||||
<div className="absolute left-0 top-1.5 bottom-1.5 w-1 bg-[var(--sidebar-indicator)] rounded-r" />
|
||||
)}
|
||||
<div className="shrink-0 text-krona-green">
|
||||
<Workflow className="w-3.5 h-3.5" />
|
||||
|
|
@ -212,14 +212,14 @@ export const Sidebar: React.FC<SidebarProps> = ({ isTabletCompact = false }) =>
|
|||
</div>
|
||||
|
||||
{/* Footer / Role indicator */}
|
||||
<div className="p-2.5 border-t border-[#3A3D35] bg-[#20221E]/60 text-xs">
|
||||
<div className="p-2.5 border-t border-[var(--sidebar-border)] bg-[var(--sidebar-deep)] text-xs transition-colors duration-300">
|
||||
{!collapsed ? (
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2 h-2 rounded-full bg-krona-green animate-pulse" />
|
||||
<div className="truncate">
|
||||
<div className="text-[11px] font-semibold text-[#F5F0E5] truncate">{role.label}</div>
|
||||
<div className="text-[9px] text-[#858980]">RBAC: {role.badge}</div>
|
||||
<div className="text-[11px] font-semibold text-[var(--sidebar-text)] truncate">{role.label}</div>
|
||||
<div className="text-[9px] text-[var(--sidebar-text-muted)]">RBAC: {role.badge}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ export const Topbar: React.FC = () => {
|
|||
if (m.route === '/') return currentPath === '/';
|
||||
return currentPath.startsWith(m.route);
|
||||
}) || SYSTEM_MODULES[0];
|
||||
const isCommunicationsModule = currentModule.id === 'communications';
|
||||
|
||||
// For operations, subtabs are dynamic based on active profile & capabilities
|
||||
const getSubtabs = () => {
|
||||
|
|
@ -351,8 +352,16 @@ export const Topbar: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Communications owns its local tabs inside the module. Keep only the
|
||||
module title here so the shell does not render a duplicate menu. */}
|
||||
{isCommunicationsModule && (
|
||||
<div className="hidden md:flex h-10 px-5 border-t border-krona-border/60 bg-krona-workspace/40 items-center shrink-0">
|
||||
<span className="font-serif text-lg font-bold text-krona-primary">Коммуникации</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Subheader / Subtabs Navigation Bar (Desktop & Tablet) */}
|
||||
{activeSubtabs.length > 0 && (
|
||||
{!isCommunicationsModule && activeSubtabs.length > 0 && (
|
||||
<div className="h-10 px-4 border-t border-krona-border/60 bg-krona-workspace/40 flex items-center overflow-x-auto gap-1 text-xs">
|
||||
{activeSubtabs.map((tab) => {
|
||||
const isActive =
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ export function CommunicationsModule() {
|
|||
<CommunicationsHeader
|
||||
activeTab={currentTab}
|
||||
onTabChange={handleTabChange}
|
||||
onAddChannel={() => setIsConnectChannelOpen(true)}
|
||||
unreadChats={48}
|
||||
unreadEmails={10}
|
||||
unreadChannels={4}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import React from 'react';
|
||||
import { MessageSquare, Mail, Hash, Users, Settings, Plus } from 'lucide-react';
|
||||
import { MessageSquare, Mail, Hash, Users, Settings } from 'lucide-react';
|
||||
import { CommunicationTab } from '../types';
|
||||
import { Button, Tabs } from '@krona/ui';
|
||||
import { Tabs } from '@krona/ui';
|
||||
|
||||
interface CommunicationsHeaderProps {
|
||||
activeTab: CommunicationTab;
|
||||
onTabChange: (tab: CommunicationTab) => void;
|
||||
onAddChannel: () => void;
|
||||
unreadChats: number;
|
||||
unreadEmails: number;
|
||||
unreadChannels: number;
|
||||
|
|
@ -15,7 +14,6 @@ interface CommunicationsHeaderProps {
|
|||
export function CommunicationsHeader({
|
||||
activeTab,
|
||||
onTabChange,
|
||||
onAddChannel,
|
||||
unreadChats,
|
||||
unreadEmails,
|
||||
unreadChannels,
|
||||
|
|
@ -52,51 +50,8 @@ export function CommunicationsHeader({
|
|||
];
|
||||
|
||||
return (
|
||||
<header className="relative bg-[var(--krona-surface)] border-b border-[var(--krona-border-subtle)] px-3 sm:px-6 pt-3 sm:pt-5 pb-2 sm:pb-3 shrink-0 overflow-hidden">
|
||||
<div className="hidden lg:flex items-center gap-3 absolute right-8 top-4 text-right pointer-events-none opacity-50 font-serif italic text-sm text-[var(--krona-text-secondary)]">
|
||||
<span>Больше, чем общение с поддержкой</span>
|
||||
<svg
|
||||
className="w-8 h-8 text-[var(--krona-gold)] shrink-0"
|
||||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.2"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path d="M16 28C16 18 20 10 28 6" strokeLinecap="round" />
|
||||
<path d="M16 24C12 20 8 18 4 17" strokeLinecap="round" />
|
||||
<path d="M16 19C20 16 24 15 27 15" strokeLinecap="round" />
|
||||
<path d="M16 14C12 11 9 10 6 10" strokeLinecap="round" />
|
||||
<path d="M18 10C21 8 24 7 26 7" strokeLinecap="round" />
|
||||
<circle cx="28" cy="6" r="1.5" fill="currentColor" />
|
||||
<circle cx="4" cy="17" r="1.5" fill="currentColor" />
|
||||
<circle cx="27" cy="15" r="1.5" fill="currentColor" />
|
||||
<circle cx="6" cy="10" r="1.5" fill="currentColor" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between gap-3 mb-2 sm:mb-4">
|
||||
<div>
|
||||
<h1 className="text-xl sm:text-3xl font-bold font-serif text-[var(--krona-text-primary)]">
|
||||
Коммуникации
|
||||
</h1>
|
||||
<p className="hidden sm:block text-sm text-[var(--krona-text-secondary)] mt-1">
|
||||
Все сообщения, почта и каналы компании в одном пространстве
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Mobile compact action button */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={onAddChannel}
|
||||
className="sm:hidden h-10 w-10 rounded-lg border border-[var(--krona-border)] bg-[var(--krona-surface)] hover:bg-[var(--krona-surface-hover)] text-[var(--krona-primary)] font-medium flex items-center justify-center shrink-0 transition-colors active:scale-95"
|
||||
aria-label="Добавить канал"
|
||||
>
|
||||
<Plus className="w-4 h-4 text-[var(--krona-primary)]" />
|
||||
<span className="sr-only">Добавить канал</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<header className="bg-[var(--krona-surface)] border-b border-[var(--krona-border-subtle)] px-3 sm:px-5 py-1.5 shrink-0 overflow-hidden">
|
||||
<h1 className="sr-only">Коммуникации</h1>
|
||||
<div className="flex items-center justify-between gap-3 min-w-0">
|
||||
<div className="flex-1 min-w-0 overflow-x-auto scrollbar-none">
|
||||
<Tabs
|
||||
|
|
@ -107,17 +62,6 @@ export function CommunicationsHeader({
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* Desktop / Tablet full button */}
|
||||
<div className="hidden sm:flex items-center gap-2 shrink-0">
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={onAddChannel}
|
||||
leftIcon={<Plus className="w-4 h-4 text-[var(--krona-primary)]" />}
|
||||
>
|
||||
Добавить канал
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
|
|
|||