tot-ui-kit 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # tot-ui-kit
2
2
 
3
- UI-библиотека с `Layout`, `ScMainMenu` и поддержкой тем для React-приложений.
3
+ UI-библиотека с `Layout`, `ScMainMenu` и поддержкой светлой/тёмной темы для React-приложений.
4
4
 
5
- > **Важно**: Библиотека использует обычный CSS (без CSS Modules). В проектах на webpack убедитесь, что подключены `css-loader` и `style-loader` (или `mini-css-extract-plugin` для продакшена). В Vite всё работает из коробки.
5
+ > **Важно**: Библиотека использует обычный CSS (без CSS Modules). В проектах на webpack убедитесь, что подключены `css-loader` и `style-loader`. В Vite всё работает из коробки.
6
6
 
7
7
  ## Установка
8
8
 
@@ -12,33 +12,27 @@ npm install tot-ui-kit @sberbusiness/triplex-next @sberbusiness/icons-next
12
12
 
13
13
  ## ⚠️ Критически важно: Подключение CSS
14
14
 
15
- **Порядок и состав CSS импортов критичен для корректной работы!**
15
+ **Порядок CSS импортов критичен для корректной работы тем!**
16
16
 
17
- В входном файле приложения (`src/main.tsx`) импорты CSS должны быть:
18
- 1. **В начале файла** (до импорта React и компонентов)
19
- 2. **В строго определённом порядке**
17
+ В входном файле приложения (`src/main.tsx`):
20
18
 
21
19
  ```tsx
22
20
  // src/main.tsx
23
21
 
24
22
  // 1. CSS импорты — ПЕРВЫМИ и в этом порядке!
25
- import '@sberbusiness/icons-next/styles/icons.css'
26
- import '@sberbusiness/triplex-next/styles/triplex-next.css'
27
- import 'tot-ui-kit/global.css'
28
- import 'tot-ui-kit/dist/index.css' // Обязательно! Без этого меню не отображается
29
- import './styles/index.css' // ваши локальные стили последними
23
+ import '@sberbusiness/icons-next/styles/icons.css' // Стили иконок
24
+ import '@sberbusiness/triplex-next/styles/triplex-next.css' // Triplex базовые стили
25
+ import 'tot-ui-kit/dist/index.css' // Стили Layout + меню + темы (включает global.css)
26
+ import './styles/index.css' // Ваши локальные стили последними
30
27
 
31
28
  // 2. Только потом React и компоненты
32
29
  import { StrictMode } from 'react'
33
30
  import { createRoot } from 'react-dom/client'
34
- import { BrowserRouter } from 'react-router-dom'
35
31
  import App from './App'
36
32
 
37
33
  createRoot(document.getElementById('root')!).render(
38
34
  <StrictMode>
39
- <BrowserRouter>
40
- <App />
41
- </BrowserRouter>
35
+ <App />
42
36
  </StrictMode>,
43
37
  )
44
38
  ```
@@ -47,21 +41,19 @@ createRoot(document.getElementById('root')!).render(
47
41
 
48
42
  | Проблема | Симптом | Решение |
49
43
  |----------|---------|---------|
50
- | Отсутствует `tot-ui-kit/dist/index.css` | Меню отображается как текст без стилей, иконки в ряд сверху | Добавить импорт `import 'tot-ui-kit/dist/index.css'` |
51
- | Неправильный порядок CSS | Стили перебиваются, меню выглядит сломанным | Соблюдать порядок: icons → triplex → tot-ui-kit → локальные |
52
- | CSS после React импортов | Стили могут не применяться | CSS импорты должны быть в самом начале файла |
44
+ | Отсутствует `tot-ui-kit/dist/index.css` | Меню без стилей, тема не работает | Добавить импорт |
45
+ | Неправильный порядок CSS | Стили перебиваются | icons → triplex → tot-ui-kit → локальные |
46
+ | CSS после React импортов | Стили могут не применяться | CSS импорты в самом начале файла |
53
47
 
54
48
  ## Быстрый старт
55
49
 
56
50
  ```tsx
57
51
  import { Layout } from 'tot-ui-kit'
58
52
 
59
- const API_BASE = import.meta.env.VITE_API_BASE ?? 'http://localhost:4000'
60
-
61
53
  export const App = () => (
62
54
  <Layout
63
55
  menuProps={{
64
- baseUrl: API_BASE,
56
+ baseUrl: 'http://localhost:4000',
65
57
  menuId: '<your-menu-id>',
66
58
  activeAppId: 'my-app',
67
59
  systemTitle: 'Моё приложение',
@@ -72,136 +64,108 @@ export const App = () => (
72
64
  )
73
65
  ```
74
66
 
75
- ## Основные пропсы
76
-
77
- ### Layout
78
-
79
- | Проп | Описание |
80
- |------|----------|
81
- | `menuProps` | Пропсы для `ScMainMenu` (кроме `theme`/`layout`) |
82
- | `initialMenuLayout` | Начальное состояние меню: `'full'` или `'compact'` |
83
- | `initialTheme` | Начальная тема: `'light'` или `'dark'` |
84
- | `headerTitle`, `headerSubtitle` | Заголовок и подзаголовок в шапке |
85
- | `upperMenuSlot`, `pageLabelSlot` | Кастомные слоты для шапки |
86
- | `footerLeft`, `footerRight` | Контент футера |
87
-
88
- ### ScMainMenu
89
-
90
- | Проп | Описание |
91
- |------|----------|
92
- | `baseUrl` | Базовый URL API (формирует `${baseUrl}/idp/single-menu-data/${menuId}`) |
93
- | `menuId` | ID меню для загрузки данных |
94
- | `dataUrl` | Полный URL для загрузки (альтернатива `baseUrl` + `menuId`) |
95
- | `apps` | Готовый список приложений (вместо загрузки) |
96
- | `activeAppId` | ID активного приложения |
97
- | `useMockData` | Использовать встроенные mock-данные |
98
- | `iconResolver` | Кастомная функция для построения `AppDescriptor` |
99
- | `onLayoutChange` | Callback при переключении layout |
100
- | `onThemeChange` | Callback при переключении темы |
101
-
102
67
  ## Темы: светлая и тёмная
103
68
 
104
- ### Как работает переключение темы
69
+ ### Как это работает
105
70
 
106
- 1. **Layout** управляет темой автоматически:
107
- - Устанавливает `data-theme="light"` или `data-theme="dark"` на `<html>`
108
- - Добавляет классы `triplex-theme-light` / `triplex-theme-dark`
109
- - Сохраняет выбор в `localStorage`
110
- - Кнопка переключения встроена в меню
71
+ Layout автоматически управляет темой:
111
72
 
112
- 2. **CSS-переменные** определены в `global.css`:
113
- - Светлая тема значения по умолчанию
114
- - Тёмная темапереопределения в `html[data-theme='dark']`
73
+ 1. **Triplex ThemeProvider** — инжектит CSS-переменные для всех Triplex-компонентов (Button, TextField, Select, Tabs и т.д.)
74
+ 2. **CSS-переменные**дополнительные переопределения в `global.css`
75
+ 3. **CSS-хак для иконок** принудительное переопределение цветов SVG из `@sberbusiness/icons-next`
115
76
 
116
- 3. **Triplex компоненты** используют CSS-переменные вида `--triplex-next-*`
77
+ При смене темы Layout:
78
+ - Устанавливает `data-theme="light"` / `data-theme="dark"` на `<html>`
79
+ - Добавляет классы `triplex-theme-light` / `triplex-theme-dark`
80
+ - Переключает `ThemeProvider` из triplex-next
81
+ - Сохраняет выбор в `localStorage`
117
82
 
118
- ### Использование темы в коде
83
+ **Кнопка переключения** встроена в боковое меню (иконка солнца/луны).
84
+
85
+ ### Использование в коде
119
86
 
120
87
  ```tsx
121
88
  import { Layout, useTheme, getCurrentTheme } from 'tot-ui-kit'
122
89
 
123
- // Хук — автоматически обновляется при смене темы
90
+ // Хук — реактивно обновляется при смене темы
124
91
  const theme = useTheme() // 'light' | 'dark'
125
92
 
126
93
  // Функция — получить текущую тему синхронно
127
94
  const currentTheme = getCurrentTheme()
128
95
  ```
129
96
 
130
- ### Кастомизация цветов
131
-
132
- Переопределите CSS-переменные в своём CSS **после** импорта `global.css`:
97
+ ### Применение темы к своим компонентам
133
98
 
134
99
  ```css
135
- /* your-styles.css */
136
- html[data-theme='light'] {
137
- /* Ваши цвета для светлой темы */
138
- --triplex-next-Typography-Primary_Color-1-14-0: #333;
139
- --triplex-next-ColorNeutral-90-1-14-0: #f0f0f0;
100
+ /* Используйте CSS-переменные из Triplex */
101
+ .my-card {
102
+ background: var(--triplex-next-Card-Static_General_Background-1-14-0);
103
+ color: var(--triplex-next-Typography-Primary_Color-1-14-0);
140
104
  }
141
105
 
142
- html[data-theme='dark'] {
143
- /* Ваши цвета для тёмной темы */
144
- --triplex-next-Typography-Primary_Color-1-14-0: #eee;
145
- --triplex-next-ColorNeutral-90-1-14-0: #1a1a1a;
106
+ /* Или через data-theme */
107
+ html[data-theme='dark'] .my-card {
108
+ background: #2d2d30;
146
109
  }
147
110
  ```
148
111
 
149
- ### Кастомизация меню
112
+ ### Поддерживаемые компоненты
150
113
 
151
- Меню использует классы с префиксом `sc-`:
114
+ Тёмная тема работает из коробки для:
115
+ - Typography, Button, Tabs
116
+ - TextField, SelectField, Checkbox, Radio
117
+ - Card, Modal, Dropdown
118
+ - Link, Tag, Divider, Island
119
+ - **Иконки** из `@sberbusiness/icons-next` (крестики, шевроны и т.д.)
152
120
 
153
- ```css
154
- /* Светлая тема меню */
155
- .sc-main-menu_theme_light {
156
- background-color: #your-light-bg;
157
- color: #your-light-text;
158
- }
159
-
160
- /* Тёмная тема меню */
161
- .sc-main-menu_theme_dark {
162
- background-color: #your-dark-bg;
163
- color: #your-dark-text;
164
- }
165
- ```
121
+ > Подробная документация: см. **[DARK-THEME.md](./DARK-THEME.md)**
166
122
 
167
- ### Основные CSS-переменные
123
+ ## Основные пропсы
168
124
 
169
- | Переменная | Назначение |
170
- |------------|------------|
171
- | `--triplex-next-Typography-Primary_Color-*` | Основной цвет текста |
172
- | `--triplex-next-Typography-Secondary_Color-*` | Вторичный цвет текста |
173
- | `--triplex-next-ColorNeutral-90-*` | Фон страницы |
174
- | `--triplex-next-Button-*` | Кнопки |
175
- | `--triplex-next-FormField-*` | Инпуты, селекты |
176
- | `--triplex-next-Card-*` | Карточки |
177
- | `--triplex-next-Dropdown-*` | Выпадающие списки |
125
+ ### Layout
178
126
 
179
- ### Принципы подбора цветов для тёмной темы
127
+ | Проп | Описание |
128
+ |------|----------|
129
+ | `menuProps` | Пропсы для `ScMainMenu` (кроме `theme`/`layout`) |
130
+ | `initialMenuLayout` | Начальное состояние меню: `'full'` или `'compact'` |
131
+ | `initialTheme` | Начальная тема: `'light'` или `'dark'` |
180
132
 
181
- | Элемент | Рекомендация |
182
- |---------|--------------|
183
- | Фон | `rgba(255, 255, 255, 0.05-0.15)` |
184
- | Фон hover | Увеличить opacity на 0.05-0.07 |
185
- | Фон selected | `rgba(255, 255, 255, 0.15-0.2)` |
186
- | Текст primary | `rgba(255, 255, 255, 1)` |
187
- | Текст secondary | `rgba(255, 255, 255, 0.65)` |
188
- | Текст disabled | `rgba(255, 255, 255, 0.35)` |
189
- | Бордеры | `rgba(255, 255, 255, 0.12-0.2)` |
133
+ ### ScMainMenu
190
134
 
191
- > Подробная документация по темам: см. `DARK-THEME.md`
135
+ | Проп | Описание |
136
+ |------|----------|
137
+ | `baseUrl` | Базовый URL API |
138
+ | `menuId` | ID меню для загрузки данных |
139
+ | `activeAppId` | ID активного приложения |
140
+ | `useMockData` | Использовать встроенные mock-данные |
141
+ | `onLayoutChange` | Callback при переключении layout |
142
+ | `onThemeChange` | Callback при переключении темы |
192
143
 
193
144
  ## Peer Dependencies
194
145
 
195
146
  ```json
196
147
  {
197
- "@sberbusiness/triplex-next": "^1.0.0",
198
- "@sberbusiness/icons-next": "^1.0.0",
148
+ "@sberbusiness/triplex-next": "^1.14.0",
149
+ "@sberbusiness/icons-next": "^1.11.0",
199
150
  "react": "^18.0.0",
200
151
  "react-dom": "^18.0.0"
201
152
  }
202
153
  ```
203
154
 
204
- > Рекомендуемые версии: `@sberbusiness/triplex-next@^1.14.0`, `@sberbusiness/icons-next@^1.12.0`
155
+ ## Структура файлов (темы)
156
+
157
+ ```
158
+ tot-ui-kit/
159
+ ├── src/
160
+ │ ├── global.css # CSS-переменные для тёмной темы + хаки для иконок
161
+ │ ├── components/
162
+ │ │ └── Layout/
163
+ │ │ └── Layout.tsx # ThemeProvider + логика переключения
164
+ │ └── theme/
165
+ │ └── index.ts # useTheme, getCurrentTheme
166
+ ├── DARK-THEME.md # Подробная документация по темам
167
+ └── README.md # Этот файл
168
+ ```
205
169
 
206
170
  ## Лицензия
207
171
 
package/dist/index.cjs CHANGED
@@ -125,6 +125,7 @@ __export(index_exports, {
125
125
  module.exports = __toCommonJS(index_exports);
126
126
 
127
127
  // src/components/Layout/Layout.tsx
128
+ var import_triplex_next = require("@sberbusiness/triplex-next");
128
129
  var import_react2 = require("react");
129
130
 
130
131
  // src/components/MainMenu/ScMainMenu.tsx
@@ -1091,6 +1092,10 @@ var Layout = ({
1091
1092
  root.classList.add(
1092
1093
  theme === "dark" ? "triplex-theme-dark" : "triplex-theme-light"
1093
1094
  );
1095
+ root.classList.remove("icons-light_tptl2v", "icons-dark_7mk9a3");
1096
+ root.classList.add(
1097
+ theme === "dark" ? "icons-dark_7mk9a3" : "icons-light_tptl2v"
1098
+ );
1094
1099
  try {
1095
1100
  window.localStorage.setItem(THEME_STORAGE_KEY, theme);
1096
1101
  } catch {
@@ -1110,9 +1115,12 @@ var Layout = ({
1110
1115
  setTheme(next);
1111
1116
  menuProps.onThemeChange?.(next);
1112
1117
  };
1113
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1118
+ const triplexTheme = theme === "dark" ? import_triplex_next.ETriplexNextTheme.DARK : import_triplex_next.ETriplexNextTheme.LIGHT;
1119
+ const scopeRef = (0, import_react2.useRef)(null);
1120
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_triplex_next.ThemeProvider, { theme: triplexTheme, scopeRef, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1114
1121
  "div",
1115
1122
  {
1123
+ ref: scopeRef,
1116
1124
  className: appClassName,
1117
1125
  style: {
1118
1126
  paddingLeft: `${sidebarWidth}px`,
@@ -1134,23 +1142,23 @@ var Layout = ({
1134
1142
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("main", { className: styles2.main, children })
1135
1143
  ]
1136
1144
  }
1137
- );
1145
+ ) });
1138
1146
  };
1139
1147
  var Layout_default = Layout;
1140
1148
 
1141
1149
  // src/components/PageLabel/PageLabel.tsx
1142
- var import_triplex_next = require("@sberbusiness/triplex-next");
1150
+ var import_triplex_next2 = require("@sberbusiness/triplex-next");
1143
1151
  var import_jsx_runtime6 = require("react/jsx-runtime");
1144
1152
  var PageLabel = ({ title, subtitle }) => {
1145
1153
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1146
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_triplex_next.Text, { size: import_triplex_next.ETextSize.B2, type: import_triplex_next.EFontType.PRIMARY, children: title }),
1147
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_triplex_next.Text, { size: import_triplex_next.ETextSize.B2, type: import_triplex_next.EFontType.SECONDARY, children: subtitle })
1154
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_triplex_next2.Text, { size: import_triplex_next2.ETextSize.B2, type: import_triplex_next2.EFontType.PRIMARY, children: title }),
1155
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_triplex_next2.Text, { size: import_triplex_next2.ETextSize.B2, type: import_triplex_next2.EFontType.SECONDARY, children: subtitle })
1148
1156
  ] });
1149
1157
  };
1150
1158
  var PageLabel_default = PageLabel;
1151
1159
 
1152
1160
  // src/components/UpperMenu/UpperMenu.tsx
1153
- var import_triplex_next2 = require("@sberbusiness/triplex-next");
1161
+ var import_triplex_next3 = require("@sberbusiness/triplex-next");
1154
1162
  var import_jsx_runtime7 = require("react/jsx-runtime");
1155
1163
  var styles3 = {
1156
1164
  root: "sc-upper-menu",
@@ -1165,10 +1173,10 @@ var UpperMenu = ({
1165
1173
  }) => {
1166
1174
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: styles3.root, children: [
1167
1175
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: styles3.left, children: [
1168
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_triplex_next2.Text, { size: import_triplex_next2.ETextSize.B2, type: import_triplex_next2.EFontType.PRIMARY, children: title }),
1169
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_triplex_next2.Text, { size: import_triplex_next2.ETextSize.B3, type: import_triplex_next2.EFontType.SECONDARY, children: subtitle })
1176
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_triplex_next3.Text, { size: import_triplex_next3.ETextSize.B2, type: import_triplex_next3.EFontType.PRIMARY, children: title }),
1177
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_triplex_next3.Text, { size: import_triplex_next3.ETextSize.B3, type: import_triplex_next3.EFontType.SECONDARY, children: subtitle })
1170
1178
  ] }),
1171
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: styles3.right, children: rightSlot ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_triplex_next2.Text, { size: import_triplex_next2.ETextSize.B3, type: import_triplex_next2.EFontType.SECONDARY, children: "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C" }) })
1179
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: styles3.right, children: rightSlot ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_triplex_next3.Text, { size: import_triplex_next3.ETextSize.B3, type: import_triplex_next3.EFontType.SECONDARY, children: "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C" }) })
1172
1180
  ] });
1173
1181
  };
1174
1182
  var UpperMenu_default = UpperMenu;
package/dist/index.css CHANGED
@@ -1,3 +1,199 @@
1
+ /* src/global.css */
2
+ html {
3
+ --triplex-next-Typography-Primary_Color-1-14-0: rgba(31, 31, 34, 1);
4
+ --triplex-next-Typography-Complementary_Color-1-14-0: rgba(31, 31, 34, 0.85);
5
+ --triplex-next-Typography-Secondary_Color-1-14-0: rgba(31, 31, 34, 0.65);
6
+ --triplex-next-Typography-Tertiary_Color-1-14-0: rgba(31, 31, 34, 0.55);
7
+ --triplex-next-Typography-Disabled_Color-1-14-0: rgba(31, 31, 34, 0.35);
8
+ --triplex-next-ColorNeutral-90-1-14-0: #f2f4f7;
9
+ --triplex-next-ColorNeutral-100-1-14-0: #ffffff;
10
+ background-color: var(--triplex-next-ColorNeutral-90-1-14-0, #f2f4f7);
11
+ }
12
+ html[data-theme=light] {
13
+ --triplex-next-Typography-Primary_Color-1-14-0: rgba(31, 31, 34, 1);
14
+ --triplex-next-Typography-Complementary_Color-1-14-0: rgba(31, 31, 34, 0.85);
15
+ --triplex-next-Typography-Secondary_Color-1-14-0: rgba(31, 31, 34, 0.65);
16
+ --triplex-next-Typography-Tertiary_Color-1-14-0: rgba(31, 31, 34, 0.55);
17
+ --triplex-next-Typography-Disabled_Color-1-14-0: rgba(31, 31, 34, 0.35);
18
+ --triplex-next-ColorNeutral-90-1-14-0: #f2f4f7;
19
+ --triplex-next-ColorNeutral-100-1-14-0: #ffffff;
20
+ background-color: var(--triplex-next-ColorNeutral-90-1-14-0, #f2f4f7);
21
+ }
22
+ html[data-theme=dark] {
23
+ --triplex-next-Typography-Primary_Color-1-14-0: rgba(255, 255, 255, 1);
24
+ --triplex-next-Typography-Complementary_Color-1-14-0: rgba( 255, 255, 255, 0.85 );
25
+ --triplex-next-Typography-Secondary_Color-1-14-0: rgba(255, 255, 255, 0.65);
26
+ --triplex-next-Typography-Tertiary_Color-1-14-0: rgba(255, 255, 255, 0.55);
27
+ --triplex-next-Typography-Disabled_Color-1-14-0: rgba(255, 255, 255, 0.35);
28
+ --triplex-next-ColorNeutral-90-1-14-0: #1f1f22;
29
+ --triplex-next-ColorNeutral-100-1-14-0: #1f1f22;
30
+ --triplex-next-Tabs-Type1_Background-1-14-0: rgba(255, 255, 255, 0.08);
31
+ --triplex-next-Tabs-Type2_Background-1-14-0: rgba(255, 255, 255, 0.05);
32
+ --triplex-next-Tabs-Type1_Tab_Background_Default-1-14-0: transparent;
33
+ --triplex-next-Tabs-Type2_Tab_Background_Default-1-14-0: transparent;
34
+ --triplex-next-Tabs-Type1_Tab_Background_Selected-1-14-0: rgba(255, 255, 255, 0.15);
35
+ --triplex-next-Tabs-Type2_Tab_Background_Selected-1-14-0: rgba(255, 255, 255, 0.12);
36
+ --triplex-next-Tabs-Type1_Tab_Background_Hover-1-14-0: rgba(255, 255, 255, 0.1);
37
+ --triplex-next-Tabs-Type2_Tab_Background_Hover-1-14-0: rgba(255, 255, 255, 0.08);
38
+ --triplex-next-Tabs-Type1_Tab_Color_Default-1-14-0: rgba(255, 255, 255, 0.65);
39
+ --triplex-next-Tabs-Type2_Tab_Color_Default-1-14-0: rgba(255, 255, 255, 0.65);
40
+ --triplex-next-Tabs-Type1_Tab_Color_Selected-1-14-0: rgba(255, 255, 255, 1);
41
+ --triplex-next-Tabs-Type2_Tab_Color_Selected-1-14-0: rgba(255, 255, 255, 1);
42
+ --triplex-next-Tabs-Type1_Tab_Color_Hover-1-14-0: rgba(255, 255, 255, 1);
43
+ --triplex-next-Tabs-Type2_Tab_Color_Hover-1-14-0: rgba(255, 255, 255, 1);
44
+ --triplex-next-Button-Secondary_Background_Default-1-14-0: rgba(255, 255, 255, 0.08);
45
+ --triplex-next-Button-Secondary_Background_Hover-1-14-0: rgba(255, 255, 255, 0.12);
46
+ --triplex-next-Button-Secondary_Background_Active-1-14-0: rgba(255, 255, 255, 0.15);
47
+ --triplex-next-Button-Secondary_Background_Disabled-1-14-0: rgba(255, 255, 255, 0.05);
48
+ --triplex-next-Button-Secondary_Color_Default-1-14-0: #21A19A;
49
+ --triplex-next-Button-Secondary_Color_Hover-1-14-0: #19BDB0;
50
+ --triplex-next-Button-Secondary_Color_Active-1-14-0: #007777;
51
+ --triplex-next-Button-Secondary_Color_Disabled-1-14-0: rgba(255, 255, 255, 0.35);
52
+ --triplex-next-Button-SecondaryLight_Background_Default-1-14-0: rgba(255, 255, 255, 0.1);
53
+ --triplex-next-Button-SecondaryLight_Background_Hover-1-14-0: rgba(255, 255, 255, 0.15);
54
+ --triplex-next-Button-SecondaryLight_Background_Active-1-14-0: rgba(255, 255, 255, 0.18);
55
+ --triplex-next-Button-SecondaryLight_Background_Disabled-1-14-0: rgba(255, 255, 255, 0.05);
56
+ --triplex-next-Button-SecondaryLight_Color_Default-1-14-0: #21A19A;
57
+ --triplex-next-Button-SecondaryLight_Color_Hover-1-14-0: #19BDB0;
58
+ --triplex-next-Button-SecondaryLight_Color_Active-1-14-0: #007777;
59
+ --triplex-next-Button-SecondaryLight_Color_Disabled-1-14-0: rgba(255, 255, 255, 0.35);
60
+ --triplex-next-Button-General_Background_Disabled-1-14-0: rgba(255, 255, 255, 0.08);
61
+ --triplex-next-Button-General_Color_Disabled-1-14-0: rgba(255, 255, 255, 0.35);
62
+ --triplex-next-Button-Danger_Background_Disabled-1-14-0: rgba(255, 255, 255, 0.08);
63
+ --triplex-next-Button-Danger_Color_Disabled-1-14-0: rgba(255, 255, 255, 0.35);
64
+ --triplex-next-Button-Link_Color_Default-1-14-0: #19BDB0;
65
+ --triplex-next-Button-Link_Color_Hover-1-14-0: #4BD9CF;
66
+ --triplex-next-Button-Link_Color_Active-1-14-0: #008985;
67
+ --triplex-next-Button-Link_Color_Disabled-1-14-0: rgba(255, 255, 255, 0.35);
68
+ --triplex-next-FormField-Background_Default-1-14-0: rgba(255, 255, 255, 0.08);
69
+ --triplex-next-FormField-Background_Hover-1-14-0: rgba(255, 255, 255, 0.12);
70
+ --triplex-next-FormField-Background_Active-1-14-0: rgba(255, 255, 255, 0.08);
71
+ --triplex-next-FormField-Background_Disabled-1-14-0: rgba(255, 255, 255, 0.05);
72
+ --triplex-next-FormField-Background_Error-1-14-0: rgba(230, 0, 55, 0.15);
73
+ --triplex-next-FormField-Background_Error_Hover-1-14-0: rgba(230, 0, 55, 0.2);
74
+ --triplex-next-FormField-Background_Warning-1-14-0: rgba(253, 101, 8, 0.15);
75
+ --triplex-next-FormField-Background_Warning_Hover-1-14-0: rgba(253, 101, 8, 0.2);
76
+ --triplex-next-FormField-Input_Color_Default-1-14-0: rgba(255, 255, 255, 1);
77
+ --triplex-next-FormField-Input_Color_Disabled-1-14-0: rgba(255, 255, 255, 0.35);
78
+ --triplex-next-FormField-Target_Color_Default-1-14-0: rgba(255, 255, 255, 1);
79
+ --triplex-next-FormField-Target_Color_Disabled-1-14-0: rgba(255, 255, 255, 0.45);
80
+ --triplex-next-FormField-Target_PlaceholderColor_Default-1-14-0: rgba(255, 255, 255, 0.65);
81
+ --triplex-next-FormField-Label_Color_Default-1-14-0: rgba(255, 255, 255, 0.65);
82
+ --triplex-next-FormField-Label_Color_Disabled-1-14-0: rgba(255, 255, 255, 0.35);
83
+ --triplex-next-FormField-Placeholder_Color-1-14-0: rgba(255, 255, 255, 0.65);
84
+ --triplex-next-SmallInput-Background-1-14-0: rgba(255, 255, 255, 0.08);
85
+ --triplex-next-SmallInput-Color-1-14-0: rgba(255, 255, 255, 1);
86
+ --triplex-next-SmallInput-PlaceholderColor-1-14-0: rgba(255, 255, 255, 0.65);
87
+ --triplex-next-Dropdown-Background-1-14-0: #2a2d31;
88
+ --triplex-next-Dropdown-Shadow-1-14-0: 0px 2px 12px rgba(0, 0, 0, 0.4);
89
+ --triplex-next-DropdownList-Background_Default-1-14-0: transparent;
90
+ --triplex-next-DropdownList-Background_Active-1-14-0: rgba(255, 255, 255, 0.1);
91
+ --triplex-next-DropdownList-Background_Selected-1-14-0: rgba(255, 255, 255, 0.15);
92
+ --triplex-next-DropdownList-Color-1-14-0: rgba(255, 255, 255, 1);
93
+ --triplex-next-Checkbox-Background_Default-1-14-0: rgba(255, 255, 255, 0.08);
94
+ --triplex-next-Checkbox-Background_Disabled-1-14-0: rgba(255, 255, 255, 0.05);
95
+ --triplex-next-Checkbox-Background_Checked_Disabled-1-14-0: rgba(255, 255, 255, 0.1);
96
+ --triplex-next-Checkbox-BorderColor_Default-1-14-0: 0 0 0 1px rgba(255, 255, 255, 0.25) inset;
97
+ --triplex-next-Checkbox-BorderColor_Disabled-1-14-0: 0 0 0 1px rgba(255, 255, 255, 0.1) inset;
98
+ --triplex-next-Checkbox-Checkmark_Fill_Disabled-1-14-0: rgba(255, 255, 255, 0.35);
99
+ --triplex-next-Radio-Background_Default-1-14-0: rgba(255, 255, 255, 0.08);
100
+ --triplex-next-Radio-Background_Disabled-1-14-0: rgba(255, 255, 255, 0.05);
101
+ --triplex-next-Radio-Background_Checked_Disabled-1-14-0: rgba(255, 255, 255, 0.1);
102
+ --triplex-next-Radio-BorderColor_Default-1-14-0: 0 0 0 1px rgba(255, 255, 255, 0.25) inset;
103
+ --triplex-next-Radio-BorderColor_Disabled-1-14-0: 0 0 0 1px rgba(255, 255, 255, 0.1) inset;
104
+ --triplex-next-Radio-Dot_Disabled-1-14-0: rgba(255, 255, 255, 0.35);
105
+ --triplex-next-Card-Static_General_Background-1-14-0: rgba(255, 255, 255, 0.08);
106
+ --triplex-next-Card-Static_Secondary_Background-1-14-0: rgba(255, 255, 255, 0.05);
107
+ --triplex-next-Card-Action_General_Background-1-14-0: rgba(255, 255, 255, 0.08);
108
+ --triplex-next-Card-Action_General_Background_Hover-1-14-0: rgba(255, 255, 255, 0.1);
109
+ --triplex-next-Card-Action_General_Background_Selected-1-14-0: rgba(255, 255, 255, 0.12);
110
+ --triplex-next-Card-Action_General_Background_Selected_Hover-1-14-0: rgba(255, 255, 255, 0.15);
111
+ --triplex-next-Card-Action_Secondary_Background-1-14-0: rgba(255, 255, 255, 0.05);
112
+ --triplex-next-Card-Action_Secondary_Background_Hover-1-14-0: rgba(255, 255, 255, 0.08);
113
+ --triplex-next-Card-Action_Secondary_Background_Selected-1-14-0: rgba(255, 255, 255, 0.1);
114
+ --triplex-next-Card-Action_Secondary_Background_Selected_Hover-1-14-0: rgba(255, 255, 255, 0.12);
115
+ --triplex-next-Card-Shadow_Default-1-14-0: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
116
+ --triplex-next-Card-Shadow_Hover-1-14-0: 0 4px 16px 0 rgba(0, 0, 0, 0.4);
117
+ --triplex-next-ModalWindow-Background-1-14-0: #2a2d31;
118
+ --triplex-next-ModalWindow-Backdrop_Background-1-14-0: rgba(0, 0, 0, 0.6);
119
+ --triplex-next-Island-Type1_Background-1-14-0: rgba(255, 255, 255, 0.08);
120
+ --triplex-next-Island-Type2_Background-1-14-0: rgba(255, 255, 255, 0.05);
121
+ --triplex-next-Island-Type3_Background-1-14-0: rgba(255, 255, 255, 0.03);
122
+ --triplex-next-Island-Type2_Shadow-1-14-0: 0 0 0 1px rgba(255, 255, 255, 0.1) inset;
123
+ --triplex-next-ListItem-Background-1-14-0: rgba(255, 255, 255, 0.08);
124
+ --triplex-next-ListItem-Background_Dragging-1-14-0: rgba(255, 255, 255, 0.12);
125
+ --triplex-next-ListItem-Background_Selected-1-14-0: rgba(255, 255, 255, 0.15);
126
+ --triplex-next-ListItem-Shadow-1-14-0: 0 2px 8px rgba(0, 0, 0, 0.4);
127
+ --triplex-next-ListItemControlsButton-Background_Default-1-14-0: transparent;
128
+ --triplex-next-ListItemControlsButton-Background_Hover-1-14-0: rgba(255, 255, 255, 0.1);
129
+ --triplex-next-ListItemControlsButton-Background_Active-1-14-0: rgba(255, 255, 255, 0.15);
130
+ --triplex-next-ListItemControlsButton-Color_Default-1-14-0: rgba(255, 255, 255, 0.65);
131
+ --triplex-next-ListItemControlsButton-Color_Hover-1-14-0: rgba(255, 255, 255, 0.85);
132
+ --triplex-next-ListItemControlsButton-Color_Active-1-14-0: rgba(255, 255, 255, 1);
133
+ --triplex-next-Divider-Background-1-14-0: rgba(255, 255, 255, 0.12);
134
+ --triplex-next-Link-Text_Color_Default-1-14-0: #19BDB0;
135
+ --triplex-next-Link-Text_Color_Hover-1-14-0: #4BD9CF;
136
+ --triplex-next-Link-Text_Color_Active-1-14-0: #008985;
137
+ --triplex-next-Tag-Background-1-14-0: rgba(255, 255, 255, 0.12);
138
+ --triplex-next-MultiselectField-Divider_Color-1-14-0: rgba(255, 255, 255, 0.2);
139
+ background-color: var(--triplex-next-ColorNeutral-90-1-14-0, #1f1f22);
140
+ }
141
+ *,
142
+ *::before,
143
+ *::after {
144
+ box-sizing: border-box;
145
+ }
146
+ html,
147
+ body {
148
+ margin: 0;
149
+ padding: 0;
150
+ min-height: 100%;
151
+ }
152
+ body {
153
+ font-family:
154
+ system-ui,
155
+ -apple-system,
156
+ BlinkMacSystemFont,
157
+ "Segoe UI",
158
+ sans-serif;
159
+ line-height: 1.5;
160
+ background-color: inherit;
161
+ color: rgb(46, 52, 56);
162
+ background: rgb(246, 249, 252);
163
+ }
164
+ html[data-theme=dark] body {
165
+ color: rgb(201, 205, 207);
166
+ background: rgb(34, 36, 37);
167
+ }
168
+ #root {
169
+ min-height: 100vh;
170
+ }
171
+ a {
172
+ color: inherit;
173
+ text-decoration: none;
174
+ }
175
+ button {
176
+ font-family: inherit;
177
+ }
178
+ html[data-theme=dark] ._505n0h {
179
+ fill: #FFFFFF !important;
180
+ fill-opacity: 0.35 !important;
181
+ }
182
+ html[data-theme=dark] .hoverable:hover ._505n0h {
183
+ fill: #FFFFFF !important;
184
+ fill-opacity: 1 !important;
185
+ }
186
+ html[data-theme=dark] .hoverable:not(:disabled):active ._505n0h,
187
+ html[data-theme=dark] .hoverable.active ._505n0h {
188
+ fill: #FFFFFF !important;
189
+ fill-opacity: 1 !important;
190
+ }
191
+ html[data-theme=dark] .hoverable:disabled ._505n0h,
192
+ html[data-theme=dark] .hoverable.disabled ._505n0h {
193
+ fill: #FFFFFF !important;
194
+ fill-opacity: 0.15 !important;
195
+ }
196
+
1
197
  /* src/components/Layout/styles.css */
2
198
  .sc-layout {
3
199
  height: 100vh;
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/components/Layout/Layout.tsx
2
- import { useEffect as useEffect2, useState as useState2 } from "react";
2
+ import { ThemeProvider, ETriplexNextTheme } from "@sberbusiness/triplex-next";
3
+ import { useEffect as useEffect2, useRef, useState as useState2 } from "react";
3
4
 
4
5
  // src/components/MainMenu/ScMainMenu.tsx
5
6
  import { useEffect, useState } from "react";
@@ -965,6 +966,10 @@ var Layout = ({
965
966
  root.classList.add(
966
967
  theme === "dark" ? "triplex-theme-dark" : "triplex-theme-light"
967
968
  );
969
+ root.classList.remove("icons-light_tptl2v", "icons-dark_7mk9a3");
970
+ root.classList.add(
971
+ theme === "dark" ? "icons-dark_7mk9a3" : "icons-light_tptl2v"
972
+ );
968
973
  try {
969
974
  window.localStorage.setItem(THEME_STORAGE_KEY, theme);
970
975
  } catch {
@@ -984,9 +989,12 @@ var Layout = ({
984
989
  setTheme(next);
985
990
  menuProps.onThemeChange?.(next);
986
991
  };
987
- return /* @__PURE__ */ jsxs3(
992
+ const triplexTheme = theme === "dark" ? ETriplexNextTheme.DARK : ETriplexNextTheme.LIGHT;
993
+ const scopeRef = useRef(null);
994
+ return /* @__PURE__ */ jsx5(ThemeProvider, { theme: triplexTheme, scopeRef, children: /* @__PURE__ */ jsxs3(
988
995
  "div",
989
996
  {
997
+ ref: scopeRef,
990
998
  className: appClassName,
991
999
  style: {
992
1000
  paddingLeft: `${sidebarWidth}px`,
@@ -1008,7 +1016,7 @@ var Layout = ({
1008
1016
  /* @__PURE__ */ jsx5("main", { className: styles2.main, children })
1009
1017
  ]
1010
1018
  }
1011
- );
1019
+ ) });
1012
1020
  };
1013
1021
  var Layout_default = Layout;
1014
1022
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tot-ui-kit",
3
- "version": "2.0.1",
3
+ "version": "2.2.0",
4
4
  "description": "UI Kit with Layout, MainMenu, and theme support for React applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
package/src/global.css CHANGED
@@ -163,6 +163,14 @@ html[data-theme='dark'] {
163
163
  --triplex-next-ListItem-Background_Selected-1-14-0: rgba(255, 255, 255, 0.15);
164
164
  --triplex-next-ListItem-Shadow-1-14-0: 0 2px 8px rgba(0, 0, 0, 0.4);
165
165
 
166
+ /* ===== ListItemControlsButton (иконки: крестик очистки, шеврон и т.д.) ===== */
167
+ --triplex-next-ListItemControlsButton-Background_Default-1-14-0: transparent;
168
+ --triplex-next-ListItemControlsButton-Background_Hover-1-14-0: rgba(255, 255, 255, 0.1);
169
+ --triplex-next-ListItemControlsButton-Background_Active-1-14-0: rgba(255, 255, 255, 0.15);
170
+ --triplex-next-ListItemControlsButton-Color_Default-1-14-0: rgba(255, 255, 255, 0.65);
171
+ --triplex-next-ListItemControlsButton-Color_Hover-1-14-0: rgba(255, 255, 255, 0.85);
172
+ --triplex-next-ListItemControlsButton-Color_Active-1-14-0: rgba(255, 255, 255, 1);
173
+
166
174
  /* ===== Divider ===== */
167
175
  --triplex-next-Divider-Background-1-14-0: rgba(255, 255, 255, 0.12);
168
176
 
@@ -174,6 +182,9 @@ html[data-theme='dark'] {
174
182
  /* ===== Tag ===== */
175
183
  --triplex-next-Tag-Background-1-14-0: rgba(255, 255, 255, 0.12);
176
184
 
185
+ /* ===== MultiselectField ===== */
186
+ --triplex-next-MultiselectField-Divider_Color-1-14-0: rgba(255, 255, 255, 0.2);
187
+
177
188
  background-color: var(--triplex-next-ColorNeutral-90-1-14-0, #1f1f22);
178
189
  }
179
190
 
@@ -218,3 +229,29 @@ a {
218
229
  button {
219
230
  font-family: inherit;
220
231
  }
232
+
233
+ /* ===== Icons-next: переопределение цветов иконок для тёмной темы ===== */
234
+ /* Иконки из @sberbusiness/icons-next используют класс _505n0h для светлой темы (тёмная заливка)
235
+ и _1h7ffvx для тёмной темы (белая заливка). Поскольку Context не работает между
236
+ библиотекой и проектом (разные копии React), принудительно меняем цвета через CSS */
237
+ html[data-theme='dark'] ._505n0h {
238
+ fill: #FFFFFF !important;
239
+ fill-opacity: 0.35 !important;
240
+ }
241
+
242
+ html[data-theme='dark'] .hoverable:hover ._505n0h {
243
+ fill: #FFFFFF !important;
244
+ fill-opacity: 1 !important;
245
+ }
246
+
247
+ html[data-theme='dark'] .hoverable:not(:disabled):active ._505n0h,
248
+ html[data-theme='dark'] .hoverable.active ._505n0h {
249
+ fill: #FFFFFF !important;
250
+ fill-opacity: 1 !important;
251
+ }
252
+
253
+ html[data-theme='dark'] .hoverable:disabled ._505n0h,
254
+ html[data-theme='dark'] .hoverable.disabled ._505n0h {
255
+ fill: #FFFFFF !important;
256
+ fill-opacity: 0.15 !important;
257
+ }