hallo-kit 0.3.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 +168 -0
- package/bin/cli.mjs +136 -0
- package/fonts/Manrope/Manrope-VariableFont_wght.woff2 +0 -0
- package/fonts/Manrope/OFL.txt +93 -0
- package/fonts/index.ts +30 -0
- package/package.json +77 -0
- package/src/config.ts +11 -0
- package/src/hooks/index.ts +14 -0
- package/src/hooks/useAutoHideOnScroll.ts +26 -0
- package/src/hooks/useCountdown.ts +44 -0
- package/src/hooks/useDevice.ts +63 -0
- package/src/hooks/useIsTelegramMiniApp.ts +17 -0
- package/src/hooks/useIsTouch.ts +23 -0
- package/src/hooks/useKeyboardOpen.ts +35 -0
- package/src/hooks/useMediaQuery.ts +24 -0
- package/src/hooks/usePlatform.ts +102 -0
- package/src/hooks/useQueryParams.tsx +70 -0
- package/src/hooks/useRevealOnce.ts +21 -0
- package/src/hooks/useScrolledPast.ts +19 -0
- package/src/hooks/useSettleOnce.ts +26 -0
- package/src/hooks/useTelegram.tsx +57 -0
- package/src/i18n/index.tsx +92 -0
- package/src/index.ts +35 -0
- package/src/lib/device.ts +28 -0
- package/src/lib/platform.ts +19 -0
- package/src/lib/utils.ts +36 -0
- package/src/logo/LogoFull.tsx +59 -0
- package/src/logo/LogoMark.tsx +31 -0
- package/src/logo/index.ts +2 -0
- package/src/next.ts +13 -0
- package/src/server.ts +4 -0
- package/src/theme-color-sync.tsx +43 -0
- package/src/theme-provider.tsx +31 -0
- package/src/types/css.d.ts +6 -0
- package/src/types/globals.d.ts +47 -0
- package/src/ui/Icon/Icon.module.css +25 -0
- package/src/ui/Icon/Icon.tsx +45 -0
- package/src/ui/Icon/Icon.types.ts +60 -0
- package/src/ui/Icon/data/brand.data.tsx +75 -0
- package/src/ui/Icon/data/index.ts +2 -0
- package/src/ui/Icon/data/ui.data.tsx +780 -0
- package/src/ui/Icon/index.ts +3 -0
- package/src/ui/badge/badge.tsx +185 -0
- package/src/ui/badge/index.ts +1 -0
- package/src/ui/breadcrumbs/breadcrumbs.tsx +63 -0
- package/src/ui/breadcrumbs/index.ts +1 -0
- package/src/ui/burger-icon/burger-icon.tsx +22 -0
- package/src/ui/burger-icon/index.ts +1 -0
- package/src/ui/button/button.tsx +179 -0
- package/src/ui/button/index.ts +1 -0
- package/src/ui/card/card.tsx +100 -0
- package/src/ui/card/index.ts +1 -0
- package/src/ui/confirm/confirm-dialog-host.tsx +89 -0
- package/src/ui/confirm/index.ts +1 -0
- package/src/ui/count-up/count-up.tsx +96 -0
- package/src/ui/count-up/index.ts +1 -0
- package/src/ui/data-list/data-list.tsx +331 -0
- package/src/ui/data-list/index.ts +1 -0
- package/src/ui/drawer/drawer.tsx +166 -0
- package/src/ui/drawer/index.ts +1 -0
- package/src/ui/flag/flag.data.ts +240 -0
- package/src/ui/flag/flag.tsx +57 -0
- package/src/ui/flag/index.ts +1 -0
- package/src/ui/image/image.tsx +67 -0
- package/src/ui/image/index.ts +1 -0
- package/src/ui/input/amount-input.tsx +55 -0
- package/src/ui/input/index.ts +2 -0
- package/src/ui/input/input.tsx +391 -0
- package/src/ui/label/index.ts +1 -0
- package/src/ui/label/label.tsx +34 -0
- package/src/ui/method-card/index.ts +1 -0
- package/src/ui/method-card/method-card.tsx +101 -0
- package/src/ui/modal/index.ts +1 -0
- package/src/ui/modal/modal.tsx +128 -0
- package/src/ui/otp-input/index.ts +1 -0
- package/src/ui/otp-input/otp-input.tsx +78 -0
- package/src/ui/pagination/index.ts +1 -0
- package/src/ui/pagination/pagination.tsx +138 -0
- package/src/ui/radio-group/index.ts +1 -0
- package/src/ui/radio-group/radio-group.tsx +81 -0
- package/src/ui/select/index.ts +1 -0
- package/src/ui/select/select.tsx +215 -0
- package/src/ui/separator/index.ts +1 -0
- package/src/ui/separator/separator.tsx +54 -0
- package/src/ui/skeleton/index.ts +1 -0
- package/src/ui/skeleton/skeleton.tsx +44 -0
- package/src/ui/spinner/index.ts +1 -0
- package/src/ui/spinner/spinner.tsx +33 -0
- package/src/ui/switch/index.ts +1 -0
- package/src/ui/switch/switch.tsx +48 -0
- package/src/ui/tabs/index.ts +1 -0
- package/src/ui/tabs/tabs.tsx +190 -0
- package/src/ui/textarea/index.ts +1 -0
- package/src/ui/textarea/textarea.tsx +151 -0
- package/src/ui/theme-switch/index.ts +1 -0
- package/src/ui/theme-switch/theme-switch.tsx +161 -0
- package/src/ui/toast/index.ts +1 -0
- package/src/ui/toast/toast.tsx +159 -0
- package/src/utils/api/stringFormat.ts +5 -0
- package/src/utils/clearAllCookies.ts +7 -0
- package/src/utils/clsx.ts +18 -0
- package/src/utils/confirm.ts +48 -0
- package/src/utils/copy-to-clipboard.ts +12 -0
- package/src/utils/date/convertTimestamp.ts +44 -0
- package/src/utils/date/formatCountdown.ts +9 -0
- package/src/utils/date/formatDayLabel.ts +50 -0
- package/src/utils/date/formatRelativeDateTime.ts +34 -0
- package/src/utils/date/locales.ts +9 -0
- package/src/utils/form/validationSchema.ts +46 -0
- package/src/utils/getByKeyString.ts +15 -0
- package/src/utils/getCssVar.ts +2 -0
- package/src/utils/getDeepType.ts +3 -0
- package/src/utils/getQueryParams.ts +21 -0
- package/src/utils/inAppBrowser.ts +151 -0
- package/src/utils/index.ts +28 -0
- package/src/utils/isRTL.ts +29 -0
- package/src/utils/notify.ts +46 -0
- package/src/utils/openExternal.ts +27 -0
- package/src/utils/system/getMillisecondsPeriod.ts +31 -0
- package/src/utils/validation/authValidators.ts +23 -0
- package/src/utils/validation/refCode.ts +30 -0
- package/styles/base.css +97 -0
- package/styles/brand.css +36 -0
- package/styles/index.css +19 -0
- package/styles/motion.css +207 -0
- package/styles/semantic.css +151 -0
- package/styles/theme.css +143 -0
- package/styles/utilities.css +289 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/* СЕМАНТИЧЕСКИЙ СЛОЙ — контракт дизайн-системы (light + dark).
|
|
2
|
+
Имена по назначению; тема меняет значения, классы остаются те же.
|
|
3
|
+
Источник: hallo/client — src/app/globals.css. Файл раздаётся пакетом @hallo/kit;
|
|
4
|
+
правки вносить ЗДЕСЬ, кабинет и сайты получают их обновлением пакета. */
|
|
5
|
+
|
|
6
|
+
/* Тёмная тема — классом .dark на <html> (его ставит next-themes, attribute="class"). */
|
|
7
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
8
|
+
|
|
9
|
+
:root {
|
|
10
|
+
/* Схема для НАТИВНОЙ отрисовки WebKit/Blink (каретка ввода, скроллбары,
|
|
11
|
+
автозаполнение). Тему мы переключаем классом `.dark`, а не media, поэтому без
|
|
12
|
+
явного color-scheme движок берёт СИСТЕМНУЮ схему — в Telegram MiniApp на iOS
|
|
13
|
+
WebView навязывает свою (обычно dark), из-за чего на светлой теме каретка в
|
|
14
|
+
инпутах белая = невидимая. Привязываем схему к теме → каретка красится верно. */
|
|
15
|
+
color-scheme: light;
|
|
16
|
+
|
|
17
|
+
/* ============================================================
|
|
18
|
+
СЕМАНТИЧЕСКИЙ СЛОЙ — светлая тема.
|
|
19
|
+
Имена по назначению; тема меняет значения, а классы остаются те же.
|
|
20
|
+
============================================================ */
|
|
21
|
+
/* поверхности и текст */
|
|
22
|
+
--background: var(--sky-mist); /* Sky Mist — весь задний фон страницы */
|
|
23
|
+
--foreground: var(--deep-navy);
|
|
24
|
+
--card: var(
|
|
25
|
+
--cloud-white
|
|
26
|
+
); /* Cloud White — блок/карточка поверх фона, внутри контент */
|
|
27
|
+
--card-foreground: var(--deep-navy);
|
|
28
|
+
--popover: var(--cloud-white); /* всплывающие поверхности — тоже белые */
|
|
29
|
+
--popover-foreground: var(--deep-navy);
|
|
30
|
+
|
|
31
|
+
/* приглушённые элементы (вторичный текст, фоны-заглушки) */
|
|
32
|
+
--muted: var(--sky-mist);
|
|
33
|
+
--muted-foreground: #556a92; /* вторичный текст */
|
|
34
|
+
/* Здесь стоял --disabled-blue (#8ea6d8) с пометкой «при нехватке контраста
|
|
35
|
+
заменить». Замерено: 2.42:1 на карточке (#fefefe), 2.17:1 на фоне страницы
|
|
36
|
+
(#eaf2ff), 2.23:1 на soft-карточках — при пороге WCAG AA 4.5:1 для обычного
|
|
37
|
+
текста. Этим токеном набран весь вторичный текст кабинета: подписи полей,
|
|
38
|
+
описания карточек, подвал, пустые состояния. #556a92 даёт 5.39 / 4.83 / 4.96.
|
|
39
|
+
Роль «неактивный контрол» осталась за --disabled, он не менялся.
|
|
40
|
+
В тёмной теме токен другой, там 7.2:1 — её не трогаем. */
|
|
41
|
+
|
|
42
|
+
/* границы, поля ввода, кольцо фокуса */
|
|
43
|
+
--border: var(--ice-blue);
|
|
44
|
+
--input: var(--ice-blue);
|
|
45
|
+
--ring: var(--brand-blue);
|
|
46
|
+
|
|
47
|
+
/* основной бренд */
|
|
48
|
+
--primary: var(--brand-blue);
|
|
49
|
+
--primary-foreground: var(--cloud-white);
|
|
50
|
+
/* вторичный / акцентный фон (hover-состояния, чипы) */
|
|
51
|
+
--secondary: var(--sky-mist);
|
|
52
|
+
--secondary-foreground: var(--deep-navy);
|
|
53
|
+
--accent: var(--ice-blue);
|
|
54
|
+
--accent-foreground: var(--deep-navy);
|
|
55
|
+
|
|
56
|
+
/* статус: успех / подключение */
|
|
57
|
+
--success: var(--connection-green);
|
|
58
|
+
--success-strong: var(--connection-green-dark);
|
|
59
|
+
--success-foreground: var(--cloud-white);
|
|
60
|
+
--success-soft: var(--green-soft);
|
|
61
|
+
|
|
62
|
+
/* статус: ошибка / алерт */
|
|
63
|
+
--error: var(--error-red);
|
|
64
|
+
--error-foreground: var(--cloud-white);
|
|
65
|
+
--error-soft: var(--error-red-soft);
|
|
66
|
+
--error-strong: var(--error-red-dark); /* текст/hover на soft-фоне */
|
|
67
|
+
|
|
68
|
+
/* статус: предупреждение / warning */
|
|
69
|
+
--warning: var(--warning-gold);
|
|
70
|
+
--warning-strong: var(--warning-gold-dark);
|
|
71
|
+
--warning-foreground: var(--deep-navy);
|
|
72
|
+
--warning-soft: var(--gold-soft);
|
|
73
|
+
|
|
74
|
+
/* неактивные элементы */
|
|
75
|
+
--disabled: var(--disabled-blue);
|
|
76
|
+
--disabled-foreground: var(--cloud-white);
|
|
77
|
+
|
|
78
|
+
/* блик skeleton-заглушки (shimmer) поверх bg-accent — в light яркий белый */
|
|
79
|
+
--skeleton-sheen: rgba(255, 255, 255, 0.7);
|
|
80
|
+
|
|
81
|
+
/* радиус скругления (базовый, остальные считаются от него) */
|
|
82
|
+
--radius: 1rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ============================================================
|
|
86
|
+
ТЁМНАЯ ТЕМА. Переопределяем СЕМАНТИЧЕСКИЙ слой — формы и логика компонентов
|
|
87
|
+
те же, меняются только поверхности и текст. Бренд (primary/синий) и hue
|
|
88
|
+
статусов (success/error/warning) сохраняем; у статусов меняем лишь soft-подложки
|
|
89
|
+
на тёмные тонированные. Палитра — navy-tinted dark (в тон бренду, не серый).
|
|
90
|
+
|
|
91
|
+
Поверхности от тёмного к светлому: background → card → popover/secondary → accent.
|
|
92
|
+
Raw-цвета (bg-blue, bg-navy и т.п.) НЕ адаптируются — это фиксированный бренд.
|
|
93
|
+
============================================================ */
|
|
94
|
+
.dark {
|
|
95
|
+
/* Нативная схема — тёмная (см. пояснение к color-scheme в :root). */
|
|
96
|
+
color-scheme: dark;
|
|
97
|
+
|
|
98
|
+
/* поверхности и текст */
|
|
99
|
+
--background: #0a0e1a; /* фон страницы — почти чёрный с синевой */
|
|
100
|
+
--foreground: #e8edf7; /* основной текст — почти белый, прохладный */
|
|
101
|
+
--card: #121829; /* карточка над фоном */
|
|
102
|
+
--card-foreground: #e8edf7;
|
|
103
|
+
--popover: #161d31; /* меню/селект — чуть светлее карточки */
|
|
104
|
+
--popover-foreground: #e8edf7;
|
|
105
|
+
|
|
106
|
+
/* приглушённые */
|
|
107
|
+
--muted: #1b2440;
|
|
108
|
+
--muted-foreground: var(
|
|
109
|
+
--disabled-blue
|
|
110
|
+
); /* читается как вторичный текст и на тёмном */
|
|
111
|
+
|
|
112
|
+
/* границы, поля ввода, кольцо фокуса */
|
|
113
|
+
--border: #232c46; /* тонкая граница чуть светлее поверхностей */
|
|
114
|
+
--input: #232c46;
|
|
115
|
+
--ring: var(--brand-blue); /* фокус — бренд-синий */
|
|
116
|
+
|
|
117
|
+
/* основной бренд — НЕ меняем, кнопки остаются те же */
|
|
118
|
+
--primary: var(--brand-blue);
|
|
119
|
+
--primary-foreground: var(--cloud-white);
|
|
120
|
+
|
|
121
|
+
/* вторичный/акцентный фон: заливка инпутов, hover, неактивные табы */
|
|
122
|
+
--secondary: #1b2440; /* фон инпута на тёмной карточке (роль как у sky-mist на светлой) */
|
|
123
|
+
--secondary-foreground: #e8edf7;
|
|
124
|
+
--accent: #243057; /* hover — чуть светлее secondary */
|
|
125
|
+
--accent-foreground: #e8edf7;
|
|
126
|
+
|
|
127
|
+
/* статусы: hue прежний, soft-подложки — тёмные тонированные */
|
|
128
|
+
--success: var(--connection-green);
|
|
129
|
+
--success-strong: #4ade80;
|
|
130
|
+
--success-foreground: var(--cloud-white);
|
|
131
|
+
--success-soft: #132a1f;
|
|
132
|
+
|
|
133
|
+
--error: var(--error-red);
|
|
134
|
+
--error-foreground: var(--cloud-white);
|
|
135
|
+
--error-soft: #2b1618;
|
|
136
|
+
--error-strong: #f87171; /* светлее красный — текст/hover на тёмном soft */
|
|
137
|
+
|
|
138
|
+
--warning: var(--warning-gold);
|
|
139
|
+
--warning-strong: #facc15;
|
|
140
|
+
--warning-foreground: var(
|
|
141
|
+
--deep-navy
|
|
142
|
+
); /* на gold-кнопке текст тёмный, как и в light */
|
|
143
|
+
--warning-soft: #2b2412;
|
|
144
|
+
|
|
145
|
+
/* неактивные: disabled-blue оставляем — он же цвет разделителей, должен быть виден на тёмном */
|
|
146
|
+
--disabled: var(--disabled-blue);
|
|
147
|
+
--disabled-foreground: var(--cloud-white);
|
|
148
|
+
|
|
149
|
+
/* блик skeleton — на тёмном navy мягкий (низкая альфа), иначе слишком резко */
|
|
150
|
+
--skeleton-sheen: rgba(255, 255, 255, 0.12);
|
|
151
|
+
}
|
package/styles/theme.css
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/* Проброс токенов в Tailwind: bg-primary, text-foreground, text-h1, rounded-lg …
|
|
2
|
+
Источник: hallo/client — src/app/globals.css. Файл раздаётся пакетом @hallo/kit;
|
|
3
|
+
правки вносить ЗДЕСЬ, кабинет и сайты получают их обновлением пакета. */
|
|
4
|
+
|
|
5
|
+
/* ============================================================
|
|
6
|
+
Прокидываем токены в Tailwind → появляются утилиты:
|
|
7
|
+
bg-primary, text-foreground, border-border, ring-ring, bg-success,
|
|
8
|
+
text-error-strong, bg-warning-soft, bg-brand, text-navy,
|
|
9
|
+
rounded-lg, text-h1 …
|
|
10
|
+
============================================================ */
|
|
11
|
+
@theme inline {
|
|
12
|
+
/* — семантические — */
|
|
13
|
+
--color-background: var(--background);
|
|
14
|
+
--color-foreground: var(--foreground);
|
|
15
|
+
--color-card: var(--card);
|
|
16
|
+
--color-card-foreground: var(--card-foreground);
|
|
17
|
+
--color-popover: var(--popover);
|
|
18
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
19
|
+
--color-muted: var(--muted);
|
|
20
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
21
|
+
--color-border: var(--border);
|
|
22
|
+
--color-input: var(--input);
|
|
23
|
+
--color-ring: var(--ring);
|
|
24
|
+
--color-primary: var(--primary);
|
|
25
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
26
|
+
--color-secondary: var(--secondary);
|
|
27
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
28
|
+
--color-accent: var(--accent);
|
|
29
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
30
|
+
--color-success: var(--success);
|
|
31
|
+
--color-success-strong: var(--success-strong);
|
|
32
|
+
--color-success-foreground: var(--success-foreground);
|
|
33
|
+
--color-success-soft: var(--success-soft);
|
|
34
|
+
--color-error: var(--error);
|
|
35
|
+
--color-error-foreground: var(--error-foreground);
|
|
36
|
+
--color-error-soft: var(--error-soft);
|
|
37
|
+
--color-error-strong: var(--error-strong);
|
|
38
|
+
--color-warning: var(--warning);
|
|
39
|
+
--color-warning-strong: var(--warning-strong);
|
|
40
|
+
--color-warning-foreground: var(--warning-foreground);
|
|
41
|
+
--color-warning-soft: var(--warning-soft);
|
|
42
|
+
--color-disabled: var(--disabled);
|
|
43
|
+
--color-disabled-foreground: var(--disabled-foreground);
|
|
44
|
+
--color-skeleton-sheen: var(--skeleton-sheen);
|
|
45
|
+
|
|
46
|
+
/* — ПРЯМОЙ ДОСТУП КО ВСЕЙ ПАЛИТРЕ по «цветовым» именам (bg-blue, text-navy,
|
|
47
|
+
bg-sky, bg-green, bg-red, bg-gold …). Удобно, когда проще думать цветом.
|
|
48
|
+
Для обычного UI (фоны/текст/кнопки) лучше семантика (bg-primary, text-foreground)
|
|
49
|
+
— она адаптируется к теме; raw-цвета остаются неизменными. — */
|
|
50
|
+
--color-blue: var(--brand-blue);
|
|
51
|
+
--color-blue-light: var(--blue-light);
|
|
52
|
+
--color-blue-pressed: var(--blue-pressed);
|
|
53
|
+
--color-line-strong: var(--line-strong);
|
|
54
|
+
--color-navy: var(--deep-navy);
|
|
55
|
+
--color-cloud: var(--cloud-white);
|
|
56
|
+
--color-sky: var(--sky-mist);
|
|
57
|
+
--color-ice: var(--ice-blue);
|
|
58
|
+
--color-green: var(--connection-green);
|
|
59
|
+
--color-green-soft: var(--green-soft);
|
|
60
|
+
--color-red: var(--error-red);
|
|
61
|
+
--color-red-soft: var(--error-red-soft);
|
|
62
|
+
--color-red-dark: var(--error-red-dark);
|
|
63
|
+
--color-gold: var(--warning-gold);
|
|
64
|
+
--color-gold-soft: var(--gold-soft);
|
|
65
|
+
--color-disabled: var(--disabled-blue);
|
|
66
|
+
|
|
67
|
+
/* шрифты: --font-manrope и --font-geist-mono приходят из next/font в layout.tsx */
|
|
68
|
+
--font-sans: var(--font-manrope);
|
|
69
|
+
--font-mono: var(--font-geist-mono);
|
|
70
|
+
--font-display: var(--font-manrope);
|
|
71
|
+
|
|
72
|
+
/* шкала радиусов от базового --radius */
|
|
73
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
74
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
75
|
+
--radius-lg: var(--radius);
|
|
76
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
77
|
+
|
|
78
|
+
/* ============================================================
|
|
79
|
+
ТИПОГРАФИКА (Manrope). Каждая утилита ставит размер + line-height +
|
|
80
|
+
letter-spacing + вес разом: text-h1, text-body-l, text-button-m, text-caption …
|
|
81
|
+
letter-spacing -2% = -0.02em везде.
|
|
82
|
+
Заголовки и Body (L/M/S) — fluid через clamp() между 320px и 1280px,
|
|
83
|
+
Caption и Button — фиксированный размер. (комментарий справа: моб → десктоп, px)
|
|
84
|
+
============================================================ */
|
|
85
|
+
|
|
86
|
+
/* Заголовки — Bold (700), line-height 110% */
|
|
87
|
+
--text-h1: clamp(2.25rem, 1.833rem + 2.083vw, 3.5rem); /* 36 → 56 */
|
|
88
|
+
--text-h1--line-height: 1.1;
|
|
89
|
+
--text-h1--letter-spacing: -0.02em;
|
|
90
|
+
--text-h1--font-weight: 700;
|
|
91
|
+
--text-h2: clamp(1.875rem, 1.667rem + 1.042vw, 2.5rem); /* 30 → 40 */
|
|
92
|
+
--text-h2--line-height: 1.1;
|
|
93
|
+
--text-h2--letter-spacing: -0.02em;
|
|
94
|
+
--text-h2--font-weight: 700;
|
|
95
|
+
--text-h3: clamp(1.5rem, 1.333rem + 0.833vw, 2rem); /* 24 → 32 */
|
|
96
|
+
--text-h3--line-height: 1.1;
|
|
97
|
+
--text-h3--letter-spacing: -0.02em;
|
|
98
|
+
--text-h3--font-weight: 700;
|
|
99
|
+
--text-h4: clamp(1.25rem, 1.167rem + 0.417vw, 1.5rem); /* 20 → 24 */
|
|
100
|
+
--text-h4--line-height: 1.1;
|
|
101
|
+
--text-h4--letter-spacing: -0.02em;
|
|
102
|
+
--text-h4--font-weight: 700;
|
|
103
|
+
--text-h5: clamp(1.125rem, 1.083rem + 0.208vw, 1.25rem); /* 18 → 20 */
|
|
104
|
+
--text-h5--line-height: 1.1;
|
|
105
|
+
--text-h5--letter-spacing: -0.02em;
|
|
106
|
+
--text-h5--font-weight: 700;
|
|
107
|
+
|
|
108
|
+
/* Body — Medium (500), line-height 145% */
|
|
109
|
+
--text-body-l: clamp(1rem, 0.958rem + 0.208vw, 1.125rem); /* 16 → 18 */
|
|
110
|
+
--text-body-l--line-height: 1.45;
|
|
111
|
+
--text-body-l--letter-spacing: -0.02em;
|
|
112
|
+
--text-body-l--font-weight: 500;
|
|
113
|
+
--text-body-m: clamp(0.875rem, 0.833rem + 0.208vw, 1rem); /* 14 → 16 */
|
|
114
|
+
--text-body-m--line-height: 1.45;
|
|
115
|
+
--text-body-m--letter-spacing: -0.02em;
|
|
116
|
+
--text-body-m--font-weight: 500;
|
|
117
|
+
--text-body-s: clamp(0.75rem, 0.708rem + 0.208vw, 0.875rem); /* 12 → 14 */
|
|
118
|
+
--text-body-s--line-height: 1.45;
|
|
119
|
+
--text-body-s--letter-spacing: -0.02em;
|
|
120
|
+
--text-body-s--font-weight: 500;
|
|
121
|
+
|
|
122
|
+
/* Caption — Medium (500), 12px, line-height 145% */
|
|
123
|
+
--text-caption: 0.75rem; /* 12 */
|
|
124
|
+
--text-caption--line-height: 1.45;
|
|
125
|
+
--text-caption--letter-spacing: -0.02em;
|
|
126
|
+
--text-caption--font-weight: 500;
|
|
127
|
+
|
|
128
|
+
/* Buttons — SemiBold (600), line-height 100%. Fluid: клампятся 320→1280px (как body-*). */
|
|
129
|
+
--text-button-l: clamp(1rem, 0.958rem + 0.208vw, 1.125rem); /* 16 → 18 */
|
|
130
|
+
--text-button-l--line-height: 1;
|
|
131
|
+
--text-button-l--letter-spacing: -0.02em;
|
|
132
|
+
--text-button-l--font-weight: 600;
|
|
133
|
+
--text-button-m: clamp(0.875rem, 0.833rem + 0.208vw, 1rem); /* 14 → 16 */
|
|
134
|
+
--text-button-m--line-height: 1;
|
|
135
|
+
--text-button-m--letter-spacing: -0.02em;
|
|
136
|
+
--text-button-m--font-weight: 600;
|
|
137
|
+
--text-button-s: clamp(0.75rem, 0.708rem + 0.208vw, 0.875rem); /* 12 → 14 */
|
|
138
|
+
--text-button-s--line-height: 1;
|
|
139
|
+
--text-button-s--letter-spacing: -0.02em;
|
|
140
|
+
--text-button-s--font-weight: 600;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* Утилита фирменного градиента: bg-brand-gradient */
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/* Утилиты дизайн-системы: фирменный градиент, тонкий скроллбар и FLUID-размеры
|
|
2
|
+
(text-fl-14/18, p-fl-18/20 …) — плавный clamp между 320 и 1280px.
|
|
3
|
+
Источник: hallo/client — src/app/globals.css. Файл раздаётся пакетом @hallo/kit;
|
|
4
|
+
правки вносить ЗДЕСЬ, кабинет и сайты получают их обновлением пакета. */
|
|
5
|
+
|
|
6
|
+
@utility bg-brand-gradient {
|
|
7
|
+
background-image: var(--gradient-brand);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* Тонкий ненавязчивый скроллбар для overflow-контейнеров (webkit + firefox).
|
|
11
|
+
Системный «жирный» скроллбар наезжает на контент и выглядит грубо — этот узкий
|
|
12
|
+
(6px), трек прозрачный, бегунок — приглушённый bg-border со скруглением, ярче на
|
|
13
|
+
hover. Вешать класс `scrollbar-slim` на элемент с overflow-y-auto. */
|
|
14
|
+
@utility scrollbar-slim {
|
|
15
|
+
scrollbar-width: thin;
|
|
16
|
+
scrollbar-color: var(--color-border) transparent;
|
|
17
|
+
|
|
18
|
+
&::-webkit-scrollbar {
|
|
19
|
+
width: 10px;
|
|
20
|
+
height: 10px;
|
|
21
|
+
}
|
|
22
|
+
&::-webkit-scrollbar-track {
|
|
23
|
+
background: transparent;
|
|
24
|
+
}
|
|
25
|
+
/* Бегунок — «плавающая» скруглённая пилюля: прозрачная рамка 3px + background-clip
|
|
26
|
+
поджимают заливку внутрь дорожки (реальная ширина ~4px), поэтому виден зазор от
|
|
27
|
+
края и скругление читается, а не «выпирает» встык к контенту/скруглению карточки. */
|
|
28
|
+
&::-webkit-scrollbar-thumb {
|
|
29
|
+
border-radius: 9999px;
|
|
30
|
+
background-color: var(--color-border);
|
|
31
|
+
border: 3px solid transparent;
|
|
32
|
+
background-clip: padding-box;
|
|
33
|
+
}
|
|
34
|
+
&:hover::-webkit-scrollbar-thumb {
|
|
35
|
+
background-color: var(--color-muted-foreground);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Динамический fluid-размер шрифта: text-fl-{минPx}/{максPx} между 320px и 1280px.
|
|
40
|
+
Напр. text-fl-14/18 — плавно 14 в 18px; clamp считается прямо в CSS, без предрасчёта.
|
|
41
|
+
Для размеров дизайн-системы бери именованные (text-h1 … text-body-s) — они с
|
|
42
|
+
готовыми line-height/letter-spacing/весом; эта утилита — для разовых случаев. */
|
|
43
|
+
@utility text-fl-* {
|
|
44
|
+
font-size: clamp(
|
|
45
|
+
calc(--value(integer) * 1px),
|
|
46
|
+
calc(
|
|
47
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
48
|
+
(100vw - 320px) / 960
|
|
49
|
+
),
|
|
50
|
+
calc(--modifier(integer) * 1px)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Динамический fluid-spacing: <свойство>-fl-{минPx}/{максPx} между 320px и 1280px.
|
|
55
|
+
Тот же приём, что у text-fl. Напр. gap-fl-12/24, px-fl-16/32, mt-fl-8/20, m-fl-16/40.
|
|
56
|
+
--fl-clamp — общая формула clamp(min, наклон·vw + база, max), считается в CSS. */
|
|
57
|
+
@utility gap-fl-* {
|
|
58
|
+
gap: clamp(
|
|
59
|
+
calc(--value(integer) * 1px),
|
|
60
|
+
calc(
|
|
61
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
62
|
+
(100vw - 320px) / 960
|
|
63
|
+
),
|
|
64
|
+
calc(--modifier(integer) * 1px)
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
@utility gap-x-fl-* {
|
|
68
|
+
column-gap: clamp(
|
|
69
|
+
calc(--value(integer) * 1px),
|
|
70
|
+
calc(
|
|
71
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
72
|
+
(100vw - 320px) / 960
|
|
73
|
+
),
|
|
74
|
+
calc(--modifier(integer) * 1px)
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
@utility gap-y-fl-* {
|
|
78
|
+
row-gap: clamp(
|
|
79
|
+
calc(--value(integer) * 1px),
|
|
80
|
+
calc(
|
|
81
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
82
|
+
(100vw - 320px) / 960
|
|
83
|
+
),
|
|
84
|
+
calc(--modifier(integer) * 1px)
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
@utility p-fl-* {
|
|
88
|
+
padding: clamp(
|
|
89
|
+
calc(--value(integer) * 1px),
|
|
90
|
+
calc(
|
|
91
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
92
|
+
(100vw - 320px) / 960
|
|
93
|
+
),
|
|
94
|
+
calc(--modifier(integer) * 1px)
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
@utility px-fl-* {
|
|
98
|
+
padding-inline: clamp(
|
|
99
|
+
calc(--value(integer) * 1px),
|
|
100
|
+
calc(
|
|
101
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
102
|
+
(100vw - 320px) / 960
|
|
103
|
+
),
|
|
104
|
+
calc(--modifier(integer) * 1px)
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
@utility py-fl-* {
|
|
108
|
+
padding-block: clamp(
|
|
109
|
+
calc(--value(integer) * 1px),
|
|
110
|
+
calc(
|
|
111
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
112
|
+
(100vw - 320px) / 960
|
|
113
|
+
),
|
|
114
|
+
calc(--modifier(integer) * 1px)
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
/* Fluid-высота-«пол» и квадрат: min-h-fl-{min}/{max}, size-fl-{min}/{max}. Для
|
|
118
|
+
контролов, чтобы высота/квадрат тоже клампились (а не держались фиксом). */
|
|
119
|
+
@utility min-h-fl-* {
|
|
120
|
+
min-height: clamp(
|
|
121
|
+
calc(--value(integer) * 1px),
|
|
122
|
+
calc(
|
|
123
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
124
|
+
(100vw - 320px) / 960
|
|
125
|
+
),
|
|
126
|
+
calc(--modifier(integer) * 1px)
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
@utility size-fl-* {
|
|
130
|
+
width: clamp(
|
|
131
|
+
calc(--value(integer) * 1px),
|
|
132
|
+
calc(
|
|
133
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
134
|
+
(100vw - 320px) / 960
|
|
135
|
+
),
|
|
136
|
+
calc(--modifier(integer) * 1px)
|
|
137
|
+
);
|
|
138
|
+
height: clamp(
|
|
139
|
+
calc(--value(integer) * 1px),
|
|
140
|
+
calc(
|
|
141
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
142
|
+
(100vw - 320px) / 960
|
|
143
|
+
),
|
|
144
|
+
calc(--modifier(integer) * 1px)
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
@utility h-fl-* {
|
|
148
|
+
height: clamp(
|
|
149
|
+
calc(--value(integer) * 1px),
|
|
150
|
+
calc(
|
|
151
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
152
|
+
(100vw - 320px) / 960
|
|
153
|
+
),
|
|
154
|
+
calc(--modifier(integer) * 1px)
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
@utility w-fl-* {
|
|
158
|
+
width: clamp(
|
|
159
|
+
calc(--value(integer) * 1px),
|
|
160
|
+
calc(
|
|
161
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
162
|
+
(100vw - 320px) / 960
|
|
163
|
+
),
|
|
164
|
+
calc(--modifier(integer) * 1px)
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
/* Fluid translateX через ту же механику, что у Tailwind (--tw-translate-x + translate). */
|
|
168
|
+
@utility translate-x-fl-* {
|
|
169
|
+
--tw-translate-x: clamp(
|
|
170
|
+
calc(--value(integer) * 1px),
|
|
171
|
+
calc(
|
|
172
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
173
|
+
(100vw - 320px) / 960
|
|
174
|
+
),
|
|
175
|
+
calc(--modifier(integer) * 1px)
|
|
176
|
+
);
|
|
177
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
178
|
+
}
|
|
179
|
+
@utility pt-fl-* {
|
|
180
|
+
padding-top: clamp(
|
|
181
|
+
calc(--value(integer) * 1px),
|
|
182
|
+
calc(
|
|
183
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
184
|
+
(100vw - 320px) / 960
|
|
185
|
+
),
|
|
186
|
+
calc(--modifier(integer) * 1px)
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
@utility pr-fl-* {
|
|
190
|
+
padding-right: clamp(
|
|
191
|
+
calc(--value(integer) * 1px),
|
|
192
|
+
calc(
|
|
193
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
194
|
+
(100vw - 320px) / 960
|
|
195
|
+
),
|
|
196
|
+
calc(--modifier(integer) * 1px)
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
@utility pb-fl-* {
|
|
200
|
+
padding-bottom: clamp(
|
|
201
|
+
calc(--value(integer) * 1px),
|
|
202
|
+
calc(
|
|
203
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
204
|
+
(100vw - 320px) / 960
|
|
205
|
+
),
|
|
206
|
+
calc(--modifier(integer) * 1px)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
@utility pl-fl-* {
|
|
210
|
+
padding-left: clamp(
|
|
211
|
+
calc(--value(integer) * 1px),
|
|
212
|
+
calc(
|
|
213
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
214
|
+
(100vw - 320px) / 960
|
|
215
|
+
),
|
|
216
|
+
calc(--modifier(integer) * 1px)
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
@utility m-fl-* {
|
|
220
|
+
margin: clamp(
|
|
221
|
+
calc(--value(integer) * 1px),
|
|
222
|
+
calc(
|
|
223
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
224
|
+
(100vw - 320px) / 960
|
|
225
|
+
),
|
|
226
|
+
calc(--modifier(integer) * 1px)
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
@utility mx-fl-* {
|
|
230
|
+
margin-inline: clamp(
|
|
231
|
+
calc(--value(integer) * 1px),
|
|
232
|
+
calc(
|
|
233
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
234
|
+
(100vw - 320px) / 960
|
|
235
|
+
),
|
|
236
|
+
calc(--modifier(integer) * 1px)
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
@utility my-fl-* {
|
|
240
|
+
margin-block: clamp(
|
|
241
|
+
calc(--value(integer) * 1px),
|
|
242
|
+
calc(
|
|
243
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
244
|
+
(100vw - 320px) / 960
|
|
245
|
+
),
|
|
246
|
+
calc(--modifier(integer) * 1px)
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
@utility mt-fl-* {
|
|
250
|
+
margin-top: clamp(
|
|
251
|
+
calc(--value(integer) * 1px),
|
|
252
|
+
calc(
|
|
253
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
254
|
+
(100vw - 320px) / 960
|
|
255
|
+
),
|
|
256
|
+
calc(--modifier(integer) * 1px)
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
@utility mr-fl-* {
|
|
260
|
+
margin-right: clamp(
|
|
261
|
+
calc(--value(integer) * 1px),
|
|
262
|
+
calc(
|
|
263
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
264
|
+
(100vw - 320px) / 960
|
|
265
|
+
),
|
|
266
|
+
calc(--modifier(integer) * 1px)
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
@utility mb-fl-* {
|
|
270
|
+
margin-bottom: clamp(
|
|
271
|
+
calc(--value(integer) * 1px),
|
|
272
|
+
calc(
|
|
273
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
274
|
+
(100vw - 320px) / 960
|
|
275
|
+
),
|
|
276
|
+
calc(--modifier(integer) * 1px)
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
@utility ml-fl-* {
|
|
280
|
+
margin-left: clamp(
|
|
281
|
+
calc(--value(integer) * 1px),
|
|
282
|
+
calc(
|
|
283
|
+
--value(integer) * 1px + (--modifier(integer) - --value(integer)) *
|
|
284
|
+
(100vw - 320px) / 960
|
|
285
|
+
),
|
|
286
|
+
calc(--modifier(integer) * 1px)
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|