@soxa-ui/theme-base 0.0.0-stage → 0.3.0-beta.1
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/LICENSE +21 -0
- package/README.md +399 -2
- package/dist/setup/index.d.ts +31 -0
- package/dist/setup/index.js +4 -0
- package/dist/setup/plugins/index.d.ts +3 -0
- package/dist/setup/plugins/table-head.plugin.d.ts +44 -0
- package/dist/setup/plugins/table-head.plugin.js +86 -0
- package/dist/setup/plugins/tabs-view.plugin.d.ts +32 -0
- package/dist/setup/plugins/tabs-view.plugin.js +100 -0
- package/dist/setup/plugins/toasts-front.plugin.d.ts +63 -0
- package/dist/setup/plugins/toasts-front.plugin.js +131 -0
- package/dist/setup/plugins/transitions.d.ts +43 -0
- package/dist/setup/plugins/transitions.js +75 -0
- package/package.json +55 -4
- package/src/anchored.css +75 -0
- package/src/caption.css +71 -0
- package/src/components/accordion.css +96 -0
- package/src/components/button.css +139 -0
- package/src/components/calendar.css +594 -0
- package/src/components/check-box.css +121 -0
- package/src/components/date-input.css +224 -0
- package/src/components/date-picker.css +208 -0
- package/src/components/dialog.css +95 -0
- package/src/components/drag-and-drop.css +18 -0
- package/src/components/drawer.css +171 -0
- package/src/components/field.css +440 -0
- package/src/components/icon.css +61 -0
- package/src/components/input.css +189 -0
- package/src/components/label.css +160 -0
- package/src/components/list-box.css +165 -0
- package/src/components/menu.css +224 -0
- package/src/components/number-input.css +183 -0
- package/src/components/pagination.css +164 -0
- package/src/components/popover.css +164 -0
- package/src/components/progress-linear.css +88 -0
- package/src/components/progress-spinner.css +127 -0
- package/src/components/radio-group.css +130 -0
- package/src/components/rating.css +141 -0
- package/src/components/scroller.css +136 -0
- package/src/components/select.css +233 -0
- package/src/components/skeleton.css +33 -0
- package/src/components/slider.css +482 -0
- package/src/components/switch.css +142 -0
- package/src/components/table.css +1513 -0
- package/src/components/tabs.css +166 -0
- package/src/components/tags.css +371 -0
- package/src/components/textarea.css +179 -0
- package/src/components/toasts.css +447 -0
- package/src/components/tooltip.css +59 -0
- package/src/direction.css +30 -0
- package/src/disabled.css +26 -0
- package/src/group.css +90 -0
- package/src/index.css +97 -0
- package/src/modal.css +183 -0
- package/src/place.css +30 -0
- package/src/required.css +40 -0
- package/src/reset.css +172 -0
- package/src/swipe.css +71 -0
- package/src/target.css +46 -0
- package/theme-contract.json +3373 -0
- package/theme-variables.json +336 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/* Tabs structure: the bar and active content panel are children of the root.
|
|
2
|
+
*
|
|
3
|
+
* .so-tabs root
|
|
4
|
+
* .so-tabs__bar tab list and slots at its edges
|
|
5
|
+
* .so-tabs__leading leading slot
|
|
6
|
+
* .so-tabs__list tab list, [role=tablist]
|
|
7
|
+
* .so-tabs-item tab row (Button) and sibling close button
|
|
8
|
+
* .so-tabs__trailing trailing slot
|
|
9
|
+
* .so-tabs-content active tab panel
|
|
10
|
+
*
|
|
11
|
+
* Slots sit beside the list: ARIA only allows tabs inside a tablist. The list
|
|
12
|
+
* fills the space between slots and aligns tabs within it: center centers them,
|
|
13
|
+
* end places them at the trailing edge, and stretch expands tabs without
|
|
14
|
+
* changing slot widths.
|
|
15
|
+
*
|
|
16
|
+
* Core sets root modifiers for orientation (--orientation-horizontal, --orientation-vertical), alignment
|
|
17
|
+
* (--alignment-center, --alignment-end, --alignment-stretch; start has no modifier), and vertical bar position
|
|
18
|
+
* (--position-end). A horizontal bar sits above the panel; a vertical bar sits
|
|
19
|
+
* at its inline start or end. Positions are logical, so inline start is right
|
|
20
|
+
* in RTL. Horizontal bar children form a row; vertical bar children form a column.
|
|
21
|
+
*
|
|
22
|
+
* Root-dependent rules use child combinators throughout: > .so-tabs__bar,
|
|
23
|
+
* > .so-tabs__bar > .so-tabs__list, and > .so-tabs-content. Descendant selectors
|
|
24
|
+
* would leak outer orientation and alignment into nested Tabs. Adapters keep
|
|
25
|
+
* bars and panels directly under the root, slots and lists under the bar, and
|
|
26
|
+
* tabs under the list.
|
|
27
|
+
*
|
|
28
|
+
* Document-root variables control gaps between tabs and slots, between a
|
|
29
|
+
* vertical bar and its panel, and margins above and below a horizontal panel.
|
|
30
|
+
* Defaults match oren; themes set their own values on the document root.
|
|
31
|
+
*
|
|
32
|
+
* Themes provide views (line, contained, outline), variants, text colors,
|
|
33
|
+
* inactive-tab dimming, focus rings, and part appearance. View lines, indicators,
|
|
34
|
+
* and containers belong to the bar, which anchors tab measurements. */
|
|
35
|
+
|
|
36
|
+
:root {
|
|
37
|
+
--so-tabs-gap: 1rem;
|
|
38
|
+
--so-tabs-panel-gap: 1rem;
|
|
39
|
+
--so-tabs-panel-margin: 0.625rem;
|
|
40
|
+
--so-tabs-slot-padding: 0.375rem;
|
|
41
|
+
--so-tabs-row-padding: 0.25rem;
|
|
42
|
+
--so-tabs-close-padding: 0.25rem;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.so-tabs {
|
|
46
|
+
display: flex;
|
|
47
|
+
width: 100%;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.so-tabs--orientation-horizontal {
|
|
51
|
+
flex-direction: column;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.so-tabs--orientation-horizontal > .so-tabs__bar,
|
|
55
|
+
.so-tabs--orientation-horizontal > .so-tabs__bar > .so-tabs__list {
|
|
56
|
+
flex-direction: row;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.so-tabs--orientation-vertical {
|
|
60
|
+
flex-direction: row;
|
|
61
|
+
gap: var(--so-tabs-panel-gap);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.so-tabs--orientation-vertical > .so-tabs__bar,
|
|
65
|
+
.so-tabs--orientation-vertical > .so-tabs__bar > .so-tabs__list {
|
|
66
|
+
flex-direction: column;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Вертикальная панель — остаток строки рядом с рядом, без полей над и под
|
|
70
|
+
* собой: от ряда её отделяет зазор корня. */
|
|
71
|
+
.so-tabs--orientation-vertical > .so-tabs-content {
|
|
72
|
+
flex: 1;
|
|
73
|
+
margin-block: 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.so-tabs--orientation-vertical.so-tabs--position-end {
|
|
77
|
+
flex-direction: row-reverse;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Ряд позиционирован: `offset*` табов считаются от ближайшего
|
|
81
|
+
* позиционированного предка, и место активного таба плагин раскладки
|
|
82
|
+
* (`TTabsViewPlugin`) пишет на ряд — отметку тема рисует от его же края.
|
|
83
|
+
* Список не позиционирован: `offset*` считались бы от него, а переменные
|
|
84
|
+
* лежат на ряду. */
|
|
85
|
+
.so-tabs__bar {
|
|
86
|
+
position: relative;
|
|
87
|
+
display: flex;
|
|
88
|
+
gap: var(--so-tabs-gap);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* Список забирает всё место ряда между слотами: слоты остаются у краёв ряда,
|
|
92
|
+
* а табы выравниваются внутри списка. */
|
|
93
|
+
.so-tabs__list {
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-grow: 1;
|
|
96
|
+
gap: var(--so-tabs-gap);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Слоты — у краёв ряда, своей ширины: стоят до списка и после него, и место
|
|
100
|
+
* между ними забирает список. Содержимое — по центру поперёк ряда. */
|
|
101
|
+
.so-tabs__leading,
|
|
102
|
+
.so-tabs__trailing {
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
padding-inline: var(--so-tabs-slot-padding);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.so-tabs-content {
|
|
109
|
+
margin-block: var(--so-tabs-panel-margin);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.so-tabs--alignment-center > .so-tabs__bar > .so-tabs__list {
|
|
113
|
+
justify-content: center;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.so-tabs--alignment-end > .so-tabs__bar > .so-tabs__list {
|
|
117
|
+
justify-content: flex-end;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.so-tabs--alignment-stretch > .so-tabs__bar > .so-tabs__list > * {
|
|
121
|
+
flex: 1;
|
|
122
|
+
justify-content: center;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* Выключенный набор гаснет корнем целиком — табы вместе с панелями
|
|
126
|
+
* (`disabled.css`): набор читается выключенным весь, а выключить поля в
|
|
127
|
+
* панелях — дело приложения. Нажатия гаснут у всего набора, в панелях тоже.
|
|
128
|
+
* Состояние — `data-disabled` корня: ядро пишет его на любом теге, а
|
|
129
|
+
* модификатора `--disabled` у блока нет. Табы выключены вместе с набором — их
|
|
130
|
+
* `disabled` распространяется от владельца — и под погасшим корнем второй раз
|
|
131
|
+
* не гаснут. */
|
|
132
|
+
.so-tabs[data-disabled='true'] {
|
|
133
|
+
opacity: var(--so-disabled-opacity);
|
|
134
|
+
pointer-events: none;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.so-tabs[data-disabled='true'] > * {
|
|
138
|
+
--so-disabled-opacity: 1;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Строка таба и кнопка закрытия — соседи в одну линию. Внутри строки кнопке
|
|
142
|
+
* не место: строка — `<button role="tab">`, интерактивный потомок у кнопки
|
|
143
|
+
* запрещён, а подпись крестика вошла бы в имя таба. Поэтому всё, что
|
|
144
|
+
* покрывает таб целиком, стоит на обёртке или меряется по ней, и `relative`
|
|
145
|
+
* — опора для этого. */
|
|
146
|
+
.so-tabs-item {
|
|
147
|
+
position: relative;
|
|
148
|
+
display: flex;
|
|
149
|
+
align-items: center;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Строка — всё в обёртке, кроме кнопки закрытия: она стоит рядом со строкой. */
|
|
153
|
+
.so-tabs-item > :not(.so-tabs-item__close) {
|
|
154
|
+
width: 100%;
|
|
155
|
+
padding-block: var(--so-tabs-row-padding);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Крестик стоит сразу за строкой, без зазора, со своим узким полем. Высота —
|
|
159
|
+
* высота строки без её поля по оси блока, а не размерная высота Button. */
|
|
160
|
+
.so-tabs-item > .so-tabs-item__close {
|
|
161
|
+
flex-shrink: 0;
|
|
162
|
+
align-self: stretch;
|
|
163
|
+
height: auto;
|
|
164
|
+
margin-block: var(--so-tabs-row-padding);
|
|
165
|
+
padding-inline: var(--so-tabs-close-padding);
|
|
166
|
+
}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/* ─── Tags ────────────────────────────────────────────────────
|
|
2
|
+
* Набор тегов — горизонтальный ряд, а не список: теги переносятся по
|
|
3
|
+
* строкам и держатся друг от друга на одинаковом зазоре.
|
|
4
|
+
*
|
|
5
|
+
* .so-tags корень — ряд
|
|
6
|
+
* .so-tags-item тег — пилюля: строка (Button) и крестик рядом
|
|
7
|
+
* .so-tags-item__close кнопка закрытия — Button
|
|
8
|
+
*
|
|
9
|
+
* Что делать с тегами, которым не хватило ширины ряда, решает компонент, а
|
|
10
|
+
* сюда это приходит состоянием — `data-overflow`: `wrap` — перенос (база
|
|
11
|
+
* ряда), `scroll` — одна строка с прокруткой. Тег под фокусом с клавиатуры
|
|
12
|
+
* ряд `scroll` доводит до своего окна (`TTagsScrollPlugin`), а окно — паддинг
|
|
13
|
+
* ряда за вычетом отступа прокрутки (`scroll-padding-inline`).
|
|
14
|
+
*
|
|
15
|
+
* Шкала тега — переменные корня документа по размеру (`sm`…`2xl`): высота
|
|
16
|
+
* пилюли, кегль и интерлиньяж, поле строки и зазор между её частями. Своя, а
|
|
17
|
+
* не шкала Button: тег на ступень мельче кнопки того же размера — метка в
|
|
18
|
+
* ряду, а не действие. Зазор ряда, запас под кольцо фокуса и поле крестика —
|
|
19
|
+
* тоже переменные корня. Умолчания — числа темы oren; тема задаёт свои на
|
|
20
|
+
* корне документа.
|
|
21
|
+
*
|
|
22
|
+
* Облик — поверхность пилюли, виды и варианты набора и тега, цвет крестика,
|
|
23
|
+
* кольцо фокуса и подсказка у края ряда `scroll` в поле — рисует тема. */
|
|
24
|
+
|
|
25
|
+
:root {
|
|
26
|
+
--so-tags-gap: 0.375rem;
|
|
27
|
+
--so-tags-field-gap: 0.25rem;
|
|
28
|
+
--so-tags-bleed: 0.25rem;
|
|
29
|
+
--so-tags-close-padding: 0.125rem;
|
|
30
|
+
|
|
31
|
+
--so-tags-item-height-sm: 1.5rem;
|
|
32
|
+
--so-tags-item-height-normal: 1.75rem;
|
|
33
|
+
--so-tags-item-height-lg: 2rem;
|
|
34
|
+
--so-tags-item-height-xl: 2.25rem;
|
|
35
|
+
--so-tags-item-height-2xl: 2.5rem;
|
|
36
|
+
|
|
37
|
+
/* Tags are a step smaller than the text next to them, and every step counts
|
|
38
|
+
* from the font of the place: 4px smaller at `sm`, 2px at `normal`, the font
|
|
39
|
+
* of the place at `lg`, 2px and 4px larger at `xl` and `2xl` — 12 / 14 / 16
|
|
40
|
+
* / 18 / 20px at a 16px place, 10 / 12 / 14 / 16 / 18px at 14px. `em`
|
|
41
|
+
* resolves where the variable is read: on the row and the close button of a
|
|
42
|
+
* tag, against the tag, that is the place — a set or the field of a Select. */
|
|
43
|
+
--so-tags-item-font-size-sm: calc(1em - 0.25rem);
|
|
44
|
+
--so-tags-item-line-height-sm: calc(1 / 0.75);
|
|
45
|
+
--so-tags-item-font-size-normal: calc(1em - 0.125rem);
|
|
46
|
+
--so-tags-item-line-height-normal: calc(1.25 / 0.875);
|
|
47
|
+
--so-tags-item-font-size-lg: 1em;
|
|
48
|
+
--so-tags-item-line-height-lg: 1.5;
|
|
49
|
+
--so-tags-item-font-size-xl: calc(1em + 0.125rem);
|
|
50
|
+
--so-tags-item-line-height-xl: calc(1.75 / 1.125);
|
|
51
|
+
--so-tags-item-font-size-2xl: calc(1em + 0.25rem);
|
|
52
|
+
--so-tags-item-line-height-2xl: calc(1.75 / 1.25);
|
|
53
|
+
|
|
54
|
+
--so-tags-item-padding-sm: 0.375rem;
|
|
55
|
+
--so-tags-item-padding-normal: 0.375rem;
|
|
56
|
+
--so-tags-item-padding-lg: 0.5rem;
|
|
57
|
+
--so-tags-item-padding-xl: 0.625rem;
|
|
58
|
+
--so-tags-item-padding-2xl: 0.75rem;
|
|
59
|
+
|
|
60
|
+
--so-tags-item-gap-sm: 0.25rem;
|
|
61
|
+
--so-tags-item-gap-normal: 0.25rem;
|
|
62
|
+
--so-tags-item-gap-lg: 0.375rem;
|
|
63
|
+
--so-tags-item-gap-xl: 0.375rem;
|
|
64
|
+
--so-tags-item-gap-2xl: 0.5rem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Зазор — переменной, а не числом на месте: своя раскладка в слоте `default`
|
|
68
|
+
* (лента, ряд с хвостом в панели) ставит теги не прямыми детьми набора, и то
|
|
69
|
+
* же число нужно уже ей. В поле оно своё (ниже). */
|
|
70
|
+
.so-tags {
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-wrap: wrap;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: var(--so-tags-gap);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Выключенный набор гаснет корнем целиком — ряд с тегами и содержимым слота
|
|
78
|
+
* (`disabled.css`). Состояние — `data-disabled` корня: ядро пишет его на любом
|
|
79
|
+
* теге, а модификатора `--disabled` у блока нет. Теги выключены вместе с
|
|
80
|
+
* набором — их `disabled` распространяется от владельца, нажатия они гасят
|
|
81
|
+
* сами — и под погасшим корнем второй раз не гаснут. */
|
|
82
|
+
.so-tags[data-disabled='true'] {
|
|
83
|
+
opacity: var(--so-disabled-opacity);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.so-tags[data-disabled='true'] > * {
|
|
87
|
+
--so-disabled-opacity: 1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Одна строка с нативной прокруткой: ряд листают колесом и пальцем.
|
|
91
|
+
*
|
|
92
|
+
* Тег не сжимается: ширина у него натуральная, а что не поместилось, уходит
|
|
93
|
+
* за край ряда и прокручивается. Сжимайся он по месту, флексбокс ужал бы ряд
|
|
94
|
+
* под ширину контейнера, и листать стало бы нечего.
|
|
95
|
+
*
|
|
96
|
+
* Запас под кольцо фокуса. Прокрутка по строке делает ряд прокручиваемой
|
|
97
|
+
* областью и по вертикали (`overflow-y` у него вычисляется в `auto`), а такая
|
|
98
|
+
* область режет всё, что вышло за её паддинг-бокс, — запаса за краем обрезки
|
|
99
|
+
* (`overflow-clip-margin`) у неё не бывает. Место кольцу даёт только паддинг.
|
|
100
|
+
* По вертикали отрицательное поле сверху возвращает тегам прежнее место;
|
|
101
|
+
* снизу поля нет: под паддингом стоит полоса прокрутки, и поле вынесло бы её
|
|
102
|
+
* на соседа под рядом. По строке поля нет вовсе: ряд, выступающий за свой
|
|
103
|
+
* контейнер, накрыл бы соседа и перехватывал бы у него указатель. Поэтому
|
|
104
|
+
* теги стоят на запас дальше от края ряда, чем в `wrap`.
|
|
105
|
+
*
|
|
106
|
+
* Тот же запас по строке — и отступом прокрутки. Паддинг даёт место кольцу
|
|
107
|
+
* только в начале и в конце прокрутки, а тег, который ряд докручивает до края
|
|
108
|
+
* посередине, встаёт к краю вплотную. Отступ прокрутки сужает на запас окно,
|
|
109
|
+
* до края которого ряд докручивают плагин ряда и сам браузер, и кольцо
|
|
110
|
+
* остаётся внутри ряда. */
|
|
111
|
+
.so-tags[data-overflow='scroll'] {
|
|
112
|
+
flex-wrap: nowrap;
|
|
113
|
+
overflow-x: auto;
|
|
114
|
+
padding-block: var(--so-tags-bleed);
|
|
115
|
+
padding-inline: var(--so-tags-bleed);
|
|
116
|
+
margin-block-start: calc(-1 * var(--so-tags-bleed));
|
|
117
|
+
scroll-padding-inline: var(--so-tags-bleed);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.so-tags[data-overflow='scroll'] > .so-tags-item {
|
|
121
|
+
flex-shrink: 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Строка тега и кнопка закрытия — соседи в одну линию. Внутри строки кнопке
|
|
125
|
+
* не место: в режиме выбора строка — `role="option"`, её потомки для
|
|
126
|
+
* скринридера презентационны, и подпись крестика вошла бы в имя тега.
|
|
127
|
+
* Поэтому пилюлю рисует обёртка, и `relative` — опора для того, что встаёт
|
|
128
|
+
* поверх неё. Высота пилюли — переменной: её задают ступень (ниже) и строка
|
|
129
|
+
* слота в поле, а по ней же держит себя в пилюле зона нажатия крестика. */
|
|
130
|
+
.so-tags-item {
|
|
131
|
+
position: relative;
|
|
132
|
+
display: flex;
|
|
133
|
+
align-items: center;
|
|
134
|
+
height: var(--so-tags-item-height);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Строка — во всю высоту пилюли изнутри, поэтому рамка вида тег не раздувает.
|
|
138
|
+
* Крестик — квадрат вокруг значка по центру пилюли: отступ от верха и низа —
|
|
139
|
+
* половина остатка высоты от значка без поля крестика. Тот же отступ — поле
|
|
140
|
+
* строки по оси блока: высота крестика — высота строки без него. `1em` —
|
|
141
|
+
* кегль того узла, на котором стоит отступ, а у строки и крестика он один:
|
|
142
|
+
* одна формула ставит крестик и в пилюлю своей ступени, и в строку слота
|
|
143
|
+
* поля, которая ниже пилюли. */
|
|
144
|
+
.so-tags-item > :not(.so-tags-item__close) {
|
|
145
|
+
height: 100%;
|
|
146
|
+
padding-block: calc((var(--so-tags-item-height) - 1em) / 2 - var(--so-tags-close-padding));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* Значок крестика — в кегль строки на любой ступени, а не по шкале иконок
|
|
150
|
+
* (`icon.css`): там с `lg` значок растёт быстрее кегля, и крестик рядом с
|
|
151
|
+
* подписью тега выходил бы жирнее её самой. Иконка из слота `close-icon` —
|
|
152
|
+
* тоже: размер ей здесь даёт крестик, а не её `size`. */
|
|
153
|
+
.so-tags-item > .so-tags-item__close {
|
|
154
|
+
flex-shrink: 0;
|
|
155
|
+
align-self: stretch;
|
|
156
|
+
height: auto;
|
|
157
|
+
padding-inline: var(--so-tags-close-padding);
|
|
158
|
+
margin-block: calc((var(--so-tags-item-height) - 1em) / 2 - var(--so-tags-close-padding));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.so-tags-item > .so-tags-item__close .so-icon {
|
|
162
|
+
width: 1em;
|
|
163
|
+
height: 1em;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* Зона нажатия крестика — невидимый квадрат по центру со стороной в минимум
|
|
167
|
+
* цели (`target.css`): сам крестик до `2xl` меньше, а в режиме выбора
|
|
168
|
+
* вплотную к нему стоит нажимаемая строка тега. Поверх строки зона лежит
|
|
169
|
+
* сама: строка и крестик позиционированы (`relative` у Button), и крестик в
|
|
170
|
+
* дереве позже.
|
|
171
|
+
*
|
|
172
|
+
* За пилюлю зона не выходит: снаружи она перехватывала бы нажатия у соседей,
|
|
173
|
+
* а ряду `scroll` добавила бы переполнение. По строке места хватает на любой
|
|
174
|
+
* ступени: от конца пилюли крестик отступает на поле строки, а к строке зона
|
|
175
|
+
* заходит на её концевое поле. По высоте зона — меньшее из минимума и высоты
|
|
176
|
+
* пилюли: крестик стоит по центру пилюли, и такая зона за неё не выходит. */
|
|
177
|
+
.so-tags-item > .so-tags-item__close::before {
|
|
178
|
+
content: '';
|
|
179
|
+
position: absolute;
|
|
180
|
+
inset-inline: calc(50% - var(--so-target-size) / 2);
|
|
181
|
+
inset-block: calc(50% - min(var(--so-target-size), var(--so-tags-item-height)) / 2);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* Размер тега — по его шкале. Строка и крестик — Button, и `size` тега
|
|
185
|
+
* доходит до них размерным классом Button; числа шкалы тега ложатся поверх
|
|
186
|
+
* него, на класс сильнее. Крестик встаёт на место последней части строки:
|
|
187
|
+
* перед ним — зазор строки, после — её поле. Строка, за которой он стоит,
|
|
188
|
+
* отдаёт ему своё концевое поле. */
|
|
189
|
+
.so-tags-item--size-sm {
|
|
190
|
+
--so-tags-item-height: var(--so-tags-item-height-sm);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.so-tags-item--size-sm > .so-button {
|
|
194
|
+
font-size: var(--so-tags-item-font-size-sm);
|
|
195
|
+
line-height: var(--so-tags-item-line-height-sm);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.so-tags-item--size-sm > :not(.so-tags-item__close) {
|
|
199
|
+
gap: var(--so-tags-item-gap-sm);
|
|
200
|
+
padding-inline: var(--so-tags-item-padding-sm);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.so-tags-item--size-sm > :has(+ .so-tags-item__close) {
|
|
204
|
+
padding-inline-end: var(--so-tags-item-gap-sm);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.so-tags-item--size-sm > .so-tags-item__close {
|
|
208
|
+
margin-inline-end: var(--so-tags-item-padding-sm);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.so-tags-item--size-normal {
|
|
212
|
+
--so-tags-item-height: var(--so-tags-item-height-normal);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.so-tags-item--size-normal > .so-button {
|
|
216
|
+
font-size: var(--so-tags-item-font-size-normal);
|
|
217
|
+
line-height: var(--so-tags-item-line-height-normal);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.so-tags-item--size-normal > :not(.so-tags-item__close) {
|
|
221
|
+
gap: var(--so-tags-item-gap-normal);
|
|
222
|
+
padding-inline: var(--so-tags-item-padding-normal);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.so-tags-item--size-normal > :has(+ .so-tags-item__close) {
|
|
226
|
+
padding-inline-end: var(--so-tags-item-gap-normal);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.so-tags-item--size-normal > .so-tags-item__close {
|
|
230
|
+
margin-inline-end: var(--so-tags-item-padding-normal);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.so-tags-item--size-lg {
|
|
234
|
+
--so-tags-item-height: var(--so-tags-item-height-lg);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.so-tags-item--size-lg > .so-button {
|
|
238
|
+
font-size: var(--so-tags-item-font-size-lg);
|
|
239
|
+
line-height: var(--so-tags-item-line-height-lg);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.so-tags-item--size-lg > :not(.so-tags-item__close) {
|
|
243
|
+
gap: var(--so-tags-item-gap-lg);
|
|
244
|
+
padding-inline: var(--so-tags-item-padding-lg);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.so-tags-item--size-lg > :has(+ .so-tags-item__close) {
|
|
248
|
+
padding-inline-end: var(--so-tags-item-gap-lg);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.so-tags-item--size-lg > .so-tags-item__close {
|
|
252
|
+
margin-inline-end: var(--so-tags-item-padding-lg);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.so-tags-item--size-xl {
|
|
256
|
+
--so-tags-item-height: var(--so-tags-item-height-xl);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.so-tags-item--size-xl > .so-button {
|
|
260
|
+
font-size: var(--so-tags-item-font-size-xl);
|
|
261
|
+
line-height: var(--so-tags-item-line-height-xl);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.so-tags-item--size-xl > :not(.so-tags-item__close) {
|
|
265
|
+
gap: var(--so-tags-item-gap-xl);
|
|
266
|
+
padding-inline: var(--so-tags-item-padding-xl);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.so-tags-item--size-xl > :has(+ .so-tags-item__close) {
|
|
270
|
+
padding-inline-end: var(--so-tags-item-gap-xl);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.so-tags-item--size-xl > .so-tags-item__close {
|
|
274
|
+
margin-inline-end: var(--so-tags-item-padding-xl);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.so-tags-item--size-2xl {
|
|
278
|
+
--so-tags-item-height: var(--so-tags-item-height-2xl);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.so-tags-item--size-2xl > .so-button {
|
|
282
|
+
font-size: var(--so-tags-item-font-size-2xl);
|
|
283
|
+
line-height: var(--so-tags-item-line-height-2xl);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.so-tags-item--size-2xl > :not(.so-tags-item__close) {
|
|
287
|
+
gap: var(--so-tags-item-gap-2xl);
|
|
288
|
+
padding-inline: var(--so-tags-item-padding-2xl);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.so-tags-item--size-2xl > :has(+ .so-tags-item__close) {
|
|
292
|
+
padding-inline-end: var(--so-tags-item-gap-2xl);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.so-tags-item--size-2xl > .so-tags-item__close {
|
|
296
|
+
margin-inline-end: var(--so-tags-item-padding-2xl);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/* Выключенный тег гаснет целиком, с крестиком, и нажатий не ловит
|
|
300
|
+
* (`disabled.css`). Строка и крестик — Button со своим `data-disabled` и под
|
|
301
|
+
* погасшей пилюлей второй раз не гаснут. */
|
|
302
|
+
.so-tags-item[data-disabled='true'] {
|
|
303
|
+
opacity: var(--so-disabled-opacity);
|
|
304
|
+
cursor: default;
|
|
305
|
+
pointer-events: none;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.so-tags-item[data-disabled='true'] > * {
|
|
309
|
+
--so-disabled-opacity: 1;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/* Теги внутри поля ввода: высоту задаёт строка слота поля (`input.css`) —
|
|
313
|
+
* высота размера поля без рамки и просветов, — ширину — слот, а не размерный
|
|
314
|
+
* класс. Кегль, поля и крестик — те же, что у тега вне поля: шкала тега и так
|
|
315
|
+
* мельче Button. Значение, а не процент от слота: поле Select растёт по
|
|
316
|
+
* строкам тегов, у растущего поля и слота высота авто, и процент от неё не
|
|
317
|
+
* разрешается.
|
|
318
|
+
*
|
|
319
|
+
* Ширину отдаёт слот. Ряд переносится по строкам, а один тег переносить
|
|
320
|
+
* некуда, поэтому тег шире слота сжимается сам: текст строки обрезается
|
|
321
|
+
* многоточием (у области текста Button оно уже есть), крестик не сжимается.
|
|
322
|
+
* Для этого автоматический минимум ширины — по всему тексту тега — снят у
|
|
323
|
+
* всей цепочки: у ряда, у тега и у строки. В `scroll` тег натуральной ширины:
|
|
324
|
+
* не поместившееся там прокручивается, а не сжимается (`flex-shrink` выше).
|
|
325
|
+
*
|
|
326
|
+
* Зазор в поле уже: строка поля коротка, и зазор ряда вне поля съедал бы
|
|
327
|
+
* ширину, которой не хватает вводу. */
|
|
328
|
+
.so-input__leading > .so-tags,
|
|
329
|
+
.so-input__trailing > .so-tags {
|
|
330
|
+
--so-tags-gap: var(--so-tags-field-gap);
|
|
331
|
+
min-width: 0;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.so-input__leading > .so-tags .so-tags-item,
|
|
335
|
+
.so-input__trailing > .so-tags .so-tags-item {
|
|
336
|
+
--so-tags-item-height: var(--so-input-slot-row);
|
|
337
|
+
min-width: 0;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.so-input__leading > .so-tags .so-tags-item > :not(.so-tags-item__close),
|
|
341
|
+
.so-input__trailing > .so-tags .so-tags-item > :not(.so-tags-item__close) {
|
|
342
|
+
min-width: 0;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/* Ряд `scroll` в поле — без полосы прокрутки. Классическая полоса (Windows,
|
|
346
|
+
* Linux) занимает место под тегами, а поле в `scroll` постоянной высоты: ряд
|
|
347
|
+
* вытягивался бы вниз мимо слота. Прокрутка остаётся: палец, трекпад, колесо
|
|
348
|
+
* с Shift.
|
|
349
|
+
*
|
|
350
|
+
* Запас под кольцо в поле — просвет слота: паддинг-бокс ряда с ним ровно до
|
|
351
|
+
* рамки поля. Полосы здесь нет, и низ ряд возвращает так же, как верх:
|
|
352
|
+
* внешняя высота ряда — строка слота, и поле не растёт. По строке запаса нет:
|
|
353
|
+
* у пилюли в поле остановки Tab нет, а крестик отступает от края пилюли
|
|
354
|
+
* дальше, чем выходит его кольцо. Отступ прокрутки по строке — ширина
|
|
355
|
+
* подсказки у края, если её рисует тема (`--so-tags-fade`, контракт): окно ряда
|
|
356
|
+
* — его чистая часть, и тег под фокусом докручивают туда, а не под подсказку.
|
|
357
|
+
* Без подсказки отступа нет, и тег встаёт вплотную к краю. */
|
|
358
|
+
.so-input__leading > .so-tags[data-overflow='scroll'],
|
|
359
|
+
.so-input__trailing > .so-tags[data-overflow='scroll'] {
|
|
360
|
+
--so-tags-bleed: var(--so-input-slot-gap);
|
|
361
|
+
margin-block-end: calc(-1 * var(--so-tags-bleed));
|
|
362
|
+
padding-inline: 0;
|
|
363
|
+
scroll-padding-inline: var(--so-tags-fade, 0px);
|
|
364
|
+
scrollbar-width: none;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/* Полоса в движках WebKit: `scrollbar-width` там появился поздно. */
|
|
368
|
+
.so-input__leading > .so-tags[data-overflow='scroll']::-webkit-scrollbar,
|
|
369
|
+
.so-input__trailing > .so-tags[data-overflow='scroll']::-webkit-scrollbar {
|
|
370
|
+
display: none;
|
|
371
|
+
}
|