ΠŸΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ ΠΊ основному содСрТимому

🎨 Руководство ΠΏΠΎ ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ Lucide Icons Π² Sidebar

Π­Ρ‚ΠΎ руководство ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ способы добавлСния красивых ΠΈΠΊΠΎΠ½ΠΎΠΊ Lucide Π² Π±ΠΎΠΊΠΎΠ²ΡƒΡŽ панСль вашСго Docusaurus ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°.

πŸš€ Бпособ 1: React ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ (РСкомСндуСтся)​

Установка​

npm install lucide-react

Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° компонСнтов​

// src/components/SidebarIcon/index.tsx
import React from 'react';
import * as Icons from 'lucide-react';

interface SidebarIconProps {
iconName: string;
size?: number;
className?: string;
strokeWidth?: number;
}

/** ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Lucide-ΠΈΠΊΠΎΠ½ΠΊΠΈ для sidebar */
const SidebarIcon: React.FC<SidebarIconProps> = ({ iconName, size = 20, className = '', strokeWidth = 1.5 }) => {
// ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΏΠΎ названию
const IconComponent = (Icons as any)[iconName] as React.ComponentType<any>;

if (!IconComponent) {
console.warn(`Icon "${iconName}" not found in lucide-react`);
return null;
}

return (
<IconComponent
size={size}
strokeWidth={strokeWidth}
className={`sidebar-icon ${className}`}
/>
);
};

export default SidebarIcon;

ОбновлСниС Sidebar​

// sidebars.js
const sidebars = {
tutorialSidebar: [
{
type: 'doc',
id: 'intro',
customProps: {
icon: 'Home', // НазваниС иконки из lucide-react
},
},
{
type: 'category',
label: 'Руководства',
customProps: {
icon: 'BookOpen',
},
items: [
{
type: 'doc',
id: 'guides/getting-started',
customProps: {
icon: 'Play',
},
},
],
},
],
};

Swizzled компонСнт​

// src/theme/DocSidebarItem/index.tsx (ΡƒΠΏΡ€ΠΎΡ‰Ρ‘Π½Π½Ρ‹ΠΉ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚)
import React, {type ReactNode} from 'react';
import DocSidebarItem from '@theme-original/DocSidebarItem';
import SidebarIcon from '../../components/SidebarIcon';

export default function DocSidebarItemWrapper(props: any): ReactNode {
const { item } = props;
const itemWithProps = item as any;
const hasCustomIcon = itemWithProps.customProps?.icon && typeof itemWithProps.customProps.icon === 'string';

// 1) Если ΠΈΠΊΠΎΠ½ΠΊΠ° Π·Π°Π΄Π°Π½Π° явно β€” ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π΅Ρ‘
if (hasCustomIcon) {
const labelElement = (
<span className="sidebar-item-with-icon">
<SidebarIcon iconName={itemWithProps.customProps.icon} size={20} strokeWidth={1.5} />
<span className="sidebar-item-text">{itemWithProps.label}</span>
</span>
);
return <DocSidebarItem {...props} item={{ ...item, label: labelElement }} />;
}

// 2) ΠšΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΡ Π±Π΅Π· кастомной ΠΈΠΊΠΎΠ½ΠΊΠΈ β€” Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠΌ ΠΎΠ±Π΅ (FolderClosed/FolderOpen)
if ((item as any).type === 'category') {
const labelElement = (
<span className="sidebar-item-with-icon">
<SidebarIcon iconName="FolderClosed" size={20} className="sidebar-icon-folder-closed" />
<SidebarIcon iconName="FolderOpen" size={20} className="sidebar-icon-folder-open" />
<span className="sidebar-item-text">{itemWithProps.label}</span>
</span>
);
return <DocSidebarItem {...props} item={{ ...item, label: labelElement }} />;
}

// 3) Π€Π°ΠΉΠ» Π±Π΅Π· кастомной ΠΈΠΊΠΎΠ½ΠΊΠΈ β€” File
const labelElement = (
<span className="sidebar-item-with-icon">
<SidebarIcon iconName="File" size={20} strokeWidth={1.5} />
<span className="sidebar-item-text">{itemWithProps.label}</span>
</span>
);
return <DocSidebarItem {...props} item={{ ...item, label: labelElement }} />;
}

✨ Fallback иконки​

БистСма автоматичСски ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, Ссли кастомная ΠΈΠΊΠΎΠ½ΠΊΠ° Π½Π΅ Π·Π°Π΄Π°Π½Π°:

  • Для ΠΏΠ°ΠΏΠΎΠΊ (ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ): FolderClosed ΠΊΠΎΠ³Π΄Π° ΠΏΠ°ΠΏΠΊΠ° Π·Π°ΠΊΡ€Ρ‹Ρ‚Π°, FolderOpen ΠΊΠΎΠ³Π΄Π° ΠΏΠ°ΠΏΠΊΠ° ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Π°
  • Для Ρ„Π°ΠΉΠ»ΠΎΠ² (Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ²): File Ссли кастомная ΠΈΠΊΠΎΠ½ΠΊΠ° Π½Π΅ ΡƒΠΊΠ°Π·Π°Π½Π°

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ использования fallback​

// sidebars.js
const sidebars = {
tutorialSidebar: [
// Π‘Π΅Π· customProps - Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠΊΠ°Π·Π°Π½Π° ΠΈΠΊΠΎΠ½ΠΊΠ° File
'intro',

{
type: 'category',
label: 'Руководства',
// Π‘Π΅Π· customProps - Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠΊΠ°Π·Π°Π½Π° ΠΈΠΊΠΎΠ½ΠΊΠ° Folder/FolderOpen
items: [
// Π’ΠΎΠΆΠ΅ Π±Π΅Π· ΠΈΠΊΠΎΠ½ΠΊΠΈ - ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ File
'guides/getting-started',

// Π‘ кастомной ΠΈΠΊΠΎΠ½ΠΊΠΎΠΉ
{
type: 'doc',
id: 'guides/advanced',
customProps: {
icon: 'Rocket',
},
},
],
},
],
};

ДинамичСскоС ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΎΠΊ папок​

ΠŸΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ΠΎ Ρ‡Π΅Ρ€Π΅Π· CSS ΠΏΠΎ классам menu__list-item--collapsed ΠΈ aria-expanded:

/* src/css/custom.css */
.sidebar-icon-folder-open { display: none; }
.menu__list-item--collapsed .sidebar-icon-folder-closed { display: inline-block; }
.menu__list-item--collapsed .sidebar-icon-folder-open { display: none; }
.menu__list-item:not(.menu__list-item--collapsed) .sidebar-icon-folder-closed { display: none; }
.menu__list-item:not(.menu__list-item--collapsed) .sidebar-icon-folder-open { display: inline-block; }

🎯 Бпособ 2: CSS Data-атрибуты​

Π‘ΠΎΠ»Π΅Π΅ простой ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ Ρ‡Π΅Ρ€Π΅Π· CSS:

1. CSS стили​

/* src/css/custom.css */
[data-sidebar-icon]::before {
content: '';
display: inline-block;
width: 16px;
height: 16px;
margin-right: 8px;
background-size: contain;
vertical-align: middle;
}

[data-sidebar-icon="home"]::before {
background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJtMyA5IDkgLTcgOSA3djExYTJbUg0KMTEwIDBoLTRWMTBhMiAyIDAgMCAwIC0yIC0yaDJhMiAyIDAgMCAwIC0yIDJ2NGgtNFoiLz48L3N2Zz4=');
}

[data-sidebar-icon="book"]::before {
background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiI+PHBhdGggZD0iTTIgM2g2YTQgNCAwIDAgMSA0IDR2MThsLTMtMy0zIDN2LTEuNWEyIDIgMCAwIDAtMi0yaDYiLz48L3N2Zz4=');
}

2. Sidebar конфигурация​

// sidebars.js
const sidebars = {
tutorialSidebar: [
{
type: 'doc',
id: 'intro',
customProps: {
'data-sidebar-icon': 'home',
},
},
{
type: 'category',
label: 'Руководства',
customProps: {
'data-sidebar-icon': 'book',
},
items: ['guides/getting-started'],
},
],
};

🌟 Бпособ 3: Emoji иконки​

Π‘Π°ΠΌΡ‹ΠΉ простой способ - ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ emoji:

// sidebars.js
const sidebars = {
tutorialSidebar: [
{
type: 'category',
label: '🏠 Главная',
items: ['intro'],
},
{
type: 'category',
label: 'πŸ“š Руководства',
items: ['guides/getting-started'],
},
{
type: 'category',
label: 'βš™οΈ Настройки',
items: ['settings/overview'],
},
],
};

🎨 Бтилизация иконок​

ВСмная/свСтлая тСма​

/* Π‘Π°Π·ΠΎΠ²Ρ‹Π΅ ΠΏΡ€Π°Π²ΠΈΠ»Π° для Lucide */
.sidebar-icon {
stroke: currentColor !important;
fill: none !important;
}

[data-theme='dark'] .sidebar-icon { /* Ρ†Π²Π΅Ρ‚ задаётся Ρ‚Π΅ΠΌΠΎΠΉ */ }
[data-theme='light'] .sidebar-icon { /* Ρ†Π²Π΅Ρ‚ задаётся Ρ‚Π΅ΠΌΠΎΠΉ */ }

πŸ“¦ ДоступныС ΠΈΠΊΠΎΠ½ΠΊΠΈ Lucide​

ΠŸΠΎΠΏΡƒΠ»ΡΡ€Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ для Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ:

  • Навигация: Home, ArrowLeft, ArrowRight, ChevronDown
  • Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹: FileText, BookOpen, File, Folder
  • ДСйствия: Settings, Search, Edit, Save
  • Бостояния: CheckCircle, AlertTriangle, Info, X
  • Π Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°: Code2, Terminal, GitBranch, Database
  • Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ: Menu, Grid, List, Layout

Поиск иконок​

ΠŸΠΎΠ»Π½Ρ‹ΠΉ список доступСн Π½Π° lucide.dev.

πŸ”§ Π‘ΠΎΠ²Π΅Ρ‚Ρ‹ ΠΈ рСкомСндации​

1. ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒβ€‹

// Π˜ΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠΉΡ‚Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½ΡƒΠΆΠ½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ
import { Home, BookOpen, Settings } from 'lucide-react';

// ВмСсто ΠΈΠΌΠΏΠΎΡ€Ρ‚Π° всСх
import * as Icons from 'lucide-react';

2. ΠšΠΎΠ½ΡΠΈΡΡ‚Π΅Π½Ρ‚Π½ΠΎΡΡ‚ΡŒβ€‹

// Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΌΠ°ΠΏΠΈΠ½Π³ для консистСнтности
const ICON_MAPPING = {
intro: 'Home',
guide: 'BookOpen',
api: 'Code2',
settings: 'Settings',
};

3. Fallback иконки​

БистСма автоматичСски прСдоставляСт fallback ΠΈΠΊΠΎΠ½ΠΊΠΈ:

// АвтоматичСскиС fallback (ΡƒΠΆΠ΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ΠΎ)
// - Папки: Folder (Π·Π°ΠΊΡ€Ρ‹Ρ‚Π°) / FolderOpen (ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Π°)
// - Π€Π°ΠΉΠ»Ρ‹: File

// Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ fallback Π² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π΅ SidebarIcon
const SidebarIcon = ({ iconName, fallback = 'Circle' }) => {
const IconComponent = Icons[iconName] || Icons[fallback];
return <IconComponent size={16} />;
};

4. Π Π°Π±ΠΎΡ‚Π° с Π΄Π»ΠΈΠ½Π½Ρ‹ΠΌΠΈ названиями​

БистСма автоматичСски ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π΄Π»ΠΈΠ½Π½Ρ‹Π΅ названия Π±Π΅Π· ΡƒΡ‰Π΅Ρ€Π±Π° для ΠΈΠΊΠΎΠ½ΠΎΠΊ:

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ с Π΄Π»ΠΈΠ½Π½Ρ‹ΠΌ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ
{
type: 'doc',
id: 'guides/comprehensive-guide',
label: 'ΠžΡ‡Π΅Π½ΡŒ Π΄Π»ΠΈΠ½Π½ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ руководства, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π½ΠΎΡΠΈΡ‚ΡŒΡΡ Π½Π° нСсколько строк Π² sidebar',
customProps: {
icon: 'BookOpen',
},
}

ΠžΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ:

  • βœ… Иконки ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ фиксированный Ρ€Π°Π·ΠΌΠ΅Ρ€ 20x20px
  • βœ… Иконки Π²Ρ‹Ρ€Π°Π²Π½ΠΈΠ²Π°ΡŽΡ‚ΡΡ ΠΏΠΎ Π²Π΅Ρ€Ρ…Π½Π΅ΠΌΡƒ ΠΊΡ€Π°ΡŽ тСкста
  • βœ… ВСкст автоматичСски пСрСносится с пСрСносом слов
  • βœ… Иконки Π½Π΅ ΡΠΆΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΏΡ€ΠΈ любой Π΄Π»ΠΈΠ½Π΅ тСкста

CSS стили (автоматичСски ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ):

.sidebar-icon {
flex-shrink: 0 !important; /* НС сТимаСтся */
align-self: center !important; /* Π¦Π΅Π½Ρ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊ многострочному тСксту */
min-width: 20px !important;
width: 20px !important;
height: 20px !important;
}

5. БмСшанноС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΠ΅β€‹

// ΠšΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΡƒΠΉΡ‚Π΅ кастомныС ΠΈΠΊΠΎΠ½ΠΊΠΈ с автоматичСскими fallback
const sidebars = {
tutorialSidebar: [
// АвтоматичСская ΠΈΠΊΠΎΠ½ΠΊΠ° File
'intro',

{
type: 'category',
label: 'API',
customProps: { icon: 'Code2' }, // ΠšΠ°ΡΡ‚ΠΎΠΌΠ½Π°Ρ ΠΈΠΊΠΎΠ½ΠΊΠ°
items: [
'api/getting-started', // АвтоматичСская ΠΈΠΊΠΎΠ½ΠΊΠ° File
{
type: 'doc',
id: 'api/authentication',
customProps: { icon: 'Lock' }, // ΠšΠ°ΡΡ‚ΠΎΠΌΠ½Π°Ρ ΠΈΠΊΠΎΠ½ΠΊΠ°
},
],
},
],
};

⚑ Troubleshooting​

ЧастыС проблСмы​

  1. Иконка Π½Π΅ отобраТаСтся: ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΡΡ‚ΡŒ написания ΠΈΠΌΠ΅Π½ΠΈ
  2. TypeScript ошибки: Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ as any для ΠΎΠ±Ρ…ΠΎΠ΄Π° Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ
  3. Π‘Ρ‚ΠΈΠ»ΠΈ Π½Π΅ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ: Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ CSS загруТаСтся послС Docusaurus стилСй
  4. Fallback ΠΈΠΊΠΎΠ½ΠΊΠΈ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚: Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ swizzled ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ DocSidebarItem установлСн ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ
  5. Папки Π½Π΅ ΠΌΠ΅Π½ΡΡŽΡ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ: ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅, Ρ‡Ρ‚ΠΎ состояниС collapsed пСрСдаСтся ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ
  6. Иконки ΡΠΆΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΏΡ€ΠΈ Π΄Π»ΠΈΠ½Π½ΠΎΠΌ тСкстС: БистСма автоматичСски ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ сТатиС ΠΈΠΊΠΎΠ½ΠΎΠΊ

ΠžΡ‚Π»Π°Π΄ΠΊΠ°β€‹

// Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π»ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅
console.log('Available icons:', Object.keys(Icons));
console.log('Looking for icon:', iconName);