From cb6e5a6f11f4356b6b5beb556604a890e0f67516 Mon Sep 17 00:00:00 2001 From: Vladimir Korotaev Date: Tue, 25 Aug 2026 14:49:10 +0300 Subject: [PATCH 1/2] feat(icons): add category filtering and mobile category sheet --- package-lock.json | 8 +- package.json | 2 +- .../IconCollection/IconButton/IconButton.scss | 7 +- .../IconCollection/IconButton/IconButton.tsx | 2 +- .../Icons/IconCollection/IconCollection.scss | 8 +- src/components/Icons/Icons.scss | 177 ++++++++++++++++++ src/components/Icons/Icons.tsx | 125 ++++++++++++- src/components/Icons/categories.ts | 34 ++++ src/components/Icons/types.ts | 6 + 9 files changed, 346 insertions(+), 23 deletions(-) create mode 100644 src/components/Icons/categories.ts diff --git a/package-lock.json b/package-lock.json index 6f0812682276..20a52859a016 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@gravity-ui/date-components": "^3.4.2", "@gravity-ui/date-utils": "^2.6.0", "@gravity-ui/graph": "^1.9.1", - "@gravity-ui/icons": "^2.21.0", + "@gravity-ui/icons": "^2.22.0", "@gravity-ui/illustrations": "^2.1.1", "@gravity-ui/markdown-editor": "^15.1.0", "@gravity-ui/navigation": "^6.3.1", @@ -3738,9 +3738,9 @@ "integrity": "sha512-bVt/UGjL96Naw0h03QW+3z2tf6t4zvLh1j+eFzpdLlAIMeNu0dRjxn4X6EGtwhwKrfMyIfrlOqmLSroXtCNQAw==" }, "node_modules/@gravity-ui/icons": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/@gravity-ui/icons/-/icons-2.21.0.tgz", - "integrity": "sha512-KWghsvXDq+5AapT3bh2a/p1Iv923PDFln/U51fqaK9AMOftiOlkWfJHSJEFSxpgvbCJ/MOHjCSbhCT7Jx9mJAg==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@gravity-ui/icons/-/icons-2.22.0.tgz", + "integrity": "sha512-v304kVTXbtsq8b3Uq3ZnX9R3LnRdECToeLspDgCs92C9fcID4C7dJqS3PywHKEaM4PFEZO8LRp/6JQbIm9UjHA==", "license": "MIT", "dependencies": { "tslib": "^2.8.1" diff --git a/package.json b/package.json index ecf621fc3319..0ab92943a8fa 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@gravity-ui/date-components": "^3.4.2", "@gravity-ui/date-utils": "^2.6.0", "@gravity-ui/graph": "^1.9.1", - "@gravity-ui/icons": "^2.21.0", + "@gravity-ui/icons": "^2.22.0", "@gravity-ui/illustrations": "^2.1.1", "@gravity-ui/markdown-editor": "^15.1.0", "@gravity-ui/navigation": "^6.3.1", diff --git a/src/components/Icons/IconCollection/IconButton/IconButton.scss b/src/components/Icons/IconCollection/IconButton/IconButton.scss index 26b04b7714c7..a28b2beb97fd 100644 --- a/src/components/Icons/IconCollection/IconButton/IconButton.scss +++ b/src/components/Icons/IconCollection/IconButton/IconButton.scss @@ -7,14 +7,15 @@ $block: '.#{variables.$ns}icon-button'; &.g-button, &.g-button:has(.g-button__icon:only-child) { --g-button-border-radius: 16px; + --g-button-background-color: #281a26; display: flex; justify-content: center; align-items: center; - width: 62px; - height: 62px; + width: 150px; + height: 150px; } &:hover { - --g-button-background-color: rgba(255, 255, 255, 0.16); + --g-button-background-color: #3c2e3a; } } diff --git a/src/components/Icons/IconCollection/IconButton/IconButton.tsx b/src/components/Icons/IconCollection/IconButton/IconButton.tsx index 7b3e88cd8638..7e67fe3c89e1 100644 --- a/src/components/Icons/IconCollection/IconButton/IconButton.tsx +++ b/src/components/Icons/IconCollection/IconButton/IconButton.tsx @@ -8,7 +8,7 @@ import './IconButton.scss'; const b = block('icon-button'); -const ICON_SIZE = 20; +const ICON_SIZE = 24; interface IconsProps { icon: IconItem; diff --git a/src/components/Icons/IconCollection/IconCollection.scss b/src/components/Icons/IconCollection/IconCollection.scss index 8d6116e96c5f..7ff970b96822 100644 --- a/src/components/Icons/IconCollection/IconCollection.scss +++ b/src/components/Icons/IconCollection/IconCollection.scss @@ -1,11 +1,9 @@ -@use '~@gravity-ui/page-constructor/styles/variables.scss' as pcVariables; @use '../../../variables.scss'; $block: '.#{variables.$ns}icon-collection'; #{$block} { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: pcVariables.$indentXS; + display: grid; + grid-template-columns: repeat(auto-fill, 150px); + gap: 20px; } diff --git a/src/components/Icons/Icons.scss b/src/components/Icons/Icons.scss index b677af8df9fb..c5637c0a066c 100644 --- a/src/components/Icons/Icons.scss +++ b/src/components/Icons/Icons.scss @@ -104,4 +104,181 @@ $block: '.#{variables.$ns}icons'; color: rgba(255, 255, 255, 0.8); } } + + &__catalog { + display: flex; + align-items: flex-start; + gap: 32px; + } + + &__categories { + position: sticky; + top: 76px; + flex: 0 0 200px; + max-height: calc(100vh - 96px); + overflow-y: auto; + scrollbar-width: thin; + } + + &__section-title { + margin: 0; + color: var(--g-color-text-primary); + font-size: 20px; + line-height: 24px; + font-weight: 600; + } + + &__category-list { + display: flex; + flex-direction: column; + margin-top: 20px; + } + + &__category { + display: flex; + width: 100%; + height: 36px; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 8px 12px; + border: 0; + border-radius: 8px; + color: var(--g-color-text-primary); + background: transparent; + font: inherit; + font-size: 13px; + line-height: 20px; + text-align: left; + cursor: pointer; + + &:hover { + background: rgba(255, 255, 255, 0.06); + } + + &_selected, + &_selected:hover { + background: rgba(255, 190, 92, 0.08); + } + + &:disabled { + color: var(--g-color-text-hint); + background: transparent; + cursor: default; + + #{$block}__category-count { + color: var(--g-color-text-hint); + } + } + } + + &__category-count, + &__results-count { + color: var(--g-color-text-secondary); + font-size: 13px; + font-weight: 400; + } + + &__results { + min-width: 0; + flex: 1 1 auto; + } + + &__results-heading { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 20px; + } + + &__mobile-category-trigger { + display: none; + } + + &__category-sheet { + --g-color-base-float: #474247; + } + + &__category-sheet-content { + padding: 0 20px 16px; + + .g-sheet__sheet-content-title { + min-height: 48px; + justify-content: flex-start; + border-bottom: 1px solid var(--g-color-line-generic); + font-size: 20px; + line-height: 24px; + text-align: left; + } + } + + &__category-sheet-list { + max-height: calc(100vh - 168px); + padding-top: 8px; + overflow-y: auto; + + #{$block}__category { + height: 44px; + padding: 12px 16px; + border-radius: 6px; + font-size: 15px; + } + + #{$block}__category-count { + font-size: 11px; + } + } + + @media (max-width: map-get(pcVariables.$gridBreakpoints, 'md') - 1) { + &__catalog { + display: block; + gap: 24px; + } + + &__categories { + display: none; + } + + &__mobile-category-trigger { + display: flex; + width: 100%; + height: 44px; + align-items: center; + justify-content: space-between; + margin-bottom: 24px; + padding: 12px 16px; + border: 0; + border-radius: 12px; + color: var(--g-color-text-primary); + background: rgba(255, 255, 255, 0.08); + font: inherit; + text-align: left; + cursor: pointer; + + &:disabled { + color: var(--g-color-text-hint); + cursor: default; + } + } + + &__mobile-category-label { + font-size: 15px; + line-height: 20px; + font-weight: 500; + } + + &__mobile-category-count { + color: var(--g-color-text-secondary); + font-size: 13px; + line-height: 18px; + } + + &__results { + width: 100%; + } + + &__results-heading { + display: none; + } + } } diff --git a/src/components/Icons/Icons.tsx b/src/components/Icons/Icons.tsx index dd4b76fb1461..87c3fc080578 100644 --- a/src/components/Icons/Icons.tsx +++ b/src/components/Icons/Icons.tsx @@ -1,6 +1,6 @@ -import {ArrowUpRightFromSquare, Magnifier, Xmark} from '@gravity-ui/icons'; +import {ArrowUpRightFromSquare, ChevronRight, Magnifier, Xmark} from '@gravity-ui/icons'; import {Col, Grid, Row} from '@gravity-ui/page-constructor'; -import {Button, Icon, TextInput} from '@gravity-ui/uikit'; +import {Button, Icon, Sheet, TextInput} from '@gravity-ui/uikit'; import {useTranslation} from 'next-i18next'; import React from 'react'; @@ -13,6 +13,7 @@ import {IconDialog} from './IconDialog/IconDialog'; import './Icons.scss'; import {IconsNotFound} from './IconsNotFound'; import {useImageSearch} from './ImageSearch'; +import {iconCategories, isIconInCategory} from './categories'; import {allIcons} from './constants'; import type {IconItem} from './types'; @@ -29,6 +30,8 @@ export const Icons: React.FC = ({currentIcon, onChangeCurrentIcon}) const isMobile = useIsMobile(); const [filterString, setFilterString] = React.useState(''); + const [categoryId, setCategoryId] = React.useState('all'); + const [isCategorySheetOpen, setIsCategorySheetOpen] = React.useState(false); const [imageSearchResults, setImageSearchResults] = React.useState(null); const [isOpenIconDialog, setIsOpenIconDialog] = React.useState(false); @@ -100,13 +103,15 @@ export const Icons: React.FC = ({currentIcon, onChangeCurrentIcon}) isActive: imageSearchResults !== null, }); - const icons = React.useMemo(() => { + const searchedIcons = React.useMemo(() => { if (imageSearchResults) { const resultSet = new Set(imageSearchResults); const matched = allIcons.filter(({name}) => resultSet.has(name)); // preserve the ranking order from the search results matched.sort( - (a, b) => imageSearchResults.indexOf(a.name) - imageSearchResults.indexOf(b.name), + (first, second) => + imageSearchResults.indexOf(first.name) - + imageSearchResults.indexOf(second.name), ); return matched; } @@ -127,6 +132,68 @@ export const Icons: React.FC = ({currentIcon, onChangeCurrentIcon}) ); }, [filterString, imageSearchResults]); + const categoryCounts = React.useMemo( + () => + Object.fromEntries( + iconCategories.map((category) => [ + category.id, + allIcons.filter((icon) => isIconInCategory(icon, category.id)).length, + ]), + ), + [], + ); + + const isSearching = Boolean(filterString) || imageSearch.isActive; + + const icons = React.useMemo( + () => + isSearching || categoryId === 'all' + ? searchedIcons + : searchedIcons.filter((icon) => isIconInCategory(icon, categoryId)), + [categoryId, isSearching, searchedIcons], + ); + + const selectedCategory = iconCategories.find(({id}) => id === categoryId); + const resultsTitle = isSearching ? 'All icons' : selectedCategory?.label ?? 'All icons'; + const resultsCount = isSearching ? allIcons.length : icons.length; + + const handleSelectCategory = React.useCallback((nextCategoryId: string) => { + setCategoryId(nextCategoryId); + setIsCategorySheetOpen(false); + }, []); + + const categoryOptions = ( + + + {iconCategories.map((category) => ( + + ))} + + ); + const searchStartContent = imageSearch.isActive ? ( imageSearch.startContent ) : ( @@ -195,11 +262,37 @@ export const Icons: React.FC = ({currentIcon, onChangeCurrentIcon}) - {icons.length ? ( - - ) : ( - - )} +
+ + +
+
+

{resultsTitle}

+ {resultsCount} +
+ {icons.length ? ( + + ) : ( + + )} +
+
@@ -210,6 +303,20 @@ export const Icons: React.FC = ({currentIcon, onChangeCurrentIcon}) onClickToKeyword={handleClickToKeyword} /> + {isMobile && ( + setIsCategorySheetOpen(false)} + title="Category" + > +
+ {categoryOptions} +
+
+ )} + {imageSearch.dropOverlay} ); diff --git a/src/components/Icons/categories.ts b/src/components/Icons/categories.ts new file mode 100644 index 000000000000..41f9d0a9a58f --- /dev/null +++ b/src/components/Icons/categories.ts @@ -0,0 +1,34 @@ +import type {IconCategory, IconItem} from './types'; + +export const iconCategories: IconCategory[] = [ + {id: 'arrows', label: 'Arrows'}, + {id: 'layout', label: 'Layout'}, + {id: 'text', label: 'Text'}, + {id: 'status', label: 'Status'}, + {id: 'files', label: 'Files'}, + {id: 'shapes', label: 'Shapes'}, + {id: 'development', label: 'Development'}, + {id: 'editor', label: 'Editor'}, + {id: 'people', label: 'People'}, + {id: 'media', label: 'Media'}, + {id: 'brands', label: 'Brands'}, + {id: 'charts', label: 'Charts'}, + {id: 'commerce', label: 'Commerce'}, + {id: 'communication', label: 'Communication'}, + {id: 'games', label: 'Games'}, + {id: 'devices', label: 'Devices'}, + {id: 'maps', label: 'Maps'}, + {id: 'tools', label: 'Tools'}, + {id: 'math', label: 'Math'}, + {id: 'security', label: 'Security'}, + {id: 'cloud', label: 'Cloud'}, + {id: 'finance', label: 'Finance'}, + {id: 'health', label: 'Health'}, + {id: 'transport', label: 'Transport'}, + {id: 'weather', label: 'Weather'}, + {id: 'time', label: 'Time'}, + {id: 'food', label: 'Food'}, +]; + +export const isIconInCategory = ({meta}: IconItem, categoryId: string) => + meta.categories.includes(categoryId); diff --git a/src/components/Icons/types.ts b/src/components/Icons/types.ts index 4f3e4724eeb3..dcf6927bec05 100644 --- a/src/components/Icons/types.ts +++ b/src/components/Icons/types.ts @@ -6,6 +6,7 @@ export type IconMeta = { svgName: string; componentName: string; keywords: string[]; + categories: string[]; }; export type IconItem = { @@ -13,3 +14,8 @@ export type IconItem = { data: IconProps['data']; meta: IconMeta; }; + +export type IconCategory = { + id: string; + label: string; +}; From 2cc8d82b6957f0813c2ff7af21345cc2150755f3 Mon Sep 17 00:00:00 2001 From: Vladimir Korotaev Date: Thu, 27 Aug 2026 08:57:33 +0300 Subject: [PATCH 2/2] fix(icons): localize category labels --- public/locales/de/icons.json | 37 ++++++++++++++++++-- public/locales/en/icons.json | 37 ++++++++++++++++++-- public/locales/es/icons.json | 37 ++++++++++++++++++-- public/locales/fr/icons.json | 37 ++++++++++++++++++-- public/locales/ja/icons.json | 37 ++++++++++++++++++-- public/locales/ko/icons.json | 37 ++++++++++++++++++-- public/locales/pt/icons.json | 37 ++++++++++++++++++-- public/locales/ru/icons.json | 37 ++++++++++++++++++-- public/locales/zh/icons.json | 37 ++++++++++++++++++-- src/components/Icons/Icons.tsx | 21 ++++++++---- src/components/Icons/categories.ts | 54 +++++++++++++++--------------- src/components/Icons/types.ts | 1 - 12 files changed, 356 insertions(+), 53 deletions(-) diff --git a/public/locales/de/icons.json b/public/locales/de/icons.json index 006d84ff9e6c..012e15046c9f 100644 --- a/public/locales/de/icons.json +++ b/public/locales/de/icons.json @@ -15,5 +15,38 @@ "usage_reactComponent": "React-Komponente", "usage_svg": "SVG", "imageSearch_tooltip": "Nach Bild suchen (oder aus der Zwischenablage einfügen)", - "imageSearch_drop": "Bild hierher ziehen, um ähnliche Icons zu suchen" -} \ No newline at end of file + "imageSearch_drop": "Bild hierher ziehen, um ähnliche Icons zu suchen", + "category": "Kategorie", + "allIcons": "Alle Icons", + "categoriesLabel": "Icon-Kategorien", + "mobileCategoriesLabel": "Mobile Icon-Kategorien", + "categories": { + "arrows": "Pfeile", + "layout": "Layout", + "text": "Text", + "status": "Status", + "files": "Dateien", + "shapes": "Formen", + "development": "Entwicklung", + "editor": "Editor", + "people": "Personen", + "media": "Medien", + "brands": "Marken", + "charts": "Diagramme", + "commerce": "Handel", + "communication": "Kommunikation", + "games": "Spiele", + "devices": "Geräte", + "maps": "Karten", + "tools": "Werkzeuge", + "math": "Mathematik", + "security": "Sicherheit", + "cloud": "Cloud", + "finance": "Finanzen", + "health": "Gesundheit", + "transport": "Transport", + "weather": "Wetter", + "time": "Zeit", + "food": "Essen" + } +} diff --git a/public/locales/en/icons.json b/public/locales/en/icons.json index 8c5f9144d5f7..d5efc2d584e0 100644 --- a/public/locales/en/icons.json +++ b/public/locales/en/icons.json @@ -15,5 +15,38 @@ "usage_reactComponent": "React component", "usage_svg": "SVG", "imageSearch_tooltip": "Search by image (or paste from clipboard)", - "imageSearch_drop": "Drop image to search for similar icons" -} \ No newline at end of file + "imageSearch_drop": "Drop image to search for similar icons", + "category": "Category", + "allIcons": "All icons", + "categoriesLabel": "Icon categories", + "mobileCategoriesLabel": "Mobile icon categories", + "categories": { + "arrows": "Arrows", + "layout": "Layout", + "text": "Text", + "status": "Status", + "files": "Files", + "shapes": "Shapes", + "development": "Development", + "editor": "Editor", + "people": "People", + "media": "Media", + "brands": "Brands", + "charts": "Charts", + "commerce": "Commerce", + "communication": "Communication", + "games": "Games", + "devices": "Devices", + "maps": "Maps", + "tools": "Tools", + "math": "Math", + "security": "Security", + "cloud": "Cloud", + "finance": "Finance", + "health": "Health", + "transport": "Transport", + "weather": "Weather", + "time": "Time", + "food": "Food" + } +} diff --git a/public/locales/es/icons.json b/public/locales/es/icons.json index 0ab037cb357f..2cca0767baaf 100644 --- a/public/locales/es/icons.json +++ b/public/locales/es/icons.json @@ -15,5 +15,38 @@ "usage_reactComponent": "Componente React", "usage_svg": "SVG", "imageSearch_tooltip": "Buscar por imagen (o pegar desde el portapapeles)", - "imageSearch_drop": "Arrastra una imagen para buscar iconos similares" -} \ No newline at end of file + "imageSearch_drop": "Arrastra una imagen para buscar iconos similares", + "category": "Categoría", + "allIcons": "Todos los iconos", + "categoriesLabel": "Categorías de iconos", + "mobileCategoriesLabel": "Categorías de iconos para móviles", + "categories": { + "arrows": "Flechas", + "layout": "Diseño", + "text": "Texto", + "status": "Estado", + "files": "Archivos", + "shapes": "Formas", + "development": "Desarrollo", + "editor": "Editor", + "people": "Personas", + "media": "Multimedia", + "brands": "Marcas", + "charts": "Gráficos", + "commerce": "Comercio", + "communication": "Comunicación", + "games": "Juegos", + "devices": "Dispositivos", + "maps": "Mapas", + "tools": "Herramientas", + "math": "Matemáticas", + "security": "Seguridad", + "cloud": "Nube", + "finance": "Finanzas", + "health": "Salud", + "transport": "Transporte", + "weather": "Clima", + "time": "Tiempo", + "food": "Comida" + } +} diff --git a/public/locales/fr/icons.json b/public/locales/fr/icons.json index f66cdc4be5e4..49c085064a9e 100644 --- a/public/locales/fr/icons.json +++ b/public/locales/fr/icons.json @@ -15,5 +15,38 @@ "usage_reactComponent": "Composant React", "usage_svg": "SVG", "imageSearch_tooltip": "Rechercher par image (ou coller depuis le presse-papiers)", - "imageSearch_drop": "Déposer une image pour rechercher des icônes similaires" -} \ No newline at end of file + "imageSearch_drop": "Déposer une image pour rechercher des icônes similaires", + "category": "Catégorie", + "allIcons": "Toutes les icônes", + "categoriesLabel": "Catégories d’icônes", + "mobileCategoriesLabel": "Catégories d’icônes sur mobile", + "categories": { + "arrows": "Flèches", + "layout": "Mise en page", + "text": "Texte", + "status": "Statut", + "files": "Fichiers", + "shapes": "Formes", + "development": "Développement", + "editor": "Éditeur", + "people": "Personnes", + "media": "Médias", + "brands": "Marques", + "charts": "Graphiques", + "commerce": "Commerce", + "communication": "Communication", + "games": "Jeux", + "devices": "Appareils", + "maps": "Cartes", + "tools": "Outils", + "math": "Mathématiques", + "security": "Sécurité", + "cloud": "Cloud", + "finance": "Finance", + "health": "Santé", + "transport": "Transport", + "weather": "Météo", + "time": "Temps", + "food": "Alimentation" + } +} diff --git a/public/locales/ja/icons.json b/public/locales/ja/icons.json index 4d8548148906..5afc5992bc52 100644 --- a/public/locales/ja/icons.json +++ b/public/locales/ja/icons.json @@ -15,5 +15,38 @@ "usage_reactComponent": "Reactコンポーネント", "usage_svg": "SVG", "imageSearch_tooltip": "画像で検索(またはクリップボードから貼り付け)", - "imageSearch_drop": "画像をドロップして類似アイコンを検索" -} \ No newline at end of file + "imageSearch_drop": "画像をドロップして類似アイコンを検索", + "category": "カテゴリー", + "allIcons": "すべてのアイコン", + "categoriesLabel": "アイコンのカテゴリー", + "mobileCategoriesLabel": "モバイル用アイコンのカテゴリー", + "categories": { + "arrows": "矢印", + "layout": "レイアウト", + "text": "テキスト", + "status": "ステータス", + "files": "ファイル", + "shapes": "図形", + "development": "開発", + "editor": "エディター", + "people": "人物", + "media": "メディア", + "brands": "ブランド", + "charts": "チャート", + "commerce": "コマース", + "communication": "コミュニケーション", + "games": "ゲーム", + "devices": "デバイス", + "maps": "地図", + "tools": "ツール", + "math": "数学", + "security": "セキュリティ", + "cloud": "クラウド", + "finance": "金融", + "health": "健康", + "transport": "交通", + "weather": "天気", + "time": "時間", + "food": "食べ物" + } +} diff --git a/public/locales/ko/icons.json b/public/locales/ko/icons.json index 97348a1b7d22..41504050cb16 100644 --- a/public/locales/ko/icons.json +++ b/public/locales/ko/icons.json @@ -15,5 +15,38 @@ "usage_reactComponent": "React 컴포넌트", "usage_svg": "SVG", "imageSearch_tooltip": "이미지로 검색 (또는 클립보드에서 붙여넣기)", - "imageSearch_drop": "이미지를 드롭하여 유사한 아이콘 검색" -} \ No newline at end of file + "imageSearch_drop": "이미지를 드롭하여 유사한 아이콘 검색", + "category": "카테고리", + "allIcons": "모든 아이콘", + "categoriesLabel": "아이콘 카테고리", + "mobileCategoriesLabel": "모바일 아이콘 카테고리", + "categories": { + "arrows": "화살표", + "layout": "레이아웃", + "text": "텍스트", + "status": "상태", + "files": "파일", + "shapes": "도형", + "development": "개발", + "editor": "편집기", + "people": "사람", + "media": "미디어", + "brands": "브랜드", + "charts": "차트", + "commerce": "상거래", + "communication": "커뮤니케이션", + "games": "게임", + "devices": "기기", + "maps": "지도", + "tools": "도구", + "math": "수학", + "security": "보안", + "cloud": "클라우드", + "finance": "금융", + "health": "건강", + "transport": "교통", + "weather": "날씨", + "time": "시간", + "food": "음식" + } +} diff --git a/public/locales/pt/icons.json b/public/locales/pt/icons.json index 459cebdbc39f..405defda4562 100644 --- a/public/locales/pt/icons.json +++ b/public/locales/pt/icons.json @@ -15,5 +15,38 @@ "usage_reactComponent": "Componente React", "usage_svg": "SVG", "imageSearch_tooltip": "Pesquisar por imagem (ou colar da área de transferência)", - "imageSearch_drop": "Solte a imagem para pesquisar ícones semelhantes" -} \ No newline at end of file + "imageSearch_drop": "Solte a imagem para pesquisar ícones semelhantes", + "category": "Categoria", + "allIcons": "Todos os ícones", + "categoriesLabel": "Categorias de ícones", + "mobileCategoriesLabel": "Categorias de ícones para dispositivos móveis", + "categories": { + "arrows": "Setas", + "layout": "Layout", + "text": "Texto", + "status": "Status", + "files": "Arquivos", + "shapes": "Formas", + "development": "Desenvolvimento", + "editor": "Editor", + "people": "Pessoas", + "media": "Mídia", + "brands": "Marcas", + "charts": "Gráficos", + "commerce": "Comércio", + "communication": "Comunicação", + "games": "Jogos", + "devices": "Dispositivos", + "maps": "Mapas", + "tools": "Ferramentas", + "math": "Matemática", + "security": "Segurança", + "cloud": "Nuvem", + "finance": "Finanças", + "health": "Saúde", + "transport": "Transporte", + "weather": "Clima", + "time": "Tempo", + "food": "Comida" + } +} diff --git a/public/locales/ru/icons.json b/public/locales/ru/icons.json index 321233726d38..19fd247c790c 100644 --- a/public/locales/ru/icons.json +++ b/public/locales/ru/icons.json @@ -15,5 +15,38 @@ "usage_reactComponent": "React-компонент", "usage_svg": "SVG", "imageSearch_tooltip": "Поиск по изображению (или вставьте из буфера обмена)", - "imageSearch_drop": "Перетащите изображение для поиска похожих иконок" -} \ No newline at end of file + "imageSearch_drop": "Перетащите изображение для поиска похожих иконок", + "category": "Категория", + "allIcons": "Все иконки", + "categoriesLabel": "Категории иконок", + "mobileCategoriesLabel": "Категории иконок для мобильных устройств", + "categories": { + "arrows": "Стрелки", + "layout": "Макет", + "text": "Текст", + "status": "Статус", + "files": "Файлы", + "shapes": "Фигуры", + "development": "Разработка", + "editor": "Редактор", + "people": "Люди", + "media": "Медиа", + "brands": "Бренды", + "charts": "Диаграммы", + "commerce": "Коммерция", + "communication": "Общение", + "games": "Игры", + "devices": "Устройства", + "maps": "Карты", + "tools": "Инструменты", + "math": "Математика", + "security": "Безопасность", + "cloud": "Облако", + "finance": "Финансы", + "health": "Здоровье", + "transport": "Транспорт", + "weather": "Погода", + "time": "Время", + "food": "Еда" + } +} diff --git a/public/locales/zh/icons.json b/public/locales/zh/icons.json index 6b521da94a0a..b88a12a652d5 100644 --- a/public/locales/zh/icons.json +++ b/public/locales/zh/icons.json @@ -15,5 +15,38 @@ "usage_reactComponent": "React 组件", "usage_svg": "SVG", "imageSearch_tooltip": "按图片搜索(或粘贴剪贴板内容)", - "imageSearch_drop": "拖放图片以搜索相似图标" -} \ No newline at end of file + "imageSearch_drop": "拖放图片以搜索相似图标", + "category": "类别", + "allIcons": "所有图标", + "categoriesLabel": "图标类别", + "mobileCategoriesLabel": "移动端图标类别", + "categories": { + "arrows": "箭头", + "layout": "布局", + "text": "文本", + "status": "状态", + "files": "文件", + "shapes": "形状", + "development": "开发", + "editor": "编辑器", + "people": "人物", + "media": "媒体", + "brands": "品牌", + "charts": "图表", + "commerce": "商业", + "communication": "通信", + "games": "游戏", + "devices": "设备", + "maps": "地图", + "tools": "工具", + "math": "数学", + "security": "安全", + "cloud": "云", + "finance": "金融", + "health": "健康", + "transport": "交通", + "weather": "天气", + "time": "时间", + "food": "食物" + } +} diff --git a/src/components/Icons/Icons.tsx b/src/components/Icons/Icons.tsx index 87c3fc080578..de930ab577b2 100644 --- a/src/components/Icons/Icons.tsx +++ b/src/components/Icons/Icons.tsx @@ -154,7 +154,11 @@ export const Icons: React.FC = ({currentIcon, onChangeCurrentIcon}) ); const selectedCategory = iconCategories.find(({id}) => id === categoryId); - const resultsTitle = isSearching ? 'All icons' : selectedCategory?.label ?? 'All icons'; + const allIconsTitle = t('icons:allIcons'); + const resultsTitle = + !isSearching && selectedCategory + ? t(`icons:categories.${selectedCategory.id}`) + : allIconsTitle; const resultsCount = isSearching ? allIcons.length : icons.length; const handleSelectCategory = React.useCallback((nextCategoryId: string) => { @@ -173,7 +177,7 @@ export const Icons: React.FC = ({currentIcon, onChangeCurrentIcon}) })} onClick={() => handleSelectCategory('all')} > - All icons + {allIconsTitle} {allIcons.length} {iconCategories.map((category) => ( @@ -187,7 +191,7 @@ export const Icons: React.FC = ({currentIcon, onChangeCurrentIcon}) })} onClick={() => handleSelectCategory(category.id)} > - {category.label} + {t(`icons:categories.${category.id}`)} {categoryCounts[category.id]} ))} @@ -263,8 +267,8 @@ export const Icons: React.FC = ({currentIcon, onChangeCurrentIcon})
-