tot-ui-kit 2.0.0 → 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,6 +64,62 @@ export const App = () => (
72
64
  )
73
65
  ```
74
66
 
67
+ ## Темы: светлая и тёмная
68
+
69
+ ### Как это работает
70
+
71
+ Layout автоматически управляет темой:
72
+
73
+ 1. **Triplex ThemeProvider** — инжектит CSS-переменные для всех Triplex-компонентов (Button, TextField, Select, Tabs и т.д.)
74
+ 2. **CSS-переменные** — дополнительные переопределения в `global.css`
75
+ 3. **CSS-хак для иконок** — принудительное переопределение цветов SVG из `@sberbusiness/icons-next`
76
+
77
+ При смене темы Layout:
78
+ - Устанавливает `data-theme="light"` / `data-theme="dark"` на `<html>`
79
+ - Добавляет классы `triplex-theme-light` / `triplex-theme-dark`
80
+ - Переключает `ThemeProvider` из triplex-next
81
+ - Сохраняет выбор в `localStorage`
82
+
83
+ **Кнопка переключения** встроена в боковое меню (иконка солнца/луны).
84
+
85
+ ### Использование в коде
86
+
87
+ ```tsx
88
+ import { Layout, useTheme, getCurrentTheme } from 'tot-ui-kit'
89
+
90
+ // Хук — реактивно обновляется при смене темы
91
+ const theme = useTheme() // 'light' | 'dark'
92
+
93
+ // Функция — получить текущую тему синхронно
94
+ const currentTheme = getCurrentTheme()
95
+ ```
96
+
97
+ ### Применение темы к своим компонентам
98
+
99
+ ```css
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);
104
+ }
105
+
106
+ /* Или через data-theme */
107
+ html[data-theme='dark'] .my-card {
108
+ background: #2d2d30;
109
+ }
110
+ ```
111
+
112
+ ### Поддерживаемые компоненты
113
+
114
+ Тёмная тема работает из коробки для:
115
+ - Typography, Button, Tabs
116
+ - TextField, SelectField, Checkbox, Radio
117
+ - Card, Modal, Dropdown
118
+ - Link, Tag, Divider, Island
119
+ - **Иконки** из `@sberbusiness/icons-next` (крестики, шевроны и т.д.)
120
+
121
+ > Подробная документация: см. **[DARK-THEME.md](./DARK-THEME.md)**
122
+
75
123
  ## Основные пропсы
76
124
 
77
125
  ### Layout
@@ -81,21 +129,15 @@ export const App = () => (
81
129
  | `menuProps` | Пропсы для `ScMainMenu` (кроме `theme`/`layout`) |
82
130
  | `initialMenuLayout` | Начальное состояние меню: `'full'` или `'compact'` |
83
131
  | `initialTheme` | Начальная тема: `'light'` или `'dark'` |
84
- | `headerTitle`, `headerSubtitle` | Заголовок и подзаголовок в шапке |
85
- | `upperMenuSlot`, `pageLabelSlot` | Кастомные слоты для шапки |
86
- | `footerLeft`, `footerRight` | Контент футера |
87
132
 
88
133
  ### ScMainMenu
89
134
 
90
135
  | Проп | Описание |
91
136
  |------|----------|
92
- | `baseUrl` | Базовый URL API (формирует `${baseUrl}/idp/single-menu-data/${menuId}`) |
137
+ | `baseUrl` | Базовый URL API |
93
138
  | `menuId` | ID меню для загрузки данных |
94
- | `dataUrl` | Полный URL для загрузки (альтернатива `baseUrl` + `menuId`) |
95
- | `apps` | Готовый список приложений (вместо загрузки) |
96
139
  | `activeAppId` | ID активного приложения |
97
140
  | `useMockData` | Использовать встроенные mock-данные |
98
- | `iconResolver` | Кастомная функция для построения `AppDescriptor` |
99
141
  | `onLayoutChange` | Callback при переключении layout |
100
142
  | `onThemeChange` | Callback при переключении темы |
101
143
 
@@ -103,14 +145,27 @@ export const App = () => (
103
145
 
104
146
  ```json
105
147
  {
106
- "@sberbusiness/triplex-next": "^1.0.0",
107
- "@sberbusiness/icons-next": "^1.0.0",
148
+ "@sberbusiness/triplex-next": "^1.14.0",
149
+ "@sberbusiness/icons-next": "^1.11.0",
108
150
  "react": "^18.0.0",
109
151
  "react-dom": "^18.0.0"
110
152
  }
111
153
  ```
112
154
 
113
- > Рекомендуемые версии: `@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
+ ```
114
169
 
115
170
  ## Лицензия
116
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.0",
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",
@@ -27,7 +27,7 @@
27
27
  "lint:fix": "eslint . --fix",
28
28
  "typecheck": "tsc --noEmit",
29
29
  "prepublishOnly": "npm run build",
30
- "publish": "npm publish --access public"
30
+ "send": "npm publish --access public"
31
31
  },
32
32
  "keywords": [
33
33
  "react",
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
+ }