@rt-tools/ui-kit-v2 0.3.0 → 0.4.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 +25 -16
- package/fesm2022/rt-tools-ui-kit-v2.mjs +501 -1327
- package/fesm2022/rt-tools-ui-kit-v2.mjs.map +1 -1
- package/package.json +1 -2
- package/rt-tools-ui-kit-v2-0.4.0.tgz +0 -0
- package/src/lib/components/CONTEXT.md +1 -1
- package/src/lib/components/bar-list/CONTEXT.md +5 -5
- package/src/lib/components/button/rt-button.directive.scss +4 -0
- package/src/lib/components/checkbox/rt-checkbox.component.scss +6 -2
- package/src/lib/components/confirm-popover/CONTEXT.md +8 -8
- package/src/lib/components/dialog/footer/rt-dialog-footer.component.scss +20 -9
- package/src/lib/components/dialog/header/rt-dialog-header.component.scss +27 -15
- package/src/lib/components/download-link/CONTEXT.md +1 -1
- package/src/lib/components/download-link/rt-download-link.component.scss +13 -0
- package/src/lib/components/file-drop/CONTEXT.md +6 -6
- package/src/lib/components/file-input/CONTEXT.md +6 -6
- package/src/lib/components/live-badge/CONTEXT.md +5 -5
- package/src/lib/components/menu/CONTEXT.md +6 -6
- package/src/lib/components/message-composer/CONTEXT.md +10 -10
- package/src/lib/components/multiselect/CONTEXT.md +6 -6
- package/src/lib/components/night-grid/CONTEXT.md +4 -4
- package/src/lib/components/page-header/CONTEXT.md +7 -7
- package/src/lib/components/pagination/CONTEXT.md +1 -1
- package/src/lib/components/select/CONTEXT.md +8 -8
- package/src/lib/components/split-button/CONTEXT.md +7 -7
- package/src/lib/components/split-button/rt-split-button.component.scss +13 -0
- package/src/lib/components/stat-tile/CONTEXT.md +1 -1
- package/src/lib/components/table/CONTEXT.md +1 -1
- package/src/lib/components/tabs/CONTEXT.md +9 -9
- package/src/lib/components/tag/CONTEXT.md +2 -2
- package/src/lib/components/theme-toggle/CONTEXT.md +1 -1
- package/src/lib/components/toggle-switch/rt-toggle-switch.component.scss +6 -2
- package/src/styles/_semantic.scss +11 -2
- package/styles/tokens.css +12 -1
- package/types/rt-tools-ui-kit-v2.d.ts +315 -58
- package/rt-tools-ui-kit-v2-0.3.0.tgz +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rt-tools/ui-kit-v2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Yauheni Krumin",
|
|
6
6
|
"type": "module",
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"@angular/forms": "^22.0.0",
|
|
20
20
|
"@angular/platform-browser": "^22.0.0",
|
|
21
21
|
"@angular/router": "^22.0.0",
|
|
22
|
-
"@jsverse/transloco": "^8.4.0",
|
|
23
22
|
"quill": "^2.0.3",
|
|
24
23
|
"rxjs": "^7.8.2",
|
|
25
24
|
"typescript": "^6.0.0"
|
|
Binary file
|
|
@@ -26,7 +26,7 @@ tag/
|
|
|
26
26
|
`rt-tag--closable`, камелкейс превращается в дефис (`hasIndicator` → `--has-indicator`).
|
|
27
27
|
- **Точки для проверок помечены `qa-dataid`** — по нему компонент находят и спеки, и e2e.
|
|
28
28
|
- **Подписи, которые кит рисует сам**, живут в неймспейсе `rtKit` и приходят через
|
|
29
|
-
`
|
|
29
|
+
`provideRtKitLabels()`. Свой текст почти везде перебивает переведённый; пустая строка
|
|
30
30
|
равна отсутствию входа.
|
|
31
31
|
- **Цвета и размеры — только токены `--rt-*`**, ни одного HEX в компонентных стилях.
|
|
32
32
|
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
<rt-bar-list title="Источники" [rows]="[{ id: 'direct', title: 'Прямые заходы', meta: '1 240 визитов', value: '52%', sharePercent: 52 }]" />
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
| вход | тип | умолчание
|
|
10
|
-
| ----------- | ---------------------------------------------------------- |
|
|
11
|
-
| `rows` | `ReadonlyArray<{ id, title, meta?, value, sharePercent }>` | **обязателен**
|
|
12
|
-
| `title` | `string` | `''`
|
|
13
|
-
| `emptyText` | `string` | `''` → `
|
|
9
|
+
| вход | тип | умолчание |
|
|
10
|
+
| ----------- | ---------------------------------------------------------- | ----------------- |
|
|
11
|
+
| `rows` | `ReadonlyArray<{ id, title, meta?, value, sharePercent }>` | **обязателен** |
|
|
12
|
+
| `title` | `string` | `''` |
|
|
13
|
+
| `emptyText` | `string` | `''` → `uiNoData` |
|
|
14
14
|
|
|
15
15
|
Выходов нет.
|
|
16
16
|
|
|
@@ -79,10 +79,14 @@
|
|
|
79
79
|
cursor: not-allowed;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/* `flex-shrink: 0` — иконке заданного размера. Без него в кнопке, которой ширину
|
|
83
|
+
навязали снаружи (пункт меню `rt-split-button` берёт её от панели), лейбл давит
|
|
84
|
+
на иконку, и та сжимается до нуля: место занято, а иконки не видно. */
|
|
82
85
|
&__icon {
|
|
83
86
|
display: inline-flex;
|
|
84
87
|
width: var(--rt-btn-icon-size);
|
|
85
88
|
height: var(--rt-btn-icon-size);
|
|
89
|
+
flex-shrink: 0;
|
|
86
90
|
align-items: center;
|
|
87
91
|
justify-content: center;
|
|
88
92
|
font-size: var(--rt-btn-icon-size);
|
|
@@ -44,8 +44,12 @@ rt-checkbox .rt-checkbox {
|
|
|
44
44
|
border-color var(--rt-duration-fast) ease;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
/* Элемент адресуется классом, а не вторым `&`: родитель здесь составной
|
|
48
|
+
(`rt-checkbox .rt-checkbox`), и второй `&` развернулся бы в него целиком —
|
|
49
|
+
`… .rt-checkbox--checked rt-checkbox .rt-checkbox__box`, то есть в селектор,
|
|
50
|
+
требующий вложенного чекбокса. Заливка отмеченного из-за этого не применялась. */
|
|
51
|
+
&--checked .rt-checkbox__box,
|
|
52
|
+
&--indeterminate .rt-checkbox__box {
|
|
49
53
|
border-color: var(--rt-color-action-primary);
|
|
50
54
|
background: var(--rt-color-action-primary);
|
|
51
55
|
}
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
(confirmed)="reject()" />
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
| вход (алиас) | тип | умолчание
|
|
17
|
-
| ---------------------- | ------------------------------------ |
|
|
18
|
-
| `rtConfirm` | `string` | `''`
|
|
19
|
-
| `rtConfirmTitle` | `string \| null` | `null`
|
|
20
|
-
| `rtConfirmLabel` | `string` | `''` → `
|
|
21
|
-
| `rtConfirmCancelLabel` | `string` | `''` → `
|
|
22
|
-
| `rtConfirmTone` | `'danger' \| 'warning' \| 'primary'` | `'danger'`
|
|
23
|
-
| `rtConfirmDisabled` | `boolean` | `false`
|
|
16
|
+
| вход (алиас) | тип | умолчание |
|
|
17
|
+
| ---------------------- | ------------------------------------ | ------------------ |
|
|
18
|
+
| `rtConfirm` | `string` | `''` |
|
|
19
|
+
| `rtConfirmTitle` | `string \| null` | `null` |
|
|
20
|
+
| `rtConfirmLabel` | `string` | `''` → `uiConfirm` |
|
|
21
|
+
| `rtConfirmCancelLabel` | `string` | `''` → `uiCancel` |
|
|
22
|
+
| `rtConfirmTone` | `'danger' \| 'warning' \| 'primary'` | `'danger'` |
|
|
23
|
+
| `rtConfirmDisabled` | `boolean` | `false` |
|
|
24
24
|
|
|
25
25
|
| выход | тип |
|
|
26
26
|
| ----------- | ------ |
|
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
/* rt-dialog-footer — footer-слот модалки. ViewEncapsulation.None.
|
|
1
|
+
/* rt-dialog-footer — footer-слот модалки. ViewEncapsulation.None.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Хост адресуется по имени элемента, а не по классу блока: класс
|
|
4
|
+
`.rt-dialog-footer` висит и на `<rt-dialog-footer>`, и на `<footer>` внутри
|
|
5
|
+
него. Правило на голом классе доставалось обоим — кнопки прижимались к правому
|
|
6
|
+
краю не окна, а строки по содержимому, и разделитель рисовался дважды. Заодно
|
|
7
|
+
`:empty` теперь спрашивается у `<footer>`, а не у хоста: у хоста внутри всегда
|
|
8
|
+
лежит `<footer>`, и пустым он не бывал никогда. */
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
rt-dialog-footer {
|
|
11
|
+
display: contents;
|
|
12
|
+
|
|
13
|
+
.rt-dialog-footer {
|
|
14
|
+
display: flex;
|
|
15
|
+
justify-content: flex-end;
|
|
16
|
+
padding: var(--rt-space-lg);
|
|
17
|
+
border-block-start: 1px solid var(--rt-color-border-subtle);
|
|
18
|
+
gap: var(--rt-space-sm);
|
|
19
|
+
|
|
20
|
+
&:empty {
|
|
21
|
+
display: none;
|
|
22
|
+
}
|
|
12
23
|
}
|
|
13
24
|
}
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
/* rt-dialog-header — заголовок модалки. ViewEncapsulation.None.
|
|
2
|
-
Селекторы префиксованы `.rt-dialog-header`.
|
|
2
|
+
Селекторы префиксованы `.rt-dialog-header`.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
Хост адресуется по имени элемента, а не по классу блока: класс
|
|
5
|
+
`.rt-dialog-header` висит и на `<rt-dialog-header>`, и на `<header>` внутри
|
|
6
|
+
него. Правило на голом классе доставалось обоим — хост становился flex-строкой,
|
|
7
|
+
а `<header>` внутри неё сжимался по содержимому: заголовок и крестик стояли
|
|
8
|
+
вплотную вместо краёв окна, и разделитель рисовался дважды, двумя линиями
|
|
9
|
+
разной длины. Хост боксом не становится: строка шапки должна быть прямым
|
|
10
|
+
flex-ребёнком рамки окна. */
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
rt-dialog-header {
|
|
13
|
+
display: contents;
|
|
14
|
+
|
|
15
|
+
.rt-dialog-header {
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: space-between;
|
|
19
|
+
padding: var(--rt-space-lg);
|
|
20
|
+
border-block-end: 1px solid var(--rt-color-border-subtle);
|
|
21
|
+
gap: var(--rt-space-sm);
|
|
22
|
+
|
|
23
|
+
&__title {
|
|
24
|
+
margin: 0;
|
|
25
|
+
color: var(--rt-color-text-primary);
|
|
26
|
+
font-size: var(--rt-text-xl);
|
|
27
|
+
}
|
|
17
28
|
|
|
18
|
-
|
|
19
|
-
|
|
29
|
+
&__close {
|
|
30
|
+
margin-inline-start: auto;
|
|
31
|
+
}
|
|
20
32
|
}
|
|
21
33
|
}
|
|
@@ -21,6 +21,6 @@
|
|
|
21
21
|
## Как этим пользоваться
|
|
22
22
|
|
|
23
23
|
- Подпись для скринридера собирается из переведённой формулировки и имени файла
|
|
24
|
-
(`
|
|
24
|
+
(`uiDownloadFile` с подстановкой `{{name}}`) — на экране видно имя, а вслух читается
|
|
25
25
|
«Download: Договор.pdf».
|
|
26
26
|
- Для перечня вложений есть [`rt-file-list`](../file-list/CONTEXT.md); эта кнопка — одиночная.
|
|
@@ -14,6 +14,19 @@
|
|
|
14
14
|
font-weight: var(--rt-font-weight-medium);
|
|
15
15
|
gap: var(--rt-space-sm);
|
|
16
16
|
line-height: var(--rt-leading-snug);
|
|
17
|
+
|
|
18
|
+
&:hover {
|
|
19
|
+
text-decoration: underline;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Своей рамки у кнопки нет — она нарисована как ссылка, и умолчательный контур
|
|
23
|
+
браузер снимает вместе с рамкой. Без этого правила место фокуса с клавиатуры
|
|
24
|
+
не видно вовсе: кнопка выглядит одинаково выбранной и невыбранной. */
|
|
25
|
+
&:focus-visible {
|
|
26
|
+
border-radius: var(--rt-radius-sm);
|
|
27
|
+
box-shadow: var(--rt-shadow-focus-ring);
|
|
28
|
+
outline: none;
|
|
29
|
+
}
|
|
17
30
|
}
|
|
18
31
|
|
|
19
32
|
&__icon {
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
</rt-file-drop>
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
| вход | тип | умолчание
|
|
13
|
-
| -------------- | ----------------- |
|
|
14
|
-
| `disabled` | `boolean` | `false`
|
|
15
|
-
| `overlayLabel` | `string` | `''` → `
|
|
16
|
-
| `zones` | `readonly Zone[]` | `[]`
|
|
17
|
-
| `accept` | `string` | `''`
|
|
12
|
+
| вход | тип | умолчание |
|
|
13
|
+
| -------------- | ----------------- | -------------------------- |
|
|
14
|
+
| `disabled` | `boolean` | `false` |
|
|
15
|
+
| `overlayLabel` | `string` | `''` → `uiFileDropOverlay` |
|
|
16
|
+
| `zones` | `readonly Zone[]` | `[]` |
|
|
17
|
+
| `accept` | `string` | `''` |
|
|
18
18
|
|
|
19
19
|
Выходы: `filesDropped` (`File[]`), `zoneFilesDropped` (`{ zoneId, files }`), `draggingChange`.
|
|
20
20
|
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
Свои входы поверх общих из [`RtFormControlBase`](../form-control/CONTEXT.md):
|
|
12
12
|
|
|
13
|
-
| вход | тип | умолчание
|
|
14
|
-
| ------------- | ---------------- |
|
|
15
|
-
| `multiple` | `boolean` | `false`
|
|
16
|
-
| `accept` | `string \| null` | `null`
|
|
17
|
-
| `directory` | `boolean` | `false`
|
|
18
|
-
| `buttonLabel` | `string` | `''` → `
|
|
13
|
+
| вход | тип | умолчание |
|
|
14
|
+
| ------------- | ---------------- | --------------------- |
|
|
15
|
+
| `multiple` | `boolean` | `false` |
|
|
16
|
+
| `accept` | `string \| null` | `null` |
|
|
17
|
+
| `directory` | `boolean` | `false` |
|
|
18
|
+
| `buttonLabel` | `string` | `''` → `uiChooseFile` |
|
|
19
19
|
|
|
20
20
|
Значение — `File[]`.
|
|
21
21
|
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
<rt-live-badge label="Смотрят сейчас" [count]="visitors()" [active]="streamAlive()" />
|
|
5
5
|
```
|
|
6
6
|
|
|
7
|
-
| вход | тип | умолчание
|
|
8
|
-
| -------- | ---------------- |
|
|
9
|
-
| `label` | `string` | `''` → переведённое `
|
|
10
|
-
| `count` | `number \| null` | `null` → прочерк `—`
|
|
11
|
-
| `active` | `boolean` | `false`
|
|
7
|
+
| вход | тип | умолчание |
|
|
8
|
+
| -------- | ---------------- | ---------------------------------- |
|
|
9
|
+
| `label` | `string` | `''` → переведённое `uiLiveOnSite` |
|
|
10
|
+
| `count` | `number \| null` | `null` → прочерк `—` |
|
|
11
|
+
| `active` | `boolean` | `false` |
|
|
12
12
|
|
|
13
13
|
Выходов нет.
|
|
14
14
|
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
## `rt-menu`
|
|
19
19
|
|
|
20
|
-
| вход | тип | умолчание
|
|
21
|
-
| ----------- | ------------------ |
|
|
22
|
-
| `icon` | `IRtIcon.Name` | `'ellipsis-h'`
|
|
23
|
-
| `ariaLabel` | `string` | `''` → `
|
|
24
|
-
| `align` | `'start' \| 'end'` | `'end'`
|
|
25
|
-
| `disabled` | `boolean` | `false`
|
|
20
|
+
| вход | тип | умолчание |
|
|
21
|
+
| ----------- | ------------------ | ------------------ |
|
|
22
|
+
| `icon` | `IRtIcon.Name` | `'ellipsis-h'` |
|
|
23
|
+
| `ariaLabel` | `string` | `''` → `uiActions` |
|
|
24
|
+
| `align` | `'start' \| 'end'` | `'end'` |
|
|
25
|
+
| `disabled` | `boolean` | `false` |
|
|
26
26
|
|
|
27
27
|
## `rt-menu-item`
|
|
28
28
|
|
|
@@ -11,16 +11,16 @@
|
|
|
11
11
|
(submitted)="send($event)" />
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
| вход | тип | умолчание
|
|
15
|
-
| ---------------------- | ---------------------- |
|
|
16
|
-
| `placeholder` | `string` | `''` → `
|
|
17
|
-
| `attachments` | `boolean` | `false`
|
|
18
|
-
| `accept` | `string` | `''`
|
|
19
|
-
| `sending` / `disabled` | `boolean` | `false`
|
|
20
|
-
| `formatting` | `boolean` | `false`
|
|
21
|
-
| `toolbar` | `IRtRichEditorToolbar` | `'full'`
|
|
22
|
-
| `minRows` / `maxRows` | `number` | 1 / 6
|
|
23
|
-
| `droppedFiles` | `File[] \| null` | `null`
|
|
14
|
+
| вход | тип | умолчание |
|
|
15
|
+
| ---------------------- | ---------------------- | ------------------------ |
|
|
16
|
+
| `placeholder` | `string` | `''` → `chatPlaceholder` |
|
|
17
|
+
| `attachments` | `boolean` | `false` |
|
|
18
|
+
| `accept` | `string` | `''` |
|
|
19
|
+
| `sending` / `disabled` | `boolean` | `false` |
|
|
20
|
+
| `formatting` | `boolean` | `false` |
|
|
21
|
+
| `toolbar` | `IRtRichEditorToolbar` | `'full'` |
|
|
22
|
+
| `minRows` / `maxRows` | `number` | 1 / 6 |
|
|
23
|
+
| `droppedFiles` | `File[] \| null` | `null` |
|
|
24
24
|
|
|
25
25
|
Выход: `submitted` — `{ text, delta?, files }`.
|
|
26
26
|
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
Свои входы поверх общих из [`RtFormControlBase`](../form-control/CONTEXT.md):
|
|
10
10
|
|
|
11
|
-
| вход | тип | умолчание
|
|
12
|
-
| ------------- | ---------------------------------------------------------------------------- |
|
|
13
|
-
| `options` | `ReadonlyArray<{ label, value, disabled? }>` (тот же тип, что у `rt-select`) | `[]`
|
|
14
|
-
| `placeholder` | `string` | `''` → `
|
|
15
|
-
| `maxChips` | `number` | `3`
|
|
11
|
+
| вход | тип | умолчание |
|
|
12
|
+
| ------------- | ---------------------------------------------------------------------------- | ----------------------- |
|
|
13
|
+
| `options` | `ReadonlyArray<{ label, value, disabled? }>` (тот же тип, что у `rt-select`) | `[]` |
|
|
14
|
+
| `placeholder` | `string` | `''` → `uiSelectValues` |
|
|
15
|
+
| `maxChips` | `number` | `3` |
|
|
16
16
|
|
|
17
17
|
Значение — `ReadonlyArray<TValue>`. Отдельного выхода выбора нет: значение едет только формой.
|
|
18
18
|
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
- Закрытие панели помечает контрол тронутым; `FormControl.disable()` закрывает раскрытую панель.
|
|
32
32
|
- Подпись фишки берётся из `options` пайпом `rtMultiselectLabel`; для значения вне набора
|
|
33
33
|
подставляется его строковое представление.
|
|
34
|
-
- Отключённые опции не выбираются, пустой набор даёт `
|
|
34
|
+
- Отключённые опции не выбираются, пустой набор даёт `uiNoOptions`.
|
|
35
35
|
|
|
36
36
|
## Клавиатура
|
|
37
37
|
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
<rt-night-grid ariaLabel="Ночи марта" [cells]="cells()" (cellClick)="toggle($event)" />
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
| вход | тип | умолчание
|
|
10
|
-
| ----------- | ------------------------------------- |
|
|
11
|
-
| `cells` | `ReadonlyArray<{ id, state, title }>` | **обязателен**
|
|
12
|
-
| `ariaLabel` | `string` | `''` → `
|
|
9
|
+
| вход | тип | умолчание |
|
|
10
|
+
| ----------- | ------------------------------------- | ------------------------ |
|
|
11
|
+
| `cells` | `ReadonlyArray<{ id, state, title }>` | **обязателен** |
|
|
12
|
+
| `ariaLabel` | `string` | `''` → `uiNightGridAria` |
|
|
13
13
|
|
|
14
14
|
Выход: `cellClick` — отдаёт **целую клетку**, а не идентификатор.
|
|
15
15
|
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
<rt-page-header ariaLabel="Разделы" [items]="sections()" [user]="user()" (itemClick)="go($event)" (userClick)="openProfile()" />
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
| вход | тип | умолчание
|
|
10
|
-
| ----------- | --------------------------- |
|
|
11
|
-
| `items` | `ReadonlyArray<Item>` | `[]`
|
|
12
|
-
| `user` | `{ name, avatar? } \| null` | `null`
|
|
13
|
-
| `userTitle` | `string` | `''`
|
|
14
|
-
| `userMenu` | `TemplateRef \| null` | `null`
|
|
15
|
-
| `ariaLabel` | `string` | `''` → `
|
|
9
|
+
| вход | тип | умолчание |
|
|
10
|
+
| ----------- | --------------------------- | ------------------ |
|
|
11
|
+
| `items` | `ReadonlyArray<Item>` | `[]` |
|
|
12
|
+
| `user` | `{ name, avatar? } \| null` | `null` |
|
|
13
|
+
| `userTitle` | `string` | `''` |
|
|
14
|
+
| `userMenu` | `TemplateRef \| null` | `null` |
|
|
15
|
+
| `ariaLabel` | `string` | `''` → `uiMainNav` |
|
|
16
16
|
|
|
17
17
|
Выходы: `itemClick`, `userClick`.
|
|
18
18
|
|
|
@@ -38,6 +38,6 @@
|
|
|
38
38
|
- Узкая и широкая разметки живут в DOM **одновременно** (`pagination-compact` и
|
|
39
39
|
`pagination-nav`): какую показать, решает медиазапрос, а не условная отрисовка.
|
|
40
40
|
- **У пустого набора нет своего вида строки диапазона — бар при нём спрятан целиком.** Ветка на
|
|
41
|
-
`
|
|
41
|
+
`uiRangeEmpty` тут была, но показать её не могло ничто: правило видимости прячет бар
|
|
42
42
|
раньше. Сам ключ в словаре остался (он часть публичного `rtKit`), но кит его больше не читает.
|
|
43
43
|
Про пустоту говорит [`rt-empty-state`](../empty-state/CONTEXT.md), а не пагинация.
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
Свои входы поверх общих из [`RtFormControlBase`](../form-control/CONTEXT.md):
|
|
10
10
|
|
|
11
|
-
| вход | тип | умолчание
|
|
12
|
-
| ------------------- | -------------------------------------------- |
|
|
13
|
-
| `options` | `ReadonlyArray<{ label, value, disabled? }>` | `[]`
|
|
14
|
-
| `placeholder` | `string` | `''`
|
|
15
|
-
| `iconLeft` | `IRtIcon.Name \| null` | `null`
|
|
16
|
-
| `filter` | `boolean` | `false`
|
|
17
|
-
| `filterPlaceholder` | `string` | `''` → `
|
|
11
|
+
| вход | тип | умолчание |
|
|
12
|
+
| ------------------- | -------------------------------------------- | ----------------- |
|
|
13
|
+
| `options` | `ReadonlyArray<{ label, value, disabled? }>` | `[]` |
|
|
14
|
+
| `placeholder` | `string` | `''` |
|
|
15
|
+
| `iconLeft` | `IRtIcon.Name \| null` | `null` |
|
|
16
|
+
| `filter` | `boolean` | `false` |
|
|
17
|
+
| `filterPlaceholder` | `string` | `''` → `uiSearch` |
|
|
18
18
|
|
|
19
19
|
| выход | тип |
|
|
20
20
|
| ----------------- | ---------------- |
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
- Закрытие списка помечает контрол тронутым и сбрасывает строку фильтра.
|
|
46
46
|
- `FormControl.disable()` **закрывает уже раскрытый** список — иначе панель висела бы над
|
|
47
47
|
контролом, которым уже нельзя пользоваться.
|
|
48
|
-
- Пустой набор опций рисует строку `
|
|
48
|
+
- Пустой набор опций рисует строку `uiNoOptions`.
|
|
49
49
|
- Ширина панели равна ширине триггера (`rtPopoverWidth="trigger"`).
|
|
50
50
|
|
|
51
51
|
## Рядом
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
(itemSelect)="run($event)" />
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
| вход | тип | умолчание
|
|
15
|
-
| ---------------------- | ----------------------------------------------- |
|
|
16
|
-
| `label` | `string` | **обязателен**
|
|
17
|
-
| `menuItems` | `readonly { value, label, icon?, disabled? }[]` | **обязателен**
|
|
18
|
-
| `theme` / `size` | как у [`[rtButton]`](../button/CONTEXT.md) | `'primary'` / `'md'`
|
|
19
|
-
| `menuAriaLabel` | `string` | `''` → `
|
|
20
|
-
| `loading` / `disabled` | `boolean` | `false`
|
|
14
|
+
| вход | тип | умолчание |
|
|
15
|
+
| ---------------------- | ----------------------------------------------- | ---------------------- |
|
|
16
|
+
| `label` | `string` | **обязателен** |
|
|
17
|
+
| `menuItems` | `readonly { value, label, icon?, disabled? }[]` | **обязателен** |
|
|
18
|
+
| `theme` / `size` | как у [`[rtButton]`](../button/CONTEXT.md) | `'primary'` / `'md'` |
|
|
19
|
+
| `menuAriaLabel` | `string` | `''` → `uiMoreActions` |
|
|
20
|
+
| `loading` / `disabled` | `boolean` | `false` |
|
|
21
21
|
|
|
22
22
|
Выходы: `faceClick`, `itemSelect` (значение пункта).
|
|
23
23
|
|
|
@@ -57,8 +57,21 @@
|
|
|
57
57
|
list-style: none;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/* Ширину пункту задаёт панель, а не его текст: `width="trigger"` держит её равной
|
|
61
|
+
кнопке. Пункт длиннее обязан обрезаться, иначе лейбл вылезает за скруглённую
|
|
62
|
+
рамку панели и висит в воздухе. Многоточие требует блочного лейбла: у
|
|
63
|
+
`inline-flex` `text-overflow` не работает — текст внутри становится анонимным
|
|
64
|
+
flex-элементом, и обрезка проходит без знака. */
|
|
60
65
|
&__menu-item.rt-button {
|
|
66
|
+
overflow: hidden;
|
|
61
67
|
width: 100%;
|
|
62
68
|
justify-content: flex-start;
|
|
69
|
+
|
|
70
|
+
.rt-button__label {
|
|
71
|
+
display: block;
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
min-width: 0;
|
|
74
|
+
text-overflow: ellipsis;
|
|
75
|
+
}
|
|
63
76
|
}
|
|
64
77
|
}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
Знак и стрелка выводятся из числа: `> 0` — «+» и стрелка вверх, `< 0` — стрелка вниз. Дробная
|
|
30
30
|
часть отделяется запятой.
|
|
31
31
|
|
|
32
|
-
**Значение базы уходит параметром
|
|
32
|
+
**Значение базы уходит параметром подписи, а не подставляется в готовую строку.** Переводчик приложения
|
|
33
33
|
интерполирует `{{value}}` в момент перевода, и к возвращённой строке подставлять уже нечего:
|
|
34
34
|
`String.replace` после `translateSignal` не находил плейсхолдера, и от подписи оставалась одна
|
|
35
35
|
приставка («было», «was»). Параметр передан сигналом — смена базы переписывает строку.
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
|
|
48
48
|
## Края
|
|
49
49
|
|
|
50
|
-
- Пустой набор рисует заглушку с переведённым `
|
|
50
|
+
- Пустой набор рисует заглушку с переведённым `uiNoData`; свой текст перебивает её.
|
|
51
51
|
- Колонка `rtRowActions` добавляется китом сама, когда включён `showRowActions`, и рисует
|
|
52
52
|
[`rt-menu`](../menu/CONTEXT.md) в строке.
|
|
53
53
|
- Спеки логики лежат рядом: сортировка и предикат действий строки проверены отдельно.
|
|
@@ -23,15 +23,15 @@
|
|
|
23
23
|
|
|
24
24
|
## `[rtTab]`
|
|
25
25
|
|
|
26
|
-
| вход | тип | умолчание
|
|
27
|
-
| --------------------------------- | --------------------------------------------- |
|
|
28
|
-
| `rtTab` | `IRtTabs.Id` — идентификатор вкладки | `''`
|
|
29
|
-
| `label` | `string` | `''`
|
|
30
|
-
| `titleTemplate` | `TemplateRef \| null` | `null`
|
|
31
|
-
| `icon` / `iconColor` | `IRtIcon.Name \| null` / `IRtTabs.TitleColor` | `null` / `'current'`
|
|
32
|
-
| `badge` | `string \| number \| null` | `null`
|
|
33
|
-
| `disabled` / `hidden` / `invalid` | `boolean` | `false`
|
|
34
|
-
| `invalidMessage` | `string` | `''` → `
|
|
26
|
+
| вход | тип | умолчание |
|
|
27
|
+
| --------------------------------- | --------------------------------------------- | --------------------- |
|
|
28
|
+
| `rtTab` | `IRtTabs.Id` — идентификатор вкладки | `''` |
|
|
29
|
+
| `label` | `string` | `''` |
|
|
30
|
+
| `titleTemplate` | `TemplateRef \| null` | `null` |
|
|
31
|
+
| `icon` / `iconColor` | `IRtIcon.Name \| null` / `IRtTabs.TitleColor` | `null` / `'current'` |
|
|
32
|
+
| `badge` | `string \| number \| null` | `null` |
|
|
33
|
+
| `disabled` / `hidden` / `invalid` | `boolean` | `false` |
|
|
34
|
+
| `invalidMessage` | `string` | `''` → `uiTabInvalid` |
|
|
35
35
|
|
|
36
36
|
## Главное, что нужно знать
|
|
37
37
|
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
вовсе — радиус берётся из `shape`.
|
|
33
33
|
- Палитра дублируется атрибутом `data-severity` — по нему тег находят проверки и внешние стили,
|
|
34
34
|
не завязываясь на BEM-класс.
|
|
35
|
-
- Подпись крестика для скринридера берётся из словаря кита (`
|
|
36
|
-
`
|
|
35
|
+
- Подпись крестика для скринридера берётся из словаря кита (`uiRemove`). Без
|
|
36
|
+
`provideRtKitLabels()` там будет пусто.
|
|
37
37
|
|
|
38
38
|
## Края
|
|
39
39
|
|
|
@@ -23,6 +23,6 @@
|
|
|
23
23
|
|
|
24
24
|
## Края
|
|
25
25
|
|
|
26
|
-
- Подпись берётся из словаря кита (`
|
|
26
|
+
- Подпись берётся из словаря кита (`themeToggleLabel`) и вычисляется один раз при создании.
|
|
27
27
|
- В тестах между случаями надо чистить хранилище: иначе выбор предыдущего теста становится
|
|
28
28
|
начальным состоянием следующего.
|
|
@@ -63,7 +63,11 @@ rt-toggle-switch .rt-toggle-switch {
|
|
|
63
63
|
box-shadow var(--rt-duration-fast) ease;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
/* Элемент адресуется классом, а не вторым `&`: родитель здесь составной
|
|
67
|
+
(`rt-toggle-switch .rt-toggle-switch`), и второй `&` развернулся бы в него целиком —
|
|
68
|
+
то есть в селектор, требующий вложенного переключателя. Включённое состояние
|
|
69
|
+
из-за этого не применялось: трек оставался серым, бегунок — слева. */
|
|
70
|
+
&--on .rt-toggle-switch__track {
|
|
67
71
|
background: var(--rt-toggle-color-track-on);
|
|
68
72
|
box-shadow: none;
|
|
69
73
|
}
|
|
@@ -97,7 +101,7 @@ rt-toggle-switch .rt-toggle-switch {
|
|
|
97
101
|
transition: transform var(--rt-duration-fast) ease;
|
|
98
102
|
}
|
|
99
103
|
|
|
100
|
-
&--on
|
|
104
|
+
&--on .rt-toggle-switch__thumb {
|
|
101
105
|
transform: translateX(var(--rt-toggle-thumb-travel));
|
|
102
106
|
}
|
|
103
107
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
/* Semantic design tokens — light defaults.
|
|
1
|
+
/* Semantic design tokens — light defaults.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Тело вынесено в @mixin по той же причине, что и у тёмной темы: набор нужен не
|
|
4
|
+
только на `:root`, но и на отдельном контейнере. Без этого светлую половину
|
|
5
|
+
пары «светлая ↔ тёмная» нельзя показать, пока приложение стоит в тёмной теме, —
|
|
6
|
+
контейнер унаследует тёмные значения, и обе половины покажут одно и то же. */
|
|
7
|
+
|
|
8
|
+
@mixin rt-theme-light-tokens {
|
|
4
9
|
/* Background */
|
|
5
10
|
--rt-color-bg-page: var(--rt-neutral-50);
|
|
6
11
|
--rt-color-bg-surface: var(--rt-neutral-0);
|
|
@@ -287,6 +292,10 @@
|
|
|
287
292
|
--rt-field-value-empty-color: var(--rt-color-text-muted);
|
|
288
293
|
}
|
|
289
294
|
|
|
295
|
+
:root {
|
|
296
|
+
@include rt-theme-light-tokens;
|
|
297
|
+
}
|
|
298
|
+
|
|
290
299
|
/* На тач-устройствах инпут не меньше 16px: WebKit (весь iOS, включая Chrome)
|
|
291
300
|
зумит страницу при фокусе на поле с font-size < 16px — отсюда горизонтальный
|
|
292
301
|
сдвиг вёрстки. Десктоп сохраняет плотный 14px. */
|