From bb4cf3f06e97af2e257ee6efa8b3b51c3ccf260b Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Thu, 30 Jul 2026 20:27:44 +0300 Subject: [PATCH 01/60] =?UTF-8?q?feat:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=82?= =?UTF-8?q?=D0=BE=D1=80=20=D0=B4=D0=B8=D0=B7=D0=B0=D0=B9=D0=BD-=D1=82?= =?UTF-8?q?=D0=BE=D0=BA=D0=B5=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eslint.config.ts | 4 + package.json | 8 +- scripts/token-generator/README.md | 102 +++++ .../__tests__/compiler.test.ts | 353 ++++++++++++++++++ scripts/token-generator/build.ts | 84 +++++ scripts/token-generator/core/compiler.ts | 206 ++++++++++ scripts/token-generator/core/normalization.ts | 151 ++++++++ scripts/token-generator/core/resolution.ts | 99 +++++ scripts/token-generator/core/tree.ts | 49 +++ scripts/token-generator/core/types.ts | 26 ++ scripts/token-generator/core/validation.ts | 81 ++++ scripts/token-generator/io.ts | 109 ++++++ scripts/token-generator/tsconfig.json | 11 + yarn.lock | 3 +- 14 files changed, 1284 insertions(+), 2 deletions(-) create mode 100644 scripts/token-generator/README.md create mode 100644 scripts/token-generator/__tests__/compiler.test.ts create mode 100644 scripts/token-generator/build.ts create mode 100644 scripts/token-generator/core/compiler.ts create mode 100644 scripts/token-generator/core/normalization.ts create mode 100644 scripts/token-generator/core/resolution.ts create mode 100644 scripts/token-generator/core/tree.ts create mode 100644 scripts/token-generator/core/types.ts create mode 100644 scripts/token-generator/core/validation.ts create mode 100644 scripts/token-generator/io.ts create mode 100644 scripts/token-generator/tsconfig.json diff --git a/eslint.config.ts b/eslint.config.ts index 8b9966fb..29583883 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -5,6 +5,10 @@ import { MobileConfig } from './configs/eslint' export default defineConfig([ ...MobileConfig, { files: ['configs/eslint/**/*'], rules: { 'max-lines': 'off' } }, + { + files: ['scripts/**/*.ts'], + rules: { 'import-x/no-nodejs-modules': 'off' }, + }, { ignores: [ 'node_modules/**/*', diff --git a/package.json b/package.json index fc50f07e..3710f509 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,17 @@ } }, "scripts": { - "build": "rm -rf dist && tsc -p tsconfig.build.json", + "build": "yarn tokens:validate && rm -rf dist && tsc -p tsconfig.build.json", "test": "jest", "start": "expo start --dev-client --clear", "android": "expo run:android", "ios": "expo run:ios --no-install", "storybook-generate": "sb-rn-get-stories --config-path .storybook && sed -i -e 's/export const view = global.view/export const view: ReturnType = global.view/' .storybook/storybook.requires.ts && prettier .storybook --write", + "tokens:generate": "ts-node --project scripts/token-generator/tsconfig.json scripts/token-generator/build.ts && yarn tokens:format", + "tokens:format": "prettier 'design-tokens/input/*.json' 'src/theme/tokens/**/*.json' --write", + "tokens:check": "ts-node --project scripts/token-generator/tsconfig.json scripts/token-generator/build.ts --check", + "tokens:typecheck": "tsc --noEmit -p scripts/token-generator/tsconfig.json", + "tokens:validate": "yarn tokens:typecheck && yarn tokens:check", "doctor": "expo-doctor", "check": "expo install --check", "lint:check": "eslint --cache .", @@ -75,6 +80,7 @@ "@testing-library/react-native": "13.3.3", "@types/jest": "29.5.14", "@types/lodash.map": "4.6.13", + "@types/node": "22.7.7", "@types/react": "19.2.14", "babel-loader": "8.2.3", "chalk": "4.1.2", diff --git a/scripts/token-generator/README.md b/scripts/token-generator/README.md new file mode 100644 index 00000000..bbe25f0b --- /dev/null +++ b/scripts/token-generator/README.md @@ -0,0 +1,102 @@ +# Генератор токенов + +Генератор преобразует входные токены из Figma в JSON для React Native. + +## Обновление токенов + +1. Обновить `design-tokens/input/tokens.json`. +2. Запустить `yarn tokens:generate`. +3. Проверить изменения в `src/theme/tokens`. +4. Запустить `yarn tokens:validate`. +5. Закоммитить входные и сгенерированные токены вместе. + +`tokens:generate` записывает и форматирует файлы. `tokens:validate` ничего не +меняет: проверяет TypeScript генератора и актуальность сгенерированных токенов. + +## Использование в компонентах + +Внутри UI Kit используются component-токены: + +```ts +StyleSheet.create(({ components }) => ({ + header: { + backgroundColor: components.accordion.colorScheme.header.background, + }, +})) +``` + +Semantic-токены доступны потребителям библиотеки в `semantic`. Unistyles +подставляет соответствующие light- или dark-токены при переключении темы. + +## Результат генерации + +Из `design-tokens/input/tokens.json` создаются четыре файла: + +```text +src/theme/tokens +├── semantic +│ ├── light.json +│ └── dark.json +└── components + ├── light.json + └── dark.json +``` + +Для каждого выходного файла выбирается соответствующая ветка `colorScheme.light` +или `colorScheme.dark`. Ключ `colorScheme` сохраняется, а уровень `light`/`dark` +удаляется: + +```text +semantic.colorScheme.light.color +→ semantic/light.json: colorScheme.color + +components.button.colorScheme.light.outlined +→ components/light.json: button.colorScheme.outlined +``` + +`primitive` нужен только для подстановки ссылок и не записывается в результат. +Light- и dark-файлы должны иметь одинаковую структуру и типы значений. + +## Преобразование значений + +Ссылки разрешаются до нормализации. Поддерживаются ссылки на всё значение и +вставки внутри строк: + +```text +"{dimension.space.400}" -> "0.875rem" -> 14 + +"inset 0 0 0 {dimension.focusRing.width} {colors.solid.green.200}" +-> "inset 0 0 0 4px #d4fedc" +``` + +```text +"1.5rem" -> 24 +"150ms" -> 150 +"0" -> 0 +``` + +CSS shorthand из 2–4 значений раскрывается в поля React Native: + +```text +padding: "8 14" +-> paddingTop: 8 +-> paddingRight: 14 +-> paddingBottom: 8 +-> paddingLeft: 14 +``` + +Генерация завершается с ошибкой при отсутствующей или циклической ссылке, +неподдерживаемом shorthand, оставшихся `rem`/`ms`, `NaN` или `Infinity`. + +## Автоматические проверки + +`yarn tokens:validate` запускается при сборке, в CI и перед push. Если +сгенерированные файлы устарели, нужно выполнить `yarn tokens:generate` и +проверить diff. + +## Устройство генератора + +Для изменения генератора: `core/compiler.ts` собирает темы, `core/resolution.ts` +разрешает ссылки, `core/normalization.ts` преобразует значения, +`core/validation.ts` проверяет результат. CLI и запись файлов находятся в +`build.ts` и `io.ts`. diff --git a/scripts/token-generator/__tests__/compiler.test.ts b/scripts/token-generator/__tests__/compiler.test.ts new file mode 100644 index 00000000..a0be0dc4 --- /dev/null +++ b/scripts/token-generator/__tests__/compiler.test.ts @@ -0,0 +1,353 @@ +import { readdirSync, mkdtempSync, writeFileSync, rmSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' + +import { + INPUT_DIRECTORY, + INPUT_FILE, + TOKENS_DIRECTORY, + parseArgs, +} from '../build' +import { compileTokens } from '../core/compiler' +import { convertUnit, parseBoxShorthand } from '../core/normalization' +import { resolveReferences } from '../core/resolution' +import { + isTokenTree, + type CompiledTokens, + type TokenTree, + type TokenValue, +} from '../core/types' +import { + OUTPUT_FILES, + findStaleGeneratedTokens, + loadTokenTree, + writeGeneratedTokens, +} from '../io' + +const listJsonFiles = (directory: string, prefix = ''): string[] => + readdirSync(directory, { withFileTypes: true }) + .flatMap((entry) => { + const relativePath = join(prefix, entry.name) + + return entry.isDirectory() + ? listJsonFiles(join(directory, entry.name), relativePath) + : entry.name.endsWith('.json') + ? [relativePath] + : [] + }) + .sort() + +const containsColorSchemeThemeBranch = (node: TokenValue): boolean => { + if (Array.isArray(node)) return node.some(containsColorSchemeThemeBranch) + + if (!isTokenTree(node)) return false + + return Object.entries(node).some(([key, value]) => { + if ( + key === 'colorScheme' && + isTokenTree(value) && + ('light' in value || 'dark' in value) + ) { + return true + } + + return containsColorSchemeThemeBranch(value) + }) +} + +describe('token compiler', () => { + describe('convertUnit', () => { + test.each([ + { name: 'положительный rem', value: '1.5rem', expected: 24 }, + { name: 'отрицательный rem', value: '-0.5rem', expected: -8 }, + { name: 'миллисекунды', value: '150ms', expected: 150 }, + { name: 'строковый ноль', value: '0', expected: 0 }, + { + name: 'rem внутри составной строки', + value: 'inset 0 0 0 0.25rem #fff', + expected: 'inset 0 0 0 4px #fff', + }, + { name: 'обычная строка', value: 'auto', expected: 'auto' }, + ])('$name преобразуется в ожидаемое значение', ({ value, expected }) => { + expect(convertUnit(value)).toBe(expected) + }) + }) + + describe('parseBoxShorthand', () => { + test.each([ + { + name: 'одно значение', + value: '8', + expected: { top: 8, right: 8, bottom: 8, left: 8 }, + }, + { + name: 'два значения', + value: '8 14', + expected: { top: 8, right: 14, bottom: 8, left: 14 }, + }, + { + name: 'три значения', + value: '8 14 10', + expected: { top: 8, right: 14, bottom: 10, left: 14 }, + }, + { + name: 'четыре значения с rem', + value: '0rem 1.5rem 0.875rem 1.5rem', + expected: { top: 0, right: 24, bottom: 14, left: 24 }, + }, + ])('$name раскрывается по правилам CSS', ({ value, expected }) => { + expect(parseBoxShorthand(value)).toStrictEqual(expected) + }) + + test.each([ + { name: 'пустая строка', value: '', message: 'Expected 1-4 box values' }, + { + name: 'пять значений', + value: '1 2 3 4 5', + message: 'Expected 1-4 box values', + }, + { + name: 'неподдерживаемая единица', + value: '1px 2px', + message: 'Invalid box value', + }, + { + name: 'нечисловое значение', + value: 'auto', + message: 'Invalid box value', + }, + ])('$name отклоняется', ({ value, message }) => { + expect(() => parseBoxShorthand(value)).toThrow(message) + }) + }) + + test('разделяет один источник на темы, разрешает ссылки и нормализует значения', () => { + const source: TokenTree = { + primitive: { + sizing: { small: '0.5rem', base: '1rem' }, + motion: { fast: '150ms' }, + }, + semantic: { + dimension: { + spacing: { small: '{sizing.small}', base: '{sizing.base}' }, + }, + effects: { duration: '{motion.fast}' }, + colorScheme: { + light: { color: { text: '#111111' } }, + dark: { color: { text: '#eeeeee' } }, + }, + }, + components: { + demo: { + extend: { + padding: '{dimension.spacing.small} {dimension.spacing.base}', + }, + root: { + margin: '{dimension.spacing.base}', + duration: '{effects.duration}', + borderWidth: '0rem 0rem {dimension.spacing.small} 0rem', + }, + icon: { size: '{dimension.spacing.base}' }, + colorScheme: { + light: { color: '{color.text}' }, + dark: { color: '{color.text}' }, + }, + }, + }, + } + + const compiled = compileTokens(source) + + expect(compiled).not.toHaveProperty('primitive') + expect(compiled.semantic).toStrictEqual({ + light: { + colorScheme: { color: { text: '#111111' } }, + dimension: { spacing: { small: 8, base: 16 } }, + effects: { duration: 150 }, + }, + dark: { + colorScheme: { color: { text: '#eeeeee' } }, + dimension: { spacing: { small: 8, base: 16 } }, + effects: { duration: 150 }, + }, + }) + expect(compiled.components.light).toStrictEqual({ + demo: { + extend: { + paddingTop: 8, + paddingRight: 16, + paddingBottom: 8, + paddingLeft: 16, + }, + root: { + margin: 16, + duration: 150, + borderTopWidth: 0, + borderRightWidth: 0, + borderBottomWidth: 8, + borderLeftWidth: 0, + }, + icon: { size: 16 }, + colorScheme: { color: '#111111' }, + }, + }) + expect(compiled.components.dark.demo).toHaveProperty( + 'colorScheme.color', + '#eeeeee' + ) + expect(compiled.components.light.demo).not.toHaveProperty( + 'colorScheme.light' + ) + expect(compiled.components.dark.demo).not.toHaveProperty('colorScheme.dark') + }) + + test('отклоняет источник без одной из цветовых схем semantic', () => { + const source: TokenTree = { + primitive: {}, + semantic: { colorScheme: { light: {} } }, + components: {}, + } + + expect(() => compileTokens(source)).toThrow( + 'Expected an object at "semantic.colorScheme.dark"' + ) + }) + + test('отклоняет циклические ссылки', () => { + const references: TokenTree = { first: '{second}', second: '{first}' } + + expect(() => resolveReferences('{first}', references)).toThrow( + 'Circular token reference' + ) + }) +}) + +describe('production input tokens', () => { + const source = loadTokenTree(INPUT_FILE) + const compiled: CompiledTokens = compileTokens(source) + + test('использует единственный входной tokens-файл', () => { + const tokenFiles = readdirSync(INPUT_DIRECTORY) + .filter((fileName) => /\.json$/.test(fileName)) + .sort() + + expect(tokenFiles).toStrictEqual(['tokens.json']) + }) + + test('не экспортирует primitive и убирает разделение тем из colorScheme', () => { + expect(Object.keys(compiled)).toStrictEqual(['semantic', 'components']) + expect(compiled).not.toHaveProperty('primitive') + + const inputComponents = source.components + const lightOutputComponents = compiled.components.light + const darkOutputComponents = compiled.components.dark + + if ( + !isTokenTree(inputComponents) || + !isTokenTree(inputComponents.button) || + !isTokenTree(lightOutputComponents.button) + ) { + throw new Error('Expected component namespaces') + } + + expect(Object.keys(lightOutputComponents).sort()).toStrictEqual( + Object.keys(inputComponents).sort() + ) + expect(Object.keys(darkOutputComponents).sort()).toStrictEqual( + Object.keys(inputComponents).sort() + ) + expect(lightOutputComponents.button).toHaveProperty('extend') + expect(lightOutputComponents.button).toHaveProperty('root') + expect(lightOutputComponents.button).toHaveProperty('colorScheme') + expect(darkOutputComponents.button).toHaveProperty('colorScheme') + expect(compiled.semantic.light).toHaveProperty('colorScheme.color') + expect(compiled.semantic.dark).toHaveProperty('colorScheme.color') + expect( + [ + compiled.semantic.light, + compiled.semantic.dark, + compiled.components.light, + compiled.components.dark, + ].filter(containsColorSchemeThemeBranch) + ).toHaveLength(0) + }) + + test('содержит только целевые файлы', () => { + const tokenFiles = listJsonFiles(TOKENS_DIRECTORY) + const expectedFiles = Object.values(OUTPUT_FILES) + .flatMap((group) => Object.values(group)) + .sort() + + expect(tokenFiles).toStrictEqual(expectedFiles) + }) + + test('не содержит неразрешённых ссылок и CSS-единиц', () => { + const serialized = JSON.stringify(compiled) + + expect(serialized).not.toMatch(/\{[a-z][^}]*\}/i) + expect(serialized).not.toMatch(/-?\d*\.?\d+(?:rem|ms)\b/) + }) + + test('совпадает с закоммиченными сгенерированными токенами', () => { + expect(findStaleGeneratedTokens(compiled, TOKENS_DIRECTORY)).toStrictEqual( + [] + ) + }) + + test('component-токены содержат выбранную схему на исходных путях', () => { + expect(compiled.components.light.accordion).toHaveProperty('root') + expect(compiled.components.light.accordion).toHaveProperty('extend') + expect(compiled.components.light.accordion).toHaveProperty( + 'colorScheme.header.background' + ) + expect(compiled.components.dark.accordion).toHaveProperty( + 'colorScheme.header.background' + ) + }) + + test('после записи повторная проверка не находит изменений', () => { + const temporaryDirectory = mkdtempSync(join(tmpdir(), 'token-generator-')) + + try { + writeGeneratedTokens(compiled, temporaryDirectory) + + expect(listJsonFiles(temporaryDirectory)).toStrictEqual( + Object.values(OUTPUT_FILES) + .flatMap((group) => Object.values(group)) + .sort() + ) + expect( + findStaleGeneratedTokens(compiled, temporaryDirectory) + ).toStrictEqual([]) + + writeFileSync(join(temporaryDirectory, 'common.json'), '{}\n') + + expect(findStaleGeneratedTokens(compiled, temporaryDirectory)).toContain( + 'common.json' + ) + + writeFileSync( + join(temporaryDirectory, OUTPUT_FILES.semantic.light), + '{}\n' + ) + + expect(findStaleGeneratedTokens(compiled, temporaryDirectory)).toContain( + OUTPUT_FILES.semantic.light + ) + } finally { + rmSync(temporaryDirectory, { recursive: true, force: true }) + } + }) +}) + +describe('token generator CLI', () => { + test('распознаёт check-режим', () => { + expect(parseArgs(['--check'])).toStrictEqual({ check: true, help: false }) + }) + + test('отклоняет неизвестный аргумент', () => { + expect(() => parseArgs(['--unknown'])).toThrow( + 'Неизвестный аргумент "--unknown"' + ) + }) +}) diff --git a/scripts/token-generator/build.ts b/scripts/token-generator/build.ts new file mode 100644 index 00000000..d4fb1510 --- /dev/null +++ b/scripts/token-generator/build.ts @@ -0,0 +1,84 @@ +import { resolve, join } from 'node:path' + +import { compileTokens } from './core/compiler' +import type { CompiledTokens } from './core/types' +import { + findStaleGeneratedTokens, + loadTokenTree, + writeGeneratedTokens, +} from './io' + +export const DESIGN_TOKENS_DIRECTORY = resolve(__dirname, '../../design-tokens') +export const INPUT_DIRECTORY = join(DESIGN_TOKENS_DIRECTORY, 'input') +export const TOKENS_DIRECTORY = resolve(__dirname, '../../src/theme/tokens') +export const INPUT_FILE = join(INPUT_DIRECTORY, 'tokens.json') + +interface CliOptions { + check: boolean + help: boolean +} + +const HELP = `Использование: + yarn tokens:generate + yarn tokens:check + +Опции: + --check проверить актуальность сгенерированных токенов без записи + --help показать эту справку` + +export const parseArgs = (arguments_: string[]): CliOptions => { + const options: CliOptions = { check: false, help: false } + + for (const argument of arguments_) { + if (argument === '--check') options.check = true + else if (argument === '--help') options.help = true + else { + throw new Error(`Неизвестный аргумент "${argument}"`) + } + } + + return options +} + +export const compileInputTokens = (): CompiledTokens => + compileTokens(loadTokenTree(INPUT_FILE)) + +export const run = (arguments_: string[]): void => { + const options = parseArgs(arguments_) + + if (options.help) { + console.log(HELP) + + return + } + + const compiled = compileInputTokens() + + if (options.check) { + const staleFiles = findStaleGeneratedTokens(compiled, TOKENS_DIRECTORY) + + if (staleFiles.length > 0) { + throw new Error( + `Сгенерированные токены устарели: ${staleFiles.join(', ')}. ` + + 'Запустите yarn tokens:generate.' + ) + } + + console.log('Сгенерированные токены актуальны.') + + return + } + + writeGeneratedTokens(compiled, TOKENS_DIRECTORY) + console.log(`Сгенерированные токены записаны в ${TOKENS_DIRECTORY}`) +} + +if (require.main === module) { + try { + run(process.argv.slice(2)) + } catch (error: unknown) { + const message = error instanceof Error ? error.message : String(error) + console.error(message) + process.exitCode = 1 + } +} diff --git a/scripts/token-generator/core/compiler.ts b/scripts/token-generator/core/compiler.ts new file mode 100644 index 00000000..1c57644a --- /dev/null +++ b/scripts/token-generator/core/compiler.ts @@ -0,0 +1,206 @@ +import { normalizeTree } from './normalization' +import { resolveReferences } from './resolution' +import { mergeTrees, resolvePath } from './tree' +import { + isTokenTree, + type CompiledTokens, + type ThemeTokens, + type TokenTree, + type TokenValue, +} from './types' +import { assertSameShape, assertValidOutput } from './validation' + +type ColorScheme = keyof ThemeTokens + +const compileGroup = ( + input: TokenValue, + group: 'semantic' | 'components', + scheme: 'light' | 'dark' +): TokenTree => { + const normalized = normalizeTree(input, group) + + if (!isTokenTree(normalized)) { + throw new Error( + `Expected an object at "${group}" in ${scheme} input tokens` + ) + } + + assertValidOutput(normalized, `${scheme}.${group}`) + + return normalized +} + +const getGroup = ( + source: TokenTree, + group: 'primitive' | 'semantic' | 'components' +): TokenTree => { + const value = resolvePath(source, group) + + if (!isTokenTree(value)) { + throw new Error(`Expected an object at "${group}" in input tokens`) + } + + return value +} + +const selectColorScheme = ( + group: TokenTree, + scheme: ColorScheme, + tokenPath: string +): TokenTree => { + const { colorScheme } = group + const selectedScheme = isTokenTree(colorScheme) + ? colorScheme[scheme] + : undefined + + if (!isTokenTree(selectedScheme)) { + throw new Error( + `Expected an object at "${tokenPath}.colorScheme.${scheme}"` + ) + } + + return Object.fromEntries( + Object.entries(group).map(([key, value]) => [ + key, + key === 'colorScheme' ? mergeTrees({}, selectedScheme) : value, + ]) + ) +} + +const selectComponentColorSchemes = ( + components: TokenTree, + scheme: ColorScheme +): TokenTree => + Object.fromEntries( + Object.entries(components).map(([componentName, component]) => { + if (!isTokenTree(component)) { + throw new Error(`Expected an object at "components.${componentName}"`) + } + + const { colorScheme, ...base } = component + + if (colorScheme === undefined) { + return [componentName, mergeTrees({}, base)] + } + + const selectedScheme = isTokenTree(colorScheme) + ? colorScheme[scheme] + : undefined + + if (!isTokenTree(selectedScheme)) { + throw new Error( + `Expected an object at "components.${componentName}.colorScheme.${scheme}"` + ) + } + + return [ + componentName, + Object.fromEntries( + Object.entries(component).map(([key, value]) => [ + key, + key === 'colorScheme' ? mergeTrees({}, selectedScheme) : value, + ]) + ), + ] + }) + ) + +const unwrapColorScheme = (group: TokenTree, tokenPath: string): TokenTree => { + const { colorScheme, ...base } = group + + if (!isTokenTree(colorScheme)) { + throw new Error(`Expected an object at "${tokenPath}.colorScheme"`) + } + + return mergeTrees(base, colorScheme) +} + +const createReferenceRoot = ( + primitive: TokenTree, + semantic: TokenTree +): TokenTree => { + const duplicateKeys = Object.keys(primitive).filter((key) => key in semantic) + + if (duplicateKeys.length > 0) { + throw new Error( + `Duplicate primitive and semantic namespaces: ${duplicateKeys.join(', ')}` + ) + } + + return { ...primitive, ...semantic } +} + +const compileScheme = ( + primitive: TokenTree, + semanticSource: TokenTree, + componentsSource: TokenTree, + scheme: ColorScheme +): { semantic: TokenTree; components: TokenTree } => { + const selectedSemantic = selectColorScheme(semanticSource, scheme, 'semantic') + const semanticForReferences = unwrapColorScheme(selectedSemantic, 'semantic') + const semanticReferences = createReferenceRoot( + primitive, + semanticForReferences + ) + const resolvedSemanticForReferences = resolveReferences( + semanticForReferences, + semanticReferences, + `${scheme}.semantic` + ) + const resolvedSemantic = resolveReferences( + selectedSemantic, + semanticReferences, + `${scheme}.semantic` + ) + + if ( + !isTokenTree(resolvedSemantic) || + !isTokenTree(resolvedSemanticForReferences) + ) { + throw new Error(`Expected resolved semantic tokens for "${scheme}"`) + } + + const componentReferences = createReferenceRoot( + primitive, + resolvedSemanticForReferences + ) + const selectedComponents = selectComponentColorSchemes( + componentsSource, + scheme + ) + const resolvedComponents = resolveReferences( + selectedComponents, + componentReferences, + `${scheme}.components` + ) + + return { + semantic: compileGroup(resolvedSemantic, 'semantic', scheme), + components: compileGroup(resolvedComponents, 'components', scheme), + } +} + +export const compileTokens = (source: TokenTree): CompiledTokens => { + const primitive = getGroup(source, 'primitive') + const semanticSource = getGroup(source, 'semantic') + const componentsSource = getGroup(source, 'components') + const light = compileScheme( + primitive, + semanticSource, + componentsSource, + 'light' + ) + const dark = compileScheme( + primitive, + semanticSource, + componentsSource, + 'dark' + ) + const semantic = { light: light.semantic, dark: dark.semantic } + const components = { light: light.components, dark: dark.components } + + assertSameShape(semantic.light, semantic.dark) + assertSameShape(components.light, components.dark) + + return { semantic, components } +} diff --git a/scripts/token-generator/core/normalization.ts b/scripts/token-generator/core/normalization.ts new file mode 100644 index 00000000..6856ba86 --- /dev/null +++ b/scripts/token-generator/core/normalization.ts @@ -0,0 +1,151 @@ +import { + isTokenTree, + type BoxEdges, + type TokenPrimitive, + type TokenTree, + type TokenValue, +} from './types' + +const REM_BASE = 16 +export const BOX_PROPERTIES = ['padding', 'margin', 'borderWidth'] as const + +export type BoxProperty = (typeof BOX_PROPERTIES)[number] + +export const convertUnit = (value: TokenPrimitive): TokenPrimitive => { + if (typeof value !== 'string') return value + + const isRem = /^-?\d*\.?\d+rem$/.test(value) + + if (isRem) return Number(value.slice(0, -3)) * REM_BASE + + const isMilliseconds = /^-?\d*\.?\d+ms$/.test(value) + + if (isMilliseconds) return Number(value.slice(0, -2)) + + if (value === '0') return 0 + + return value.replace(/-?\d*\.?\d+rem\b/g, (token) => { + const pixels = Number(token.slice(0, -3)) * REM_BASE + + return `${pixels}px` + }) +} + +const parseBoxPart = (part: string, tokenPath: string): number => { + if (!/^-?\d*\.?\d+(?:rem)?$/.test(part)) { + throw new Error(`Invalid box value "${part}" at "${tokenPath}"`) + } + + const isRem = part.endsWith('rem') + const value = Number(isRem ? part.slice(0, -3) : part) + const normalized = isRem ? value * REM_BASE : value + + if (!Number.isFinite(normalized)) { + throw new Error(`Non-finite box value "${part}" at "${tokenPath}"`) + } + + return normalized +} + +export const parseBoxShorthand = ( + value: string | number, + tokenPath = 'box' +): BoxEdges => { + const parts = + typeof value === 'number' + ? [value] + : value + .trim() + .split(/\s+/) + .filter(Boolean) + .map((part) => parseBoxPart(part, tokenPath)) + + if (parts.length === 0 || parts.length > 4) { + throw new Error(`Expected 1-4 box values at "${tokenPath}"`) + } + + const [top, right = top, bottom = top, left = right] = parts + + if ( + top === undefined || + right === undefined || + bottom === undefined || + left === undefined + ) { + throw new Error(`Unable to expand box value at "${tokenPath}"`) + } + + return { top, right, bottom, left } +} + +const edgePropertyName = ( + property: BoxProperty, + edge: keyof BoxEdges +): string => { + const capitalizedEdge = `${edge[0].toUpperCase()}${edge.slice(1)}` + + return property === 'borderWidth' + ? `border${capitalizedEdge}Width` + : `${property}${capitalizedEdge}` +} + +const assignBoxEdges = ( + target: TokenTree, + source: TokenTree, + property: BoxProperty, + edges: BoxEdges, + tokenPath: string +): void => { + for (const [edge, edgeValue] of Object.entries(edges) as Array< + [keyof BoxEdges, number] + >) { + const edgeKey = edgePropertyName(property, edge) + + if (edgeKey in source || edgeKey in target) { + throw new Error(`Duplicate generated token "${tokenPath}.${edgeKey}"`) + } + + target[edgeKey] = edgeValue + } +} + +export const normalizeTree = ( + node: TokenValue, + tokenPath = 'root' +): TokenValue => { + if (Array.isArray(node)) { + return node.map((item, index) => + normalizeTree(item, `${tokenPath}.${index}`) + ) + } + + if (!isTokenTree(node)) return convertUnit(node) + + const normalized: TokenTree = {} + + for (const [key, value] of Object.entries(node)) { + const currentPath = `${tokenPath}.${key}` + const boxProperty = BOX_PROPERTIES.find((property) => property === key) + + if ( + boxProperty && + (typeof value === 'string' || typeof value === 'number') + ) { + const edges = parseBoxShorthand(value, currentPath) + const partCount = + typeof value === 'number' + ? 1 + : value.trim().split(/\s+/).filter(Boolean).length + + if (partCount === 1) { + normalized[key] = edges.top + } else { + assignBoxEdges(normalized, node, boxProperty, edges, currentPath) + } + } else { + normalized[key] = normalizeTree(value, currentPath) + } + } + + return normalized +} diff --git a/scripts/token-generator/core/resolution.ts b/scripts/token-generator/core/resolution.ts new file mode 100644 index 00000000..42078ff6 --- /dev/null +++ b/scripts/token-generator/core/resolution.ts @@ -0,0 +1,99 @@ +import { resolvePath } from './tree' +import { isTokenTree, type TokenTree, type TokenValue } from './types' + +const EXACT_REFERENCE_PATTERN = /^\{[^{}]+\}$/ +const REFERENCE_PATTERN = /\{[^{}]+\}/g + +const stringifyReference = ( + value: TokenValue, + reference: string, + tokenPath: string +): string => { + if (value === null || Array.isArray(value) || isTokenTree(value)) { + throw new Error( + `Reference "${reference}" at "${tokenPath}" cannot be embedded in a string` + ) + } + + return String(value) +} + +export const resolveReferences = ( + node: TokenValue, + referenceRoot: TokenTree, + tokenPath = 'root' +): TokenValue => { + const cache = new Map() + + const resolveReference = ( + reference: string, + sourcePath: string, + stack: string[] + ): TokenValue => { + if (stack.includes(reference)) { + throw new Error( + `Circular token reference at "${sourcePath}": ${[ + ...stack, + reference, + ].join(' -> ')}` + ) + } + + const cached = cache.get(reference) + + if (cached !== undefined) return cached + + const referencedValue = resolvePath( + referenceRoot, + reference, + `references for "${sourcePath}"` + ) + const resolved = resolveNode(referencedValue, reference, [ + ...stack, + reference, + ]) + + cache.set(reference, resolved) + + return resolved + } + + const resolveNode = ( + value: TokenValue, + currentPath: string, + stack: string[] + ): TokenValue => { + if (Array.isArray(value)) { + return value.map((item, index) => + resolveNode(item, `${currentPath}.${index}`, stack) + ) + } + + if (isTokenTree(value)) { + return Object.fromEntries( + Object.entries(value).map(([key, nestedValue]) => [ + key, + resolveNode(nestedValue, `${currentPath}.${key}`, stack), + ]) + ) + } + + if (typeof value !== 'string') return value + + if (EXACT_REFERENCE_PATTERN.test(value)) { + return resolveReference(value.slice(1, -1), currentPath, stack) + } + + return value.replace(REFERENCE_PATTERN, (token) => { + const reference = token.slice(1, -1) + + return stringifyReference( + resolveReference(reference, currentPath, stack), + reference, + currentPath + ) + }) + } + + return resolveNode(node, tokenPath, []) +} diff --git a/scripts/token-generator/core/tree.ts b/scripts/token-generator/core/tree.ts new file mode 100644 index 00000000..e8141baa --- /dev/null +++ b/scripts/token-generator/core/tree.ts @@ -0,0 +1,49 @@ +import { isTokenTree, type TokenTree, type TokenValue } from './types' + +const cloneValue = (value: TokenValue): TokenValue => { + if (Array.isArray(value)) return value.map(cloneValue) + + if (isTokenTree(value)) { + return Object.fromEntries( + Object.entries(value).map(([key, nestedValue]) => [ + key, + cloneValue(nestedValue), + ]) + ) + } + + return value +} + +export const mergeTrees = (base: TokenTree, override: TokenTree): TokenTree => { + const result = cloneValue(base) as TokenTree + + for (const [key, value] of Object.entries(override)) { + const current = result[key] + + result[key] = + isTokenTree(current) && isTokenTree(value) + ? mergeTrees(current, value) + : cloneValue(value) + } + + return result +} + +export const resolvePath = ( + source: TokenTree, + tokenPath: string, + context = 'input tokens' +): TokenValue => { + let current: TokenValue = source + + for (const segment of tokenPath.split('.')) { + if (!isTokenTree(current) || !(segment in current)) { + throw new Error(`Missing "${tokenPath}" in ${context}`) + } + + current = current[segment] + } + + return current +} diff --git a/scripts/token-generator/core/types.ts b/scripts/token-generator/core/types.ts new file mode 100644 index 00000000..2c98a251 --- /dev/null +++ b/scripts/token-generator/core/types.ts @@ -0,0 +1,26 @@ +export type TokenPrimitive = string | number | boolean | null +export type TokenValue = TokenPrimitive | TokenTree | TokenValue[] + +export interface TokenTree { + [key: string]: TokenValue +} + +export interface BoxEdges { + top: number + right: number + bottom: number + left: number +} + +export interface CompiledTokens { + semantic: ThemeTokens + components: ThemeTokens +} + +export interface ThemeTokens { + light: TokenTree + dark: TokenTree +} + +export const isTokenTree = (value: unknown): value is TokenTree => + typeof value === 'object' && value !== null && !Array.isArray(value) diff --git a/scripts/token-generator/core/validation.ts b/scripts/token-generator/core/validation.ts new file mode 100644 index 00000000..3e02b946 --- /dev/null +++ b/scripts/token-generator/core/validation.ts @@ -0,0 +1,81 @@ +import { BOX_PROPERTIES, type BoxProperty } from './normalization' +import { isTokenTree, type TokenTree, type TokenValue } from './types' + +const REFERENCE_PATTERN = /\{[^}]+\}/ +const UNCONVERTED_UNIT_PATTERN = /-?\d*\.?\d+(?:rem|ms)\b/ + +export const assertValidOutput = ( + node: TokenValue, + tokenPath: string +): void => { + if (Array.isArray(node)) { + node.forEach((item, index) => + assertValidOutput(item, `${tokenPath}.${index}`) + ) + + return + } + + if (isTokenTree(node)) { + for (const [key, value] of Object.entries(node)) { + if ( + BOX_PROPERTIES.includes(key as BoxProperty) && + typeof value === 'string' + ) { + throw new Error(`Unconverted box shorthand at "${tokenPath}.${key}"`) + } + + assertValidOutput(value, `${tokenPath}.${key}`) + } + + return + } + + if (typeof node === 'number' && !Number.isFinite(node)) { + throw new Error(`Non-finite number at "${tokenPath}"`) + } + + if ( + typeof node === 'string' && + (REFERENCE_PATTERN.test(node) || UNCONVERTED_UNIT_PATTERN.test(node)) + ) { + throw new Error(`Unconverted token "${node}" at "${tokenPath}"`) + } +} + +const collectShape = ( + node: TokenValue, + tokenPath = 'root', + shape: string[] = [] +): string[] => { + if (Array.isArray(node)) { + shape.push(`${tokenPath}:array`) + node.forEach((item, index) => + collectShape(item, `${tokenPath}.${index}`, shape) + ) + + return shape + } + + if (isTokenTree(node)) { + shape.push(`${tokenPath}:object`) + Object.entries(node).forEach(([key, value]) => + collectShape(value, `${tokenPath}.${key}`, shape) + ) + + return shape + } + + shape.push(`${tokenPath}:${node === null ? 'null' : typeof node}`) + + return shape +} + +export const assertSameShape = (light: TokenTree, dark: TokenTree): void => { + const lightShape = collectShape(light).sort() + const darkShape = collectShape(dark).sort() + + if (JSON.stringify(lightShape) !== JSON.stringify(darkShape)) { + throw new Error('Light and dark runtime tokens have different shapes') + } +} diff --git a/scripts/token-generator/io.ts b/scripts/token-generator/io.ts new file mode 100644 index 00000000..d4c0e85f --- /dev/null +++ b/scripts/token-generator/io.ts @@ -0,0 +1,109 @@ +import { + readFileSync, + readdirSync, + mkdirSync, + writeFileSync, + renameSync, + existsSync, +} from 'node:fs' +import { dirname, join } from 'node:path' +import { isDeepStrictEqual } from 'node:util' + +import { isTokenTree, type CompiledTokens, type TokenTree } from './core/types' + +export const OUTPUT_FILES = { + semantic: { + light: join('semantic', 'light.json'), + dark: join('semantic', 'dark.json'), + }, + components: { + light: join('components', 'light.json'), + dark: join('components', 'dark.json'), + }, +} as const + +export const parseTokenTree = ( + contents: string, + filePath: string +): TokenTree => { + const parsed: unknown = JSON.parse(contents) + + if (!isTokenTree(parsed)) { + throw new Error(`Expected an object in "${filePath}"`) + } + + return parsed +} + +export const loadTokenTree = (filePath: string): TokenTree => + parseTokenTree(readFileSync(filePath, 'utf8'), filePath) + +export const renderJson = (value: TokenTree): string => + `${JSON.stringify(value, null, 2)}\n` + +const outputEntries = ( + compiled: CompiledTokens +): Array<[string, TokenTree]> => [ + [OUTPUT_FILES.semantic.light, compiled.semantic.light], + [OUTPUT_FILES.semantic.dark, compiled.semantic.dark], + [OUTPUT_FILES.components.light, compiled.components.light], + [OUTPUT_FILES.components.dark, compiled.components.dark], +] + +export const writeGeneratedTokens = ( + compiled: CompiledTokens, + outputDirectory: string +): void => { + mkdirSync(outputDirectory, { recursive: true }) + + for (const [fileName, value] of outputEntries(compiled)) { + const outputPath = join(outputDirectory, fileName) + const temporaryPath = `${outputPath}.tmp` + + mkdirSync(dirname(outputPath), { recursive: true }) + writeFileSync(temporaryPath, renderJson(value)) + renameSync(temporaryPath, outputPath) + } +} + +const findJsonFiles = (directory: string, prefix = ''): string[] => { + if (!existsSync(directory)) return [] + + return readdirSync(directory, { withFileTypes: true }) + .flatMap((entry) => { + const relativePath = join(prefix, entry.name) + + if (entry.isDirectory()) { + return findJsonFiles(join(directory, entry.name), relativePath) + } + + return entry.isFile() && entry.name.endsWith('.json') + ? [relativePath] + : [] + }) + .sort() +} + +export const findStaleGeneratedTokens = ( + compiled: CompiledTokens, + outputDirectory: string +): string[] => { + const entries = outputEntries(compiled) + const expectedFiles = new Set(entries.map(([fileName]) => fileName)) + const staleFiles = entries + .filter(([fileName, value]) => { + const outputPath = join(outputDirectory, fileName) + + return ( + !existsSync(outputPath) || + !isDeepStrictEqual(loadTokenTree(outputPath), value) + ) + }) + .map(([fileName]) => fileName) + + const unexpectedFiles = findJsonFiles(outputDirectory).filter( + (fileName) => !expectedFiles.has(fileName) + ) + + return [...staleFiles, ...unexpectedFiles] +} diff --git a/scripts/token-generator/tsconfig.json b/scripts/token-generator/tsconfig.json new file mode 100644 index 00000000..e2005382 --- /dev/null +++ b/scripts/token-generator/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "noEmit": true, + "types": ["jest", "node"] + }, + "include": ["**/*.ts"], + "exclude": [] +} diff --git a/yarn.lock b/yarn.lock index 3ec08e23..d17ddfa0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2841,6 +2841,7 @@ __metadata: "@testing-library/react-native": "npm:13.3.3" "@types/jest": "npm:29.5.14" "@types/lodash.map": "npm:4.6.13" + "@types/node": "npm:22.7.7" "@types/react": "npm:19.2.14" babel-loader: "npm:8.2.3" chalk: "npm:4.1.2" @@ -6088,7 +6089,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*": +"@types/node@npm:*, @types/node@npm:22.7.7": version: 22.7.7 resolution: "@types/node@npm:22.7.7" dependencies: From e52c2f74ba2b295c8d29f18a6e5f701ba51db513 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Thu, 30 Jul 2026 20:28:07 +0300 Subject: [PATCH 02/60] =?UTF-8?q?ci:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B4=D0=B8=D0=B7=D0=B0=D0=B9=D0=BD-=D1=82?= =?UTF-8?q?=D0=BE=D0=BA=D0=B5=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/typecheck/action.yml | 8 ++++++-- lefthook.yml | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/actions/typecheck/action.yml b/.github/actions/typecheck/action.yml index be5114d9..9c14c2dd 100644 --- a/.github/actions/typecheck/action.yml +++ b/.github/actions/typecheck/action.yml @@ -1,5 +1,5 @@ -name: Run Typecheck -description: Run typecheck +name: Run Typechecks +description: Typecheck the project and validate generated tokens runs: using: composite @@ -9,3 +9,7 @@ runs: - name: Run Typecheck shell: bash run: yarn tsc --noEmit + + - name: Validate Design Tokens + shell: bash + run: yarn tokens:validate diff --git a/lefthook.yml b/lefthook.yml index c0ea5595..849f2579 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -73,3 +73,5 @@ pre-push: run: npx yarn eslint . type-check: run: npx yarn tsc --noEmit + tokens-validate: + run: npx yarn tokens:validate From b49dc2faca64b743c7acde7b896ecc3494f3e89d Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Thu, 30 Jul 2026 20:28:27 +0300 Subject: [PATCH 03/60] =?UTF-8?q?feat:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B8=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D0=B4=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D0=B9=D0=BD-=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/README.md | 6 + design-tokens/input/tokens.json | 5220 +++++++++++++++++++++ src/theme/__tests__/ThemeContext.test.tsx | 15 + src/theme/darkTheme.ts | 4 + src/theme/lightTheme.ts | 4 + src/theme/tokens/README.md | 9 + src/theme/tokens/components/dark.json | 2920 ++++++++++++ src/theme/tokens/components/light.json | 2920 ++++++++++++ src/theme/tokens/semantic/dark.json | 352 ++ src/theme/tokens/semantic/light.json | 352 ++ src/theme/types.ts | 4 + 11 files changed, 11806 insertions(+) create mode 100644 design-tokens/README.md create mode 100644 design-tokens/input/tokens.json create mode 100644 src/theme/tokens/README.md create mode 100644 src/theme/tokens/components/dark.json create mode 100644 src/theme/tokens/components/light.json create mode 100644 src/theme/tokens/semantic/dark.json create mode 100644 src/theme/tokens/semantic/light.json diff --git a/design-tokens/README.md b/design-tokens/README.md new file mode 100644 index 00000000..73d1cf5c --- /dev/null +++ b/design-tokens/README.md @@ -0,0 +1,6 @@ +# Design tokens + +`input/tokens.json` содержит входные токены из Figma, из которых генерируются +light- и dark-токены проекта. + +Подробности: [генератор токенов](../scripts/token-generator/README.md). diff --git a/design-tokens/input/tokens.json b/design-tokens/input/tokens.json new file mode 100644 index 00000000..16993284 --- /dev/null +++ b/design-tokens/input/tokens.json @@ -0,0 +1,5220 @@ +{ + "primitive": { + "colors": { + "alpha": { + "white": { + "10": "rgba(255, 255, 255, 0.0100)", + "40": "rgba(255, 255, 255, 0.0400)", + "50": "rgba(255, 255, 255, 0.0500)", + "60": "rgba(255, 255, 255, 0.0600)", + "100": "rgba(255, 255, 255, 0.1000)", + "160": "rgba(255, 255, 255, 0.1600)", + "200": "rgba(255, 255, 255, 0.2000)", + "300": "rgba(255, 255, 255, 0.3000)", + "400": "rgba(255, 255, 255, 0.4000)", + "500": "rgba(255, 255, 255, 0.5000)", + "600": "rgba(255, 255, 255, 0.6000)", + "700": "rgba(255, 255, 255, 0.7000)", + "800": "rgba(255, 255, 255, 0.8000)", + "870": "rgba(255, 255, 255, 0.8700)", + "900": "rgba(255, 255, 255, 0.9000)", + "1000": "#ffffff" + }, + "black": { + "40": "rgba(0, 0, 0, 0.0400)", + "100": "rgba(0, 0, 0, 0.1000)", + "200": "rgba(0, 0, 0, 0.2000)", + "300": "rgba(0, 0, 0, 0.3000)", + "400": "rgba(0, 0, 0, 0.4000)", + "500": "rgba(0, 0, 0, 0.5000)", + "600": "rgba(0, 0, 0, 0.6000)", + "700": "rgba(0, 0, 0, 0.7000)", + "800": "rgba(0, 0, 0, 0.8000)", + "900": "rgba(0, 0, 0, 0.9000)", + "1000": "#000000" + }, + "green": { + "40": "rgba(68, 232, 88, 0.04)", + "100": "rgba(68, 232, 88, 0.1)", + "200": "rgba(68, 232, 88, 0.2)", + "400": "rgba(68, 232, 88, 0.4)", + "600": "rgba(68, 232, 88, 0.6)" + }, + "blue": { + "40": "rgba(68, 150, 232, 0.04)", + "100": "rgba(68, 150, 232, 0.1)", + "200": "rgba(68, 150, 232, 0.2)", + "400": "rgba(68, 150, 232, 0.4)", + "600": "rgba(68, 150, 232, 0.6)" + }, + "yellow": { + "40": "rgba(245, 184, 61, 0.04)", + "100": "rgba(245, 184, 61, 0.1)", + "200": "rgba(245, 184, 61, 0.2)", + "400": "rgba(245, 184, 61, 0.4)", + "600": "rgba(245, 184, 61, 0.6)" + }, + "red": { + "40": "rgba(232, 82, 68, 0.04)", + "100": "rgba(232, 82, 68, 0.1)", + "200": "rgba(232, 82, 68, 0.2)", + "400": "rgba(232, 82, 68, 0.4)", + "600": "rgba(232, 82, 68, 0.6)" + } + }, + "solid": { + "purple": { + "50": "#faf5ff", + "100": "#f3e8ff", + "200": "#e9d5ff", + "300": "#d8b4fe", + "400": "#c084fc", + "500": "#a855f7", + "600": "#9333ea", + "700": "#7e22ce", + "800": "#6b21a8", + "900": "#581c87", + "950": "#3b0764" + }, + "fuchsia": { + "50": "#fdf4ff", + "100": "#fae8ff", + "200": "#f5d0fe", + "300": "#f0abfc", + "400": "#e879f9", + "500": "#d946ef", + "600": "#c026d3", + "700": "#a21caf", + "800": "#86198f", + "900": "#701a75", + "950": "#4a044e" + }, + "pink": { + "50": "#fdf2f8", + "100": "#fce7f3", + "200": "#fbcfe8", + "300": "#f9a8d4", + "400": "#f472b6", + "500": "#ec4899", + "600": "#db2777", + "700": "#be185d", + "800": "#9d174d", + "900": "#831843", + "950": "#500724" + }, + "rose": { + "50": "#fff1f2", + "100": "#ffe4e6", + "200": "#fecdd3", + "300": "#fda4af", + "400": "#fb7185", + "500": "#f43f5e", + "600": "#e11d48", + "700": "#be123c", + "800": "#9f1239", + "900": "#881337", + "950": "#4c0519" + }, + "teal": { + "50": "#f0fdfa", + "100": "#ccfbf1", + "200": "#99f6e4", + "300": "#5eead4", + "400": "#2dd4bf", + "500": "#14b8a6", + "600": "#0d9488", + "700": "#0f766e", + "800": "#115e59", + "900": "#134e4a", + "950": "#042f2e" + }, + "cyan": { + "50": "#ecfeff", + "100": "#cffafe", + "200": "#a5f3fc", + "300": "#67e8f9", + "400": "#22d3ee", + "500": "#06b6d4", + "600": "#0891b2", + "700": "#0e7490", + "800": "#155e75", + "900": "#164e63", + "950": "#013138" + }, + "sky": { + "50": "#f0f9ff", + "100": "#e0f2fe", + "200": "#bae6fd", + "300": "#7dd3fc", + "400": "#38bdf8", + "500": "#0ea5e9", + "600": "#0284c7", + "700": "#0369a1", + "800": "#075985", + "900": "#0c4a6e", + "950": "#082f49" + }, + "blue": { + "50": "#fafdff", + "100": "#f0f9ff", + "200": "#d4ecfe", + "300": "#aad7fb", + "400": "#77baf4", + "500": "#4496e8", + "600": "#1e76cd", + "700": "#18538d", + "800": "#123a61", + "900": "#0e2a45", + "950": "#0c243b" + }, + "indigo": { + "50": "#eef2ff", + "100": "#e0e7ff", + "200": "#c7d2fe", + "300": "#a5b4fc", + "400": "#818cf8", + "500": "#6366f1", + "600": "#4f46e5", + "700": "#4338ca", + "800": "#3730a3", + "900": "#312e81", + "950": "#1e1b4b" + }, + "violet": { + "50": "#fcfaff", + "100": "#f6f0ff", + "200": "#e5d4fe", + "300": "#cbaafb", + "400": "#b284f5", + "500": "#a265ec", + "600": "#9457ea", + "700": "#48188d", + "800": "#321261", + "900": "#240e45", + "950": "#1f0c3b" + }, + "emerald": { + "50": "#ecfdf5", + "100": "#d1fae5", + "200": "#a7f3d0", + "300": "#6ee7b7", + "400": "#34d399", + "500": "#10b981", + "600": "#059669", + "700": "#047857", + "800": "#065f46", + "900": "#064e3b", + "950": "#022c22" + }, + "green": { + "50": "#fafffb", + "100": "#f0fff3", + "200": "#d4fedc", + "300": "#aafbb7", + "400": "#77f48a", + "500": "#44e858", + "600": "#1dc831", + "700": "#168322", + "800": "#12611b", + "900": "#0e4514", + "950": "#0c3b11" + }, + "lime": { + "50": "#f7fee7", + "100": "#ecfccb", + "200": "#d9f99d", + "300": "#bef264", + "400": "#a3e635", + "500": "#84cc16", + "600": "#65a30d", + "700": "#4d7c0f", + "800": "#3f6212", + "900": "#365314", + "950": "#1a2e05" + }, + "red": { + "50": "#fffafa", + "100": "#fff0f0", + "200": "#fed4d4", + "300": "#fbacaa", + "400": "#f47f77", + "500": "#e85244", + "600": "#db3424", + "700": "#8d2218", + "800": "#611912", + "900": "#45120e", + "950": "#3b100c" + }, + "orange": { + "50": "#fffbfa", + "100": "#fff3f0", + "200": "#ffddd5", + "300": "#ffbca9", + "400": "#ff9273", + "500": "#fe6434", + "600": "#d53f0b", + "700": "#a83107", + "800": "#752506", + "900": "#561c05", + "950": "#4b1905" + }, + "amber": { + "50": "#fffbeb", + "100": "#fef3c7", + "200": "#fde68a", + "300": "#fcd34d", + "400": "#fbbf24", + "500": "#f59e0b", + "600": "#d97706", + "700": "#b45309", + "800": "#92400e", + "900": "#78350f", + "950": "#451a03" + }, + "yellow": { + "50": "#fffdfa", + "100": "#fff9f0", + "200": "#ffeed4", + "300": "#fddeaa", + "400": "#facb75", + "500": "#f5b83d", + "600": "#dc9710", + "700": "#9d6d0e", + "800": "#6d4c0b", + "900": "#4f3709", + "950": "#453008" + }, + "slate": { + "50": "#f8fafc", + "100": "#f1f5f9", + "200": "#e2e8f0", + "300": "#cbd5e1", + "400": "#94a3b8", + "500": "#64748b", + "600": "#475569", + "700": "#334155", + "800": "#1e293b", + "900": "#0f172a", + "950": "#020617" + }, + "gray": { + "50": "#f9fafb", + "100": "#f3f4f6", + "200": "#e5e7eb", + "300": "#d1d5db", + "400": "#9ca3af", + "500": "#6b7280", + "600": "#4b5563", + "700": "#374151", + "800": "#1f2937", + "900": "#111827", + "950": "#030712" + }, + "zinc": { + "50": "#fafafa", + "100": "#f0f0f1", + "200": "#e2e2e4", + "300": "#cecfd2", + "400": "#a2a5a9", + "500": "#85888e", + "600": "#6d7076", + "700": "#56595f", + "800": "#404348", + "900": "#2b2e33", + "950": "#181a1f" + }, + "neutral": { + "50": "#fafafa", + "100": "#f5f5f5", + "200": "#e5e5e5", + "300": "#d4d4d4", + "400": "#a3a3a3", + "500": "#737373", + "600": "#525252", + "700": "#404040", + "800": "#262626", + "900": "#171717", + "950": "#0a0a0a" + }, + "stone": { + "50": "#fafaf9", + "100": "#f5f5f4", + "200": "#e7e5e4", + "300": "#d6d3d1", + "400": "#a8a29e", + "500": "#78716c", + "600": "#57534e", + "700": "#44403c", + "800": "#292524", + "900": "#1c1917", + "950": "#0c0a09" + } + } + }, + "sizing": { + "none": "0rem", + "05x": "0.0625rem", + "1x": "0.125rem", + "2x": "0.25rem", + "3x": "0.375rem", + "4x": "0.5rem", + "5x": "0.625rem", + "6x": "0.75rem", + "7x": "0.875rem", + "8x": "1rem", + "9x": "1.125rem", + "10x": "1.25rem", + "12x": "1.5rem", + "13x": "1.625rem", + "14x": "1.75rem", + "16x": "2rem", + "18x": "2.25rem", + "19x": "2.375rem", + "21x": "2.625rem", + "23x": "2.875rem", + "24x": "3rem", + "26x": "3.25rem", + "28x": "3.5rem", + "30x": "3.75rem", + "32x": "4rem", + "33x": "4.125rem", + "35x": "4.375rem", + "42x": "5.25rem", + "49x": "6.125rem", + "50x": "6.25rem", + "56x": "7rem", + "63x": "7.875rem", + "70x": "8.75rem", + "77x": "9.625rem", + "84x": "10.5rem", + "91x": "11.375rem", + "98x": "12.25rem", + "105x": "13.125rem", + "112x": "14rem", + "119x": "14.875rem", + "126x": "15.75rem", + "133x": "16.625rem", + "140x": "17.5rem", + "147x": "18.375rem", + "154x": "19.25rem", + "161x": "20.125rem", + "168x": "21rem", + "175x": "21.875rem", + "182x": "22.75rem", + "189x": "23.625rem", + "196x": "24.5rem", + "203x": "25.375rem", + "210x": "26.25rem", + "238x": "29.75rem", + "288x": "36rem", + "315x": "39.375rem", + "350x": "43.75rem", + "378x": "47.25rem", + "384x": "48rem", + "406x": "50.75rem", + "420x": "52.5rem", + "496x": "62rem", + "600x": "75rem", + "700x": "87.5rem", + "max": "100rem", + "20x": "2.5rem", + "40x": "5rem", + "120x": "15rem", + "136x": "17rem", + "152x": "19rem", + "200x": "25rem" + }, + "fonts": { + "fontFamily": { "base": "Noto Sans", "heading": "TT Fellows" }, + "fontWeight": { + "regular": "400", + "medium": "500", + "demibold": "600", + "bold": "700" + }, + "fontSize": { + "100": "0.75rem", + "200": "0.875rem", + "300": "1rem", + "400": "1.125rem", + "500": "1.25rem", + "600": "1.5rem", + "650": "1.875rem", + "700": "2.25rem", + "750": "3rem", + "800": "3.75rem", + "900": "4.5rem", + "1000": "6rem" + }, + "lineHeight": { + "100": "0.75rem", + "150": "0.875rem", + "200": "0.875rem", + "250": "1rem", + "300": "1.125rem", + "350": "1.125rem", + "400": "1.25rem", + "450": "1.375rem", + "500": "1.5rem", + "550": "1.625rem", + "600": "1.75rem", + "700": "1.875rem", + "800": "2.25rem", + "850": "2.375rem", + "900": "2.75rem", + "1000": "3.375rem", + "none": "1", + "auto": "auto" + }, + "letterSpacing": { + "200": "-0.02rem", + "400": "-0.03rem", + "500": "0rem", + "600": "0.02rem", + "700": "0.03rem" + } + } + }, + "semantic": { + "colorScheme": { + "light": { + "color": { + "fg": { + "default": "{colors.solid.zinc.900}", + "hover": "{colors.solid.zinc.700}", + "active": "{colors.solid.zinc.950}", + "focus": "{colors.solid.zinc.900}", + "muted": "{colors.solid.zinc.500}", + "subtle": "{colors.solid.zinc.600}", + "brand": { + "default": "{colors.solid.green.500}", + "hover": "{colors.solid.green.600}", + "active": "{colors.solid.green.700}", + "disabled": "{colors.solid.green.300}", + "visited": "{colors.solid.green.800}", + "muted": "{colors.solid.green.400}" + }, + "inverse": { + "default": "{colors.alpha.white.1000}", + "hover": "{colors.alpha.white.1000}", + "active": "{colors.alpha.white.1000}", + "focus": "{colors.alpha.white.1000}", + "muted": "{colors.alpha.white.700}" + }, + "status": { + "danger": { + "default": "{colors.solid.red.500}", + "hover": "{colors.solid.red.600}", + "active": "{colors.solid.red.700}", + "disabled": "{colors.solid.red.300}", + "visited": "{colors.solid.red.800}", + "muted": "{colors.solid.red.400}" + }, + "info": { + "default": "{colors.solid.blue.500}", + "hover": "{colors.solid.blue.600}", + "active": "{colors.solid.blue.700}", + "disabled": "{colors.solid.blue.300}", + "visited": "{colors.solid.blue.800}", + "muted": "{colors.solid.blue.400}" + }, + "warning": { + "default": "{colors.solid.yellow.500}", + "hover": "{colors.solid.yellow.600}", + "active": "{colors.solid.yellow.700}", + "disabled": "{colors.solid.yellow.300}", + "visited": "{colors.solid.yellow.800}", + "muted": "{colors.solid.yellow.400}" + }, + "success": { + "default": "{colors.solid.green.500}", + "hover": "{colors.solid.green.600}", + "active": "{colors.solid.green.700}", + "disabled": "{colors.solid.green.300}", + "visited": "{colors.solid.green.800}", + "muted": "{colors.solid.green.400}" + }, + "help": { + "default": "{colors.solid.purple.500}", + "hover": "{colors.solid.purple.600}", + "active": "{colors.solid.purple.700}", + "disabled": "{colors.solid.purple.300}", + "visited": "{colors.solid.purple.800}", + "muted": "{colors.solid.purple.400}" + } + }, + "on": { + "brand": { + "default": "{colors.solid.zinc.900}", + "hover": "{colors.solid.zinc.900}", + "active": "{colors.solid.zinc.900}" + }, + "fill": { + "default": "{colors.alpha.white.1000}", + "hover": "{colors.alpha.white.1000}", + "active": "{colors.alpha.white.1000}", + "muted": "{colors.solid.zinc.200}" + }, + "status": { + "danger": { + "default": "{colors.solid.red.900}", + "hover": "{colors.solid.red.950}" + }, + "info": { + "default": "{colors.solid.blue.900}", + "hover": "{colors.solid.blue.950}" + }, + "warning": { + "default": "{colors.solid.yellow.900}", + "hover": "{colors.solid.yellow.950}" + }, + "success": { + "default": "{colors.solid.green.900}", + "hover": "{colors.solid.green.950}" + }, + "help": { + "default": "{colors.solid.purple.900}", + "hover": "{colors.solid.purple.950}" + } + } + } + }, + "bg": { + "status": { + "danger": { + "weak": { + "default": "{colors.solid.red.50}", + "hover": "{colors.solid.red.100}", + "active": "{colors.solid.red.200}" + }, + "strong": { + "default": "{colors.solid.red.300}", + "hover": "{colors.solid.red.400}", + "active": "{colors.solid.red.500}" + } + }, + "info": { + "weak": { + "default": "{colors.solid.blue.50}", + "hover": "{colors.solid.blue.100}", + "active": "{colors.solid.blue.200}" + }, + "strong": { + "default": "{colors.solid.blue.300}", + "hover": "{colors.solid.blue.400}", + "active": "{colors.solid.blue.500}" + } + }, + "warning": { + "weak": { + "default": "{colors.solid.yellow.50}", + "hover": "{colors.solid.yellow.100}", + "active": "{colors.solid.yellow.200}" + }, + "strong": { + "default": "{colors.solid.yellow.300}", + "hover": "{colors.solid.yellow.400}", + "active": "{colors.solid.yellow.500}" + } + }, + "success": { + "weak": { + "default": "{colors.solid.green.50}", + "hover": "{colors.solid.green.100}", + "active": "{colors.solid.green.200}" + }, + "strong": { + "default": "{colors.solid.green.300}", + "hover": "{colors.solid.green.400}", + "active": "{colors.solid.green.500}" + } + }, + "help": { + "weak": { + "default": "{colors.solid.purple.50}", + "hover": "{colors.solid.purple.100}", + "active": "{colors.solid.purple.200}" + }, + "strong": { + "default": "{colors.solid.purple.300}", + "hover": "{colors.solid.purple.400}", + "active": "{colors.solid.purple.500}" + } + } + }, + "brand": { + "weak": { + "hover": "{colors.solid.green.50}", + "active": "{colors.solid.green.100}" + }, + "strong": { + "default": "{colors.solid.green.500}", + "hover": "{colors.solid.green.600}", + "active": "{colors.solid.green.700}" + } + }, + "surface": { + "canvas": { + "default": "{colors.solid.zinc.100}", + "hover": "{colors.solid.zinc.200}", + "active": "{colors.solid.zinc.300}", + "selected": "{colors.solid.zinc.200}" + }, + "default": { + "default": "{colors.alpha.white.1000}", + "hover": "{colors.solid.zinc.50}", + "active": "{colors.solid.zinc.100}", + "selected": "{colors.solid.zinc.50}" + }, + "raised": { + "default": "{colors.alpha.white.1000}", + "hover": "{colors.solid.zinc.50}", + "active": "{colors.solid.zinc.100}", + "selected": "{colors.solid.zinc.50}" + }, + "overlay": { + "default": "{colors.alpha.white.1000}", + "hover": "{colors.solid.zinc.50}" + }, + "backdrop": "{colors.alpha.black.400}" + }, + "neutral": { + "weak": { + "default": "{colors.solid.zinc.100}", + "hover": "{colors.solid.zinc.200}", + "active": "{colors.solid.zinc.300}", + "disabled": "{colors.solid.zinc.200}" + }, + "medium": { + "default": "{colors.solid.zinc.200}", + "hover": "{colors.solid.zinc.300}", + "active": "{colors.solid.zinc.400}", + "strong": "{colors.solid.zinc.500}" + }, + "strong": { + "default": "{colors.solid.zinc.900}", + "hover": "{colors.solid.zinc.800}", + "active": "{colors.solid.zinc.700}", + "selected": "{colors.solid.zinc.900}" + } + } + }, + "border": { + "focus": "{colors.solid.green.200}", + "neutral": { + "default": "{colors.solid.zinc.200}", + "strong": "{colors.solid.zinc.300}", + "bold": { + "default": "{colors.solid.zinc.900}", + "hover": "{colors.solid.zinc.800}" + }, + "inverse": "{colors.alpha.white.1000}" + }, + "brand": { + "subtle": "{colors.solid.green.200}", + "default": "{colors.solid.green.500}", + "strong": "{colors.solid.green.600}" + }, + "status": { + "danger": { + "subtle": "{colors.solid.red.400}", + "default": "{colors.solid.red.500}", + "strong": "{colors.solid.red.600}" + }, + "info": { + "default": "{colors.solid.blue.500}", + "strong": "{colors.solid.blue.600}" + }, + "warning": { + "default": "{colors.solid.yellow.500}", + "strong": "{colors.solid.yellow.600}" + }, + "success": { + "default": "{colors.solid.green.500}", + "strong": "{colors.solid.green.600}" + }, + "help": { "strong": "{colors.solid.purple.600}" } + } + } + } + }, + "dark": { + "color": { + "fg": { + "default": "{colors.alpha.white.1000}", + "hover": "{colors.solid.zinc.300}", + "active": "{colors.solid.zinc.100}", + "focus": "{colors.alpha.white.1000}", + "muted": "{colors.solid.zinc.400}", + "subtle": "{colors.solid.zinc.400}", + "brand": { + "default": "{colors.solid.green.400}", + "hover": "{colors.solid.green.300}", + "active": "{colors.solid.green.200}", + "disabled": "{colors.solid.green.700}", + "visited": "{colors.solid.green.300}", + "muted": "{colors.solid.green.500}" + }, + "inverse": { + "default": "{colors.solid.zinc.900}", + "hover": "{colors.solid.zinc.700}", + "active": "{colors.solid.zinc.950}", + "focus": "{colors.solid.zinc.900}", + "muted": "{colors.solid.zinc.500}" + }, + "status": { + "danger": { + "default": "{colors.solid.red.400}", + "hover": "{colors.solid.red.300}", + "active": "{colors.solid.red.200}", + "disabled": "{colors.solid.red.700}", + "visited": "{colors.solid.red.300}", + "muted": "{colors.solid.red.500}" + }, + "info": { + "default": "{colors.solid.blue.400}", + "hover": "{colors.solid.blue.300}", + "active": "{colors.solid.blue.200}", + "disabled": "{colors.solid.blue.700}", + "visited": "{colors.solid.blue.300}", + "muted": "{colors.solid.blue.500}" + }, + "warning": { + "default": "{colors.solid.yellow.400}", + "hover": "{colors.solid.yellow.300}", + "active": "{colors.solid.yellow.200}", + "disabled": "{colors.solid.yellow.700}", + "visited": "{colors.solid.yellow.300}", + "muted": "{colors.solid.yellow.500}" + }, + "success": { + "default": "{colors.solid.green.400}", + "hover": "{colors.solid.green.300}", + "active": "{colors.solid.green.200}", + "disabled": "{colors.solid.green.700}", + "visited": "{colors.solid.green.300}", + "muted": "{colors.solid.green.500}" + }, + "help": { + "default": "{colors.solid.purple.400}", + "hover": "{colors.solid.purple.300}", + "active": "{colors.solid.purple.200}", + "disabled": "{colors.solid.purple.700}", + "visited": "{colors.solid.purple.300}", + "muted": "{colors.solid.purple.500}" + } + }, + "on": { + "brand": { + "default": "{colors.solid.zinc.900}", + "hover": "{colors.solid.zinc.900}", + "active": "{colors.solid.zinc.900}" + }, + "fill": { + "default": "{colors.alpha.white.1000}", + "hover": "{colors.alpha.white.1000}", + "active": "{colors.alpha.white.1000}", + "muted": "{colors.solid.zinc.200}" + }, + "status": { + "danger": { + "default": "{colors.solid.red.100}", + "hover": "{colors.solid.red.50}" + }, + "info": { + "default": "{colors.solid.blue.100}", + "hover": "{colors.solid.blue.50}" + }, + "warning": { + "default": "{colors.solid.yellow.100}", + "hover": "{colors.solid.yellow.50}" + }, + "success": { + "default": "{colors.solid.green.100}", + "hover": "{colors.solid.green.50}" + }, + "help": { + "default": "{colors.solid.purple.100}", + "hover": "{colors.solid.purple.50}" + } + } + } + }, + "bg": { + "status": { + "danger": { + "weak": { + "default": "{colors.solid.red.950}", + "hover": "{colors.solid.red.900}", + "active": "{colors.solid.red.800}" + }, + "strong": { + "default": "{colors.solid.red.700}", + "hover": "{colors.solid.red.600}", + "active": "{colors.solid.red.500}" + } + }, + "info": { + "weak": { + "default": "{colors.solid.blue.950}", + "hover": "{colors.solid.blue.900}", + "active": "{colors.solid.blue.800}" + }, + "strong": { + "default": "{colors.solid.blue.700}", + "hover": "{colors.solid.blue.600}", + "active": "{colors.solid.blue.500}" + } + }, + "warning": { + "weak": { + "default": "{colors.solid.yellow.950}", + "hover": "{colors.solid.yellow.900}", + "active": "{colors.solid.yellow.800}" + }, + "strong": { + "default": "{colors.solid.yellow.700}", + "hover": "{colors.solid.yellow.600}", + "active": "{colors.solid.yellow.500}" + } + }, + "success": { + "weak": { + "default": "{colors.solid.green.950}", + "hover": "{colors.solid.green.900}", + "active": "{colors.solid.green.800}" + }, + "strong": { + "default": "{colors.solid.green.700}", + "hover": "{colors.solid.green.600}", + "active": "{colors.solid.green.500}" + } + }, + "help": { + "weak": { + "default": "{colors.solid.purple.950}", + "hover": "{colors.solid.purple.900}", + "active": "{colors.solid.purple.800}" + }, + "strong": { + "default": "{colors.solid.purple.700}", + "hover": "{colors.solid.purple.600}", + "active": "{colors.solid.purple.500}" + } + } + }, + "brand": { + "weak": { + "hover": "{colors.solid.green.950}", + "active": "{colors.solid.green.900}" + }, + "strong": { + "default": "{colors.solid.green.500}", + "hover": "{colors.solid.green.400}", + "active": "{colors.solid.green.300}" + } + }, + "surface": { + "canvas": { + "default": "{colors.solid.zinc.900}", + "hover": "{colors.solid.zinc.800}", + "active": "{colors.solid.zinc.700}", + "selected": "{colors.solid.zinc.800}" + }, + "default": { + "default": "{colors.solid.zinc.800}", + "hover": "{colors.solid.zinc.700}", + "active": "{colors.solid.zinc.600}", + "selected": "{colors.solid.zinc.700}" + }, + "raised": { + "default": "{colors.solid.zinc.700}", + "hover": "{colors.solid.zinc.600}", + "active": "{colors.solid.zinc.500}", + "selected": "{colors.solid.zinc.600}" + }, + "overlay": { + "default": "{colors.solid.zinc.800}", + "hover": "{colors.solid.zinc.700}" + }, + "backdrop": "{colors.alpha.black.600}" + }, + "neutral": { + "weak": { + "default": "{colors.solid.zinc.900}", + "hover": "{colors.solid.zinc.800}", + "active": "{colors.solid.zinc.700}", + "disabled": "{colors.solid.zinc.800}" + }, + "medium": { + "default": "{colors.solid.zinc.800}", + "hover": "{colors.solid.zinc.700}", + "active": "{colors.solid.zinc.600}", + "strong": "{colors.solid.zinc.500}" + }, + "strong": { + "default": "{colors.solid.zinc.100}", + "hover": "{colors.solid.zinc.200}", + "active": "{colors.solid.zinc.300}", + "selected": "{colors.solid.zinc.100}" + } + } + }, + "border": { + "focus": "{colors.solid.green.200}", + "neutral": { + "default": "{colors.solid.zinc.800}", + "strong": "{colors.solid.zinc.700}", + "bold": { + "default": "{colors.solid.zinc.100}", + "hover": "{colors.solid.zinc.200}" + }, + "inverse": "{colors.solid.zinc.900}" + }, + "brand": { + "subtle": "{colors.solid.green.800}", + "default": "{colors.solid.green.500}", + "strong": "{colors.solid.green.400}" + }, + "status": { + "danger": { + "subtle": "{colors.solid.red.600}", + "default": "{colors.solid.red.500}", + "strong": "{colors.solid.red.400}" + }, + "info": { + "default": "{colors.solid.blue.500}", + "strong": "{colors.solid.blue.400}" + }, + "warning": { + "default": "{colors.solid.yellow.500}", + "strong": "{colors.solid.yellow.400}" + }, + "success": { + "default": "{colors.solid.green.500}", + "strong": "{colors.solid.green.400}" + }, + "help": { "strong": "{colors.solid.purple.400}" } + } + } + } + } + }, + "dimension": { + "space": { + "none": "{sizing.none}", + "100": "{sizing.2x}", + "150": "{sizing.3x}", + "200": "{sizing.4x}", + "300": "{sizing.5x}", + "400": "{sizing.7x}", + "500": "{sizing.9x}", + "600": "{sizing.10x}", + "700": "{sizing.12x}", + "800": "{sizing.14x}", + "negative": { + "50": "-0.125rem", + "200": "-0.5rem", + "300": "-0.75rem", + "600": "-1.5rem" + } + }, + "size": { + "none": "{sizing.none}", + "50": "{sizing.1x}", + "100": "{sizing.2x}", + "150": "{sizing.3x}", + "200": "{sizing.4x}", + "300": "{sizing.5x}", + "350": "{sizing.6x}", + "400": "{sizing.7x}", + "450": "{sizing.8x}", + "500": "{sizing.9x}", + "600": "{sizing.10x}", + "700": "{sizing.12x}", + "750": "{sizing.13x}", + "800": "{sizing.14x}", + "900": "{sizing.16x}", + "1000": "{sizing.18x}", + "1100": "{sizing.20x}", + "1200": "{sizing.24x}", + "1300": "{sizing.28x}", + "1400": "{sizing.32x}", + "1500": "{sizing.40x}", + "1600": "{sizing.120x}", + "1700": "{sizing.136x}", + "1800": "{sizing.152x}", + "1900": "{sizing.168x}", + "2000": "{sizing.200x}", + "max": "{sizing.max}" + }, + "borderRadius": { + "none": "{sizing.none}", + "100": "{sizing.2x}", + "200": "{sizing.4x}", + "300": "{sizing.5x}", + "400": "{sizing.7x}", + "500": "{sizing.10x}", + "max": "{sizing.max}" + }, + "borderWidth": { + "none": "{sizing.none}", + "100": "{sizing.05x}", + "200": "{sizing.1x}", + "300": "{sizing.2x}" + }, + "focusRing": { "width": "{sizing.2x}", "offset": "{sizing.none}" }, + "depth": { + "100": "1000", + "200": "1100", + "300": "1200", + "400": "1300", + "500": "1400", + "600": "1500", + "700": "1600" + }, + "viewport": { + "100": "{sizing.288x}", + "200": "{sizing.384x}", + "300": "{sizing.496x}", + "400": "{sizing.600x}", + "500": "{sizing.700x}" + } + }, + "effects": { + "opacity": { + "0": "0", + "4": "0.04", + "8": "0.08", + "12": "0.12", + "16": "0.16", + "20": "0.2", + "30": "0.3", + "40": "0.4", + "50": "0.5", + "60": "0.6", + "70": "0.7", + "80": "0.8", + "90": "0.9", + "100": "1" + }, + "blur": { + "none": "0", + "100": "4px", + "200": "8px", + "300": "16px", + "400": "24px" + }, + "transition": { + "easing": { + "linear": "linear", + "in": "cubic-bezier(0.55, 0.06, 0.7, 0.2)", + "out": "cubic-bezier(0.2, 0.6, 0.4, 1)", + "inOut": "cubic-bezier(0.65, 0.05, 0.35, 1)", + "standard": "cubic-bezier(0.2, 0, 0, 1)", + "accelerate": "cubic-bezier(0.3, 0, 1, 1)", + "decelerate": "cubic-bezier(0, 0, 0, 1)", + "emphasizedAccelerate": "cubic-bezier(0.3, 0, 0.8, 0.15)", + "emphasizedDecelerate": "cubic-bezier(0.05, 0.7, 0.1, 1)", + "spring": "cubic-bezier(0.34, 1.56, 0.64, 1)" + }, + "duration": { + "100": "140ms", + "200": "180ms", + "300": "240ms", + "400": "320ms", + "500": "400ms" + } + }, + "elevation": { + "none": "none", + "100": "0 0 2px {colors.alpha.black.200}", + "200": "0 0 4px {colors.alpha.black.200}", + "300": "0 2px 4px {colors.alpha.black.200}", + "400": "0 4px 8px {colors.alpha.black.200}", + "500": "0 8px 16px 0 {colors.alpha.black.200}", + "status": { + "info": "0px 4px 8px 0px {colors.alpha.blue.40}", + "success": "0px 4px 8px 0px {colors.alpha.green.40}", + "warning": "0px 4px 8px 0px {colors.alpha.yellow.40}", + "danger": "0px 4px 8px 0px {colors.alpha.red.40}", + "secondary": "0px 4px 8px 0px {colors.alpha.black.40}", + "contrast": "0px 4px 8px 0px {colors.alpha.black.40}" + } + }, + "focusRing": { + "shadow": "inset 0 0 0 {dimension.focusRing.width} {colors.solid.green.200}" + } + } + }, + "components": { + "accordion": { + "extend": { + "extHeader": { + "iconSize": "{dimension.size.600}", + "gap": "{dimension.space.200}" + } + }, + "colorScheme": { + "light": { + "header": { + "background": "transparent", + "hoverBackground": "transparent", + "activeBackground": "transparent", + "activeHoverBackground": "transparent" + } + }, + "dark": { + "header": { + "activeBackground": "transparent", + "activeHoverBackground": "transparent", + "background": "transparent", + "hoverBackground": "transparent" + } + } + }, + "header": { + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "activeColor": "{color.fg.default}", + "activeHoverColor": "{color.fg.hover}", + "borderColor": "transparent", + "padding": "{dimension.space.400} {dimension.space.none} {dimension.space.400} {dimension.space.none}", + "fontWeight": "{fonts.fontWeight.bold}", + "borderRadius": "{dimension.borderRadius.none}", + "borderWidth": "{dimension.borderWidth.none}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.focusRing.shadow}" + }, + "toggleIcon": { + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "activeColor": "{color.fg.default}", + "activeHoverColor": "{color.fg.hover}" + }, + "last": { + "bottomBorderRadius": "{dimension.borderRadius.none}", + "activeBottomBorderRadius": "{dimension.borderRadius.none}" + }, + "first": { + "borderWidth": "{dimension.borderWidth.none}", + "topBorderRadius": "{dimension.borderRadius.none}" + } + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" }, + "panel": { + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.300} {dimension.borderWidth.none}", + "borderColor": "{color.border.neutral.strong}" + }, + "content": { + "borderWidth": "{dimension.borderWidth.100} {dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.none}", + "borderColor": "transparent", + "background": "transparent", + "color": "{color.fg.default}", + "padding": "{dimension.space.none} {dimension.space.700} {dimension.space.400} {dimension.space.700}" + } + }, + "autocomplete": { + "extend": { + "extOption": { "gap": "{dimension.space.200}" }, + "extOptionGroup": { "gap": "{dimension.space.200}" } + }, + "colorScheme": { + "light": { + "chip": { + "focusBackground": "{color.bg.neutral.medium.default}", + "focusColor": "{color.fg.default}" + }, + "dropdown": { + "background": "{color.bg.surface.default.default}", + "hoverBackground": "{color.bg.surface.default.default}", + "activeBackground": "{color.bg.surface.default.default}", + "color": "{color.fg.active}", + "hoverColor": "{color.fg.active}", + "activeColor": "{color.fg.active}" + } + }, + "dark": { + "chip": { + "focusBackground": "{color.bg.neutral.strong.hover}", + "focusColor": "{color.fg.inverse.focus}" + }, + "dropdown": { + "activeBackground": "{color.bg.surface.default.default}", + "activeColor": "{color.fg.inverse.active}", + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.inverse.active}", + "hoverBackground": "{color.bg.surface.default.default}", + "hoverColor": "{color.fg.inverse.active}" + } + } + }, + "root": { + "background": "{color.bg.surface.default.default}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "filledBackground": "{color.bg.surface.default.default}", + "filledHoverBackground": "{color.bg.surface.default.default}", + "filledFocusBackground": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.strong}", + "hoverBorderColor": "{color.border.brand.strong}", + "focusBorderColor": "{color.border.brand.strong}", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "color": "{color.fg.active}", + "disabledColor": "{color.fg.muted}", + "placeholderColor": "{color.fg.muted}", + "invalidPlaceholderColor": "{color.fg.status.danger.hover}", + "shadow": "{effects.elevation.none}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}" + } + }, + "overlay": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "borderRadius": "{dimension.borderRadius.400}", + "color": "{color.fg.default}", + "shadow": "{effects.elevation.200}" + }, + "list": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}" + }, + "option": { + "focusBackground": "{color.bg.neutral.weak.default}", + "selectedBackground": "{color.bg.neutral.strong.selected}", + "selectedFocusBackground": "{color.bg.neutral.strong.active}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "selectedColor": "{color.fg.on.fill.default}", + "selectedFocusColor": "{color.fg.on.fill.active}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}" + }, + "optionGroup": { + "background": "{color.bg.surface.raised.default}", + "color": "{color.fg.muted}", + "fontWeight": "{fonts.fontWeight.demibold}", + "padding": "{dimension.space.200} {dimension.space.400}" + }, + "dropdown": { + "width": "{dimension.size.1700}", + "borderColor": "{color.border.neutral.strong}", + "hoverBorderColor": "{color.border.brand.strong}", + "activeBorderColor": "{color.border.brand.strong}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}" + }, + "sm": { "width": "{dimension.size.1600}" }, + "lg": { "width": "{dimension.size.1800}" } + }, + "chip": { "borderRadius": "{dimension.borderRadius.200}" }, + "emptyMessage": { + "padding": "{dimension.space.200} {dimension.space.400}" + } + }, + "avatar": { + "extend": { + "borderColor": "{color.border.neutral.strong}", + "circle": { "borderRadius": "{dimension.borderRadius.max}" } + }, + "root": { + "width": "{dimension.size.900}", + "height": "{dimension.size.900}", + "fontSize": "{fonts.fontSize.300}", + "color": "{color.fg.default}", + "background": "{color.bg.brand.strong.default}", + "borderRadius": "{dimension.borderRadius.400}" + }, + "icon": { "size": "{dimension.size.450}" }, + "group": { + "borderColor": "{color.border.neutral.inverse}", + "offset": "{dimension.space.negative.300}" + }, + "lg": { + "width": "{dimension.size.1100}", + "height": "{dimension.size.1100}", + "fontSize": "{fonts.fontSize.300}", + "icon": { "size": "{dimension.size.450}" }, + "group": { "offset": "{dimension.space.negative.300}" } + }, + "xl": { + "width": "{dimension.size.1300}", + "height": "{dimension.size.1300}", + "icon": { "size": "{dimension.size.700}" }, + "group": { "offset": "{dimension.space.negative.600}" }, + "fontSize": "{fonts.fontSize.300}" + } + }, + "badge": { + "extend": { + "extDot": { + "success": { "background": "{color.bg.status.success.strong.hover}" }, + "info": { "background": "{color.bg.status.info.strong.hover}" }, + "warn": { "background": "{color.bg.status.warning.strong.hover}" }, + "danger": { "background": "{color.bg.status.danger.strong.hover}" }, + "lg": { "size": "{dimension.size.350}" }, + "xlg": { "size": "{dimension.size.450}" } + }, + "ext": { "padding": "{dimension.space.none}" } + }, + "colorScheme": { + "light": { + "primary": { + "color": "{color.fg.default}", + "background": "{color.bg.brand.strong.default}" + }, + "secondary": { + "color": "{color.fg.on.fill.default}", + "background": "{color.bg.neutral.strong.default}" + }, + "success": { + "color": "{color.fg.on.status.success.default}", + "background": "{color.bg.status.success.strong.default}" + }, + "info": { + "color": "{color.fg.on.status.info.default}", + "background": "{color.bg.status.info.strong.default}" + }, + "warn": { + "color": "{color.fg.on.status.warning.default}", + "background": "{color.bg.status.warning.strong.default}" + }, + "danger": { + "color": "{color.fg.on.status.danger.default}", + "background": "{color.bg.status.danger.strong.default}" + }, + "contrast": { + "background": "{color.bg.neutral.strong.default}", + "color": "{color.fg.on.fill.default}" + } + }, + "dark": { + "contrast": { + "background": "{color.bg.surface.canvas.default}", + "color": "{color.fg.default}" + }, + "danger": { + "background": "{color.bg.status.danger.strong.default}", + "color": "{color.fg.on.status.danger.default}" + }, + "info": { + "background": "{color.bg.status.info.strong.default}", + "color": "{color.fg.on.status.info.default}" + }, + "primary": { + "background": "{color.bg.brand.strong.default}", + "color": "{color.fg.inverse.default}" + }, + "secondary": { + "background": "{color.bg.surface.canvas.default}", + "color": "{color.fg.default}" + }, + "success": { + "background": "{color.bg.brand.strong.active}", + "color": "{color.fg.on.status.success.default}" + }, + "warn": { + "background": "{color.bg.status.warning.strong.default}", + "color": "{color.fg.on.status.warning.default}" + } + } + }, + "root": { + "borderRadius": "{dimension.borderRadius.200}", + "padding": "{dimension.space.200}", + "fontSize": "{fonts.fontSize.100}", + "fontWeight": "{fonts.fontWeight.regular}", + "minWidth": "{dimension.size.700}", + "height": "{dimension.size.700}" + }, + "dot": { "size": "{dimension.size.200}" }, + "sm": { + "fontSize": "{fonts.fontSize.100}", + "minWidth": "{dimension.size.none}", + "height": "{dimension.size.none}" + }, + "lg": { + "fontSize": "{fonts.fontSize.100}", + "minWidth": "{dimension.size.800}", + "height": "{dimension.size.800}" + }, + "xl": { + "fontSize": "{fonts.fontSize.100}", + "minWidth": "{dimension.size.900}", + "height": "{dimension.size.900}" + } + }, + "breadcrumb": { + "extend": { + "hoverBackground": "{color.bg.neutral.weak.default}", + "iconSize": "{dimension.size.600}", + "extItem": { "padding": "{dimension.space.100}" } + }, + "root": { + "padding": "{dimension.space.none}", + "background": "transparent", + "gap": "{dimension.space.none}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + }, + "item": { + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "borderRadius": "{dimension.borderRadius.100}", + "gap": "{dimension.space.200}", + "icon": { + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}" + }, + "focusRing": { + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}", + "style": "none", + "width": "{dimension.focusRing.width}" + } + }, + "separator": { "color": "{color.fg.default}" } + }, + "button": { + "extend": { + "disabledBackground": "{color.bg.neutral.weak.disabled}", + "extOutlined": { + "danger": { "focusBackground": "transparent" }, + "warn": { "focusBackground": "transparent" }, + "info": { "focusBackground": "transparent" }, + "help": { "focusBackground": "transparent" }, + "success": { "focusBackground": "transparent" } + }, + "disabledColor": "{color.fg.muted}", + "extText": { + "danger": { "focusBackground": "transparent" }, + "warn": { "focusBackground": "transparent" }, + "info": { "focusBackground": "transparent" }, + "help": { "focusBackground": "transparent" }, + "success": { "focusBackground": "transparent" } + }, + "extLink": { + "background": "transparent", + "colorHover": "{color.fg.hover}", + "paddingX": "{dimension.space.none}", + "paddingY": "{dimension.space.100}", + "sm": { "iconOnlyWidth": "{dimension.size.450}" }, + "base": { "iconOnlyWidth": "{dimension.size.700}" }, + "lg": { "iconOnlyWidth": "{dimension.size.800}" }, + "xlg": { "iconOnlyWidth": "{dimension.size.900}" } + }, + "extSm": { + "borderRadius": "{dimension.borderRadius.400}", + "gap": "{dimension.space.200}" + }, + "extLg": { + "borderRadius": "{dimension.borderRadius.400}", + "gap": "{dimension.space.400}", + "height": "{dimension.size.1300}" + }, + "extXlg": { + "borderRadius": "{dimension.borderRadius.400}", + "gap": "{dimension.space.400}", + "iconOnlyWidth": "{dimension.size.1400}", + "paddingX": "{dimension.space.700}", + "paddingY": "{dimension.space.600}", + "height": "{dimension.size.1400}" + }, + "borderWidth": "{dimension.borderWidth.100}", + "iconSize": { + "sm": "{dimension.size.450}", + "md": "{dimension.size.600}", + "lg": "{dimension.size.700}" + } + }, + "colorScheme": { + "light": { + "root": { + "primary": { + "background": "{color.bg.brand.strong.default}", + "hoverBackground": "{color.bg.brand.strong.hover}", + "activeBackground": "{color.bg.brand.strong.active}", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.default}", + "activeColor": "{color.fg.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "secondary": { + "background": "{color.bg.neutral.strong.default}", + "hoverBackground": "{color.bg.neutral.strong.hover}", + "activeBackground": "{color.bg.neutral.strong.active}", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "{color.fg.on.fill.default}", + "hoverColor": "{color.fg.on.fill.hover}", + "activeColor": "{color.fg.on.fill.active}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "contrast": { + "background": "{color.bg.surface.canvas.hover}", + "hoverBackground": "{color.bg.surface.canvas.active}", + "activeBackground": "{color.bg.neutral.medium.active}", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.default}", + "activeColor": "{color.fg.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "info": { + "background": "{color.bg.status.info.strong.default}", + "hoverBackground": "{color.bg.status.info.strong.hover}", + "activeBackground": "{color.bg.status.info.strong.active}", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "{color.fg.on.status.info.default}", + "hoverColor": "{color.fg.on.status.info.hover}", + "activeColor": "{color.fg.on.status.info.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + } + }, + "success": { + "background": "{color.bg.status.success.strong.default}", + "hoverBackground": "{color.bg.status.success.strong.hover}", + "activeBackground": "{color.bg.status.success.strong.active}", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "{color.fg.on.status.success.default}", + "hoverColor": "{color.fg.on.status.success.hover}", + "activeColor": "{color.fg.on.status.success.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + } + }, + "warn": { + "background": "{color.bg.status.warning.strong.default}", + "hoverBackground": "{color.bg.status.warning.strong.hover}", + "activeBackground": "{color.bg.status.warning.strong.active}", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "{color.fg.on.status.warning.default}", + "hoverColor": "{color.fg.on.status.warning.hover}", + "activeColor": "{color.fg.on.status.warning.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + } + }, + "help": { + "background": "{color.bg.status.help.strong.default}", + "hoverBackground": "{color.bg.status.help.strong.hover}", + "activeBackground": "{color.bg.status.help.strong.active}", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "{color.fg.on.status.help.default}", + "hoverColor": "{color.fg.on.status.help.hover}", + "activeColor": "{color.fg.on.status.help.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + } + }, + "danger": { + "background": "{color.bg.status.danger.strong.default}", + "hoverBackground": "{color.bg.status.danger.strong.hover}", + "activeBackground": "{color.bg.status.danger.strong.active}", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "{color.fg.on.status.danger.default}", + "hoverColor": "{color.fg.on.status.danger.hover}", + "activeColor": "{color.fg.on.status.danger.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + } + } + }, + "outlined": { + "primary": { + "hoverBackground": "{color.bg.brand.weak.hover}", + "activeBackground": "{color.bg.brand.weak.active}", + "borderColor": "{color.border.focus}", + "color": "{color.fg.brand.default}" + }, + "success": { + "hoverBackground": "{color.bg.status.success.weak.hover}", + "activeBackground": "{color.bg.status.success.weak.active}", + "borderColor": "{color.border.brand.strong}", + "color": "{color.fg.status.success.hover}" + }, + "info": { + "hoverBackground": "{color.bg.status.info.weak.hover}", + "activeBackground": "{color.bg.status.info.weak.active}", + "borderColor": "{color.border.status.info.strong}", + "color": "{color.fg.status.info.hover}" + }, + "warn": { + "hoverBackground": "{color.bg.status.warning.weak.hover}", + "activeBackground": "{color.bg.status.warning.weak.active}", + "borderColor": "{color.border.status.warning.strong}", + "color": "{color.fg.status.warning.hover}" + }, + "help": { + "hoverBackground": "{color.bg.status.help.weak.hover}", + "activeBackground": "{color.bg.status.help.weak.active}", + "borderColor": "{color.border.status.help.strong}", + "color": "{color.fg.status.help.hover}" + }, + "danger": { + "hoverBackground": "{color.bg.status.danger.weak.hover}", + "activeBackground": "{color.bg.status.danger.weak.active}", + "borderColor": "{color.border.status.danger.strong}", + "color": "{color.fg.status.danger.hover}" + }, + "contrast": { + "activeBackground": "{color.bg.neutral.strong.active}", + "borderColor": "{color.border.neutral.bold.default}", + "color": "{color.fg.on.fill.default}", + "hoverBackground": "{color.bg.neutral.strong.hover}" + }, + "plain": { + "activeBackground": "{color.bg.neutral.medium.default}", + "borderColor": "{color.border.neutral.strong}", + "color": "{color.fg.default}", + "hoverBackground": "{color.bg.neutral.weak.default}" + }, + "secondary": { + "activeBackground": "{color.bg.neutral.medium.default}", + "borderColor": "{color.border.neutral.strong}", + "color": "{color.fg.default}", + "hoverBackground": "{color.bg.neutral.weak.default}" + } + }, + "text": { + "primary": { + "hoverBackground": "{color.bg.neutral.weak.default}", + "activeBackground": "{color.bg.neutral.medium.default}", + "color": "{color.fg.default}" + }, + "success": { + "hoverBackground": "{color.bg.status.success.weak.hover}", + "activeBackground": "{color.bg.status.success.weak.active}", + "color": "{color.fg.status.success.hover}" + }, + "info": { + "hoverBackground": "{color.bg.status.info.weak.hover}", + "activeBackground": "{color.bg.status.info.weak.active}", + "color": "{color.fg.status.info.hover}" + }, + "warn": { + "hoverBackground": "{color.bg.status.warning.weak.hover}", + "activeBackground": "{color.bg.status.warning.weak.active}", + "color": "{color.fg.status.warning.hover}" + }, + "help": { + "hoverBackground": "{color.bg.status.help.weak.hover}", + "activeBackground": "{color.bg.status.help.weak.active}", + "color": "{color.fg.status.help.hover}" + }, + "danger": { + "hoverBackground": "{color.bg.status.danger.weak.hover}", + "activeBackground": "{color.bg.status.danger.weak.active}", + "color": "{color.fg.status.danger.hover}" + }, + "contrast": { + "activeBackground": "{color.bg.neutral.strong.active}", + "color": "{color.fg.on.fill.default}", + "hoverBackground": "{color.bg.neutral.strong.hover}" + }, + "plain": { + "activeBackground": "{color.bg.neutral.medium.default}", + "color": "{color.fg.default}", + "hoverBackground": "{color.bg.neutral.weak.default}" + }, + "secondary": { + "activeBackground": "{color.bg.neutral.medium.default}", + "color": "{color.fg.default}", + "hoverBackground": "{color.bg.neutral.weak.default}" + } + }, + "link": { + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "activeColor": "{color.fg.muted}" + } + }, + "dark": { + "link": { + "activeColor": "{color.fg.inverse.muted}", + "color": "{color.fg.inverse.default}", + "hoverColor": "{color.fg.inverse.hover}" + }, + "outlined": { + "contrast": { + "activeBackground": "{color.bg.surface.canvas.active}", + "borderColor": "{color.border.neutral.inverse}", + "color": "{color.fg.default}", + "hoverBackground": "{color.bg.surface.canvas.hover}" + }, + "danger": { + "activeBackground": "{color.bg.status.danger.weak.active}", + "borderColor": "{color.border.status.danger.subtle}", + "color": "{color.fg.status.danger.hover}", + "hoverBackground": "{color.bg.status.danger.weak.hover}" + }, + "help": { + "activeBackground": "{color.bg.status.help.weak.active}", + "borderColor": "{color.border.status.help.strong}", + "color": "{color.fg.status.help.hover}", + "hoverBackground": "{color.bg.status.help.weak.hover}" + }, + "info": { + "activeBackground": "{color.bg.status.info.weak.active}", + "borderColor": "{color.border.status.info.strong}", + "color": "{color.fg.status.info.hover}", + "hoverBackground": "{color.bg.status.info.weak.hover}" + }, + "plain": { + "activeBackground": "{color.bg.neutral.strong.hover}", + "borderColor": "{color.border.neutral.strong}", + "color": "{color.fg.inverse.default}", + "hoverBackground": "{color.bg.neutral.strong.selected}" + }, + "primary": { + "activeBackground": "{color.bg.brand.weak.active}", + "borderColor": "{color.border.focus}", + "color": "{color.fg.brand.muted}", + "hoverBackground": "{color.bg.brand.weak.hover}" + }, + "secondary": { + "activeBackground": "{color.bg.neutral.strong.hover}", + "borderColor": "{color.border.neutral.strong}", + "color": "{color.fg.inverse.default}", + "hoverBackground": "{color.bg.neutral.strong.selected}" + }, + "success": { + "activeBackground": "{color.bg.status.success.weak.active}", + "borderColor": "{color.border.brand.strong}", + "color": "{color.fg.status.success.hover}", + "hoverBackground": "{color.bg.status.success.weak.hover}" + }, + "warn": { + "activeBackground": "{color.bg.status.warning.weak.active}", + "borderColor": "{color.border.status.warning.strong}", + "color": "{color.fg.status.warning.hover}", + "hoverBackground": "{color.bg.status.warning.weak.hover}" + } + }, + "root": { + "contrast": { + "activeBackground": "{color.bg.neutral.medium.active}", + "activeBorderColor": "transparent", + "activeColor": "{color.fg.on.brand.active}", + "background": "{color.bg.neutral.strong.hover}", + "borderColor": "transparent", + "color": "{color.fg.inverse.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.neutral.strong.active}", + "hoverBorderColor": "transparent", + "hoverColor": "{color.fg.on.brand.hover}" + }, + "danger": { + "activeBackground": "{color.bg.status.danger.strong.active}", + "activeBorderColor": "transparent", + "activeColor": "{color.fg.on.status.danger.default}", + "background": "{color.bg.status.danger.strong.default}", + "borderColor": "transparent", + "color": "{color.fg.on.status.danger.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + }, + "hoverBackground": "{color.bg.status.danger.strong.hover}", + "hoverBorderColor": "transparent", + "hoverColor": "{color.fg.on.status.danger.hover}" + }, + "help": { + "activeBackground": "{color.bg.status.help.strong.active}", + "activeBorderColor": "transparent", + "activeColor": "{color.fg.on.status.help.default}", + "background": "{color.bg.status.help.strong.default}", + "borderColor": "transparent", + "color": "{color.fg.on.status.help.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + }, + "hoverBackground": "{color.bg.status.help.strong.hover}", + "hoverBorderColor": "transparent", + "hoverColor": "{color.fg.on.status.help.hover}" + }, + "info": { + "activeBackground": "{color.bg.status.info.strong.active}", + "activeBorderColor": "transparent", + "activeColor": "{color.fg.on.status.info.default}", + "background": "{color.bg.status.info.strong.default}", + "borderColor": "transparent", + "color": "{color.fg.on.status.info.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + }, + "hoverBackground": "{color.bg.status.info.strong.hover}", + "hoverBorderColor": "transparent", + "hoverColor": "{color.fg.on.status.info.hover}" + }, + "primary": { + "activeBackground": "{color.bg.status.success.strong.default}", + "activeBorderColor": "transparent", + "activeColor": "{color.fg.on.brand.active}", + "background": "{color.bg.brand.strong.default}", + "borderColor": "transparent", + "color": "{color.fg.inverse.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.status.success.strong.hover}", + "hoverBorderColor": "transparent", + "hoverColor": "{color.fg.on.brand.hover}" + }, + "secondary": { + "activeBackground": "{color.bg.surface.canvas.active}", + "activeBorderColor": "transparent", + "activeColor": "{color.fg.on.fill.active}", + "background": "{color.bg.surface.canvas.default}", + "borderColor": "transparent", + "color": "{color.fg.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.surface.canvas.hover}", + "hoverBorderColor": "transparent", + "hoverColor": "{color.fg.on.fill.hover}" + }, + "success": { + "activeBackground": "{color.bg.status.success.strong.active}", + "activeBorderColor": "transparent", + "activeColor": "{color.fg.on.status.success.default}", + "background": "{color.bg.brand.strong.active}", + "borderColor": "transparent", + "color": "{color.fg.on.status.success.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + }, + "hoverBackground": "{color.bg.brand.strong.hover}", + "hoverBorderColor": "transparent", + "hoverColor": "{color.fg.on.status.success.hover}" + }, + "warn": { + "activeBackground": "{color.bg.status.warning.strong.active}", + "activeBorderColor": "transparent", + "activeColor": "{color.fg.on.status.warning.default}", + "background": "{color.bg.status.warning.strong.default}", + "borderColor": "transparent", + "color": "{color.fg.on.status.warning.default}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + }, + "hoverBackground": "{color.bg.status.warning.strong.hover}", + "hoverBorderColor": "transparent", + "hoverColor": "{color.fg.on.status.warning.hover}" + } + }, + "text": { + "contrast": { + "activeBackground": "{color.bg.surface.canvas.active}", + "color": "{color.fg.default}", + "hoverBackground": "{color.bg.surface.canvas.hover}" + }, + "danger": { + "activeBackground": "{color.bg.status.danger.weak.active}", + "color": "{color.fg.status.danger.hover}", + "hoverBackground": "{color.bg.status.danger.weak.hover}" + }, + "help": { + "activeBackground": "{color.bg.status.help.weak.active}", + "color": "{color.fg.status.help.hover}", + "hoverBackground": "{color.bg.status.help.weak.hover}" + }, + "info": { + "activeBackground": "{color.bg.status.info.weak.active}", + "color": "{color.fg.status.info.hover}", + "hoverBackground": "{color.bg.status.info.weak.hover}" + }, + "plain": { + "activeBackground": "{color.bg.neutral.strong.hover}", + "color": "{color.fg.inverse.default}", + "hoverBackground": "{color.bg.neutral.strong.selected}" + }, + "primary": { + "activeBackground": "{color.bg.neutral.strong.hover}", + "color": "{color.fg.inverse.default}", + "hoverBackground": "{color.bg.neutral.strong.selected}" + }, + "secondary": { + "activeBackground": "{color.bg.neutral.strong.hover}", + "color": "{color.fg.inverse.default}", + "hoverBackground": "{color.bg.neutral.strong.selected}" + }, + "success": { + "activeBackground": "{color.bg.status.success.weak.active}", + "color": "{color.fg.status.success.hover}", + "hoverBackground": "{color.bg.status.success.weak.hover}" + }, + "warn": { + "activeBackground": "{color.bg.status.warning.weak.active}", + "color": "{color.fg.status.warning.hover}", + "hoverBackground": "{color.bg.status.warning.weak.hover}" + } + } + } + }, + "root": { + "borderRadius": "{dimension.borderRadius.400}", + "roundedBorderRadius": "{dimension.borderRadius.max}", + "gap": "{dimension.space.200}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.200}", + "iconOnlyWidth": "{dimension.size.1100}", + "raisedShadow": "none", + "badgeSize": "{dimension.size.450}", + "transitionDuration": "{effects.transition.duration.200}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "offset": "{dimension.focusRing.offset}" + }, + "sm": { + "fontSize": "{fonts.fontSize.200}", + "iconOnlyWidth": "{dimension.size.900}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.200}" + }, + "lg": { + "fontSize": "{fonts.fontSize.500}", + "iconOnlyWidth": "{dimension.size.1300}", + "paddingX": "{dimension.space.700}", + "paddingY": "{dimension.space.400}" + }, + "label": { "fontWeight": "{fonts.fontWeight.demibold}" } + } + }, + "card": { + "extend": { + "borderColor": "{color.border.neutral.default}", + "borderWidth": "{dimension.borderWidth.100}" + }, + "root": { + "background": "{color.bg.surface.default.default}", + "borderRadius": "{dimension.borderRadius.400}", + "color": "{color.fg.default}", + "shadow": "{effects.elevation.none}" + }, + "body": { + "padding": "{dimension.space.400}", + "gap": "{dimension.space.400}" + }, + "caption": { "gap": "{dimension.space.100}" }, + "title": { + "fontSize": "{fonts.fontSize.400}", + "fontWeight": "{fonts.fontWeight.demibold}" + }, + "subtitle": { "color": "{color.fg.muted}" } + }, + "carousel": { + "colorScheme": { + "light": { + "indicator": { + "background": "{color.bg.neutral.weak.active}", + "hoverBackground": "{color.bg.neutral.medium.active}", + "activeBackground": "{color.bg.neutral.strong.default}" + } + }, + "dark": { + "indicator": { + "activeBackground": "{color.bg.surface.canvas.default}", + "background": "{color.bg.neutral.strong.active}", + "hoverBackground": "{color.bg.neutral.medium.active}" + } + } + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" }, + "content": { "gap": "{dimension.space.200}" }, + "indicatorList": { + "padding": "{dimension.space.400}", + "gap": "{dimension.space.200}" + }, + "indicator": { + "width": "{dimension.size.200}", + "height": "{dimension.size.200}", + "borderRadius": "{dimension.borderRadius.max}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + } + }, + "checkbox": { + "root": { + "borderRadius": "{dimension.borderRadius.200}", + "extend": { "borderWidth": "{dimension.borderWidth.100}" }, + "width": "{dimension.size.700}", + "height": "{dimension.size.700}", + "background": "{color.bg.surface.default.default}", + "checkedBackground": "{color.bg.neutral.strong.default}", + "checkedHoverBackground": "{color.bg.neutral.strong.hover}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "filledBackground": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.strong}", + "hoverBorderColor": "{color.border.neutral.bold.default}", + "focusBorderColor": "{color.border.neutral.bold.default}", + "checkedBorderColor": "{color.border.neutral.bold.default}", + "checkedHoverBorderColor": "{color.border.neutral.bold.hover}", + "checkedFocusBorderColor": "{color.border.brand.default}", + "checkedDisabledBorderColor": "{color.border.neutral.strong}", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "shadow": "{effects.elevation.none}", + "focusRing": { + "focusRing": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}", + "width": "{dimension.focusRing.width}" + }, + "sm": { + "width": "{dimension.size.200}", + "height": "{dimension.size.200}" + }, + "lg": { + "width": "{dimension.size.600}", + "height": "{dimension.size.600}" + }, + "transitionDuration": "{effects.transition.duration.200}" + }, + "icon": { + "size": "{dimension.size.450}", + "color": "{color.fg.active}", + "checkedColor": "{color.fg.on.fill.default}", + "checkedHoverColor": "{color.fg.on.fill.hover}", + "disabledColor": "{color.fg.muted}", + "sm": { "size": "{dimension.size.350}" }, + "lg": { "size": "{dimension.size.600}" } + } + }, + "chip": { + "extend": { + "borderColor": "transparent", + "borderWidth": "{dimension.borderWidth.100}" + }, + "root": { + "borderRadius": "{dimension.borderRadius.200}", + "paddingX": "{dimension.space.200}", + "paddingY": "{dimension.space.100}", + "gap": "{dimension.space.200}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "colorScheme": { + "light": { + "root": { + "background": "{color.bg.surface.canvas.hover}", + "color": "{color.fg.default}" + }, + "icon": { "color": "{color.fg.default}" }, + "removeIcon": { "color": "{color.fg.default}" } + }, + "dark": { + "icon": { "color": "{color.fg.inverse.default}" }, + "removeIcon": { "color": "{color.fg.inverse.default}" }, + "root": { + "background": "{color.bg.neutral.strong.hover}", + "color": "{color.fg.inverse.default}" + } + } + }, + "image": { + "width": "{dimension.size.none}", + "height": "{dimension.size.none}" + }, + "icon": { "size": "{dimension.size.450}" }, + "removeIcon": { + "size": "{dimension.size.450}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + } + }, + "confirmdialog": { + "extend": { + "extIcon": { + "success": "{color.fg.status.success.default}", + "info": "{color.fg.status.info.default}", + "help": "{color.fg.status.help.default}", + "warn": "{color.fg.status.warning.default}", + "danger": "{color.fg.status.danger.default}" + } + }, + "icon": { "size": "{dimension.size.700}", "color": "{color.fg.default}" }, + "content": { "gap": "{dimension.space.none}" } + }, + "confirmpopup": { + "root": { + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.default}", + "shadow": "{effects.elevation.400}", + "gutter": "{dimension.space.400}", + "arrowOffset": "{dimension.space.600}", + "borderColor": "{color.border.neutral.default}", + "borderRadius": "{dimension.borderRadius.400}" + }, + "content": { + "padding": "{dimension.space.400}", + "gap": "{dimension.space.400}" + }, + "icon": { "size": "{dimension.size.700}", "color": "{color.fg.default}" }, + "footer": { + "gap": "{dimension.space.200}", + "padding": "{dimension.space.none} {dimension.space.700} {dimension.space.700} {dimension.space.700}" + } + }, + "contextmenu": { + "root": { + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.default}", + "shadow": "{effects.elevation.400}", + "borderColor": "{color.border.neutral.default}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "list": { + "padding": "{dimension.space.200} {dimension.space.none}", + "gap": "{dimension.space.100}" + }, + "item": { + "padding": "{dimension.space.200} {dimension.space.400}", + "gap": "{dimension.space.200}", + "activeBackground": "{color.bg.neutral.medium.default}", + "activeColor": "{color.fg.hover}", + "borderRadius": "{dimension.borderRadius.400}", + "color": "{color.fg.default}", + "focusBackground": "{color.bg.neutral.weak.default}", + "focusColor": "{color.fg.hover}", + "icon": { + "activeColor": "{color.fg.hover}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.hover}" + } + }, + "submenu": { "mobileIndent": "{dimension.space.600}" }, + "separator": { "borderColor": "{color.border.neutral.default}" }, + "submenuIcon": { + "activeColor": "{color.fg.hover}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.hover}", + "size": "{dimension.size.400}" + } + }, + "datatable": { + "colorScheme": { + "light": { + "root": { + "color": "{color.fg.default}", + "borderColor": "{color.border.neutral.default}" + }, + "header": { + "background": "{color.bg.surface.default.hover}", + "color": "{color.fg.default}" + }, + "headerCell": { + "background": "{color.bg.surface.raised.selected}", + "hoverBackground": "{color.bg.neutral.weak.default}", + "color": "{color.fg.default}" + }, + "footer": { + "background": "{color.bg.surface.canvas.default}", + "color": "{color.fg.default}" + }, + "footerCell": { + "background": "{color.bg.neutral.weak.default}", + "color": "{color.fg.default}" + }, + "row": { "stripedBackground": "{color.bg.neutral.weak.default}" }, + "bodyCell": { + "selectedBorderColor": "{color.border.neutral.default}" + } + }, + "dark": { + "bodyCell": { + "selectedBorderColor": "{color.border.neutral.bold.hover}" + }, + "footer": { + "background": "{color.bg.neutral.strong.default}", + "color": "{color.fg.inverse.default}" + }, + "footerCell": { + "background": "{color.bg.neutral.strong.default}", + "color": "{color.fg.inverse.default}" + }, + "header": { + "background": "{color.bg.surface.default.hover}", + "color": "{color.fg.inverse.default}" + }, + "headerCell": { + "background": "{color.bg.surface.raised.selected}", + "color": "{color.fg.inverse.default}", + "hoverBackground": "{color.bg.neutral.strong.selected}" + }, + "root": { + "borderColor": "{color.border.neutral.bold.hover}", + "color": "{color.fg.inverse.default}" + }, + "row": { "stripedBackground": "{color.bg.neutral.strong.default}" } + } + }, + "extended": { + "extHeaderCell": { + "selectedHoverBackground": "{color.bg.neutral.strong.hover}" + }, + "extRow": { + "selectedHoverBackground": "{color.bg.neutral.strong.hover}", + "stripedHoverBackground": "{color.bg.neutral.weak.default}", + "iconSize": "{dimension.size.600}" + } + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" }, + "header": { + "borderColor": "{color.border.neutral.default}", + "borderWidth": "{dimension.borderWidth.100} {dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.none}", + "padding": "{dimension.space.400}", + "sm": { "padding": "{dimension.space.200}" }, + "lg": { "padding": "{dimension.space.600}" } + }, + "headerCell": { + "selectedBackground": "{color.bg.neutral.strong.selected}", + "borderColor": "{color.border.neutral.default}", + "hoverColor": "{color.fg.hover}", + "selectedColor": "{color.fg.on.fill.default}", + "gap": "{dimension.space.200}", + "padding": "{dimension.space.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.focusRing.shadow}" + }, + "sm": { "padding": "{dimension.space.200}" }, + "lg": { "padding": "{dimension.space.600}" } + }, + "columnTitle": { "fontWeight": "{fonts.fontWeight.bold}" }, + "row": { + "background": "{color.bg.surface.raised.default}", + "hoverBackground": "{color.bg.neutral.weak.default}", + "selectedBackground": "{color.bg.neutral.strong.selected}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "selectedColor": "{color.fg.on.fill.default}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.focusRing.shadow}" + } + }, + "bodyCell": { + "borderColor": "{color.border.neutral.default}", + "padding": "{dimension.space.400}", + "sm": { "padding": "{dimension.space.200}" }, + "lg": { "padding": "{dimension.space.600}" } + }, + "footerCell": { + "borderColor": "{color.border.neutral.default}", + "padding": "{dimension.space.400}", + "sm": { "padding": "{dimension.space.200}" }, + "lg": { "padding": "{dimension.space.600}" } + }, + "columnFooter": { "fontWeight": "{fonts.fontWeight.bold}" }, + "dropPoint": { "color": "{color.fg.default}" }, + "footer": { + "borderColor": "{color.border.neutral.default}", + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.none}", + "padding": "{dimension.space.400}", + "sm": { "padding": "{dimension.space.200}" }, + "lg": { "padding": "{dimension.space.600}" } + }, + "columnResizer": { "width": "{dimension.size.200}" }, + "resizeIndicator": { + "width": "{dimension.borderWidth.100}", + "color": "{color.fg.default}" + }, + "sortIcon": { + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "size": "{dimension.size.450}" + }, + "loadingIcon": { "size": "{dimension.size.900}" }, + "rowToggleButton": { + "hoverBackground": "{color.bg.neutral.weak.default}", + "selectedHoverBackground": "{color.bg.neutral.weak.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.default}", + "selectedHoverColor": "{color.fg.default}", + "size": "{dimension.size.900}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "filter": { + "inlineGap": "{dimension.space.200}", + "rule": { "borderColor": "{color.border.neutral.default}" }, + "constraintList": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}" + }, + "constraint": { + "focusBackground": "{color.bg.neutral.weak.default}", + "selectedBackground": "{color.bg.neutral.strong.selected}", + "selectedFocusBackground": "{color.bg.neutral.strong.active}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "selectedColor": "{color.fg.on.fill.default}", + "selectedFocusColor": "{color.fg.on.fill.active}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}", + "separator": { "borderColor": "{color.border.neutral.default}" } + }, + "overlaySelect": { + "background": "{color.bg.surface.raised.default}", + "color": "{color.fg.default}", + "borderColor": "{color.border.neutral.default}", + "borderRadius": "{dimension.borderRadius.400}", + "shadow": "{effects.elevation.400}" + }, + "overlayPopover": { + "background": "{color.bg.surface.raised.default}", + "color": "{color.fg.default}", + "borderColor": "{color.border.neutral.default}", + "borderRadius": "{dimension.borderRadius.400}", + "shadow": "{effects.elevation.400}", + "padding": "{dimension.space.400}", + "gap": "{dimension.space.100}" + } + }, + "paginatorTop": { + "borderColor": "{color.border.neutral.strong}", + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.none}" + }, + "paginatorBottom": { + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.none}", + "borderColor": "{color.border.neutral.default}" + } + }, + "dataview": { + "root": { + "borderWidth": "{dimension.borderWidth.100}", + "borderRadius": "{dimension.borderRadius.100}", + "padding": "{dimension.space.none}", + "borderColor": "{color.border.neutral.default}" + }, + "header": { + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.none}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.none} {dimension.borderRadius.none} {dimension.borderRadius.none} {dimension.borderRadius.none}", + "color": "{color.fg.default}", + "borderColor": "{color.border.neutral.default}" + }, + "content": { + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.default}", + "borderColor": "{color.border.neutral.default}", + "borderWidth": "{dimension.borderWidth.none}", + "padding": "{dimension.space.none}", + "borderRadius": "{dimension.borderRadius.none}" + }, + "footer": { + "background": "{color.bg.surface.canvas.default}", + "color": "{color.fg.default}", + "borderWidth": "{dimension.borderWidth.100} {dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.none}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.none} {dimension.borderRadius.none} {dimension.borderRadius.none} {dimension.borderRadius.none}", + "borderColor": "{color.border.neutral.default}" + }, + "paginatorTop": { + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.none}", + "borderColor": "{color.border.neutral.default}" + }, + "paginatorBottom": { + "borderWidth": "{dimension.borderWidth.100} {dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.none}", + "borderColor": "{color.border.neutral.default}" + }, + "colorScheme": { + "dark": { + "header": { + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.inverse.default}" + } + }, + "light": { + "header": { + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.default}" + } + } + } + }, + "datepicker": { + "extend": { + "extDate": { + "selectedHoverBackground": "{color.bg.neutral.strong.hover}" + }, + "extToday": { + "hoverBackground": "{color.bg.neutral.weak.default}", + "borderColor": "{color.border.neutral.bold.hover}" + }, + "extTitle": { "width": "{dimension.size.1900}" }, + "extTimePicker": { + "minWidth": "{dimension.size.1800}", + "color": "{color.fg.default}" + } + }, + "colorScheme": { + "light": { + "dropdown": { + "background": "{color.bg.surface.default.default}", + "hoverBackground": "{color.bg.surface.canvas.default}", + "activeBackground": "{color.bg.neutral.strong.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.default}", + "activeColor": "{color.fg.inverse.active}" + }, + "today": { + "background": "transparent", + "color": "{color.fg.default}" + } + }, + "dark": { + "dropdown": { + "activeBackground": "{color.bg.surface.canvas.default}", + "activeColor": "{color.fg.on.fill.active}", + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.inverse.default}", + "hoverBackground": "{color.bg.neutral.strong.selected}", + "hoverColor": "{color.fg.on.brand.hover}" + }, + "today": { + "background": "transparent", + "color": "{color.fg.inverse.default}" + } + } + }, + "panel": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}", + "borderRadius": "{dimension.borderRadius.400}", + "shadow": "{effects.elevation.400}", + "padding": "{dimension.space.none}" + }, + "header": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}", + "padding": "{dimension.space.400}" + }, + "title": { + "gap": "{dimension.space.200}", + "fontWeight": "{fonts.fontWeight.bold}" + }, + "selectMonth": { + "hoverBackground": "{color.bg.neutral.weak.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "borderRadius": "{dimension.borderRadius.400}", + "padding": "{dimension.space.200}" + }, + "inputIcon": { "color": "{color.fg.muted}" }, + "dropdown": { + "width": "{dimension.size.1700}", + "borderColor": "{color.border.neutral.strong}", + "hoverBorderColor": "{color.border.neutral.strong}", + "activeBorderColor": "{color.border.neutral.strong}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + }, + "sm": { "width": "{dimension.size.none}" }, + "lg": { "width": "{dimension.size.none}" } + }, + "group": { + "borderColor": "{color.border.neutral.default}", + "gap": "{dimension.space.400}" + }, + "selectYear": { + "hoverBackground": "{color.bg.neutral.weak.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "borderRadius": "{dimension.borderRadius.400}", + "padding": "{dimension.space.100}" + }, + "dayView": { "margin": "{dimension.space.400}" }, + "weekDay": { + "padding": "{dimension.space.100}", + "fontWeight": "{fonts.fontWeight.bold}", + "color": "{color.fg.default}" + }, + "date": { + "hoverBackground": "{color.bg.neutral.weak.default}", + "selectedBackground": "{color.bg.neutral.strong.selected}", + "rangeSelectedBackground": "{color.bg.neutral.weak.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.default}", + "selectedColor": "{color.fg.on.fill.default}", + "rangeSelectedColor": "{color.fg.default}", + "width": "{dimension.size.900}", + "height": "{dimension.size.900}", + "borderRadius": "{dimension.borderRadius.200}", + "padding": "{dimension.space.100}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "monthView": { + "margin": "{dimension.space.none} {dimension.space.none} {dimension.space.none} {dimension.space.none}" + }, + "month": { + "padding": "{dimension.space.none}", + "borderRadius": "{dimension.borderRadius.none}" + }, + "yearView": { + "margin": "{dimension.space.none} {dimension.space.none} {dimension.space.none} {dimension.space.none}" + }, + "year": { + "padding": "{dimension.space.none}", + "borderRadius": "{dimension.borderRadius.none}" + }, + "buttonbar": { + "padding": "{dimension.space.400}", + "borderColor": "{color.border.neutral.default}" + }, + "timePicker": { + "padding": "{dimension.space.400}", + "borderColor": "{color.border.neutral.default}", + "gap": "{dimension.space.200}", + "buttonGap": "{dimension.space.100}" + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" } + }, + "dialog": { + "extend": { + "borderWidth": "{dimension.borderWidth.100}", + "backdrop": "{color.bg.surface.backdrop}" + }, + "root": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}", + "borderRadius": "{dimension.borderRadius.max}", + "shadow": "{effects.elevation.400}" + }, + "header": { + "padding": "{dimension.space.700} {dimension.space.700} {dimension.space.400} {dimension.space.700}", + "gap": "{dimension.space.200}" + }, + "title": { + "fontSize": "{fonts.fontSize.500}", + "fontWeight": "{fonts.fontWeight.demibold}" + }, + "content": { "padding": "{dimension.space.700}" }, + "footer": { + "padding": "{dimension.space.none} {dimension.space.700} {dimension.space.700} {dimension.space.700}", + "gap": "{dimension.space.200}" + } + }, + "divider": { + "extend": { + "content": { "gap": "{dimension.space.200}" }, + "iconSize": "{dimension.size.450}" + }, + "horizontal": { + "margin": "{dimension.space.400} {dimension.space.none}", + "padding": "{dimension.space.none} {dimension.space.400}", + "content": { "padding": "{dimension.space.none} {dimension.space.200}" } + }, + "vertical": { + "margin": "{dimension.space.none} {dimension.space.400}", + "padding": "{dimension.space.400} {dimension.space.none}", + "content": { "padding": "{dimension.space.200} {dimension.space.none}" } + }, + "content": { + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.default}" + }, + "root": { "borderColor": "{color.border.neutral.default}" } + }, + "drawer": { + "extend": { + "borderRadius": "{dimension.borderRadius.200}", + "borderWidth": "{dimension.borderWidth.100}", + "width": "{dimension.size.2000}", + "extHeader": { + "gap": "{dimension.space.200}", + "borderColor": "{color.border.neutral.default}" + }, + "margin": "{dimension.space.200}", + "scale": "{dimension.size.50}", + "backdrop": "{color.bg.surface.backdrop}" + }, + "root": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}", + "shadow": "{effects.elevation.200}" + }, + "header": { + "padding": "{dimension.space.700} {dimension.space.700} {dimension.space.400} {dimension.space.700}" + }, + "title": { + "fontSize": "{fonts.fontSize.500}", + "fontWeight": "{fonts.fontWeight.demibold}" + }, + "content": { "padding": "{dimension.space.700}" }, + "footer": { + "padding": "{dimension.space.none} {dimension.space.700} {dimension.space.700} {dimension.space.700}" + } + }, + "fileupload": { + "extend": { + "extDragNdrop": { + "background": "{color.bg.surface.raised.default}", + "borderRadius": "{dimension.borderRadius.400}", + "iconSize": "{dimension.size.900}", + "padding": "{dimension.space.400}", + "info": { "gap": "{dimension.space.100}" } + }, + "extFile": { "iconSize": "{dimension.size.600}" }, + "extContent": { + "borderRadius": "{dimension.borderRadius.400}", + "highlightBorderDefault": "{color.border.neutral.strong}" + } + }, + "colorScheme": { + "light": { + "header": { + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.default}" + } + }, + "dark": { + "header": { + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.inverse.default}" + } + } + }, + "root": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "header": { + "borderColor": "{color.border.neutral.default}", + "borderWidth": "{dimension.borderWidth.none}", + "padding": "{dimension.space.none}", + "borderRadius": "{dimension.borderRadius.none}", + "gap": "{dimension.space.200}" + }, + "content": { + "highlightBorderColor": "{color.border.neutral.bold.default}", + "padding": "{dimension.space.none}", + "gap": "{dimension.space.200}" + }, + "file": { + "padding": "{dimension.space.200}", + "gap": "{dimension.space.200}", + "borderColor": "{color.border.neutral.strong}", + "info": { "gap": "{dimension.space.100}" } + }, + "fileList": { "gap": "{dimension.space.200}" }, + "progressbar": { "height": "{dimension.size.200}" }, + "basic": { "gap": "{dimension.space.200}" } + }, + "floatlabel": { + "extend": { + "height": "{dimension.size.1400}", + "iconSize": "{dimension.size.600}" + }, + "root": { + "color": "{color.fg.muted}", + "focusColor": "{color.fg.muted}", + "activeColor": "{color.fg.muted}", + "invalidColor": "{color.fg.status.danger.hover}", + "transitionDuration": "{effects.transition.duration.200}", + "positionX": "{dimension.space.400}", + "positionY": "{dimension.space.400}", + "fontWeight": "{fonts.fontWeight.regular}", + "active": { + "fontSize": "{fonts.fontSize.100}", + "fontWeight": "{fonts.fontWeight.regular}" + } + }, + "over": { "active": { "top": "{dimension.space.400}" } }, + "inside": { + "input": { + "paddingTop": "{dimension.space.800}", + "paddingBottom": "{dimension.space.400}" + }, + "active": { "top": "{dimension.space.400}" } + }, + "on": { + "borderRadius": "{dimension.borderRadius.none}", + "active": { + "padding": "{dimension.space.none} {dimension.space.100}", + "background": "{color.bg.surface.raised.default}" + } + } + }, + "galleria": { + "extend": { "backdrop": "{color.bg.surface.backdrop}" }, + "colorScheme": { + "light": { + "thumbnailContent": { + "background": "{color.bg.neutral.weak.default}" + }, + "thumbnailNavButton": { + "hoverBackground": "{color.bg.neutral.medium.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}" + }, + "indicatorButton": { + "background": "{color.bg.neutral.weak.active}", + "hoverBackground": "{color.bg.neutral.medium.active}" + }, + "thumbnailsContent": { + "background": "{color.bg.neutral.medium.default}" + } + }, + "dark": { + "indicatorButton": { + "background": "{color.bg.neutral.strong.active}", + "hoverBackground": "{color.bg.neutral.medium.active}" + }, + "thumbnailNavButton": { + "color": "{color.fg.inverse.default}", + "hoverBackground": "{color.bg.neutral.medium.default}", + "hoverColor": "{color.fg.inverse.hover}" + }, + "thumbnailsContent": { + "background": "{color.bg.neutral.medium.default}" + }, + "thumbnailContent": { + "background": "{color.bg.neutral.strong.default}" + } + } + }, + "root": { + "borderWidth": "{dimension.borderWidth.100}", + "borderColor": "{color.border.neutral.default}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "navButton": { + "background": "transparent", + "hoverBackground": "{color.bg.neutral.medium.default}", + "color": "{color.fg.inverse.default}", + "hoverColor": "{color.fg.inverse.hover}", + "size": "{dimension.size.1400}", + "gutter": "{dimension.space.200}", + "prev": { "borderRadius": "{dimension.borderRadius.200}" }, + "next": { "borderRadius": "{dimension.borderRadius.200}" }, + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "navIcon": { "size": "{dimension.size.900}" }, + "thumbnailsContent": { "padding": "{dimension.space.100}" }, + "thumbnailNavButton": { + "size": "{dimension.size.900}", + "borderRadius": "{dimension.borderRadius.400}", + "gutter": "{dimension.space.200}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "thumbnailNavButtonIcon": { "size": "{dimension.size.450}" }, + "caption": { + "background": "{color.bg.neutral.medium.default}", + "color": "{color.fg.default}", + "padding": "{dimension.space.200}" + }, + "indicatorList": { + "gap": "{dimension.space.200}", + "padding": "{dimension.space.400}" + }, + "indicatorButton": { + "width": "{dimension.size.200}", + "height": "{dimension.size.200}", + "activeBackground": "{color.bg.neutral.strong.default}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "insetIndicatorList": { "background": "{color.bg.surface.backdrop}" }, + "insetIndicatorButton": { + "background": "{color.bg.neutral.medium.default}", + "hoverBackground": "{color.bg.neutral.medium.default}", + "activeBackground": "{color.bg.neutral.medium.default}" + }, + "closeButton": { + "size": "{dimension.size.1400}", + "gutter": "{dimension.space.200}", + "background": "{color.bg.neutral.medium.default}", + "hoverBackground": "{color.bg.neutral.medium.default}", + "color": "{color.fg.inverse.default}", + "hoverColor": "{color.fg.inverse.hover}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "closeButtonIcon": { "size": "{dimension.size.900}" } + }, + "inputgroup": { + "extend": { + "borderWidth": "{dimension.borderWidth.100}", + "iconSize": "{dimension.size.450}" + }, + "colorScheme": { + "light": { + "addon": { + "background": "{color.bg.surface.raised.default}", + "borderColor": "{color.border.neutral.strong}", + "color": "{color.fg.muted}" + } + }, + "dark": { + "addon": { + "background": "{color.bg.surface.raised.default}", + "borderColor": "{color.border.neutral.strong}", + "color": "{color.fg.inverse.muted}" + } + } + }, + "addon": { + "borderRadius": "{dimension.borderRadius.400}", + "padding": "{dimension.space.400}", + "minWidth": "{dimension.size.1700}" + } + }, + "inputnumber": { + "extend": { + "borderWidth": "{dimension.borderWidth.100}", + "extButton": { + "height": "{dimension.size.1100}", + "iconSize": "{dimension.size.450}" + } + }, + "colorScheme": { + "light": { + "button": { + "background": "{color.bg.surface.raised.default}", + "hoverBackground": "{color.bg.neutral.weak.default}", + "activeBackground": "transparent", + "borderColor": "{color.border.neutral.strong}", + "hoverBorderColor": "{color.border.neutral.strong}", + "activeBorderColor": "{color.border.neutral.strong}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "activeColor": "{color.fg.default}" + } + }, + "dark": { + "button": { + "activeBackground": "transparent", + "activeBorderColor": "{color.border.neutral.strong}", + "activeColor": "{color.fg.on.brand.active}", + "background": "{color.bg.surface.raised.default}", + "borderColor": "{color.border.neutral.strong}", + "color": "{color.fg.inverse.default}", + "hoverBackground": "{color.bg.neutral.strong.selected}", + "hoverBorderColor": "{color.border.neutral.strong}", + "hoverColor": "{color.fg.inverse.hover}" + } + } + }, + "transitionDuration": { + "transitionDuration": "{effects.transition.duration.200}" + }, + "button": { + "width": "{dimension.size.1700}", + "borderRadius": "{dimension.borderRadius.400}", + "verticalPadding": "{dimension.space.400}" + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" } + }, + "inputotp": { + "extend": { + "height": "{dimension.size.1100}", + "borderWidth": "{dimension.borderWidth.100}" + }, + "root": { "gap": "{dimension.space.200}" }, + "input": { + "width": "{dimension.size.1800}", + "lg": { "width": "{dimension.size.1900}" }, + "sm": { "width": "{dimension.size.1700}" } + }, + "sm": { "width": "{dimension.size.none}" }, + "lg": { "width": "{dimension.size.none}" } + }, + "inputtext": { + "extend": { + "readonlyBackground": "{color.bg.neutral.weak.default}", + "iconSize": "{dimension.size.450}", + "borderWidth": "{dimension.borderWidth.100}", + "extXlg": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}" + } + }, + "root": { + "background": "{color.bg.surface.default.default}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "filledBackground": "{color.bg.surface.default.default}", + "filledHoverBackground": "{color.bg.surface.default.default}", + "filledFocusBackground": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.strong}", + "hoverBorderColor": "{color.border.brand.strong}", + "focusBorderColor": "{color.border.brand.strong}", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "color": "{color.fg.default}", + "disabledColor": "{color.fg.muted}", + "placeholderColor": "{color.fg.muted}", + "invalidPlaceholderColor": "{color.fg.status.danger.hover}", + "shadow": "{effects.elevation.none}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}", + "sm": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}" + }, + "lg": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}" + }, + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}" + } + } + }, + "listbox": { + "extend": { + "extOption": { + "label": { "gap": "{dimension.space.100}" }, + "caption": { + "color": "{color.fg.muted}", + "stripedColor": "{color.fg.muted}" + }, + "gap": "{dimension.space.200}" + } + }, + "colorScheme": { + "light": { + "option": { + "stripedBackground": "{color.bg.surface.raised.selected}" + } + }, + "dark": { + "option": { + "stripedBackground": "{color.bg.surface.raised.selected}" + } + } + }, + "root": { + "background": "{color.bg.surface.default.default}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "borderColor": "{color.border.neutral.strong}", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "color": "{color.fg.active}", + "disabledColor": "{color.fg.muted}", + "shadow": "{effects.elevation.none}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "list": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}", + "header": { + "padding": "{dimension.space.400} {dimension.space.400} {dimension.space.none} {dimension.space.400}" + } + }, + "option": { + "focusBackground": "{color.bg.neutral.weak.default}", + "selectedBackground": "{color.bg.neutral.strong.selected}", + "selectedFocusBackground": "{color.bg.neutral.strong.active}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "selectedColor": "{color.fg.on.fill.default}", + "selectedFocusColor": "{color.fg.on.fill.active}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}" + }, + "optionGroup": { + "background": "{color.bg.surface.raised.default}", + "color": "{color.fg.muted}", + "fontWeight": "{fonts.fontWeight.demibold}", + "padding": "{dimension.space.200} {dimension.space.400}" + }, + "checkmark": { + "color": "{color.fg.default}", + "gutterStart": "{dimension.space.negative.200}", + "gutterEnd": "{dimension.space.200}" + }, + "emptyMessage": { + "padding": "{dimension.space.200} {dimension.space.400}" + } + }, + "megamenu": { + "extend": { + "extItem": { + "caption": { + "color": "{color.fg.muted}", + "gap": "{dimension.space.100}" + } + }, + "iconSize": "{dimension.size.600}" + }, + "colorScheme": { + "light": { "root": { "background": "transparent" } }, + "dark": { "root": { "background": "transparent" } } + }, + "root": { + "borderColor": "transparent", + "borderRadius": "{dimension.borderRadius.400}", + "color": "{color.fg.default}", + "gap": "{dimension.space.100}", + "transitionDuration": "{effects.transition.duration.200}", + "verticalOrientation": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}" + }, + "horizontalOrientation": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}" + } + }, + "baseItem": { + "borderRadius": "{dimension.borderRadius.400}", + "padding": "{dimension.space.200} {dimension.space.400}" + }, + "item": { + "focusBackground": "{color.bg.neutral.weak.default}", + "activeBackground": "{color.bg.neutral.strong.default}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "activeColor": "{color.fg.inverse.active}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}", + "gap": "{dimension.space.200}", + "icon": { + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "activeColor": "{color.fg.inverse.active}" + } + }, + "overlay": { + "padding": "{dimension.space.100}", + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "borderRadius": "{dimension.borderRadius.400}", + "color": "{color.fg.default}", + "shadow": "{effects.elevation.400}", + "gap": "{dimension.space.none}" + }, + "submenu": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}" + }, + "submenuLabel": { + "padding": "{dimension.space.200} {dimension.space.400}", + "background": "transparent", + "color": "{color.fg.muted}", + "fontWeight": "{fonts.fontWeight.demibold}" + }, + "submenuIcon": { + "size": "{dimension.size.600}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "activeColor": "{color.fg.inverse.active}" + }, + "separator": { "borderColor": "{color.border.neutral.default}" }, + "mobileButton": { + "borderRadius": "{dimension.borderRadius.200}", + "size": "{dimension.size.900}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "hoverBackground": "{color.bg.neutral.weak.default}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + } + }, + "menu": { + "extend": { + "paddingX": "{dimension.space.100}", + "iconSize": "{dimension.size.600}", + "paddingY": "{dimension.space.100}", + "extItem": { + "caption": { + "gap": "{dimension.space.100}", + "color": "{color.fg.muted}" + }, + "activeBackground": "{color.bg.neutral.strong.default}", + "activeColor": "{color.fg.inverse.active}", + "icon": { "activeColor": "{color.fg.inverse.active}" } + } + }, + "root": { + "borderRadius": "{dimension.borderRadius.400}", + "shadow": "{effects.elevation.400}", + "transitionDuration": "{effects.transition.duration.200}", + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}" + }, + "list": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}" + }, + "submenuLabel": { + "padding": "{dimension.space.200} {dimension.space.400}", + "fontWeight": "{fonts.fontWeight.demibold}", + "background": "transparent", + "color": "{color.fg.muted}" + }, + "separator": { "borderColor": "{color.border.neutral.default}" }, + "item": { + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}", + "gap": "{dimension.space.200}", + "color": "{color.fg.default}", + "focusBackground": "{color.bg.surface.canvas.default}", + "focusColor": "{color.fg.hover}", + "icon": { + "color": "{color.fg.default}", + "focusColor": "{color.fg.hover}" + } + } + }, + "menubar": { + "extend": { + "iconSize": "{dimension.size.600}", + "extItem": { + "caption": { + "color": "{color.fg.muted}", + "gap": "{dimension.space.100}" + } + }, + "extSubmenuLabel": { + "padding": "{dimension.space.200} {dimension.space.400}", + "fontWeight": "{fonts.fontWeight.demibold}", + "background": "transparent", + "color": "{color.fg.muted}" + } + }, + "colorScheme": { + "light": { "root": { "background": "transparent" } }, + "dark": { "root": { "background": "transparent" } } + }, + "root": { + "borderColor": "transparent", + "borderRadius": "{dimension.borderRadius.200}", + "color": "{color.fg.default}", + "gap": "{dimension.space.100}", + "padding": "{dimension.space.100}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "baseItem": { + "borderRadius": "{dimension.borderRadius.200}", + "padding": "{dimension.space.200} {dimension.space.400}" + }, + "item": { + "focusBackground": "{color.bg.neutral.weak.default}", + "activeBackground": "{color.bg.neutral.strong.default}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "activeColor": "{color.fg.inverse.active}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}", + "gap": "{dimension.space.200}", + "icon": { + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "activeColor": "{color.fg.inverse.active}" + } + }, + "submenu": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}", + "background": "{color.bg.surface.raised.default}", + "borderColor": "{color.border.neutral.default}", + "borderRadius": "{dimension.borderRadius.400}", + "shadow": "{effects.elevation.400}", + "mobileIndent": "{dimension.space.400}", + "icon": { + "size": "{dimension.size.600}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "activeColor": "{color.fg.inverse.active}" + } + }, + "separator": { "borderColor": "{color.border.neutral.default}" }, + "mobileButton": { + "borderRadius": "{dimension.borderRadius.200}", + "size": "{dimension.size.900}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "hoverBackground": "{color.bg.neutral.weak.default}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + } + }, + "message": { + "extend": { + "width": "{dimension.size.2000}", + "extText": { "gap": "{dimension.space.100}" }, + "extInfo": { + "color": "{color.fg.status.info.default}", + "closeButton": { + "color": "{color.fg.status.info.default}", + "borderColor": "{color.border.status.info.default}" + }, + "caption": { "color": "{color.fg.default}" } + }, + "extAccentLine": { "width": "{dimension.size.100}" }, + "extCloseButton": { "width": "{dimension.borderWidth.100}" }, + "extSuccess": { + "color": "{color.fg.status.success.default}", + "closeButton": { + "color": "{color.fg.status.success.default}", + "borderColor": "{color.border.brand.default}" + }, + "caption": { "color": "{color.fg.default}" } + }, + "extWarn": { + "color": "{color.fg.status.warning.default}", + "closeButton": { + "color": "{color.fg.status.warning.default}", + "borderColor": "{color.border.status.warning.default}" + }, + "caption": { "color": "{color.fg.default}" } + }, + "extError": { + "color": "{color.fg.status.danger.default}", + "closeButton": { + "color": "{color.fg.status.danger.default}", + "borderColor": "{color.border.status.danger.default}" + }, + "caption": { "color": "{color.fg.default}" } + } + }, + "colorScheme": { + "light": { + "success": { + "background": "{color.bg.status.success.weak.default}", + "borderColor": "{color.border.brand.default}", + "color": "{color.fg.default}", + "shadow": "none", + "outlined": { + "color": "{color.fg.default}", + "borderColor": "{color.border.brand.default}" + }, + "closeButton": { + "hoverBackground": "{color.bg.status.success.weak.active}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "simple": { "color": "{color.fg.default}" } + }, + "outlined": { + "root": { "borderWidth": "{dimension.borderWidth.none}" }, + "closeButton": { + "hoverBackground": "transparent", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "outlined": { + "color": "transparent", + "borderColor": "transparent" + }, + "simple": { "color": "transparent" } + }, + "simple": { "content": { "padding": "{dimension.space.none}" } }, + "warn": { + "background": "{color.bg.status.warning.weak.default}", + "borderColor": "{color.border.status.warning.default}", + "color": "{color.fg.default}", + "shadow": "none", + "outlined": { + "color": "{color.fg.default}", + "borderColor": "{color.border.status.warning.default}" + }, + "closeButton": { + "hoverBackground": "{color.bg.status.warning.weak.active}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "simple": { "color": "{color.fg.default}" } + }, + "error": { + "background": "{color.bg.status.danger.weak.default}", + "borderColor": "{color.border.status.danger.default}", + "color": "{color.fg.default}", + "shadow": "none", + "outlined": { + "color": "{color.fg.default}", + "borderColor": "{color.border.status.danger.default}" + }, + "closeButton": { + "hoverBackground": "{color.bg.status.danger.weak.active}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "simple": { "color": "{color.fg.default}" } + }, + "secondary": { + "borderColor": "transparent", + "shadow": "none", + "closeButton": { + "hoverBackground": "transparent", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "simple": { "color": "transparent" }, + "outlined": { + "color": "transparent", + "borderColor": "transparent" + }, + "background": "{color.bg.neutral.weak.default}", + "color": "{color.fg.default}" + }, + "contrast": { + "borderColor": "transparent", + "shadow": "none", + "closeButton": { + "hoverBackground": "transparent", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "simple": { "color": "transparent" }, + "outlined": { + "color": "transparent", + "borderColor": "transparent" + }, + "background": "{color.bg.neutral.strong.default}", + "color": "{color.fg.on.fill.default}" + }, + "info": { + "background": "{color.bg.status.info.weak.default}", + "borderColor": "{color.border.status.info.default}", + "color": "{color.fg.default}", + "shadow": "none", + "closeButton": { + "hoverBackground": "{color.bg.status.info.weak.active}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "outlined": { + "color": "{color.fg.default}", + "borderColor": "{color.border.status.info.default}" + }, + "simple": { "color": "{color.fg.default}" } + } + }, + "dark": { + "contrast": { + "background": "{color.bg.surface.canvas.default}", + "borderColor": "transparent", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "transparent" + }, + "color": "{color.fg.default}", + "outlined": { + "borderColor": "transparent", + "color": "transparent" + }, + "shadow": "none", + "simple": { "color": "transparent" } + }, + "error": { + "background": "{color.bg.status.danger.weak.default}", + "borderColor": "{color.border.status.danger.default}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.status.danger.weak.active}" + }, + "color": "{color.fg.inverse.default}", + "outlined": { + "borderColor": "{color.border.status.danger.default}", + "color": "{color.fg.inverse.default}" + }, + "shadow": "none", + "simple": { "color": "{color.fg.inverse.default}" } + }, + "info": { + "background": "{color.bg.status.info.weak.default}", + "borderColor": "{color.border.status.info.default}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.status.info.weak.active}" + }, + "color": "{color.fg.inverse.default}", + "outlined": { + "borderColor": "{color.border.status.info.default}", + "color": "{color.fg.inverse.default}" + }, + "shadow": "none", + "simple": { "color": "{color.fg.inverse.default}" } + }, + "secondary": { + "background": "{color.bg.neutral.strong.default}", + "borderColor": "transparent", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "transparent" + }, + "color": "{color.fg.inverse.default}", + "outlined": { + "borderColor": "transparent", + "color": "transparent" + }, + "shadow": "none", + "simple": { "color": "transparent" } + }, + "success": { + "background": "{color.bg.status.success.weak.default}", + "borderColor": "{color.border.brand.default}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.status.success.weak.active}" + }, + "color": "{color.fg.inverse.default}", + "outlined": { + "borderColor": "{color.border.brand.default}", + "color": "{color.fg.inverse.default}" + }, + "shadow": "none", + "simple": { "color": "{color.fg.inverse.default}" } + }, + "warn": { + "background": "{color.bg.status.warning.weak.default}", + "borderColor": "{color.border.status.warning.default}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.status.warning.weak.active}" + }, + "color": "{color.fg.inverse.default}", + "outlined": { + "borderColor": "{color.border.status.warning.default}", + "color": "{color.fg.inverse.default}" + }, + "shadow": "none", + "simple": { "color": "{color.fg.inverse.default}" } + }, + "outlined": { + "root": { "borderWidth": "{dimension.borderWidth.none}" }, + "closeButton": { + "hoverBackground": "transparent", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + }, + "outlined": { + "color": "transparent", + "borderColor": "transparent" + }, + "simple": { "color": "transparent" } + }, + "simple": { "content": { "padding": "{dimension.space.none}" } } + } + }, + "root": { + "borderRadius": "{dimension.borderRadius.400}", + "borderWidth": "{dimension.borderWidth.100}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "content": { + "padding": "{dimension.space.400}", + "gap": "{dimension.space.400}", + "sm": { "padding": "{dimension.space.400}" }, + "lg": { "padding": "{dimension.space.400}" } + }, + "text": { + "fontSize": "{fonts.fontSize.300}", + "fontWeight": "{fonts.fontWeight.bold}", + "sm": { "fontSize": "{fonts.fontSize.300}" }, + "lg": { "fontSize": "{fonts.fontSize.300}" } + }, + "icon": { + "size": "{dimension.size.1000}", + "sm": { "size": "{dimension.size.1000}" }, + "lg": { "size": "{dimension.size.1000}" } + }, + "closeButton": { + "width": "{dimension.size.900}", + "height": "{dimension.size.900}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "offset": "{dimension.focusRing.offset}" + } + }, + "closeIcon": { + "size": "{dimension.size.450}", + "sm": { "size": "{dimension.size.450}" }, + "lg": { "size": "{dimension.size.450}" } + }, + "outlined": { "root": { "borderWidth": "{dimension.borderWidth.100}" } }, + "simple": { "content": { "padding": "{dimension.space.none}" } } + }, + "metergroup": { + "extend": { "extLabel": { "color": "{color.fg.muted}" } }, + "root": { + "borderRadius": "{dimension.borderRadius.400}", + "gap": "{dimension.space.400}" + }, + "meters": { + "size": "{dimension.size.200}", + "background": "{color.bg.neutral.medium.default}" + }, + "label": { "gap": "{dimension.space.100}" }, + "labelMarker": { "size": "{dimension.size.200}" }, + "labelIcon": { "size": "{dimension.size.450}" }, + "labelList": { + "verticalGap": "{dimension.space.200}", + "horizontalGap": "{dimension.space.400}" + } + }, + "multiselect": { + "extend": { + "paddingX": "{dimension.space.150}", + "paddingY": "{dimension.space.150}", + "borderWidth": "{dimension.borderWidth.100}", + "iconSize": "{dimension.size.450}", + "width": "{dimension.size.1700}", + "readonlyBackground": "{color.bg.neutral.weak.default}" + }, + "root": { + "shadow": "{effects.elevation.none}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}", + "sm": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.200}", + "paddingY": "{dimension.space.200}" + }, + "lg": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}" + }, + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}", + "color": "{color.border.focus}" + }, + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.strong}", + "color": "{color.fg.default}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "disabledColor": "{color.fg.muted}", + "filledBackground": "{color.bg.surface.default.default}", + "filledFocusBackground": "{color.bg.surface.default.default}", + "filledHoverBackground": "{color.bg.surface.default.default}", + "focusBorderColor": "{color.border.brand.strong}", + "hoverBorderColor": "{color.border.brand.strong}", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "invalidPlaceholderColor": "{color.fg.status.danger.hover}", + "placeholderColor": "{color.fg.muted}" + }, + "dropdown": { + "width": "{dimension.size.1700}", + "color": "{color.fg.active}" + }, + "overlay": { + "borderRadius": "{dimension.borderRadius.400}", + "shadow": "{effects.elevation.400}", + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}" + }, + "list": { + "padding": "{dimension.space.100}", + "header": { + "padding": "{dimension.space.400} {dimension.space.400} {dimension.space.none} {dimension.space.400}" + }, + "gap": "{dimension.space.100}" + }, + "chip": { "borderRadius": "{dimension.borderRadius.200}" }, + "option": { + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}", + "gap": "{dimension.space.200}", + "color": "{color.fg.default}", + "focusBackground": "{color.bg.neutral.weak.default}", + "focusColor": "{color.fg.default}", + "selectedBackground": "{color.bg.neutral.strong.selected}", + "selectedColor": "{color.fg.on.fill.default}", + "selectedFocusBackground": "{color.bg.neutral.strong.active}", + "selectedFocusColor": "{color.fg.on.fill.active}" + }, + "optionGroup": { + "fontWeight": "{fonts.fontWeight.demibold}", + "padding": "{dimension.space.200} {dimension.space.400}", + "background": "{color.bg.surface.raised.default}", + "color": "{color.fg.muted}" + }, + "emptyMessage": { + "padding": "{dimension.space.200} {dimension.space.400}" + }, + "clearIcon": { "color": "{color.fg.active}" } + }, + "paginator": { + "root": { + "padding": "{dimension.space.none} {dimension.space.200}", + "gap": "{dimension.space.200}", + "borderRadius": "{dimension.borderRadius.400}", + "background": "transparent", + "color": "{color.fg.default}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "currentPageReport": { "color": "{color.fg.muted}" }, + "navButton": { + "background": "transparent", + "hoverBackground": "{color.bg.neutral.weak.default}", + "selectedBackground": "{color.bg.neutral.strong.selected}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "selectedColor": "{color.fg.on.fill.default}", + "width": "{dimension.size.1100}", + "height": "{dimension.size.1100}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "focus": "{effects.elevation.200}", + "shadow": "{effects.elevation.none}" + } + }, + "jumpToPageInput": { "maxWidth": "{dimension.size.1500}" } + }, + "panelmenu": { + "extend": { + "iconSize": "{dimension.size.600}", + "extPanel": { "gap": "{dimension.space.100}" }, + "extItem": { + "activeBackground": "{color.bg.neutral.strong.default}", + "activeColor": "{color.fg.inverse.active}", + "caption": { + "color": "{color.fg.muted}", + "gap": "{dimension.space.100}" + } + } + }, + "root": { + "gap": "{dimension.space.100}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "panel": { + "background": "transparent", + "borderColor": "transparent", + "borderWidth": "{dimension.borderWidth.100}", + "color": "{color.fg.default}", + "padding": "{dimension.space.100}", + "borderRadius": "{dimension.borderRadius.400}", + "first": { + "borderWidth": "{dimension.borderWidth.100} {dimension.borderWidth.100} {dimension.borderWidth.none} {dimension.borderWidth.100}", + "topBorderRadius": "{dimension.borderRadius.400}" + }, + "last": { + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.100} {dimension.borderWidth.100}", + "topBorderRadius": "{dimension.borderRadius.400}", + "bottomBorderRadius": "{dimension.borderRadius.400}" + } + }, + "item": { + "focusBackground": "{color.bg.neutral.weak.default}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "gap": "{dimension.space.200}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}", + "icon": { + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}" + } + }, + "submenu": { "indent": "{dimension.space.700}" }, + "separator": { "borderColor": "{color.border.neutral.default}" }, + "submenuIcon": { + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}" + } + }, + "password": { + "extend": { "borderWidth": "{dimension.borderWidth.100}" }, + "colorScheme": { + "light": { + "strength": { + "weakBackground": "{color.bg.status.danger.strong.active}", + "mediumBackground": "{color.bg.status.warning.strong.active}", + "strongBackground": "{color.bg.brand.strong.hover}" + }, + "icon": { "color": "{color.fg.muted}" } + }, + "dark": { + "strength": { + "mediumBackground": "{color.bg.status.warning.strong.active}", + "strongBackground": "{color.bg.status.success.strong.hover}", + "weakBackground": "{color.bg.status.danger.strong.active}" + }, + "icon": { "color": "{color.fg.inverse.muted}" } + } + }, + "meter": { + "background": "{color.bg.neutral.medium.default}", + "borderRadius": "{dimension.borderRadius.400}", + "height": "{dimension.size.200}" + }, + "overlay": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.strong}", + "borderRadius": "{dimension.borderRadius.200}", + "color": "{color.fg.default}", + "padding": "{dimension.space.400}", + "shadow": "{effects.elevation.400}" + }, + "content": { "gap": "{dimension.space.200}" }, + "icon": { "color": "{color.fg.default}" } + }, + "popover": { + "extend": { + "borderWidth": "{dimension.borderWidth.100}", + "arrow": { + "width": "{dimension.size.350}", + "height": "{dimension.size.200}" + } + }, + "root": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.strong}", + "color": "{color.fg.default}", + "borderRadius": "{dimension.borderRadius.200}", + "shadow": "{effects.elevation.400}", + "gutter": "{dimension.space.100}", + "arrowOffset": "{dimension.space.600}" + }, + "content": { "padding": "{dimension.space.400}" } + }, + "progressbar": { + "label": { + "color": "{color.fg.default}", + "fontSize": "{fonts.fontSize.100}", + "fontWeight": "{fonts.fontWeight.regular}" + }, + "root": { + "background": "{color.bg.surface.canvas.hover}", + "borderRadius": "{dimension.borderRadius.400}", + "height": "{dimension.size.450}" + }, + "value": { "background": "{color.bg.brand.strong.default}" } + }, + "progressspinner": { + "extend": { + "small": "{dimension.size.450}", + "medium": "{dimension.size.900}", + "large": "{dimension.size.1200}", + "xlarge": "{dimension.size.1300}" + }, + "colorScheme": { + "light": { + "root": { + "colorOne": "{color.fg.brand.default}", + "colorTwo": "{color.fg.status.info.default}", + "colorThree": "{color.fg.status.danger.default}", + "colorFour": "{color.fg.status.warning.default}" + } + }, + "dark": { + "root": { + "colorFour": "{color.fg.status.warning.muted}", + "colorOne": "{color.fg.brand.muted}", + "colorThree": "{color.fg.status.danger.muted}", + "colorTwo": "{color.fg.status.info.muted}" + } + } + }, + "root": { "borderWidth": "{dimension.borderWidth.300}" } + }, + "radiobutton": { + "root": { + "width": "{dimension.size.700}", + "height": "{dimension.size.700}", + "background": "{color.bg.surface.default.default}", + "checkedBackground": "{color.bg.neutral.strong.default}", + "checkedHoverBackground": "{color.bg.neutral.strong.hover}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "filledBackground": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.strong}", + "hoverBorderColor": "{color.border.neutral.bold.default}", + "focusBorderColor": "{color.border.neutral.strong}", + "checkedBorderColor": "{color.border.neutral.bold.default}", + "checkedHoverBorderColor": "{color.border.neutral.bold.default}", + "checkedFocusBorderColor": "{color.border.neutral.bold.default}", + "checkedDisabledBorderColor": "{color.border.neutral.strong}", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "shadow": "{effects.elevation.none}", + "transitionDuration": "{effects.transition.duration.200}", + "focusRing": { + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}", + "style": "none", + "width": "{dimension.focusRing.width}" + }, + "lg": { + "height": "{dimension.size.600}", + "width": "{dimension.size.600}" + }, + "sm": { + "height": "{dimension.size.200}", + "width": "{dimension.size.200}" + } + }, + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + }, + "sm": { + "width": "{dimension.size.450}", + "height": "{dimension.size.450}" + }, + "lg": { + "width": "{dimension.size.600}", + "height": "{dimension.size.600}" + }, + "icon": { + "size": "{dimension.size.350}", + "checkedColor": "{color.fg.on.fill.default}", + "checkedHoverColor": "{color.fg.on.fill.hover}", + "disabledColor": "{color.fg.muted}", + "sm": { "size": "{dimension.size.200}" }, + "lg": { "size": "{dimension.size.450}" } + } + }, + "rating": { + "root": { + "gap": "{dimension.space.200}", + "transitionDuration": "{effects.transition.duration.200}", + "focusRing": { + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}", + "style": "none", + "width": "{dimension.focusRing.width}" + } + }, + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + }, + "icon": { + "size": "{dimension.size.700}", + "color": "{color.fg.muted}", + "hoverColor": "{color.fg.status.warning.default}", + "activeColor": "{color.fg.status.warning.default}" + } + }, + "ripple": { + "colorScheme": { + "light": { + "root": { "background": "{color.bg.neutral.medium.default}" } + }, + "dark": { + "root": { "background": "{color.bg.neutral.medium.default}" } + } + } + }, + "scrollpanel": { + "colorScheme": { + "light": { "bar": { "background": "{color.bg.neutral.weak.active}" } }, + "dark": { "bar": { "background": "{color.bg.neutral.strong.active}" } } + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" }, + "bar": { + "size": "{dimension.size.200}", + "borderRadius": "{dimension.borderRadius.200}", + "focusRing": { + "width": "{dimension.size.none}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + } + }, + "select": { + "extend": { + "extOption": { + "background": "{color.bg.surface.raised.default}", + "gap": "{dimension.space.200}" + }, + "extOptionGroup": { "gap": "{dimension.space.200}" }, + "readonlyBackground": "{color.bg.neutral.weak.default}", + "borderWidth": "{dimension.borderWidth.100}", + "iconSize": "{dimension.size.450}" + }, + "root": { + "background": "{color.bg.surface.default.default}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "filledBackground": "{color.bg.surface.default.default}", + "filledHoverBackground": "{color.bg.surface.default.default}", + "filledFocusBackground": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.strong}", + "hoverBorderColor": "{color.border.brand.strong}", + "focusBorderColor": "{color.border.brand.strong}", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "color": "{color.fg.default}", + "disabledColor": "{color.fg.muted}", + "placeholderColor": "{color.fg.muted}", + "invalidPlaceholderColor": "{color.fg.status.danger.hover}", + "shadow": "{effects.elevation.none}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}", + "sm": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}" + }, + "lg": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}" + }, + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}" + } + }, + "dropdown": { + "width": "{dimension.size.1700}", + "color": "{color.fg.active}" + }, + "overlay": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "borderRadius": "{dimension.borderRadius.400}", + "color": "{color.fg.default}", + "shadow": "{effects.elevation.400}" + }, + "list": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}", + "header": { + "padding": "{dimension.space.400} {dimension.space.400} {dimension.space.none} {dimension.space.400}" + } + }, + "option": { + "focusBackground": "{color.bg.neutral.weak.default}", + "selectedBackground": "{color.bg.neutral.strong.selected}", + "selectedFocusBackground": "{color.bg.neutral.strong.active}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "selectedColor": "{color.fg.on.fill.default}", + "selectedFocusColor": "{color.fg.on.fill.active}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}" + }, + "optionGroup": { + "background": "{color.bg.surface.raised.default}", + "color": "{color.fg.muted}", + "fontWeight": "{fonts.fontWeight.demibold}", + "padding": "{dimension.space.200} {dimension.space.400}" + }, + "clearIcon": { "color": "{color.fg.active}" }, + "checkmark": { + "color": "{color.fg.default}", + "gutterStart": "{dimension.space.negative.200}", + "gutterEnd": "{dimension.space.200}" + }, + "emptyMessage": { + "padding": "{dimension.space.200} {dimension.space.400}" + } + }, + "selectbutton": { + "extend": { + "gap": "{dimension.space.100}", + "paddingX": "{dimension.space.100}", + "paddingY": "{dimension.space.100}", + "iconSize": { + "sm": "{dimension.size.450}", + "md": "{dimension.size.600}", + "lg": "{dimension.size.700}", + "xlg": "{dimension.size.800}" + }, + "checkedBackground": "{color.bg.surface.raised.default}", + "checkedBorderColor": "{color.border.neutral.inverse}", + "checkedColor": "{color.fg.active}", + "ext": { "borderRadius": "{dimension.borderRadius.200}" } + }, + "colorScheme": { + "light": { + "root": { + "invalidBorderColor": "{color.border.status.danger.subtle}" + }, + "extend": { "background": "{color.bg.neutral.medium.default}" } + }, + "dark": { + "root": { + "invalidBorderColor": "{color.border.status.danger.strong}" + }, + "extend": { "background": "{color.bg.neutral.strong.hover}" } + } + }, + "root": { "borderRadius": "{dimension.borderRadius.400}" } + }, + "skeleton": { + "extend": { + "minWidth": "{dimension.size.900}", + "height": "{dimension.size.900}" + }, + "colorScheme": { + "light": { + "root": { + "background": "{color.bg.surface.canvas.hover}", + "animationBackground": "{color.bg.surface.canvas.default}" + } + }, + "dark": { + "root": { + "background": "{color.bg.surface.raised.default}", + "animationBackground": "{color.bg.surface.raised.selected}" + } + } + }, + "root": { "borderRadius": "{dimension.borderRadius.400}" } + }, + "slider": { + "colorScheme": { + "light": { + "handle": { + "content": { "background": "{color.bg.surface.default.default}" } + } + }, + "dark": { + "handle": { + "content": { "background": "{color.bg.surface.canvas.default}" } + } + } + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" }, + "track": { + "background": "{color.bg.neutral.medium.default}", + "borderRadius": "{dimension.borderRadius.400}", + "size": "{dimension.size.100}" + }, + "range": { "background": "{color.bg.neutral.strong.default}" }, + "handle": { + "width": "{dimension.size.600}", + "height": "{dimension.size.600}", + "borderRadius": "{dimension.borderRadius.max}", + "background": "{color.bg.neutral.strong.default}", + "hoverBackground": "{color.bg.neutral.strong.default}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + }, + "content": { + "borderRadius": "{dimension.borderRadius.max}", + "hoverBackground": "{color.bg.neutral.strong.default}", + "width": "{dimension.size.350}", + "height": "{dimension.size.350}", + "shadow": "none" + } + } + }, + "splitter": { + "colorScheme": { + "light": { + "handle": { "background": "{color.bg.neutral.strong.default}" } + }, + "dark": { + "handle": { "background": "{color.bg.surface.canvas.default}" } + } + }, + "gutter": { "background": "{color.bg.neutral.weak.default}" }, + "root": { + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "handle": { + "size": "{dimension.size.100}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + } + }, + "stepper": { + "extend": { + "extCaption": { "gap": "{dimension.space.100}" }, + "extStepNumber": { + "invalidBackground": "{color.bg.status.danger.strong.hover}", + "invalidColor": "{color.fg.on.status.danger.default}", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "borderWidth": "{dimension.borderWidth.100}", + "iconSize": "{dimension.size.700}" + } + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" }, + "separator": { + "background": "{color.bg.neutral.medium.default}", + "activeBackground": "{color.bg.neutral.strong.default}", + "margin": "{dimension.space.none} {dimension.space.none} {dimension.space.none} {dimension.space.700}", + "size": "{dimension.borderWidth.100}" + }, + "step": { + "padding": "{dimension.space.200}", + "gap": "{dimension.space.200}" + }, + "stepHeader": { + "padding": "{dimension.space.none}", + "borderRadius": "{dimension.borderRadius.none}", + "gap": "{dimension.space.200}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "stepTitle": { + "color": "{color.fg.default}", + "activeColor": "{color.fg.default}", + "fontWeight": "{fonts.fontWeight.regular}" + }, + "stepNumber": { + "background": "{color.bg.surface.raised.default}", + "activeBackground": "{color.bg.brand.strong.default}", + "borderColor": "{color.border.neutral.default}", + "activeBorderColor": "{color.border.brand.default}", + "color": "{color.fg.default}", + "activeColor": "{color.fg.default}", + "size": "{dimension.size.700}", + "fontSize": "{fonts.fontSize.300}", + "fontWeight": "{fonts.fontWeight.bold}", + "borderRadius": "{dimension.borderRadius.max}", + "shadow": "none" + }, + "steppanels": { "padding": "{dimension.space.400}" }, + "steppanel": { + "background": "{color.bg.surface.raised.default}", + "color": "{color.fg.default}", + "padding": "{dimension.space.none}", + "indent": "{dimension.space.none}" + } + }, + "steps": { + "itemLink": { + "gap": "{dimension.space.200}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}", + "style": "none", + "width": "{dimension.focusRing.width}" + } + }, + "itemLabel": { + "fontWeight": "{fonts.fontWeight.regular}", + "activeColor": "{color.fg.hover}", + "color": "{color.fg.default}" + }, + "itemNumber": { + "background": "{color.bg.surface.raised.default}", + "size": "{dimension.size.900}", + "fontSize": "{fonts.fontSize.300}", + "fontWeight": "{fonts.fontWeight.bold}", + "borderRadius": "{dimension.borderRadius.max}", + "shadow": "none", + "activeBackground": "{color.bg.surface.raised.default}", + "activeBorderColor": "{color.border.neutral.default}", + "activeColor": "{color.fg.hover}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}" + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" }, + "separator": { "background": "{color.bg.neutral.medium.default}" } + }, + "tabs": { + "colorScheme": { + "light": { + "navButton": { "shadow": "none" }, + "tab": { + "background": "transparent", + "hoverBackground": "transparent", + "activeBackground": "transparent" + } + }, + "dark": { + "navButton": { "shadow": "none" }, + "tab": { + "activeBackground": "transparent", + "background": "transparent", + "hoverBackground": "transparent" + } + } + }, + "root": { "transitionDuration": "{effects.transition.duration.200}" }, + "tablist": { + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.none}", + "background": "transparent", + "borderColor": "{color.border.neutral.default}" + }, + "tab": { + "borderWidth": "{dimension.borderWidth.none}", + "borderColor": "{color.border.neutral.default}", + "hoverBorderColor": "{color.border.neutral.default}", + "activeBorderColor": "{color.border.neutral.bold.hover}", + "color": "{color.fg.muted}", + "hoverColor": "{color.fg.default}", + "activeColor": "{color.fg.default}", + "padding": "{dimension.space.400}", + "fontWeight": "{fonts.fontWeight.demibold}", + "margin": "{dimension.space.none}", + "gap": "{dimension.space.200}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "tabpanel": { + "background": "transparent", + "color": "{color.fg.default}", + "padding": "{dimension.space.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "navButton": { + "background": "{color.bg.surface.raised.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}", + "width": "{dimension.size.700}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + } + }, + "activeBar": { + "height": "{dimension.size.50}", + "bottom": "{dimension.space.negative.50}", + "background": "{color.bg.neutral.strong.default}" + } + }, + "toast": { + "extend": { + "extInfo": { + "color": "{color.fg.status.info.default}", + "closeButton": { + "color": "{color.fg.status.info.default}", + "borderColor": "{color.border.status.info.default}" + }, + "caption": { "color": "{color.fg.default}" } + }, + "extAccentLine": { "width": "{dimension.size.100}" }, + "extCloseButton": { "width": "{dimension.borderWidth.100}" }, + "extSuccess": { + "color": "{color.fg.status.success.default}", + "closeButton": { + "color": "{color.fg.status.success.default}", + "borderColor": "{color.border.brand.default}" + }, + "caption": { "color": "{color.fg.default}" } + }, + "extWarn": { + "color": "{color.fg.status.warning.default}", + "closeButton": { + "color": "{color.fg.status.warning.default}", + "borderColor": "{color.border.status.warning.default}" + }, + "caption": { "color": "{color.fg.default}" } + }, + "extError": { + "color": "{color.fg.status.danger.default}", + "closeButton": { + "color": "{color.fg.status.danger.default}", + "borderColor": "{color.border.status.danger.default}" + }, + "caption": { "color": "{color.fg.default}" } + } + }, + "colorScheme": { + "light": { + "info": { + "background": "{color.bg.status.info.weak.default}", + "borderColor": "{color.border.status.info.default}", + "color": "{color.fg.default}", + "detailColor": "{color.fg.default}", + "shadow": "{effects.elevation.400}", + "closeButton": { + "hoverBackground": "{color.bg.status.info.weak.active}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + } + }, + "success": { + "background": "{color.bg.status.success.weak.default}", + "borderColor": "{color.border.brand.default}", + "color": "{color.fg.default}", + "detailColor": "{color.fg.default}", + "shadow": "{effects.elevation.400}", + "closeButton": { + "hoverBackground": "{color.bg.status.success.weak.active}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + } + }, + "warn": { + "background": "{color.bg.status.warning.weak.default}", + "borderColor": "{color.border.status.warning.default}", + "color": "{color.fg.default}", + "detailColor": "{color.fg.default}", + "shadow": "{effects.elevation.400}", + "closeButton": { + "hoverBackground": "{color.bg.status.warning.weak.active}", + "focusRing": { "color": "{color.border.focus}", "shadow": "none" } + } + }, + "error": { + "background": "{color.bg.status.danger.weak.default}", + "borderColor": "{color.border.status.danger.default}", + "color": "{color.fg.default}", + "detailColor": "{color.fg.default}", + "shadow": "{effects.elevation.400}", + "closeButton": { + "hoverBackground": "{color.bg.status.danger.weak.active}", + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + } + } + }, + "secondary": { + "shadow": "{effects.elevation.400}", + "background": "{color.bg.neutral.weak.default}", + "borderColor": "{color.border.neutral.strong}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + }, + "hoverBackground": "{color.bg.neutral.weak.default}" + }, + "color": "{color.fg.default}", + "detailColor": "{color.fg.subtle}" + }, + "contrast": { + "shadow": "{effects.elevation.400}", + "background": "{color.bg.neutral.strong.default}", + "borderColor": "{color.border.neutral.bold.default}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + }, + "hoverBackground": "{color.bg.neutral.strong.hover}" + }, + "color": "{color.fg.on.fill.default}", + "detailColor": "{color.fg.on.fill.muted}" + }, + "root": { "blur": "{effects.blur.none}" } + }, + "dark": { + "contrast": { + "background": "{color.bg.surface.canvas.default}", + "borderColor": "{color.border.neutral.inverse}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + }, + "hoverBackground": "{color.bg.surface.canvas.hover}" + }, + "color": "{color.fg.default}", + "detailColor": "{color.fg.on.fill.muted}", + "shadow": "{effects.elevation.400}" + }, + "error": { + "background": "{color.bg.status.danger.weak.default}", + "borderColor": "{color.border.status.danger.default}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.status.danger.weak.active}" + }, + "color": "{color.fg.inverse.default}", + "detailColor": "{color.fg.inverse.default}", + "shadow": "{effects.elevation.400}" + }, + "info": { + "background": "{color.bg.status.info.weak.default}", + "borderColor": "{color.border.status.info.default}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.status.info.weak.active}" + }, + "color": "{color.fg.inverse.default}", + "detailColor": "{color.fg.inverse.default}", + "shadow": "{effects.elevation.400}" + }, + "root": { "blur": "{effects.blur.none}" }, + "secondary": { + "background": "{color.bg.neutral.strong.default}", + "borderColor": "{color.border.neutral.strong}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.none}" + }, + "hoverBackground": "{color.bg.neutral.strong.selected}" + }, + "color": "{color.fg.inverse.default}", + "detailColor": "{color.fg.subtle}", + "shadow": "{effects.elevation.400}" + }, + "success": { + "background": "{color.bg.status.success.weak.default}", + "borderColor": "{color.border.brand.default}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "{effects.elevation.200}" + }, + "hoverBackground": "{color.bg.status.success.weak.active}" + }, + "color": "{color.fg.inverse.default}", + "detailColor": "{color.fg.inverse.default}", + "shadow": "{effects.elevation.400}" + }, + "warn": { + "background": "{color.bg.status.warning.weak.default}", + "borderColor": "{color.border.status.warning.default}", + "closeButton": { + "focusRing": { + "color": "{color.border.focus}", + "shadow": "none" + }, + "hoverBackground": "{color.bg.status.warning.weak.active}" + }, + "color": "{color.fg.inverse.default}", + "detailColor": "{color.fg.inverse.default}", + "shadow": "{effects.elevation.400}" + } + } + }, + "root": { + "width": "{dimension.size.2000}", + "borderWidth": "{dimension.borderWidth.100}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "icon": { "size": "{dimension.size.1000}" }, + "content": { + "padding": "{dimension.space.400}", + "gap": "{dimension.space.400}" + }, + "text": { "gap": "{dimension.space.100}" }, + "summary": { + "fontWeight": "{fonts.fontWeight.bold}", + "fontSize": "{fonts.fontSize.300}" + }, + "detail": { + "fontWeight": "{fonts.fontWeight.regular}", + "fontSize": "{fonts.fontSize.200}" + }, + "closeButton": { + "width": "{dimension.size.900}", + "height": "{dimension.size.900}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "offset": "{dimension.focusRing.offset}" + } + }, + "closeIcon": { "size": "{dimension.size.450}" } + }, + "tag": { + "colorScheme": { + "light": { + "primary": { + "background": "{color.bg.brand.strong.default}", + "color": "{color.fg.default}" + }, + "secondary": { + "background": "{color.bg.neutral.medium.default}", + "color": "{color.fg.default}" + }, + "success": { + "background": "{color.bg.status.success.strong.hover}", + "color": "{color.fg.on.status.success.default}" + }, + "info": { + "background": "{color.bg.status.info.strong.default}", + "color": "{color.fg.on.status.info.default}" + }, + "warn": { + "background": "{color.bg.status.warning.strong.default}", + "color": "{color.fg.on.status.warning.default}" + }, + "danger": { + "background": "{color.bg.status.danger.strong.default}", + "color": "{color.fg.on.status.danger.default}" + }, + "contrast": { + "background": "{color.bg.neutral.strong.default}", + "color": "{color.fg.on.fill.default}" + } + }, + "dark": { + "contrast": { + "background": "{color.bg.surface.canvas.default}", + "color": "{color.fg.default}" + }, + "danger": { + "background": "{color.bg.status.danger.strong.default}", + "color": "{color.fg.on.status.danger.default}" + }, + "info": { + "background": "{color.bg.status.info.strong.default}", + "color": "{color.fg.on.status.info.default}" + }, + "primary": { + "background": "{color.bg.brand.strong.default}", + "color": "{color.fg.inverse.default}" + }, + "secondary": { + "background": "{color.bg.neutral.strong.hover}", + "color": "{color.fg.inverse.default}" + }, + "success": { + "background": "{color.bg.brand.strong.hover}", + "color": "{color.fg.on.status.success.default}" + }, + "warn": { + "background": "{color.bg.status.warning.strong.default}", + "color": "{color.fg.on.status.warning.default}" + } + } + }, + "root": { + "fontSize": "{fonts.fontSize.100}", + "fontWeight": "{fonts.fontWeight.regular}", + "padding": "{dimension.space.100} {dimension.space.200}", + "gap": "{dimension.space.100}", + "borderRadius": "{dimension.borderRadius.200}", + "roundedBorderRadius": "{dimension.borderRadius.max}" + }, + "icon": { "size": "{dimension.size.450}" } + }, + "textarea": { + "extend": { + "readonlyBackground": "{color.bg.neutral.weak.default}", + "borderWidth": "{dimension.borderWidth.100}", + "iconSize": "{dimension.size.450}", + "minHeight": "{dimension.size.1500}" + }, + "root": { + "background": "{color.bg.surface.default.default}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "filledBackground": "{color.bg.surface.default.default}", + "filledHoverBackground": "{color.bg.surface.default.default}", + "filledFocusBackground": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.strong}", + "hoverBorderColor": "{color.border.brand.strong}", + "focusBorderColor": "{color.border.brand.strong}", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "color": "{color.fg.active}", + "disabledColor": "{color.fg.muted}", + "placeholderColor": "{color.fg.muted}", + "invalidPlaceholderColor": "{color.fg.status.danger.hover}", + "shadow": "{effects.elevation.none}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}", + "borderRadius": "{dimension.borderRadius.400}", + "transitionDuration": "{effects.transition.duration.200}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}" + }, + "lg": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}" + }, + "sm": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}" + } + }, + "sm": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.200}", + "paddingY": "{dimension.space.200}" + }, + "lg": { + "fontSize": "{fonts.fontSize.300}", + "paddingX": "{dimension.space.400}", + "paddingY": "{dimension.space.400}" + } + }, + "tieredmenu": { + "extend": { + "iconSize": "{dimension.size.600}", + "extSubmenu": { + "borderColor": "{color.border.neutral.default}", + "background": "{color.bg.surface.raised.default}" + }, + "extItem": { + "caption": { + "gap": "{dimension.space.100}", + "color": "{color.fg.muted}" + } + } + }, + "root": { + "background": "{color.bg.surface.default.default}", + "borderColor": "transparent", + "color": "{color.fg.default}", + "borderRadius": "{dimension.borderRadius.400}", + "shadow": "{effects.elevation.400}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "list": { + "padding": "{dimension.space.100}", + "gap": "{dimension.space.100}" + }, + "item": { + "focusBackground": "{color.bg.neutral.weak.default}", + "activeBackground": "{color.bg.neutral.strong.default}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "activeColor": "{color.fg.inverse.active}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}", + "gap": "{dimension.space.200}", + "icon": { + "color": "{color.fg.default}", + "focusColor": "{color.fg.default}", + "activeColor": "{color.fg.inverse.active}" + } + }, + "submenu": { "mobileIndent": "{dimension.space.400}" }, + "separator": { "borderColor": "{color.border.neutral.default}" }, + "submenuIcon": { + "activeColor": "{color.fg.hover}", + "color": "{color.fg.default}", + "focusColor": "{color.fg.hover}", + "size": "{dimension.size.400}" + } + }, + "timeline": { + "extend": { "extEvent": { "gap": "{dimension.space.100}" } }, + "event": { "minHeight": "{dimension.size.1400}" }, + "vertical": { + "eventContent": { + "padding": "{dimension.space.none} {dimension.space.600}" + } + }, + "horizontal": { + "eventContent": { + "padding": "{dimension.space.600} {dimension.space.none}" + } + }, + "eventMarker": { + "size": "{dimension.size.450}", + "borderRadius": "{dimension.borderRadius.400}", + "borderWidth": "{dimension.borderWidth.300}", + "background": "{color.bg.surface.raised.default}", + "borderColor": "{color.border.brand.default}", + "content": { + "borderRadius": "{dimension.borderRadius.400}", + "size": "{dimension.size.350}", + "background": "transparent", + "insetShadow": "none" + } + }, + "eventConnector": { + "color": "{color.border.neutral.default}", + "size": "{dimension.borderWidth.100}" + } + }, + "togglebutton": { + "extend": { + "ext": { "gap": "{dimension.space.400}" }, + "iconSize": { + "sm": "{dimension.size.450}", + "md": "{dimension.size.600}", + "lg": "{dimension.size.700}" + }, + "iconOnlyWidth": "{dimension.size.1100}", + "hoverBorderColor": "{color.border.neutral.strong}", + "checkedHoverColor": "{color.fg.on.fill.hover}", + "checkedHoverBackground": "{color.bg.neutral.strong.hover}", + "checkedHoverBorderColor": "{color.border.neutral.bold.hover}", + "extXlg": { + "padding": "{dimension.space.600} {dimension.space.600}", + "iconOnlyWidth": "{dimension.size.1400}" + }, + "extSm": { "iconOnlyWidth": "{dimension.size.900}" }, + "extLg": { "iconOnlyWidth": "{dimension.size.1300}" } + }, + "colorScheme": { + "light": { + "root": { + "background": "{color.bg.surface.canvas.hover}", + "hoverBackground": "{color.bg.surface.canvas.active}", + "borderColor": "{color.border.neutral.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.default}", + "checkedBackground": "{color.bg.neutral.strong.default}", + "checkedColor": "{color.fg.on.fill.default}", + "checkedBorderColor": "{color.border.neutral.bold.default}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "disabledBorderColor": "{color.border.neutral.default}", + "disabledColor": "{color.fg.muted}", + "invalidBorderColor": "{color.border.status.danger.subtle}" + }, + "icon": { + "color": "{color.fg.default}", + "hoverColor": "{color.fg.default}", + "checkedColor": "{color.fg.on.fill.default}", + "disabledColor": "{color.fg.muted}" + }, + "content": { "checkedBackground": "transparent" } + }, + "dark": { + "root": { + "hoverBackground": "{color.bg.neutral.strong.active}", + "background": "{color.bg.neutral.strong.hover}", + "borderColor": "{color.border.neutral.bold.hover}", + "color": "{color.fg.inverse.default}", + "hoverColor": "{color.fg.on.brand.hover}", + "checkedBackground": "{color.bg.surface.canvas.default}", + "checkedColor": "{color.fg.focus}", + "checkedBorderColor": "{color.border.neutral.inverse}", + "disabledBackground": "{color.bg.neutral.strong.hover}", + "disabledBorderColor": "{color.border.neutral.bold.hover}", + "disabledColor": "{color.fg.inverse.muted}", + "invalidBorderColor": "{color.border.status.danger.strong}" + }, + "icon": { + "color": "{color.fg.inverse.default}", + "hoverColor": "{color.fg.on.brand.hover}", + "checkedColor": "{color.fg.focus}", + "disabledColor": "{color.fg.inverse.muted}" + }, + "content": { "checkedBackground": "transparent" } + } + }, + "root": { + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.max}", + "gap": "{dimension.space.200}", + "fontWeight": "{fonts.fontWeight.demibold}", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.200}" + }, + "sm": { + "fontSize": "{fonts.fontSize.200}", + "padding": "{dimension.space.100} {dimension.space.400}" + }, + "lg": { + "fontSize": "{fonts.fontSize.500}", + "padding": "{dimension.space.400} {dimension.space.700}" + }, + "transitionDuration": "{effects.transition.duration.200}", + "background": "{color.bg.surface.default.default}", + "borderColor": "{color.border.neutral.default}", + "checkedBackground": "{color.bg.surface.default.default}", + "checkedBorderColor": "{color.border.neutral.default}", + "checkedColor": "{color.fg.default}", + "color": "{color.fg.default}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "disabledBorderColor": "{color.border.neutral.default}", + "disabledColor": "{color.fg.muted}", + "hoverColor": "{color.fg.hover}", + "invalidBorderColor": "{color.border.status.danger.subtle}" + }, + "content": { + "checkedShadow": "none", + "padding": "{dimension.space.none}", + "borderRadius": "{dimension.borderRadius.none}", + "sm": { "padding": "{dimension.space.none}" }, + "lg": { "padding": "{dimension.space.none}" }, + "checkedBackground": "{color.bg.surface.default.default}" + }, + "icon": { + "checkedColor": "{color.fg.default}", + "color": "{color.fg.default}", + "disabledColor": "{color.fg.muted}", + "hoverColor": "{color.fg.hover}" + } + }, + "toggleswitch": { + "colorScheme": { + "light": { + "root": { + "background": "{color.bg.neutral.medium.active}", + "hoverBackground": "{color.bg.neutral.medium.strong}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "checkedBackground": "{color.bg.neutral.strong.default}", + "checkedHoverBackground": "{color.bg.neutral.strong.hover}" + }, + "handle": { + "background": "{color.bg.surface.raised.default}", + "hoverBackground": "{color.bg.surface.raised.default}", + "disabledBackground": "{color.bg.neutral.medium.strong}", + "checkedBackground": "{color.bg.surface.raised.default}", + "checkedHoverBackground": "{color.bg.surface.raised.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.default}", + "checkedColor": "{color.fg.default}", + "checkedHoverColor": "{color.fg.default}" + } + }, + "dark": { + "handle": { + "background": "{color.bg.surface.raised.default}", + "checkedBackground": "{color.bg.surface.raised.default}", + "checkedColor": "{color.fg.inverse.focus}", + "checkedHoverBackground": "{color.bg.surface.raised.default}", + "checkedHoverColor": "{color.fg.on.brand.hover}", + "color": "{color.fg.inverse.default}", + "disabledBackground": "{color.bg.surface.raised.active}", + "hoverBackground": "{color.bg.surface.raised.default}", + "hoverColor": "{color.fg.on.brand.hover}" + }, + "root": { + "background": "{color.bg.neutral.medium.active}", + "checkedBackground": "{color.bg.surface.canvas.default}", + "checkedHoverBackground": "{color.bg.surface.canvas.hover}", + "disabledBackground": "{color.bg.neutral.strong.hover}", + "hoverBackground": "{color.bg.surface.raised.active}" + } + } + }, + "root": { + "width": "{dimension.size.1100}", + "height": "{dimension.size.700}", + "borderRadius": "{dimension.borderRadius.max}", + "gap": "{dimension.space.100}", + "borderWidth": "{dimension.borderWidth.100}", + "shadow": "none", + "focusRing": { + "width": "{dimension.focusRing.width}", + "style": "none", + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}" + }, + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "checkedBorderColor": "transparent", + "checkedHoverBorderColor": "transparent", + "invalidBorderColor": "{color.border.status.danger.subtle}", + "transitionDuration": "{effects.transition.duration.200}", + "slideDuration": "{effects.transition.duration.200}" + }, + "handle": { + "borderRadius": "{dimension.borderRadius.max}", + "size": "{dimension.size.450}" + } + }, + "tooltip": { + "colorScheme": { + "light": { + "root": { + "background": "{color.bg.neutral.strong.default}", + "color": "{color.fg.inverse.default}" + } + }, + "dark": { + "root": { + "background": "{color.bg.surface.canvas.default}", + "color": "{color.fg.default}" + } + } + }, + "root": { + "maxWidth": "{dimension.size.2000}", + "gutter": "{dimension.space.100}", + "shadow": "{effects.elevation.400}", + "padding": "{dimension.space.200} {dimension.space.400}", + "borderRadius": "{dimension.borderRadius.200}" + } + }, + "tree": { + "root": { + "background": "{color.bg.surface.default.default}", + "color": "{color.fg.default}", + "padding": "{dimension.space.400}", + "gap": "{dimension.space.100}", + "indent": "{dimension.space.400}", + "transitionDuration": "{effects.transition.duration.200}" + }, + "node": { + "padding": "{dimension.space.200} {dimension.space.400}", + "color": "{color.fg.default}", + "selectedColor": "{color.fg.on.fill.default}", + "gap": "{dimension.space.100}", + "borderRadius": "{dimension.borderRadius.400}", + "focusRing": { + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}", + "style": "none", + "width": "{dimension.focusRing.width}" + }, + "hoverBackground": "{color.bg.neutral.weak.default}", + "hoverColor": "{color.fg.default}", + "selectedBackground": "{color.bg.neutral.strong.selected}" + }, + "nodeIcon": { + "selectedColor": "{color.fg.on.fill.default}", + "color": "{color.fg.default}", + "hoverColor": "{color.fg.hover}" + }, + "nodeToggleButton": { + "borderRadius": "{dimension.borderRadius.100}", + "size": "{dimension.size.800}", + "selectedHoverBackground": "{color.bg.neutral.strong.default}", + "color": "{color.fg.default}", + "focusRing": { + "color": "{color.border.focus}", + "offset": "{dimension.focusRing.offset}", + "shadow": "{effects.elevation.none}", + "style": "none", + "width": "{dimension.focusRing.width}" + }, + "hoverBackground": "{color.bg.neutral.weak.default}", + "hoverColor": "{color.fg.hover}", + "selectedHoverColor": "{color.fg.hover}" + }, + "loadingIcon": { "size": "{dimension.size.450}" }, + "filter": { + "margin": "{dimension.space.none} {dimension.space.none} {dimension.space.200} {dimension.space.none}" + } + }, + "overlaybadge": { + "root": { + "outline": { "width": "{dimension.size.none}", "color": "transparent" } + } + } + } +} diff --git a/src/theme/__tests__/ThemeContext.test.tsx b/src/theme/__tests__/ThemeContext.test.tsx index ed58df0e..0106d5ff 100644 --- a/src/theme/__tests__/ThemeContext.test.tsx +++ b/src/theme/__tests__/ThemeContext.test.tsx @@ -4,7 +4,12 @@ import { Text } from 'react-native' import { UnistylesRuntime } from 'react-native-unistyles' import { ThemeContextProvider } from '../ThemeContext' +import { darkTheme } from '../darkTheme' import { lightTheme } from '../lightTheme' +import darkComponentTokens from '../tokens/components/dark.json' +import lightComponentTokens from '../tokens/components/light.json' +import darkSemanticTokens from '../tokens/semantic/dark.json' +import lightSemanticTokens from '../tokens/semantic/light.json' import { ThemeVariant } from '../types' describe('ThemeContextProvider', () => { @@ -66,4 +71,14 @@ describe('ThemeContextProvider', () => { expect(UnistylesRuntime.updateTheme).not.toHaveBeenCalled() }) + + test('каждая тема содержит соответствующие semantic-токены', () => { + expect(lightTheme.semantic).toBe(lightSemanticTokens) + expect(darkTheme.semantic).toBe(darkSemanticTokens) + }) + + test('каждая тема содержит соответствующие component-токены', () => { + expect(lightTheme.components).toBe(lightComponentTokens) + expect(darkTheme.components).toBe(darkComponentTokens) + }) }) diff --git a/src/theme/darkTheme.ts b/src/theme/darkTheme.ts index 1f52f8ed..aa8bf3f0 100644 --- a/src/theme/darkTheme.ts +++ b/src/theme/darkTheme.ts @@ -3,9 +3,13 @@ import { ModalSize } from './assets/ModalSize' import { customDark } from './assets/customDark' import darkThemeAssets from './assets/themeDark.json' import { commonTheme } from './commonTheme' +import darkComponentTokens from './tokens/components/dark.json' +import darkSemanticTokens from './tokens/semantic/dark.json' import type { ThemeType } from './types' export const darkTheme: ThemeType = { + semantic: darkSemanticTokens, + components: darkComponentTokens, theme: { ...darkThemeAssets, InputSize, ModalSize, custom: customDark }, ...commonTheme, fonts: { primary: 'TT Fellows', secondary: 'Noto Sans' }, diff --git a/src/theme/lightTheme.ts b/src/theme/lightTheme.ts index cc47c3be..b91a6008 100644 --- a/src/theme/lightTheme.ts +++ b/src/theme/lightTheme.ts @@ -3,9 +3,13 @@ import { ModalSize } from './assets/ModalSize' import { customLight } from './assets/customLight' import lightThemeAssets from './assets/themeLight.json' import { commonTheme } from './commonTheme' +import lightComponentTokens from './tokens/components/light.json' +import lightSemanticTokens from './tokens/semantic/light.json' import type { ThemeType } from './types' export const lightTheme: ThemeType = { + semantic: lightSemanticTokens, + components: lightComponentTokens, theme: { ...lightThemeAssets, InputSize, ModalSize, custom: customLight }, ...commonTheme, fonts: { primary: 'TT Fellows', secondary: 'Noto Sans' }, diff --git a/src/theme/tokens/README.md b/src/theme/tokens/README.md new file mode 100644 index 00000000..3badaaae --- /dev/null +++ b/src/theme/tokens/README.md @@ -0,0 +1,9 @@ +# Сгенерированные токены + +`semantic` подключается к темам как `ThemeType.semantic`. `components` хранит +внутренние токены компонентов для `ThemeType.components`. В сгенерированных +файлах нет `primitive`; `colorScheme` содержит только выбранную ветку без +вложенных `light` и `dark`. Всё генерируется из +`design-tokens/input/tokens.json` и не редактируется вручную. + +Подробности: [генератор токенов](../../../scripts/token-generator/README.md). diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json new file mode 100644 index 00000000..111be1c4 --- /dev/null +++ b/src/theme/tokens/components/dark.json @@ -0,0 +1,2920 @@ +{ + "accordion": { + "extend": { "extHeader": { "iconSize": 20, "gap": 8 } }, + "colorScheme": { + "header": { + "activeBackground": "transparent", + "activeHoverBackground": "transparent", + "background": "transparent", + "hoverBackground": "transparent" + } + }, + "header": { + "color": "#ffffff", + "hoverColor": "#cecfd2", + "activeColor": "#ffffff", + "activeHoverColor": "#cecfd2", + "borderColor": "transparent", + "paddingTop": 14, + "paddingRight": 0, + "paddingBottom": 14, + "paddingLeft": 0, + "fontWeight": "700", + "borderRadius": 0, + "borderWidth": 0, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "inset 0 0 0 4px #d4fedc" + }, + "toggleIcon": { + "color": "#ffffff", + "hoverColor": "#cecfd2", + "activeColor": "#ffffff", + "activeHoverColor": "#cecfd2" + }, + "last": { "bottomBorderRadius": 0, "activeBottomBorderRadius": 0 }, + "first": { "borderWidth": 0, "topBorderRadius": 0 } + }, + "root": { "transitionDuration": 180 }, + "panel": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 4, + "borderLeftWidth": 0, + "borderColor": "#56595f" + }, + "content": { + "borderTopWidth": 1, + "borderRightWidth": 0, + "borderBottomWidth": 0, + "borderLeftWidth": 0, + "borderColor": "transparent", + "background": "transparent", + "color": "#ffffff", + "paddingTop": 0, + "paddingRight": 24, + "paddingBottom": 14, + "paddingLeft": 24 + } + }, + "autocomplete": { + "extend": { "extOption": { "gap": 8 }, "extOptionGroup": { "gap": 8 } }, + "colorScheme": { + "chip": { "focusBackground": "#e2e2e4", "focusColor": "#2b2e33" }, + "dropdown": { + "activeBackground": "#404348", + "activeColor": "#181a1f", + "background": "#404348", + "color": "#181a1f", + "hoverBackground": "#404348", + "hoverColor": "#181a1f" + } + }, + "root": { + "background": "#404348", + "disabledBackground": "#404348", + "filledBackground": "#404348", + "filledHoverBackground": "#404348", + "filledFocusBackground": "#404348", + "borderColor": "#56595f", + "hoverBorderColor": "#77f48a", + "focusBorderColor": "#77f48a", + "invalidBorderColor": "#db3424", + "color": "#f0f0f1", + "disabledColor": "#a2a5a9", + "placeholderColor": "#a2a5a9", + "invalidPlaceholderColor": "#fbacaa", + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + } + }, + "overlay": { + "background": "#404348", + "borderColor": "#404348", + "borderRadius": 14, + "color": "#ffffff", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "list": { "padding": 4, "gap": 4 }, + "option": { + "focusBackground": "#2b2e33", + "selectedBackground": "#f0f0f1", + "selectedFocusBackground": "#cecfd2", + "color": "#ffffff", + "focusColor": "#ffffff", + "selectedColor": "#ffffff", + "selectedFocusColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8 + }, + "optionGroup": { + "background": "#56595f", + "color": "#a2a5a9", + "fontWeight": "600", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "dropdown": { + "width": 272, + "borderColor": "#56595f", + "hoverBorderColor": "#77f48a", + "activeBorderColor": "#77f48a", + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + }, + "sm": { "width": 240 }, + "lg": { "width": 304 } + }, + "chip": { "borderRadius": 8 }, + "emptyMessage": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + } + }, + "avatar": { + "extend": { "borderColor": "#56595f", "circle": { "borderRadius": 1600 } }, + "root": { + "width": 32, + "height": 32, + "fontSize": 16, + "color": "#ffffff", + "background": "#44e858", + "borderRadius": 14 + }, + "icon": { "size": 16 }, + "group": { "borderColor": "#2b2e33", "offset": -12 }, + "lg": { + "width": 40, + "height": 40, + "fontSize": 16, + "icon": { "size": 16 }, + "group": { "offset": -12 } + }, + "xl": { + "width": 56, + "height": 56, + "icon": { "size": 24 }, + "group": { "offset": -24 }, + "fontSize": 16 + } + }, + "badge": { + "extend": { + "extDot": { + "success": { "background": "#1dc831" }, + "info": { "background": "#1e76cd" }, + "warn": { "background": "#dc9710" }, + "danger": { "background": "#db3424" }, + "lg": { "size": 12 }, + "xlg": { "size": 16 } + }, + "ext": { "padding": 0 } + }, + "colorScheme": { + "contrast": { "background": "#2b2e33", "color": "#ffffff" }, + "danger": { "background": "#8d2218", "color": "#fff0f0" }, + "info": { "background": "#18538d", "color": "#f0f9ff" }, + "primary": { "background": "#44e858", "color": "#2b2e33" }, + "secondary": { "background": "#2b2e33", "color": "#ffffff" }, + "success": { "background": "#aafbb7", "color": "#f0fff3" }, + "warn": { "background": "#9d6d0e", "color": "#fff9f0" } + }, + "root": { + "borderRadius": 8, + "padding": 8, + "fontSize": 12, + "fontWeight": "400", + "minWidth": 24, + "height": 24 + }, + "dot": { "size": 8 }, + "sm": { "fontSize": 12, "minWidth": 0, "height": 0 }, + "lg": { "fontSize": 12, "minWidth": 28, "height": 28 }, + "xl": { "fontSize": 12, "minWidth": 32, "height": 32 } + }, + "breadcrumb": { + "extend": { + "hoverBackground": "#2b2e33", + "iconSize": 20, + "extItem": { "padding": 4 } + }, + "root": { + "padding": 0, + "background": "transparent", + "gap": 0, + "transitionDuration": 180 + }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "item": { + "color": "#ffffff", + "hoverColor": "#cecfd2", + "borderRadius": 4, + "gap": 8, + "icon": { "color": "#ffffff", "hoverColor": "#cecfd2" }, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + } + }, + "separator": { "color": "#ffffff" } + }, + "button": { + "extend": { + "disabledBackground": "#404348", + "extOutlined": { + "danger": { "focusBackground": "transparent" }, + "warn": { "focusBackground": "transparent" }, + "info": { "focusBackground": "transparent" }, + "help": { "focusBackground": "transparent" }, + "success": { "focusBackground": "transparent" } + }, + "disabledColor": "#a2a5a9", + "extText": { + "danger": { "focusBackground": "transparent" }, + "warn": { "focusBackground": "transparent" }, + "info": { "focusBackground": "transparent" }, + "help": { "focusBackground": "transparent" }, + "success": { "focusBackground": "transparent" } + }, + "extLink": { + "background": "transparent", + "colorHover": "#cecfd2", + "paddingX": 0, + "paddingY": 4, + "sm": { "iconOnlyWidth": 16 }, + "base": { "iconOnlyWidth": 24 }, + "lg": { "iconOnlyWidth": 28 }, + "xlg": { "iconOnlyWidth": 32 } + }, + "extSm": { "borderRadius": 14, "gap": 8 }, + "extLg": { "borderRadius": 14, "gap": 14, "height": 56 }, + "extXlg": { + "borderRadius": 14, + "gap": 14, + "iconOnlyWidth": 64, + "paddingX": 24, + "paddingY": 20, + "height": 64 + }, + "borderWidth": 1, + "iconSize": { "sm": 16, "md": 20, "lg": 24 } + }, + "colorScheme": { + "link": { + "activeColor": "#85888e", + "color": "#2b2e33", + "hoverColor": "#56595f" + }, + "outlined": { + "contrast": { + "activeBackground": "#56595f", + "borderColor": "#2b2e33", + "color": "#ffffff", + "hoverBackground": "#404348" + }, + "danger": { + "activeBackground": "#611912", + "borderColor": "#db3424", + "color": "#fbacaa", + "hoverBackground": "#45120e" + }, + "help": { + "activeBackground": "#6b21a8", + "borderColor": "#c084fc", + "color": "#d8b4fe", + "hoverBackground": "#581c87" + }, + "info": { + "activeBackground": "#123a61", + "borderColor": "#77baf4", + "color": "#aad7fb", + "hoverBackground": "#0e2a45" + }, + "plain": { + "activeBackground": "#e2e2e4", + "borderColor": "#56595f", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + }, + "primary": { + "activeBackground": "#0e4514", + "borderColor": "#d4fedc", + "color": "#44e858", + "hoverBackground": "#0c3b11" + }, + "secondary": { + "activeBackground": "#e2e2e4", + "borderColor": "#56595f", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + }, + "success": { + "activeBackground": "#12611b", + "borderColor": "#77f48a", + "color": "#aafbb7", + "hoverBackground": "#0e4514" + }, + "warn": { + "activeBackground": "#6d4c0b", + "borderColor": "#facb75", + "color": "#fddeaa", + "hoverBackground": "#4f3709" + } + }, + "root": { + "contrast": { + "activeBackground": "#6d7076", + "activeBorderColor": "transparent", + "activeColor": "#2b2e33", + "background": "#e2e2e4", + "borderColor": "transparent", + "color": "#2b2e33", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#cecfd2", + "hoverBorderColor": "transparent", + "hoverColor": "#2b2e33" + }, + "danger": { + "activeBackground": "#e85244", + "activeBorderColor": "transparent", + "activeColor": "#fff0f0", + "background": "#8d2218", + "borderColor": "transparent", + "color": "#fff0f0", + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#db3424", + "hoverBorderColor": "transparent", + "hoverColor": "#fffafa" + }, + "help": { + "activeBackground": "#a855f7", + "activeBorderColor": "transparent", + "activeColor": "#f3e8ff", + "background": "#7e22ce", + "borderColor": "transparent", + "color": "#f3e8ff", + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#9333ea", + "hoverBorderColor": "transparent", + "hoverColor": "#faf5ff" + }, + "info": { + "activeBackground": "#4496e8", + "activeBorderColor": "transparent", + "activeColor": "#f0f9ff", + "background": "#18538d", + "borderColor": "transparent", + "color": "#f0f9ff", + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#1e76cd", + "hoverBorderColor": "transparent", + "hoverColor": "#fafdff" + }, + "primary": { + "activeBackground": "#168322", + "activeBorderColor": "transparent", + "activeColor": "#2b2e33", + "background": "#44e858", + "borderColor": "transparent", + "color": "#2b2e33", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#1dc831", + "hoverBorderColor": "transparent", + "hoverColor": "#2b2e33" + }, + "secondary": { + "activeBackground": "#56595f", + "activeBorderColor": "transparent", + "activeColor": "#ffffff", + "background": "#2b2e33", + "borderColor": "transparent", + "color": "#ffffff", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#404348", + "hoverBorderColor": "transparent", + "hoverColor": "#ffffff" + }, + "success": { + "activeBackground": "#44e858", + "activeBorderColor": "transparent", + "activeColor": "#f0fff3", + "background": "#aafbb7", + "borderColor": "transparent", + "color": "#f0fff3", + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#77f48a", + "hoverBorderColor": "transparent", + "hoverColor": "#fafffb" + }, + "warn": { + "activeBackground": "#f5b83d", + "activeBorderColor": "transparent", + "activeColor": "#fff9f0", + "background": "#9d6d0e", + "borderColor": "transparent", + "color": "#fff9f0", + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#dc9710", + "hoverBorderColor": "transparent", + "hoverColor": "#fffdfa" + } + }, + "text": { + "contrast": { + "activeBackground": "#56595f", + "color": "#ffffff", + "hoverBackground": "#404348" + }, + "danger": { + "activeBackground": "#611912", + "color": "#fbacaa", + "hoverBackground": "#45120e" + }, + "help": { + "activeBackground": "#6b21a8", + "color": "#d8b4fe", + "hoverBackground": "#581c87" + }, + "info": { + "activeBackground": "#123a61", + "color": "#aad7fb", + "hoverBackground": "#0e2a45" + }, + "plain": { + "activeBackground": "#e2e2e4", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + }, + "primary": { + "activeBackground": "#e2e2e4", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + }, + "secondary": { + "activeBackground": "#e2e2e4", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + }, + "success": { + "activeBackground": "#12611b", + "color": "#aafbb7", + "hoverBackground": "#0e4514" + }, + "warn": { + "activeBackground": "#6d4c0b", + "color": "#fddeaa", + "hoverBackground": "#4f3709" + } + } + }, + "root": { + "borderRadius": 14, + "roundedBorderRadius": 1600, + "gap": 8, + "paddingX": 14, + "paddingY": 8, + "iconOnlyWidth": 40, + "raisedShadow": "none", + "badgeSize": 16, + "transitionDuration": 180, + "focusRing": { "width": 4, "style": "none", "offset": 0 }, + "sm": { + "fontSize": 14, + "iconOnlyWidth": 32, + "paddingX": 14, + "paddingY": 8 + }, + "lg": { + "fontSize": 20, + "iconOnlyWidth": 56, + "paddingX": 24, + "paddingY": 14 + }, + "label": { "fontWeight": "600" } + } + }, + "card": { + "extend": { "borderColor": "#404348", "borderWidth": 1 }, + "root": { + "background": "#404348", + "borderRadius": 14, + "color": "#ffffff", + "shadow": "none" + }, + "body": { "padding": 14, "gap": 14 }, + "caption": { "gap": 4 }, + "title": { "fontSize": 18, "fontWeight": "600" }, + "subtitle": { "color": "#a2a5a9" } + }, + "carousel": { + "colorScheme": { + "indicator": { + "activeBackground": "#2b2e33", + "background": "#cecfd2", + "hoverBackground": "#6d7076" + } + }, + "root": { "transitionDuration": 180 }, + "content": { "gap": 8 }, + "indicatorList": { "padding": 14, "gap": 8 }, + "indicator": { + "width": 8, + "height": 8, + "borderRadius": 1600, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "checkbox": { + "root": { + "borderRadius": 8, + "extend": { "borderWidth": 1 }, + "width": 24, + "height": 24, + "background": "#404348", + "checkedBackground": "#f0f0f1", + "checkedHoverBackground": "#e2e2e4", + "disabledBackground": "#404348", + "filledBackground": "#404348", + "borderColor": "#56595f", + "hoverBorderColor": "#f0f0f1", + "focusBorderColor": "#f0f0f1", + "checkedBorderColor": "#f0f0f1", + "checkedHoverBorderColor": "#e2e2e4", + "checkedFocusBorderColor": "#44e858", + "checkedDisabledBorderColor": "#56595f", + "invalidBorderColor": "#db3424", + "shadow": "none", + "focusRing": { + "focusRing": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)", + "width": 4 + }, + "sm": { "width": 8, "height": 8 }, + "lg": { "width": 20, "height": 20 }, + "transitionDuration": 180 + }, + "icon": { + "size": 16, + "color": "#f0f0f1", + "checkedColor": "#ffffff", + "checkedHoverColor": "#ffffff", + "disabledColor": "#a2a5a9", + "sm": { "size": 12 }, + "lg": { "size": 20 } + } + }, + "chip": { + "extend": { "borderColor": "transparent", "borderWidth": 1 }, + "root": { + "borderRadius": 8, + "paddingX": 8, + "paddingY": 4, + "gap": 8, + "transitionDuration": 180 + }, + "colorScheme": { + "icon": { "color": "#2b2e33" }, + "removeIcon": { "color": "#2b2e33" }, + "root": { "background": "#e2e2e4", "color": "#2b2e33" } + }, + "image": { "width": 0, "height": 0 }, + "icon": { "size": 16 }, + "removeIcon": { + "size": 16, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "confirmdialog": { + "extend": { + "extIcon": { + "success": "#77f48a", + "info": "#77baf4", + "help": "#c084fc", + "warn": "#facb75", + "danger": "#f47f77" + } + }, + "icon": { "size": 24, "color": "#ffffff" }, + "content": { "gap": 0 } + }, + "confirmpopup": { + "root": { + "background": "#404348", + "color": "#ffffff", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "gutter": 14, + "arrowOffset": 20, + "borderColor": "#404348", + "borderRadius": 14 + }, + "content": { "padding": 14, "gap": 14 }, + "icon": { "size": 24, "color": "#ffffff" }, + "footer": { + "gap": 8, + "paddingTop": 0, + "paddingRight": 24, + "paddingBottom": 24, + "paddingLeft": 24 + } + }, + "contextmenu": { + "root": { + "background": "#404348", + "color": "#ffffff", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "borderColor": "#404348", + "borderRadius": 14, + "transitionDuration": 180 + }, + "list": { + "paddingTop": 8, + "paddingRight": 0, + "paddingBottom": 8, + "paddingLeft": 0, + "gap": 4 + }, + "item": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "gap": 8, + "activeBackground": "#404348", + "activeColor": "#cecfd2", + "borderRadius": 14, + "color": "#ffffff", + "focusBackground": "#2b2e33", + "focusColor": "#cecfd2", + "icon": { + "activeColor": "#cecfd2", + "color": "#ffffff", + "focusColor": "#cecfd2" + } + }, + "submenu": { "mobileIndent": 20 }, + "separator": { "borderColor": "#404348" }, + "submenuIcon": { + "activeColor": "#cecfd2", + "color": "#ffffff", + "focusColor": "#cecfd2", + "size": 14 + } + }, + "datatable": { + "colorScheme": { + "bodyCell": { "selectedBorderColor": "#e2e2e4" }, + "footer": { "background": "#f0f0f1", "color": "#2b2e33" }, + "footerCell": { "background": "#f0f0f1", "color": "#2b2e33" }, + "header": { "background": "#56595f", "color": "#2b2e33" }, + "headerCell": { + "background": "#6d7076", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + }, + "root": { "borderColor": "#e2e2e4", "color": "#2b2e33" }, + "row": { "stripedBackground": "#f0f0f1" } + }, + "extended": { + "extHeaderCell": { "selectedHoverBackground": "#e2e2e4" }, + "extRow": { + "selectedHoverBackground": "#e2e2e4", + "stripedHoverBackground": "#2b2e33", + "iconSize": 20 + } + }, + "root": { "transitionDuration": 180 }, + "header": { + "borderColor": "#404348", + "borderTopWidth": 1, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "padding": 14, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "headerCell": { + "selectedBackground": "#f0f0f1", + "borderColor": "#404348", + "hoverColor": "#cecfd2", + "selectedColor": "#ffffff", + "gap": 8, + "padding": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "inset 0 0 0 4px #d4fedc" + }, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "columnTitle": { "fontWeight": "700" }, + "row": { + "background": "#56595f", + "hoverBackground": "#2b2e33", + "selectedBackground": "#f0f0f1", + "color": "#ffffff", + "hoverColor": "#cecfd2", + "selectedColor": "#ffffff", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "inset 0 0 0 4px #d4fedc" + } + }, + "bodyCell": { + "borderColor": "#404348", + "padding": 14, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "footerCell": { + "borderColor": "#404348", + "padding": 14, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "columnFooter": { "fontWeight": "700" }, + "dropPoint": { "color": "#ffffff" }, + "footer": { + "borderColor": "#404348", + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "padding": 14, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "columnResizer": { "width": 8 }, + "resizeIndicator": { "width": 1, "color": "#ffffff" }, + "sortIcon": { "color": "#ffffff", "hoverColor": "#cecfd2", "size": 16 }, + "loadingIcon": { "size": 32 }, + "rowToggleButton": { + "hoverBackground": "#2b2e33", + "selectedHoverBackground": "#2b2e33", + "color": "#ffffff", + "hoverColor": "#ffffff", + "selectedHoverColor": "#ffffff", + "size": 32, + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "filter": { + "inlineGap": 8, + "rule": { "borderColor": "#404348" }, + "constraintList": { "padding": 4, "gap": 4 }, + "constraint": { + "focusBackground": "#2b2e33", + "selectedBackground": "#f0f0f1", + "selectedFocusBackground": "#cecfd2", + "color": "#ffffff", + "focusColor": "#ffffff", + "selectedColor": "#ffffff", + "selectedFocusColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "separator": { "borderColor": "#404348" } + }, + "overlaySelect": { + "background": "#56595f", + "color": "#ffffff", + "borderColor": "#404348", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "overlayPopover": { + "background": "#56595f", + "color": "#ffffff", + "borderColor": "#404348", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "padding": 14, + "gap": 4 + } + }, + "paginatorTop": { + "borderColor": "#56595f", + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0 + }, + "paginatorBottom": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "borderColor": "#404348" + } + }, + "dataview": { + "root": { + "borderWidth": 1, + "borderRadius": 4, + "padding": 0, + "borderColor": "#404348" + }, + "header": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": "0px 0px 0px 0px", + "color": "#ffffff", + "borderColor": "#404348" + }, + "content": { + "background": "#404348", + "color": "#ffffff", + "borderColor": "#404348", + "borderWidth": 0, + "padding": 0, + "borderRadius": 0 + }, + "footer": { + "background": "#2b2e33", + "color": "#ffffff", + "borderTopWidth": 1, + "borderRightWidth": 0, + "borderBottomWidth": 0, + "borderLeftWidth": 0, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": "0px 0px 0px 0px", + "borderColor": "#404348" + }, + "paginatorTop": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "borderColor": "#404348" + }, + "paginatorBottom": { + "borderTopWidth": 1, + "borderRightWidth": 0, + "borderBottomWidth": 0, + "borderLeftWidth": 0, + "borderColor": "#404348" + }, + "colorScheme": { "header": { "background": "#404348", "color": "#2b2e33" } } + }, + "datepicker": { + "extend": { + "extDate": { "selectedHoverBackground": "#e2e2e4" }, + "extToday": { "hoverBackground": "#2b2e33", "borderColor": "#e2e2e4" }, + "extTitle": { "width": 336 }, + "extTimePicker": { "minWidth": 304, "color": "#ffffff" } + }, + "colorScheme": { + "dropdown": { + "activeBackground": "#2b2e33", + "activeColor": "#ffffff", + "background": "#404348", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1", + "hoverColor": "#2b2e33" + }, + "today": { "background": "transparent", "color": "#2b2e33" } + }, + "panel": { + "background": "#404348", + "borderColor": "#404348", + "color": "#ffffff", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "padding": 0 + }, + "header": { + "background": "#404348", + "borderColor": "#404348", + "color": "#ffffff", + "padding": 14 + }, + "title": { "gap": 8, "fontWeight": "700" }, + "selectMonth": { + "hoverBackground": "#2b2e33", + "color": "#ffffff", + "hoverColor": "#cecfd2", + "borderRadius": 14, + "padding": 8 + }, + "inputIcon": { "color": "#a2a5a9" }, + "dropdown": { + "width": 272, + "borderColor": "#56595f", + "hoverBorderColor": "#56595f", + "activeBorderColor": "#56595f", + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "sm": { "width": 0 }, + "lg": { "width": 0 } + }, + "group": { "borderColor": "#404348", "gap": 14 }, + "selectYear": { + "hoverBackground": "#2b2e33", + "color": "#ffffff", + "hoverColor": "#cecfd2", + "borderRadius": 14, + "padding": 4 + }, + "dayView": { "margin": 14 }, + "weekDay": { "padding": 4, "fontWeight": "700", "color": "#ffffff" }, + "date": { + "hoverBackground": "#2b2e33", + "selectedBackground": "#f0f0f1", + "rangeSelectedBackground": "#2b2e33", + "color": "#ffffff", + "hoverColor": "#ffffff", + "selectedColor": "#ffffff", + "rangeSelectedColor": "#ffffff", + "width": 32, + "height": 32, + "borderRadius": 8, + "padding": 4, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "monthView": { + "marginTop": 0, + "marginRight": 0, + "marginBottom": 0, + "marginLeft": 0 + }, + "month": { "padding": 0, "borderRadius": 0 }, + "yearView": { + "marginTop": 0, + "marginRight": 0, + "marginBottom": 0, + "marginLeft": 0 + }, + "year": { "padding": 0, "borderRadius": 0 }, + "buttonbar": { "padding": 14, "borderColor": "#404348" }, + "timePicker": { + "padding": 14, + "borderColor": "#404348", + "gap": 8, + "buttonGap": 4 + }, + "root": { "transitionDuration": 180 } + }, + "dialog": { + "extend": { "borderWidth": 1, "backdrop": "rgba(0, 0, 0, 0.6000)" }, + "root": { + "background": "#404348", + "borderColor": "#404348", + "color": "#ffffff", + "borderRadius": 1600, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "header": { + "paddingTop": 24, + "paddingRight": 24, + "paddingBottom": 14, + "paddingLeft": 24, + "gap": 8 + }, + "title": { "fontSize": 20, "fontWeight": "600" }, + "content": { "padding": 24 }, + "footer": { + "paddingTop": 0, + "paddingRight": 24, + "paddingBottom": 24, + "paddingLeft": 24, + "gap": 8 + } + }, + "divider": { + "extend": { "content": { "gap": 8 }, "iconSize": 16 }, + "horizontal": { + "marginTop": 14, + "marginRight": 0, + "marginBottom": 14, + "marginLeft": 0, + "paddingTop": 0, + "paddingRight": 14, + "paddingBottom": 0, + "paddingLeft": 14, + "content": { + "paddingTop": 0, + "paddingRight": 8, + "paddingBottom": 0, + "paddingLeft": 8 + } + }, + "vertical": { + "marginTop": 0, + "marginRight": 14, + "marginBottom": 0, + "marginLeft": 14, + "paddingTop": 14, + "paddingRight": 0, + "paddingBottom": 14, + "paddingLeft": 0, + "content": { + "paddingTop": 8, + "paddingRight": 0, + "paddingBottom": 8, + "paddingLeft": 0 + } + }, + "content": { "background": "#404348", "color": "#ffffff" }, + "root": { "borderColor": "#404348" } + }, + "drawer": { + "extend": { + "borderRadius": 8, + "borderWidth": 1, + "width": 400, + "extHeader": { "gap": 8, "borderColor": "#404348" }, + "margin": 8, + "scale": 2, + "backdrop": "rgba(0, 0, 0, 0.6000)" + }, + "root": { + "background": "#404348", + "borderColor": "#404348", + "color": "#ffffff", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "header": { + "paddingTop": 24, + "paddingRight": 24, + "paddingBottom": 14, + "paddingLeft": 24 + }, + "title": { "fontSize": 20, "fontWeight": "600" }, + "content": { "padding": 24 }, + "footer": { + "paddingTop": 0, + "paddingRight": 24, + "paddingBottom": 24, + "paddingLeft": 24 + } + }, + "fileupload": { + "extend": { + "extDragNdrop": { + "background": "#56595f", + "borderRadius": 14, + "iconSize": 32, + "padding": 14, + "info": { "gap": 4 } + }, + "extFile": { "iconSize": 20 }, + "extContent": { "borderRadius": 14, "highlightBorderDefault": "#56595f" } + }, + "colorScheme": { + "header": { "background": "#404348", "color": "#2b2e33" } + }, + "root": { + "background": "#404348", + "borderColor": "#404348", + "color": "#ffffff", + "borderRadius": 14, + "transitionDuration": 180 + }, + "header": { + "borderColor": "#404348", + "borderWidth": 0, + "padding": 0, + "borderRadius": 0, + "gap": 8 + }, + "content": { "highlightBorderColor": "#f0f0f1", "padding": 0, "gap": 8 }, + "file": { + "padding": 8, + "gap": 8, + "borderColor": "#56595f", + "info": { "gap": 4 } + }, + "fileList": { "gap": 8 }, + "progressbar": { "height": 8 }, + "basic": { "gap": 8 } + }, + "floatlabel": { + "extend": { "height": 64, "iconSize": 20 }, + "root": { + "color": "#a2a5a9", + "focusColor": "#a2a5a9", + "activeColor": "#a2a5a9", + "invalidColor": "#fbacaa", + "transitionDuration": 180, + "positionX": 14, + "positionY": 14, + "fontWeight": "400", + "active": { "fontSize": 12, "fontWeight": "400" } + }, + "over": { "active": { "top": 14 } }, + "inside": { + "input": { "paddingTop": 28, "paddingBottom": 14 }, + "active": { "top": 14 } + }, + "on": { + "borderRadius": 0, + "active": { + "paddingTop": 0, + "paddingRight": 4, + "paddingBottom": 0, + "paddingLeft": 4, + "background": "#56595f" + } + } + }, + "galleria": { + "extend": { "backdrop": "rgba(0, 0, 0, 0.6000)" }, + "colorScheme": { + "indicatorButton": { + "background": "#cecfd2", + "hoverBackground": "#6d7076" + }, + "thumbnailNavButton": { + "color": "#2b2e33", + "hoverBackground": "#404348", + "hoverColor": "#56595f" + }, + "thumbnailsContent": { "background": "#404348" }, + "thumbnailContent": { "background": "#f0f0f1" } + }, + "root": { + "borderWidth": 1, + "borderColor": "#404348", + "borderRadius": 14, + "transitionDuration": 180 + }, + "navButton": { + "background": "transparent", + "hoverBackground": "#404348", + "color": "#2b2e33", + "hoverColor": "#56595f", + "size": 64, + "gutter": 8, + "prev": { "borderRadius": 8 }, + "next": { "borderRadius": 8 }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "navIcon": { "size": 32 }, + "thumbnailsContent": { "padding": 4 }, + "thumbnailNavButton": { + "size": 32, + "borderRadius": 14, + "gutter": 8, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "thumbnailNavButtonIcon": { "size": 16 }, + "caption": { "background": "#404348", "color": "#ffffff", "padding": 8 }, + "indicatorList": { "gap": 8, "padding": 14 }, + "indicatorButton": { + "width": 8, + "height": 8, + "activeBackground": "#f0f0f1", + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "insetIndicatorList": { "background": "rgba(0, 0, 0, 0.6000)" }, + "insetIndicatorButton": { + "background": "#404348", + "hoverBackground": "#404348", + "activeBackground": "#404348" + }, + "closeButton": { + "size": 64, + "gutter": 8, + "background": "#404348", + "hoverBackground": "#404348", + "color": "#2b2e33", + "hoverColor": "#56595f", + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "closeButtonIcon": { "size": 32 } + }, + "inputgroup": { + "extend": { "borderWidth": 1, "iconSize": 16 }, + "colorScheme": { + "addon": { + "background": "#56595f", + "borderColor": "#56595f", + "color": "#85888e" + } + }, + "addon": { "borderRadius": 14, "padding": 14, "minWidth": 272 } + }, + "inputnumber": { + "extend": { + "borderWidth": 1, + "extButton": { "height": 40, "iconSize": 16 } + }, + "colorScheme": { + "button": { + "activeBackground": "transparent", + "activeBorderColor": "#56595f", + "activeColor": "#2b2e33", + "background": "#56595f", + "borderColor": "#56595f", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1", + "hoverBorderColor": "#56595f", + "hoverColor": "#56595f" + } + }, + "transitionDuration": { "transitionDuration": 180 }, + "button": { "width": 272, "borderRadius": 14, "verticalPadding": 14 }, + "root": { "transitionDuration": 180 } + }, + "inputotp": { + "extend": { "height": 40, "borderWidth": 1 }, + "root": { "gap": 8 }, + "input": { "width": 304, "lg": { "width": 336 }, "sm": { "width": 272 } }, + "sm": { "width": 0 }, + "lg": { "width": 0 } + }, + "inputtext": { + "extend": { + "readonlyBackground": "#2b2e33", + "iconSize": 16, + "borderWidth": 1, + "extXlg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 } + }, + "root": { + "background": "#404348", + "disabledBackground": "#404348", + "filledBackground": "#404348", + "filledHoverBackground": "#404348", + "filledFocusBackground": "#404348", + "borderColor": "#56595f", + "hoverBorderColor": "#77f48a", + "focusBorderColor": "#77f48a", + "invalidBorderColor": "#db3424", + "color": "#ffffff", + "disabledColor": "#a2a5a9", + "placeholderColor": "#a2a5a9", + "invalidPlaceholderColor": "#fbacaa", + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "sm": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + } + } + }, + "listbox": { + "extend": { + "extOption": { + "label": { "gap": 4 }, + "caption": { "color": "#a2a5a9", "stripedColor": "#a2a5a9" }, + "gap": 8 + } + }, + "colorScheme": { "option": { "stripedBackground": "#6d7076" } }, + "root": { + "background": "#404348", + "disabledBackground": "#404348", + "borderColor": "#56595f", + "invalidBorderColor": "#db3424", + "color": "#f0f0f1", + "disabledColor": "#a2a5a9", + "shadow": "none", + "borderRadius": 14, + "transitionDuration": 180 + }, + "list": { + "padding": 4, + "gap": 4, + "header": { + "paddingTop": 14, + "paddingRight": 14, + "paddingBottom": 0, + "paddingLeft": 14 + } + }, + "option": { + "focusBackground": "#2b2e33", + "selectedBackground": "#f0f0f1", + "selectedFocusBackground": "#cecfd2", + "color": "#ffffff", + "focusColor": "#ffffff", + "selectedColor": "#ffffff", + "selectedFocusColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8 + }, + "optionGroup": { + "background": "#56595f", + "color": "#a2a5a9", + "fontWeight": "600", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "checkmark": { "color": "#ffffff", "gutterStart": -8, "gutterEnd": 8 }, + "emptyMessage": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + } + }, + "megamenu": { + "extend": { + "extItem": { "caption": { "color": "#a2a5a9", "gap": 4 } }, + "iconSize": 20 + }, + "colorScheme": { "root": { "background": "transparent" } }, + "root": { + "borderColor": "transparent", + "borderRadius": 14, + "color": "#ffffff", + "gap": 4, + "transitionDuration": 180, + "verticalOrientation": { "padding": 4, "gap": 4 }, + "horizontalOrientation": { "padding": 4, "gap": 4 } + }, + "baseItem": { + "borderRadius": 14, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "item": { + "focusBackground": "#2b2e33", + "activeBackground": "#f0f0f1", + "color": "#ffffff", + "focusColor": "#ffffff", + "activeColor": "#181a1f", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "icon": { + "color": "#ffffff", + "focusColor": "#ffffff", + "activeColor": "#181a1f" + } + }, + "overlay": { + "padding": 4, + "background": "#404348", + "borderColor": "#404348", + "borderRadius": 14, + "color": "#ffffff", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "gap": 0 + }, + "submenu": { "padding": 4, "gap": 4 }, + "submenuLabel": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "background": "transparent", + "color": "#a2a5a9", + "fontWeight": "600" + }, + "submenuIcon": { + "size": 20, + "color": "#ffffff", + "focusColor": "#ffffff", + "activeColor": "#181a1f" + }, + "separator": { "borderColor": "#404348" }, + "mobileButton": { + "borderRadius": 8, + "size": 32, + "color": "#ffffff", + "hoverColor": "#cecfd2", + "hoverBackground": "#2b2e33", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "menu": { + "extend": { + "paddingX": 4, + "iconSize": 20, + "paddingY": 4, + "extItem": { + "caption": { "gap": 4, "color": "#a2a5a9" }, + "activeBackground": "#f0f0f1", + "activeColor": "#181a1f", + "icon": { "activeColor": "#181a1f" } + } + }, + "root": { + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "transitionDuration": 180, + "background": "#404348", + "borderColor": "#404348", + "color": "#ffffff" + }, + "list": { "padding": 4, "gap": 4 }, + "submenuLabel": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "fontWeight": "600", + "background": "transparent", + "color": "#a2a5a9" + }, + "separator": { "borderColor": "#404348" }, + "item": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "color": "#ffffff", + "focusBackground": "#2b2e33", + "focusColor": "#cecfd2", + "icon": { "color": "#ffffff", "focusColor": "#cecfd2" } + } + }, + "menubar": { + "extend": { + "iconSize": 20, + "extItem": { "caption": { "color": "#a2a5a9", "gap": 4 } }, + "extSubmenuLabel": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "fontWeight": "600", + "background": "transparent", + "color": "#a2a5a9" + } + }, + "colorScheme": { "root": { "background": "transparent" } }, + "root": { + "borderColor": "transparent", + "borderRadius": 8, + "color": "#ffffff", + "gap": 4, + "padding": 4, + "transitionDuration": 180 + }, + "baseItem": { + "borderRadius": 8, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "item": { + "focusBackground": "#2b2e33", + "activeBackground": "#f0f0f1", + "color": "#ffffff", + "focusColor": "#ffffff", + "activeColor": "#181a1f", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "icon": { + "color": "#ffffff", + "focusColor": "#ffffff", + "activeColor": "#181a1f" + } + }, + "submenu": { + "padding": 4, + "gap": 4, + "background": "#56595f", + "borderColor": "#404348", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "mobileIndent": 14, + "icon": { + "size": 20, + "color": "#ffffff", + "focusColor": "#ffffff", + "activeColor": "#181a1f" + } + }, + "separator": { "borderColor": "#404348" }, + "mobileButton": { + "borderRadius": 8, + "size": 32, + "color": "#ffffff", + "hoverColor": "#cecfd2", + "hoverBackground": "#2b2e33", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "message": { + "extend": { + "width": 400, + "extText": { "gap": 4 }, + "extInfo": { + "color": "#77baf4", + "closeButton": { "color": "#77baf4", "borderColor": "#4496e8" }, + "caption": { "color": "#ffffff" } + }, + "extAccentLine": { "width": 4 }, + "extCloseButton": { "width": 1 }, + "extSuccess": { + "color": "#77f48a", + "closeButton": { "color": "#77f48a", "borderColor": "#44e858" }, + "caption": { "color": "#ffffff" } + }, + "extWarn": { + "color": "#facb75", + "closeButton": { "color": "#facb75", "borderColor": "#f5b83d" }, + "caption": { "color": "#ffffff" } + }, + "extError": { + "color": "#f47f77", + "closeButton": { "color": "#f47f77", "borderColor": "#e85244" }, + "caption": { "color": "#ffffff" } + } + }, + "colorScheme": { + "contrast": { + "background": "#2b2e33", + "borderColor": "transparent", + "closeButton": { + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "transparent" + }, + "color": "#ffffff", + "outlined": { "borderColor": "transparent", "color": "transparent" }, + "shadow": "none", + "simple": { "color": "transparent" } + }, + "error": { + "background": "#3b100c", + "borderColor": "#e85244", + "closeButton": { + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#611912" + }, + "color": "#2b2e33", + "outlined": { "borderColor": "#e85244", "color": "#2b2e33" }, + "shadow": "none", + "simple": { "color": "#2b2e33" } + }, + "info": { + "background": "#0c243b", + "borderColor": "#4496e8", + "closeButton": { + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#123a61" + }, + "color": "#2b2e33", + "outlined": { "borderColor": "#4496e8", "color": "#2b2e33" }, + "shadow": "none", + "simple": { "color": "#2b2e33" } + }, + "secondary": { + "background": "#f0f0f1", + "borderColor": "transparent", + "closeButton": { + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "transparent" + }, + "color": "#2b2e33", + "outlined": { "borderColor": "transparent", "color": "transparent" }, + "shadow": "none", + "simple": { "color": "transparent" } + }, + "success": { + "background": "#0c3b11", + "borderColor": "#44e858", + "closeButton": { + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#12611b" + }, + "color": "#2b2e33", + "outlined": { "borderColor": "#44e858", "color": "#2b2e33" }, + "shadow": "none", + "simple": { "color": "#2b2e33" } + }, + "warn": { + "background": "#453008", + "borderColor": "#f5b83d", + "closeButton": { + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#6d4c0b" + }, + "color": "#2b2e33", + "outlined": { "borderColor": "#f5b83d", "color": "#2b2e33" }, + "shadow": "none", + "simple": { "color": "#2b2e33" } + }, + "outlined": { + "root": { "borderWidth": 0 }, + "closeButton": { + "hoverBackground": "transparent", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "outlined": { "color": "transparent", "borderColor": "transparent" }, + "simple": { "color": "transparent" } + }, + "simple": { "content": { "padding": 0 } } + }, + "root": { "borderRadius": 14, "borderWidth": 1, "transitionDuration": 180 }, + "content": { + "padding": 14, + "gap": 14, + "sm": { "padding": 14 }, + "lg": { "padding": 14 } + }, + "text": { + "fontSize": 16, + "fontWeight": "700", + "sm": { "fontSize": 16 }, + "lg": { "fontSize": 16 } + }, + "icon": { "size": 36, "sm": { "size": 36 }, "lg": { "size": 36 } }, + "closeButton": { + "width": 32, + "height": 32, + "borderRadius": 14, + "focusRing": { "width": 4, "style": "none", "offset": 0 } + }, + "closeIcon": { "size": 16, "sm": { "size": 16 }, "lg": { "size": 16 } }, + "outlined": { "root": { "borderWidth": 1 } }, + "simple": { "content": { "padding": 0 } } + }, + "metergroup": { + "extend": { "extLabel": { "color": "#a2a5a9" } }, + "root": { "borderRadius": 14, "gap": 14 }, + "meters": { "size": 8, "background": "#404348" }, + "label": { "gap": 4 }, + "labelMarker": { "size": 8 }, + "labelIcon": { "size": 16 }, + "labelList": { "verticalGap": 8, "horizontalGap": 14 } + }, + "multiselect": { + "extend": { + "paddingX": 6, + "paddingY": 6, + "borderWidth": 1, + "iconSize": 16, + "width": 272, + "readonlyBackground": "#2b2e33" + }, + "root": { + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "sm": { "fontSize": 16, "paddingX": 8, "paddingY": 8 }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "focusRing": { + "width": 4, + "style": "none", + "offset": 0, + "shadow": "none", + "color": "#d4fedc" + }, + "background": "#404348", + "borderColor": "#56595f", + "color": "#ffffff", + "disabledBackground": "#404348", + "disabledColor": "#a2a5a9", + "filledBackground": "#404348", + "filledFocusBackground": "#404348", + "filledHoverBackground": "#404348", + "focusBorderColor": "#77f48a", + "hoverBorderColor": "#77f48a", + "invalidBorderColor": "#db3424", + "invalidPlaceholderColor": "#fbacaa", + "placeholderColor": "#a2a5a9" + }, + "dropdown": { "width": 272, "color": "#f0f0f1" }, + "overlay": { + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "background": "#404348", + "borderColor": "#404348", + "color": "#ffffff" + }, + "list": { + "padding": 4, + "header": { + "paddingTop": 14, + "paddingRight": 14, + "paddingBottom": 0, + "paddingLeft": 14 + }, + "gap": 4 + }, + "chip": { "borderRadius": 8 }, + "option": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "color": "#ffffff", + "focusBackground": "#2b2e33", + "focusColor": "#ffffff", + "selectedBackground": "#f0f0f1", + "selectedColor": "#ffffff", + "selectedFocusBackground": "#cecfd2", + "selectedFocusColor": "#ffffff" + }, + "optionGroup": { + "fontWeight": "600", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "background": "#56595f", + "color": "#a2a5a9" + }, + "emptyMessage": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "clearIcon": { "color": "#f0f0f1" } + }, + "paginator": { + "root": { + "paddingTop": 0, + "paddingRight": 8, + "paddingBottom": 0, + "paddingLeft": 8, + "gap": 8, + "borderRadius": 14, + "background": "transparent", + "color": "#ffffff", + "transitionDuration": 180 + }, + "currentPageReport": { "color": "#a2a5a9" }, + "navButton": { + "background": "transparent", + "hoverBackground": "#2b2e33", + "selectedBackground": "#f0f0f1", + "color": "#ffffff", + "hoverColor": "#cecfd2", + "selectedColor": "#ffffff", + "width": 40, + "height": 40, + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "focus": "0 0 4px rgba(0, 0, 0, 0.2000)", + "shadow": "none" + } + }, + "jumpToPageInput": { "maxWidth": 80 } + }, + "panelmenu": { + "extend": { + "iconSize": 20, + "extPanel": { "gap": 4 }, + "extItem": { + "activeBackground": "#f0f0f1", + "activeColor": "#181a1f", + "caption": { "color": "#a2a5a9", "gap": 4 } + } + }, + "root": { "gap": 4, "transitionDuration": 180 }, + "panel": { + "background": "transparent", + "borderColor": "transparent", + "borderWidth": 1, + "color": "#ffffff", + "padding": 4, + "borderRadius": 14, + "first": { + "borderTopWidth": 1, + "borderRightWidth": 1, + "borderBottomWidth": 0, + "borderLeftWidth": 1, + "topBorderRadius": 14 + }, + "last": { + "borderTopWidth": 0, + "borderRightWidth": 1, + "borderBottomWidth": 1, + "borderLeftWidth": 1, + "topBorderRadius": 14, + "bottomBorderRadius": 14 + } + }, + "item": { + "focusBackground": "#2b2e33", + "color": "#ffffff", + "focusColor": "#ffffff", + "gap": 8, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "icon": { "color": "#ffffff", "focusColor": "#ffffff" } + }, + "submenu": { "indent": 24 }, + "separator": { "borderColor": "#404348" }, + "submenuIcon": { "color": "#ffffff", "focusColor": "#ffffff" } + }, + "password": { + "extend": { "borderWidth": 1 }, + "colorScheme": { + "strength": { + "mediumBackground": "#f5b83d", + "strongBackground": "#1dc831", + "weakBackground": "#e85244" + }, + "icon": { "color": "#85888e" } + }, + "meter": { "background": "#404348", "borderRadius": 14, "height": 8 }, + "overlay": { + "background": "#404348", + "borderColor": "#56595f", + "borderRadius": 8, + "color": "#ffffff", + "padding": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "content": { "gap": 8 }, + "icon": { "color": "#ffffff" } + }, + "popover": { + "extend": { "borderWidth": 1, "arrow": { "width": 12, "height": 8 } }, + "root": { + "background": "#404348", + "borderColor": "#56595f", + "color": "#ffffff", + "borderRadius": 8, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "gutter": 4, + "arrowOffset": 20 + }, + "content": { "padding": 14 } + }, + "progressbar": { + "label": { "color": "#ffffff", "fontSize": 12, "fontWeight": "400" }, + "root": { "background": "#404348", "borderRadius": 14, "height": 16 }, + "value": { "background": "#44e858" } + }, + "progressspinner": { + "extend": { "small": 16, "medium": 32, "large": 48, "xlarge": 56 }, + "colorScheme": { + "root": { + "colorFour": "#f5b83d", + "colorOne": "#44e858", + "colorThree": "#e85244", + "colorTwo": "#4496e8" + } + }, + "root": { "borderWidth": 4 } + }, + "radiobutton": { + "root": { + "width": 24, + "height": 24, + "background": "#404348", + "checkedBackground": "#f0f0f1", + "checkedHoverBackground": "#e2e2e4", + "disabledBackground": "#404348", + "filledBackground": "#404348", + "borderColor": "#56595f", + "hoverBorderColor": "#f0f0f1", + "focusBorderColor": "#56595f", + "checkedBorderColor": "#f0f0f1", + "checkedHoverBorderColor": "#f0f0f1", + "checkedFocusBorderColor": "#f0f0f1", + "checkedDisabledBorderColor": "#56595f", + "invalidBorderColor": "#db3424", + "shadow": "none", + "transitionDuration": 180, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + }, + "lg": { "height": 20, "width": 20 }, + "sm": { "height": 8, "width": 8 } + }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "sm": { "width": 16, "height": 16 }, + "lg": { "width": 20, "height": 20 }, + "icon": { + "size": 12, + "checkedColor": "#ffffff", + "checkedHoverColor": "#ffffff", + "disabledColor": "#a2a5a9", + "sm": { "size": 8 }, + "lg": { "size": 16 } + } + }, + "rating": { + "root": { + "gap": 8, + "transitionDuration": 180, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + } + }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "icon": { + "size": 24, + "color": "#a2a5a9", + "hoverColor": "#facb75", + "activeColor": "#facb75" + } + }, + "ripple": { "colorScheme": { "root": { "background": "#404348" } } }, + "scrollpanel": { + "colorScheme": { "bar": { "background": "#cecfd2" } }, + "root": { "transitionDuration": 180 }, + "bar": { + "size": 8, + "borderRadius": 8, + "focusRing": { + "width": 0, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "select": { + "extend": { + "extOption": { "background": "#56595f", "gap": 8 }, + "extOptionGroup": { "gap": 8 }, + "readonlyBackground": "#2b2e33", + "borderWidth": 1, + "iconSize": 16 + }, + "root": { + "background": "#404348", + "disabledBackground": "#404348", + "filledBackground": "#404348", + "filledHoverBackground": "#404348", + "filledFocusBackground": "#404348", + "borderColor": "#56595f", + "hoverBorderColor": "#77f48a", + "focusBorderColor": "#77f48a", + "invalidBorderColor": "#db3424", + "color": "#ffffff", + "disabledColor": "#a2a5a9", + "placeholderColor": "#a2a5a9", + "invalidPlaceholderColor": "#fbacaa", + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "sm": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + } + }, + "dropdown": { "width": 272, "color": "#f0f0f1" }, + "overlay": { + "background": "#404348", + "borderColor": "#404348", + "borderRadius": 14, + "color": "#ffffff", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "list": { + "padding": 4, + "gap": 4, + "header": { + "paddingTop": 14, + "paddingRight": 14, + "paddingBottom": 0, + "paddingLeft": 14 + } + }, + "option": { + "focusBackground": "#2b2e33", + "selectedBackground": "#f0f0f1", + "selectedFocusBackground": "#cecfd2", + "color": "#ffffff", + "focusColor": "#ffffff", + "selectedColor": "#ffffff", + "selectedFocusColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8 + }, + "optionGroup": { + "background": "#56595f", + "color": "#a2a5a9", + "fontWeight": "600", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "clearIcon": { "color": "#f0f0f1" }, + "checkmark": { "color": "#ffffff", "gutterStart": -8, "gutterEnd": 8 }, + "emptyMessage": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + } + }, + "selectbutton": { + "extend": { + "gap": 4, + "paddingX": 4, + "paddingY": 4, + "iconSize": { "sm": 16, "md": 20, "lg": 24, "xlg": 28 }, + "checkedBackground": "#56595f", + "checkedBorderColor": "#2b2e33", + "checkedColor": "#f0f0f1", + "ext": { "borderRadius": 8 } + }, + "colorScheme": { + "root": { "invalidBorderColor": "#f47f77" }, + "extend": { "background": "#e2e2e4" } + }, + "root": { "borderRadius": 14 } + }, + "skeleton": { + "extend": { "minWidth": 32, "height": 32 }, + "colorScheme": { + "root": { "background": "#56595f", "animationBackground": "#6d7076" } + }, + "root": { "borderRadius": 14 } + }, + "slider": { + "colorScheme": { "handle": { "content": { "background": "#2b2e33" } } }, + "root": { "transitionDuration": 180 }, + "track": { "background": "#404348", "borderRadius": 14, "size": 4 }, + "range": { "background": "#f0f0f1" }, + "handle": { + "width": 20, + "height": 20, + "borderRadius": 1600, + "background": "#f0f0f1", + "hoverBackground": "#f0f0f1", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "content": { + "borderRadius": 1600, + "hoverBackground": "#f0f0f1", + "width": 12, + "height": 12, + "shadow": "none" + } + } + }, + "splitter": { + "colorScheme": { "handle": { "background": "#2b2e33" } }, + "gutter": { "background": "#2b2e33" }, + "root": { + "background": "#404348", + "borderColor": "#404348", + "color": "#ffffff", + "transitionDuration": 180 + }, + "handle": { + "size": 4, + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "stepper": { + "extend": { + "extCaption": { "gap": 4 }, + "extStepNumber": { + "invalidBackground": "#db3424", + "invalidColor": "#fff0f0", + "invalidBorderColor": "#db3424", + "borderWidth": 1, + "iconSize": 24 + } + }, + "root": { "transitionDuration": 180 }, + "separator": { + "background": "#404348", + "activeBackground": "#f0f0f1", + "marginTop": 0, + "marginRight": 0, + "marginBottom": 0, + "marginLeft": 24, + "size": 1 + }, + "step": { "padding": 8, "gap": 8 }, + "stepHeader": { + "padding": 0, + "borderRadius": 0, + "gap": 8, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "stepTitle": { + "color": "#ffffff", + "activeColor": "#ffffff", + "fontWeight": "400" + }, + "stepNumber": { + "background": "#56595f", + "activeBackground": "#44e858", + "borderColor": "#404348", + "activeBorderColor": "#44e858", + "color": "#ffffff", + "activeColor": "#ffffff", + "size": 24, + "fontSize": 16, + "fontWeight": "700", + "borderRadius": 1600, + "shadow": "none" + }, + "steppanels": { "padding": 14 }, + "steppanel": { + "background": "#56595f", + "color": "#ffffff", + "padding": 0, + "indent": 0 + } + }, + "steps": { + "itemLink": { + "gap": 8, + "borderRadius": 14, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + } + }, + "itemLabel": { + "fontWeight": "400", + "activeColor": "#cecfd2", + "color": "#ffffff" + }, + "itemNumber": { + "background": "#56595f", + "size": 32, + "fontSize": 16, + "fontWeight": "700", + "borderRadius": 1600, + "shadow": "none", + "activeBackground": "#56595f", + "activeBorderColor": "#404348", + "activeColor": "#cecfd2", + "borderColor": "#404348", + "color": "#ffffff" + }, + "root": { "transitionDuration": 180 }, + "separator": { "background": "#404348" } + }, + "tabs": { + "colorScheme": { + "navButton": { "shadow": "none" }, + "tab": { + "activeBackground": "transparent", + "background": "transparent", + "hoverBackground": "transparent" + } + }, + "root": { "transitionDuration": 180 }, + "tablist": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "background": "transparent", + "borderColor": "#404348" + }, + "tab": { + "borderWidth": 0, + "borderColor": "#404348", + "hoverBorderColor": "#404348", + "activeBorderColor": "#e2e2e4", + "color": "#a2a5a9", + "hoverColor": "#ffffff", + "activeColor": "#ffffff", + "padding": 14, + "fontWeight": "600", + "margin": 0, + "gap": 8, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "tabpanel": { + "background": "transparent", + "color": "#ffffff", + "padding": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "navButton": { + "background": "#56595f", + "color": "#ffffff", + "hoverColor": "#cecfd2", + "width": 24, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "activeBar": { "height": 2, "bottom": -2, "background": "#f0f0f1" } + }, + "toast": { + "extend": { + "extInfo": { + "color": "#77baf4", + "closeButton": { "color": "#77baf4", "borderColor": "#4496e8" }, + "caption": { "color": "#ffffff" } + }, + "extAccentLine": { "width": 4 }, + "extCloseButton": { "width": 1 }, + "extSuccess": { + "color": "#77f48a", + "closeButton": { "color": "#77f48a", "borderColor": "#44e858" }, + "caption": { "color": "#ffffff" } + }, + "extWarn": { + "color": "#facb75", + "closeButton": { "color": "#facb75", "borderColor": "#f5b83d" }, + "caption": { "color": "#ffffff" } + }, + "extError": { + "color": "#f47f77", + "closeButton": { "color": "#f47f77", "borderColor": "#e85244" }, + "caption": { "color": "#ffffff" } + } + }, + "colorScheme": { + "contrast": { + "background": "#2b2e33", + "borderColor": "#2b2e33", + "closeButton": { + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#404348" + }, + "color": "#ffffff", + "detailColor": "#e2e2e4", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "error": { + "background": "#3b100c", + "borderColor": "#e85244", + "closeButton": { + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#611912" + }, + "color": "#2b2e33", + "detailColor": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "info": { + "background": "#0c243b", + "borderColor": "#4496e8", + "closeButton": { + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#123a61" + }, + "color": "#2b2e33", + "detailColor": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "root": { "blur": 0 }, + "secondary": { + "background": "#f0f0f1", + "borderColor": "#56595f", + "closeButton": { + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#f0f0f1" + }, + "color": "#2b2e33", + "detailColor": "#a2a5a9", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "success": { + "background": "#0c3b11", + "borderColor": "#44e858", + "closeButton": { + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "hoverBackground": "#12611b" + }, + "color": "#2b2e33", + "detailColor": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "warn": { + "background": "#453008", + "borderColor": "#f5b83d", + "closeButton": { + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#6d4c0b" + }, + "color": "#2b2e33", + "detailColor": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + } + }, + "root": { + "width": 400, + "borderWidth": 1, + "borderRadius": 14, + "transitionDuration": 180 + }, + "icon": { "size": 36 }, + "content": { "padding": 14, "gap": 14 }, + "text": { "gap": 4 }, + "summary": { "fontWeight": "700", "fontSize": 16 }, + "detail": { "fontWeight": "400", "fontSize": 14 }, + "closeButton": { + "width": 32, + "height": 32, + "borderRadius": 14, + "focusRing": { "width": 4, "style": "none", "offset": 0 } + }, + "closeIcon": { "size": 16 } + }, + "tag": { + "colorScheme": { + "contrast": { "background": "#2b2e33", "color": "#ffffff" }, + "danger": { "background": "#8d2218", "color": "#fff0f0" }, + "info": { "background": "#18538d", "color": "#f0f9ff" }, + "primary": { "background": "#44e858", "color": "#2b2e33" }, + "secondary": { "background": "#e2e2e4", "color": "#2b2e33" }, + "success": { "background": "#77f48a", "color": "#f0fff3" }, + "warn": { "background": "#9d6d0e", "color": "#fff9f0" } + }, + "root": { + "fontSize": 12, + "fontWeight": "400", + "paddingTop": 4, + "paddingRight": 8, + "paddingBottom": 4, + "paddingLeft": 8, + "gap": 4, + "borderRadius": 8, + "roundedBorderRadius": 1600 + }, + "icon": { "size": 16 } + }, + "textarea": { + "extend": { + "readonlyBackground": "#2b2e33", + "borderWidth": 1, + "iconSize": 16, + "minHeight": 80 + }, + "root": { + "background": "#404348", + "disabledBackground": "#404348", + "filledBackground": "#404348", + "filledHoverBackground": "#404348", + "filledFocusBackground": "#404348", + "borderColor": "#56595f", + "hoverBorderColor": "#77f48a", + "focusBorderColor": "#77f48a", + "invalidBorderColor": "#db3424", + "color": "#f0f0f1", + "disabledColor": "#a2a5a9", + "placeholderColor": "#a2a5a9", + "invalidPlaceholderColor": "#fbacaa", + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "sm": { "fontSize": 16, "paddingX": 14, "paddingY": 14 } + }, + "sm": { "fontSize": 16, "paddingX": 8, "paddingY": 8 }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 } + }, + "tieredmenu": { + "extend": { + "iconSize": 20, + "extSubmenu": { "borderColor": "#404348", "background": "#56595f" }, + "extItem": { "caption": { "gap": 4, "color": "#a2a5a9" } } + }, + "root": { + "background": "#404348", + "borderColor": "transparent", + "color": "#ffffff", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "transitionDuration": 180 + }, + "list": { "padding": 4, "gap": 4 }, + "item": { + "focusBackground": "#2b2e33", + "activeBackground": "#f0f0f1", + "color": "#ffffff", + "focusColor": "#ffffff", + "activeColor": "#181a1f", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "icon": { + "color": "#ffffff", + "focusColor": "#ffffff", + "activeColor": "#181a1f" + } + }, + "submenu": { "mobileIndent": 14 }, + "separator": { "borderColor": "#404348" }, + "submenuIcon": { + "activeColor": "#cecfd2", + "color": "#ffffff", + "focusColor": "#cecfd2", + "size": 14 + } + }, + "timeline": { + "extend": { "extEvent": { "gap": 4 } }, + "event": { "minHeight": 64 }, + "vertical": { + "eventContent": { + "paddingTop": 0, + "paddingRight": 20, + "paddingBottom": 0, + "paddingLeft": 20 + } + }, + "horizontal": { + "eventContent": { + "paddingTop": 20, + "paddingRight": 0, + "paddingBottom": 20, + "paddingLeft": 0 + } + }, + "eventMarker": { + "size": 16, + "borderRadius": 14, + "borderWidth": 4, + "background": "#56595f", + "borderColor": "#44e858", + "content": { + "borderRadius": 14, + "size": 12, + "background": "transparent", + "insetShadow": "none" + } + }, + "eventConnector": { "color": "#404348", "size": 1 } + }, + "togglebutton": { + "extend": { + "ext": { "gap": 14 }, + "iconSize": { "sm": 16, "md": 20, "lg": 24 }, + "iconOnlyWidth": 40, + "hoverBorderColor": "#56595f", + "checkedHoverColor": "#ffffff", + "checkedHoverBackground": "#e2e2e4", + "checkedHoverBorderColor": "#e2e2e4", + "extXlg": { + "paddingTop": 20, + "paddingRight": 20, + "paddingBottom": 20, + "paddingLeft": 20, + "iconOnlyWidth": 64 + }, + "extSm": { "iconOnlyWidth": 32 }, + "extLg": { "iconOnlyWidth": 56 } + }, + "colorScheme": { + "root": { + "hoverBackground": "#cecfd2", + "background": "#e2e2e4", + "borderColor": "#e2e2e4", + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "checkedBackground": "#2b2e33", + "checkedColor": "#ffffff", + "checkedBorderColor": "#2b2e33", + "disabledBackground": "#e2e2e4", + "disabledBorderColor": "#e2e2e4", + "disabledColor": "#85888e", + "invalidBorderColor": "#f47f77" + }, + "icon": { + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "checkedColor": "#ffffff", + "disabledColor": "#85888e" + }, + "content": { "checkedBackground": "transparent" } + }, + "root": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 1600, + "gap": 8, + "fontWeight": "600", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "sm": { + "fontSize": 14, + "paddingTop": 4, + "paddingRight": 14, + "paddingBottom": 4, + "paddingLeft": 14 + }, + "lg": { + "fontSize": 20, + "paddingTop": 14, + "paddingRight": 24, + "paddingBottom": 14, + "paddingLeft": 24 + }, + "transitionDuration": 180, + "background": "#404348", + "borderColor": "#404348", + "checkedBackground": "#404348", + "checkedBorderColor": "#404348", + "checkedColor": "#ffffff", + "color": "#ffffff", + "disabledBackground": "#404348", + "disabledBorderColor": "#404348", + "disabledColor": "#a2a5a9", + "hoverColor": "#cecfd2", + "invalidBorderColor": "#db3424" + }, + "content": { + "checkedShadow": "none", + "padding": 0, + "borderRadius": 0, + "sm": { "padding": 0 }, + "lg": { "padding": 0 }, + "checkedBackground": "#404348" + }, + "icon": { + "checkedColor": "#ffffff", + "color": "#ffffff", + "disabledColor": "#a2a5a9", + "hoverColor": "#cecfd2" + } + }, + "toggleswitch": { + "colorScheme": { + "handle": { + "background": "#56595f", + "checkedBackground": "#56595f", + "checkedColor": "#2b2e33", + "checkedHoverBackground": "#56595f", + "checkedHoverColor": "#2b2e33", + "color": "#2b2e33", + "disabledBackground": "#85888e", + "hoverBackground": "#56595f", + "hoverColor": "#2b2e33" + }, + "root": { + "background": "#6d7076", + "checkedBackground": "#2b2e33", + "checkedHoverBackground": "#404348", + "disabledBackground": "#e2e2e4", + "hoverBackground": "#85888e" + } + }, + "root": { + "width": 40, + "height": 24, + "borderRadius": 1600, + "gap": 4, + "borderWidth": 1, + "shadow": "none", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + }, + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "checkedBorderColor": "transparent", + "checkedHoverBorderColor": "transparent", + "invalidBorderColor": "#db3424", + "transitionDuration": 180, + "slideDuration": 180 + }, + "handle": { "borderRadius": 1600, "size": 16 } + }, + "tooltip": { + "colorScheme": { "root": { "background": "#2b2e33", "color": "#ffffff" } }, + "root": { + "maxWidth": 400, + "gutter": 4, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8 + } + }, + "tree": { + "root": { + "background": "#404348", + "color": "#ffffff", + "padding": 14, + "gap": 4, + "indent": 14, + "transitionDuration": 180 + }, + "node": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "color": "#ffffff", + "selectedColor": "#ffffff", + "gap": 4, + "borderRadius": 14, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + }, + "hoverBackground": "#2b2e33", + "hoverColor": "#ffffff", + "selectedBackground": "#f0f0f1" + }, + "nodeIcon": { + "selectedColor": "#ffffff", + "color": "#ffffff", + "hoverColor": "#cecfd2" + }, + "nodeToggleButton": { + "borderRadius": 4, + "size": 28, + "selectedHoverBackground": "#f0f0f1", + "color": "#ffffff", + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + }, + "hoverBackground": "#2b2e33", + "hoverColor": "#cecfd2", + "selectedHoverColor": "#cecfd2" + }, + "loadingIcon": { "size": 16 }, + "filter": { + "marginTop": 0, + "marginRight": 0, + "marginBottom": 8, + "marginLeft": 0 + } + }, + "overlaybadge": { + "root": { "outline": { "width": 0, "color": "transparent" } } + } +} diff --git a/src/theme/tokens/components/light.json b/src/theme/tokens/components/light.json new file mode 100644 index 00000000..ab86e22f --- /dev/null +++ b/src/theme/tokens/components/light.json @@ -0,0 +1,2920 @@ +{ + "accordion": { + "extend": { "extHeader": { "iconSize": 20, "gap": 8 } }, + "colorScheme": { + "header": { + "background": "transparent", + "hoverBackground": "transparent", + "activeBackground": "transparent", + "activeHoverBackground": "transparent" + } + }, + "header": { + "color": "#2b2e33", + "hoverColor": "#56595f", + "activeColor": "#2b2e33", + "activeHoverColor": "#56595f", + "borderColor": "transparent", + "paddingTop": 14, + "paddingRight": 0, + "paddingBottom": 14, + "paddingLeft": 0, + "fontWeight": "700", + "borderRadius": 0, + "borderWidth": 0, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "inset 0 0 0 4px #d4fedc" + }, + "toggleIcon": { + "color": "#2b2e33", + "hoverColor": "#56595f", + "activeColor": "#2b2e33", + "activeHoverColor": "#56595f" + }, + "last": { "bottomBorderRadius": 0, "activeBottomBorderRadius": 0 }, + "first": { "borderWidth": 0, "topBorderRadius": 0 } + }, + "root": { "transitionDuration": 180 }, + "panel": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 4, + "borderLeftWidth": 0, + "borderColor": "#cecfd2" + }, + "content": { + "borderTopWidth": 1, + "borderRightWidth": 0, + "borderBottomWidth": 0, + "borderLeftWidth": 0, + "borderColor": "transparent", + "background": "transparent", + "color": "#2b2e33", + "paddingTop": 0, + "paddingRight": 24, + "paddingBottom": 14, + "paddingLeft": 24 + } + }, + "autocomplete": { + "extend": { "extOption": { "gap": 8 }, "extOptionGroup": { "gap": 8 } }, + "colorScheme": { + "chip": { "focusBackground": "#e2e2e4", "focusColor": "#2b2e33" }, + "dropdown": { + "background": "#ffffff", + "hoverBackground": "#ffffff", + "activeBackground": "#ffffff", + "color": "#181a1f", + "hoverColor": "#181a1f", + "activeColor": "#181a1f" + } + }, + "root": { + "background": "#ffffff", + "disabledBackground": "#e2e2e4", + "filledBackground": "#ffffff", + "filledHoverBackground": "#ffffff", + "filledFocusBackground": "#ffffff", + "borderColor": "#cecfd2", + "hoverBorderColor": "#1dc831", + "focusBorderColor": "#1dc831", + "invalidBorderColor": "#f47f77", + "color": "#181a1f", + "disabledColor": "#85888e", + "placeholderColor": "#85888e", + "invalidPlaceholderColor": "#db3424", + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + } + }, + "overlay": { + "background": "#ffffff", + "borderColor": "#e2e2e4", + "borderRadius": 14, + "color": "#2b2e33", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "list": { "padding": 4, "gap": 4 }, + "option": { + "focusBackground": "#f0f0f1", + "selectedBackground": "#2b2e33", + "selectedFocusBackground": "#56595f", + "color": "#2b2e33", + "focusColor": "#2b2e33", + "selectedColor": "#ffffff", + "selectedFocusColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8 + }, + "optionGroup": { + "background": "#ffffff", + "color": "#85888e", + "fontWeight": "600", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "dropdown": { + "width": 272, + "borderColor": "#cecfd2", + "hoverBorderColor": "#1dc831", + "activeBorderColor": "#1dc831", + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + }, + "sm": { "width": 240 }, + "lg": { "width": 304 } + }, + "chip": { "borderRadius": 8 }, + "emptyMessage": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + } + }, + "avatar": { + "extend": { "borderColor": "#cecfd2", "circle": { "borderRadius": 1600 } }, + "root": { + "width": 32, + "height": 32, + "fontSize": 16, + "color": "#2b2e33", + "background": "#44e858", + "borderRadius": 14 + }, + "icon": { "size": 16 }, + "group": { "borderColor": "#ffffff", "offset": -12 }, + "lg": { + "width": 40, + "height": 40, + "fontSize": 16, + "icon": { "size": 16 }, + "group": { "offset": -12 } + }, + "xl": { + "width": 56, + "height": 56, + "icon": { "size": 24 }, + "group": { "offset": -24 }, + "fontSize": 16 + } + }, + "badge": { + "extend": { + "extDot": { + "success": { "background": "#77f48a" }, + "info": { "background": "#77baf4" }, + "warn": { "background": "#facb75" }, + "danger": { "background": "#f47f77" }, + "lg": { "size": 12 }, + "xlg": { "size": 16 } + }, + "ext": { "padding": 0 } + }, + "colorScheme": { + "primary": { "color": "#2b2e33", "background": "#44e858" }, + "secondary": { "color": "#ffffff", "background": "#2b2e33" }, + "success": { "color": "#0e4514", "background": "#aafbb7" }, + "info": { "color": "#0e2a45", "background": "#aad7fb" }, + "warn": { "color": "#4f3709", "background": "#fddeaa" }, + "danger": { "color": "#45120e", "background": "#fbacaa" }, + "contrast": { "background": "#2b2e33", "color": "#ffffff" } + }, + "root": { + "borderRadius": 8, + "padding": 8, + "fontSize": 12, + "fontWeight": "400", + "minWidth": 24, + "height": 24 + }, + "dot": { "size": 8 }, + "sm": { "fontSize": 12, "minWidth": 0, "height": 0 }, + "lg": { "fontSize": 12, "minWidth": 28, "height": 28 }, + "xl": { "fontSize": 12, "minWidth": 32, "height": 32 } + }, + "breadcrumb": { + "extend": { + "hoverBackground": "#f0f0f1", + "iconSize": 20, + "extItem": { "padding": 4 } + }, + "root": { + "padding": 0, + "background": "transparent", + "gap": 0, + "transitionDuration": 180 + }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "item": { + "color": "#2b2e33", + "hoverColor": "#56595f", + "borderRadius": 4, + "gap": 8, + "icon": { "color": "#2b2e33", "hoverColor": "#56595f" }, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + } + }, + "separator": { "color": "#2b2e33" } + }, + "button": { + "extend": { + "disabledBackground": "#e2e2e4", + "extOutlined": { + "danger": { "focusBackground": "transparent" }, + "warn": { "focusBackground": "transparent" }, + "info": { "focusBackground": "transparent" }, + "help": { "focusBackground": "transparent" }, + "success": { "focusBackground": "transparent" } + }, + "disabledColor": "#85888e", + "extText": { + "danger": { "focusBackground": "transparent" }, + "warn": { "focusBackground": "transparent" }, + "info": { "focusBackground": "transparent" }, + "help": { "focusBackground": "transparent" }, + "success": { "focusBackground": "transparent" } + }, + "extLink": { + "background": "transparent", + "colorHover": "#56595f", + "paddingX": 0, + "paddingY": 4, + "sm": { "iconOnlyWidth": 16 }, + "base": { "iconOnlyWidth": 24 }, + "lg": { "iconOnlyWidth": 28 }, + "xlg": { "iconOnlyWidth": 32 } + }, + "extSm": { "borderRadius": 14, "gap": 8 }, + "extLg": { "borderRadius": 14, "gap": 14, "height": 56 }, + "extXlg": { + "borderRadius": 14, + "gap": 14, + "iconOnlyWidth": 64, + "paddingX": 24, + "paddingY": 20, + "height": 64 + }, + "borderWidth": 1, + "iconSize": { "sm": 16, "md": 20, "lg": 24 } + }, + "colorScheme": { + "root": { + "primary": { + "background": "#44e858", + "hoverBackground": "#1dc831", + "activeBackground": "#168322", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "activeColor": "#2b2e33", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "secondary": { + "background": "#2b2e33", + "hoverBackground": "#404348", + "activeBackground": "#56595f", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "#ffffff", + "hoverColor": "#ffffff", + "activeColor": "#ffffff", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "contrast": { + "background": "#e2e2e4", + "hoverBackground": "#cecfd2", + "activeBackground": "#a2a5a9", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "activeColor": "#2b2e33", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "info": { + "background": "#aad7fb", + "hoverBackground": "#77baf4", + "activeBackground": "#4496e8", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "#0e2a45", + "hoverColor": "#0c243b", + "activeColor": "#0e2a45", + "focusRing": { "color": "#d4fedc", "shadow": "none" } + }, + "success": { + "background": "#aafbb7", + "hoverBackground": "#77f48a", + "activeBackground": "#44e858", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "#0e4514", + "hoverColor": "#0c3b11", + "activeColor": "#0e4514", + "focusRing": { "color": "#d4fedc", "shadow": "none" } + }, + "warn": { + "background": "#fddeaa", + "hoverBackground": "#facb75", + "activeBackground": "#f5b83d", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "#4f3709", + "hoverColor": "#453008", + "activeColor": "#4f3709", + "focusRing": { "color": "#d4fedc", "shadow": "none" } + }, + "help": { + "background": "#d8b4fe", + "hoverBackground": "#c084fc", + "activeBackground": "#a855f7", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "#581c87", + "hoverColor": "#3b0764", + "activeColor": "#581c87", + "focusRing": { "color": "#d4fedc", "shadow": "none" } + }, + "danger": { + "background": "#fbacaa", + "hoverBackground": "#f47f77", + "activeBackground": "#e85244", + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "activeBorderColor": "transparent", + "color": "#45120e", + "hoverColor": "#3b100c", + "activeColor": "#45120e", + "focusRing": { "color": "#d4fedc", "shadow": "none" } + } + }, + "outlined": { + "primary": { + "hoverBackground": "#fafffb", + "activeBackground": "#f0fff3", + "borderColor": "#d4fedc", + "color": "#44e858" + }, + "success": { + "hoverBackground": "#f0fff3", + "activeBackground": "#d4fedc", + "borderColor": "#1dc831", + "color": "#1dc831" + }, + "info": { + "hoverBackground": "#f0f9ff", + "activeBackground": "#d4ecfe", + "borderColor": "#1e76cd", + "color": "#1e76cd" + }, + "warn": { + "hoverBackground": "#fff9f0", + "activeBackground": "#ffeed4", + "borderColor": "#dc9710", + "color": "#dc9710" + }, + "help": { + "hoverBackground": "#f3e8ff", + "activeBackground": "#e9d5ff", + "borderColor": "#9333ea", + "color": "#9333ea" + }, + "danger": { + "hoverBackground": "#fff0f0", + "activeBackground": "#fed4d4", + "borderColor": "#db3424", + "color": "#db3424" + }, + "contrast": { + "activeBackground": "#56595f", + "borderColor": "#2b2e33", + "color": "#ffffff", + "hoverBackground": "#404348" + }, + "plain": { + "activeBackground": "#e2e2e4", + "borderColor": "#cecfd2", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + }, + "secondary": { + "activeBackground": "#e2e2e4", + "borderColor": "#cecfd2", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + } + }, + "text": { + "primary": { + "hoverBackground": "#f0f0f1", + "activeBackground": "#e2e2e4", + "color": "#2b2e33" + }, + "success": { + "hoverBackground": "#f0fff3", + "activeBackground": "#d4fedc", + "color": "#1dc831" + }, + "info": { + "hoverBackground": "#f0f9ff", + "activeBackground": "#d4ecfe", + "color": "#1e76cd" + }, + "warn": { + "hoverBackground": "#fff9f0", + "activeBackground": "#ffeed4", + "color": "#dc9710" + }, + "help": { + "hoverBackground": "#f3e8ff", + "activeBackground": "#e9d5ff", + "color": "#9333ea" + }, + "danger": { + "hoverBackground": "#fff0f0", + "activeBackground": "#fed4d4", + "color": "#db3424" + }, + "contrast": { + "activeBackground": "#56595f", + "color": "#ffffff", + "hoverBackground": "#404348" + }, + "plain": { + "activeBackground": "#e2e2e4", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + }, + "secondary": { + "activeBackground": "#e2e2e4", + "color": "#2b2e33", + "hoverBackground": "#f0f0f1" + } + }, + "link": { + "color": "#2b2e33", + "hoverColor": "#56595f", + "activeColor": "#85888e" + } + }, + "root": { + "borderRadius": 14, + "roundedBorderRadius": 1600, + "gap": 8, + "paddingX": 14, + "paddingY": 8, + "iconOnlyWidth": 40, + "raisedShadow": "none", + "badgeSize": 16, + "transitionDuration": 180, + "focusRing": { "width": 4, "style": "none", "offset": 0 }, + "sm": { + "fontSize": 14, + "iconOnlyWidth": 32, + "paddingX": 14, + "paddingY": 8 + }, + "lg": { + "fontSize": 20, + "iconOnlyWidth": 56, + "paddingX": 24, + "paddingY": 14 + }, + "label": { "fontWeight": "600" } + } + }, + "card": { + "extend": { "borderColor": "#e2e2e4", "borderWidth": 1 }, + "root": { + "background": "#ffffff", + "borderRadius": 14, + "color": "#2b2e33", + "shadow": "none" + }, + "body": { "padding": 14, "gap": 14 }, + "caption": { "gap": 4 }, + "title": { "fontSize": 18, "fontWeight": "600" }, + "subtitle": { "color": "#85888e" } + }, + "carousel": { + "colorScheme": { + "indicator": { + "background": "#cecfd2", + "hoverBackground": "#a2a5a9", + "activeBackground": "#2b2e33" + } + }, + "root": { "transitionDuration": 180 }, + "content": { "gap": 8 }, + "indicatorList": { "padding": 14, "gap": 8 }, + "indicator": { + "width": 8, + "height": 8, + "borderRadius": 1600, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "checkbox": { + "root": { + "borderRadius": 8, + "extend": { "borderWidth": 1 }, + "width": 24, + "height": 24, + "background": "#ffffff", + "checkedBackground": "#2b2e33", + "checkedHoverBackground": "#404348", + "disabledBackground": "#e2e2e4", + "filledBackground": "#ffffff", + "borderColor": "#cecfd2", + "hoverBorderColor": "#2b2e33", + "focusBorderColor": "#2b2e33", + "checkedBorderColor": "#2b2e33", + "checkedHoverBorderColor": "#404348", + "checkedFocusBorderColor": "#44e858", + "checkedDisabledBorderColor": "#cecfd2", + "invalidBorderColor": "#f47f77", + "shadow": "none", + "focusRing": { + "focusRing": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)", + "width": 4 + }, + "sm": { "width": 8, "height": 8 }, + "lg": { "width": 20, "height": 20 }, + "transitionDuration": 180 + }, + "icon": { + "size": 16, + "color": "#181a1f", + "checkedColor": "#ffffff", + "checkedHoverColor": "#ffffff", + "disabledColor": "#85888e", + "sm": { "size": 12 }, + "lg": { "size": 20 } + } + }, + "chip": { + "extend": { "borderColor": "transparent", "borderWidth": 1 }, + "root": { + "borderRadius": 8, + "paddingX": 8, + "paddingY": 4, + "gap": 8, + "transitionDuration": 180 + }, + "colorScheme": { + "root": { "background": "#e2e2e4", "color": "#2b2e33" }, + "icon": { "color": "#2b2e33" }, + "removeIcon": { "color": "#2b2e33" } + }, + "image": { "width": 0, "height": 0 }, + "icon": { "size": 16 }, + "removeIcon": { + "size": 16, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "confirmdialog": { + "extend": { + "extIcon": { + "success": "#44e858", + "info": "#4496e8", + "help": "#a855f7", + "warn": "#f5b83d", + "danger": "#e85244" + } + }, + "icon": { "size": 24, "color": "#2b2e33" }, + "content": { "gap": 0 } + }, + "confirmpopup": { + "root": { + "background": "#ffffff", + "color": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "gutter": 14, + "arrowOffset": 20, + "borderColor": "#e2e2e4", + "borderRadius": 14 + }, + "content": { "padding": 14, "gap": 14 }, + "icon": { "size": 24, "color": "#2b2e33" }, + "footer": { + "gap": 8, + "paddingTop": 0, + "paddingRight": 24, + "paddingBottom": 24, + "paddingLeft": 24 + } + }, + "contextmenu": { + "root": { + "background": "#ffffff", + "color": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "borderColor": "#e2e2e4", + "borderRadius": 14, + "transitionDuration": 180 + }, + "list": { + "paddingTop": 8, + "paddingRight": 0, + "paddingBottom": 8, + "paddingLeft": 0, + "gap": 4 + }, + "item": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "gap": 8, + "activeBackground": "#e2e2e4", + "activeColor": "#56595f", + "borderRadius": 14, + "color": "#2b2e33", + "focusBackground": "#f0f0f1", + "focusColor": "#56595f", + "icon": { + "activeColor": "#56595f", + "color": "#2b2e33", + "focusColor": "#56595f" + } + }, + "submenu": { "mobileIndent": 20 }, + "separator": { "borderColor": "#e2e2e4" }, + "submenuIcon": { + "activeColor": "#56595f", + "color": "#2b2e33", + "focusColor": "#56595f", + "size": 14 + } + }, + "datatable": { + "colorScheme": { + "root": { "color": "#2b2e33", "borderColor": "#e2e2e4" }, + "header": { "background": "#fafafa", "color": "#2b2e33" }, + "headerCell": { + "background": "#fafafa", + "hoverBackground": "#f0f0f1", + "color": "#2b2e33" + }, + "footer": { "background": "#f0f0f1", "color": "#2b2e33" }, + "footerCell": { "background": "#f0f0f1", "color": "#2b2e33" }, + "row": { "stripedBackground": "#f0f0f1" }, + "bodyCell": { "selectedBorderColor": "#e2e2e4" } + }, + "extended": { + "extHeaderCell": { "selectedHoverBackground": "#404348" }, + "extRow": { + "selectedHoverBackground": "#404348", + "stripedHoverBackground": "#f0f0f1", + "iconSize": 20 + } + }, + "root": { "transitionDuration": 180 }, + "header": { + "borderColor": "#e2e2e4", + "borderTopWidth": 1, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "padding": 14, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "headerCell": { + "selectedBackground": "#2b2e33", + "borderColor": "#e2e2e4", + "hoverColor": "#56595f", + "selectedColor": "#ffffff", + "gap": 8, + "padding": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "inset 0 0 0 4px #d4fedc" + }, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "columnTitle": { "fontWeight": "700" }, + "row": { + "background": "#ffffff", + "hoverBackground": "#f0f0f1", + "selectedBackground": "#2b2e33", + "color": "#2b2e33", + "hoverColor": "#56595f", + "selectedColor": "#ffffff", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "inset 0 0 0 4px #d4fedc" + } + }, + "bodyCell": { + "borderColor": "#e2e2e4", + "padding": 14, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "footerCell": { + "borderColor": "#e2e2e4", + "padding": 14, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "columnFooter": { "fontWeight": "700" }, + "dropPoint": { "color": "#2b2e33" }, + "footer": { + "borderColor": "#e2e2e4", + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "padding": 14, + "sm": { "padding": 8 }, + "lg": { "padding": 20 } + }, + "columnResizer": { "width": 8 }, + "resizeIndicator": { "width": 1, "color": "#2b2e33" }, + "sortIcon": { "color": "#2b2e33", "hoverColor": "#56595f", "size": 16 }, + "loadingIcon": { "size": 32 }, + "rowToggleButton": { + "hoverBackground": "#f0f0f1", + "selectedHoverBackground": "#f0f0f1", + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "selectedHoverColor": "#2b2e33", + "size": 32, + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "filter": { + "inlineGap": 8, + "rule": { "borderColor": "#e2e2e4" }, + "constraintList": { "padding": 4, "gap": 4 }, + "constraint": { + "focusBackground": "#f0f0f1", + "selectedBackground": "#2b2e33", + "selectedFocusBackground": "#56595f", + "color": "#2b2e33", + "focusColor": "#2b2e33", + "selectedColor": "#ffffff", + "selectedFocusColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "separator": { "borderColor": "#e2e2e4" } + }, + "overlaySelect": { + "background": "#ffffff", + "color": "#2b2e33", + "borderColor": "#e2e2e4", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "overlayPopover": { + "background": "#ffffff", + "color": "#2b2e33", + "borderColor": "#e2e2e4", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "padding": 14, + "gap": 4 + } + }, + "paginatorTop": { + "borderColor": "#cecfd2", + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0 + }, + "paginatorBottom": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "borderColor": "#e2e2e4" + } + }, + "dataview": { + "root": { + "borderWidth": 1, + "borderRadius": 4, + "padding": 0, + "borderColor": "#e2e2e4" + }, + "header": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": "0px 0px 0px 0px", + "color": "#2b2e33", + "borderColor": "#e2e2e4" + }, + "content": { + "background": "#ffffff", + "color": "#2b2e33", + "borderColor": "#e2e2e4", + "borderWidth": 0, + "padding": 0, + "borderRadius": 0 + }, + "footer": { + "background": "#f0f0f1", + "color": "#2b2e33", + "borderTopWidth": 1, + "borderRightWidth": 0, + "borderBottomWidth": 0, + "borderLeftWidth": 0, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": "0px 0px 0px 0px", + "borderColor": "#e2e2e4" + }, + "paginatorTop": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "borderColor": "#e2e2e4" + }, + "paginatorBottom": { + "borderTopWidth": 1, + "borderRightWidth": 0, + "borderBottomWidth": 0, + "borderLeftWidth": 0, + "borderColor": "#e2e2e4" + }, + "colorScheme": { "header": { "background": "#ffffff", "color": "#2b2e33" } } + }, + "datepicker": { + "extend": { + "extDate": { "selectedHoverBackground": "#404348" }, + "extToday": { "hoverBackground": "#f0f0f1", "borderColor": "#404348" }, + "extTitle": { "width": 336 }, + "extTimePicker": { "minWidth": 304, "color": "#2b2e33" } + }, + "colorScheme": { + "dropdown": { + "background": "#ffffff", + "hoverBackground": "#f0f0f1", + "activeBackground": "#2b2e33", + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "activeColor": "#ffffff" + }, + "today": { "background": "transparent", "color": "#2b2e33" } + }, + "panel": { + "background": "#ffffff", + "borderColor": "#e2e2e4", + "color": "#2b2e33", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "padding": 0 + }, + "header": { + "background": "#ffffff", + "borderColor": "#e2e2e4", + "color": "#2b2e33", + "padding": 14 + }, + "title": { "gap": 8, "fontWeight": "700" }, + "selectMonth": { + "hoverBackground": "#f0f0f1", + "color": "#2b2e33", + "hoverColor": "#56595f", + "borderRadius": 14, + "padding": 8 + }, + "inputIcon": { "color": "#85888e" }, + "dropdown": { + "width": 272, + "borderColor": "#cecfd2", + "hoverBorderColor": "#cecfd2", + "activeBorderColor": "#cecfd2", + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "sm": { "width": 0 }, + "lg": { "width": 0 } + }, + "group": { "borderColor": "#e2e2e4", "gap": 14 }, + "selectYear": { + "hoverBackground": "#f0f0f1", + "color": "#2b2e33", + "hoverColor": "#56595f", + "borderRadius": 14, + "padding": 4 + }, + "dayView": { "margin": 14 }, + "weekDay": { "padding": 4, "fontWeight": "700", "color": "#2b2e33" }, + "date": { + "hoverBackground": "#f0f0f1", + "selectedBackground": "#2b2e33", + "rangeSelectedBackground": "#f0f0f1", + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "selectedColor": "#ffffff", + "rangeSelectedColor": "#2b2e33", + "width": 32, + "height": 32, + "borderRadius": 8, + "padding": 4, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "monthView": { + "marginTop": 0, + "marginRight": 0, + "marginBottom": 0, + "marginLeft": 0 + }, + "month": { "padding": 0, "borderRadius": 0 }, + "yearView": { + "marginTop": 0, + "marginRight": 0, + "marginBottom": 0, + "marginLeft": 0 + }, + "year": { "padding": 0, "borderRadius": 0 }, + "buttonbar": { "padding": 14, "borderColor": "#e2e2e4" }, + "timePicker": { + "padding": 14, + "borderColor": "#e2e2e4", + "gap": 8, + "buttonGap": 4 + }, + "root": { "transitionDuration": 180 } + }, + "dialog": { + "extend": { "borderWidth": 1, "backdrop": "rgba(0, 0, 0, 0.4000)" }, + "root": { + "background": "#ffffff", + "borderColor": "#e2e2e4", + "color": "#2b2e33", + "borderRadius": 1600, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "header": { + "paddingTop": 24, + "paddingRight": 24, + "paddingBottom": 14, + "paddingLeft": 24, + "gap": 8 + }, + "title": { "fontSize": 20, "fontWeight": "600" }, + "content": { "padding": 24 }, + "footer": { + "paddingTop": 0, + "paddingRight": 24, + "paddingBottom": 24, + "paddingLeft": 24, + "gap": 8 + } + }, + "divider": { + "extend": { "content": { "gap": 8 }, "iconSize": 16 }, + "horizontal": { + "marginTop": 14, + "marginRight": 0, + "marginBottom": 14, + "marginLeft": 0, + "paddingTop": 0, + "paddingRight": 14, + "paddingBottom": 0, + "paddingLeft": 14, + "content": { + "paddingTop": 0, + "paddingRight": 8, + "paddingBottom": 0, + "paddingLeft": 8 + } + }, + "vertical": { + "marginTop": 0, + "marginRight": 14, + "marginBottom": 0, + "marginLeft": 14, + "paddingTop": 14, + "paddingRight": 0, + "paddingBottom": 14, + "paddingLeft": 0, + "content": { + "paddingTop": 8, + "paddingRight": 0, + "paddingBottom": 8, + "paddingLeft": 0 + } + }, + "content": { "background": "#ffffff", "color": "#2b2e33" }, + "root": { "borderColor": "#e2e2e4" } + }, + "drawer": { + "extend": { + "borderRadius": 8, + "borderWidth": 1, + "width": 400, + "extHeader": { "gap": 8, "borderColor": "#e2e2e4" }, + "margin": 8, + "scale": 2, + "backdrop": "rgba(0, 0, 0, 0.4000)" + }, + "root": { + "background": "#ffffff", + "borderColor": "#e2e2e4", + "color": "#2b2e33", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "header": { + "paddingTop": 24, + "paddingRight": 24, + "paddingBottom": 14, + "paddingLeft": 24 + }, + "title": { "fontSize": 20, "fontWeight": "600" }, + "content": { "padding": 24 }, + "footer": { + "paddingTop": 0, + "paddingRight": 24, + "paddingBottom": 24, + "paddingLeft": 24 + } + }, + "fileupload": { + "extend": { + "extDragNdrop": { + "background": "#ffffff", + "borderRadius": 14, + "iconSize": 32, + "padding": 14, + "info": { "gap": 4 } + }, + "extFile": { "iconSize": 20 }, + "extContent": { "borderRadius": 14, "highlightBorderDefault": "#cecfd2" } + }, + "colorScheme": { + "header": { "background": "#ffffff", "color": "#2b2e33" } + }, + "root": { + "background": "#ffffff", + "borderColor": "#e2e2e4", + "color": "#2b2e33", + "borderRadius": 14, + "transitionDuration": 180 + }, + "header": { + "borderColor": "#e2e2e4", + "borderWidth": 0, + "padding": 0, + "borderRadius": 0, + "gap": 8 + }, + "content": { "highlightBorderColor": "#2b2e33", "padding": 0, "gap": 8 }, + "file": { + "padding": 8, + "gap": 8, + "borderColor": "#cecfd2", + "info": { "gap": 4 } + }, + "fileList": { "gap": 8 }, + "progressbar": { "height": 8 }, + "basic": { "gap": 8 } + }, + "floatlabel": { + "extend": { "height": 64, "iconSize": 20 }, + "root": { + "color": "#85888e", + "focusColor": "#85888e", + "activeColor": "#85888e", + "invalidColor": "#db3424", + "transitionDuration": 180, + "positionX": 14, + "positionY": 14, + "fontWeight": "400", + "active": { "fontSize": 12, "fontWeight": "400" } + }, + "over": { "active": { "top": 14 } }, + "inside": { + "input": { "paddingTop": 28, "paddingBottom": 14 }, + "active": { "top": 14 } + }, + "on": { + "borderRadius": 0, + "active": { + "paddingTop": 0, + "paddingRight": 4, + "paddingBottom": 0, + "paddingLeft": 4, + "background": "#ffffff" + } + } + }, + "galleria": { + "extend": { "backdrop": "rgba(0, 0, 0, 0.4000)" }, + "colorScheme": { + "thumbnailContent": { "background": "#f0f0f1" }, + "thumbnailNavButton": { + "hoverBackground": "#e2e2e4", + "color": "#2b2e33", + "hoverColor": "#56595f" + }, + "indicatorButton": { + "background": "#cecfd2", + "hoverBackground": "#a2a5a9" + }, + "thumbnailsContent": { "background": "#e2e2e4" } + }, + "root": { + "borderWidth": 1, + "borderColor": "#e2e2e4", + "borderRadius": 14, + "transitionDuration": 180 + }, + "navButton": { + "background": "transparent", + "hoverBackground": "#e2e2e4", + "color": "#ffffff", + "hoverColor": "#ffffff", + "size": 64, + "gutter": 8, + "prev": { "borderRadius": 8 }, + "next": { "borderRadius": 8 }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "navIcon": { "size": 32 }, + "thumbnailsContent": { "padding": 4 }, + "thumbnailNavButton": { + "size": 32, + "borderRadius": 14, + "gutter": 8, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "thumbnailNavButtonIcon": { "size": 16 }, + "caption": { "background": "#e2e2e4", "color": "#2b2e33", "padding": 8 }, + "indicatorList": { "gap": 8, "padding": 14 }, + "indicatorButton": { + "width": 8, + "height": 8, + "activeBackground": "#2b2e33", + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "insetIndicatorList": { "background": "rgba(0, 0, 0, 0.4000)" }, + "insetIndicatorButton": { + "background": "#e2e2e4", + "hoverBackground": "#e2e2e4", + "activeBackground": "#e2e2e4" + }, + "closeButton": { + "size": 64, + "gutter": 8, + "background": "#e2e2e4", + "hoverBackground": "#e2e2e4", + "color": "#ffffff", + "hoverColor": "#ffffff", + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "closeButtonIcon": { "size": 32 } + }, + "inputgroup": { + "extend": { "borderWidth": 1, "iconSize": 16 }, + "colorScheme": { + "addon": { + "background": "#ffffff", + "borderColor": "#cecfd2", + "color": "#85888e" + } + }, + "addon": { "borderRadius": 14, "padding": 14, "minWidth": 272 } + }, + "inputnumber": { + "extend": { + "borderWidth": 1, + "extButton": { "height": 40, "iconSize": 16 } + }, + "colorScheme": { + "button": { + "background": "#ffffff", + "hoverBackground": "#f0f0f1", + "activeBackground": "transparent", + "borderColor": "#cecfd2", + "hoverBorderColor": "#cecfd2", + "activeBorderColor": "#cecfd2", + "color": "#2b2e33", + "hoverColor": "#56595f", + "activeColor": "#2b2e33" + } + }, + "transitionDuration": { "transitionDuration": 180 }, + "button": { "width": 272, "borderRadius": 14, "verticalPadding": 14 }, + "root": { "transitionDuration": 180 } + }, + "inputotp": { + "extend": { "height": 40, "borderWidth": 1 }, + "root": { "gap": 8 }, + "input": { "width": 304, "lg": { "width": 336 }, "sm": { "width": 272 } }, + "sm": { "width": 0 }, + "lg": { "width": 0 } + }, + "inputtext": { + "extend": { + "readonlyBackground": "#f0f0f1", + "iconSize": 16, + "borderWidth": 1, + "extXlg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 } + }, + "root": { + "background": "#ffffff", + "disabledBackground": "#e2e2e4", + "filledBackground": "#ffffff", + "filledHoverBackground": "#ffffff", + "filledFocusBackground": "#ffffff", + "borderColor": "#cecfd2", + "hoverBorderColor": "#1dc831", + "focusBorderColor": "#1dc831", + "invalidBorderColor": "#f47f77", + "color": "#2b2e33", + "disabledColor": "#85888e", + "placeholderColor": "#85888e", + "invalidPlaceholderColor": "#db3424", + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "sm": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + } + } + }, + "listbox": { + "extend": { + "extOption": { + "label": { "gap": 4 }, + "caption": { "color": "#85888e", "stripedColor": "#85888e" }, + "gap": 8 + } + }, + "colorScheme": { "option": { "stripedBackground": "#fafafa" } }, + "root": { + "background": "#ffffff", + "disabledBackground": "#e2e2e4", + "borderColor": "#cecfd2", + "invalidBorderColor": "#f47f77", + "color": "#181a1f", + "disabledColor": "#85888e", + "shadow": "none", + "borderRadius": 14, + "transitionDuration": 180 + }, + "list": { + "padding": 4, + "gap": 4, + "header": { + "paddingTop": 14, + "paddingRight": 14, + "paddingBottom": 0, + "paddingLeft": 14 + } + }, + "option": { + "focusBackground": "#f0f0f1", + "selectedBackground": "#2b2e33", + "selectedFocusBackground": "#56595f", + "color": "#2b2e33", + "focusColor": "#2b2e33", + "selectedColor": "#ffffff", + "selectedFocusColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8 + }, + "optionGroup": { + "background": "#ffffff", + "color": "#85888e", + "fontWeight": "600", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "checkmark": { "color": "#2b2e33", "gutterStart": -8, "gutterEnd": 8 }, + "emptyMessage": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + } + }, + "megamenu": { + "extend": { + "extItem": { "caption": { "color": "#85888e", "gap": 4 } }, + "iconSize": 20 + }, + "colorScheme": { "root": { "background": "transparent" } }, + "root": { + "borderColor": "transparent", + "borderRadius": 14, + "color": "#2b2e33", + "gap": 4, + "transitionDuration": 180, + "verticalOrientation": { "padding": 4, "gap": 4 }, + "horizontalOrientation": { "padding": 4, "gap": 4 } + }, + "baseItem": { + "borderRadius": 14, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "item": { + "focusBackground": "#f0f0f1", + "activeBackground": "#2b2e33", + "color": "#2b2e33", + "focusColor": "#2b2e33", + "activeColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "icon": { + "color": "#2b2e33", + "focusColor": "#2b2e33", + "activeColor": "#ffffff" + } + }, + "overlay": { + "padding": 4, + "background": "#ffffff", + "borderColor": "#e2e2e4", + "borderRadius": 14, + "color": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "gap": 0 + }, + "submenu": { "padding": 4, "gap": 4 }, + "submenuLabel": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "background": "transparent", + "color": "#85888e", + "fontWeight": "600" + }, + "submenuIcon": { + "size": 20, + "color": "#2b2e33", + "focusColor": "#2b2e33", + "activeColor": "#ffffff" + }, + "separator": { "borderColor": "#e2e2e4" }, + "mobileButton": { + "borderRadius": 8, + "size": 32, + "color": "#2b2e33", + "hoverColor": "#56595f", + "hoverBackground": "#f0f0f1", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "menu": { + "extend": { + "paddingX": 4, + "iconSize": 20, + "paddingY": 4, + "extItem": { + "caption": { "gap": 4, "color": "#85888e" }, + "activeBackground": "#2b2e33", + "activeColor": "#ffffff", + "icon": { "activeColor": "#ffffff" } + } + }, + "root": { + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "transitionDuration": 180, + "background": "#ffffff", + "borderColor": "#e2e2e4", + "color": "#2b2e33" + }, + "list": { "padding": 4, "gap": 4 }, + "submenuLabel": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "fontWeight": "600", + "background": "transparent", + "color": "#85888e" + }, + "separator": { "borderColor": "#e2e2e4" }, + "item": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "color": "#2b2e33", + "focusBackground": "#f0f0f1", + "focusColor": "#56595f", + "icon": { "color": "#2b2e33", "focusColor": "#56595f" } + } + }, + "menubar": { + "extend": { + "iconSize": 20, + "extItem": { "caption": { "color": "#85888e", "gap": 4 } }, + "extSubmenuLabel": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "fontWeight": "600", + "background": "transparent", + "color": "#85888e" + } + }, + "colorScheme": { "root": { "background": "transparent" } }, + "root": { + "borderColor": "transparent", + "borderRadius": 8, + "color": "#2b2e33", + "gap": 4, + "padding": 4, + "transitionDuration": 180 + }, + "baseItem": { + "borderRadius": 8, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "item": { + "focusBackground": "#f0f0f1", + "activeBackground": "#2b2e33", + "color": "#2b2e33", + "focusColor": "#2b2e33", + "activeColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "icon": { + "color": "#2b2e33", + "focusColor": "#2b2e33", + "activeColor": "#ffffff" + } + }, + "submenu": { + "padding": 4, + "gap": 4, + "background": "#ffffff", + "borderColor": "#e2e2e4", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "mobileIndent": 14, + "icon": { + "size": 20, + "color": "#2b2e33", + "focusColor": "#2b2e33", + "activeColor": "#ffffff" + } + }, + "separator": { "borderColor": "#e2e2e4" }, + "mobileButton": { + "borderRadius": 8, + "size": 32, + "color": "#2b2e33", + "hoverColor": "#56595f", + "hoverBackground": "#f0f0f1", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "message": { + "extend": { + "width": 400, + "extText": { "gap": 4 }, + "extInfo": { + "color": "#4496e8", + "closeButton": { "color": "#4496e8", "borderColor": "#4496e8" }, + "caption": { "color": "#2b2e33" } + }, + "extAccentLine": { "width": 4 }, + "extCloseButton": { "width": 1 }, + "extSuccess": { + "color": "#44e858", + "closeButton": { "color": "#44e858", "borderColor": "#44e858" }, + "caption": { "color": "#2b2e33" } + }, + "extWarn": { + "color": "#f5b83d", + "closeButton": { "color": "#f5b83d", "borderColor": "#f5b83d" }, + "caption": { "color": "#2b2e33" } + }, + "extError": { + "color": "#e85244", + "closeButton": { "color": "#e85244", "borderColor": "#e85244" }, + "caption": { "color": "#2b2e33" } + } + }, + "colorScheme": { + "success": { + "background": "#fafffb", + "borderColor": "#44e858", + "color": "#2b2e33", + "shadow": "none", + "outlined": { "color": "#2b2e33", "borderColor": "#44e858" }, + "closeButton": { + "hoverBackground": "#d4fedc", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "simple": { "color": "#2b2e33" } + }, + "outlined": { + "root": { "borderWidth": 0 }, + "closeButton": { + "hoverBackground": "transparent", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "outlined": { "color": "transparent", "borderColor": "transparent" }, + "simple": { "color": "transparent" } + }, + "simple": { "content": { "padding": 0 } }, + "warn": { + "background": "#fffdfa", + "borderColor": "#f5b83d", + "color": "#2b2e33", + "shadow": "none", + "outlined": { "color": "#2b2e33", "borderColor": "#f5b83d" }, + "closeButton": { + "hoverBackground": "#ffeed4", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "simple": { "color": "#2b2e33" } + }, + "error": { + "background": "#fffafa", + "borderColor": "#e85244", + "color": "#2b2e33", + "shadow": "none", + "outlined": { "color": "#2b2e33", "borderColor": "#e85244" }, + "closeButton": { + "hoverBackground": "#fed4d4", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "simple": { "color": "#2b2e33" } + }, + "secondary": { + "borderColor": "transparent", + "shadow": "none", + "closeButton": { + "hoverBackground": "transparent", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "simple": { "color": "transparent" }, + "outlined": { "color": "transparent", "borderColor": "transparent" }, + "background": "#f0f0f1", + "color": "#2b2e33" + }, + "contrast": { + "borderColor": "transparent", + "shadow": "none", + "closeButton": { + "hoverBackground": "transparent", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "simple": { "color": "transparent" }, + "outlined": { "color": "transparent", "borderColor": "transparent" }, + "background": "#2b2e33", + "color": "#ffffff" + }, + "info": { + "background": "#fafdff", + "borderColor": "#4496e8", + "color": "#2b2e33", + "shadow": "none", + "closeButton": { + "hoverBackground": "#d4ecfe", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "outlined": { "color": "#2b2e33", "borderColor": "#4496e8" }, + "simple": { "color": "#2b2e33" } + } + }, + "root": { "borderRadius": 14, "borderWidth": 1, "transitionDuration": 180 }, + "content": { + "padding": 14, + "gap": 14, + "sm": { "padding": 14 }, + "lg": { "padding": 14 } + }, + "text": { + "fontSize": 16, + "fontWeight": "700", + "sm": { "fontSize": 16 }, + "lg": { "fontSize": 16 } + }, + "icon": { "size": 36, "sm": { "size": 36 }, "lg": { "size": 36 } }, + "closeButton": { + "width": 32, + "height": 32, + "borderRadius": 14, + "focusRing": { "width": 4, "style": "none", "offset": 0 } + }, + "closeIcon": { "size": 16, "sm": { "size": 16 }, "lg": { "size": 16 } }, + "outlined": { "root": { "borderWidth": 1 } }, + "simple": { "content": { "padding": 0 } } + }, + "metergroup": { + "extend": { "extLabel": { "color": "#85888e" } }, + "root": { "borderRadius": 14, "gap": 14 }, + "meters": { "size": 8, "background": "#e2e2e4" }, + "label": { "gap": 4 }, + "labelMarker": { "size": 8 }, + "labelIcon": { "size": 16 }, + "labelList": { "verticalGap": 8, "horizontalGap": 14 } + }, + "multiselect": { + "extend": { + "paddingX": 6, + "paddingY": 6, + "borderWidth": 1, + "iconSize": 16, + "width": 272, + "readonlyBackground": "#f0f0f1" + }, + "root": { + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "sm": { "fontSize": 16, "paddingX": 8, "paddingY": 8 }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "focusRing": { + "width": 4, + "style": "none", + "offset": 0, + "shadow": "none", + "color": "#d4fedc" + }, + "background": "#ffffff", + "borderColor": "#cecfd2", + "color": "#2b2e33", + "disabledBackground": "#e2e2e4", + "disabledColor": "#85888e", + "filledBackground": "#ffffff", + "filledFocusBackground": "#ffffff", + "filledHoverBackground": "#ffffff", + "focusBorderColor": "#1dc831", + "hoverBorderColor": "#1dc831", + "invalidBorderColor": "#f47f77", + "invalidPlaceholderColor": "#db3424", + "placeholderColor": "#85888e" + }, + "dropdown": { "width": 272, "color": "#181a1f" }, + "overlay": { + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "background": "#ffffff", + "borderColor": "#e2e2e4", + "color": "#2b2e33" + }, + "list": { + "padding": 4, + "header": { + "paddingTop": 14, + "paddingRight": 14, + "paddingBottom": 0, + "paddingLeft": 14 + }, + "gap": 4 + }, + "chip": { "borderRadius": 8 }, + "option": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "color": "#2b2e33", + "focusBackground": "#f0f0f1", + "focusColor": "#2b2e33", + "selectedBackground": "#2b2e33", + "selectedColor": "#ffffff", + "selectedFocusBackground": "#56595f", + "selectedFocusColor": "#ffffff" + }, + "optionGroup": { + "fontWeight": "600", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "background": "#ffffff", + "color": "#85888e" + }, + "emptyMessage": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "clearIcon": { "color": "#181a1f" } + }, + "paginator": { + "root": { + "paddingTop": 0, + "paddingRight": 8, + "paddingBottom": 0, + "paddingLeft": 8, + "gap": 8, + "borderRadius": 14, + "background": "transparent", + "color": "#2b2e33", + "transitionDuration": 180 + }, + "currentPageReport": { "color": "#85888e" }, + "navButton": { + "background": "transparent", + "hoverBackground": "#f0f0f1", + "selectedBackground": "#2b2e33", + "color": "#2b2e33", + "hoverColor": "#56595f", + "selectedColor": "#ffffff", + "width": 40, + "height": 40, + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "focus": "0 0 4px rgba(0, 0, 0, 0.2000)", + "shadow": "none" + } + }, + "jumpToPageInput": { "maxWidth": 80 } + }, + "panelmenu": { + "extend": { + "iconSize": 20, + "extPanel": { "gap": 4 }, + "extItem": { + "activeBackground": "#2b2e33", + "activeColor": "#ffffff", + "caption": { "color": "#85888e", "gap": 4 } + } + }, + "root": { "gap": 4, "transitionDuration": 180 }, + "panel": { + "background": "transparent", + "borderColor": "transparent", + "borderWidth": 1, + "color": "#2b2e33", + "padding": 4, + "borderRadius": 14, + "first": { + "borderTopWidth": 1, + "borderRightWidth": 1, + "borderBottomWidth": 0, + "borderLeftWidth": 1, + "topBorderRadius": 14 + }, + "last": { + "borderTopWidth": 0, + "borderRightWidth": 1, + "borderBottomWidth": 1, + "borderLeftWidth": 1, + "topBorderRadius": 14, + "bottomBorderRadius": 14 + } + }, + "item": { + "focusBackground": "#f0f0f1", + "color": "#2b2e33", + "focusColor": "#2b2e33", + "gap": 8, + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "icon": { "color": "#2b2e33", "focusColor": "#2b2e33" } + }, + "submenu": { "indent": 24 }, + "separator": { "borderColor": "#e2e2e4" }, + "submenuIcon": { "color": "#2b2e33", "focusColor": "#2b2e33" } + }, + "password": { + "extend": { "borderWidth": 1 }, + "colorScheme": { + "strength": { + "weakBackground": "#e85244", + "mediumBackground": "#f5b83d", + "strongBackground": "#1dc831" + }, + "icon": { "color": "#85888e" } + }, + "meter": { "background": "#e2e2e4", "borderRadius": 14, "height": 8 }, + "overlay": { + "background": "#ffffff", + "borderColor": "#cecfd2", + "borderRadius": 8, + "color": "#2b2e33", + "padding": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "content": { "gap": 8 }, + "icon": { "color": "#2b2e33" } + }, + "popover": { + "extend": { "borderWidth": 1, "arrow": { "width": 12, "height": 8 } }, + "root": { + "background": "#ffffff", + "borderColor": "#cecfd2", + "color": "#2b2e33", + "borderRadius": 8, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "gutter": 4, + "arrowOffset": 20 + }, + "content": { "padding": 14 } + }, + "progressbar": { + "label": { "color": "#2b2e33", "fontSize": 12, "fontWeight": "400" }, + "root": { "background": "#e2e2e4", "borderRadius": 14, "height": 16 }, + "value": { "background": "#44e858" } + }, + "progressspinner": { + "extend": { "small": 16, "medium": 32, "large": 48, "xlarge": 56 }, + "colorScheme": { + "root": { + "colorOne": "#44e858", + "colorTwo": "#4496e8", + "colorThree": "#e85244", + "colorFour": "#f5b83d" + } + }, + "root": { "borderWidth": 4 } + }, + "radiobutton": { + "root": { + "width": 24, + "height": 24, + "background": "#ffffff", + "checkedBackground": "#2b2e33", + "checkedHoverBackground": "#404348", + "disabledBackground": "#e2e2e4", + "filledBackground": "#ffffff", + "borderColor": "#cecfd2", + "hoverBorderColor": "#2b2e33", + "focusBorderColor": "#cecfd2", + "checkedBorderColor": "#2b2e33", + "checkedHoverBorderColor": "#2b2e33", + "checkedFocusBorderColor": "#2b2e33", + "checkedDisabledBorderColor": "#cecfd2", + "invalidBorderColor": "#f47f77", + "shadow": "none", + "transitionDuration": 180, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + }, + "lg": { "height": 20, "width": 20 }, + "sm": { "height": 8, "width": 8 } + }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "sm": { "width": 16, "height": 16 }, + "lg": { "width": 20, "height": 20 }, + "icon": { + "size": 12, + "checkedColor": "#ffffff", + "checkedHoverColor": "#ffffff", + "disabledColor": "#85888e", + "sm": { "size": 8 }, + "lg": { "size": 16 } + } + }, + "rating": { + "root": { + "gap": 8, + "transitionDuration": 180, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + } + }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "icon": { + "size": 24, + "color": "#85888e", + "hoverColor": "#f5b83d", + "activeColor": "#f5b83d" + } + }, + "ripple": { "colorScheme": { "root": { "background": "#e2e2e4" } } }, + "scrollpanel": { + "colorScheme": { "bar": { "background": "#cecfd2" } }, + "root": { "transitionDuration": 180 }, + "bar": { + "size": 8, + "borderRadius": 8, + "focusRing": { + "width": 0, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "select": { + "extend": { + "extOption": { "background": "#ffffff", "gap": 8 }, + "extOptionGroup": { "gap": 8 }, + "readonlyBackground": "#f0f0f1", + "borderWidth": 1, + "iconSize": 16 + }, + "root": { + "background": "#ffffff", + "disabledBackground": "#e2e2e4", + "filledBackground": "#ffffff", + "filledHoverBackground": "#ffffff", + "filledFocusBackground": "#ffffff", + "borderColor": "#cecfd2", + "hoverBorderColor": "#1dc831", + "focusBorderColor": "#1dc831", + "invalidBorderColor": "#f47f77", + "color": "#2b2e33", + "disabledColor": "#85888e", + "placeholderColor": "#85888e", + "invalidPlaceholderColor": "#db3424", + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "sm": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + } + }, + "dropdown": { "width": 272, "color": "#181a1f" }, + "overlay": { + "background": "#ffffff", + "borderColor": "#e2e2e4", + "borderRadius": 14, + "color": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" + }, + "list": { + "padding": 4, + "gap": 4, + "header": { + "paddingTop": 14, + "paddingRight": 14, + "paddingBottom": 0, + "paddingLeft": 14 + } + }, + "option": { + "focusBackground": "#f0f0f1", + "selectedBackground": "#2b2e33", + "selectedFocusBackground": "#56595f", + "color": "#2b2e33", + "focusColor": "#2b2e33", + "selectedColor": "#ffffff", + "selectedFocusColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8 + }, + "optionGroup": { + "background": "#ffffff", + "color": "#85888e", + "fontWeight": "600", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + }, + "clearIcon": { "color": "#181a1f" }, + "checkmark": { "color": "#2b2e33", "gutterStart": -8, "gutterEnd": 8 }, + "emptyMessage": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14 + } + }, + "selectbutton": { + "extend": { + "gap": 4, + "paddingX": 4, + "paddingY": 4, + "iconSize": { "sm": 16, "md": 20, "lg": 24, "xlg": 28 }, + "checkedBackground": "#ffffff", + "checkedBorderColor": "#ffffff", + "checkedColor": "#181a1f", + "ext": { "borderRadius": 8 } + }, + "colorScheme": { + "root": { "invalidBorderColor": "#f47f77" }, + "extend": { "background": "#e2e2e4" } + }, + "root": { "borderRadius": 14 } + }, + "skeleton": { + "extend": { "minWidth": 32, "height": 32 }, + "colorScheme": { + "root": { "background": "#e2e2e4", "animationBackground": "#f0f0f1" } + }, + "root": { "borderRadius": 14 } + }, + "slider": { + "colorScheme": { "handle": { "content": { "background": "#ffffff" } } }, + "root": { "transitionDuration": 180 }, + "track": { "background": "#e2e2e4", "borderRadius": 14, "size": 4 }, + "range": { "background": "#2b2e33" }, + "handle": { + "width": 20, + "height": 20, + "borderRadius": 1600, + "background": "#2b2e33", + "hoverBackground": "#2b2e33", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "content": { + "borderRadius": 1600, + "hoverBackground": "#2b2e33", + "width": 12, + "height": 12, + "shadow": "none" + } + } + }, + "splitter": { + "colorScheme": { "handle": { "background": "#2b2e33" } }, + "gutter": { "background": "#f0f0f1" }, + "root": { + "background": "#ffffff", + "borderColor": "#e2e2e4", + "color": "#2b2e33", + "transitionDuration": 180 + }, + "handle": { + "size": 4, + "borderRadius": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "stepper": { + "extend": { + "extCaption": { "gap": 4 }, + "extStepNumber": { + "invalidBackground": "#f47f77", + "invalidColor": "#45120e", + "invalidBorderColor": "#f47f77", + "borderWidth": 1, + "iconSize": 24 + } + }, + "root": { "transitionDuration": 180 }, + "separator": { + "background": "#e2e2e4", + "activeBackground": "#2b2e33", + "marginTop": 0, + "marginRight": 0, + "marginBottom": 0, + "marginLeft": 24, + "size": 1 + }, + "step": { "padding": 8, "gap": 8 }, + "stepHeader": { + "padding": 0, + "borderRadius": 0, + "gap": 8, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "stepTitle": { + "color": "#2b2e33", + "activeColor": "#2b2e33", + "fontWeight": "400" + }, + "stepNumber": { + "background": "#ffffff", + "activeBackground": "#44e858", + "borderColor": "#e2e2e4", + "activeBorderColor": "#44e858", + "color": "#2b2e33", + "activeColor": "#2b2e33", + "size": 24, + "fontSize": 16, + "fontWeight": "700", + "borderRadius": 1600, + "shadow": "none" + }, + "steppanels": { "padding": 14 }, + "steppanel": { + "background": "#ffffff", + "color": "#2b2e33", + "padding": 0, + "indent": 0 + } + }, + "steps": { + "itemLink": { + "gap": 8, + "borderRadius": 14, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + } + }, + "itemLabel": { + "fontWeight": "400", + "activeColor": "#56595f", + "color": "#2b2e33" + }, + "itemNumber": { + "background": "#ffffff", + "size": 32, + "fontSize": 16, + "fontWeight": "700", + "borderRadius": 1600, + "shadow": "none", + "activeBackground": "#ffffff", + "activeBorderColor": "#e2e2e4", + "activeColor": "#56595f", + "borderColor": "#e2e2e4", + "color": "#2b2e33" + }, + "root": { "transitionDuration": 180 }, + "separator": { "background": "#e2e2e4" } + }, + "tabs": { + "colorScheme": { + "navButton": { "shadow": "none" }, + "tab": { + "background": "transparent", + "hoverBackground": "transparent", + "activeBackground": "transparent" + } + }, + "root": { "transitionDuration": 180 }, + "tablist": { + "borderTopWidth": 0, + "borderRightWidth": 0, + "borderBottomWidth": 1, + "borderLeftWidth": 0, + "background": "transparent", + "borderColor": "#e2e2e4" + }, + "tab": { + "borderWidth": 0, + "borderColor": "#e2e2e4", + "hoverBorderColor": "#e2e2e4", + "activeBorderColor": "#404348", + "color": "#85888e", + "hoverColor": "#2b2e33", + "activeColor": "#2b2e33", + "padding": 14, + "fontWeight": "600", + "margin": 0, + "gap": 8, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "tabpanel": { + "background": "transparent", + "color": "#2b2e33", + "padding": 14, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "navButton": { + "background": "#ffffff", + "color": "#2b2e33", + "hoverColor": "#56595f", + "width": 24, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + }, + "activeBar": { "height": 2, "bottom": -2, "background": "#2b2e33" } + }, + "toast": { + "extend": { + "extInfo": { + "color": "#4496e8", + "closeButton": { "color": "#4496e8", "borderColor": "#4496e8" }, + "caption": { "color": "#2b2e33" } + }, + "extAccentLine": { "width": 4 }, + "extCloseButton": { "width": 1 }, + "extSuccess": { + "color": "#44e858", + "closeButton": { "color": "#44e858", "borderColor": "#44e858" }, + "caption": { "color": "#2b2e33" } + }, + "extWarn": { + "color": "#f5b83d", + "closeButton": { "color": "#f5b83d", "borderColor": "#f5b83d" }, + "caption": { "color": "#2b2e33" } + }, + "extError": { + "color": "#e85244", + "closeButton": { "color": "#e85244", "borderColor": "#e85244" }, + "caption": { "color": "#2b2e33" } + } + }, + "colorScheme": { + "info": { + "background": "#fafdff", + "borderColor": "#4496e8", + "color": "#2b2e33", + "detailColor": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "closeButton": { + "hoverBackground": "#d4ecfe", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "success": { + "background": "#fafffb", + "borderColor": "#44e858", + "color": "#2b2e33", + "detailColor": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "closeButton": { + "hoverBackground": "#d4fedc", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "warn": { + "background": "#fffdfa", + "borderColor": "#f5b83d", + "color": "#2b2e33", + "detailColor": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "closeButton": { + "hoverBackground": "#ffeed4", + "focusRing": { "color": "#d4fedc", "shadow": "none" } + } + }, + "error": { + "background": "#fffafa", + "borderColor": "#e85244", + "color": "#2b2e33", + "detailColor": "#2b2e33", + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "closeButton": { + "hoverBackground": "#fed4d4", + "focusRing": { + "color": "#d4fedc", + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + } + } + }, + "secondary": { + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "background": "#f0f0f1", + "borderColor": "#cecfd2", + "closeButton": { + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#f0f0f1" + }, + "color": "#2b2e33", + "detailColor": "#6d7076" + }, + "contrast": { + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "background": "#2b2e33", + "borderColor": "#2b2e33", + "closeButton": { + "focusRing": { "color": "#d4fedc", "shadow": "none" }, + "hoverBackground": "#404348" + }, + "color": "#ffffff", + "detailColor": "#e2e2e4" + }, + "root": { "blur": 0 } + }, + "root": { + "width": 400, + "borderWidth": 1, + "borderRadius": 14, + "transitionDuration": 180 + }, + "icon": { "size": 36 }, + "content": { "padding": 14, "gap": 14 }, + "text": { "gap": 4 }, + "summary": { "fontWeight": "700", "fontSize": 16 }, + "detail": { "fontWeight": "400", "fontSize": 14 }, + "closeButton": { + "width": 32, + "height": 32, + "borderRadius": 14, + "focusRing": { "width": 4, "style": "none", "offset": 0 } + }, + "closeIcon": { "size": 16 } + }, + "tag": { + "colorScheme": { + "primary": { "background": "#44e858", "color": "#2b2e33" }, + "secondary": { "background": "#e2e2e4", "color": "#2b2e33" }, + "success": { "background": "#77f48a", "color": "#0e4514" }, + "info": { "background": "#aad7fb", "color": "#0e2a45" }, + "warn": { "background": "#fddeaa", "color": "#4f3709" }, + "danger": { "background": "#fbacaa", "color": "#45120e" }, + "contrast": { "background": "#2b2e33", "color": "#ffffff" } + }, + "root": { + "fontSize": 12, + "fontWeight": "400", + "paddingTop": 4, + "paddingRight": 8, + "paddingBottom": 4, + "paddingLeft": 8, + "gap": 4, + "borderRadius": 8, + "roundedBorderRadius": 1600 + }, + "icon": { "size": 16 } + }, + "textarea": { + "extend": { + "readonlyBackground": "#f0f0f1", + "borderWidth": 1, + "iconSize": 16, + "minHeight": 80 + }, + "root": { + "background": "#ffffff", + "disabledBackground": "#e2e2e4", + "filledBackground": "#ffffff", + "filledHoverBackground": "#ffffff", + "filledFocusBackground": "#ffffff", + "borderColor": "#cecfd2", + "hoverBorderColor": "#1dc831", + "focusBorderColor": "#1dc831", + "invalidBorderColor": "#f47f77", + "color": "#181a1f", + "disabledColor": "#85888e", + "placeholderColor": "#85888e", + "invalidPlaceholderColor": "#db3424", + "shadow": "none", + "paddingX": 14, + "paddingY": 14, + "borderRadius": 14, + "transitionDuration": 180, + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 }, + "sm": { "fontSize": 16, "paddingX": 14, "paddingY": 14 } + }, + "sm": { "fontSize": 16, "paddingX": 8, "paddingY": 8 }, + "lg": { "fontSize": 16, "paddingX": 14, "paddingY": 14 } + }, + "tieredmenu": { + "extend": { + "iconSize": 20, + "extSubmenu": { "borderColor": "#e2e2e4", "background": "#ffffff" }, + "extItem": { "caption": { "gap": 4, "color": "#85888e" } } + }, + "root": { + "background": "#ffffff", + "borderColor": "transparent", + "color": "#2b2e33", + "borderRadius": 14, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "transitionDuration": 180 + }, + "list": { "padding": 4, "gap": 4 }, + "item": { + "focusBackground": "#f0f0f1", + "activeBackground": "#2b2e33", + "color": "#2b2e33", + "focusColor": "#2b2e33", + "activeColor": "#ffffff", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8, + "gap": 8, + "icon": { + "color": "#2b2e33", + "focusColor": "#2b2e33", + "activeColor": "#ffffff" + } + }, + "submenu": { "mobileIndent": 14 }, + "separator": { "borderColor": "#e2e2e4" }, + "submenuIcon": { + "activeColor": "#56595f", + "color": "#2b2e33", + "focusColor": "#56595f", + "size": 14 + } + }, + "timeline": { + "extend": { "extEvent": { "gap": 4 } }, + "event": { "minHeight": 64 }, + "vertical": { + "eventContent": { + "paddingTop": 0, + "paddingRight": 20, + "paddingBottom": 0, + "paddingLeft": 20 + } + }, + "horizontal": { + "eventContent": { + "paddingTop": 20, + "paddingRight": 0, + "paddingBottom": 20, + "paddingLeft": 0 + } + }, + "eventMarker": { + "size": 16, + "borderRadius": 14, + "borderWidth": 4, + "background": "#ffffff", + "borderColor": "#44e858", + "content": { + "borderRadius": 14, + "size": 12, + "background": "transparent", + "insetShadow": "none" + } + }, + "eventConnector": { "color": "#e2e2e4", "size": 1 } + }, + "togglebutton": { + "extend": { + "ext": { "gap": 14 }, + "iconSize": { "sm": 16, "md": 20, "lg": 24 }, + "iconOnlyWidth": 40, + "hoverBorderColor": "#cecfd2", + "checkedHoverColor": "#ffffff", + "checkedHoverBackground": "#404348", + "checkedHoverBorderColor": "#404348", + "extXlg": { + "paddingTop": 20, + "paddingRight": 20, + "paddingBottom": 20, + "paddingLeft": 20, + "iconOnlyWidth": 64 + }, + "extSm": { "iconOnlyWidth": 32 }, + "extLg": { "iconOnlyWidth": 56 } + }, + "colorScheme": { + "root": { + "background": "#e2e2e4", + "hoverBackground": "#cecfd2", + "borderColor": "#e2e2e4", + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "checkedBackground": "#2b2e33", + "checkedColor": "#ffffff", + "checkedBorderColor": "#2b2e33", + "disabledBackground": "#e2e2e4", + "disabledBorderColor": "#e2e2e4", + "disabledColor": "#85888e", + "invalidBorderColor": "#f47f77" + }, + "icon": { + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "checkedColor": "#ffffff", + "disabledColor": "#85888e" + }, + "content": { "checkedBackground": "transparent" } + }, + "root": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 1600, + "gap": 8, + "fontWeight": "600", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "0 0 4px rgba(0, 0, 0, 0.2000)" + }, + "sm": { + "fontSize": 14, + "paddingTop": 4, + "paddingRight": 14, + "paddingBottom": 4, + "paddingLeft": 14 + }, + "lg": { + "fontSize": 20, + "paddingTop": 14, + "paddingRight": 24, + "paddingBottom": 14, + "paddingLeft": 24 + }, + "transitionDuration": 180, + "background": "#ffffff", + "borderColor": "#e2e2e4", + "checkedBackground": "#ffffff", + "checkedBorderColor": "#e2e2e4", + "checkedColor": "#2b2e33", + "color": "#2b2e33", + "disabledBackground": "#e2e2e4", + "disabledBorderColor": "#e2e2e4", + "disabledColor": "#85888e", + "hoverColor": "#56595f", + "invalidBorderColor": "#f47f77" + }, + "content": { + "checkedShadow": "none", + "padding": 0, + "borderRadius": 0, + "sm": { "padding": 0 }, + "lg": { "padding": 0 }, + "checkedBackground": "#ffffff" + }, + "icon": { + "checkedColor": "#2b2e33", + "color": "#2b2e33", + "disabledColor": "#85888e", + "hoverColor": "#56595f" + } + }, + "toggleswitch": { + "colorScheme": { + "root": { + "background": "#a2a5a9", + "hoverBackground": "#85888e", + "disabledBackground": "#e2e2e4", + "checkedBackground": "#2b2e33", + "checkedHoverBackground": "#404348" + }, + "handle": { + "background": "#ffffff", + "hoverBackground": "#ffffff", + "disabledBackground": "#85888e", + "checkedBackground": "#ffffff", + "checkedHoverBackground": "#ffffff", + "color": "#2b2e33", + "hoverColor": "#2b2e33", + "checkedColor": "#2b2e33", + "checkedHoverColor": "#2b2e33" + } + }, + "root": { + "width": 40, + "height": 24, + "borderRadius": 1600, + "gap": 4, + "borderWidth": 1, + "shadow": "none", + "focusRing": { + "width": 4, + "style": "none", + "color": "#d4fedc", + "offset": 0, + "shadow": "none" + }, + "borderColor": "transparent", + "hoverBorderColor": "transparent", + "checkedBorderColor": "transparent", + "checkedHoverBorderColor": "transparent", + "invalidBorderColor": "#f47f77", + "transitionDuration": 180, + "slideDuration": 180 + }, + "handle": { "borderRadius": 1600, "size": 16 } + }, + "tooltip": { + "colorScheme": { "root": { "background": "#2b2e33", "color": "#ffffff" } }, + "root": { + "maxWidth": 400, + "gutter": 4, + "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "borderRadius": 8 + } + }, + "tree": { + "root": { + "background": "#ffffff", + "color": "#2b2e33", + "padding": 14, + "gap": 4, + "indent": 14, + "transitionDuration": 180 + }, + "node": { + "paddingTop": 8, + "paddingRight": 14, + "paddingBottom": 8, + "paddingLeft": 14, + "color": "#2b2e33", + "selectedColor": "#ffffff", + "gap": 4, + "borderRadius": 14, + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + }, + "hoverBackground": "#f0f0f1", + "hoverColor": "#2b2e33", + "selectedBackground": "#2b2e33" + }, + "nodeIcon": { + "selectedColor": "#ffffff", + "color": "#2b2e33", + "hoverColor": "#56595f" + }, + "nodeToggleButton": { + "borderRadius": 4, + "size": 28, + "selectedHoverBackground": "#2b2e33", + "color": "#2b2e33", + "focusRing": { + "color": "#d4fedc", + "offset": 0, + "shadow": "none", + "style": "none", + "width": 4 + }, + "hoverBackground": "#f0f0f1", + "hoverColor": "#56595f", + "selectedHoverColor": "#56595f" + }, + "loadingIcon": { "size": 16 }, + "filter": { + "marginTop": 0, + "marginRight": 0, + "marginBottom": 8, + "marginLeft": 0 + } + }, + "overlaybadge": { + "root": { "outline": { "width": 0, "color": "transparent" } } + } +} diff --git a/src/theme/tokens/semantic/dark.json b/src/theme/tokens/semantic/dark.json new file mode 100644 index 00000000..1a25ff23 --- /dev/null +++ b/src/theme/tokens/semantic/dark.json @@ -0,0 +1,352 @@ +{ + "colorScheme": { + "color": { + "fg": { + "default": "#ffffff", + "hover": "#cecfd2", + "active": "#f0f0f1", + "focus": "#ffffff", + "muted": "#a2a5a9", + "subtle": "#a2a5a9", + "brand": { + "default": "#77f48a", + "hover": "#aafbb7", + "active": "#d4fedc", + "disabled": "#168322", + "visited": "#aafbb7", + "muted": "#44e858" + }, + "inverse": { + "default": "#2b2e33", + "hover": "#56595f", + "active": "#181a1f", + "focus": "#2b2e33", + "muted": "#85888e" + }, + "status": { + "danger": { + "default": "#f47f77", + "hover": "#fbacaa", + "active": "#fed4d4", + "disabled": "#8d2218", + "visited": "#fbacaa", + "muted": "#e85244" + }, + "info": { + "default": "#77baf4", + "hover": "#aad7fb", + "active": "#d4ecfe", + "disabled": "#18538d", + "visited": "#aad7fb", + "muted": "#4496e8" + }, + "warning": { + "default": "#facb75", + "hover": "#fddeaa", + "active": "#ffeed4", + "disabled": "#9d6d0e", + "visited": "#fddeaa", + "muted": "#f5b83d" + }, + "success": { + "default": "#77f48a", + "hover": "#aafbb7", + "active": "#d4fedc", + "disabled": "#168322", + "visited": "#aafbb7", + "muted": "#44e858" + }, + "help": { + "default": "#c084fc", + "hover": "#d8b4fe", + "active": "#e9d5ff", + "disabled": "#7e22ce", + "visited": "#d8b4fe", + "muted": "#a855f7" + } + }, + "on": { + "brand": { + "default": "#2b2e33", + "hover": "#2b2e33", + "active": "#2b2e33" + }, + "fill": { + "default": "#ffffff", + "hover": "#ffffff", + "active": "#ffffff", + "muted": "#e2e2e4" + }, + "status": { + "danger": { "default": "#fff0f0", "hover": "#fffafa" }, + "info": { "default": "#f0f9ff", "hover": "#fafdff" }, + "warning": { "default": "#fff9f0", "hover": "#fffdfa" }, + "success": { "default": "#f0fff3", "hover": "#fafffb" }, + "help": { "default": "#f3e8ff", "hover": "#faf5ff" } + } + } + }, + "bg": { + "status": { + "danger": { + "weak": { + "default": "#3b100c", + "hover": "#45120e", + "active": "#611912" + }, + "strong": { + "default": "#8d2218", + "hover": "#db3424", + "active": "#e85244" + } + }, + "info": { + "weak": { + "default": "#0c243b", + "hover": "#0e2a45", + "active": "#123a61" + }, + "strong": { + "default": "#18538d", + "hover": "#1e76cd", + "active": "#4496e8" + } + }, + "warning": { + "weak": { + "default": "#453008", + "hover": "#4f3709", + "active": "#6d4c0b" + }, + "strong": { + "default": "#9d6d0e", + "hover": "#dc9710", + "active": "#f5b83d" + } + }, + "success": { + "weak": { + "default": "#0c3b11", + "hover": "#0e4514", + "active": "#12611b" + }, + "strong": { + "default": "#168322", + "hover": "#1dc831", + "active": "#44e858" + } + }, + "help": { + "weak": { + "default": "#3b0764", + "hover": "#581c87", + "active": "#6b21a8" + }, + "strong": { + "default": "#7e22ce", + "hover": "#9333ea", + "active": "#a855f7" + } + } + }, + "brand": { + "weak": { "hover": "#0c3b11", "active": "#0e4514" }, + "strong": { + "default": "#44e858", + "hover": "#77f48a", + "active": "#aafbb7" + } + }, + "surface": { + "canvas": { + "default": "#2b2e33", + "hover": "#404348", + "active": "#56595f", + "selected": "#404348" + }, + "default": { + "default": "#404348", + "hover": "#56595f", + "active": "#6d7076", + "selected": "#56595f" + }, + "raised": { + "default": "#56595f", + "hover": "#6d7076", + "active": "#85888e", + "selected": "#6d7076" + }, + "overlay": { "default": "#404348", "hover": "#56595f" }, + "backdrop": "rgba(0, 0, 0, 0.6000)" + }, + "neutral": { + "weak": { + "default": "#2b2e33", + "hover": "#404348", + "active": "#56595f", + "disabled": "#404348" + }, + "medium": { + "default": "#404348", + "hover": "#56595f", + "active": "#6d7076", + "strong": "#85888e" + }, + "strong": { + "default": "#f0f0f1", + "hover": "#e2e2e4", + "active": "#cecfd2", + "selected": "#f0f0f1" + } + } + }, + "border": { + "focus": "#d4fedc", + "neutral": { + "default": "#404348", + "strong": "#56595f", + "bold": { "default": "#f0f0f1", "hover": "#e2e2e4" }, + "inverse": "#2b2e33" + }, + "brand": { + "subtle": "#12611b", + "default": "#44e858", + "strong": "#77f48a" + }, + "status": { + "danger": { + "subtle": "#db3424", + "default": "#e85244", + "strong": "#f47f77" + }, + "info": { "default": "#4496e8", "strong": "#77baf4" }, + "warning": { "default": "#f5b83d", "strong": "#facb75" }, + "success": { "default": "#44e858", "strong": "#77f48a" }, + "help": { "strong": "#c084fc" } + } + } + } + }, + "dimension": { + "space": { + "100": 4, + "150": 6, + "200": 8, + "300": 10, + "400": 14, + "500": 18, + "600": 20, + "700": 24, + "800": 28, + "none": 0, + "negative": { "50": -2, "200": -8, "300": -12, "600": -24 } + }, + "size": { + "50": 2, + "100": 4, + "150": 6, + "200": 8, + "300": 10, + "350": 12, + "400": 14, + "450": 16, + "500": 18, + "600": 20, + "700": 24, + "750": 26, + "800": 28, + "900": 32, + "1000": 36, + "1100": 40, + "1200": 48, + "1300": 56, + "1400": 64, + "1500": 80, + "1600": 240, + "1700": 272, + "1800": 304, + "1900": 336, + "2000": 400, + "none": 0, + "max": 1600 + }, + "borderRadius": { + "100": 4, + "200": 8, + "300": 10, + "400": 14, + "500": 20, + "none": 0, + "max": 1600 + }, + "borderWidth": { "100": 1, "200": 2, "300": 4, "none": 0 }, + "focusRing": { "width": 4, "offset": 0 }, + "depth": { + "100": "1000", + "200": "1100", + "300": "1200", + "400": "1300", + "500": "1400", + "600": "1500", + "700": "1600" + }, + "viewport": { "100": 576, "200": 768, "300": 992, "400": 1200, "500": 1400 } + }, + "effects": { + "opacity": { + "0": 0, + "4": "0.04", + "8": "0.08", + "12": "0.12", + "16": "0.16", + "20": "0.2", + "30": "0.3", + "40": "0.4", + "50": "0.5", + "60": "0.6", + "70": "0.7", + "80": "0.8", + "90": "0.9", + "100": "1" + }, + "blur": { + "100": "4px", + "200": "8px", + "300": "16px", + "400": "24px", + "none": 0 + }, + "transition": { + "easing": { + "linear": "linear", + "in": "cubic-bezier(0.55, 0.06, 0.7, 0.2)", + "out": "cubic-bezier(0.2, 0.6, 0.4, 1)", + "inOut": "cubic-bezier(0.65, 0.05, 0.35, 1)", + "standard": "cubic-bezier(0.2, 0, 0, 1)", + "accelerate": "cubic-bezier(0.3, 0, 1, 1)", + "decelerate": "cubic-bezier(0, 0, 0, 1)", + "emphasizedAccelerate": "cubic-bezier(0.3, 0, 0.8, 0.15)", + "emphasizedDecelerate": "cubic-bezier(0.05, 0.7, 0.1, 1)", + "spring": "cubic-bezier(0.34, 1.56, 0.64, 1)" + }, + "duration": { "100": 140, "200": 180, "300": 240, "400": 320, "500": 400 } + }, + "elevation": { + "100": "0 0 2px rgba(0, 0, 0, 0.2000)", + "200": "0 0 4px rgba(0, 0, 0, 0.2000)", + "300": "0 2px 4px rgba(0, 0, 0, 0.2000)", + "400": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "500": "0 8px 16px 0 rgba(0, 0, 0, 0.2000)", + "none": "none", + "status": { + "info": "0px 4px 8px 0px rgba(68, 150, 232, 0.04)", + "success": "0px 4px 8px 0px rgba(68, 232, 88, 0.04)", + "warning": "0px 4px 8px 0px rgba(245, 184, 61, 0.04)", + "danger": "0px 4px 8px 0px rgba(232, 82, 68, 0.04)", + "secondary": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)", + "contrast": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)" + } + }, + "focusRing": { "shadow": "inset 0 0 0 4px #d4fedc" } + } +} diff --git a/src/theme/tokens/semantic/light.json b/src/theme/tokens/semantic/light.json new file mode 100644 index 00000000..687f1010 --- /dev/null +++ b/src/theme/tokens/semantic/light.json @@ -0,0 +1,352 @@ +{ + "colorScheme": { + "color": { + "fg": { + "default": "#2b2e33", + "hover": "#56595f", + "active": "#181a1f", + "focus": "#2b2e33", + "muted": "#85888e", + "subtle": "#6d7076", + "brand": { + "default": "#44e858", + "hover": "#1dc831", + "active": "#168322", + "disabled": "#aafbb7", + "visited": "#12611b", + "muted": "#77f48a" + }, + "inverse": { + "default": "#ffffff", + "hover": "#ffffff", + "active": "#ffffff", + "focus": "#ffffff", + "muted": "rgba(255, 255, 255, 0.7000)" + }, + "status": { + "danger": { + "default": "#e85244", + "hover": "#db3424", + "active": "#8d2218", + "disabled": "#fbacaa", + "visited": "#611912", + "muted": "#f47f77" + }, + "info": { + "default": "#4496e8", + "hover": "#1e76cd", + "active": "#18538d", + "disabled": "#aad7fb", + "visited": "#123a61", + "muted": "#77baf4" + }, + "warning": { + "default": "#f5b83d", + "hover": "#dc9710", + "active": "#9d6d0e", + "disabled": "#fddeaa", + "visited": "#6d4c0b", + "muted": "#facb75" + }, + "success": { + "default": "#44e858", + "hover": "#1dc831", + "active": "#168322", + "disabled": "#aafbb7", + "visited": "#12611b", + "muted": "#77f48a" + }, + "help": { + "default": "#a855f7", + "hover": "#9333ea", + "active": "#7e22ce", + "disabled": "#d8b4fe", + "visited": "#6b21a8", + "muted": "#c084fc" + } + }, + "on": { + "brand": { + "default": "#2b2e33", + "hover": "#2b2e33", + "active": "#2b2e33" + }, + "fill": { + "default": "#ffffff", + "hover": "#ffffff", + "active": "#ffffff", + "muted": "#e2e2e4" + }, + "status": { + "danger": { "default": "#45120e", "hover": "#3b100c" }, + "info": { "default": "#0e2a45", "hover": "#0c243b" }, + "warning": { "default": "#4f3709", "hover": "#453008" }, + "success": { "default": "#0e4514", "hover": "#0c3b11" }, + "help": { "default": "#581c87", "hover": "#3b0764" } + } + } + }, + "bg": { + "status": { + "danger": { + "weak": { + "default": "#fffafa", + "hover": "#fff0f0", + "active": "#fed4d4" + }, + "strong": { + "default": "#fbacaa", + "hover": "#f47f77", + "active": "#e85244" + } + }, + "info": { + "weak": { + "default": "#fafdff", + "hover": "#f0f9ff", + "active": "#d4ecfe" + }, + "strong": { + "default": "#aad7fb", + "hover": "#77baf4", + "active": "#4496e8" + } + }, + "warning": { + "weak": { + "default": "#fffdfa", + "hover": "#fff9f0", + "active": "#ffeed4" + }, + "strong": { + "default": "#fddeaa", + "hover": "#facb75", + "active": "#f5b83d" + } + }, + "success": { + "weak": { + "default": "#fafffb", + "hover": "#f0fff3", + "active": "#d4fedc" + }, + "strong": { + "default": "#aafbb7", + "hover": "#77f48a", + "active": "#44e858" + } + }, + "help": { + "weak": { + "default": "#faf5ff", + "hover": "#f3e8ff", + "active": "#e9d5ff" + }, + "strong": { + "default": "#d8b4fe", + "hover": "#c084fc", + "active": "#a855f7" + } + } + }, + "brand": { + "weak": { "hover": "#fafffb", "active": "#f0fff3" }, + "strong": { + "default": "#44e858", + "hover": "#1dc831", + "active": "#168322" + } + }, + "surface": { + "canvas": { + "default": "#f0f0f1", + "hover": "#e2e2e4", + "active": "#cecfd2", + "selected": "#e2e2e4" + }, + "default": { + "default": "#ffffff", + "hover": "#fafafa", + "active": "#f0f0f1", + "selected": "#fafafa" + }, + "raised": { + "default": "#ffffff", + "hover": "#fafafa", + "active": "#f0f0f1", + "selected": "#fafafa" + }, + "overlay": { "default": "#ffffff", "hover": "#fafafa" }, + "backdrop": "rgba(0, 0, 0, 0.4000)" + }, + "neutral": { + "weak": { + "default": "#f0f0f1", + "hover": "#e2e2e4", + "active": "#cecfd2", + "disabled": "#e2e2e4" + }, + "medium": { + "default": "#e2e2e4", + "hover": "#cecfd2", + "active": "#a2a5a9", + "strong": "#85888e" + }, + "strong": { + "default": "#2b2e33", + "hover": "#404348", + "active": "#56595f", + "selected": "#2b2e33" + } + } + }, + "border": { + "focus": "#d4fedc", + "neutral": { + "default": "#e2e2e4", + "strong": "#cecfd2", + "bold": { "default": "#2b2e33", "hover": "#404348" }, + "inverse": "#ffffff" + }, + "brand": { + "subtle": "#d4fedc", + "default": "#44e858", + "strong": "#1dc831" + }, + "status": { + "danger": { + "subtle": "#f47f77", + "default": "#e85244", + "strong": "#db3424" + }, + "info": { "default": "#4496e8", "strong": "#1e76cd" }, + "warning": { "default": "#f5b83d", "strong": "#dc9710" }, + "success": { "default": "#44e858", "strong": "#1dc831" }, + "help": { "strong": "#9333ea" } + } + } + } + }, + "dimension": { + "space": { + "100": 4, + "150": 6, + "200": 8, + "300": 10, + "400": 14, + "500": 18, + "600": 20, + "700": 24, + "800": 28, + "none": 0, + "negative": { "50": -2, "200": -8, "300": -12, "600": -24 } + }, + "size": { + "50": 2, + "100": 4, + "150": 6, + "200": 8, + "300": 10, + "350": 12, + "400": 14, + "450": 16, + "500": 18, + "600": 20, + "700": 24, + "750": 26, + "800": 28, + "900": 32, + "1000": 36, + "1100": 40, + "1200": 48, + "1300": 56, + "1400": 64, + "1500": 80, + "1600": 240, + "1700": 272, + "1800": 304, + "1900": 336, + "2000": 400, + "none": 0, + "max": 1600 + }, + "borderRadius": { + "100": 4, + "200": 8, + "300": 10, + "400": 14, + "500": 20, + "none": 0, + "max": 1600 + }, + "borderWidth": { "100": 1, "200": 2, "300": 4, "none": 0 }, + "focusRing": { "width": 4, "offset": 0 }, + "depth": { + "100": "1000", + "200": "1100", + "300": "1200", + "400": "1300", + "500": "1400", + "600": "1500", + "700": "1600" + }, + "viewport": { "100": 576, "200": 768, "300": 992, "400": 1200, "500": 1400 } + }, + "effects": { + "opacity": { + "0": 0, + "4": "0.04", + "8": "0.08", + "12": "0.12", + "16": "0.16", + "20": "0.2", + "30": "0.3", + "40": "0.4", + "50": "0.5", + "60": "0.6", + "70": "0.7", + "80": "0.8", + "90": "0.9", + "100": "1" + }, + "blur": { + "100": "4px", + "200": "8px", + "300": "16px", + "400": "24px", + "none": 0 + }, + "transition": { + "easing": { + "linear": "linear", + "in": "cubic-bezier(0.55, 0.06, 0.7, 0.2)", + "out": "cubic-bezier(0.2, 0.6, 0.4, 1)", + "inOut": "cubic-bezier(0.65, 0.05, 0.35, 1)", + "standard": "cubic-bezier(0.2, 0, 0, 1)", + "accelerate": "cubic-bezier(0.3, 0, 1, 1)", + "decelerate": "cubic-bezier(0, 0, 0, 1)", + "emphasizedAccelerate": "cubic-bezier(0.3, 0, 0.8, 0.15)", + "emphasizedDecelerate": "cubic-bezier(0.05, 0.7, 0.1, 1)", + "spring": "cubic-bezier(0.34, 1.56, 0.64, 1)" + }, + "duration": { "100": 140, "200": 180, "300": 240, "400": 320, "500": 400 } + }, + "elevation": { + "100": "0 0 2px rgba(0, 0, 0, 0.2000)", + "200": "0 0 4px rgba(0, 0, 0, 0.2000)", + "300": "0 2px 4px rgba(0, 0, 0, 0.2000)", + "400": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "500": "0 8px 16px 0 rgba(0, 0, 0, 0.2000)", + "none": "none", + "status": { + "info": "0px 4px 8px 0px rgba(68, 150, 232, 0.04)", + "success": "0px 4px 8px 0px rgba(68, 232, 88, 0.04)", + "warning": "0px 4px 8px 0px rgba(245, 184, 61, 0.04)", + "danger": "0px 4px 8px 0px rgba(232, 82, 68, 0.04)", + "secondary": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)", + "contrast": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)" + } + }, + "focusRing": { "shadow": "inset 0 0 0 4px #d4fedc" } + } +} diff --git a/src/theme/types.ts b/src/theme/types.ts index 250836a5..7cc9d2dc 100644 --- a/src/theme/types.ts +++ b/src/theme/types.ts @@ -12,6 +12,8 @@ import type sizing from './assets/sizing.json' import type spacing from './assets/spacing.json' import type lightTheme from './assets/themeLight.json' import type typography from './assets/typography.json' +import type lightComponentTokens from './tokens/components/light.json' +import type lightSemanticTokens from './tokens/semantic/light.json' export interface ThemeType { background: typeof background @@ -21,6 +23,8 @@ export interface ThemeType { global: typeof global sizing: typeof sizing spacing: typeof spacing + semantic: typeof lightSemanticTokens + components: typeof lightComponentTokens theme: typeof lightTheme & { custom: typeof customLight InputSize: typeof InputSize From aa8281b06ff8a9f53ac896d724fdf4ffedc625b6 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Thu, 30 Jul 2026 21:36:19 +0300 Subject: [PATCH 04/60] =?UTF-8?q?fix:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BD=D0=BE=D1=80=D0=BC=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=80=D0=B0=D0=B4?= =?UTF-8?q?=D0=B8=D1=83=D1=81=D0=BE=D0=B2=20=D0=B2=20=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/token-generator/README.md | 11 +++++++ .../__tests__/compiler.test.ts | 30 ++++++++++++++++++- scripts/token-generator/core/normalization.ts | 24 +++++++++++++++ scripts/token-generator/core/validation.ts | 3 +- src/theme/tokens/components/dark.json | 4 +-- src/theme/tokens/components/light.json | 4 +-- 6 files changed, 70 insertions(+), 6 deletions(-) diff --git a/scripts/token-generator/README.md b/scripts/token-generator/README.md index bbe25f0b..c2c280f7 100644 --- a/scripts/token-generator/README.md +++ b/scripts/token-generator/README.md @@ -85,6 +85,17 @@ padding: "8 14" -> paddingLeft: 14 ``` +Для `borderRadius` одинаковые значения сворачиваются в число. Разные значения +сохраняются в объекте в порядке углов CSS: + +```text +borderRadius: "0 0 0 0" +-> borderRadius: 0 + +borderRadius: "4 8 12 16" +-> borderRadius: { left: 16, top: 4, right: 8, bottom: 12 } +``` + Генерация завершается с ошибкой при отсутствующей или циклической ссылке, неподдерживаемом shorthand, оставшихся `rem`/`ms`, `NaN` или `Infinity`. diff --git a/scripts/token-generator/__tests__/compiler.test.ts b/scripts/token-generator/__tests__/compiler.test.ts index a0be0dc4..ce899ca0 100644 --- a/scripts/token-generator/__tests__/compiler.test.ts +++ b/scripts/token-generator/__tests__/compiler.test.ts @@ -9,7 +9,11 @@ import { parseArgs, } from '../build' import { compileTokens } from '../core/compiler' -import { convertUnit, parseBoxShorthand } from '../core/normalization' +import { + convertUnit, + normalizeTree, + parseBoxShorthand, +} from '../core/normalization' import { resolveReferences } from '../core/resolution' import { isTokenTree, @@ -121,6 +125,22 @@ describe('token compiler', () => { }) }) + describe('normalizeTree', () => { + test('одинаковые радиусы сворачивает в одно значение', () => { + expect( + normalizeTree({ borderRadius: '0rem 0rem 0rem 0rem' }) + ).toStrictEqual({ borderRadius: 0 }) + }) + + test('разные радиусы сохраняет отдельными значениями', () => { + expect( + normalizeTree({ borderRadius: '0.25rem 0.5rem 0.75rem 1rem' }) + ).toStrictEqual({ + borderRadius: { left: 16, top: 4, right: 8, bottom: 12 }, + }) + }) + }) + test('разделяет один источник на темы, разрешает ссылки и нормализует значения', () => { const source: TokenTree = { primitive: { @@ -303,6 +323,14 @@ describe('production input tokens', () => { expect(compiled.components.dark.accordion).toHaveProperty( 'colorScheme.header.background' ) + expect(compiled.components.light.dataview).toHaveProperty( + 'header.borderRadius', + 0 + ) + expect(compiled.components.dark.dataview).toHaveProperty( + 'footer.borderRadius', + 0 + ) }) test('после записи повторная проверка не находит изменений', () => { diff --git a/scripts/token-generator/core/normalization.ts b/scripts/token-generator/core/normalization.ts index 6856ba86..4bf548ca 100644 --- a/scripts/token-generator/core/normalization.ts +++ b/scripts/token-generator/core/normalization.ts @@ -78,6 +78,25 @@ export const parseBoxShorthand = ( return { top, right, bottom, left } } +const normalizeBorderRadius = ( + value: string | number, + tokenPath: string +): number | TokenTree => { + const corners = parseBoxShorthand(value, tokenPath) + const values = Object.values(corners) + + if (values.every((corner) => corner === corners.top)) { + return corners.top + } + + return { + left: corners.left, + top: corners.top, + right: corners.right, + bottom: corners.bottom, + } +} + const edgePropertyName = ( property: BoxProperty, edge: keyof BoxEdges @@ -128,6 +147,11 @@ export const normalizeTree = ( const boxProperty = BOX_PROPERTIES.find((property) => property === key) if ( + key === 'borderRadius' && + (typeof value === 'string' || typeof value === 'number') + ) { + normalized[key] = normalizeBorderRadius(value, currentPath) + } else if ( boxProperty && (typeof value === 'string' || typeof value === 'number') ) { diff --git a/scripts/token-generator/core/validation.ts b/scripts/token-generator/core/validation.ts index 3e02b946..e1d5ad6b 100644 --- a/scripts/token-generator/core/validation.ts +++ b/scripts/token-generator/core/validation.ts @@ -19,7 +19,8 @@ export const assertValidOutput = ( if (isTokenTree(node)) { for (const [key, value] of Object.entries(node)) { if ( - BOX_PROPERTIES.includes(key as BoxProperty) && + (BOX_PROPERTIES.includes(key as BoxProperty) || + key === 'borderRadius') && typeof value === 'string' ) { throw new Error(`Unconverted box shorthand at "${tokenPath}.${key}"`) diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json index 111be1c4..dad859e7 100644 --- a/src/theme/tokens/components/dark.json +++ b/src/theme/tokens/components/dark.json @@ -894,7 +894,7 @@ "paddingRight": 14, "paddingBottom": 8, "paddingLeft": 14, - "borderRadius": "0px 0px 0px 0px", + "borderRadius": 0, "color": "#ffffff", "borderColor": "#404348" }, @@ -917,7 +917,7 @@ "paddingRight": 14, "paddingBottom": 8, "paddingLeft": 14, - "borderRadius": "0px 0px 0px 0px", + "borderRadius": 0, "borderColor": "#404348" }, "paginatorTop": { diff --git a/src/theme/tokens/components/light.json b/src/theme/tokens/components/light.json index ab86e22f..837beb80 100644 --- a/src/theme/tokens/components/light.json +++ b/src/theme/tokens/components/light.json @@ -894,7 +894,7 @@ "paddingRight": 14, "paddingBottom": 8, "paddingLeft": 14, - "borderRadius": "0px 0px 0px 0px", + "borderRadius": 0, "color": "#2b2e33", "borderColor": "#e2e2e4" }, @@ -917,7 +917,7 @@ "paddingRight": 14, "paddingBottom": 8, "paddingLeft": 14, - "borderRadius": "0px 0px 0px 0px", + "borderRadius": 0, "borderColor": "#e2e2e4" }, "paginatorTop": { From 88c7c365d4aa4ab617006f95a41504600196f488 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Fri, 31 Jul 2026 13:03:03 +0300 Subject: [PATCH 05/60] =?UTF-8?q?fix:=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=B0=D0=BD=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=20=D0=B4=D0=B8=D0=B7=D0=B0=D0=B9=D0=BD-?= =?UTF-8?q?=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/token-generator/README.md | 26 +++-- .../__tests__/compiler.test.ts | 105 ++++++++++++++---- scripts/token-generator/build.ts | 23 +++- scripts/token-generator/core/normalization.ts | 60 ++++++++-- scripts/token-generator/core/validation.ts | 23 +++- scripts/token-generator/io.ts | 53 ++++++--- src/theme/tokens/components/dark.json | 60 +++++----- src/theme/tokens/components/light.json | 60 +++++----- src/theme/tokens/semantic/dark.json | 48 ++++---- src/theme/tokens/semantic/light.json | 48 ++++---- 10 files changed, 335 insertions(+), 171 deletions(-) diff --git a/scripts/token-generator/README.md b/scripts/token-generator/README.md index c2c280f7..e8e7dfa1 100644 --- a/scripts/token-generator/README.md +++ b/scripts/token-generator/README.md @@ -10,8 +10,9 @@ 4. Запустить `yarn tokens:validate`. 5. Закоммитить входные и сгенерированные токены вместе. -`tokens:generate` записывает и форматирует файлы. `tokens:validate` ничего не -меняет: проверяет TypeScript генератора и актуальность сгенерированных токенов. +`tokens:generate` нормализует значения, удаляет лишние JSON и записывает +результат. `tokens:validate` ничего не меняет: проверяет TypeScript генератора и +актуальность сгенерированных токенов. ## Использование в компонентах @@ -71,14 +72,18 @@ Light- и dark-файлы должны иметь одинаковую стру ```text "1.5rem" -> 24 +"4px" -> 4 "150ms" -> 150 +"0.4" -> 0.4 "0" -> 0 ``` +Числовые строки преобразуются в числа, включая `fontWeight`. + CSS shorthand из 2–4 значений раскрывается в поля React Native: ```text -padding: "8 14" +padding: "8px 14px" -> paddingTop: 8 -> paddingRight: 14 -> paddingBottom: 8 @@ -96,14 +101,21 @@ borderRadius: "4 8 12 16" -> borderRadius: { left: 16, top: 4, right: 8, bottom: 12 } ``` +Значения `boxShadow` сохраняются строками. Размеры внутри строки записываются в +`px`, поэтому ссылка на `0.25rem` превращается в `4px`. `boxShadow` требует New +Architecture. На Android обычные тени поддерживаются с API 28, `inset` — с +API 29. Fallback для более ранних версий намеренно не предусмотрен. + Генерация завершается с ошибкой при отсутствующей или циклической ссылке, -неподдерживаемом shorthand, оставшихся `rem`/`ms`, `NaN` или `Infinity`. +неподдерживаемом shorthand, непреобразованных числовых значениях и единицах, +составных `rem`/`px` вне `boxShadow`, `NaN` или `Infinity`. ## Автоматические проверки -`yarn tokens:validate` запускается при сборке, в CI и перед push. Если -сгенерированные файлы устарели, нужно выполнить `yarn tokens:generate` и -проверить diff. +`yarn tokens:check` только проверяет файлы и отдельно показывает отсутствующие, +изменённые и лишние JSON. `yarn tokens:validate` дополнительно проверяет +TypeScript генератора. Если проверка не прошла, нужно выполнить +`yarn tokens:generate` и проверить diff. ## Устройство генератора diff --git a/scripts/token-generator/__tests__/compiler.test.ts b/scripts/token-generator/__tests__/compiler.test.ts index ce899ca0..97fd6983 100644 --- a/scripts/token-generator/__tests__/compiler.test.ts +++ b/scripts/token-generator/__tests__/compiler.test.ts @@ -1,4 +1,10 @@ -import { readdirSync, mkdtempSync, writeFileSync, rmSync } from 'node:fs' +import { + accessSync, + readdirSync, + mkdtempSync, + writeFileSync, + rmSync, +} from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' @@ -21,9 +27,10 @@ import { type TokenTree, type TokenValue, } from '../core/types' +import { assertValidOutput } from '../core/validation' import { OUTPUT_FILES, - findStaleGeneratedTokens, + findGeneratedTokenIssues, loadTokenTree, writeGeneratedTokens, } from '../io' @@ -65,6 +72,8 @@ describe('token compiler', () => { { name: 'положительный rem', value: '1.5rem', expected: 24 }, { name: 'отрицательный rem', value: '-0.5rem', expected: -8 }, { name: 'миллисекунды', value: '150ms', expected: 150 }, + { name: 'пиксели', value: '4px', expected: 4 }, + { name: 'числовая строка', value: '0.4', expected: 0.4 }, { name: 'строковый ноль', value: '0', expected: 0 }, { name: 'rem внутри составной строки', @@ -75,6 +84,12 @@ describe('token compiler', () => { ])('$name преобразуется в ожидаемое значение', ({ value, expected }) => { expect(convertUnit(value)).toBe(expected) }) + + test('отклоняет rem внутри неподдерживаемой составной строки', () => { + expect(() => convertUnit('blur(1rem)', 'semantic.effects.blur')).toThrow( + 'Unsupported composite unit value "blur(1rem)" at "semantic.effects.blur"' + ) + }) }) describe('parseBoxShorthand', () => { @@ -99,6 +114,11 @@ describe('token compiler', () => { value: '0rem 1.5rem 0.875rem 1.5rem', expected: { top: 0, right: 24, bottom: 14, left: 24 }, }, + { + name: 'значения с px', + value: '4px 8px 12px 16px', + expected: { top: 4, right: 8, bottom: 12, left: 16 }, + }, ])('$name раскрывается по правилам CSS', ({ value, expected }) => { expect(parseBoxShorthand(value)).toStrictEqual(expected) }) @@ -112,7 +132,7 @@ describe('token compiler', () => { }, { name: 'неподдерживаемая единица', - value: '1px 2px', + value: '1em 2em', message: 'Invalid box value', }, { @@ -139,6 +159,29 @@ describe('token compiler', () => { borderRadius: { left: 16, top: 4, right: 8, bottom: 12 }, }) }) + + test('преобразует числовые строки, включая fontWeight', () => { + expect( + normalizeTree({ depth: '1000', opacity: '0.4', fontWeight: '600' }) + ).toStrictEqual({ depth: 1000, opacity: 0.4, fontWeight: 600 }) + }) + }) + + describe('assertValidOutput', () => { + test.each(['4px', '0.4', 'blur(4px)'])( + 'отклоняет непреобразованное значение %s', + (value) => { + expect(() => assertValidOutput(value, 'semantic.value')).toThrow( + 'Unconverted token' + ) + } + ) + + test('разрешает boxShadow', () => { + expect(() => + assertValidOutput('0 0 4px #000', 'components.button.shadow') + ).not.toThrow() + }) }) test('разделяет один источник на темы, разрешает ссылки и нормализует значения', () => { @@ -309,8 +352,20 @@ describe('production input tokens', () => { }) test('совпадает с закоммиченными сгенерированными токенами', () => { - expect(findStaleGeneratedTokens(compiled, TOKENS_DIRECTORY)).toStrictEqual( - [] + expect(findGeneratedTokenIssues(compiled, TOKENS_DIRECTORY)).toStrictEqual({ + missing: [], + changed: [], + unexpected: [], + }) + }) + + test('преобразует числовые RN-значения', () => { + expect(compiled.semantic.light).toHaveProperty('dimension.depth.100', 1000) + expect(compiled.semantic.light).toHaveProperty('effects.opacity.4', 0.04) + expect(compiled.semantic.light).toHaveProperty('effects.blur.100', 4) + expect(compiled.components.light).toHaveProperty( + 'button.root.label.fontWeight', + 600 ) }) @@ -333,8 +388,12 @@ describe('production input tokens', () => { ) }) - test('после записи повторная проверка не находит изменений', () => { + test('check находит расхождения, а generate приводит файлы к актуальному состоянию', () => { const temporaryDirectory = mkdtempSync(join(tmpdir(), 'token-generator-')) + const unexpectedFile = join(temporaryDirectory, 'common.json') + const preservedFile = join(temporaryDirectory, 'README.md') + const missingFile = OUTPUT_FILES.semantic.dark + const changedFile = OUTPUT_FILES.semantic.light try { writeGeneratedTokens(compiled, temporaryDirectory) @@ -345,23 +404,31 @@ describe('production input tokens', () => { .sort() ) expect( - findStaleGeneratedTokens(compiled, temporaryDirectory) - ).toStrictEqual([]) + findGeneratedTokenIssues(compiled, temporaryDirectory) + ).toStrictEqual({ missing: [], changed: [], unexpected: [] }) - writeFileSync(join(temporaryDirectory, 'common.json'), '{}\n') + writeFileSync(unexpectedFile, '{}\n') + writeFileSync(preservedFile, '# Generated tokens\n') + rmSync(join(temporaryDirectory, missingFile)) + writeFileSync(join(temporaryDirectory, changedFile), '{}\n') - expect(findStaleGeneratedTokens(compiled, temporaryDirectory)).toContain( - 'common.json' - ) + expect( + findGeneratedTokenIssues(compiled, temporaryDirectory) + ).toStrictEqual({ + missing: [missingFile], + changed: [changedFile], + unexpected: ['common.json'], + }) + expect(() => accessSync(unexpectedFile)).not.toThrow() + expect(() => accessSync(preservedFile)).not.toThrow() - writeFileSync( - join(temporaryDirectory, OUTPUT_FILES.semantic.light), - '{}\n' - ) + writeGeneratedTokens(compiled, temporaryDirectory) - expect(findStaleGeneratedTokens(compiled, temporaryDirectory)).toContain( - OUTPUT_FILES.semantic.light - ) + expect( + findGeneratedTokenIssues(compiled, temporaryDirectory) + ).toStrictEqual({ missing: [], changed: [], unexpected: [] }) + expect(() => accessSync(unexpectedFile)).toThrow('ENOENT') + expect(() => accessSync(preservedFile)).not.toThrow() } finally { rmSync(temporaryDirectory, { recursive: true, force: true }) } diff --git a/scripts/token-generator/build.ts b/scripts/token-generator/build.ts index d4fb1510..e689e838 100644 --- a/scripts/token-generator/build.ts +++ b/scripts/token-generator/build.ts @@ -3,7 +3,8 @@ import { resolve, join } from 'node:path' import { compileTokens } from './core/compiler' import type { CompiledTokens } from './core/types' import { - findStaleGeneratedTokens, + findGeneratedTokenIssues, + type GeneratedTokenIssues, loadTokenTree, writeGeneratedTokens, } from './io' @@ -43,6 +44,19 @@ export const parseArgs = (arguments_: string[]): CliOptions => { export const compileInputTokens = (): CompiledTokens => compileTokens(loadTokenTree(INPUT_FILE)) +const formatTokenIssues = (issues: GeneratedTokenIssues): string => + [ + issues.missing.length > 0 + ? `Отсутствуют: ${issues.missing.join(', ')}` + : '', + issues.changed.length > 0 ? `Изменены: ${issues.changed.join(', ')}` : '', + issues.unexpected.length > 0 + ? `Лишние: ${issues.unexpected.join(', ')}` + : '', + ] + .filter(Boolean) + .join('\n') + export const run = (arguments_: string[]): void => { const options = parseArgs(arguments_) @@ -55,11 +69,12 @@ export const run = (arguments_: string[]): void => { const compiled = compileInputTokens() if (options.check) { - const staleFiles = findStaleGeneratedTokens(compiled, TOKENS_DIRECTORY) + const issues = findGeneratedTokenIssues(compiled, TOKENS_DIRECTORY) + const issueDescription = formatTokenIssues(issues) - if (staleFiles.length > 0) { + if (issueDescription) { throw new Error( - `Сгенерированные токены устарели: ${staleFiles.join(', ')}. ` + + `Сгенерированные токены неактуальны:\n${issueDescription}\n` + 'Запустите yarn tokens:generate.' ) } diff --git a/scripts/token-generator/core/normalization.ts b/scripts/token-generator/core/normalization.ts index 4bf548ca..dbde5671 100644 --- a/scripts/token-generator/core/normalization.ts +++ b/scripts/token-generator/core/normalization.ts @@ -7,11 +7,46 @@ import { } from './types' const REM_BASE = 16 +const NUMBER_PATTERN = /^-?\d*\.?\d+$/ +const PIXEL_PATTERN = /^-?\d*\.?\d+px$/ +const SHADOW_LENGTH_PATTERN = /^(?:0|-?\d*\.?\d+(?:rem|px))$/ export const BOX_PROPERTIES = ['padding', 'margin', 'borderWidth'] as const export type BoxProperty = (typeof BOX_PROPERTIES)[number] -export const convertUnit = (value: TokenPrimitive): TokenPrimitive => { +export const isBoxShadowValue = (value: string): boolean => { + const parts = value + .trim() + .split(/\s+(?![^(]*\))/) + .filter(Boolean) + const insetIndex = parts.indexOf('inset') + + if (insetIndex > 0 && insetIndex < parts.length - 1) return false + + const shadowParts = parts.filter((_, index) => index !== insetIndex) + const colorIndexes = shadowParts + .map((part, index) => (SHADOW_LENGTH_PATTERN.test(part) ? -1 : index)) + .filter((index) => index !== -1) + + if (colorIndexes.length !== 1) return false + + const [colorIndex] = colorIndexes + + if (colorIndex !== 0 && colorIndex !== shadowParts.length - 1) return false + + const lengths = shadowParts.filter((_, index) => index !== colorIndex) + + return ( + lengths.length >= 2 && + lengths.length <= 4 && + lengths.every((part) => SHADOW_LENGTH_PATTERN.test(part)) + ) +} + +export const convertUnit = ( + value: TokenPrimitive, + tokenPath = 'root' +): TokenPrimitive => { if (typeof value !== 'string') return value const isRem = /^-?\d*\.?\d+rem$/.test(value) @@ -22,22 +57,33 @@ export const convertUnit = (value: TokenPrimitive): TokenPrimitive => { if (isMilliseconds) return Number(value.slice(0, -2)) - if (value === '0') return 0 + if (PIXEL_PATTERN.test(value)) return Number(value.slice(0, -2)) - return value.replace(/-?\d*\.?\d+rem\b/g, (token) => { + if (NUMBER_PATTERN.test(value)) return Number(value) + + const converted = value.replace(/-?\d*\.?\d+rem\b/g, (token) => { const pixels = Number(token.slice(0, -3)) * REM_BASE return `${pixels}px` }) + + if (converted !== value && !isBoxShadowValue(converted)) { + throw new Error( + `Unsupported composite unit value "${value}" at "${tokenPath}"` + ) + } + + return converted } const parseBoxPart = (part: string, tokenPath: string): number => { - if (!/^-?\d*\.?\d+(?:rem)?$/.test(part)) { + if (!/^-?\d*\.?\d+(?:rem|px)?$/.test(part)) { throw new Error(`Invalid box value "${part}" at "${tokenPath}"`) } - const isRem = part.endsWith('rem') - const value = Number(isRem ? part.slice(0, -3) : part) + const unit = part.endsWith('rem') ? 'rem' : part.endsWith('px') ? 'px' : '' + const value = Number(unit ? part.slice(0, -unit.length) : part) + const isRem = unit === 'rem' const normalized = isRem ? value * REM_BASE : value if (!Number.isFinite(normalized)) { @@ -138,7 +184,7 @@ export const normalizeTree = ( ) } - if (!isTokenTree(node)) return convertUnit(node) + if (!isTokenTree(node)) return convertUnit(node, tokenPath) const normalized: TokenTree = {} diff --git a/scripts/token-generator/core/validation.ts b/scripts/token-generator/core/validation.ts index e1d5ad6b..7923ad75 100644 --- a/scripts/token-generator/core/validation.ts +++ b/scripts/token-generator/core/validation.ts @@ -1,8 +1,14 @@ -import { BOX_PROPERTIES, type BoxProperty } from './normalization' +import { + BOX_PROPERTIES, + isBoxShadowValue, + type BoxProperty, +} from './normalization' import { isTokenTree, type TokenTree, type TokenValue } from './types' const REFERENCE_PATTERN = /\{[^}]+\}/ const UNCONVERTED_UNIT_PATTERN = /-?\d*\.?\d+(?:rem|ms)\b/ +const PIXEL_PATTERN = /-?\d*\.?\d+px\b/ +const NUMERIC_STRING_PATTERN = /^-?\d*\.?\d+$/ export const assertValidOutput = ( node: TokenValue, @@ -36,11 +42,16 @@ export const assertValidOutput = ( throw new Error(`Non-finite number at "${tokenPath}"`) } - if ( - typeof node === 'string' && - (REFERENCE_PATTERN.test(node) || UNCONVERTED_UNIT_PATTERN.test(node)) - ) { - throw new Error(`Unconverted token "${node}" at "${tokenPath}"`) + if (typeof node === 'string') { + const hasUnconvertedValue = + REFERENCE_PATTERN.test(node) || + UNCONVERTED_UNIT_PATTERN.test(node) || + (PIXEL_PATTERN.test(node) && !isBoxShadowValue(node)) || + NUMERIC_STRING_PATTERN.test(node) + + if (hasUnconvertedValue) { + throw new Error(`Unconverted token "${node}" at "${tokenPath}"`) + } } } diff --git a/scripts/token-generator/io.ts b/scripts/token-generator/io.ts index d4c0e85f..301d159c 100644 --- a/scripts/token-generator/io.ts +++ b/scripts/token-generator/io.ts @@ -5,6 +5,7 @@ import { writeFileSync, renameSync, existsSync, + unlinkSync, } from 'node:fs' import { dirname, join } from 'node:path' import { isDeepStrictEqual } from 'node:util' @@ -56,6 +57,16 @@ export const writeGeneratedTokens = ( ): void => { mkdirSync(outputDirectory, { recursive: true }) + const expectedFiles = new Set( + outputEntries(compiled).map(([fileName]) => fileName) + ) + + for (const fileName of findJsonFiles(outputDirectory)) { + if (!expectedFiles.has(fileName)) { + unlinkSync(join(outputDirectory, fileName)) + } + } + for (const [fileName, value] of outputEntries(compiled)) { const outputPath = join(outputDirectory, fileName) const temporaryPath = `${outputPath}.tmp` @@ -84,26 +95,40 @@ const findJsonFiles = (directory: string, prefix = ''): string[] => { .sort() } -export const findStaleGeneratedTokens = ( +export interface GeneratedTokenIssues { + missing: string[] + changed: string[] + unexpected: string[] +} + +export const findGeneratedTokenIssues = ( compiled: CompiledTokens, outputDirectory: string -): string[] => { +): GeneratedTokenIssues => { const entries = outputEntries(compiled) const expectedFiles = new Set(entries.map(([fileName]) => fileName)) - const staleFiles = entries - .filter(([fileName, value]) => { - const outputPath = join(outputDirectory, fileName) - - return ( - !existsSync(outputPath) || - !isDeepStrictEqual(loadTokenTree(outputPath), value) - ) - }) - .map(([fileName]) => fileName) + const missing: string[] = [] + const changed: string[] = [] + + for (const [fileName, value] of entries) { + const outputPath = join(outputDirectory, fileName) + + if (existsSync(outputPath)) { + try { + if (!isDeepStrictEqual(loadTokenTree(outputPath), value)) { + changed.push(fileName) + } + } catch { + changed.push(fileName) + } + } else { + missing.push(fileName) + } + } - const unexpectedFiles = findJsonFiles(outputDirectory).filter( + const unexpected = findJsonFiles(outputDirectory).filter( (fileName) => !expectedFiles.has(fileName) ) - return [...staleFiles, ...unexpectedFiles] + return { missing, changed, unexpected } } diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json index dad859e7..3bef7b42 100644 --- a/src/theme/tokens/components/dark.json +++ b/src/theme/tokens/components/dark.json @@ -19,7 +19,7 @@ "paddingRight": 0, "paddingBottom": 14, "paddingLeft": 0, - "fontWeight": "700", + "fontWeight": 700, "borderRadius": 0, "borderWidth": 0, "focusRing": { @@ -125,7 +125,7 @@ "optionGroup": { "background": "#56595f", "color": "#a2a5a9", - "fontWeight": "600", + "fontWeight": 600, "paddingTop": 8, "paddingRight": 14, "paddingBottom": 8, @@ -207,7 +207,7 @@ "borderRadius": 8, "padding": 8, "fontSize": 12, - "fontWeight": "400", + "fontWeight": 400, "minWidth": 24, "height": 24 }, @@ -532,7 +532,7 @@ "paddingX": 24, "paddingY": 14 }, - "label": { "fontWeight": "600" } + "label": { "fontWeight": 600 } } }, "card": { @@ -545,7 +545,7 @@ }, "body": { "padding": 14, "gap": 14 }, "caption": { "gap": 4 }, - "title": { "fontSize": 18, "fontWeight": "600" }, + "title": { "fontSize": 18, "fontWeight": 600 }, "subtitle": { "color": "#a2a5a9" } }, "carousel": { @@ -767,7 +767,7 @@ "sm": { "padding": 8 }, "lg": { "padding": 20 } }, - "columnTitle": { "fontWeight": "700" }, + "columnTitle": { "fontWeight": 700 }, "row": { "background": "#56595f", "hoverBackground": "#2b2e33", @@ -795,7 +795,7 @@ "sm": { "padding": 8 }, "lg": { "padding": 20 } }, - "columnFooter": { "fontWeight": "700" }, + "columnFooter": { "fontWeight": 700 }, "dropPoint": { "color": "#ffffff" }, "footer": { "borderColor": "#404348", @@ -968,7 +968,7 @@ "color": "#ffffff", "padding": 14 }, - "title": { "gap": 8, "fontWeight": "700" }, + "title": { "gap": 8, "fontWeight": 700 }, "selectMonth": { "hoverBackground": "#2b2e33", "color": "#ffffff", @@ -1002,7 +1002,7 @@ "padding": 4 }, "dayView": { "margin": 14 }, - "weekDay": { "padding": 4, "fontWeight": "700", "color": "#ffffff" }, + "weekDay": { "padding": 4, "fontWeight": 700, "color": "#ffffff" }, "date": { "hoverBackground": "#2b2e33", "selectedBackground": "#f0f0f1", @@ -1062,7 +1062,7 @@ "paddingLeft": 24, "gap": 8 }, - "title": { "fontSize": 20, "fontWeight": "600" }, + "title": { "fontSize": 20, "fontWeight": 600 }, "content": { "padding": 24 }, "footer": { "paddingTop": 0, @@ -1131,7 +1131,7 @@ "paddingBottom": 14, "paddingLeft": 24 }, - "title": { "fontSize": 20, "fontWeight": "600" }, + "title": { "fontSize": 20, "fontWeight": 600 }, "content": { "padding": 24 }, "footer": { "paddingTop": 0, @@ -1190,8 +1190,8 @@ "transitionDuration": 180, "positionX": 14, "positionY": 14, - "fontWeight": "400", - "active": { "fontSize": 12, "fontWeight": "400" } + "fontWeight": 400, + "active": { "fontSize": 12, "fontWeight": 400 } }, "over": { "active": { "top": 14 } }, "inside": { @@ -1425,7 +1425,7 @@ "optionGroup": { "background": "#56595f", "color": "#a2a5a9", - "fontWeight": "600", + "fontWeight": 600, "paddingTop": 8, "paddingRight": 14, "paddingBottom": 8, @@ -1496,7 +1496,7 @@ "paddingLeft": 14, "background": "transparent", "color": "#a2a5a9", - "fontWeight": "600" + "fontWeight": 600 }, "submenuIcon": { "size": 20, @@ -1546,7 +1546,7 @@ "paddingRight": 14, "paddingBottom": 8, "paddingLeft": 14, - "fontWeight": "600", + "fontWeight": 600, "background": "transparent", "color": "#a2a5a9" }, @@ -1573,7 +1573,7 @@ "paddingRight": 14, "paddingBottom": 8, "paddingLeft": 14, - "fontWeight": "600", + "fontWeight": 600, "background": "transparent", "color": "#a2a5a9" } @@ -1784,7 +1784,7 @@ }, "text": { "fontSize": 16, - "fontWeight": "700", + "fontWeight": 700, "sm": { "fontSize": 16 }, "lg": { "fontSize": 16 } }, @@ -1881,7 +1881,7 @@ "selectedFocusColor": "#ffffff" }, "optionGroup": { - "fontWeight": "600", + "fontWeight": 600, "paddingTop": 8, "paddingRight": 14, "paddingBottom": 8, @@ -2017,7 +2017,7 @@ "content": { "padding": 14 } }, "progressbar": { - "label": { "color": "#ffffff", "fontSize": 12, "fontWeight": "400" }, + "label": { "color": "#ffffff", "fontSize": 12, "fontWeight": 400 }, "root": { "background": "#404348", "borderRadius": 14, "height": 16 }, "value": { "background": "#44e858" } }, @@ -2194,7 +2194,7 @@ "optionGroup": { "background": "#56595f", "color": "#a2a5a9", - "fontWeight": "600", + "fontWeight": 600, "paddingTop": 8, "paddingRight": 14, "paddingBottom": 8, @@ -2318,7 +2318,7 @@ "stepTitle": { "color": "#ffffff", "activeColor": "#ffffff", - "fontWeight": "400" + "fontWeight": 400 }, "stepNumber": { "background": "#56595f", @@ -2329,7 +2329,7 @@ "activeColor": "#ffffff", "size": 24, "fontSize": 16, - "fontWeight": "700", + "fontWeight": 700, "borderRadius": 1600, "shadow": "none" }, @@ -2354,7 +2354,7 @@ } }, "itemLabel": { - "fontWeight": "400", + "fontWeight": 400, "activeColor": "#cecfd2", "color": "#ffffff" }, @@ -2362,7 +2362,7 @@ "background": "#56595f", "size": 32, "fontSize": 16, - "fontWeight": "700", + "fontWeight": 700, "borderRadius": 1600, "shadow": "none", "activeBackground": "#56595f", @@ -2401,7 +2401,7 @@ "hoverColor": "#ffffff", "activeColor": "#ffffff", "padding": 14, - "fontWeight": "600", + "fontWeight": 600, "margin": 0, "gap": 8, "focusRing": { @@ -2551,8 +2551,8 @@ "icon": { "size": 36 }, "content": { "padding": 14, "gap": 14 }, "text": { "gap": 4 }, - "summary": { "fontWeight": "700", "fontSize": 16 }, - "detail": { "fontWeight": "400", "fontSize": 14 }, + "summary": { "fontWeight": 700, "fontSize": 16 }, + "detail": { "fontWeight": 400, "fontSize": 14 }, "closeButton": { "width": 32, "height": 32, @@ -2573,7 +2573,7 @@ }, "root": { "fontSize": 12, - "fontWeight": "400", + "fontWeight": 400, "paddingTop": 4, "paddingRight": 8, "paddingBottom": 4, @@ -2748,7 +2748,7 @@ "paddingLeft": 14, "borderRadius": 1600, "gap": 8, - "fontWeight": "600", + "fontWeight": 600, "focusRing": { "width": 4, "style": "none", diff --git a/src/theme/tokens/components/light.json b/src/theme/tokens/components/light.json index 837beb80..be686424 100644 --- a/src/theme/tokens/components/light.json +++ b/src/theme/tokens/components/light.json @@ -19,7 +19,7 @@ "paddingRight": 0, "paddingBottom": 14, "paddingLeft": 0, - "fontWeight": "700", + "fontWeight": 700, "borderRadius": 0, "borderWidth": 0, "focusRing": { @@ -125,7 +125,7 @@ "optionGroup": { "background": "#ffffff", "color": "#85888e", - "fontWeight": "600", + "fontWeight": 600, "paddingTop": 8, "paddingRight": 14, "paddingBottom": 8, @@ -207,7 +207,7 @@ "borderRadius": 8, "padding": 8, "fontSize": 12, - "fontWeight": "400", + "fontWeight": 400, "minWidth": 24, "height": 24 }, @@ -532,7 +532,7 @@ "paddingX": 24, "paddingY": 14 }, - "label": { "fontWeight": "600" } + "label": { "fontWeight": 600 } } }, "card": { @@ -545,7 +545,7 @@ }, "body": { "padding": 14, "gap": 14 }, "caption": { "gap": 4 }, - "title": { "fontSize": 18, "fontWeight": "600" }, + "title": { "fontSize": 18, "fontWeight": 600 }, "subtitle": { "color": "#85888e" } }, "carousel": { @@ -767,7 +767,7 @@ "sm": { "padding": 8 }, "lg": { "padding": 20 } }, - "columnTitle": { "fontWeight": "700" }, + "columnTitle": { "fontWeight": 700 }, "row": { "background": "#ffffff", "hoverBackground": "#f0f0f1", @@ -795,7 +795,7 @@ "sm": { "padding": 8 }, "lg": { "padding": 20 } }, - "columnFooter": { "fontWeight": "700" }, + "columnFooter": { "fontWeight": 700 }, "dropPoint": { "color": "#2b2e33" }, "footer": { "borderColor": "#e2e2e4", @@ -968,7 +968,7 @@ "color": "#2b2e33", "padding": 14 }, - "title": { "gap": 8, "fontWeight": "700" }, + "title": { "gap": 8, "fontWeight": 700 }, "selectMonth": { "hoverBackground": "#f0f0f1", "color": "#2b2e33", @@ -1002,7 +1002,7 @@ "padding": 4 }, "dayView": { "margin": 14 }, - "weekDay": { "padding": 4, "fontWeight": "700", "color": "#2b2e33" }, + "weekDay": { "padding": 4, "fontWeight": 700, "color": "#2b2e33" }, "date": { "hoverBackground": "#f0f0f1", "selectedBackground": "#2b2e33", @@ -1062,7 +1062,7 @@ "paddingLeft": 24, "gap": 8 }, - "title": { "fontSize": 20, "fontWeight": "600" }, + "title": { "fontSize": 20, "fontWeight": 600 }, "content": { "padding": 24 }, "footer": { "paddingTop": 0, @@ -1131,7 +1131,7 @@ "paddingBottom": 14, "paddingLeft": 24 }, - "title": { "fontSize": 20, "fontWeight": "600" }, + "title": { "fontSize": 20, "fontWeight": 600 }, "content": { "padding": 24 }, "footer": { "paddingTop": 0, @@ -1190,8 +1190,8 @@ "transitionDuration": 180, "positionX": 14, "positionY": 14, - "fontWeight": "400", - "active": { "fontSize": 12, "fontWeight": "400" } + "fontWeight": 400, + "active": { "fontSize": 12, "fontWeight": 400 } }, "over": { "active": { "top": 14 } }, "inside": { @@ -1425,7 +1425,7 @@ "optionGroup": { "background": "#ffffff", "color": "#85888e", - "fontWeight": "600", + "fontWeight": 600, "paddingTop": 8, "paddingRight": 14, "paddingBottom": 8, @@ -1496,7 +1496,7 @@ "paddingLeft": 14, "background": "transparent", "color": "#85888e", - "fontWeight": "600" + "fontWeight": 600 }, "submenuIcon": { "size": 20, @@ -1546,7 +1546,7 @@ "paddingRight": 14, "paddingBottom": 8, "paddingLeft": 14, - "fontWeight": "600", + "fontWeight": 600, "background": "transparent", "color": "#85888e" }, @@ -1573,7 +1573,7 @@ "paddingRight": 14, "paddingBottom": 8, "paddingLeft": 14, - "fontWeight": "600", + "fontWeight": 600, "background": "transparent", "color": "#85888e" } @@ -1784,7 +1784,7 @@ }, "text": { "fontSize": 16, - "fontWeight": "700", + "fontWeight": 700, "sm": { "fontSize": 16 }, "lg": { "fontSize": 16 } }, @@ -1881,7 +1881,7 @@ "selectedFocusColor": "#ffffff" }, "optionGroup": { - "fontWeight": "600", + "fontWeight": 600, "paddingTop": 8, "paddingRight": 14, "paddingBottom": 8, @@ -2017,7 +2017,7 @@ "content": { "padding": 14 } }, "progressbar": { - "label": { "color": "#2b2e33", "fontSize": 12, "fontWeight": "400" }, + "label": { "color": "#2b2e33", "fontSize": 12, "fontWeight": 400 }, "root": { "background": "#e2e2e4", "borderRadius": 14, "height": 16 }, "value": { "background": "#44e858" } }, @@ -2194,7 +2194,7 @@ "optionGroup": { "background": "#ffffff", "color": "#85888e", - "fontWeight": "600", + "fontWeight": 600, "paddingTop": 8, "paddingRight": 14, "paddingBottom": 8, @@ -2318,7 +2318,7 @@ "stepTitle": { "color": "#2b2e33", "activeColor": "#2b2e33", - "fontWeight": "400" + "fontWeight": 400 }, "stepNumber": { "background": "#ffffff", @@ -2329,7 +2329,7 @@ "activeColor": "#2b2e33", "size": 24, "fontSize": 16, - "fontWeight": "700", + "fontWeight": 700, "borderRadius": 1600, "shadow": "none" }, @@ -2354,7 +2354,7 @@ } }, "itemLabel": { - "fontWeight": "400", + "fontWeight": 400, "activeColor": "#56595f", "color": "#2b2e33" }, @@ -2362,7 +2362,7 @@ "background": "#ffffff", "size": 32, "fontSize": 16, - "fontWeight": "700", + "fontWeight": 700, "borderRadius": 1600, "shadow": "none", "activeBackground": "#ffffff", @@ -2401,7 +2401,7 @@ "hoverColor": "#2b2e33", "activeColor": "#2b2e33", "padding": 14, - "fontWeight": "600", + "fontWeight": 600, "margin": 0, "gap": 8, "focusRing": { @@ -2551,8 +2551,8 @@ "icon": { "size": 36 }, "content": { "padding": 14, "gap": 14 }, "text": { "gap": 4 }, - "summary": { "fontWeight": "700", "fontSize": 16 }, - "detail": { "fontWeight": "400", "fontSize": 14 }, + "summary": { "fontWeight": 700, "fontSize": 16 }, + "detail": { "fontWeight": 400, "fontSize": 14 }, "closeButton": { "width": 32, "height": 32, @@ -2573,7 +2573,7 @@ }, "root": { "fontSize": 12, - "fontWeight": "400", + "fontWeight": 400, "paddingTop": 4, "paddingRight": 8, "paddingBottom": 4, @@ -2748,7 +2748,7 @@ "paddingLeft": 14, "borderRadius": 1600, "gap": 8, - "fontWeight": "600", + "fontWeight": 600, "focusRing": { "width": 4, "style": "none", diff --git a/src/theme/tokens/semantic/dark.json b/src/theme/tokens/semantic/dark.json index 1a25ff23..57ea1bc0 100644 --- a/src/theme/tokens/semantic/dark.json +++ b/src/theme/tokens/semantic/dark.json @@ -282,40 +282,34 @@ "borderWidth": { "100": 1, "200": 2, "300": 4, "none": 0 }, "focusRing": { "width": 4, "offset": 0 }, "depth": { - "100": "1000", - "200": "1100", - "300": "1200", - "400": "1300", - "500": "1400", - "600": "1500", - "700": "1600" + "100": 1000, + "200": 1100, + "300": 1200, + "400": 1300, + "500": 1400, + "600": 1500, + "700": 1600 }, "viewport": { "100": 576, "200": 768, "300": 992, "400": 1200, "500": 1400 } }, "effects": { "opacity": { "0": 0, - "4": "0.04", - "8": "0.08", - "12": "0.12", - "16": "0.16", - "20": "0.2", - "30": "0.3", - "40": "0.4", - "50": "0.5", - "60": "0.6", - "70": "0.7", - "80": "0.8", - "90": "0.9", - "100": "1" - }, - "blur": { - "100": "4px", - "200": "8px", - "300": "16px", - "400": "24px", - "none": 0 + "4": 0.04, + "8": 0.08, + "12": 0.12, + "16": 0.16, + "20": 0.2, + "30": 0.3, + "40": 0.4, + "50": 0.5, + "60": 0.6, + "70": 0.7, + "80": 0.8, + "90": 0.9, + "100": 1 }, + "blur": { "100": 4, "200": 8, "300": 16, "400": 24, "none": 0 }, "transition": { "easing": { "linear": "linear", diff --git a/src/theme/tokens/semantic/light.json b/src/theme/tokens/semantic/light.json index 687f1010..0ba6a30c 100644 --- a/src/theme/tokens/semantic/light.json +++ b/src/theme/tokens/semantic/light.json @@ -282,40 +282,34 @@ "borderWidth": { "100": 1, "200": 2, "300": 4, "none": 0 }, "focusRing": { "width": 4, "offset": 0 }, "depth": { - "100": "1000", - "200": "1100", - "300": "1200", - "400": "1300", - "500": "1400", - "600": "1500", - "700": "1600" + "100": 1000, + "200": 1100, + "300": 1200, + "400": 1300, + "500": 1400, + "600": 1500, + "700": 1600 }, "viewport": { "100": 576, "200": 768, "300": 992, "400": 1200, "500": 1400 } }, "effects": { "opacity": { "0": 0, - "4": "0.04", - "8": "0.08", - "12": "0.12", - "16": "0.16", - "20": "0.2", - "30": "0.3", - "40": "0.4", - "50": "0.5", - "60": "0.6", - "70": "0.7", - "80": "0.8", - "90": "0.9", - "100": "1" - }, - "blur": { - "100": "4px", - "200": "8px", - "300": "16px", - "400": "24px", - "none": 0 + "4": 0.04, + "8": 0.08, + "12": 0.12, + "16": 0.16, + "20": 0.2, + "30": 0.3, + "40": 0.4, + "50": 0.5, + "60": 0.6, + "70": 0.7, + "80": 0.8, + "90": 0.9, + "100": 1 }, + "blur": { "100": 4, "200": 8, "300": 16, "400": 24, "none": 0 }, "transition": { "easing": { "linear": "linear", From 54915e6fcfa3ec992fc6a54cce3d06a660e1d98d Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Fri, 31 Jul 2026 13:03:34 +0300 Subject: [PATCH 06/60] =?UTF-8?q?chore:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD?= =?UTF-8?q?=D0=B4=D1=8B=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B4=D0=B8=D0=B7=D0=B0=D0=B9=D0=BD-=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lefthook.yml | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lefthook.yml b/lefthook.yml index 849f2579..1fa2a1e0 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -70,8 +70,8 @@ pre-push: exit 1 fi eslint: - run: npx yarn eslint . + run: yarn eslint . type-check: - run: npx yarn tsc --noEmit + run: yarn tsc --noEmit tokens-validate: - run: npx yarn tokens:validate + run: yarn tokens:validate diff --git a/package.json b/package.json index 3710f509..9c265a7d 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "storybook-generate": "sb-rn-get-stories --config-path .storybook && sed -i -e 's/export const view = global.view/export const view: ReturnType = global.view/' .storybook/storybook.requires.ts && prettier .storybook --write", "tokens:generate": "ts-node --project scripts/token-generator/tsconfig.json scripts/token-generator/build.ts && yarn tokens:format", "tokens:format": "prettier 'design-tokens/input/*.json' 'src/theme/tokens/**/*.json' --write", - "tokens:check": "ts-node --project scripts/token-generator/tsconfig.json scripts/token-generator/build.ts --check", + "tokens:check": "ts-node --transpile-only --project scripts/token-generator/tsconfig.json scripts/token-generator/build.ts --check", "tokens:typecheck": "tsc --noEmit -p scripts/token-generator/tsconfig.json", "tokens:validate": "yarn tokens:typecheck && yarn tokens:check", "doctor": "expo-doctor", From 158c6752110c6c81c9c1f8accb31c851a4ef1378 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Fri, 31 Jul 2026 14:43:07 +0300 Subject: [PATCH 07/60] =?UTF-8?q?feat:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=BA=D0=B0=20focusRing-=D1=82=D0=BE=D0=BA=D0=B5=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/token-generator/README.md | 6 ++ .../__tests__/compiler.test.ts | 71 +++++++++++++++++++ src/theme/tokens/README.md | 4 ++ 3 files changed, 81 insertions(+) diff --git a/scripts/token-generator/README.md b/scripts/token-generator/README.md index e8e7dfa1..ebfd2493 100644 --- a/scripts/token-generator/README.md +++ b/scripts/token-generator/README.md @@ -106,6 +106,12 @@ borderRadius: "4 8 12 16" Architecture. На Android обычные тени поддерживаются с API 28, `inset` — с API 29. Fallback для более ранних версий намеренно не предусмотрен. +`focusRing` сохраняет исходную структуру. Его размеры нормализуются, а `shadow` +обрабатывается по правилам `boxShadow`. Значение `style: "none"` отключает +только применение `width`, `color` и `offset` как outline-свойств: генератор не +зануляет эти токены. `shadow` остаётся независимым и может использоваться как +`boxShadow`. + Генерация завершается с ошибкой при отсутствующей или циклической ссылке, неподдерживаемом shorthand, непреобразованных числовых значениях и единицах, составных `rem`/`px` вне `boxShadow`, `NaN` или `Infinity`. diff --git a/scripts/token-generator/__tests__/compiler.test.ts b/scripts/token-generator/__tests__/compiler.test.ts index 97fd6983..19c3c036 100644 --- a/scripts/token-generator/__tests__/compiler.test.ts +++ b/scripts/token-generator/__tests__/compiler.test.ts @@ -264,6 +264,60 @@ describe('token compiler', () => { expect(compiled.components.dark.demo).not.toHaveProperty('colorScheme.dark') }) + test('сохраняет focusRing и нормализует его значения', () => { + const source: TokenTree = { + primitive: { + sizing: { focusRing: '0.25rem' }, + colors: { focus: '#d4fedc' }, + }, + semantic: { + dimension: { + focusRing: { width: '{sizing.focusRing}', offset: '0px' }, + }, + effects: { + focusRing: { + shadow: 'inset 0 0 0 {dimension.focusRing.width} {colors.focus}', + }, + }, + colorScheme: { light: {}, dark: {} }, + }, + components: { + demo: { + root: { + focusRing: { + width: '{dimension.focusRing.width}', + style: 'none', + color: '{colors.focus}', + offset: '{dimension.focusRing.offset}', + shadow: '{effects.focusRing.shadow}', + }, + }, + }, + }, + } + + const compiled = compileTokens(source) + + expect(compiled.semantic.light).toStrictEqual({ + dimension: { focusRing: { width: 4, offset: 0 } }, + effects: { focusRing: { shadow: 'inset 0 0 0 4px #d4fedc' } }, + colorScheme: {}, + }) + expect(compiled.semantic.dark).toStrictEqual(compiled.semantic.light) + expect(compiled.components.light.demo).toStrictEqual({ + root: { + focusRing: { + width: 4, + style: 'none', + color: '#d4fedc', + offset: 0, + shadow: 'inset 0 0 0 4px #d4fedc', + }, + }, + }) + expect(compiled.components.dark).toStrictEqual(compiled.components.light) + }) + test('отклоняет источник без одной из цветовых схем semantic', () => { const source: TokenTree = { primitive: {}, @@ -351,6 +405,23 @@ describe('production input tokens', () => { expect(serialized).not.toMatch(/-?\d*\.?\d+(?:rem|ms)\b/) }) + test('экспортирует focusRing без изменения его структуры', () => { + expect(compiled.semantic.light).toHaveProperty( + 'effects.focusRing.shadow', + 'inset 0 0 0 4px #d4fedc' + ) + expect(compiled.components.light).toHaveProperty( + 'accordion.header.focusRing', + { + width: 4, + style: 'none', + color: '#d4fedc', + offset: 0, + shadow: 'inset 0 0 0 4px #d4fedc', + } + ) + }) + test('совпадает с закоммиченными сгенерированными токенами', () => { expect(findGeneratedTokenIssues(compiled, TOKENS_DIRECTORY)).toStrictEqual({ missing: [], diff --git a/src/theme/tokens/README.md b/src/theme/tokens/README.md index 3badaaae..c702dde1 100644 --- a/src/theme/tokens/README.md +++ b/src/theme/tokens/README.md @@ -7,3 +7,7 @@ `design-tokens/input/tokens.json` и не редактируется вручную. Подробности: [генератор токенов](../../../scripts/token-generator/README.md). + +`focusRing` сохраняет структуру входных токенов. При `style: "none"` компонент +не применяет `width`, `color` и `offset` как outline-свойства, но может +использовать независимый `shadow` как `boxShadow`. From 4f7b4e32a6993a0d9cc572d8b983511f27e4e9bf Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Fri, 31 Jul 2026 13:49:08 +0300 Subject: [PATCH 08/60] =?UTF-8?q?feat:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=BA=D0=B0=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=B0=D0=BD=D0=B8=D0=BC=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 +++ scripts/token-generator/README.md | 15 +++- .../__tests__/compiler.test.ts | 75 +++++++++++++++++++ scripts/token-generator/core/normalization.ts | 52 +++++++++++++ scripts/token-generator/core/validation.ts | 6 +- src/index.ts | 2 + src/theme/__tests__/tokenAdapters.test.ts | 11 +++ src/theme/index.ts | 1 + src/theme/tokenAdapters.ts | 15 ++++ src/theme/tokens/README.md | 8 ++ src/theme/tokens/semantic/dark.json | 20 ++--- src/theme/tokens/semantic/light.json | 20 ++--- 12 files changed, 211 insertions(+), 25 deletions(-) create mode 100644 src/theme/__tests__/tokenAdapters.test.ts create mode 100644 src/theme/tokenAdapters.ts diff --git a/README.md b/README.md index b74edb56..1b382f18 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,17 @@ UI kit использует следующие виды шрифтов. ``` +## Токены анимации + +Длительность анимации хранится в теме числом в миллисекундах. Easing-токен +нужно передать в Reanimated через публичный адаптер: + +```ts +import { toEasing } from '@cdek-it/react-native-ui-kit' + +const easing = toEasing(theme.semantic.effects.transition.easing.standard) +``` + ## Dependencies Для использования данной библиотеки необходимо: diff --git a/scripts/token-generator/README.md b/scripts/token-generator/README.md index ebfd2493..5894c4b8 100644 --- a/scripts/token-generator/README.md +++ b/scripts/token-generator/README.md @@ -61,13 +61,10 @@ Light- и dark-файлы должны иметь одинаковую стру ## Преобразование значений Ссылки разрешаются до нормализации. Поддерживаются ссылки на всё значение и -вставки внутри строк: +вставки внутри поддерживаемых shorthand и `boxShadow`: ```text "{dimension.space.400}" -> "0.875rem" -> 14 - -"inset 0 0 0 {dimension.focusRing.width} {colors.solid.green.200}" --> "inset 0 0 0 4px #d4fedc" ``` ```text @@ -80,6 +77,16 @@ Light- и dark-файлы должны иметь одинаковую стру Числовые строки преобразуются в числа, включая `fontWeight`. +Animation duration преобразуется из `ms` в число. Easing записывается как +коэффициенты для `Easing.bezier`: + +```text +"linear" -> { x1: 0, y1: 0, x2: 1, y2: 1 } +"cubic-bezier(0.2, 0, 0, 1)" -> { x1: 0.2, y1: 0, x2: 0, y2: 1 } +``` + +Коэффициенты `x1` и `x2` должны находиться в диапазоне от `0` до `1`. + CSS shorthand из 2–4 значений раскрывается в поля React Native: ```text diff --git a/scripts/token-generator/__tests__/compiler.test.ts b/scripts/token-generator/__tests__/compiler.test.ts index 19c3c036..a32d2611 100644 --- a/scripts/token-generator/__tests__/compiler.test.ts +++ b/scripts/token-generator/__tests__/compiler.test.ts @@ -17,6 +17,7 @@ import { import { compileTokens } from '../core/compiler' import { convertUnit, + normalizeEasing, normalizeTree, parseBoxShorthand, } from '../core/normalization' @@ -67,6 +68,56 @@ const containsColorSchemeThemeBranch = (node: TokenValue): boolean => { } describe('token compiler', () => { + describe('normalizeEasing', () => { + test.each([ + { + name: 'linear', + value: 'linear', + expected: { x1: 0, y1: 0, x2: 1, y2: 1 }, + }, + { + name: 'cubic-bezier', + value: 'cubic-bezier(0.2, 0, 0, 1)', + expected: { x1: 0.2, y1: 0, x2: 0, y2: 1 }, + }, + { + name: 'spring с y больше единицы', + value: 'cubic-bezier(0.34, 1.56, 0.64, 1)', + expected: { x1: 0.34, y1: 1.56, x2: 0.64, y2: 1 }, + }, + ])('$name преобразуется в коэффициенты', ({ value, expected }) => { + expect(normalizeEasing(value)).toStrictEqual(expected) + }) + + test('отклоняет неподдерживаемый формат', () => { + expect(() => normalizeEasing('ease-in')).toThrow('Unsupported easing') + }) + + test('отклоняет объект вместо easing-строки при нормализации дерева', () => { + expect(() => + normalizeTree( + { + effects: { + transition: { easing: { standard: { unexpected: 'value' } } }, + }, + }, + 'semantic' + ) + ).toThrow( + 'Expected easing string at "semantic.effects.transition.easing.standard"' + ) + }) + + test.each([ + { name: 'x1 меньше нуля', value: 'cubic-bezier(-0.1, 0, 1, 1)' }, + { name: 'x2 больше единицы', value: 'cubic-bezier(0, 0, 1.1, 1)' }, + ])('$name отклоняется', ({ value }) => { + expect(() => normalizeEasing(value)).toThrow( + 'Easing x coordinates must be between 0 and 1' + ) + }) + }) + describe('convertUnit', () => { test.each([ { name: 'положительный rem', value: '1.5rem', expected: 24 }, @@ -405,6 +456,30 @@ describe('production input tokens', () => { expect(serialized).not.toMatch(/-?\d*\.?\d+(?:rem|ms)\b/) }) + test('преобразует animation-токены в runtime-формат', () => { + expect(compiled.semantic.light).toHaveProperty( + 'effects.transition.easing.linear', + { x1: 0, y1: 0, x2: 1, y2: 1 } + ) + expect(compiled.semantic.dark).toHaveProperty( + 'effects.transition.easing.spring', + { x1: 0.34, y1: 1.56, x2: 0.64, y2: 1 } + ) + expect(compiled.semantic.light).toHaveProperty( + 'effects.transition.duration.200', + 180 + ) + expect(compiled.components.light).toHaveProperty( + 'button.root.transitionDuration', + 180 + ) + expect(compiled.components.dark).toHaveProperty( + 'toggleswitch.root.slideDuration', + 180 + ) + expect(JSON.stringify(compiled)).not.toMatch(/cubic-bezier\s*\(/) + }) + test('экспортирует focusRing без изменения его структуры', () => { expect(compiled.semantic.light).toHaveProperty( 'effects.focusRing.shadow', diff --git a/scripts/token-generator/core/normalization.ts b/scripts/token-generator/core/normalization.ts index dbde5671..ee351b77 100644 --- a/scripts/token-generator/core/normalization.ts +++ b/scripts/token-generator/core/normalization.ts @@ -7,13 +7,61 @@ import { } from './types' const REM_BASE = 16 +const NUMBER_SOURCE = '[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)' const NUMBER_PATTERN = /^-?\d*\.?\d+$/ const PIXEL_PATTERN = /^-?\d*\.?\d+px$/ const SHADOW_LENGTH_PATTERN = /^(?:0|-?\d*\.?\d+(?:rem|px))$/ +const CUBIC_BEZIER_PATTERN = new RegExp( + `^cubic-bezier\\(\\s*(${NUMBER_SOURCE})\\s*,\\s*(${NUMBER_SOURCE})\\s*,\\s*(${NUMBER_SOURCE})\\s*,\\s*(${NUMBER_SOURCE})\\s*\\)$` +) export const BOX_PROPERTIES = ['padding', 'margin', 'borderWidth'] as const export type BoxProperty = (typeof BOX_PROPERTIES)[number] +export const isEasingTokenPath = (tokenPath: string): boolean => + /\.effects\.transition\.easing\.[^.]+$/.test(tokenPath) + +export const normalizeEasing = ( + value: TokenValue, + tokenPath = 'semantic.effects.transition.easing' +): TokenTree => { + if (typeof value !== 'string') { + throw new Error(`Expected easing string at "${tokenPath}"`) + } + + const easing = value.trim() + + if (easing === 'linear') return { x1: 0, y1: 0, x2: 1, y2: 1 } + + const match = CUBIC_BEZIER_PATTERN.exec(easing) + + if (!match) { + throw new Error(`Unsupported easing "${value}" at "${tokenPath}"`) + } + + const [, x1Source, y1Source, x2Source, y2Source] = match + const coordinates = [x1Source, y1Source, x2Source, y2Source].map(Number) + const [x1, y1, x2, y2] = coordinates + + if ( + coordinates.some((coordinate) => !Number.isFinite(coordinate)) || + x1 === undefined || + y1 === undefined || + x2 === undefined || + y2 === undefined + ) { + throw new Error(`Invalid easing "${value}" at "${tokenPath}"`) + } + + if (x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) { + throw new Error( + `Easing x coordinates must be between 0 and 1 at "${tokenPath}"` + ) + } + + return { x1, y1, x2, y2 } +} + export const isBoxShadowValue = (value: string): boolean => { const parts = value .trim() @@ -178,6 +226,10 @@ export const normalizeTree = ( node: TokenValue, tokenPath = 'root' ): TokenValue => { + if (isEasingTokenPath(tokenPath)) { + return normalizeEasing(node, tokenPath) + } + if (Array.isArray(node)) { return node.map((item, index) => normalizeTree(item, `${tokenPath}.${index}`) diff --git a/scripts/token-generator/core/validation.ts b/scripts/token-generator/core/validation.ts index 7923ad75..d93dcdec 100644 --- a/scripts/token-generator/core/validation.ts +++ b/scripts/token-generator/core/validation.ts @@ -1,5 +1,6 @@ import { BOX_PROPERTIES, + isEasingTokenPath, isBoxShadowValue, type BoxProperty, } from './normalization' @@ -9,6 +10,7 @@ const REFERENCE_PATTERN = /\{[^}]+\}/ const UNCONVERTED_UNIT_PATTERN = /-?\d*\.?\d+(?:rem|ms)\b/ const PIXEL_PATTERN = /-?\d*\.?\d+px\b/ const NUMERIC_STRING_PATTERN = /^-?\d*\.?\d+$/ +const CUBIC_BEZIER_PATTERN = /cubic-bezier\s*\(/ export const assertValidOutput = ( node: TokenValue, @@ -47,7 +49,9 @@ export const assertValidOutput = ( REFERENCE_PATTERN.test(node) || UNCONVERTED_UNIT_PATTERN.test(node) || (PIXEL_PATTERN.test(node) && !isBoxShadowValue(node)) || - NUMERIC_STRING_PATTERN.test(node) + NUMERIC_STRING_PATTERN.test(node) || + CUBIC_BEZIER_PATTERN.test(node) || + (node === 'linear' && isEasingTokenPath(tokenPath)) if (hasUnconvertedValue) { throw new Error(`Unconverted token "${node}" at "${tokenPath}"`) diff --git a/src/index.ts b/src/index.ts index 0a2d5231..35bfb92a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,7 +8,9 @@ export { ThemeVariant, darkTheme, lightTheme, + toEasing, type ThemeType, + type EasingToken, type FontsConfig, type FontsConfigType, type ThemeContextProviderProps, diff --git a/src/theme/__tests__/tokenAdapters.test.ts b/src/theme/__tests__/tokenAdapters.test.ts new file mode 100644 index 00000000..f11c67b4 --- /dev/null +++ b/src/theme/__tests__/tokenAdapters.test.ts @@ -0,0 +1,11 @@ +import { toEasing } from '../tokenAdapters' + +describe('toEasing', () => { + test('создаёт Reanimated easing из коэффициентов токена', () => { + const easing = toEasing({ x1: 0, y1: 0, x2: 1, y2: 1 }).factory() + + expect(easing(0)).toBe(0) + expect(easing(0.5)).toBeCloseTo(0.5) + expect(easing(1)).toBe(1) + }) +}) diff --git a/src/theme/index.ts b/src/theme/index.ts index f1312be7..d00250c0 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -1,5 +1,6 @@ export { darkTheme } from './darkTheme' export { lightTheme } from './lightTheme' +export { toEasing, type EasingToken } from './tokenAdapters' export { ThemeContext, ThemeContextProvider, diff --git a/src/theme/tokenAdapters.ts b/src/theme/tokenAdapters.ts new file mode 100644 index 00000000..855e15e8 --- /dev/null +++ b/src/theme/tokenAdapters.ts @@ -0,0 +1,15 @@ +import { Easing, type EasingFunctionFactory } from 'react-native-reanimated' + +export interface EasingToken { + readonly x1: number + readonly y1: number + readonly x2: number + readonly y2: number +} + +export const toEasing = ({ + x1, + y1, + x2, + y2, +}: EasingToken): EasingFunctionFactory => Easing.bezier(x1, y1, x2, y2) diff --git a/src/theme/tokens/README.md b/src/theme/tokens/README.md index c702dde1..0d61579b 100644 --- a/src/theme/tokens/README.md +++ b/src/theme/tokens/README.md @@ -11,3 +11,11 @@ `focusRing` сохраняет структуру входных токенов. При `style: "none"` компонент не применяет `width`, `color` и `offset` как outline-свойства, но может использовать независимый `shadow` как `boxShadow`. + +Для передачи easing в Reanimated используйте адаптер: + +```ts +import { toEasing } from '@cdek-it/react-native-ui-kit' + +const easing = toEasing(theme.semantic.effects.transition.easing.standard) +``` diff --git a/src/theme/tokens/semantic/dark.json b/src/theme/tokens/semantic/dark.json index 57ea1bc0..32086ae3 100644 --- a/src/theme/tokens/semantic/dark.json +++ b/src/theme/tokens/semantic/dark.json @@ -312,16 +312,16 @@ "blur": { "100": 4, "200": 8, "300": 16, "400": 24, "none": 0 }, "transition": { "easing": { - "linear": "linear", - "in": "cubic-bezier(0.55, 0.06, 0.7, 0.2)", - "out": "cubic-bezier(0.2, 0.6, 0.4, 1)", - "inOut": "cubic-bezier(0.65, 0.05, 0.35, 1)", - "standard": "cubic-bezier(0.2, 0, 0, 1)", - "accelerate": "cubic-bezier(0.3, 0, 1, 1)", - "decelerate": "cubic-bezier(0, 0, 0, 1)", - "emphasizedAccelerate": "cubic-bezier(0.3, 0, 0.8, 0.15)", - "emphasizedDecelerate": "cubic-bezier(0.05, 0.7, 0.1, 1)", - "spring": "cubic-bezier(0.34, 1.56, 0.64, 1)" + "linear": { "x1": 0, "y1": 0, "x2": 1, "y2": 1 }, + "in": { "x1": 0.55, "y1": 0.06, "x2": 0.7, "y2": 0.2 }, + "out": { "x1": 0.2, "y1": 0.6, "x2": 0.4, "y2": 1 }, + "inOut": { "x1": 0.65, "y1": 0.05, "x2": 0.35, "y2": 1 }, + "standard": { "x1": 0.2, "y1": 0, "x2": 0, "y2": 1 }, + "accelerate": { "x1": 0.3, "y1": 0, "x2": 1, "y2": 1 }, + "decelerate": { "x1": 0, "y1": 0, "x2": 0, "y2": 1 }, + "emphasizedAccelerate": { "x1": 0.3, "y1": 0, "x2": 0.8, "y2": 0.15 }, + "emphasizedDecelerate": { "x1": 0.05, "y1": 0.7, "x2": 0.1, "y2": 1 }, + "spring": { "x1": 0.34, "y1": 1.56, "x2": 0.64, "y2": 1 } }, "duration": { "100": 140, "200": 180, "300": 240, "400": 320, "500": 400 } }, diff --git a/src/theme/tokens/semantic/light.json b/src/theme/tokens/semantic/light.json index 0ba6a30c..b3ff8316 100644 --- a/src/theme/tokens/semantic/light.json +++ b/src/theme/tokens/semantic/light.json @@ -312,16 +312,16 @@ "blur": { "100": 4, "200": 8, "300": 16, "400": 24, "none": 0 }, "transition": { "easing": { - "linear": "linear", - "in": "cubic-bezier(0.55, 0.06, 0.7, 0.2)", - "out": "cubic-bezier(0.2, 0.6, 0.4, 1)", - "inOut": "cubic-bezier(0.65, 0.05, 0.35, 1)", - "standard": "cubic-bezier(0.2, 0, 0, 1)", - "accelerate": "cubic-bezier(0.3, 0, 1, 1)", - "decelerate": "cubic-bezier(0, 0, 0, 1)", - "emphasizedAccelerate": "cubic-bezier(0.3, 0, 0.8, 0.15)", - "emphasizedDecelerate": "cubic-bezier(0.05, 0.7, 0.1, 1)", - "spring": "cubic-bezier(0.34, 1.56, 0.64, 1)" + "linear": { "x1": 0, "y1": 0, "x2": 1, "y2": 1 }, + "in": { "x1": 0.55, "y1": 0.06, "x2": 0.7, "y2": 0.2 }, + "out": { "x1": 0.2, "y1": 0.6, "x2": 0.4, "y2": 1 }, + "inOut": { "x1": 0.65, "y1": 0.05, "x2": 0.35, "y2": 1 }, + "standard": { "x1": 0.2, "y1": 0, "x2": 0, "y2": 1 }, + "accelerate": { "x1": 0.3, "y1": 0, "x2": 1, "y2": 1 }, + "decelerate": { "x1": 0, "y1": 0, "x2": 0, "y2": 1 }, + "emphasizedAccelerate": { "x1": 0.3, "y1": 0, "x2": 0.8, "y2": 0.15 }, + "emphasizedDecelerate": { "x1": 0.05, "y1": 0.7, "x2": 0.1, "y2": 1 }, + "spring": { "x1": 0.34, "y1": 1.56, "x2": 0.64, "y2": 1 } }, "duration": { "100": 140, "200": 180, "300": 240, "400": 320, "500": 400 } }, From acc97ec103e1ecf7ba51a06d9414e9cc794225ad Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Mon, 3 Aug 2026 18:24:48 +0300 Subject: [PATCH 09/60] =?UTF-8?q?feat:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=20=D1=88=D1=80=D0=B8=D1=84=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/README.md | 2 +- scripts/token-generator/README.md | 11 +++-- .../__tests__/compiler.test.ts | 44 +++++++++++++----- scripts/token-generator/core/compiler.ts | 22 ++++++++- scripts/token-generator/core/types.ts | 1 + scripts/token-generator/io.ts | 2 + src/theme/tokens/README.md | 10 +++-- src/theme/tokens/fonts.json | 45 +++++++++++++++++++ 8 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 src/theme/tokens/fonts.json diff --git a/design-tokens/README.md b/design-tokens/README.md index 73d1cf5c..a7592028 100644 --- a/design-tokens/README.md +++ b/design-tokens/README.md @@ -1,6 +1,6 @@ # Design tokens `input/tokens.json` содержит входные токены из Figma, из которых генерируются -light- и dark-токены проекта. +light- и dark-токены проекта, а также общий `fonts.json`. Подробности: [генератор токенов](../scripts/token-generator/README.md). diff --git a/scripts/token-generator/README.md b/scripts/token-generator/README.md index 5894c4b8..cc2dd9e8 100644 --- a/scripts/token-generator/README.md +++ b/scripts/token-generator/README.md @@ -31,10 +31,11 @@ Semantic-токены доступны потребителям библиоте ## Результат генерации -Из `design-tokens/input/tokens.json` создаются четыре файла: +Из `design-tokens/input/tokens.json` создаются пять файлов: ```text src/theme/tokens +├── fonts.json ├── semantic │ ├── light.json │ └── dark.json @@ -55,8 +56,12 @@ components.button.colorScheme.light.outlined → components/light.json: button.colorScheme.outlined ``` -`primitive` нужен только для подстановки ссылок и не записывается в результат. -Light- и dark-файлы должны иметь одинаковую структуру и типы значений. +`fonts.json` собирается из `primitive.fonts`, нормализуется по общим правилам и +не разделяется по цветовым схемам. Пока файл не экспортируется из библиотеки. + +Остальная часть `primitive` нужна только для подстановки ссылок и не +записывается в результат. Light- и dark-файлы должны иметь одинаковую структуру +и типы значений. ## Преобразование значений diff --git a/scripts/token-generator/__tests__/compiler.test.ts b/scripts/token-generator/__tests__/compiler.test.ts index a32d2611..63b1d8fa 100644 --- a/scripts/token-generator/__tests__/compiler.test.ts +++ b/scripts/token-generator/__tests__/compiler.test.ts @@ -49,6 +49,12 @@ const listJsonFiles = (directory: string, prefix = ''): string[] => }) .sort() +const expectedOutputFiles = [ + OUTPUT_FILES.fonts, + ...Object.values(OUTPUT_FILES.semantic), + ...Object.values(OUTPUT_FILES.components), +].sort() + const containsColorSchemeThemeBranch = (node: TokenValue): boolean => { if (Array.isArray(node)) return node.some(containsColorSchemeThemeBranch) @@ -238,6 +244,11 @@ describe('token compiler', () => { test('разделяет один источник на темы, разрешает ссылки и нормализует значения', () => { const source: TokenTree = { primitive: { + fonts: { + fontFamily: { base: 'Noto Sans' }, + fontWeight: { regular: '400' }, + fontSize: { base: '1rem' }, + }, sizing: { small: '0.5rem', base: '1rem' }, motion: { fast: '150ms' }, }, @@ -273,6 +284,11 @@ describe('token compiler', () => { const compiled = compileTokens(source) expect(compiled).not.toHaveProperty('primitive') + expect(compiled.fonts).toStrictEqual({ + fontFamily: { base: 'Noto Sans' }, + fontWeight: { regular: 400 }, + fontSize: { base: 16 }, + }) expect(compiled.semantic).toStrictEqual({ light: { colorScheme: { color: { text: '#111111' } }, @@ -318,6 +334,7 @@ describe('token compiler', () => { test('сохраняет focusRing и нормализует его значения', () => { const source: TokenTree = { primitive: { + fonts: {}, sizing: { focusRing: '0.25rem' }, colors: { focus: '#d4fedc' }, }, @@ -371,7 +388,7 @@ describe('token compiler', () => { test('отклоняет источник без одной из цветовых схем semantic', () => { const source: TokenTree = { - primitive: {}, + primitive: { fonts: {} }, semantic: { colorScheme: { light: {} } }, components: {}, } @@ -402,8 +419,12 @@ describe('production input tokens', () => { expect(tokenFiles).toStrictEqual(['tokens.json']) }) - test('не экспортирует primitive и убирает разделение тем из colorScheme', () => { - expect(Object.keys(compiled)).toStrictEqual(['semantic', 'components']) + test('экспортирует fonts без primitive и убирает темы из colorScheme', () => { + expect(Object.keys(compiled)).toStrictEqual([ + 'fonts', + 'semantic', + 'components', + ]) expect(compiled).not.toHaveProperty('primitive') const inputComponents = source.components @@ -440,13 +461,18 @@ describe('production input tokens', () => { ).toHaveLength(0) }) + test('собирает и нормализует primitive.fonts без цветовой схемы', () => { + expect(compiled.fonts).toHaveProperty('fontFamily.base', 'Noto Sans') + expect(compiled.fonts).toHaveProperty('fontWeight.demibold', 600) + expect(compiled.fonts).toHaveProperty('fontSize.300', 16) + expect(compiled.fonts).toHaveProperty('lineHeight.auto', 'auto') + expect(compiled.fonts).toHaveProperty('letterSpacing.400', -0.48) + }) + test('содержит только целевые файлы', () => { const tokenFiles = listJsonFiles(TOKENS_DIRECTORY) - const expectedFiles = Object.values(OUTPUT_FILES) - .flatMap((group) => Object.values(group)) - .sort() - expect(tokenFiles).toStrictEqual(expectedFiles) + expect(tokenFiles).toStrictEqual(expectedOutputFiles) }) test('не содержит неразрешённых ссылок и CSS-единиц', () => { @@ -545,9 +571,7 @@ describe('production input tokens', () => { writeGeneratedTokens(compiled, temporaryDirectory) expect(listJsonFiles(temporaryDirectory)).toStrictEqual( - Object.values(OUTPUT_FILES) - .flatMap((group) => Object.values(group)) - .sort() + expectedOutputFiles ) expect( findGeneratedTokenIssues(compiled, temporaryDirectory) diff --git a/scripts/token-generator/core/compiler.ts b/scripts/token-generator/core/compiler.ts index 1c57644a..240e471f 100644 --- a/scripts/token-generator/core/compiler.ts +++ b/scripts/token-generator/core/compiler.ts @@ -43,6 +43,25 @@ const getGroup = ( return value } +const compileFonts = (primitive: TokenTree): TokenTree => { + const fonts = resolvePath(primitive, 'fonts') + + if (!isTokenTree(fonts)) { + throw new Error('Expected an object at "primitive.fonts" in input tokens') + } + + const resolvedFonts = resolveReferences(fonts, primitive, 'fonts') + const normalizedFonts = normalizeTree(resolvedFonts, 'fonts') + + if (!isTokenTree(normalizedFonts)) { + throw new Error('Expected an object at "fonts" in output tokens') + } + + assertValidOutput(normalizedFonts, 'fonts') + + return normalizedFonts +} + const selectColorScheme = ( group: TokenTree, scheme: ColorScheme, @@ -184,6 +203,7 @@ export const compileTokens = (source: TokenTree): CompiledTokens => { const primitive = getGroup(source, 'primitive') const semanticSource = getGroup(source, 'semantic') const componentsSource = getGroup(source, 'components') + const fonts = compileFonts(primitive) const light = compileScheme( primitive, semanticSource, @@ -202,5 +222,5 @@ export const compileTokens = (source: TokenTree): CompiledTokens => { assertSameShape(semantic.light, semantic.dark) assertSameShape(components.light, components.dark) - return { semantic, components } + return { fonts, semantic, components } } diff --git a/scripts/token-generator/core/types.ts b/scripts/token-generator/core/types.ts index 2c98a251..216aaa8a 100644 --- a/scripts/token-generator/core/types.ts +++ b/scripts/token-generator/core/types.ts @@ -13,6 +13,7 @@ export interface BoxEdges { } export interface CompiledTokens { + fonts: TokenTree semantic: ThemeTokens components: ThemeTokens } diff --git a/scripts/token-generator/io.ts b/scripts/token-generator/io.ts index 301d159c..074eb8ce 100644 --- a/scripts/token-generator/io.ts +++ b/scripts/token-generator/io.ts @@ -13,6 +13,7 @@ import { isDeepStrictEqual } from 'node:util' import { isTokenTree, type CompiledTokens, type TokenTree } from './core/types' export const OUTPUT_FILES = { + fonts: 'fonts.json', semantic: { light: join('semantic', 'light.json'), dark: join('semantic', 'dark.json'), @@ -45,6 +46,7 @@ export const renderJson = (value: TokenTree): string => const outputEntries = ( compiled: CompiledTokens ): Array<[string, TokenTree]> => [ + [OUTPUT_FILES.fonts, compiled.fonts], [OUTPUT_FILES.semantic.light, compiled.semantic.light], [OUTPUT_FILES.semantic.dark, compiled.semantic.dark], [OUTPUT_FILES.components.light, compiled.components.light], diff --git a/src/theme/tokens/README.md b/src/theme/tokens/README.md index 0d61579b..e3d127f2 100644 --- a/src/theme/tokens/README.md +++ b/src/theme/tokens/README.md @@ -1,10 +1,12 @@ # Сгенерированные токены `semantic` подключается к темам как `ThemeType.semantic`. `components` хранит -внутренние токены компонентов для `ThemeType.components`. В сгенерированных -файлах нет `primitive`; `colorScheme` содержит только выбранную ветку без -вложенных `light` и `dark`. Всё генерируется из -`design-tokens/input/tokens.json` и не редактируется вручную. +внутренние токены компонентов для `ThemeType.components`. `fonts.json` содержит +общие для цветовых схем токены из `primitive.fonts`, но пока не подключён к теме +и не экспортируется из библиотеки. Остальная часть `primitive` не записывается; +`colorScheme` содержит только выбранную ветку без вложенных `light` и `dark`. +Всё генерируется из `design-tokens/input/tokens.json` и не редактируется +вручную. Подробности: [генератор токенов](../../../scripts/token-generator/README.md). diff --git a/src/theme/tokens/fonts.json b/src/theme/tokens/fonts.json new file mode 100644 index 00000000..bec6ffbc --- /dev/null +++ b/src/theme/tokens/fonts.json @@ -0,0 +1,45 @@ +{ + "fontFamily": { "base": "Noto Sans", "heading": "TT Fellows" }, + "fontWeight": { "regular": 400, "medium": 500, "demibold": 600, "bold": 700 }, + "fontSize": { + "100": 12, + "200": 14, + "300": 16, + "400": 18, + "500": 20, + "600": 24, + "650": 30, + "700": 36, + "750": 48, + "800": 60, + "900": 72, + "1000": 96 + }, + "lineHeight": { + "100": 12, + "150": 14, + "200": 14, + "250": 16, + "300": 18, + "350": 18, + "400": 20, + "450": 22, + "500": 24, + "550": 26, + "600": 28, + "700": 30, + "800": 36, + "850": 38, + "900": 44, + "1000": 54, + "none": 1, + "auto": "auto" + }, + "letterSpacing": { + "200": -0.32, + "400": -0.48, + "500": 0, + "600": 0.32, + "700": 0.48 + } +} From 7782938a6eafc1fa901a46f371905df5a8f0729e Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 12:25:57 +0300 Subject: [PATCH 10/60] =?UTF-8?q?refactor(tokens):=20=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D1=8B=20semantic-=D1=82=D0=BE?= =?UTF-8?q?=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +- scripts/token-generator/README.md | 28 +- .../__tests__/compiler.test.ts | 76 ++-- scripts/token-generator/core/compiler.ts | 52 ++- scripts/token-generator/core/types.ts | 8 +- scripts/token-generator/io.ts | 17 +- src/index.ts | 2 + src/theme/__tests__/ThemeContext.test.tsx | 20 +- src/theme/darkTheme.ts | 4 +- src/theme/index.ts | 1 + src/theme/lightTheme.ts | 4 +- src/theme/tokens/README.md | 18 +- src/theme/tokens/index.ts | 6 + .../tokens/semantic/colorScheme/dark.json | 228 ++++++++++++ .../tokens/semantic/colorScheme/light.json | 228 ++++++++++++ src/theme/tokens/semantic/dark.json | 346 ------------------ src/theme/tokens/semantic/dimensions.json | 65 ++++ src/theme/tokens/semantic/effects.json | 51 +++ src/theme/tokens/semantic/light.json | 346 ------------------ src/theme/types.ts | 4 +- 20 files changed, 749 insertions(+), 763 deletions(-) create mode 100644 src/theme/tokens/index.ts create mode 100644 src/theme/tokens/semantic/colorScheme/dark.json create mode 100644 src/theme/tokens/semantic/colorScheme/light.json delete mode 100644 src/theme/tokens/semantic/dark.json create mode 100644 src/theme/tokens/semantic/dimensions.json create mode 100644 src/theme/tokens/semantic/effects.json delete mode 100644 src/theme/tokens/semantic/light.json diff --git a/README.md b/README.md index 1b382f18..4460ccdb 100644 --- a/README.md +++ b/README.md @@ -162,13 +162,13 @@ UI kit использует следующие виды шрифтов. ## Токены анимации -Длительность анимации хранится в теме числом в миллисекундах. Easing-токен -нужно передать в Reanimated через публичный адаптер: +Длительность анимации хранится в `semanticTokens` числом в миллисекундах. +Easing-токен нужно передать в Reanimated через публичный адаптер: ```ts -import { toEasing } from '@cdek-it/react-native-ui-kit' +import { semanticTokens, toEasing } from '@cdek-it/react-native-ui-kit' -const easing = toEasing(theme.semantic.effects.transition.easing.standard) +const easing = toEasing(semanticTokens.effects.transition.easing.standard) ``` ## Dependencies diff --git a/scripts/token-generator/README.md b/scripts/token-generator/README.md index cc2dd9e8..29b8a12f 100644 --- a/scripts/token-generator/README.md +++ b/scripts/token-generator/README.md @@ -26,36 +26,46 @@ StyleSheet.create(({ components }) => ({ })) ``` -Semantic-токены доступны потребителям библиотеки в `semantic`. Unistyles -подставляет соответствующие light- или dark-токены при переключении темы. +В `semantic` темы находится только `colorScheme`: Unistyles подставляет +соответствующие light- или dark-токены при переключении темы. Не зависящие от +темы `dimension` и `effects` доступны в статическом `semanticTokens`. ## Результат генерации -Из `design-tokens/input/tokens.json` создаются пять файлов: +Из `design-tokens/input/tokens.json` создаются семь файлов: ```text src/theme/tokens ├── fonts.json ├── semantic -│ ├── light.json -│ └── dark.json +│ ├── colorScheme +│ │ ├── light.json +│ │ └── dark.json +│ ├── dimensions.json +│ └── effects.json └── components ├── light.json └── dark.json ``` -Для каждого выходного файла выбирается соответствующая ветка `colorScheme.light` -или `colorScheme.dark`. Ключ `colorScheme` сохраняется, а уровень `light`/`dark` -удаляется: +Для `semantic/colorScheme` и component-файлов выбирается соответствующая ветка +`colorScheme.light` или `colorScheme.dark`, а уровень `light`/`dark` удаляется. +Semantic-файл подключается в тему как `semantic.colorScheme`; в component-файлах +ключ `colorScheme` сохраняется: ```text semantic.colorScheme.light.color -→ semantic/light.json: colorScheme.color +→ semantic/colorScheme/light.json: color components.button.colorScheme.light.outlined → components/light.json: button.colorScheme.outlined ``` +`semantic.dimension` записывается в `semantic/dimensions.json`, а +`semantic.effects` — в `semantic/effects.json`. Эти секции генерируются один раз +и не входят в тему. Если их итоговые значения зависят от `colorScheme`, +генератор завершится с ошибкой. + `fonts.json` собирается из `primitive.fonts`, нормализуется по общим правилам и не разделяется по цветовым схемам. Пока файл не экспортируется из библиотеки. diff --git a/scripts/token-generator/__tests__/compiler.test.ts b/scripts/token-generator/__tests__/compiler.test.ts index 63b1d8fa..7d68397e 100644 --- a/scripts/token-generator/__tests__/compiler.test.ts +++ b/scripts/token-generator/__tests__/compiler.test.ts @@ -51,7 +51,9 @@ const listJsonFiles = (directory: string, prefix = ''): string[] => const expectedOutputFiles = [ OUTPUT_FILES.fonts, - ...Object.values(OUTPUT_FILES.semantic), + ...Object.values(OUTPUT_FILES.semantic.colorScheme), + OUTPUT_FILES.semantic.dimensions, + OUTPUT_FILES.semantic.effects, ...Object.values(OUTPUT_FILES.components), ].sort() @@ -290,16 +292,12 @@ describe('token compiler', () => { fontSize: { base: 16 }, }) expect(compiled.semantic).toStrictEqual({ - light: { - colorScheme: { color: { text: '#111111' } }, - dimension: { spacing: { small: 8, base: 16 } }, - effects: { duration: 150 }, - }, - dark: { - colorScheme: { color: { text: '#eeeeee' } }, - dimension: { spacing: { small: 8, base: 16 } }, - effects: { duration: 150 }, + colorScheme: { + light: { color: { text: '#111111' } }, + dark: { color: { text: '#eeeeee' } }, }, + dimension: { spacing: { small: 8, base: 16 } }, + effects: { duration: 150 }, }) expect(compiled.components.light).toStrictEqual({ demo: { @@ -366,12 +364,11 @@ describe('token compiler', () => { const compiled = compileTokens(source) - expect(compiled.semantic.light).toStrictEqual({ + expect(compiled.semantic).toStrictEqual({ + colorScheme: { light: {}, dark: {} }, dimension: { focusRing: { width: 4, offset: 0 } }, effects: { focusRing: { shadow: 'inset 0 0 0 4px #d4fedc' } }, - colorScheme: {}, }) - expect(compiled.semantic.dark).toStrictEqual(compiled.semantic.light) expect(compiled.components.light.demo).toStrictEqual({ root: { focusRing: { @@ -398,6 +395,25 @@ describe('token compiler', () => { ) }) + test('отклоняет общие semantic-токены, зависящие от цветовой схемы', () => { + const source: TokenTree = { + primitive: { fonts: {} }, + semantic: { + colorScheme: { + light: { color: { spacing: '1rem' } }, + dark: { color: { spacing: '2rem' } }, + }, + dimension: { spacing: '{color.spacing}' }, + effects: {}, + }, + components: {}, + } + + expect(() => compileTokens(source)).toThrow( + 'Semantic "dimension" tokens must not depend on colorScheme' + ) + }) + test('отклоняет циклические ссылки', () => { const references: TokenTree = { first: '{second}', second: '{first}' } @@ -449,12 +465,12 @@ describe('production input tokens', () => { expect(lightOutputComponents.button).toHaveProperty('root') expect(lightOutputComponents.button).toHaveProperty('colorScheme') expect(darkOutputComponents.button).toHaveProperty('colorScheme') - expect(compiled.semantic.light).toHaveProperty('colorScheme.color') - expect(compiled.semantic.dark).toHaveProperty('colorScheme.color') + expect(compiled.semantic.colorScheme.light).toHaveProperty('color') + expect(compiled.semantic.colorScheme.dark).toHaveProperty('color') expect( [ - compiled.semantic.light, - compiled.semantic.dark, + compiled.semantic.colorScheme.light, + compiled.semantic.colorScheme.dark, compiled.components.light, compiled.components.dark, ].filter(containsColorSchemeThemeBranch) @@ -483,16 +499,16 @@ describe('production input tokens', () => { }) test('преобразует animation-токены в runtime-формат', () => { - expect(compiled.semantic.light).toHaveProperty( - 'effects.transition.easing.linear', + expect(compiled.semantic.effects).toHaveProperty( + 'transition.easing.linear', { x1: 0, y1: 0, x2: 1, y2: 1 } ) - expect(compiled.semantic.dark).toHaveProperty( - 'effects.transition.easing.spring', + expect(compiled.semantic.effects).toHaveProperty( + 'transition.easing.spring', { x1: 0.34, y1: 1.56, x2: 0.64, y2: 1 } ) - expect(compiled.semantic.light).toHaveProperty( - 'effects.transition.duration.200', + expect(compiled.semantic.effects).toHaveProperty( + 'transition.duration.200', 180 ) expect(compiled.components.light).toHaveProperty( @@ -507,8 +523,8 @@ describe('production input tokens', () => { }) test('экспортирует focusRing без изменения его структуры', () => { - expect(compiled.semantic.light).toHaveProperty( - 'effects.focusRing.shadow', + expect(compiled.semantic.effects).toHaveProperty( + 'focusRing.shadow', 'inset 0 0 0 4px #d4fedc' ) expect(compiled.components.light).toHaveProperty( @@ -532,9 +548,9 @@ describe('production input tokens', () => { }) test('преобразует числовые RN-значения', () => { - expect(compiled.semantic.light).toHaveProperty('dimension.depth.100', 1000) - expect(compiled.semantic.light).toHaveProperty('effects.opacity.4', 0.04) - expect(compiled.semantic.light).toHaveProperty('effects.blur.100', 4) + expect(compiled.semantic.dimension).toHaveProperty('depth.100', 1000) + expect(compiled.semantic.effects).toHaveProperty('opacity.4', 0.04) + expect(compiled.semantic.effects).toHaveProperty('blur.100', 4) expect(compiled.components.light).toHaveProperty( 'button.root.label.fontWeight', 600 @@ -564,8 +580,8 @@ describe('production input tokens', () => { const temporaryDirectory = mkdtempSync(join(tmpdir(), 'token-generator-')) const unexpectedFile = join(temporaryDirectory, 'common.json') const preservedFile = join(temporaryDirectory, 'README.md') - const missingFile = OUTPUT_FILES.semantic.dark - const changedFile = OUTPUT_FILES.semantic.light + const missingFile = OUTPUT_FILES.semantic.colorScheme.dark + const changedFile = OUTPUT_FILES.semantic.dimensions try { writeGeneratedTokens(compiled, temporaryDirectory) diff --git a/scripts/token-generator/core/compiler.ts b/scripts/token-generator/core/compiler.ts index 240e471f..4dfe18c0 100644 --- a/scripts/token-generator/core/compiler.ts +++ b/scripts/token-generator/core/compiler.ts @@ -1,9 +1,12 @@ +import { isDeepStrictEqual } from 'node:util' + import { normalizeTree } from './normalization' import { resolveReferences } from './resolution' import { mergeTrees, resolvePath } from './tree' import { isTokenTree, type CompiledTokens, + type SemanticTokens, type ThemeTokens, type TokenTree, type TokenValue, @@ -199,6 +202,46 @@ const compileScheme = ( } } +const getSemanticGroup = ( + semantic: TokenTree, + group: 'colorScheme' | 'dimension' | 'effects', + scheme: ColorScheme +): TokenTree => { + const value = semantic[group] + + if (!isTokenTree(value)) { + throw new Error(`Expected an object at "${scheme}.semantic.${group}"`) + } + + return value +} + +const splitSemantic = (light: TokenTree, dark: TokenTree): SemanticTokens => { + const dimension = getSemanticGroup(light, 'dimension', 'light') + const darkDimension = getSemanticGroup(dark, 'dimension', 'dark') + const effects = getSemanticGroup(light, 'effects', 'light') + const darkEffects = getSemanticGroup(dark, 'effects', 'dark') + + if (!isDeepStrictEqual(dimension, darkDimension)) { + throw new Error( + 'Semantic "dimension" tokens must not depend on colorScheme' + ) + } + + if (!isDeepStrictEqual(effects, darkEffects)) { + throw new Error('Semantic "effects" tokens must not depend on colorScheme') + } + + return { + colorScheme: { + light: getSemanticGroup(light, 'colorScheme', 'light'), + dark: getSemanticGroup(dark, 'colorScheme', 'dark'), + }, + dimension, + effects, + } +} + export const compileTokens = (source: TokenTree): CompiledTokens => { const primitive = getGroup(source, 'primitive') const semanticSource = getGroup(source, 'semantic') @@ -216,11 +259,14 @@ export const compileTokens = (source: TokenTree): CompiledTokens => { componentsSource, 'dark' ) - const semantic = { light: light.semantic, dark: dark.semantic } const components = { light: light.components, dark: dark.components } - assertSameShape(semantic.light, semantic.dark) + assertSameShape(light.semantic, dark.semantic) assertSameShape(components.light, components.dark) - return { fonts, semantic, components } + return { + fonts, + semantic: splitSemantic(light.semantic, dark.semantic), + components, + } } diff --git a/scripts/token-generator/core/types.ts b/scripts/token-generator/core/types.ts index 216aaa8a..89522e41 100644 --- a/scripts/token-generator/core/types.ts +++ b/scripts/token-generator/core/types.ts @@ -14,10 +14,16 @@ export interface BoxEdges { export interface CompiledTokens { fonts: TokenTree - semantic: ThemeTokens + semantic: SemanticTokens components: ThemeTokens } +export interface SemanticTokens { + colorScheme: ThemeTokens + dimension: TokenTree + effects: TokenTree +} + export interface ThemeTokens { light: TokenTree dark: TokenTree diff --git a/scripts/token-generator/io.ts b/scripts/token-generator/io.ts index 074eb8ce..bcf07389 100644 --- a/scripts/token-generator/io.ts +++ b/scripts/token-generator/io.ts @@ -15,8 +15,12 @@ import { isTokenTree, type CompiledTokens, type TokenTree } from './core/types' export const OUTPUT_FILES = { fonts: 'fonts.json', semantic: { - light: join('semantic', 'light.json'), - dark: join('semantic', 'dark.json'), + colorScheme: { + light: join('semantic', 'colorScheme', 'light.json'), + dark: join('semantic', 'colorScheme', 'dark.json'), + }, + dimensions: join('semantic', 'dimensions.json'), + effects: join('semantic', 'effects.json'), }, components: { light: join('components', 'light.json'), @@ -47,8 +51,13 @@ const outputEntries = ( compiled: CompiledTokens ): Array<[string, TokenTree]> => [ [OUTPUT_FILES.fonts, compiled.fonts], - [OUTPUT_FILES.semantic.light, compiled.semantic.light], - [OUTPUT_FILES.semantic.dark, compiled.semantic.dark], + [ + OUTPUT_FILES.semantic.colorScheme.light, + compiled.semantic.colorScheme.light, + ], + [OUTPUT_FILES.semantic.colorScheme.dark, compiled.semantic.colorScheme.dark], + [OUTPUT_FILES.semantic.dimensions, compiled.semantic.dimension], + [OUTPUT_FILES.semantic.effects, compiled.semantic.effects], [OUTPUT_FILES.components.light, compiled.components.light], [OUTPUT_FILES.components.dark, compiled.components.dark], ] diff --git a/src/index.ts b/src/index.ts index 35bfb92a..12678ece 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,7 +8,9 @@ export { ThemeVariant, darkTheme, lightTheme, + semanticTokens, toEasing, + type SemanticTokens, type ThemeType, type EasingToken, type FontsConfig, diff --git a/src/theme/__tests__/ThemeContext.test.tsx b/src/theme/__tests__/ThemeContext.test.tsx index 0106d5ff..14499cc5 100644 --- a/src/theme/__tests__/ThemeContext.test.tsx +++ b/src/theme/__tests__/ThemeContext.test.tsx @@ -6,10 +6,13 @@ import { UnistylesRuntime } from 'react-native-unistyles' import { ThemeContextProvider } from '../ThemeContext' import { darkTheme } from '../darkTheme' import { lightTheme } from '../lightTheme' +import { semanticTokens } from '../tokens' import darkComponentTokens from '../tokens/components/dark.json' import lightComponentTokens from '../tokens/components/light.json' -import darkSemanticTokens from '../tokens/semantic/dark.json' -import lightSemanticTokens from '../tokens/semantic/light.json' +import darkSemanticColorSchemeTokens from '../tokens/semantic/colorScheme/dark.json' +import lightSemanticColorSchemeTokens from '../tokens/semantic/colorScheme/light.json' +import semanticDimensions from '../tokens/semantic/dimensions.json' +import semanticEffects from '../tokens/semantic/effects.json' import { ThemeVariant } from '../types' describe('ThemeContextProvider', () => { @@ -72,9 +75,16 @@ describe('ThemeContextProvider', () => { expect(UnistylesRuntime.updateTheme).not.toHaveBeenCalled() }) - test('каждая тема содержит соответствующие semantic-токены', () => { - expect(lightTheme.semantic).toBe(lightSemanticTokens) - expect(darkTheme.semantic).toBe(darkSemanticTokens) + test('каждая тема содержит только соответствующую цветовую схему', () => { + expect(lightTheme.semantic.colorScheme).toBe(lightSemanticColorSchemeTokens) + expect(darkTheme.semantic.colorScheme).toBe(darkSemanticColorSchemeTokens) + expect(lightTheme.semantic).not.toHaveProperty('dimension') + expect(lightTheme.semantic).not.toHaveProperty('effects') + }) + + test('общие semantic-токены не зависят от темы', () => { + expect(semanticTokens.dimension).toBe(semanticDimensions) + expect(semanticTokens.effects).toBe(semanticEffects) }) test('каждая тема содержит соответствующие component-токены', () => { diff --git a/src/theme/darkTheme.ts b/src/theme/darkTheme.ts index aa8bf3f0..4cce3ec9 100644 --- a/src/theme/darkTheme.ts +++ b/src/theme/darkTheme.ts @@ -4,11 +4,11 @@ import { customDark } from './assets/customDark' import darkThemeAssets from './assets/themeDark.json' import { commonTheme } from './commonTheme' import darkComponentTokens from './tokens/components/dark.json' -import darkSemanticTokens from './tokens/semantic/dark.json' +import darkSemanticColorSchemeTokens from './tokens/semantic/colorScheme/dark.json' import type { ThemeType } from './types' export const darkTheme: ThemeType = { - semantic: darkSemanticTokens, + semantic: { colorScheme: darkSemanticColorSchemeTokens }, components: darkComponentTokens, theme: { ...darkThemeAssets, InputSize, ModalSize, custom: customDark }, ...commonTheme, diff --git a/src/theme/index.ts b/src/theme/index.ts index d00250c0..4266d324 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -1,6 +1,7 @@ export { darkTheme } from './darkTheme' export { lightTheme } from './lightTheme' export { toEasing, type EasingToken } from './tokenAdapters' +export { semanticTokens, type SemanticTokens } from './tokens' export { ThemeContext, ThemeContextProvider, diff --git a/src/theme/lightTheme.ts b/src/theme/lightTheme.ts index b91a6008..2abc1957 100644 --- a/src/theme/lightTheme.ts +++ b/src/theme/lightTheme.ts @@ -4,11 +4,11 @@ import { customLight } from './assets/customLight' import lightThemeAssets from './assets/themeLight.json' import { commonTheme } from './commonTheme' import lightComponentTokens from './tokens/components/light.json' -import lightSemanticTokens from './tokens/semantic/light.json' +import lightSemanticColorSchemeTokens from './tokens/semantic/colorScheme/light.json' import type { ThemeType } from './types' export const lightTheme: ThemeType = { - semantic: lightSemanticTokens, + semantic: { colorScheme: lightSemanticColorSchemeTokens }, components: lightComponentTokens, theme: { ...lightThemeAssets, InputSize, ModalSize, custom: customLight }, ...commonTheme, diff --git a/src/theme/tokens/README.md b/src/theme/tokens/README.md index e3d127f2..9cbee6d0 100644 --- a/src/theme/tokens/README.md +++ b/src/theme/tokens/README.md @@ -1,12 +1,12 @@ # Сгенерированные токены -`semantic` подключается к темам как `ThemeType.semantic`. `components` хранит -внутренние токены компонентов для `ThemeType.components`. `fonts.json` содержит -общие для цветовых схем токены из `primitive.fonts`, но пока не подключён к теме -и не экспортируется из библиотеки. Остальная часть `primitive` не записывается; -`colorScheme` содержит только выбранную ветку без вложенных `light` и `dark`. -Всё генерируется из `design-tokens/input/tokens.json` и не редактируется -вручную. +В `ThemeType.semantic` подключается только выбранный `colorScheme`. Общие +`dimension` и `effects` экспортируются как статический `semanticTokens`, поэтому +не участвуют в переключении темы. `components` хранит внутренние токены +компонентов для `ThemeType.components`. `fonts.json` содержит общие для цветовых +схем токены из `primitive.fonts`, но пока не подключён к теме и не +экспортируется из библиотеки. Всё генерируется из +`design-tokens/input/tokens.json` и не редактируется вручную. Подробности: [генератор токенов](../../../scripts/token-generator/README.md). @@ -17,7 +17,7 @@ Для передачи easing в Reanimated используйте адаптер: ```ts -import { toEasing } from '@cdek-it/react-native-ui-kit' +import { semanticTokens, toEasing } from '@cdek-it/react-native-ui-kit' -const easing = toEasing(theme.semantic.effects.transition.easing.standard) +const easing = toEasing(semanticTokens.effects.transition.easing.standard) ``` diff --git a/src/theme/tokens/index.ts b/src/theme/tokens/index.ts new file mode 100644 index 00000000..9344acc6 --- /dev/null +++ b/src/theme/tokens/index.ts @@ -0,0 +1,6 @@ +import dimensions from './semantic/dimensions.json' +import effects from './semantic/effects.json' + +export const semanticTokens = { dimension: dimensions, effects } as const + +export type SemanticTokens = typeof semanticTokens diff --git a/src/theme/tokens/semantic/colorScheme/dark.json b/src/theme/tokens/semantic/colorScheme/dark.json new file mode 100644 index 00000000..4ae11e18 --- /dev/null +++ b/src/theme/tokens/semantic/colorScheme/dark.json @@ -0,0 +1,228 @@ +{ + "color": { + "fg": { + "default": "#ffffff", + "hover": "#cecfd2", + "active": "#f0f0f1", + "focus": "#ffffff", + "muted": "#a2a5a9", + "subtle": "#a2a5a9", + "brand": { + "default": "#77f48a", + "hover": "#aafbb7", + "active": "#d4fedc", + "disabled": "#168322", + "visited": "#aafbb7", + "muted": "#44e858" + }, + "inverse": { + "default": "#2b2e33", + "hover": "#56595f", + "active": "#181a1f", + "focus": "#2b2e33", + "muted": "#85888e" + }, + "status": { + "danger": { + "default": "#f47f77", + "hover": "#fbacaa", + "active": "#fed4d4", + "disabled": "#8d2218", + "visited": "#fbacaa", + "muted": "#e85244" + }, + "info": { + "default": "#77baf4", + "hover": "#aad7fb", + "active": "#d4ecfe", + "disabled": "#18538d", + "visited": "#aad7fb", + "muted": "#4496e8" + }, + "warning": { + "default": "#facb75", + "hover": "#fddeaa", + "active": "#ffeed4", + "disabled": "#9d6d0e", + "visited": "#fddeaa", + "muted": "#f5b83d" + }, + "success": { + "default": "#77f48a", + "hover": "#aafbb7", + "active": "#d4fedc", + "disabled": "#168322", + "visited": "#aafbb7", + "muted": "#44e858" + }, + "help": { + "default": "#c084fc", + "hover": "#d8b4fe", + "active": "#e9d5ff", + "disabled": "#7e22ce", + "visited": "#d8b4fe", + "muted": "#a855f7" + } + }, + "on": { + "brand": { + "default": "#2b2e33", + "hover": "#2b2e33", + "active": "#2b2e33" + }, + "fill": { + "default": "#ffffff", + "hover": "#ffffff", + "active": "#ffffff", + "muted": "#e2e2e4" + }, + "status": { + "danger": { "default": "#fff0f0", "hover": "#fffafa" }, + "info": { "default": "#f0f9ff", "hover": "#fafdff" }, + "warning": { "default": "#fff9f0", "hover": "#fffdfa" }, + "success": { "default": "#f0fff3", "hover": "#fafffb" }, + "help": { "default": "#f3e8ff", "hover": "#faf5ff" } + } + } + }, + "bg": { + "status": { + "danger": { + "weak": { + "default": "#3b100c", + "hover": "#45120e", + "active": "#611912" + }, + "strong": { + "default": "#8d2218", + "hover": "#db3424", + "active": "#e85244" + } + }, + "info": { + "weak": { + "default": "#0c243b", + "hover": "#0e2a45", + "active": "#123a61" + }, + "strong": { + "default": "#18538d", + "hover": "#1e76cd", + "active": "#4496e8" + } + }, + "warning": { + "weak": { + "default": "#453008", + "hover": "#4f3709", + "active": "#6d4c0b" + }, + "strong": { + "default": "#9d6d0e", + "hover": "#dc9710", + "active": "#f5b83d" + } + }, + "success": { + "weak": { + "default": "#0c3b11", + "hover": "#0e4514", + "active": "#12611b" + }, + "strong": { + "default": "#168322", + "hover": "#1dc831", + "active": "#44e858" + } + }, + "help": { + "weak": { + "default": "#3b0764", + "hover": "#581c87", + "active": "#6b21a8" + }, + "strong": { + "default": "#7e22ce", + "hover": "#9333ea", + "active": "#a855f7" + } + } + }, + "brand": { + "weak": { "hover": "#0c3b11", "active": "#0e4514" }, + "strong": { + "default": "#44e858", + "hover": "#77f48a", + "active": "#aafbb7" + } + }, + "surface": { + "canvas": { + "default": "#2b2e33", + "hover": "#404348", + "active": "#56595f", + "selected": "#404348" + }, + "default": { + "default": "#404348", + "hover": "#56595f", + "active": "#6d7076", + "selected": "#56595f" + }, + "raised": { + "default": "#56595f", + "hover": "#6d7076", + "active": "#85888e", + "selected": "#6d7076" + }, + "overlay": { "default": "#404348", "hover": "#56595f" }, + "backdrop": "rgba(0, 0, 0, 0.6000)" + }, + "neutral": { + "weak": { + "default": "#2b2e33", + "hover": "#404348", + "active": "#56595f", + "disabled": "#404348" + }, + "medium": { + "default": "#404348", + "hover": "#56595f", + "active": "#6d7076", + "strong": "#85888e" + }, + "strong": { + "default": "#f0f0f1", + "hover": "#e2e2e4", + "active": "#cecfd2", + "selected": "#f0f0f1" + } + } + }, + "border": { + "focus": "#d4fedc", + "neutral": { + "default": "#404348", + "strong": "#56595f", + "bold": { "default": "#f0f0f1", "hover": "#e2e2e4" }, + "inverse": "#2b2e33" + }, + "brand": { + "subtle": "#12611b", + "default": "#44e858", + "strong": "#77f48a" + }, + "status": { + "danger": { + "subtle": "#db3424", + "default": "#e85244", + "strong": "#f47f77" + }, + "info": { "default": "#4496e8", "strong": "#77baf4" }, + "warning": { "default": "#f5b83d", "strong": "#facb75" }, + "success": { "default": "#44e858", "strong": "#77f48a" }, + "help": { "strong": "#c084fc" } + } + } + } +} diff --git a/src/theme/tokens/semantic/colorScheme/light.json b/src/theme/tokens/semantic/colorScheme/light.json new file mode 100644 index 00000000..695bff01 --- /dev/null +++ b/src/theme/tokens/semantic/colorScheme/light.json @@ -0,0 +1,228 @@ +{ + "color": { + "fg": { + "default": "#2b2e33", + "hover": "#56595f", + "active": "#181a1f", + "focus": "#2b2e33", + "muted": "#85888e", + "subtle": "#6d7076", + "brand": { + "default": "#44e858", + "hover": "#1dc831", + "active": "#168322", + "disabled": "#aafbb7", + "visited": "#12611b", + "muted": "#77f48a" + }, + "inverse": { + "default": "#ffffff", + "hover": "#ffffff", + "active": "#ffffff", + "focus": "#ffffff", + "muted": "rgba(255, 255, 255, 0.7000)" + }, + "status": { + "danger": { + "default": "#e85244", + "hover": "#db3424", + "active": "#8d2218", + "disabled": "#fbacaa", + "visited": "#611912", + "muted": "#f47f77" + }, + "info": { + "default": "#4496e8", + "hover": "#1e76cd", + "active": "#18538d", + "disabled": "#aad7fb", + "visited": "#123a61", + "muted": "#77baf4" + }, + "warning": { + "default": "#f5b83d", + "hover": "#dc9710", + "active": "#9d6d0e", + "disabled": "#fddeaa", + "visited": "#6d4c0b", + "muted": "#facb75" + }, + "success": { + "default": "#44e858", + "hover": "#1dc831", + "active": "#168322", + "disabled": "#aafbb7", + "visited": "#12611b", + "muted": "#77f48a" + }, + "help": { + "default": "#a855f7", + "hover": "#9333ea", + "active": "#7e22ce", + "disabled": "#d8b4fe", + "visited": "#6b21a8", + "muted": "#c084fc" + } + }, + "on": { + "brand": { + "default": "#2b2e33", + "hover": "#2b2e33", + "active": "#2b2e33" + }, + "fill": { + "default": "#ffffff", + "hover": "#ffffff", + "active": "#ffffff", + "muted": "#e2e2e4" + }, + "status": { + "danger": { "default": "#45120e", "hover": "#3b100c" }, + "info": { "default": "#0e2a45", "hover": "#0c243b" }, + "warning": { "default": "#4f3709", "hover": "#453008" }, + "success": { "default": "#0e4514", "hover": "#0c3b11" }, + "help": { "default": "#581c87", "hover": "#3b0764" } + } + } + }, + "bg": { + "status": { + "danger": { + "weak": { + "default": "#fffafa", + "hover": "#fff0f0", + "active": "#fed4d4" + }, + "strong": { + "default": "#fbacaa", + "hover": "#f47f77", + "active": "#e85244" + } + }, + "info": { + "weak": { + "default": "#fafdff", + "hover": "#f0f9ff", + "active": "#d4ecfe" + }, + "strong": { + "default": "#aad7fb", + "hover": "#77baf4", + "active": "#4496e8" + } + }, + "warning": { + "weak": { + "default": "#fffdfa", + "hover": "#fff9f0", + "active": "#ffeed4" + }, + "strong": { + "default": "#fddeaa", + "hover": "#facb75", + "active": "#f5b83d" + } + }, + "success": { + "weak": { + "default": "#fafffb", + "hover": "#f0fff3", + "active": "#d4fedc" + }, + "strong": { + "default": "#aafbb7", + "hover": "#77f48a", + "active": "#44e858" + } + }, + "help": { + "weak": { + "default": "#faf5ff", + "hover": "#f3e8ff", + "active": "#e9d5ff" + }, + "strong": { + "default": "#d8b4fe", + "hover": "#c084fc", + "active": "#a855f7" + } + } + }, + "brand": { + "weak": { "hover": "#fafffb", "active": "#f0fff3" }, + "strong": { + "default": "#44e858", + "hover": "#1dc831", + "active": "#168322" + } + }, + "surface": { + "canvas": { + "default": "#f0f0f1", + "hover": "#e2e2e4", + "active": "#cecfd2", + "selected": "#e2e2e4" + }, + "default": { + "default": "#ffffff", + "hover": "#fafafa", + "active": "#f0f0f1", + "selected": "#fafafa" + }, + "raised": { + "default": "#ffffff", + "hover": "#fafafa", + "active": "#f0f0f1", + "selected": "#fafafa" + }, + "overlay": { "default": "#ffffff", "hover": "#fafafa" }, + "backdrop": "rgba(0, 0, 0, 0.4000)" + }, + "neutral": { + "weak": { + "default": "#f0f0f1", + "hover": "#e2e2e4", + "active": "#cecfd2", + "disabled": "#e2e2e4" + }, + "medium": { + "default": "#e2e2e4", + "hover": "#cecfd2", + "active": "#a2a5a9", + "strong": "#85888e" + }, + "strong": { + "default": "#2b2e33", + "hover": "#404348", + "active": "#56595f", + "selected": "#2b2e33" + } + } + }, + "border": { + "focus": "#d4fedc", + "neutral": { + "default": "#e2e2e4", + "strong": "#cecfd2", + "bold": { "default": "#2b2e33", "hover": "#404348" }, + "inverse": "#ffffff" + }, + "brand": { + "subtle": "#d4fedc", + "default": "#44e858", + "strong": "#1dc831" + }, + "status": { + "danger": { + "subtle": "#f47f77", + "default": "#e85244", + "strong": "#db3424" + }, + "info": { "default": "#4496e8", "strong": "#1e76cd" }, + "warning": { "default": "#f5b83d", "strong": "#dc9710" }, + "success": { "default": "#44e858", "strong": "#1dc831" }, + "help": { "strong": "#9333ea" } + } + } + } +} diff --git a/src/theme/tokens/semantic/dark.json b/src/theme/tokens/semantic/dark.json deleted file mode 100644 index 32086ae3..00000000 --- a/src/theme/tokens/semantic/dark.json +++ /dev/null @@ -1,346 +0,0 @@ -{ - "colorScheme": { - "color": { - "fg": { - "default": "#ffffff", - "hover": "#cecfd2", - "active": "#f0f0f1", - "focus": "#ffffff", - "muted": "#a2a5a9", - "subtle": "#a2a5a9", - "brand": { - "default": "#77f48a", - "hover": "#aafbb7", - "active": "#d4fedc", - "disabled": "#168322", - "visited": "#aafbb7", - "muted": "#44e858" - }, - "inverse": { - "default": "#2b2e33", - "hover": "#56595f", - "active": "#181a1f", - "focus": "#2b2e33", - "muted": "#85888e" - }, - "status": { - "danger": { - "default": "#f47f77", - "hover": "#fbacaa", - "active": "#fed4d4", - "disabled": "#8d2218", - "visited": "#fbacaa", - "muted": "#e85244" - }, - "info": { - "default": "#77baf4", - "hover": "#aad7fb", - "active": "#d4ecfe", - "disabled": "#18538d", - "visited": "#aad7fb", - "muted": "#4496e8" - }, - "warning": { - "default": "#facb75", - "hover": "#fddeaa", - "active": "#ffeed4", - "disabled": "#9d6d0e", - "visited": "#fddeaa", - "muted": "#f5b83d" - }, - "success": { - "default": "#77f48a", - "hover": "#aafbb7", - "active": "#d4fedc", - "disabled": "#168322", - "visited": "#aafbb7", - "muted": "#44e858" - }, - "help": { - "default": "#c084fc", - "hover": "#d8b4fe", - "active": "#e9d5ff", - "disabled": "#7e22ce", - "visited": "#d8b4fe", - "muted": "#a855f7" - } - }, - "on": { - "brand": { - "default": "#2b2e33", - "hover": "#2b2e33", - "active": "#2b2e33" - }, - "fill": { - "default": "#ffffff", - "hover": "#ffffff", - "active": "#ffffff", - "muted": "#e2e2e4" - }, - "status": { - "danger": { "default": "#fff0f0", "hover": "#fffafa" }, - "info": { "default": "#f0f9ff", "hover": "#fafdff" }, - "warning": { "default": "#fff9f0", "hover": "#fffdfa" }, - "success": { "default": "#f0fff3", "hover": "#fafffb" }, - "help": { "default": "#f3e8ff", "hover": "#faf5ff" } - } - } - }, - "bg": { - "status": { - "danger": { - "weak": { - "default": "#3b100c", - "hover": "#45120e", - "active": "#611912" - }, - "strong": { - "default": "#8d2218", - "hover": "#db3424", - "active": "#e85244" - } - }, - "info": { - "weak": { - "default": "#0c243b", - "hover": "#0e2a45", - "active": "#123a61" - }, - "strong": { - "default": "#18538d", - "hover": "#1e76cd", - "active": "#4496e8" - } - }, - "warning": { - "weak": { - "default": "#453008", - "hover": "#4f3709", - "active": "#6d4c0b" - }, - "strong": { - "default": "#9d6d0e", - "hover": "#dc9710", - "active": "#f5b83d" - } - }, - "success": { - "weak": { - "default": "#0c3b11", - "hover": "#0e4514", - "active": "#12611b" - }, - "strong": { - "default": "#168322", - "hover": "#1dc831", - "active": "#44e858" - } - }, - "help": { - "weak": { - "default": "#3b0764", - "hover": "#581c87", - "active": "#6b21a8" - }, - "strong": { - "default": "#7e22ce", - "hover": "#9333ea", - "active": "#a855f7" - } - } - }, - "brand": { - "weak": { "hover": "#0c3b11", "active": "#0e4514" }, - "strong": { - "default": "#44e858", - "hover": "#77f48a", - "active": "#aafbb7" - } - }, - "surface": { - "canvas": { - "default": "#2b2e33", - "hover": "#404348", - "active": "#56595f", - "selected": "#404348" - }, - "default": { - "default": "#404348", - "hover": "#56595f", - "active": "#6d7076", - "selected": "#56595f" - }, - "raised": { - "default": "#56595f", - "hover": "#6d7076", - "active": "#85888e", - "selected": "#6d7076" - }, - "overlay": { "default": "#404348", "hover": "#56595f" }, - "backdrop": "rgba(0, 0, 0, 0.6000)" - }, - "neutral": { - "weak": { - "default": "#2b2e33", - "hover": "#404348", - "active": "#56595f", - "disabled": "#404348" - }, - "medium": { - "default": "#404348", - "hover": "#56595f", - "active": "#6d7076", - "strong": "#85888e" - }, - "strong": { - "default": "#f0f0f1", - "hover": "#e2e2e4", - "active": "#cecfd2", - "selected": "#f0f0f1" - } - } - }, - "border": { - "focus": "#d4fedc", - "neutral": { - "default": "#404348", - "strong": "#56595f", - "bold": { "default": "#f0f0f1", "hover": "#e2e2e4" }, - "inverse": "#2b2e33" - }, - "brand": { - "subtle": "#12611b", - "default": "#44e858", - "strong": "#77f48a" - }, - "status": { - "danger": { - "subtle": "#db3424", - "default": "#e85244", - "strong": "#f47f77" - }, - "info": { "default": "#4496e8", "strong": "#77baf4" }, - "warning": { "default": "#f5b83d", "strong": "#facb75" }, - "success": { "default": "#44e858", "strong": "#77f48a" }, - "help": { "strong": "#c084fc" } - } - } - } - }, - "dimension": { - "space": { - "100": 4, - "150": 6, - "200": 8, - "300": 10, - "400": 14, - "500": 18, - "600": 20, - "700": 24, - "800": 28, - "none": 0, - "negative": { "50": -2, "200": -8, "300": -12, "600": -24 } - }, - "size": { - "50": 2, - "100": 4, - "150": 6, - "200": 8, - "300": 10, - "350": 12, - "400": 14, - "450": 16, - "500": 18, - "600": 20, - "700": 24, - "750": 26, - "800": 28, - "900": 32, - "1000": 36, - "1100": 40, - "1200": 48, - "1300": 56, - "1400": 64, - "1500": 80, - "1600": 240, - "1700": 272, - "1800": 304, - "1900": 336, - "2000": 400, - "none": 0, - "max": 1600 - }, - "borderRadius": { - "100": 4, - "200": 8, - "300": 10, - "400": 14, - "500": 20, - "none": 0, - "max": 1600 - }, - "borderWidth": { "100": 1, "200": 2, "300": 4, "none": 0 }, - "focusRing": { "width": 4, "offset": 0 }, - "depth": { - "100": 1000, - "200": 1100, - "300": 1200, - "400": 1300, - "500": 1400, - "600": 1500, - "700": 1600 - }, - "viewport": { "100": 576, "200": 768, "300": 992, "400": 1200, "500": 1400 } - }, - "effects": { - "opacity": { - "0": 0, - "4": 0.04, - "8": 0.08, - "12": 0.12, - "16": 0.16, - "20": 0.2, - "30": 0.3, - "40": 0.4, - "50": 0.5, - "60": 0.6, - "70": 0.7, - "80": 0.8, - "90": 0.9, - "100": 1 - }, - "blur": { "100": 4, "200": 8, "300": 16, "400": 24, "none": 0 }, - "transition": { - "easing": { - "linear": { "x1": 0, "y1": 0, "x2": 1, "y2": 1 }, - "in": { "x1": 0.55, "y1": 0.06, "x2": 0.7, "y2": 0.2 }, - "out": { "x1": 0.2, "y1": 0.6, "x2": 0.4, "y2": 1 }, - "inOut": { "x1": 0.65, "y1": 0.05, "x2": 0.35, "y2": 1 }, - "standard": { "x1": 0.2, "y1": 0, "x2": 0, "y2": 1 }, - "accelerate": { "x1": 0.3, "y1": 0, "x2": 1, "y2": 1 }, - "decelerate": { "x1": 0, "y1": 0, "x2": 0, "y2": 1 }, - "emphasizedAccelerate": { "x1": 0.3, "y1": 0, "x2": 0.8, "y2": 0.15 }, - "emphasizedDecelerate": { "x1": 0.05, "y1": 0.7, "x2": 0.1, "y2": 1 }, - "spring": { "x1": 0.34, "y1": 1.56, "x2": 0.64, "y2": 1 } - }, - "duration": { "100": 140, "200": 180, "300": 240, "400": 320, "500": 400 } - }, - "elevation": { - "100": "0 0 2px rgba(0, 0, 0, 0.2000)", - "200": "0 0 4px rgba(0, 0, 0, 0.2000)", - "300": "0 2px 4px rgba(0, 0, 0, 0.2000)", - "400": "0 4px 8px rgba(0, 0, 0, 0.2000)", - "500": "0 8px 16px 0 rgba(0, 0, 0, 0.2000)", - "none": "none", - "status": { - "info": "0px 4px 8px 0px rgba(68, 150, 232, 0.04)", - "success": "0px 4px 8px 0px rgba(68, 232, 88, 0.04)", - "warning": "0px 4px 8px 0px rgba(245, 184, 61, 0.04)", - "danger": "0px 4px 8px 0px rgba(232, 82, 68, 0.04)", - "secondary": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)", - "contrast": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)" - } - }, - "focusRing": { "shadow": "inset 0 0 0 4px #d4fedc" } - } -} diff --git a/src/theme/tokens/semantic/dimensions.json b/src/theme/tokens/semantic/dimensions.json new file mode 100644 index 00000000..28c7802d --- /dev/null +++ b/src/theme/tokens/semantic/dimensions.json @@ -0,0 +1,65 @@ +{ + "space": { + "100": 4, + "150": 6, + "200": 8, + "300": 10, + "400": 14, + "500": 18, + "600": 20, + "700": 24, + "800": 28, + "none": 0, + "negative": { "50": -2, "200": -8, "300": -12, "600": -24 } + }, + "size": { + "50": 2, + "100": 4, + "150": 6, + "200": 8, + "300": 10, + "350": 12, + "400": 14, + "450": 16, + "500": 18, + "600": 20, + "700": 24, + "750": 26, + "800": 28, + "900": 32, + "1000": 36, + "1100": 40, + "1200": 48, + "1300": 56, + "1400": 64, + "1500": 80, + "1600": 240, + "1700": 272, + "1800": 304, + "1900": 336, + "2000": 400, + "none": 0, + "max": 1600 + }, + "borderRadius": { + "100": 4, + "200": 8, + "300": 10, + "400": 14, + "500": 20, + "none": 0, + "max": 1600 + }, + "borderWidth": { "100": 1, "200": 2, "300": 4, "none": 0 }, + "focusRing": { "width": 4, "offset": 0 }, + "depth": { + "100": 1000, + "200": 1100, + "300": 1200, + "400": 1300, + "500": 1400, + "600": 1500, + "700": 1600 + }, + "viewport": { "100": 576, "200": 768, "300": 992, "400": 1200, "500": 1400 } +} diff --git a/src/theme/tokens/semantic/effects.json b/src/theme/tokens/semantic/effects.json new file mode 100644 index 00000000..1a1a6294 --- /dev/null +++ b/src/theme/tokens/semantic/effects.json @@ -0,0 +1,51 @@ +{ + "opacity": { + "0": 0, + "4": 0.04, + "8": 0.08, + "12": 0.12, + "16": 0.16, + "20": 0.2, + "30": 0.3, + "40": 0.4, + "50": 0.5, + "60": 0.6, + "70": 0.7, + "80": 0.8, + "90": 0.9, + "100": 1 + }, + "blur": { "100": 4, "200": 8, "300": 16, "400": 24, "none": 0 }, + "transition": { + "easing": { + "linear": { "x1": 0, "y1": 0, "x2": 1, "y2": 1 }, + "in": { "x1": 0.55, "y1": 0.06, "x2": 0.7, "y2": 0.2 }, + "out": { "x1": 0.2, "y1": 0.6, "x2": 0.4, "y2": 1 }, + "inOut": { "x1": 0.65, "y1": 0.05, "x2": 0.35, "y2": 1 }, + "standard": { "x1": 0.2, "y1": 0, "x2": 0, "y2": 1 }, + "accelerate": { "x1": 0.3, "y1": 0, "x2": 1, "y2": 1 }, + "decelerate": { "x1": 0, "y1": 0, "x2": 0, "y2": 1 }, + "emphasizedAccelerate": { "x1": 0.3, "y1": 0, "x2": 0.8, "y2": 0.15 }, + "emphasizedDecelerate": { "x1": 0.05, "y1": 0.7, "x2": 0.1, "y2": 1 }, + "spring": { "x1": 0.34, "y1": 1.56, "x2": 0.64, "y2": 1 } + }, + "duration": { "100": 140, "200": 180, "300": 240, "400": 320, "500": 400 } + }, + "elevation": { + "100": "0 0 2px rgba(0, 0, 0, 0.2000)", + "200": "0 0 4px rgba(0, 0, 0, 0.2000)", + "300": "0 2px 4px rgba(0, 0, 0, 0.2000)", + "400": "0 4px 8px rgba(0, 0, 0, 0.2000)", + "500": "0 8px 16px 0 rgba(0, 0, 0, 0.2000)", + "none": "none", + "status": { + "info": "0px 4px 8px 0px rgba(68, 150, 232, 0.04)", + "success": "0px 4px 8px 0px rgba(68, 232, 88, 0.04)", + "warning": "0px 4px 8px 0px rgba(245, 184, 61, 0.04)", + "danger": "0px 4px 8px 0px rgba(232, 82, 68, 0.04)", + "secondary": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)", + "contrast": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)" + } + }, + "focusRing": { "shadow": "inset 0 0 0 4px #d4fedc" } +} diff --git a/src/theme/tokens/semantic/light.json b/src/theme/tokens/semantic/light.json deleted file mode 100644 index b3ff8316..00000000 --- a/src/theme/tokens/semantic/light.json +++ /dev/null @@ -1,346 +0,0 @@ -{ - "colorScheme": { - "color": { - "fg": { - "default": "#2b2e33", - "hover": "#56595f", - "active": "#181a1f", - "focus": "#2b2e33", - "muted": "#85888e", - "subtle": "#6d7076", - "brand": { - "default": "#44e858", - "hover": "#1dc831", - "active": "#168322", - "disabled": "#aafbb7", - "visited": "#12611b", - "muted": "#77f48a" - }, - "inverse": { - "default": "#ffffff", - "hover": "#ffffff", - "active": "#ffffff", - "focus": "#ffffff", - "muted": "rgba(255, 255, 255, 0.7000)" - }, - "status": { - "danger": { - "default": "#e85244", - "hover": "#db3424", - "active": "#8d2218", - "disabled": "#fbacaa", - "visited": "#611912", - "muted": "#f47f77" - }, - "info": { - "default": "#4496e8", - "hover": "#1e76cd", - "active": "#18538d", - "disabled": "#aad7fb", - "visited": "#123a61", - "muted": "#77baf4" - }, - "warning": { - "default": "#f5b83d", - "hover": "#dc9710", - "active": "#9d6d0e", - "disabled": "#fddeaa", - "visited": "#6d4c0b", - "muted": "#facb75" - }, - "success": { - "default": "#44e858", - "hover": "#1dc831", - "active": "#168322", - "disabled": "#aafbb7", - "visited": "#12611b", - "muted": "#77f48a" - }, - "help": { - "default": "#a855f7", - "hover": "#9333ea", - "active": "#7e22ce", - "disabled": "#d8b4fe", - "visited": "#6b21a8", - "muted": "#c084fc" - } - }, - "on": { - "brand": { - "default": "#2b2e33", - "hover": "#2b2e33", - "active": "#2b2e33" - }, - "fill": { - "default": "#ffffff", - "hover": "#ffffff", - "active": "#ffffff", - "muted": "#e2e2e4" - }, - "status": { - "danger": { "default": "#45120e", "hover": "#3b100c" }, - "info": { "default": "#0e2a45", "hover": "#0c243b" }, - "warning": { "default": "#4f3709", "hover": "#453008" }, - "success": { "default": "#0e4514", "hover": "#0c3b11" }, - "help": { "default": "#581c87", "hover": "#3b0764" } - } - } - }, - "bg": { - "status": { - "danger": { - "weak": { - "default": "#fffafa", - "hover": "#fff0f0", - "active": "#fed4d4" - }, - "strong": { - "default": "#fbacaa", - "hover": "#f47f77", - "active": "#e85244" - } - }, - "info": { - "weak": { - "default": "#fafdff", - "hover": "#f0f9ff", - "active": "#d4ecfe" - }, - "strong": { - "default": "#aad7fb", - "hover": "#77baf4", - "active": "#4496e8" - } - }, - "warning": { - "weak": { - "default": "#fffdfa", - "hover": "#fff9f0", - "active": "#ffeed4" - }, - "strong": { - "default": "#fddeaa", - "hover": "#facb75", - "active": "#f5b83d" - } - }, - "success": { - "weak": { - "default": "#fafffb", - "hover": "#f0fff3", - "active": "#d4fedc" - }, - "strong": { - "default": "#aafbb7", - "hover": "#77f48a", - "active": "#44e858" - } - }, - "help": { - "weak": { - "default": "#faf5ff", - "hover": "#f3e8ff", - "active": "#e9d5ff" - }, - "strong": { - "default": "#d8b4fe", - "hover": "#c084fc", - "active": "#a855f7" - } - } - }, - "brand": { - "weak": { "hover": "#fafffb", "active": "#f0fff3" }, - "strong": { - "default": "#44e858", - "hover": "#1dc831", - "active": "#168322" - } - }, - "surface": { - "canvas": { - "default": "#f0f0f1", - "hover": "#e2e2e4", - "active": "#cecfd2", - "selected": "#e2e2e4" - }, - "default": { - "default": "#ffffff", - "hover": "#fafafa", - "active": "#f0f0f1", - "selected": "#fafafa" - }, - "raised": { - "default": "#ffffff", - "hover": "#fafafa", - "active": "#f0f0f1", - "selected": "#fafafa" - }, - "overlay": { "default": "#ffffff", "hover": "#fafafa" }, - "backdrop": "rgba(0, 0, 0, 0.4000)" - }, - "neutral": { - "weak": { - "default": "#f0f0f1", - "hover": "#e2e2e4", - "active": "#cecfd2", - "disabled": "#e2e2e4" - }, - "medium": { - "default": "#e2e2e4", - "hover": "#cecfd2", - "active": "#a2a5a9", - "strong": "#85888e" - }, - "strong": { - "default": "#2b2e33", - "hover": "#404348", - "active": "#56595f", - "selected": "#2b2e33" - } - } - }, - "border": { - "focus": "#d4fedc", - "neutral": { - "default": "#e2e2e4", - "strong": "#cecfd2", - "bold": { "default": "#2b2e33", "hover": "#404348" }, - "inverse": "#ffffff" - }, - "brand": { - "subtle": "#d4fedc", - "default": "#44e858", - "strong": "#1dc831" - }, - "status": { - "danger": { - "subtle": "#f47f77", - "default": "#e85244", - "strong": "#db3424" - }, - "info": { "default": "#4496e8", "strong": "#1e76cd" }, - "warning": { "default": "#f5b83d", "strong": "#dc9710" }, - "success": { "default": "#44e858", "strong": "#1dc831" }, - "help": { "strong": "#9333ea" } - } - } - } - }, - "dimension": { - "space": { - "100": 4, - "150": 6, - "200": 8, - "300": 10, - "400": 14, - "500": 18, - "600": 20, - "700": 24, - "800": 28, - "none": 0, - "negative": { "50": -2, "200": -8, "300": -12, "600": -24 } - }, - "size": { - "50": 2, - "100": 4, - "150": 6, - "200": 8, - "300": 10, - "350": 12, - "400": 14, - "450": 16, - "500": 18, - "600": 20, - "700": 24, - "750": 26, - "800": 28, - "900": 32, - "1000": 36, - "1100": 40, - "1200": 48, - "1300": 56, - "1400": 64, - "1500": 80, - "1600": 240, - "1700": 272, - "1800": 304, - "1900": 336, - "2000": 400, - "none": 0, - "max": 1600 - }, - "borderRadius": { - "100": 4, - "200": 8, - "300": 10, - "400": 14, - "500": 20, - "none": 0, - "max": 1600 - }, - "borderWidth": { "100": 1, "200": 2, "300": 4, "none": 0 }, - "focusRing": { "width": 4, "offset": 0 }, - "depth": { - "100": 1000, - "200": 1100, - "300": 1200, - "400": 1300, - "500": 1400, - "600": 1500, - "700": 1600 - }, - "viewport": { "100": 576, "200": 768, "300": 992, "400": 1200, "500": 1400 } - }, - "effects": { - "opacity": { - "0": 0, - "4": 0.04, - "8": 0.08, - "12": 0.12, - "16": 0.16, - "20": 0.2, - "30": 0.3, - "40": 0.4, - "50": 0.5, - "60": 0.6, - "70": 0.7, - "80": 0.8, - "90": 0.9, - "100": 1 - }, - "blur": { "100": 4, "200": 8, "300": 16, "400": 24, "none": 0 }, - "transition": { - "easing": { - "linear": { "x1": 0, "y1": 0, "x2": 1, "y2": 1 }, - "in": { "x1": 0.55, "y1": 0.06, "x2": 0.7, "y2": 0.2 }, - "out": { "x1": 0.2, "y1": 0.6, "x2": 0.4, "y2": 1 }, - "inOut": { "x1": 0.65, "y1": 0.05, "x2": 0.35, "y2": 1 }, - "standard": { "x1": 0.2, "y1": 0, "x2": 0, "y2": 1 }, - "accelerate": { "x1": 0.3, "y1": 0, "x2": 1, "y2": 1 }, - "decelerate": { "x1": 0, "y1": 0, "x2": 0, "y2": 1 }, - "emphasizedAccelerate": { "x1": 0.3, "y1": 0, "x2": 0.8, "y2": 0.15 }, - "emphasizedDecelerate": { "x1": 0.05, "y1": 0.7, "x2": 0.1, "y2": 1 }, - "spring": { "x1": 0.34, "y1": 1.56, "x2": 0.64, "y2": 1 } - }, - "duration": { "100": 140, "200": 180, "300": 240, "400": 320, "500": 400 } - }, - "elevation": { - "100": "0 0 2px rgba(0, 0, 0, 0.2000)", - "200": "0 0 4px rgba(0, 0, 0, 0.2000)", - "300": "0 2px 4px rgba(0, 0, 0, 0.2000)", - "400": "0 4px 8px rgba(0, 0, 0, 0.2000)", - "500": "0 8px 16px 0 rgba(0, 0, 0, 0.2000)", - "none": "none", - "status": { - "info": "0px 4px 8px 0px rgba(68, 150, 232, 0.04)", - "success": "0px 4px 8px 0px rgba(68, 232, 88, 0.04)", - "warning": "0px 4px 8px 0px rgba(245, 184, 61, 0.04)", - "danger": "0px 4px 8px 0px rgba(232, 82, 68, 0.04)", - "secondary": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)", - "contrast": "0px 4px 8px 0px rgba(0, 0, 0, 0.0400)" - } - }, - "focusRing": { "shadow": "inset 0 0 0 4px #d4fedc" } - } -} diff --git a/src/theme/types.ts b/src/theme/types.ts index 7cc9d2dc..1c5056af 100644 --- a/src/theme/types.ts +++ b/src/theme/types.ts @@ -13,7 +13,7 @@ import type spacing from './assets/spacing.json' import type lightTheme from './assets/themeLight.json' import type typography from './assets/typography.json' import type lightComponentTokens from './tokens/components/light.json' -import type lightSemanticTokens from './tokens/semantic/light.json' +import type lightSemanticColorSchemeTokens from './tokens/semantic/colorScheme/light.json' export interface ThemeType { background: typeof background @@ -23,7 +23,7 @@ export interface ThemeType { global: typeof global sizing: typeof sizing spacing: typeof spacing - semantic: typeof lightSemanticTokens + semantic: { colorScheme: typeof lightSemanticColorSchemeTokens } components: typeof lightComponentTokens theme: typeof lightTheme & { custom: typeof customLight From 75ac64a791585186598f43f71906fec290398345 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 12:32:23 +0300 Subject: [PATCH 11/60] =?UTF-8?q?refactor(tokens):=20component-=D1=82?= =?UTF-8?q?=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B=20=D1=81=D0=BA=D1=80=D1=8B=D1=82?= =?UTF-8?q?=D1=8B=20=D0=B8=D0=B7=20=D0=BF=D1=83=D0=B1=D0=BB=D0=B8=D1=87?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/token-generator/README.md | 13 +++---------- src/theme/__tests__/ThemeContext.test.tsx | 8 +++----- src/theme/darkTheme.ts | 2 -- src/theme/lightTheme.ts | 2 -- src/theme/tokens/README.md | 6 +++--- src/theme/types.ts | 2 -- 6 files changed, 9 insertions(+), 24 deletions(-) diff --git a/scripts/token-generator/README.md b/scripts/token-generator/README.md index 29b8a12f..796dc9ed 100644 --- a/scripts/token-generator/README.md +++ b/scripts/token-generator/README.md @@ -14,17 +14,10 @@ результат. `tokens:validate` ничего не меняет: проверяет TypeScript генератора и актуальность сгенерированных токенов. -## Использование в компонентах +## Использование токенов -Внутри UI Kit используются component-токены: - -```ts -StyleSheet.create(({ components }) => ({ - header: { - backgroundColor: components.accordion.colorScheme.header.background, - }, -})) -``` +Component-токены предназначены только для реализации компонентов UI Kit. Они не +входят в темы и публичные экспорты библиотеки. В `semantic` темы находится только `colorScheme`: Unistyles подставляет соответствующие light- или dark-токены при переключении темы. Не зависящие от diff --git a/src/theme/__tests__/ThemeContext.test.tsx b/src/theme/__tests__/ThemeContext.test.tsx index 14499cc5..71425de8 100644 --- a/src/theme/__tests__/ThemeContext.test.tsx +++ b/src/theme/__tests__/ThemeContext.test.tsx @@ -7,8 +7,6 @@ import { ThemeContextProvider } from '../ThemeContext' import { darkTheme } from '../darkTheme' import { lightTheme } from '../lightTheme' import { semanticTokens } from '../tokens' -import darkComponentTokens from '../tokens/components/dark.json' -import lightComponentTokens from '../tokens/components/light.json' import darkSemanticColorSchemeTokens from '../tokens/semantic/colorScheme/dark.json' import lightSemanticColorSchemeTokens from '../tokens/semantic/colorScheme/light.json' import semanticDimensions from '../tokens/semantic/dimensions.json' @@ -87,8 +85,8 @@ describe('ThemeContextProvider', () => { expect(semanticTokens.effects).toBe(semanticEffects) }) - test('каждая тема содержит соответствующие component-токены', () => { - expect(lightTheme.components).toBe(lightComponentTokens) - expect(darkTheme.components).toBe(darkComponentTokens) + test('component-токены не входят в публичные темы', () => { + expect(lightTheme).not.toHaveProperty('components') + expect(darkTheme).not.toHaveProperty('components') }) }) diff --git a/src/theme/darkTheme.ts b/src/theme/darkTheme.ts index 4cce3ec9..bbc330fe 100644 --- a/src/theme/darkTheme.ts +++ b/src/theme/darkTheme.ts @@ -3,13 +3,11 @@ import { ModalSize } from './assets/ModalSize' import { customDark } from './assets/customDark' import darkThemeAssets from './assets/themeDark.json' import { commonTheme } from './commonTheme' -import darkComponentTokens from './tokens/components/dark.json' import darkSemanticColorSchemeTokens from './tokens/semantic/colorScheme/dark.json' import type { ThemeType } from './types' export const darkTheme: ThemeType = { semantic: { colorScheme: darkSemanticColorSchemeTokens }, - components: darkComponentTokens, theme: { ...darkThemeAssets, InputSize, ModalSize, custom: customDark }, ...commonTheme, fonts: { primary: 'TT Fellows', secondary: 'Noto Sans' }, diff --git a/src/theme/lightTheme.ts b/src/theme/lightTheme.ts index 2abc1957..e3c80bfb 100644 --- a/src/theme/lightTheme.ts +++ b/src/theme/lightTheme.ts @@ -3,13 +3,11 @@ import { ModalSize } from './assets/ModalSize' import { customLight } from './assets/customLight' import lightThemeAssets from './assets/themeLight.json' import { commonTheme } from './commonTheme' -import lightComponentTokens from './tokens/components/light.json' import lightSemanticColorSchemeTokens from './tokens/semantic/colorScheme/light.json' import type { ThemeType } from './types' export const lightTheme: ThemeType = { semantic: { colorScheme: lightSemanticColorSchemeTokens }, - components: lightComponentTokens, theme: { ...lightThemeAssets, InputSize, ModalSize, custom: customLight }, ...commonTheme, fonts: { primary: 'TT Fellows', secondary: 'Noto Sans' }, diff --git a/src/theme/tokens/README.md b/src/theme/tokens/README.md index 9cbee6d0..6547d0fb 100644 --- a/src/theme/tokens/README.md +++ b/src/theme/tokens/README.md @@ -3,9 +3,9 @@ В `ThemeType.semantic` подключается только выбранный `colorScheme`. Общие `dimension` и `effects` экспортируются как статический `semanticTokens`, поэтому не участвуют в переключении темы. `components` хранит внутренние токены -компонентов для `ThemeType.components`. `fonts.json` содержит общие для цветовых -схем токены из `primitive.fonts`, но пока не подключён к теме и не -экспортируется из библиотеки. Всё генерируется из +компонентов и не входит в темы или публичные экспорты. `fonts.json` содержит +общие для цветовых схем токены из `primitive.fonts`, но пока не подключён к теме +и не экспортируется из библиотеки. Всё генерируется из `design-tokens/input/tokens.json` и не редактируется вручную. Подробности: [генератор токенов](../../../scripts/token-generator/README.md). diff --git a/src/theme/types.ts b/src/theme/types.ts index 1c5056af..a73c9ea9 100644 --- a/src/theme/types.ts +++ b/src/theme/types.ts @@ -12,7 +12,6 @@ import type sizing from './assets/sizing.json' import type spacing from './assets/spacing.json' import type lightTheme from './assets/themeLight.json' import type typography from './assets/typography.json' -import type lightComponentTokens from './tokens/components/light.json' import type lightSemanticColorSchemeTokens from './tokens/semantic/colorScheme/light.json' export interface ThemeType { @@ -24,7 +23,6 @@ export interface ThemeType { sizing: typeof sizing spacing: typeof spacing semantic: { colorScheme: typeof lightSemanticColorSchemeTokens } - components: typeof lightComponentTokens theme: typeof lightTheme & { custom: typeof customLight InputSize: typeof InputSize From 5d374f051df70d66303cc47d3744133d34a756c4 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 12:49:45 +0300 Subject: [PATCH 12/60] =?UTF-8?q?docs:=20=D0=B0=D0=BA=D1=82=D1=83=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D1=82=D0=B5=D0=BC=20=D0=B8=20=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MIGRATION.md | 86 +++++++++++++++++------------------------ README.md | 5 +-- design-tokens/README.md | 2 +- 3 files changed, 37 insertions(+), 56 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 42303352..074c690b 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,18 +1,14 @@ # Миграция на Unistyles V3 -Стили переведены на `react-native-unistyles`. `ThemeContextProvider` доступен -как внешний конфигуратор тем и шрифтов, но чтение темы и шрифтов теперь идет -через API `unistyles`. +Стили переведены на `react-native-unistyles`. UI kit предоставляет провайдер и +хуки для настройки темы и шрифтов, а стили создаются через API `unistyles`. ## Изменения -### `ThemeContextProvider` — доступен +### Настройка темы и шрифтов -UI kit по-прежнему использует `react-native-unistyles` внутри, но для внешнего -потребителя снова доступен `ThemeContextProvider` как единая точка конфигурации -тем и шрифтов. - -Если приложению нужны кастомные шрифты, настройте их через провайдер: +Оберните приложение в `ThemeContextProvider`. Через `initialTheme` задаётся +начальная тема, через `fonts` — используемые семейства шрифтов: ```tsx import { @@ -30,18 +26,17 @@ export const Root = () => ( ) ``` -Провайдер также принимает `lightTheme` и `darkTheme`, если нужно передать -полностью кастомные темы. +Провайдер не принимает пользовательские объекты тем. Он настраивает +зарегистрированные внутри UI kit темы `light` и `dark`. ### `useFonts` -Используйте `useUnistyles`: +Для получения настроенных шрифтов используйте экспортируемый UI kit хук: ```tsx -import { useUnistyles } from '@cdek-it/react-native-ui-kit' +import { useFonts } from '@cdek-it/react-native-ui-kit' -const { theme } = useUnistyles() -theme.fonts +const fonts = useFonts() ``` Или прямо в стилях через `StyleSheet.create(...)`: @@ -54,25 +49,37 @@ const styles = StyleSheet.create(({ fonts }) => ({ })) ``` -### `useTheme()` / `useChangeTheme()` +### Чтение и переключение темы + +Для чтения и переключения темы используйте публичные хуки UI kit: + +```tsx +import { + ThemeVariant, + useChangeTheme, + useTheme, +} from '@cdek-it/react-native-ui-kit' + +const theme = useTheme() +const changeTheme = useChangeTheme() -`ThemeContextProvider` больше не является источником `theme/fonts` через React -context. Он только конфигурирует `react-native-unistyles`. +changeTheme(ThemeVariant.Dark) +``` -- `useTheme()` читает `UnistylesRuntime.themeName` -- `useFonts()` читает `useUnistyles().theme.fonts` -- `ThemeContext` остается пустым и имеет значение `null` -- `useChangeTheme()` всегда вызывает `UnistylesRuntime.setTheme(...)` +`ThemeContextProvider` не хранит тему и шрифты в React Context: `ThemeContext` +имеет значение `null`, а источником состояния остаётся Unistyles. ### `makeStyles` — removed Используйте `StyleSheet.create(...)`: ```tsx -import { StyleSheet } from '@cdek-it/react-native-ui-kit' +import { StyleSheet } from 'react-native-unistyles' -const styles = StyleSheet.create((theme) => ({ - container: { backgroundColor: theme.Button.Brand.buttonBg }, +const styles = StyleSheet.create(({ semantic }) => ({ + container: { + backgroundColor: semantic.colorScheme.color.bg.surface.default.default, + }, })) ``` @@ -80,32 +87,9 @@ const styles = StyleSheet.create((theme) => ({ темы. `StyleSheet.create(...)` — нативный путь, обновляет стили **без** ререндеров. -SDK реэкспортирует `StyleSheet`, `useUnistyles`, `UnistylesRuntime` и -`withUnistyles`, поэтому потребителям не нужно импортировать -`react-native-unistyles` напрямую. - -### `useTheme()` — removed - -```tsx -import { UnistylesRuntime, useUnistyles } from '@cdek-it/react-native-ui-kit' - -const themeName = UnistylesRuntime.themeName // 'light' | 'dark' -``` - -Для реактивного поведения используйте `useUnistyles()`: - -```tsx -const { rt } = useUnistyles() -rt.themeName -``` - -### `useChangeTheme()` — removed - -```tsx -import { UnistylesRuntime } from '@cdek-it/react-native-ui-kit' - -UnistylesRuntime.setTheme('dark') -``` +UI kit не реэкспортирует `StyleSheet`, `useUnistyles`, `UnistylesRuntime` и +`withUnistyles`. Если они нужны приложению напрямую, импортируйте их из +`react-native-unistyles`. ## ESLint Правила для Unistyles diff --git a/README.md b/README.md index 4460ccdb..b95d6112 100644 --- a/README.md +++ b/README.md @@ -54,12 +54,9 @@ UI kit использует следующие виды шрифтов. После этого шрифты доступны через `useUnistyles().theme.fonts` или прямо в `StyleSheet.create(({ fonts }) => ...)`. -`ThemeContextProvider` только настраивает темы и шрифты для `unistyles`. +`ThemeContextProvider` настраивает активную тему и шрифты для `unistyles`. `ThemeContext` остается пустым и всегда имеет значение `null`. -Провайдер также принимает `lightTheme` и `darkTheme`, если нужно переопределить -темы целиком. - ### Пример подключения шрифтов с помощью expo-fonts через плагин ```ts diff --git a/design-tokens/README.md b/design-tokens/README.md index a7592028..bba3daab 100644 --- a/design-tokens/README.md +++ b/design-tokens/README.md @@ -1,6 +1,6 @@ # Design tokens `input/tokens.json` содержит входные токены из Figma, из которых генерируются -light- и dark-токены проекта, а также общий `fonts.json`. +токены проекта. Подробности: [генератор токенов](../scripts/token-generator/README.md). From d1b0ee950b586129c46212cf085eb6f7be40c399 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 13:00:05 +0300 Subject: [PATCH 13/60] =?UTF-8?q?refactor(tokens):=20=D0=BE=D0=B1=D1=8A?= =?UTF-8?q?=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D1=8B=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20=D0=B8=20=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D0=B0=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/typecheck/action.yml | 10 ++-- lefthook.yml | 4 +- package.json | 6 +-- scripts/token-generator/README.md | 17 +++--- .../__tests__/compiler.test.ts | 32 +++++------ scripts/token-generator/build.ts | 12 ++--- scripts/token-generator/io.ts | 53 ++++++++++++------- 7 files changed, 74 insertions(+), 60 deletions(-) diff --git a/.github/actions/typecheck/action.yml b/.github/actions/typecheck/action.yml index 9c14c2dd..5b74884c 100644 --- a/.github/actions/typecheck/action.yml +++ b/.github/actions/typecheck/action.yml @@ -1,5 +1,5 @@ name: Run Typechecks -description: Typecheck the project and validate generated tokens +description: Typecheck the project and check generated tokens runs: using: composite @@ -10,6 +10,10 @@ runs: shell: bash run: yarn tsc --noEmit - - name: Validate Design Tokens + - name: Typecheck Token Generator shell: bash - run: yarn tokens:validate + run: yarn tokens:typecheck + + - name: Check Generated Tokens + shell: bash + run: yarn tokens:check diff --git a/lefthook.yml b/lefthook.yml index 1fa2a1e0..9f70f8e1 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -73,5 +73,5 @@ pre-push: run: yarn eslint . type-check: run: yarn tsc --noEmit - tokens-validate: - run: yarn tokens:validate + tokens-check: + run: yarn tokens:typecheck && yarn tokens:check diff --git a/package.json b/package.json index 9c265a7d..4957e810 100644 --- a/package.json +++ b/package.json @@ -31,17 +31,15 @@ } }, "scripts": { - "build": "yarn tokens:validate && rm -rf dist && tsc -p tsconfig.build.json", + "build": "yarn tokens:typecheck && yarn tokens:check && rm -rf dist && tsc -p tsconfig.build.json", "test": "jest", "start": "expo start --dev-client --clear", "android": "expo run:android", "ios": "expo run:ios --no-install", "storybook-generate": "sb-rn-get-stories --config-path .storybook && sed -i -e 's/export const view = global.view/export const view: ReturnType = global.view/' .storybook/storybook.requires.ts && prettier .storybook --write", - "tokens:generate": "ts-node --project scripts/token-generator/tsconfig.json scripts/token-generator/build.ts && yarn tokens:format", - "tokens:format": "prettier 'design-tokens/input/*.json' 'src/theme/tokens/**/*.json' --write", + "tokens:generate": "ts-node --project scripts/token-generator/tsconfig.json scripts/token-generator/build.ts", "tokens:check": "ts-node --transpile-only --project scripts/token-generator/tsconfig.json scripts/token-generator/build.ts --check", "tokens:typecheck": "tsc --noEmit -p scripts/token-generator/tsconfig.json", - "tokens:validate": "yarn tokens:typecheck && yarn tokens:check", "doctor": "expo-doctor", "check": "expo install --check", "lint:check": "eslint --cache .", diff --git a/scripts/token-generator/README.md b/scripts/token-generator/README.md index 796dc9ed..e179f802 100644 --- a/scripts/token-generator/README.md +++ b/scripts/token-generator/README.md @@ -7,12 +7,11 @@ 1. Обновить `design-tokens/input/tokens.json`. 2. Запустить `yarn tokens:generate`. 3. Проверить изменения в `src/theme/tokens`. -4. Запустить `yarn tokens:validate`. -5. Закоммитить входные и сгенерированные токены вместе. +4. Закоммитить входные и сгенерированные токены вместе. -`tokens:generate` нормализует значения, удаляет лишние JSON и записывает -результат. `tokens:validate` ничего не меняет: проверяет TypeScript генератора и -актуальность сгенерированных токенов. +`tokens:generate` сначала собирает и валидирует весь результат в памяти. При +ошибке файлы не изменяются. После успешной проверки команда удаляет лишние JSON +и записывает отформатированный результат. ## Использование токенов @@ -133,10 +132,10 @@ API 29. Fallback для более ранних версий намеренно ## Автоматические проверки -`yarn tokens:check` только проверяет файлы и отдельно показывает отсутствующие, -изменённые и лишние JSON. `yarn tokens:validate` дополнительно проверяет -TypeScript генератора. Если проверка не прошла, нужно выполнить -`yarn tokens:generate` и проверить diff. +`yarn tokens:check` ничего не изменяет и отдельно показывает отсутствующие, +изменённые и лишние JSON. `yarn tokens:typecheck` проверяет TypeScript-код +генератора. Обе команды запускаются при сборке и в CI. Если проверка файлов не +прошла, нужно выполнить `yarn tokens:generate` и проверить diff. ## Устройство генератора diff --git a/scripts/token-generator/__tests__/compiler.test.ts b/scripts/token-generator/__tests__/compiler.test.ts index 7d68397e..4094276c 100644 --- a/scripts/token-generator/__tests__/compiler.test.ts +++ b/scripts/token-generator/__tests__/compiler.test.ts @@ -539,12 +539,10 @@ describe('production input tokens', () => { ) }) - test('совпадает с закоммиченными сгенерированными токенами', () => { - expect(findGeneratedTokenIssues(compiled, TOKENS_DIRECTORY)).toStrictEqual({ - missing: [], - changed: [], - unexpected: [], - }) + test('совпадает с закоммиченными сгенерированными токенами', async () => { + await expect( + findGeneratedTokenIssues(compiled, TOKENS_DIRECTORY) + ).resolves.toStrictEqual({ missing: [], changed: [], unexpected: [] }) }) test('преобразует числовые RN-значения', () => { @@ -576,7 +574,7 @@ describe('production input tokens', () => { ) }) - test('check находит расхождения, а generate приводит файлы к актуальному состоянию', () => { + test('check находит расхождения, а generate приводит файлы к актуальному состоянию', async () => { const temporaryDirectory = mkdtempSync(join(tmpdir(), 'token-generator-')) const unexpectedFile = join(temporaryDirectory, 'common.json') const preservedFile = join(temporaryDirectory, 'README.md') @@ -584,23 +582,25 @@ describe('production input tokens', () => { const changedFile = OUTPUT_FILES.semantic.dimensions try { - writeGeneratedTokens(compiled, temporaryDirectory) + await writeGeneratedTokens(compiled, temporaryDirectory) expect(listJsonFiles(temporaryDirectory)).toStrictEqual( expectedOutputFiles ) - expect( + await expect( findGeneratedTokenIssues(compiled, temporaryDirectory) - ).toStrictEqual({ missing: [], changed: [], unexpected: [] }) + ).resolves.toStrictEqual({ missing: [], changed: [], unexpected: [] }) writeFileSync(unexpectedFile, '{}\n') writeFileSync(preservedFile, '# Generated tokens\n') rmSync(join(temporaryDirectory, missingFile)) - writeFileSync(join(temporaryDirectory, changedFile), '{}\n') + const changedPath = join(temporaryDirectory, changedFile) - expect( + writeFileSync(changedPath, JSON.stringify(loadTokenTree(changedPath))) + + await expect( findGeneratedTokenIssues(compiled, temporaryDirectory) - ).toStrictEqual({ + ).resolves.toStrictEqual({ missing: [missingFile], changed: [changedFile], unexpected: ['common.json'], @@ -608,11 +608,11 @@ describe('production input tokens', () => { expect(() => accessSync(unexpectedFile)).not.toThrow() expect(() => accessSync(preservedFile)).not.toThrow() - writeGeneratedTokens(compiled, temporaryDirectory) + await writeGeneratedTokens(compiled, temporaryDirectory) - expect( + await expect( findGeneratedTokenIssues(compiled, temporaryDirectory) - ).toStrictEqual({ missing: [], changed: [], unexpected: [] }) + ).resolves.toStrictEqual({ missing: [], changed: [], unexpected: [] }) expect(() => accessSync(unexpectedFile)).toThrow('ENOENT') expect(() => accessSync(preservedFile)).not.toThrow() } finally { diff --git a/scripts/token-generator/build.ts b/scripts/token-generator/build.ts index e689e838..3c8f2531 100644 --- a/scripts/token-generator/build.ts +++ b/scripts/token-generator/build.ts @@ -57,7 +57,7 @@ const formatTokenIssues = (issues: GeneratedTokenIssues): string => .filter(Boolean) .join('\n') -export const run = (arguments_: string[]): void => { +export const run = async (arguments_: string[]): Promise => { const options = parseArgs(arguments_) if (options.help) { @@ -69,7 +69,7 @@ export const run = (arguments_: string[]): void => { const compiled = compileInputTokens() if (options.check) { - const issues = findGeneratedTokenIssues(compiled, TOKENS_DIRECTORY) + const issues = await findGeneratedTokenIssues(compiled, TOKENS_DIRECTORY) const issueDescription = formatTokenIssues(issues) if (issueDescription) { @@ -84,16 +84,14 @@ export const run = (arguments_: string[]): void => { return } - writeGeneratedTokens(compiled, TOKENS_DIRECTORY) + await writeGeneratedTokens(compiled, TOKENS_DIRECTORY) console.log(`Сгенерированные токены записаны в ${TOKENS_DIRECTORY}`) } if (require.main === module) { - try { - run(process.argv.slice(2)) - } catch (error: unknown) { + void run(process.argv.slice(2)).catch((error: unknown) => { const message = error instanceof Error ? error.message : String(error) console.error(message) process.exitCode = 1 - } + }) } diff --git a/scripts/token-generator/io.ts b/scripts/token-generator/io.ts index bcf07389..63974c4b 100644 --- a/scripts/token-generator/io.ts +++ b/scripts/token-generator/io.ts @@ -8,7 +8,8 @@ import { unlinkSync, } from 'node:fs' import { dirname, join } from 'node:path' -import { isDeepStrictEqual } from 'node:util' + +import { format, resolveConfig, type Options } from 'prettier' import { isTokenTree, type CompiledTokens, type TokenTree } from './core/types' @@ -44,8 +45,11 @@ export const parseTokenTree = ( export const loadTokenTree = (filePath: string): TokenTree => parseTokenTree(readFileSync(filePath, 'utf8'), filePath) -export const renderJson = (value: TokenTree): string => - `${JSON.stringify(value, null, 2)}\n` +export const renderJson = ( + value: TokenTree, + options: Options = {} +): Promise => + format(JSON.stringify(value), { ...options, parser: 'json' }) const outputEntries = ( compiled: CompiledTokens @@ -62,15 +66,30 @@ const outputEntries = ( [OUTPUT_FILES.components.dark, compiled.components.dark], ] -export const writeGeneratedTokens = ( +const renderOutputEntries = async ( compiled: CompiledTokens, outputDirectory: string -): void => { +): Promise> => { + const options = + (await resolveConfig(join(outputDirectory, OUTPUT_FILES.fonts))) ?? {} + + return Promise.all( + outputEntries(compiled).map(async ([fileName, value]) => [ + fileName, + await renderJson(value, options), + ]) + ) +} + +export const writeGeneratedTokens = async ( + compiled: CompiledTokens, + outputDirectory: string +): Promise => { + const entries = await renderOutputEntries(compiled, outputDirectory) + mkdirSync(outputDirectory, { recursive: true }) - const expectedFiles = new Set( - outputEntries(compiled).map(([fileName]) => fileName) - ) + const expectedFiles = new Set(entries.map(([fileName]) => fileName)) for (const fileName of findJsonFiles(outputDirectory)) { if (!expectedFiles.has(fileName)) { @@ -78,12 +97,12 @@ export const writeGeneratedTokens = ( } } - for (const [fileName, value] of outputEntries(compiled)) { + for (const [fileName, contents] of entries) { const outputPath = join(outputDirectory, fileName) const temporaryPath = `${outputPath}.tmp` mkdirSync(dirname(outputPath), { recursive: true }) - writeFileSync(temporaryPath, renderJson(value)) + writeFileSync(temporaryPath, contents) renameSync(temporaryPath, outputPath) } } @@ -112,24 +131,20 @@ export interface GeneratedTokenIssues { unexpected: string[] } -export const findGeneratedTokenIssues = ( +export const findGeneratedTokenIssues = async ( compiled: CompiledTokens, outputDirectory: string -): GeneratedTokenIssues => { - const entries = outputEntries(compiled) +): Promise => { + const entries = await renderOutputEntries(compiled, outputDirectory) const expectedFiles = new Set(entries.map(([fileName]) => fileName)) const missing: string[] = [] const changed: string[] = [] - for (const [fileName, value] of entries) { + for (const [fileName, contents] of entries) { const outputPath = join(outputDirectory, fileName) if (existsSync(outputPath)) { - try { - if (!isDeepStrictEqual(loadTokenTree(outputPath), value)) { - changed.push(fileName) - } - } catch { + if (readFileSync(outputPath, 'utf8') !== contents) { changed.push(fileName) } } else { From 34f1785a460cd66c342d9ec735b1f5a4a630b0a2 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:00:02 +0300 Subject: [PATCH 14/60] =?UTF-8?q?feat(Theme):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jest.setup.ts | 30 ++++++++---- src/hooks/useFonts.ts | 3 +- src/theme/ThemeContext.tsx | 58 ++++++++++++++++++++--- src/theme/__tests__/ThemeContext.test.tsx | 49 +++++++++++++++++-- src/theme/tokens/README.md | 13 +++-- src/theme/tokens/index.ts | 14 ++++++ src/theme/types.ts | 10 ++++ src/utils/SvgUniversal.tsx | 8 ++-- 8 files changed, 154 insertions(+), 31 deletions(-) diff --git a/jest.setup.ts b/jest.setup.ts index 8c1471d8..850baa92 100644 --- a/jest.setup.ts +++ b/jest.setup.ts @@ -13,8 +13,12 @@ jest.mock('react-native-worklets', () => ) interface MockedUnistylesModule { - StyleSheet: { create: (...args: unknown[]) => unknown } + StyleSheet: { + configure: jest.Mock + create: (...args: unknown[]) => unknown + } UnistylesRuntime: { + getTheme: jest.Mock miniRuntime: unknown setTheme: jest.Mock updateTheme: jest.Mock unknown]> @@ -32,23 +36,28 @@ const unistyles = jest.requireMock( // загрузки src/theme (и как следствие — src/utils/SvgUniversal с // `withUnistyles(...)` на top-level) в модуле уже стояли наши моки, а не // исходные identity-заглушки. -const themeRef: { - current: { darkTheme: unknown; lightTheme: unknown } | null -} = { current: null } +const themeRef: { current: { dark: unknown; light: unknown } | null } = { + current: null, +} const getTheme = (themeName: ThemeName | undefined) => - themeName === 'dark' - ? themeRef.current?.darkTheme - : themeRef.current?.lightTheme + themeName === 'dark' ? themeRef.current?.dark : themeRef.current?.light const runtime = unistyles.UnistylesRuntime runtime.themeName = 'light' +runtime.getTheme = jest.fn(getTheme) runtime.setTheme = jest.fn((themeName: ThemeName) => { runtime.themeName = themeName }) runtime.updateTheme = jest.fn() +unistyles.StyleSheet.configure = jest.fn(({ themes }) => { + if (themes) { + themeRef.current = themes + } +}) + unistyles.useUnistyles = jest.fn(() => ({ theme: getTheme(runtime.themeName), rt: runtime, @@ -174,11 +183,16 @@ unistyles.withUnistyles = jest.fn( } ) -themeRef.current = require('./src/theme') as { +const publicThemes = require('./src/theme') as { darkTheme: unknown lightTheme: unknown } +themeRef.current ??= { + dark: publicThemes.darkTheme, + light: publicThemes.lightTheme, +} + generatePropsCombinations = (properties: PropertyCombinations): T[] => { const keys = Object.keys(properties) as Array diff --git a/src/hooks/useFonts.ts b/src/hooks/useFonts.ts index b47218dc..e83308db 100644 --- a/src/hooks/useFonts.ts +++ b/src/hooks/useFonts.ts @@ -4,6 +4,7 @@ import type { FontsConfig } from '../theme' export const useFonts = (): FontsConfig => { const { theme } = useUnistyles() + const { primary, secondary } = theme.fonts - return theme.fonts + return { primary, secondary } } diff --git a/src/theme/ThemeContext.tsx b/src/theme/ThemeContext.tsx index e26905a3..f20afb5b 100644 --- a/src/theme/ThemeContext.tsx +++ b/src/theme/ThemeContext.tsx @@ -6,17 +6,54 @@ import { SkeletonContextProvider } from '../utils/SkeletonContext' import { darkTheme } from './darkTheme' import { lightTheme } from './lightTheme' -import { type FontsConfig, ThemeVariant } from './types' +import { + componentTokens, + fontTokens, + semanticTokens, + type ComponentTokens, + type SemanticTokens, +} from './tokens' +import { + type FontsConfig, + type FontTokens, + type ThemeType, + ThemeVariant, +} from './types' + +type InternalTheme = Omit & { + components: ComponentTokens + fonts: FontsConfig & FontTokens + semantic: ThemeType['semantic'] & SemanticTokens +} + +const createInternalTheme = ( + theme: ThemeType, + components: ComponentTokens +): InternalTheme => ({ + ...theme, + components, + fonts: { + ...fontTokens, + ...theme.fonts, + fontFamily: { base: theme.fonts.secondary, heading: theme.fonts.primary }, + }, + semantic: { ...semanticTokens, ...theme.semantic }, +}) + +const internalThemes = { + light: createInternalTheme(lightTheme, componentTokens.light), + dark: createInternalTheme(darkTheme, componentTokens.dark), +} StyleSheet.configure({ settings: { initialTheme: 'light' }, - themes: { light: lightTheme, dark: darkTheme }, + themes: internalThemes, }) declare module 'react-native-unistyles' { export interface UnistylesThemes { - light: typeof lightTheme - dark: typeof darkTheme + light: (typeof internalThemes)['light'] + dark: (typeof internalThemes)['dark'] } } @@ -42,8 +79,17 @@ export const ThemeContextProvider = ({ UnistylesRuntime.setTheme(THEME_NAME_MAP[initialTheme]) if (fonts) { - UnistylesRuntime.updateTheme('light', (t) => ({ ...t, fonts })) - UnistylesRuntime.updateTheme('dark', (t) => ({ ...t, fonts })) + const updateFonts = (theme: InternalTheme): InternalTheme => ({ + ...theme, + fonts: { + ...theme.fonts, + ...fonts, + fontFamily: { base: fonts.secondary, heading: fonts.primary }, + }, + }) + + UnistylesRuntime.updateTheme('light', updateFonts) + UnistylesRuntime.updateTheme('dark', updateFonts) } // eslint-disable-next-line react-hooks/exhaustive-deps -- initial* props применяем только на mount }, []) diff --git a/src/theme/__tests__/ThemeContext.test.tsx b/src/theme/__tests__/ThemeContext.test.tsx index 71425de8..2edec632 100644 --- a/src/theme/__tests__/ThemeContext.test.tsx +++ b/src/theme/__tests__/ThemeContext.test.tsx @@ -6,7 +6,9 @@ import { UnistylesRuntime } from 'react-native-unistyles' import { ThemeContextProvider } from '../ThemeContext' import { darkTheme } from '../darkTheme' import { lightTheme } from '../lightTheme' -import { semanticTokens } from '../tokens' +import { componentTokens, fontTokens, semanticTokens } from '../tokens' +import darkComponentTokens from '../tokens/components/dark.json' +import lightComponentTokens from '../tokens/components/light.json' import darkSemanticColorSchemeTokens from '../tokens/semantic/colorScheme/dark.json' import lightSemanticColorSchemeTokens from '../tokens/semantic/colorScheme/light.json' import semanticDimensions from '../tokens/semantic/dimensions.json' @@ -57,10 +59,16 @@ describe('ThemeContextProvider', () => { ) const [, updater] = jest.mocked(UnistylesRuntime.updateTheme).mock.calls[0] - - expect( - updater({ ...lightTheme, fonts: { primary: 'old', secondary: 'old' } }) - ).toStrictEqual({ ...lightTheme, fonts }) + const theme = UnistylesRuntime.getTheme('light') + + expect(updater(theme)).toStrictEqual({ + ...theme, + fonts: { + ...theme.fonts, + ...fonts, + fontFamily: { base: fonts.secondary, heading: fonts.primary }, + }, + }) }) test('без fonts не вызывает updateTheme', () => { @@ -89,4 +97,35 @@ describe('ThemeContextProvider', () => { expect(lightTheme).not.toHaveProperty('components') expect(darkTheme).not.toHaveProperty('components') }) + + test('внутренняя карта component-токенов содержит обе темы', () => { + expect(componentTokens.light).toBe(lightComponentTokens) + expect(componentTokens.dark).toBe(darkComponentTokens) + }) + + test('внутренняя тема Unistyles содержит сгенерированные токены', () => { + const internalLightTheme = UnistylesRuntime.getTheme('light') + const internalDarkTheme = UnistylesRuntime.getTheme('dark') + + expect(internalLightTheme).toMatchObject({ + components: lightComponentTokens, + fonts: fontTokens, + semantic: { + colorScheme: lightSemanticColorSchemeTokens, + dimension: semanticDimensions, + effects: semanticEffects, + }, + }) + + expect(internalDarkTheme).toMatchObject({ + components: darkComponentTokens, + fonts: fontTokens, + semantic: { + colorScheme: darkSemanticColorSchemeTokens, + dimension: semanticDimensions, + effects: semanticEffects, + }, + }) + expect(internalLightTheme.fonts).toStrictEqual(internalDarkTheme.fonts) + }) }) diff --git a/src/theme/tokens/README.md b/src/theme/tokens/README.md index 6547d0fb..c4c6c42c 100644 --- a/src/theme/tokens/README.md +++ b/src/theme/tokens/README.md @@ -1,12 +1,11 @@ # Сгенерированные токены -В `ThemeType.semantic` подключается только выбранный `colorScheme`. Общие -`dimension` и `effects` экспортируются как статический `semanticTokens`, поэтому -не участвуют в переключении темы. `components` хранит внутренние токены -компонентов и не входит в темы или публичные экспорты. `fonts.json` содержит -общие для цветовых схем токены из `primitive.fonts`, но пока не подключён к теме -и не экспортируется из библиотеки. Всё генерируется из -`design-tokens/input/tokens.json` и не редактируется вручную. +В публичный `ThemeType.semantic` подключается только выбранный `colorScheme`. +Общие `dimension`, `effects` и `fonts` добавляются во внутреннюю тему Unistyles и +не зависят от цветовой схемы. В неё же добавляются соответствующие светлой или +тёмной теме `components`. В публичные темы и экспорты component- и font-токены +не входят. Всё генерируется из `design-tokens/input/tokens.json` и не +редактируется вручную. Подробности: [генератор токенов](../../../scripts/token-generator/README.md). diff --git a/src/theme/tokens/index.ts b/src/theme/tokens/index.ts index 9344acc6..08fdcb6f 100644 --- a/src/theme/tokens/index.ts +++ b/src/theme/tokens/index.ts @@ -1,6 +1,20 @@ +import type { FontTokens } from '../types' + +import darkComponentTokens from './components/dark.json' +import lightComponentTokens from './components/light.json' +import generatedFontTokens from './fonts.json' import dimensions from './semantic/dimensions.json' import effects from './semantic/effects.json' export const semanticTokens = { dimension: dimensions, effects } as const export type SemanticTokens = typeof semanticTokens + +export type ComponentTokens = typeof lightComponentTokens + +export const componentTokens = { + light: lightComponentTokens, + dark: darkComponentTokens, +} as const + +export const fontTokens = generatedFontTokens as FontTokens diff --git a/src/theme/types.ts b/src/theme/types.ts index a73c9ea9..c0b3ad20 100644 --- a/src/theme/types.ts +++ b/src/theme/types.ts @@ -1,3 +1,5 @@ +import type { TextStyle } from 'react-native' + import type { InputSize } from './assets/InputSize' import type { ModalSize } from './assets/ModalSize' import type background from './assets/background.json' @@ -12,6 +14,7 @@ import type sizing from './assets/sizing.json' import type spacing from './assets/spacing.json' import type lightTheme from './assets/themeLight.json' import type typography from './assets/typography.json' +import type fontTokens from './tokens/fonts.json' import type lightSemanticColorSchemeTokens from './tokens/semantic/colorScheme/light.json' export interface ThemeType { @@ -47,3 +50,10 @@ export interface FontsConfig { export interface FontsConfigType { fonts: FontsConfig } + +export type FontTokens = Omit & { + fontWeight: Record< + keyof typeof fontTokens.fontWeight, + TextStyle['fontWeight'] + > +} diff --git a/src/utils/SvgUniversal.tsx b/src/utils/SvgUniversal.tsx index 00119d79..e169a63b 100644 --- a/src/utils/SvgUniversal.tsx +++ b/src/utils/SvgUniversal.tsx @@ -6,9 +6,7 @@ import { memo, } from 'react' import { SvgUri, SvgXml, type SvgProps } from 'react-native-svg' -import { withUnistyles } from 'react-native-unistyles' - -import type { ThemeType } from '../theme/types' +import { withUnistyles, type UnistylesThemes } from 'react-native-unistyles' export type SvgSource = | { uri: string } @@ -20,6 +18,8 @@ export interface SvgUniversalProps extends SvgProps { source: SvgSource } +export type SvgUniversalTheme = UnistylesThemes[keyof UnistylesThemes] + /** * Компонент для рендера SVG из разных источников * Поддерживает: @@ -57,7 +57,7 @@ type SvgUniversalComponent = ForwardRefExoticComponent< PropsWithoutRef< Partial & { uniProps?: ( - theme: ThemeType + theme: SvgUniversalTheme ) => Omit< Partial, 'style' | 'contentContainerStyle' From 83c6b2b1d8e39f1e65d2ffe5416e8500663ac8e9 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:40 +0300 Subject: [PATCH 15/60] =?UTF-8?q?feat(Accordion):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Accordion/Accordion.tsx | 48 ++++++----- .../__snapshots__/Accordion.test.tsx.snap | 82 +++++++++---------- 2 files changed, 68 insertions(+), 62 deletions(-) diff --git a/src/components/Accordion/Accordion.tsx b/src/components/Accordion/Accordion.tsx index 76ffb39e..e04b763f 100644 --- a/src/components/Accordion/Accordion.tsx +++ b/src/components/Accordion/Accordion.tsx @@ -109,9 +109,9 @@ export const Accordion: React.FC = ({ ({ - color: theme.Panel.Accordion.accordionHeaderTextColor, - })} + uniProps={({ components }) => { + return { color: components.accordion.header.color } + }} /> {Icon ? ( @@ -119,9 +119,9 @@ export const Accordion: React.FC = ({ {...styles.icon} source={Icon} testID={AccordionTestIds.icon} - uniProps={({ theme }) => ({ - color: theme.Panel.Accordion.accordionHeaderTextColor, - })} + uniProps={({ components }) => { + return { color: components.accordion.header.color } + }} /> ) : null} {title} @@ -159,36 +159,42 @@ export const AccordionTestIds = { separator: 'Separator', } -const styles = StyleSheet.create(({ theme, fonts }) => ({ +const styles = StyleSheet.create(({ components, semantic, fonts }) => ({ component: { width: '100%' }, header: { - paddingVertical: theme.Panel.Accordion.accordionHeaderPaddingTopBottom, - gap: 7, + paddingVertical: semantic.dimension.space[400], + gap: components.accordion.extend.extHeader.gap, flexDirection: 'row', alignItems: 'center', - backgroundColor: theme.Panel.Accordion.accordionHeaderBg, + backgroundColor: components.accordion.colorScheme.header.background, + }, + icon: { + width: components.accordion.extend.extHeader.iconSize, + height: components.accordion.extend.extHeader.iconSize, }, - icon: { width: 17.5, height: 17.5 }, title: { - fontSize: 15.75, + fontSize: fonts.fontSize[400], includeFontPadding: false, verticalAlign: 'middle', - fontWeight: 700, - color: theme.Panel.Accordion.accordionHeaderTextColor, - fontFamily: fonts.secondary, + fontWeight: fonts.fontWeight.bold, + color: components.accordion.header.color, + fontFamily: fonts.fontFamily.base, }, contentAnimated: { overflow: 'hidden' }, contentWrapper: { position: 'absolute', width: '100%', - paddingLeft: theme.Panel.Accordion.accordionContentPaddingLeft, - paddingTop: theme.Panel.Accordion.accordionContentPaddingTop, - paddingRight: theme.Panel.Accordion.accordionContentPaddingRight, - paddingBottom: theme.Panel.Accordion.accordionContentPaddingBottom, + paddingLeft: components.accordion.content.paddingLeft, + paddingTop: semantic.dimension.space.none, + paddingRight: components.accordion.content.paddingRight, + paddingBottom: semantic.dimension.space[400], }, separator: { - borderTopColor: theme.Panel.Accordion.accordionHeaderBorderColor, + borderTopColor: components.accordion.panel.borderColor, borderTopWidth: 1, }, - disabled: { mixBlendMode: 'luminosity', opacity: 0.6 }, + disabled: { + mixBlendMode: 'luminosity', + opacity: semantic.effects.opacity[60], + }, })) diff --git a/src/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap b/src/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap index 04669b17..a1483e18 100644 --- a/src/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap +++ b/src/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap @@ -8,7 +8,7 @@ exports[`Accordion Header elements maximal 1`] = ` "width": "100%", }, { - "borderTopColor": "#e2e2e4", + "borderTopColor": "#cecfd2", "borderTopWidth": 1, }, ] @@ -51,9 +51,9 @@ exports[`Accordion Header elements maximal 1`] = ` [ { "alignItems": "center", - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", "flexDirection": "row", - "gap": 7, + "gap": 8, "paddingVertical": 14, }, {}, @@ -95,15 +95,15 @@ exports[`Accordion Header elements maximal 1`] = ` > Date: Tue, 4 Aug 2026 17:05:40 +0300 Subject: [PATCH 16/60] =?UTF-8?q?feat(Avatar):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Avatar/Avatar.tsx | 30 +- .../__snapshots__/Avatar.test.tsx.snap | 274 +++++++++--------- 2 files changed, 152 insertions(+), 152 deletions(-) diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx index 83938627..2c479799 100644 --- a/src/components/Avatar/Avatar.tsx +++ b/src/components/Avatar/Avatar.tsx @@ -188,9 +188,9 @@ export const Avatar = memo( height={iconSize} source={Icon} testID={AvatarTestId.icon} - uniProps={({ theme }) => ({ - color: iconColor ?? theme.Misc.Avatar.avatarTextColor, - })} + uniProps={({ components }) => { + return { color: iconColor ?? components.avatar.root.color } + }} width={iconSize} /> ) @@ -257,30 +257,30 @@ export const Avatar = memo( } ) -const styles = StyleSheet.create(({ theme, border, typography, fonts }) => ({ +const styles = StyleSheet.create(({ components, semantic, fonts }) => ({ container: { justifyContent: 'center', alignItems: 'center', - borderRadius: theme.General.borderRadiusXL, - borderWidth: 1, - borderColor: theme.Misc.Avatar.avatarBorderColor, - backgroundColor: theme.Misc.Avatar.avatarBg, + borderRadius: components.avatar.root.borderRadius, + borderWidth: semantic.dimension.borderWidth[100], + borderColor: components.avatar.extend.borderColor, + backgroundColor: components.avatar.root.background, overflow: 'hidden', }, - backgroundFill: { backgroundColor: theme.Misc.Avatar.avatarBg }, - circle: { borderRadius: border.Radius['rounded-full'] }, + backgroundFill: { backgroundColor: components.avatar.root.background }, + circle: { borderRadius: components.avatar.extend.circle.borderRadius }, text: { - fontSize: typography.Size['text-base'], + fontSize: components.avatar.root.fontSize, textTransform: 'uppercase', - color: theme.Misc.Avatar.avatarTextColor, + color: components.avatar.root.color, includeFontPadding: false, verticalAlign: 'middle', - fontFamily: fonts.secondary, + fontFamily: fonts.fontFamily.base, }, badgeContainer: { position: 'absolute', right: 0, top: -7 }, badgeMeasureContainer: { alignSelf: 'flex-start' }, - icon: { width: typography.Size['text-base'] }, - iconXLarge: { width: typography.Size['text-2xl'] }, + icon: { width: components.avatar.icon.size }, + iconXLarge: { width: components.avatar.xl.icon.size }, })) export const AvatarTestId = { diff --git a/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap b/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap index 81e73a20..49469718 100644 --- a/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap +++ b/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap @@ -11,8 +11,8 @@ exports[`Avatar component tests Size: custom, shape: circle, type: icon, with cu { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#e2e2e4", - "borderRadius": 10.5, + "borderColor": "#cecfd2", + "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", "overflow": "hidden", @@ -25,7 +25,7 @@ exports[`Avatar component tests Size: custom, shape: circle, type: icon, with cu "backgroundColor": "#44e858", }, { - "borderRadius": 100, + "borderRadius": 1600, }, undefined, ] @@ -149,8 +149,8 @@ exports[`Avatar component tests Size: large, shape: circle, type: icon 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#e2e2e4", - "borderRadius": 10.5, + "borderColor": "#cecfd2", + "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", "overflow": "hidden", @@ -163,7 +163,7 @@ exports[`Avatar component tests Size: large, shape: circle, type: icon 1`] = ` "backgroundColor": "#44e858", }, { - "borderRadius": 100, + "borderRadius": 1600, }, undefined, ] @@ -172,15 +172,15 @@ exports[`Avatar component tests Size: large, shape: circle, type: icon 1`] = ` > Date: Tue, 4 Aug 2026 17:05:41 +0300 Subject: [PATCH 17/60] =?UTF-8?q?feat(Badge):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Badge/Badge.tsx | 92 ++++++------ .../__snapshots__/Badge.test.tsx.snap | 136 +++++++++--------- 2 files changed, 113 insertions(+), 115 deletions(-) diff --git a/src/components/Badge/Badge.tsx b/src/components/Badge/Badge.tsx index 8b0e5f6a..2cdf0052 100644 --- a/src/components/Badge/Badge.tsx +++ b/src/components/Badge/Badge.tsx @@ -103,53 +103,51 @@ export const Badge = memo( } ) -const badgeStyles = StyleSheet.create( - ({ theme, border, typography, fonts }) => ({ - container: { alignItems: 'flex-start' }, - dot: { - variants: { - severity: { - basic: { backgroundColor: theme.Misc.Badge.badgeBg }, - info: { - backgroundColor: theme.Button.Severity.Info.Basic.infoButtonBg, - }, - success: { - backgroundColor: - theme.Button.Severity.Success.Basic.successButtonBg, - }, - warning: { - backgroundColor: - theme.Button.Severity.Warning.Basic.warningButtonBg, - }, - danger: { - backgroundColor: theme.Button.Severity.Danger.Basic.dangerButtonBg, - }, +const badgeStyles = StyleSheet.create(({ components, semantic, fonts }) => ({ + container: { alignItems: 'flex-start' }, + dot: { + variants: { + severity: { + basic: { + backgroundColor: components.badge.colorScheme.primary.background, + }, + info: { + backgroundColor: components.badge.extend.extDot.info.background, + }, + success: { + backgroundColor: components.badge.extend.extDot.success.background, + }, + warning: { + backgroundColor: components.badge.extend.extDot.warn.background, + }, + danger: { + backgroundColor: components.badge.extend.extDot.danger.background, }, }, }, - dotShape: { - width: theme.Misc.Badge.badgeDotSize, - height: theme.Misc.Badge.badgeDotSize, - borderRadius: border.Radius['rounded-full'], - }, - textBadgeContainer: { - height: theme.Misc.Badge.badgeHeight, - paddingHorizontal: theme.Misc.Tag.tagPadding, - justifyContent: 'center', - borderRadius: border.Radius['rounded-full'], - }, - textBadge: { - color: theme.Misc.Badge.badgeTextColor, - fontSize: typography.Size['text-xs'], - includeFontPadding: false, - verticalAlign: 'middle', - fontFamily: fonts.primary, - }, - hiddenContainer: { - width: Dimensions.get('window').width, - height: 0, - flexDirection: 'row', - position: 'absolute', - }, - }) -) + }, + dotShape: { + width: components.badge.dot.size, + height: components.badge.dot.size, + borderRadius: components.badge.root.borderRadius, + }, + textBadgeContainer: { + height: components.badge.root.height, + paddingHorizontal: components.badge.root.padding, + justifyContent: 'center', + borderRadius: semantic.dimension.borderRadius.max, + }, + textBadge: { + color: components.badge.colorScheme.primary.color, + fontSize: components.badge.root.fontSize, + includeFontPadding: false, + verticalAlign: 'middle', + fontFamily: fonts.fontFamily.heading, + }, + hiddenContainer: { + width: Dimensions.get('window').width, + height: 0, + flexDirection: 'row', + position: 'absolute', + }, +})) diff --git a/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap b/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap index e4b181ae..c728269d 100644 --- a/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap +++ b/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap @@ -18,9 +18,9 @@ exports[`Badge component tests dot, severity: basic 1`] = ` "backgroundColor": "#44e858", }, { - "borderRadius": 100, - "height": 7, - "width": 7, + "borderRadius": 8, + "height": 8, + "width": 8, }, ] } @@ -43,12 +43,12 @@ exports[`Badge component tests dot, severity: danger 1`] = ` style={ [ { - "backgroundColor": "#fbacaa", + "backgroundColor": "#f47f77", }, { - "borderRadius": 100, - "height": 7, - "width": 7, + "borderRadius": 8, + "height": 8, + "width": 8, }, ] } @@ -71,12 +71,12 @@ exports[`Badge component tests dot, severity: info 1`] = ` style={ [ { - "backgroundColor": "#aad7fb", + "backgroundColor": "#77baf4", }, { - "borderRadius": 100, - "height": 7, - "width": 7, + "borderRadius": 8, + "height": 8, + "width": 8, }, ] } @@ -99,12 +99,12 @@ exports[`Badge component tests dot, severity: success 1`] = ` style={ [ { - "backgroundColor": "#aafbb7", + "backgroundColor": "#77f48a", }, { - "borderRadius": 100, - "height": 7, - "width": 7, + "borderRadius": 8, + "height": 8, + "width": 8, }, ] } @@ -127,12 +127,12 @@ exports[`Badge component tests dot, severity: warning 1`] = ` style={ [ { - "backgroundColor": "#fddeaa", + "backgroundColor": "#facb75", }, { - "borderRadius": 100, - "height": 7, - "width": 7, + "borderRadius": 8, + "height": 8, + "width": 8, }, ] } @@ -158,10 +158,10 @@ exports[`Badge component tests severity: basic 1`] = ` "backgroundColor": "#44e858", }, { - "borderRadius": 100, - "height": 21, + "borderRadius": 1600, + "height": 24, "justifyContent": "center", - "paddingHorizontal": 7, + "paddingHorizontal": 8, }, ] } @@ -171,9 +171,9 @@ exports[`Badge component tests severity: basic 1`] = ` style={ [ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", }, @@ -206,9 +206,9 @@ exports[`Badge component tests severity: basic 1`] = ` onLayout={[Function]} style={ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", } @@ -236,13 +236,13 @@ exports[`Badge component tests severity: basic 2`] = ` style={ [ { - "backgroundColor": "#aad7fb", + "backgroundColor": "#77baf4", }, { - "borderRadius": 100, - "height": 21, + "borderRadius": 1600, + "height": 24, "justifyContent": "center", - "paddingHorizontal": 7, + "paddingHorizontal": 8, }, ] } @@ -252,9 +252,9 @@ exports[`Badge component tests severity: basic 2`] = ` style={ [ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", }, @@ -287,9 +287,9 @@ exports[`Badge component tests severity: basic 2`] = ` onLayout={[Function]} style={ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", } @@ -317,13 +317,13 @@ exports[`Badge component tests severity: basic 3`] = ` style={ [ { - "backgroundColor": "#aafbb7", + "backgroundColor": "#77f48a", }, { - "borderRadius": 100, - "height": 21, + "borderRadius": 1600, + "height": 24, "justifyContent": "center", - "paddingHorizontal": 7, + "paddingHorizontal": 8, }, ] } @@ -333,9 +333,9 @@ exports[`Badge component tests severity: basic 3`] = ` style={ [ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", }, @@ -368,9 +368,9 @@ exports[`Badge component tests severity: basic 3`] = ` onLayout={[Function]} style={ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", } @@ -398,13 +398,13 @@ exports[`Badge component tests severity: basic 4`] = ` style={ [ { - "backgroundColor": "#fddeaa", + "backgroundColor": "#facb75", }, { - "borderRadius": 100, - "height": 21, + "borderRadius": 1600, + "height": 24, "justifyContent": "center", - "paddingHorizontal": 7, + "paddingHorizontal": 8, }, ] } @@ -414,9 +414,9 @@ exports[`Badge component tests severity: basic 4`] = ` style={ [ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", }, @@ -449,9 +449,9 @@ exports[`Badge component tests severity: basic 4`] = ` onLayout={[Function]} style={ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", } @@ -479,13 +479,13 @@ exports[`Badge component tests severity: basic 5`] = ` style={ [ { - "backgroundColor": "#fbacaa", + "backgroundColor": "#f47f77", }, { - "borderRadius": 100, - "height": 21, + "borderRadius": 1600, + "height": 24, "justifyContent": "center", - "paddingHorizontal": 7, + "paddingHorizontal": 8, }, ] } @@ -495,9 +495,9 @@ exports[`Badge component tests severity: basic 5`] = ` style={ [ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", }, @@ -530,9 +530,9 @@ exports[`Badge component tests severity: basic 5`] = ` onLayout={[Function]} style={ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", } @@ -563,10 +563,10 @@ exports[`Badge component tests severity: default 1`] = ` "backgroundColor": "#44e858", }, { - "borderRadius": 100, - "height": 21, + "borderRadius": 1600, + "height": 24, "justifyContent": "center", - "paddingHorizontal": 7, + "paddingHorizontal": 8, }, ] } @@ -576,9 +576,9 @@ exports[`Badge component tests severity: default 1`] = ` style={ [ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", }, @@ -611,9 +611,9 @@ exports[`Badge component tests severity: default 1`] = ` onLayout={[Function]} style={ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", } @@ -646,9 +646,9 @@ exports[`Badge component tests with custom style 1`] = ` "backgroundColor": "#44e858", }, { - "borderRadius": 100, - "height": 7, - "width": 7, + "borderRadius": 8, + "height": 8, + "width": 8, }, ] } From 693bf3ec75c5aeda856bdc120d4a7a640556f02b Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:41 +0300 Subject: [PATCH 18/60] =?UTF-8?q?feat(Button):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__snapshots__/Button.test.tsx.snap | 25296 ++++++++-------- .../__snapshots__/ButtonBadge.test.tsx.snap | 56 +- .../ButtonSeverity.test.tsx.snap | 64 +- .../Button/utils/ButtonActivityIndicator.tsx | 24 +- .../Button/utils/ButtonContainer.tsx | 298 +- src/components/Button/utils/ButtonIcon.tsx | 215 +- src/components/Button/utils/ButtonLabel.tsx | 205 +- 7 files changed, 12521 insertions(+), 13637 deletions(-) diff --git a/src/components/Button/__tests__/__snapshots__/Button.test.tsx.snap b/src/components/Button/__tests__/__snapshots__/Button.test.tsx.snap index 2a91e4a6..61172500 100644 --- a/src/components/Button/__tests__/__snapshots__/Button.test.tsx.snap +++ b/src/components/Button/__tests__/__snapshots__/Button.test.tsx.snap @@ -37,17 +37,15 @@ exports[`Button component tests Button default props 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 10.5, + "borderColor": "transparent", + "borderRadius": 14, "borderWidth": 1, "flexDirection": "row", - "gap": 7, - "height": 35, + "gap": 8, + "height": "auto", "justifyContent": "center", - "maxHeight": 35, - "minHeight": 35, "paddingHorizontal": 14, - "paddingVertical": 0, + "paddingVertical": 8, }, false, ] @@ -56,9 +54,9 @@ exports[`Button component tests Button default props 1`] = ` ({ - indicator: { - color: theme.Button.Disabled.disabledButtonTextColor, - variants: { - size: { - xlarge: { height: 21 }, - large: { height: 21 }, - base: { height: 17.5 }, - small: { height: 14 }, +const buttonActivityIndicatorStyles = StyleSheet.create( + ({ components: { button } }) => ({ + indicator: { + color: button.extend.disabledColor, + variants: { + size: { + xlarge: { height: 21 }, + large: { height: 21 }, + base: { height: 17.5 }, + small: { height: 14 }, + }, }, }, - }, -})) + }) +) diff --git a/src/components/Button/utils/ButtonContainer.tsx b/src/components/Button/utils/ButtonContainer.tsx index 682cc8ed..91a23db0 100644 --- a/src/components/Button/utils/ButtonContainer.tsx +++ b/src/components/Button/utils/ButtonContainer.tsx @@ -80,96 +80,91 @@ const ButtonContainerComponent = ({ export const ButtonContainer = genericMemo(ButtonContainerComponent) +// `transparent` здесь — отсутствие фона или границы, а не цвет дизайн-системы: +// прозрачность не выражена ни semantic-токеном, ни свойствами button.extend.extText. const buttonContainerStyles = StyleSheet.create( - ({ theme, border, spacing, sizing }) => ({ + ({ components: { button }, semantic }) => ({ container: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', - borderWidth: border.Width.border, + borderWidth: button.extend.borderWidth, variants: { size: { xlarge: { - paddingHorizontal: spacing.Padding['p-6'], - paddingVertical: theme.Button.Common.buttonPaddingTopBottom, - height: theme.Button.Common.buttonHeightXL, - minHeight: theme.Button.Common.buttonHeightXL, - maxHeight: theme.Button.Common.buttonHeightXL, - gap: spacing.Gap['gap-3'], - borderRadius: theme.General.borderRadius2XL, + paddingHorizontal: button.extend.extXlg.paddingX, + paddingVertical: button.extend.extXlg.paddingY, + height: button.extend.extXlg.height, + minHeight: button.extend.extXlg.height, + maxHeight: button.extend.extXlg.height, + gap: button.extend.extXlg.gap, + borderRadius: button.extend.extXlg.borderRadius, }, large: { - paddingHorizontal: spacing.Padding['p-6'], - paddingVertical: theme.Button.Common.buttonPaddingTopBottom, - height: theme.Button.Common.buttonHeightLG, - minHeight: theme.Button.Common.buttonHeightLG, - maxHeight: theme.Button.Common.buttonHeightLG, - gap: spacing.Gap['gap-3'], - borderRadius: theme.General.borderRadius2XL, + paddingHorizontal: button.root.lg.paddingX, + paddingVertical: button.root.lg.paddingY, + height: button.extend.extLg.height, + minHeight: button.extend.extLg.height, + maxHeight: button.extend.extLg.height, + gap: button.extend.extLg.gap, + borderRadius: button.extend.extLg.borderRadius, }, base: { - paddingHorizontal: theme.Button.Common.buttonPaddingLeftRight, - paddingVertical: theme.Button.Common.buttonPaddingTopBottom, - height: theme.Button.Common.buttonHeight, - minHeight: theme.Button.Common.buttonHeight, - maxHeight: theme.Button.Common.buttonHeight, - gap: theme.General.inlineSpacing, - borderRadius: theme.General.borderRadiusXL, + paddingHorizontal: button.root.paddingX, + paddingVertical: button.root.paddingY, + height: 'auto', + gap: button.root.gap, + borderRadius: button.root.borderRadius, }, small: { - paddingHorizontal: spacing.Padding['p-3'], - paddingVertical: theme.Button.Common.buttonPaddingTopBottom, - height: theme.Button.Common.buttonHeightSM, - minHeight: theme.Button.Common.buttonHeightSM, - maxHeight: theme.Button.Common.buttonHeightSM, - gap: theme.General.inlineSpacing, - borderRadius: theme.General.borderRadiusXL, + paddingHorizontal: button.root.sm.paddingX, + paddingVertical: button.root.sm.paddingY, + height: 'auto', + gap: button.extend.extSm.gap, + borderRadius: button.extend.extSm.borderRadius, }, }, shape: { square: {}, - circle: { borderRadius: border.Radius['rounded-full'] }, + circle: { borderRadius: button.root.roundedBorderRadius }, }, variant: { primary: { - borderColor: theme.Button.Brand.buttonBorderColor, - backgroundColor: theme.Button.Brand.buttonBg, + borderColor: button.colorScheme.root.primary.borderColor, + backgroundColor: button.colorScheme.root.primary.background, }, secondary: { - borderColor: theme.Button.Primary.secondaryButtonBorderColor, - backgroundColor: theme.Button.Primary.secondaryButtonBg, + borderColor: button.colorScheme.root.secondary.borderColor, + backgroundColor: button.colorScheme.root.secondary.background, }, tertiary: { - borderColor: theme.Button.Secondary.helpButtonBorderColor, - backgroundColor: theme.Button.Secondary.helpButtonBg, - }, - text: { - borderColor: theme.Button.Brand.buttonBorderColor, - backgroundColor: theme.Button.Text.textButtonBg, + borderColor: button.colorScheme.root.contrast.borderColor, + backgroundColor: button.colorScheme.root.contrast.background, }, + text: { borderColor: 'transparent', backgroundColor: 'transparent' }, link: { - paddingHorizontal: 0, - paddingVertical: spacing.Padding['p-1'], + paddingHorizontal: semantic.dimension.space.none, + paddingVertical: semantic.dimension.space[100], height: 'auto', minHeight: 'auto', - borderColor: theme.Button.Brand.buttonBorderColor, - backgroundColor: theme.Button.Text.textButtonBg, + borderColor: 'transparent', + backgroundColor: button.extend.extLink.background, }, basic: { - borderColor: theme.Button.Brand.buttonBorderColor, - backgroundColor: theme.Button.Brand.buttonBg, + borderColor: button.colorScheme.root.primary.borderColor, + backgroundColor: button.colorScheme.root.primary.background, }, outlined: { - borderColor: theme.Button.Brand.buttonBorderColor, - backgroundColor: theme.Button.Text.textButtonBg, + borderColor: button.colorScheme.outlined.primary.borderColor, + backgroundColor: 'transparent', }, }, severity: { info: {}, success: {}, warning: {}, danger: {} }, pressed: { true: {}, false: {} }, disabled: { true: { - backgroundColor: theme.Button.Disabled.disabledButtonBg, - borderColor: theme.Button.Disabled.disabledButtonBorderColor, + backgroundColor: button.extend.disabledBackground, + borderColor: 'transparent', }, false: {}, }, @@ -181,40 +176,40 @@ const buttonContainerStyles = StyleSheet.create( variant: 'primary', pressed: 'true', styles: { - borderColor: theme.Button.Brand.buttonBorderColor, - backgroundColor: theme.Button.Brand.buttonHoverBg, + borderColor: button.colorScheme.root.primary.hoverBorderColor, + backgroundColor: button.colorScheme.root.primary.hoverBackground, }, }, { variant: 'secondary', pressed: 'true', styles: { - borderColor: theme.Button.Primary.secondaryButtonHoverBorderColor, - backgroundColor: theme.Button.Primary.secondaryButtonHoverBg, + borderColor: button.colorScheme.root.secondary.hoverBorderColor, + backgroundColor: button.colorScheme.root.secondary.hoverBackground, }, }, { variant: 'tertiary', pressed: 'true', styles: { - borderColor: theme.Button.Secondary.helpButtonHoverBorderColor, - backgroundColor: theme.Button.Secondary.helpButtonHoverBg, + borderColor: button.colorScheme.root.contrast.hoverBorderColor, + backgroundColor: button.colorScheme.root.contrast.hoverBackground, }, }, { variant: 'text', pressed: 'true', styles: { - borderColor: theme.Button.Brand.buttonBorderColor, - backgroundColor: theme.Button.Text.textButtonHoverBg, + borderColor: 'transparent', + backgroundColor: button.colorScheme.text.primary.hoverBackground, }, }, { variant: 'link', disabled: 'true', styles: { - borderColor: theme.Button.Brand.buttonBorderColor, - backgroundColor: theme.Button.Text.textButtonBg, + borderColor: 'transparent', + backgroundColor: 'transparent', }, }, @@ -223,118 +218,96 @@ const buttonContainerStyles = StyleSheet.create( variant: 'basic', severity: 'info', styles: { - borderColor: theme.Button.Severity.Info.Basic.infoButtonBorderColor, - backgroundColor: theme.Button.Severity.Info.Basic.infoButtonBg, + borderColor: button.colorScheme.root.info.borderColor, + backgroundColor: button.colorScheme.root.info.background, }, }, { variant: 'outlined', severity: 'info', styles: { - borderColor: - theme.Button.Severity.Info.Outlined.infoOutlinedButtonBorderColor, - backgroundColor: - theme.Button.Severity.Info.Outlined.infoOutlinedButtonBg, + borderColor: button.colorScheme.outlined.info.borderColor, + backgroundColor: 'transparent', }, }, { variant: 'text', severity: 'info', styles: { - borderColor: theme.Button.Severity.Info.Basic.infoButtonBorderColor, - backgroundColor: theme.Button.Severity.Info.Text.infoTextButtonBg, + borderColor: 'transparent', + backgroundColor: 'transparent', }, }, { variant: 'basic', severity: 'success', styles: { - borderColor: - theme.Button.Severity.Success.Basic.successButtonBorderColor, - backgroundColor: - theme.Button.Severity.Success.Basic.successButtonBg, + borderColor: button.colorScheme.root.success.borderColor, + backgroundColor: button.colorScheme.root.success.background, }, }, { variant: 'outlined', severity: 'success', styles: { - borderColor: - theme.Button.Severity.Success.Outlined - .successOutlinedButtonBorderColor, - backgroundColor: - theme.Button.Severity.Success.Outlined.successOutlinedButtonBg, + borderColor: button.colorScheme.outlined.success.borderColor, + backgroundColor: 'transparent', }, }, { variant: 'text', severity: 'success', styles: { - borderColor: - theme.Button.Severity.Success.Basic.successButtonBorderColor, - backgroundColor: - theme.Button.Severity.Success.Text.successTextButtonBg, + borderColor: 'transparent', + backgroundColor: 'transparent', }, }, { variant: 'basic', severity: 'warning', styles: { - borderColor: - theme.Button.Severity.Warning.Basic.warningButtonBorderColor, - backgroundColor: - theme.Button.Severity.Warning.Basic.warningButtonBg, + borderColor: button.colorScheme.root.warn.borderColor, + backgroundColor: button.colorScheme.root.warn.background, }, }, { variant: 'outlined', severity: 'warning', styles: { - borderColor: - theme.Button.Severity.Warning.Outlined - .warningOutlinedButtonBorderColor, - backgroundColor: - theme.Button.Severity.Warning.Outlined.warningOutlinedButtonBg, + borderColor: button.colorScheme.outlined.warn.borderColor, + backgroundColor: 'transparent', }, }, { variant: 'text', severity: 'warning', styles: { - borderColor: - theme.Button.Severity.Warning.Basic.warningButtonBorderColor, - backgroundColor: - theme.Button.Severity.Warning.Text.warningTextButtonBg, + borderColor: 'transparent', + backgroundColor: 'transparent', }, }, { variant: 'basic', severity: 'danger', styles: { - borderColor: - theme.Button.Severity.Danger.Basic.dangerButtonBorderColor, - backgroundColor: theme.Button.Severity.Danger.Basic.dangerButtonBg, + borderColor: button.colorScheme.root.danger.borderColor, + backgroundColor: button.colorScheme.root.danger.background, }, }, { variant: 'outlined', severity: 'danger', styles: { - borderColor: - theme.Button.Severity.Danger.Outlined - .dangerOutlinedButtonBorderColor, - backgroundColor: - theme.Button.Severity.Danger.Outlined.dangerOutlinedButtonBg, + borderColor: button.colorScheme.outlined.danger.borderColor, + backgroundColor: 'transparent', }, }, { variant: 'text', severity: 'danger', styles: { - borderColor: - theme.Button.Severity.Danger.Basic.dangerButtonBorderColor, - backgroundColor: - theme.Button.Severity.Danger.Text.dangerTextButtonBg, + borderColor: 'transparent', + backgroundColor: 'transparent', }, }, @@ -344,8 +317,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'info', pressed: 'true', styles: { - borderColor: theme.Button.Severity.Info.Basic.infoButtonBorderColor, - backgroundColor: theme.Button.Severity.Info.Basic.infoButtonHoverBg, + borderColor: button.colorScheme.root.info.hoverBorderColor, + backgroundColor: button.colorScheme.root.info.hoverBackground, }, }, { @@ -353,11 +326,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'info', pressed: 'true', styles: { - borderColor: - theme.Button.Severity.Info.Outlined - .infoOutlinedButtonHoverBorderColor, - backgroundColor: - theme.Button.Severity.Info.Outlined.infoOutlinedButtonHoverBg, + borderColor: button.colorScheme.outlined.info.borderColor, + backgroundColor: button.colorScheme.outlined.info.hoverBackground, }, }, { @@ -365,9 +335,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'info', pressed: 'true', styles: { - borderColor: theme.Surface['surface-transparent'], - backgroundColor: - theme.Button.Severity.Info.Text.infoTextButtonHoverBg, + borderColor: 'transparent', + backgroundColor: button.colorScheme.text.info.hoverBackground, }, }, { @@ -375,10 +344,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'success', pressed: 'true', styles: { - borderColor: - theme.Button.Severity.Success.Basic.successButtonBorderColor, - backgroundColor: - theme.Button.Severity.Success.Basic.successButtonHoverBg, + borderColor: button.colorScheme.root.success.hoverBorderColor, + backgroundColor: button.colorScheme.root.success.hoverBackground, }, }, { @@ -386,12 +353,9 @@ const buttonContainerStyles = StyleSheet.create( severity: 'success', pressed: 'true', styles: { - borderColor: - theme.Button.Severity.Success.Outlined - .successOutlinedButtonHoverBorderColor, + borderColor: button.colorScheme.outlined.success.borderColor, backgroundColor: - theme.Button.Severity.Success.Outlined - .successOutlinedButtonHoverBg, + button.colorScheme.outlined.success.hoverBackground, }, }, { @@ -399,9 +363,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'success', pressed: 'true', styles: { - borderColor: theme.Surface['surface-transparent'], - backgroundColor: - theme.Button.Severity.Success.Text.successTextButtonHoverBg, + borderColor: 'transparent', + backgroundColor: button.colorScheme.text.success.hoverBackground, }, }, { @@ -409,10 +372,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'warning', pressed: 'true', styles: { - borderColor: - theme.Button.Severity.Warning.Basic.warningButtonBorderColor, - backgroundColor: - theme.Button.Severity.Warning.Basic.warningButtonHoverBg, + borderColor: button.colorScheme.root.warn.hoverBorderColor, + backgroundColor: button.colorScheme.root.warn.hoverBackground, }, }, { @@ -420,12 +381,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'warning', pressed: 'true', styles: { - borderColor: - theme.Button.Severity.Warning.Outlined - .warningOutlinedButtonHoverBorderColor, - backgroundColor: - theme.Button.Severity.Warning.Outlined - .warningOutlinedButtonHoverBg, + borderColor: button.colorScheme.outlined.warn.borderColor, + backgroundColor: button.colorScheme.outlined.warn.hoverBackground, }, }, { @@ -433,9 +390,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'warning', pressed: 'true', styles: { - borderColor: theme.Surface['surface-transparent'], - backgroundColor: - theme.Button.Severity.Warning.Text.warningTextButtonHoverBg, + borderColor: 'transparent', + backgroundColor: button.colorScheme.text.warn.hoverBackground, }, }, { @@ -443,10 +399,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'danger', pressed: 'true', styles: { - borderColor: - theme.Button.Severity.Danger.Basic.dangerButtonBorderColor, - backgroundColor: - theme.Button.Severity.Danger.Basic.dangerButtonHoverBg, + borderColor: button.colorScheme.root.danger.hoverBorderColor, + backgroundColor: button.colorScheme.root.danger.hoverBackground, }, }, { @@ -454,11 +408,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'danger', pressed: 'true', styles: { - borderColor: - theme.Button.Severity.Danger.Outlined - .dangerOutlinedButtonHoverBorderColor, - backgroundColor: - theme.Button.Severity.Danger.Outlined.dangerOutlinedButtonHoverBg, + borderColor: button.colorScheme.outlined.danger.borderColor, + backgroundColor: button.colorScheme.outlined.danger.hoverBackground, }, }, { @@ -466,9 +417,8 @@ const buttonContainerStyles = StyleSheet.create( severity: 'danger', pressed: 'true', styles: { - borderColor: theme.Surface['surface-transparent'], - backgroundColor: - theme.Button.Severity.Danger.Text.dangerTextButtonHoverBg, + borderColor: 'transparent', + backgroundColor: button.colorScheme.text.danger.hoverBackground, }, }, @@ -478,11 +428,11 @@ const buttonContainerStyles = StyleSheet.create( iconOnly: 'true', size: 'xlarge', styles: { - paddingHorizontal: spacing.Gap['gap-1'], - paddingVertical: spacing.Gap['gap-1'], - height: sizing.Height['h-2'], - minHeight: sizing.Height['h-2'], - maxHeight: sizing.Height['h-2'], + paddingHorizontal: semantic.dimension.space[100], + paddingVertical: semantic.dimension.space[100], + height: button.extend.extLink.xlg.iconOnlyWidth, + minHeight: button.extend.extLink.xlg.iconOnlyWidth, + maxHeight: button.extend.extLink.xlg.iconOnlyWidth, }, }, { @@ -490,11 +440,11 @@ const buttonContainerStyles = StyleSheet.create( iconOnly: 'true', size: 'large', styles: { - paddingHorizontal: spacing.Gap['gap-0'], - paddingVertical: spacing.Gap['gap-0'], - height: 24.5, - minHeight: 24.5, - maxHeight: 24.5, + paddingHorizontal: semantic.dimension.space.none, + paddingVertical: semantic.dimension.space.none, + height: button.extend.extLink.lg.iconOnlyWidth, + minHeight: button.extend.extLink.lg.iconOnlyWidth, + maxHeight: button.extend.extLink.lg.iconOnlyWidth, }, }, { @@ -502,11 +452,11 @@ const buttonContainerStyles = StyleSheet.create( iconOnly: 'true', size: 'base', styles: { - paddingHorizontal: spacing.Gap['gap-1'], - paddingVertical: spacing.Gap['gap-1'], - height: 21.5, - minHeight: 21.5, - maxHeight: 21.5, + paddingHorizontal: semantic.dimension.space[100], + paddingVertical: semantic.dimension.space[100], + height: button.extend.extLink.base.iconOnlyWidth, + minHeight: button.extend.extLink.base.iconOnlyWidth, + maxHeight: button.extend.extLink.base.iconOnlyWidth, }, }, { @@ -514,11 +464,11 @@ const buttonContainerStyles = StyleSheet.create( iconOnly: 'true', size: 'small', styles: { - paddingHorizontal: spacing.Gap['gap-1'], - paddingVertical: spacing.Gap['gap-1'], - height: sizing.Height['h-1'], - minHeight: sizing.Height['h-2'], - maxHeight: sizing.Height['h-2'], + paddingHorizontal: semantic.dimension.space[100], + paddingVertical: semantic.dimension.space[100], + height: button.extend.extLink.sm.iconOnlyWidth, + minHeight: button.extend.extLink.sm.iconOnlyWidth, + maxHeight: button.extend.extLink.sm.iconOnlyWidth, }, }, ], diff --git a/src/components/Button/utils/ButtonIcon.tsx b/src/components/Button/utils/ButtonIcon.tsx index 9dcb9c6c..6be2a77f 100644 --- a/src/components/Button/utils/ButtonIcon.tsx +++ b/src/components/Button/utils/ButtonIcon.tsx @@ -48,140 +48,111 @@ const ButtonIconComponent = ({ export const ButtonIcon = genericMemo(ButtonIconComponent) -const buttonIconStyles = StyleSheet.create(({ theme, typography }) => ({ - icon: { - variants: { - size: { - xlarge: { - height: typography.Size['text-2xl'], - width: typography.Size['text-2xl'], +const buttonIconStyles = StyleSheet.create( + ({ components: { button }, semantic }) => ({ + icon: { + variants: { + size: { + xlarge: { + height: button.extend.iconSize.lg, + width: button.extend.iconSize.lg, + }, + large: { + height: button.extend.iconSize.lg, + width: button.extend.iconSize.lg, + }, + base: { + height: button.extend.iconSize.md, + width: button.extend.iconSize.md, + }, + small: { + height: button.extend.iconSize.sm, + width: button.extend.iconSize.sm, + }, }, - large: { - height: typography.Size['text-2xl'], - width: typography.Size['text-2xl'], + variant: { + primary: { color: button.colorScheme.root.primary.color }, + secondary: { color: button.colorScheme.root.secondary.color }, + tertiary: { color: button.colorScheme.root.contrast.color }, + text: { color: button.colorScheme.text.primary.color }, + link: { color: button.colorScheme.link.color }, + basic: { color: button.colorScheme.root.primary.color }, + outlined: { color: button.colorScheme.outlined.primary.color }, }, - base: { - height: typography.Size['text-xl'], - width: typography.Size['text-xl'], + severity: { info: {}, success: {}, warning: {}, danger: {} }, + pressed: { true: {}, false: {} }, + disabled: { true: { color: button.extend.disabledColor }, false: {} }, + }, + compoundVariants: [ + // link pressed + { + variant: 'link', + pressed: 'true', + styles: { color: semantic.colorScheme.color.fg.muted }, }, - small: { - height: typography.Size['text-base'], - width: typography.Size['text-base'], - }, - }, - variant: { - primary: { color: theme.Button.Brand.buttonTextColor }, - secondary: { color: theme.Button.Primary.secondaryButtonTextColor }, - tertiary: { color: theme.Button.Secondary.helpButtonTextColor }, - text: { color: theme.Button.Text.textButtonTextColor }, - link: { color: theme.Button.Text.textButtonTextColor }, - basic: { color: theme.Button.Brand.buttonTextColor }, - outlined: { color: theme.Button.Brand.buttonTextColor }, - }, - severity: { info: {}, success: {}, warning: {}, danger: {} }, - pressed: { true: {}, false: {} }, - disabled: { - true: { color: theme.Button.Disabled.disabledButtonTextColor }, - false: {}, - }, - }, - compoundVariants: [ - // link pressed - { - variant: 'link', - pressed: 'true', - styles: { color: typography.Color.Common['text-color-secondary'] }, - }, - // severity icon colors - { - variant: 'basic', - severity: 'info', - styles: { color: theme.Button.Severity.Info.Basic.infoButtonTextColor }, - }, - { - variant: 'outlined', - severity: 'info', - styles: { - color: - theme.Button.Severity.Info.Outlined.infoOutlinedButtonTextColor, + // severity icon colors + { + variant: 'basic', + severity: 'info', + styles: { color: button.colorScheme.root.info.color }, }, - }, - { - variant: 'text', - severity: 'info', - styles: { - color: theme.Button.Severity.Info.Text.infoTextButtonTextColor, + { + variant: 'outlined', + severity: 'info', + styles: { color: button.colorScheme.outlined.info.color }, }, - }, - { - variant: 'basic', - severity: 'success', - styles: { - color: theme.Button.Severity.Success.Basic.successButtonTextColor, + { + variant: 'text', + severity: 'info', + styles: { color: button.colorScheme.text.info.color }, }, - }, - { - variant: 'outlined', - severity: 'success', - styles: { - color: - theme.Button.Severity.Success.Outlined - .successOutlinedButtonTextColor, + { + variant: 'basic', + severity: 'success', + styles: { color: button.colorScheme.root.success.color }, }, - }, - { - variant: 'text', - severity: 'success', - styles: { - color: theme.Button.Severity.Success.Text.successTextButtonTextColor, + { + variant: 'outlined', + severity: 'success', + styles: { color: button.colorScheme.outlined.success.color }, }, - }, - { - variant: 'basic', - severity: 'warning', - styles: { - color: theme.Button.Severity.Warning.Basic.warningButtonTextColor, + { + variant: 'text', + severity: 'success', + styles: { color: button.colorScheme.text.success.color }, }, - }, - { - variant: 'outlined', - severity: 'warning', - styles: { - color: - theme.Button.Severity.Warning.Outlined - .warningOutlinedButtonTextColor, + { + variant: 'basic', + severity: 'warning', + styles: { color: button.colorScheme.root.warn.color }, }, - }, - { - variant: 'text', - severity: 'warning', - styles: { - color: theme.Button.Severity.Warning.Text.warningTextButtonTextColor, + { + variant: 'outlined', + severity: 'warning', + styles: { color: button.colorScheme.outlined.warn.color }, }, - }, - { - variant: 'basic', - severity: 'danger', - styles: { - color: theme.Button.Severity.Danger.Basic.dangerButtonTextColor, + { + variant: 'text', + severity: 'warning', + styles: { color: button.colorScheme.text.warn.color }, }, - }, - { - variant: 'outlined', - severity: 'danger', - styles: { - color: - theme.Button.Severity.Danger.Outlined.dangerOutlinedButtonTextColor, + { + variant: 'basic', + severity: 'danger', + styles: { color: button.colorScheme.root.danger.color }, }, - }, - { - variant: 'text', - severity: 'danger', - styles: { - color: theme.Button.Severity.Danger.Text.dangerTextButtonTextColor, + { + variant: 'outlined', + severity: 'danger', + styles: { color: button.colorScheme.outlined.danger.color }, }, - }, - ], - }, -})) + { + variant: 'text', + severity: 'danger', + styles: { color: button.colorScheme.text.danger.color }, + }, + ], + }, + }) +) diff --git a/src/components/Button/utils/ButtonLabel.tsx b/src/components/Button/utils/ButtonLabel.tsx index 5b541a60..22e315f8 100644 --- a/src/components/Button/utils/ButtonLabel.tsx +++ b/src/components/Button/utils/ButtonLabel.tsx @@ -48,132 +48,103 @@ const ButtonLabelComponent = ({ export const ButtonLabel = genericMemo(ButtonLabelComponent) -const buttonLabelStyles = StyleSheet.create(({ theme, typography, fonts }) => ({ - label: { - fontWeight: 600, - includeFontPadding: false, - verticalAlign: 'middle', - fontFamily: fonts.primary, - variants: { - size: { - xlarge: { fontSize: typography.Size['text-xl'] }, - large: { fontSize: typography.Size['text-xl'] }, - base: { fontSize: typography.Size['text-base'] }, - small: { fontSize: typography.Size['text-sm'] }, - }, - variant: { - primary: { color: theme.Button.Brand.buttonTextColor }, - secondary: { color: theme.Button.Primary.secondaryButtonTextColor }, - tertiary: { color: theme.Button.Secondary.helpButtonTextColor }, - text: { color: theme.Button.Text.textButtonTextColor }, - link: { color: theme.Button.Text.textButtonTextColor }, - basic: { color: theme.Button.Brand.buttonTextColor }, - outlined: { color: theme.Button.Brand.buttonTextColor }, - }, - severity: { info: {}, success: {}, warning: {}, danger: {} }, - pressed: { true: {}, false: {} }, - disabled: { - true: { color: theme.Button.Disabled.disabledButtonTextColor }, - false: {}, - }, - }, - compoundVariants: [ - // link pressed color change - { - variant: 'link', - pressed: 'true', - styles: { color: typography.Color.Common['text-color-secondary'] }, - }, +const buttonLabelStyles = StyleSheet.create( + ({ components: { button }, semantic, fonts }) => ({ + label: { + fontWeight: fonts.fontWeight.demibold, + includeFontPadding: false, + verticalAlign: 'middle', + fontFamily: fonts.fontFamily.heading, + variants: { + size: { + xlarge: { fontSize: fonts.fontSize[500] }, + large: { fontSize: fonts.fontSize[500] }, + base: { fontSize: fonts.fontSize[300] }, + small: { fontSize: fonts.fontSize[100] }, + }, + variant: { + primary: { color: button.colorScheme.root.primary.color }, + secondary: { color: button.colorScheme.root.secondary.color }, + tertiary: { color: button.colorScheme.root.contrast.color }, + text: { color: button.colorScheme.text.primary.color }, + link: { color: button.colorScheme.link.color }, + basic: { color: button.colorScheme.root.primary.color }, + outlined: { color: button.colorScheme.outlined.primary.color }, + }, + severity: { info: {}, success: {}, warning: {}, danger: {} }, + pressed: { true: {}, false: {} }, + disabled: { true: { color: button.extend.disabledColor }, false: {} }, + }, + compoundVariants: [ + // link pressed color change + { + variant: 'link', + pressed: 'true', + styles: { color: semantic.colorScheme.color.fg.muted }, + }, - // severity label colors - { - variant: 'basic', - severity: 'info', - styles: { color: theme.Button.Severity.Info.Basic.infoButtonTextColor }, - }, - { - variant: 'outlined', - severity: 'info', - styles: { - color: - theme.Button.Severity.Info.Outlined.infoOutlinedButtonTextColor, + // severity label colors + { + variant: 'basic', + severity: 'info', + styles: { color: button.colorScheme.root.info.color }, }, - }, - { - variant: 'text', - severity: 'info', - styles: { - color: theme.Button.Severity.Info.Text.infoTextButtonTextColor, + { + variant: 'outlined', + severity: 'info', + styles: { color: button.colorScheme.outlined.info.color }, }, - }, - { - variant: 'basic', - severity: 'success', - styles: { - color: theme.Button.Severity.Success.Basic.successButtonTextColor, + { + variant: 'text', + severity: 'info', + styles: { color: button.colorScheme.text.info.color }, }, - }, - { - variant: 'outlined', - severity: 'success', - styles: { - color: - theme.Button.Severity.Success.Outlined - .successOutlinedButtonTextColor, + { + variant: 'basic', + severity: 'success', + styles: { color: button.colorScheme.root.success.color }, }, - }, - { - variant: 'text', - severity: 'success', - styles: { - color: theme.Button.Severity.Success.Text.successTextButtonTextColor, + { + variant: 'outlined', + severity: 'success', + styles: { color: button.colorScheme.outlined.success.color }, }, - }, - { - variant: 'basic', - severity: 'warning', - styles: { - color: theme.Button.Severity.Warning.Basic.warningButtonTextColor, + { + variant: 'text', + severity: 'success', + styles: { color: button.colorScheme.text.success.color }, }, - }, - { - variant: 'outlined', - severity: 'warning', - styles: { - color: - theme.Button.Severity.Warning.Outlined - .warningOutlinedButtonTextColor, + { + variant: 'basic', + severity: 'warning', + styles: { color: button.colorScheme.root.warn.color }, }, - }, - { - variant: 'text', - severity: 'warning', - styles: { - color: theme.Button.Severity.Warning.Text.warningTextButtonTextColor, + { + variant: 'outlined', + severity: 'warning', + styles: { color: button.colorScheme.outlined.warn.color }, }, - }, - { - variant: 'basic', - severity: 'danger', - styles: { - color: theme.Button.Severity.Danger.Basic.dangerButtonTextColor, + { + variant: 'text', + severity: 'warning', + styles: { color: button.colorScheme.text.warn.color }, }, - }, - { - variant: 'outlined', - severity: 'danger', - styles: { - color: - theme.Button.Severity.Danger.Outlined.dangerOutlinedButtonTextColor, + { + variant: 'basic', + severity: 'danger', + styles: { color: button.colorScheme.root.danger.color }, }, - }, - { - variant: 'text', - severity: 'danger', - styles: { - color: theme.Button.Severity.Danger.Text.dangerTextButtonTextColor, + { + variant: 'outlined', + severity: 'danger', + styles: { color: button.colorScheme.outlined.danger.color }, }, - }, - ], - }, -})) + { + variant: 'text', + severity: 'danger', + styles: { color: button.colorScheme.text.danger.color }, + }, + ], + }, + }) +) From 16088baf05bb6953391609a3e94aea5edf47d89d Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:42 +0300 Subject: [PATCH 19/60] =?UTF-8?q?feat(Checkbox):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Checkbox/Checkbox.tsx | 49 ++++++------- .../__snapshots__/Checkbox.test.tsx.snap | 73 ++++++++----------- 2 files changed, 52 insertions(+), 70 deletions(-) diff --git a/src/components/Checkbox/Checkbox.tsx b/src/components/Checkbox/Checkbox.tsx index 41a89bf7..b1e3b144 100644 --- a/src/components/Checkbox/Checkbox.tsx +++ b/src/components/Checkbox/Checkbox.tsx @@ -97,9 +97,9 @@ export const Checkbox = memo( ({ - color: theme.Form.Checkbox.checkboxIconActiveColor, - })} + uniProps={({ components }) => { + return { color: components.checkbox.icon.checkedColor } + }} /> ) : null} @@ -107,57 +107,52 @@ export const Checkbox = memo( } ) -const styles = StyleSheet.create(({ theme, border, sizing }) => ({ +const styles = StyleSheet.create(({ components, semantic }) => ({ container: { justifyContent: 'center', alignItems: 'center', - width: theme.Form.Checkbox.checkboxWidth, - height: theme.Form.Checkbox.checkboxHeight, + width: components.checkbox.root.width, + height: components.checkbox.root.height, }, background: { ...RNStyleSheet.absoluteFillObject }, backgroundState: { - borderRadius: border.Radius['rounded-lg'], - borderWidth: border.Width.border, + borderRadius: components.checkbox.root.borderRadius, + borderWidth: components.checkbox.root.extend.borderWidth, variants: { filled: { true: { - backgroundColor: theme.Form.Checkbox.checkboxActiveBg, - borderColor: theme.Form.Checkbox.checkboxActiveBorderColor, + backgroundColor: components.checkbox.root.checkedBackground, + borderColor: components.checkbox.root.checkedBorderColor, }, false: { - backgroundColor: theme.Form.InputText.inputBg, - borderColor: theme.Form.InputText.inputBorderColor, + backgroundColor: components.checkbox.root.background, + borderColor: components.checkbox.root.borderColor, }, }, pressed: { - true: { borderColor: theme.Form.InputText.inputHoverBorderColor }, + true: { borderColor: components.checkbox.root.hoverBorderColor }, false: {}, }, state: { - danger: { - borderColor: theme.Form.InputText.inputErrorBorderColor, - outlineStyle: 'solid', - outlineColor: theme.General.focusOutlineErrorColor, - outlineWidth: Math.round(theme.General.focusShadowWidth), - }, + danger: { borderColor: components.checkbox.root.invalidBorderColor }, }, - disabled: { true: { outlineWidth: 0 }, false: {} }, + disabled: { true: {}, false: {} }, }, compoundVariants: [ { filled: 'true', pressed: 'true', styles: { - backgroundColor: theme.Form.Checkbox.checkboxActiveHoverBg, - borderColor: theme.Form.Checkbox.checkboxActiveHoverBorderColor, + backgroundColor: components.checkbox.root.checkedHoverBackground, + borderColor: components.checkbox.root.checkedHoverBorderColor, }, }, { filled: 'false', disabled: 'true', styles: { - backgroundColor: theme.Button.Disabled.disabledButtonBg, - borderColor: theme.Form.InputText.inputBorderColor, + backgroundColor: components.checkbox.root.disabledBackground, + borderColor: components.checkbox.root.borderColor, mixBlendMode: 'luminosity', }, }, @@ -165,12 +160,12 @@ const styles = StyleSheet.create(({ theme, border, sizing }) => ({ filled: 'true', disabled: 'true', styles: { - borderColor: theme.Form.Checkbox.checkboxActiveBorderColor, - opacity: 0.2, + borderColor: components.checkbox.root.checkedBorderColor, + opacity: semantic.effects.opacity[20], mixBlendMode: 'luminosity', }, }, ], }, - icon: { height: sizing.Height['h-1'], width: sizing.Width['w-1'] }, + icon: { height: 14, width: 14 }, })) diff --git a/src/components/Checkbox/__tests__/__snapshots__/Checkbox.test.tsx.snap b/src/components/Checkbox/__tests__/__snapshots__/Checkbox.test.tsx.snap index 872efcb8..11e41577 100644 --- a/src/components/Checkbox/__tests__/__snapshots__/Checkbox.test.tsx.snap +++ b/src/components/Checkbox/__tests__/__snapshots__/Checkbox.test.tsx.snap @@ -36,9 +36,9 @@ exports[`Checkbox snapshots checked = false, indeterminate = false, disabled = f style={ { "alignItems": "center", - "height": 21, + "height": 24, "justifyContent": "center", - "width": 21, + "width": 24, } } testID="CheckboxButton_Pressable" @@ -55,12 +55,9 @@ exports[`Checkbox snapshots checked = false, indeterminate = false, disabled = f }, { "backgroundColor": "#ffffff", - "borderColor": "#db3424", - "borderRadius": 7, + "borderColor": "#f47f77", + "borderRadius": 8, "borderWidth": 1, - "outlineColor": "#fff0f0", - "outlineStyle": "solid", - "outlineWidth": 4, }, ] } @@ -104,9 +101,9 @@ exports[`Checkbox snapshots checked = false, indeterminate = false, disabled = f style={ { "alignItems": "center", - "height": 21, + "height": 24, "justifyContent": "center", - "width": 21, + "width": 24, } } testID="CheckboxButton_Pressable" @@ -124,7 +121,7 @@ exports[`Checkbox snapshots checked = false, indeterminate = false, disabled = f { "backgroundColor": "#ffffff", "borderColor": "#cecfd2", - "borderRadius": 7, + "borderRadius": 8, "borderWidth": 1, }, ] @@ -169,9 +166,9 @@ exports[`Checkbox snapshots checked = true, indeterminate = false, disabled = fa style={ { "alignItems": "center", - "height": 21, + "height": 24, "justifyContent": "center", - "width": 21, + "width": 24, } } testID="CheckboxButton_Pressable" @@ -188,12 +185,9 @@ exports[`Checkbox snapshots checked = true, indeterminate = false, disabled = fa }, { "backgroundColor": "#2b2e33", - "borderColor": "#db3424", - "borderRadius": 7, + "borderColor": "#f47f77", + "borderRadius": 8, "borderWidth": 1, - "outlineColor": "#fff0f0", - "outlineStyle": "solid", - "outlineWidth": 4, }, ] } @@ -316,9 +310,9 @@ exports[`Checkbox snapshots checked = true, indeterminate = false, disabled = fa style={ { "alignItems": "center", - "height": 21, + "height": 24, "justifyContent": "center", - "width": 21, + "width": 24, } } testID="CheckboxButton_Pressable" @@ -336,7 +330,7 @@ exports[`Checkbox snapshots checked = true, indeterminate = false, disabled = fa { "backgroundColor": "#2b2e33", "borderColor": "#2b2e33", - "borderRadius": 7, + "borderRadius": 8, "borderWidth": 1, }, ] @@ -460,9 +454,9 @@ exports[`Checkbox snapshots checked = true, indeterminate = true, disabled = fal style={ { "alignItems": "center", - "height": 21, + "height": 24, "justifyContent": "center", - "width": 21, + "width": 24, } } testID="CheckboxButton_Pressable" @@ -479,12 +473,9 @@ exports[`Checkbox snapshots checked = true, indeterminate = true, disabled = fal }, { "backgroundColor": "#2b2e33", - "borderColor": "#db3424", - "borderRadius": 7, + "borderColor": "#f47f77", + "borderRadius": 8, "borderWidth": 1, - "outlineColor": "#fff0f0", - "outlineStyle": "solid", - "outlineWidth": 4, }, ] } @@ -607,9 +598,9 @@ exports[`Checkbox snapshots checked = true, indeterminate = true, disabled = fal style={ { "alignItems": "center", - "height": 21, + "height": 24, "justifyContent": "center", - "width": 21, + "width": 24, } } testID="CheckboxButton_Pressable" @@ -627,7 +618,7 @@ exports[`Checkbox snapshots checked = true, indeterminate = true, disabled = fal { "backgroundColor": "#2b2e33", "borderColor": "#2b2e33", - "borderRadius": 7, + "borderRadius": 8, "borderWidth": 1, }, ] @@ -751,9 +742,9 @@ exports[`Checkbox snapshots checked = true, indeterminate = true, disabled = tru style={ { "alignItems": "center", - "height": 21, + "height": 24, "justifyContent": "center", - "width": 21, + "width": 24, } } testID="CheckboxButton_Pressable" @@ -771,13 +762,10 @@ exports[`Checkbox snapshots checked = true, indeterminate = true, disabled = tru { "backgroundColor": "#2b2e33", "borderColor": "#2b2e33", - "borderRadius": 7, + "borderRadius": 8, "borderWidth": 1, "mixBlendMode": "luminosity", "opacity": 0.2, - "outlineColor": "#fff0f0", - "outlineStyle": "solid", - "outlineWidth": 0, }, ] } @@ -900,9 +888,9 @@ exports[`Checkbox snapshots checked = true, indeterminate = true, disabled = tru style={ { "alignItems": "center", - "height": 21, + "height": 24, "justifyContent": "center", - "width": 21, + "width": 24, } } testID="CheckboxButton_Pressable" @@ -920,11 +908,10 @@ exports[`Checkbox snapshots checked = true, indeterminate = true, disabled = tru { "backgroundColor": "#2b2e33", "borderColor": "#2b2e33", - "borderRadius": 7, + "borderRadius": 8, "borderWidth": 1, "mixBlendMode": "luminosity", "opacity": 0.2, - "outlineWidth": 0, }, ] } @@ -1047,9 +1034,9 @@ exports[`Checkbox snapshots default 1`] = ` style={ { "alignItems": "center", - "height": 21, + "height": 24, "justifyContent": "center", - "width": 21, + "width": 24, } } testID="CheckboxButton_Pressable" @@ -1067,7 +1054,7 @@ exports[`Checkbox snapshots default 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#cecfd2", - "borderRadius": 7, + "borderRadius": 8, "borderWidth": 1, }, ] From c7b0ea32b881b92f3c02b9b717636069bbe3b9c7 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:43 +0300 Subject: [PATCH 20/60] =?UTF-8?q?feat(Chip):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Chip/Chip.tsx | 76 +-- .../__snapshots__/Chip.test.tsx.snap | 512 +++++++++--------- 2 files changed, 288 insertions(+), 300 deletions(-) diff --git a/src/components/Chip/Chip.tsx b/src/components/Chip/Chip.tsx index 921f630b..fffcb528 100644 --- a/src/components/Chip/Chip.tsx +++ b/src/components/Chip/Chip.tsx @@ -5,9 +5,11 @@ import { Text, Pressable, type PressableProps } from 'react-native' import { StyleSheet } from 'react-native-unistyles' -import type { ThemeType } from '../../theme/types' - -import { type SvgSource, SvgUniversal } from '../../utils/SvgUniversal' +import { + type SvgSource, + SvgUniversal, + type SvgUniversalTheme, +} from '../../utils/SvgUniversal' export interface ChipProps extends PressableProps { /** SVG-иконка */ @@ -44,11 +46,13 @@ export const Chip = memo( showIcon = true, ...rest }) => { - const iconUniProps = ({ theme }: ThemeType) => ({ - color: disabled - ? theme.Button.Disabled.disabledButtonTextColor - : theme.Misc.Chip.chipTextColor, - }) + const iconUniProps = ({ components, semantic }: SvgUniversalTheme) => { + return { + color: disabled + ? semantic.colorScheme.color.fg.muted + : components.chip.colorScheme.root.color, + } + } return ( ( {...styles.icon} source={IconX} style={pressed ? styles.pressedClose : null} - uniProps={({ theme }) => ({ - color: disabled - ? theme.Button.Disabled.disabledButtonTextColor - : theme.Misc.Chip.chipTextColor, - })} + uniProps={({ components, semantic }) => { + return { + color: disabled + ? semantic.colorScheme.color.fg.muted + : components.chip.colorScheme.root.color, + } + }} /> )} @@ -97,46 +103,44 @@ export const Chip = memo( } ) -const styles = StyleSheet.create(({ theme, typography, border, fonts }) => ({ +// `transparent` здесь — отсутствие границы, а не цвет дизайн-системы: +// у chip.root нет borderColor, прозрачность не выражена semantic-токеном. +const styles = StyleSheet.create(({ components, semantic, fonts }) => ({ chip: { - height: theme.Misc.Chip.chipHeight, alignSelf: 'flex-start', justifyContent: 'center', alignItems: 'center', flexDirection: 'row', - gap: theme.General.inlineSpacing, + gap: components.chip.root.gap, - paddingHorizontal: theme.Misc.Chip.chipPaddingLeftRight, - paddingVertical: theme.Misc.Chip.chipPaddingTopBottom, + paddingHorizontal: components.chip.root.paddingX, + paddingVertical: components.chip.root.paddingY, - borderRadius: theme.Misc.Chip.chipBorderRadius, - borderWidth: border.Width.border, + borderRadius: components.chip.root.borderRadius, + borderWidth: components.chip.extend.borderWidth, - backgroundColor: theme.Misc.Chip.chipBg, - borderColor: theme.Misc.Chip.chipBorderColor, + backgroundColor: components.chip.colorScheme.root.background, + borderColor: components.chip.extend.borderColor, }, disabledChip: { - backgroundColor: theme.Button.Disabled.disabledButtonBg, - borderColor: theme.Button.Disabled.disabledButtonBorderColor, - opacity: 0.6, + backgroundColor: semantic.colorScheme.color.bg.neutral.weak.disabled, + borderColor: 'transparent', + opacity: semantic.effects.opacity[60], mixBlendMode: 'luminosity', }, - icon: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], - }, + icon: { width: components.chip.icon.size, height: components.chip.icon.size }, text: { - fontSize: typography.Size['text-base'], + fontSize: fonts.fontSize[300], verticalAlign: 'middle', - color: theme.Misc.Chip.chipTextColor, + color: components.chip.colorScheme.root.color, includeFontPadding: false, - fontFamily: fonts.secondary, + fontFamily: fonts.fontFamily.base, }, - disabledText: { color: theme.General.textSecondaryColor }, + disabledText: { color: semantic.colorScheme.color.fg.muted }, pressedClose: { - borderWidth: border.Width['border-3'], - borderColor: border.Color.Service['border-success'][400], - borderRadius: border.Radius['rounded-full'], + borderWidth: semantic.dimension.borderWidth[300], + borderColor: semantic.colorScheme.color.border.status.success.strong, + borderRadius: semantic.dimension.borderRadius.max, }, })) diff --git a/src/components/Chip/__tests__/__snapshots__/Chip.test.tsx.snap b/src/components/Chip/__tests__/__snapshots__/Chip.test.tsx.snap index d7fe5652..6df9070f 100644 --- a/src/components/Chip/__tests__/__snapshots__/Chip.test.tsx.snap +++ b/src/components/Chip/__tests__/__snapshots__/Chip.test.tsx.snap @@ -42,16 +42,15 @@ exports[`Chip component tests { { "alignItems": "center", "alignSelf": "flex-start", - "backgroundColor": "#f0f0f1", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 7, + "backgroundColor": "#e2e2e4", + "borderColor": "transparent", + "borderRadius": 8, "borderWidth": 1, "flexDirection": "row", - "gap": 7, - "height": 24.5, + "gap": 8, "justifyContent": "center", - "paddingHorizontal": 7, - "paddingVertical": 0, + "paddingHorizontal": 8, + "paddingVertical": 4, }, undefined, ] @@ -63,9 +62,9 @@ exports[`Chip component tests { style={ [ { - "color": "#181a1f", + "color": "#2b2e33", "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, "verticalAlign": "middle", }, @@ -120,16 +119,15 @@ exports[`Chip component tests { { "alignItems": "center", "alignSelf": "flex-start", - "backgroundColor": "#f0f0f1", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 7, + "backgroundColor": "#e2e2e4", + "borderColor": "transparent", + "borderRadius": 8, "borderWidth": 1, "flexDirection": "row", - "gap": 7, - "height": 24.5, + "gap": 8, "justifyContent": "center", - "paddingHorizontal": 7, - "paddingVertical": 0, + "paddingHorizontal": 8, + "paddingVertical": 4, }, undefined, ] @@ -138,15 +136,15 @@ exports[`Chip component tests { > Date: Tue, 4 Aug 2026 17:05:43 +0300 Subject: [PATCH 21/60] =?UTF-8?q?feat(Dialog):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Dialog/DialogComponent.tsx | 18 +- src/components/Dialog/DialogHeader.tsx | 47 +- .../__snapshots__/Dialog.test.tsx.snap | 10 +- .../__snapshots__/DialogHeader.test.tsx.snap | 440 +++++++++--------- 4 files changed, 264 insertions(+), 251 deletions(-) diff --git a/src/components/Dialog/DialogComponent.tsx b/src/components/Dialog/DialogComponent.tsx index 04c95534..15a8a63b 100644 --- a/src/components/Dialog/DialogComponent.tsx +++ b/src/components/Dialog/DialogComponent.tsx @@ -36,18 +36,16 @@ export const DialogComponent: React.FC = ({ ) } -const styles = StyleSheet.create(({ theme }) => ({ +const styles = StyleSheet.create(({ components }) => ({ root: { - backgroundColor: theme.Overlay.Dialog.Header.dialogHeaderBg, - borderColor: theme.Overlay.Overlay.overlayContentBorderColor, - borderRadius: theme.General.borderRadius2XL, - }, - body: { - paddingVertical: theme.Overlay.Dialog.Body.dialogContentPaddingTopBottom, - paddingHorizontal: theme.Overlay.Dialog.Body.dialogContentPaddingLeftRight, + backgroundColor: components.dialog.root.background, + borderColor: components.dialog.root.borderColor, + borderRadius: components.dialog.root.borderRadius, }, + body: { padding: components.dialog.content.padding }, footer: { - paddingBottom: theme.Overlay.Dialog.Footer.dialogFooterPaddingLeftRight, - paddingHorizontal: theme.Overlay.Dialog.Footer.dialogFooterPaddingLeftRight, + paddingTop: components.dialog.footer.paddingTop, + paddingBottom: components.dialog.footer.paddingBottom, + paddingHorizontal: components.dialog.footer.paddingLeft, }, })) diff --git a/src/components/Dialog/DialogHeader.tsx b/src/components/Dialog/DialogHeader.tsx index f6dd8042..3620dd43 100644 --- a/src/components/Dialog/DialogHeader.tsx +++ b/src/components/Dialog/DialogHeader.tsx @@ -46,15 +46,17 @@ export const DialogHeader = ({ ({ - color: { - danger: t.Color.Service['text-danger'], - warning: t.Color.Service['text-warning'], - info: t.Color.Service['text-info'], - success: t.Color.Service['text-success'], - help: t.Color.Service['text-help'], - }[severity], - })} + uniProps={({ semantic }) => { + return { + color: { + danger: semantic.colorScheme.color.fg.status.danger.default, + warning: semantic.colorScheme.color.fg.status.warning.default, + info: semantic.colorScheme.color.fg.status.info.default, + success: semantic.colorScheme.color.fg.status.success.default, + help: semantic.colorScheme.color.fg.status.help.default, + }[severity], + } + }} /> ) }, [severity]) @@ -75,9 +77,9 @@ export const DialogHeader = ({ ({ - color: theme.General.actionIconColor, - })} + uniProps={({ components }) => { + return { color: components.dialog.root.color } + }} /> ) : null} @@ -88,27 +90,28 @@ export const DialogHeader = ({ ) } -const styles = StyleSheet.create(({ theme, spacing, typography, border }) => ({ +const styles = StyleSheet.create(({ components, semantic }) => ({ text: { flex: 1 }, header: { flexDirection: 'row', - gap: spacing.Gap['gap-4'], + gap: components.dialog.header.gap, alignItems: 'center', - paddingBottom: theme.Overlay.Dialog.Header.dialogHeaderPaddingTopBottom, - padding: theme.Overlay.Dialog.Header.dialogHeaderPaddingLeftRight, + paddingTop: components.dialog.header.paddingTop, + paddingBottom: components.dialog.header.paddingBottom, + paddingHorizontal: components.dialog.header.paddingLeft, }, closeTouchable: { padding: 8 }, separator: { - height: border.Width.border, - backgroundColor: theme.Overlay.Overlay.overlayContentBorderColor, + height: semantic.dimension.borderWidth[100], + backgroundColor: components.dialog.root.borderColor, }, closeIcon: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], + width: semantic.dimension.size[450], + height: semantic.dimension.size[450], }, severityIcon: { - width: typography.Size['text-2xl'], - height: typography.Size['text-2xl'], + width: semantic.dimension.size[700], + height: semantic.dimension.size[700], }, })) diff --git a/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap b/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap index 77efd620..8fd76ec3 100644 --- a/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap +++ b/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap @@ -128,7 +128,7 @@ exports[`Dialog component tests basic dialog with title, body and footer 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#e2e2e4", - "borderRadius": 14, + "borderRadius": 1600, }, { "maxHeight": 1234, @@ -143,8 +143,7 @@ exports[`Dialog component tests basic dialog with title, body and footer 1`] = ` @@ -155,8 +154,9 @@ exports[`Dialog component tests basic dialog with title, body and footer 1`] = ` diff --git a/src/components/Dialog/__tests__/__snapshots__/DialogHeader.test.tsx.snap b/src/components/Dialog/__tests__/__snapshots__/DialogHeader.test.tsx.snap index 5bc35562..92567dca 100644 --- a/src/components/Dialog/__tests__/__snapshots__/DialogHeader.test.tsx.snap +++ b/src/components/Dialog/__tests__/__snapshots__/DialogHeader.test.tsx.snap @@ -7,23 +7,24 @@ exports[`DialogHeader {"onClose": [Function mockConstructor], "severity": "dange { "alignItems": "center", "flexDirection": "row", - "gap": 14, - "padding": 21, + "gap": 8, "paddingBottom": 14, + "paddingHorizontal": 24, + "paddingTop": 24, } } > @@ -1526,14 +1532,14 @@ exports[`DialogHeader {"onClose": [Function mockConstructor], "severity": undefi style={ [ { - "color": "#181a1f", + "color": "#2b2e33", "fontFamily": "TT Fellows", "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", }, { - "fontSize": 15.75, + "fontSize": 18, }, { "flex": 1, @@ -1582,15 +1588,15 @@ exports[`DialogHeader {"onClose": [Function mockConstructor], "severity": undefi > @@ -2526,14 +2538,14 @@ exports[`DialogHeader {"onClose": undefined, "severity": undefined, "title": "Di style={ [ { - "color": "#181a1f", + "color": "#2b2e33", "fontFamily": "TT Fellows", "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", }, { - "fontSize": 15.75, + "fontSize": 18, }, { "flex": 1, From 8e51db65afd47d7db198b559d592bb36b27e1ea5 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:44 +0300 Subject: [PATCH 22/60] =?UTF-8?q?feat(Divider):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Divider/Divider.tsx | 32 +++++----- .../__snapshots__/Divider.test.tsx.snap | 64 +++++++++---------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/components/Divider/Divider.tsx b/src/components/Divider/Divider.tsx index f12c2367..2cf5964a 100644 --- a/src/components/Divider/Divider.tsx +++ b/src/components/Divider/Divider.tsx @@ -111,9 +111,9 @@ export const Divider = memo( ({ - color: theme.General.textSecondaryColor, - })} + uniProps={({ components }) => { + return { color: components.divider.content.color } + }} /> ) : null} {text ? ( @@ -133,15 +133,15 @@ export const Divider = memo( } ) -const styles = StyleSheet.create(({ spacing, theme, sizing, typography }) => ({ +const styles = StyleSheet.create(({ components, semantic }) => ({ container: { - minHeight: sizing.Height['h-2'], + minHeight: semantic.dimension.size[800], flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, containerVertical: { - minWidth: sizing.Width['w-2'], + minWidth: semantic.dimension.size[800], flexDirection: 'column', flexGrow: 1, alignSelf: 'flex-start', @@ -150,7 +150,7 @@ const styles = StyleSheet.create(({ spacing, theme, sizing, typography }) => ({ containerColumnReverse: { flexDirection: 'column-reverse' }, lineContainer: { flexGrow: 1, - flexBasis: spacing.Gap['gap-4'], + flexBasis: semantic.dimension.space[400], width: 1, height: 1, overflow: 'hidden', @@ -159,25 +159,25 @@ const styles = StyleSheet.create(({ spacing, theme, sizing, typography }) => ({ line: { width: '100%', height: '100%', - borderWidth: 1, - borderColor: theme.General.dividerColor, + borderWidth: semantic.dimension.borderWidth[100], + borderColor: components.divider.root.borderColor, }, lineDash: { borderStyle: 'dashed' }, content: { flexShrink: 1, flexDirection: 'row', alignItems: 'center', - paddingHorizontal: theme.General.inlineSpacing, - gap: spacing.Gap['gap-2'], - backgroundColor: theme.Panel.Panel.Body.panelContentBg, + paddingHorizontal: semantic.dimension.space[200], + gap: components.divider.extend.content.gap, + backgroundColor: components.divider.content.background, }, contentVertical: { - paddingHorizontal: 0, - paddingVertical: theme.General.inlineSpacing, + paddingHorizontal: semantic.dimension.space.none, + paddingVertical: semantic.dimension.space[200], }, icon: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], + width: components.divider.extend.iconSize, + height: components.divider.extend.iconSize, }, text: { flexShrink: 1 }, })) diff --git a/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap b/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap index 59628323..a632247d 100644 --- a/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap +++ b/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap @@ -102,11 +102,11 @@ exports[`Divider {"Icon": [Object], "align": "end", "layout": "horizontal", "sho [ { "alignItems": "center", - "backgroundColor": "#f0f0f1", + "backgroundColor": "#ffffff", "flexDirection": "row", "flexShrink": 1, - "gap": 7, - "paddingHorizontal": 7, + "gap": 8, + "paddingHorizontal": 8, }, false, ] @@ -117,9 +117,9 @@ exports[`Divider {"Icon": [Object], "align": "end", "layout": "horizontal", "sho [ { "fontFamily": "Noto Sans", - "fontSize": 10.5, + "fontSize": 12, "fontWeight": 700, - "lineHeight": 15, + "lineHeight": 18, "textTransform": "uppercase", }, { @@ -273,30 +273,30 @@ exports[`Divider {"Icon": [Object], "align": "end", "layout": "vertical", "text" [ { "alignItems": "center", - "backgroundColor": "#f0f0f1", + "backgroundColor": "#ffffff", "flexDirection": "row", "flexShrink": 1, - "gap": 7, - "paddingHorizontal": 7, + "gap": 8, + "paddingHorizontal": 8, }, { "paddingHorizontal": 0, - "paddingVertical": 7, + "paddingVertical": 8, }, ] } > Date: Tue, 4 Aug 2026 17:05:44 +0300 Subject: [PATCH 23/60] =?UTF-8?q?feat(InputSwitch):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__snapshots__/InputSwitch.test.tsx.snap | 736 +++++++++--------- .../InputSwitch/styles/useHandleStyles.ts | 26 +- .../InputSwitch/styles/useSliderStyles.ts | 38 +- 3 files changed, 399 insertions(+), 401 deletions(-) diff --git a/src/components/Input/InputSwitch/__tests__/__snapshots__/InputSwitch.test.tsx.snap b/src/components/Input/InputSwitch/__tests__/__snapshots__/InputSwitch.test.tsx.snap index 43c39801..9b89404e 100644 --- a/src/components/Input/InputSwitch/__tests__/__snapshots__/InputSwitch.test.tsx.snap +++ b/src/components/Input/InputSwitch/__tests__/__snapshots__/InputSwitch.test.tsx.snap @@ -33,8 +33,8 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -52,25 +52,25 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#85888e"", + "backgroundColor": ""#a2a5a9"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#85888e", + "backgroundColor": "#a2a5a9", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -90,24 +90,24 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - jestInlineStyle={ { "backgroundColor": ""#ffffff"", - "borderRadius": 100, - "height": 14, - "left": "2.5", + "borderRadius": 1600, + "height": 16, + "left": "3", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { "backgroundColor": "#ffffff", - "borderRadius": 100, - "height": 14, - "left": 2.5, + "borderRadius": 1600, + "height": 16, + "left": 3, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -149,8 +149,8 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -168,25 +168,25 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#85888e"", + "backgroundColor": ""#a2a5a9"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#85888e", + "backgroundColor": "#a2a5a9", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -206,24 +206,24 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - jestInlineStyle={ { "backgroundColor": ""#ffffff"", - "borderRadius": 100, - "height": 14, - "left": "2.5", + "borderRadius": 1600, + "height": 16, + "left": "3", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { "backgroundColor": "#ffffff", - "borderRadius": 100, - "height": 14, - "left": 2.5, + "borderRadius": 1600, + "height": 16, + "left": 3, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -265,8 +265,8 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -284,25 +284,25 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#DFDFDF"", + "backgroundColor": ""#e2e2e4"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#DFDFDF", + "backgroundColor": "#e2e2e4", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -322,24 +322,24 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - jestInlineStyle={ { "backgroundColor": ""#ffffff"", - "borderRadius": 100, - "height": 14, - "left": "2.5", + "borderRadius": 1600, + "height": 16, + "left": "3", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { "backgroundColor": "#ffffff", - "borderRadius": 100, - "height": 14, - "left": 2.5, + "borderRadius": 1600, + "height": 16, + "left": 3, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -381,8 +381,8 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -400,25 +400,25 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#DFDFDF"", + "backgroundColor": ""#e2e2e4"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#DFDFDF", + "backgroundColor": "#e2e2e4", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -438,24 +438,24 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - jestInlineStyle={ { "backgroundColor": ""#ffffff"", - "borderRadius": 100, - "height": 14, - "left": "2.5", + "borderRadius": 1600, + "height": 16, + "left": "3", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { "backgroundColor": "#ffffff", - "borderRadius": 100, - "height": 14, - "left": 2.5, + "borderRadius": 1600, + "height": 16, + "left": 3, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -497,8 +497,8 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -516,25 +516,25 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - } jestInlineStyle={ { - "backgroundColor": ""#85888e"", - "borderColor": ""#db3424"", - "borderRadius": 100, + "backgroundColor": ""#a2a5a9"", + "borderColor": ""#f47f77"", + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#85888e", - "borderColor": "#db3424", - "borderRadius": 100, + "backgroundColor": "#a2a5a9", + "borderColor": "#f47f77", + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -554,24 +554,24 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - jestInlineStyle={ { "backgroundColor": ""#ffffff"", - "borderRadius": 100, - "height": 14, - "left": "2.5", + "borderRadius": 1600, + "height": 16, + "left": "3", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { "backgroundColor": "#ffffff", - "borderRadius": 100, - "height": 14, - "left": 2.5, + "borderRadius": 1600, + "height": 16, + "left": 3, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -613,8 +613,8 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -632,25 +632,25 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - } jestInlineStyle={ { - "backgroundColor": ""#85888e"", - "borderColor": ""#db3424"", - "borderRadius": 100, + "backgroundColor": ""#a2a5a9"", + "borderColor": ""#f47f77"", + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#85888e", - "borderColor": "#db3424", - "borderRadius": 100, + "backgroundColor": "#a2a5a9", + "borderColor": "#f47f77", + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -670,24 +670,24 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - jestInlineStyle={ { "backgroundColor": ""#ffffff"", - "borderRadius": 100, - "height": 14, - "left": "2.5", + "borderRadius": 1600, + "height": 16, + "left": "3", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { "backgroundColor": "#ffffff", - "borderRadius": 100, - "height": 14, - "left": 2.5, + "borderRadius": 1600, + "height": 16, + "left": 3, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -729,8 +729,8 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -748,25 +748,25 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - } jestInlineStyle={ { - "backgroundColor": ""#DFDFDF"", + "backgroundColor": ""#e2e2e4"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#DFDFDF", + "backgroundColor": "#e2e2e4", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -786,24 +786,24 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - jestInlineStyle={ { "backgroundColor": ""#ffffff"", - "borderRadius": 100, - "height": 14, - "left": "2.5", + "borderRadius": 1600, + "height": 16, + "left": "3", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { "backgroundColor": "#ffffff", - "borderRadius": 100, - "height": 14, - "left": 2.5, + "borderRadius": 1600, + "height": 16, + "left": 3, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -845,8 +845,8 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -864,25 +864,25 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - } jestInlineStyle={ { - "backgroundColor": ""#DFDFDF"", + "backgroundColor": ""#e2e2e4"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#DFDFDF", + "backgroundColor": "#e2e2e4", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -902,24 +902,24 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - jestInlineStyle={ { "backgroundColor": ""#ffffff"", - "borderRadius": 100, - "height": 14, - "left": "2.5", + "borderRadius": 1600, + "height": 16, + "left": "3", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { "backgroundColor": "#ffffff", - "borderRadius": 100, - "height": 14, - "left": 2.5, + "borderRadius": 1600, + "height": 16, + "left": 3, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -961,8 +961,8 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -982,11 +982,11 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - { "backgroundColor": ""#2b2e33"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ @@ -994,11 +994,11 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - { "backgroundColor": "#2b2e33", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -1017,25 +1017,25 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#fafafa"", - "borderRadius": 100, - "height": 14, - "left": "16.5", + "backgroundColor": ""#ffffff"", + "borderRadius": 1600, + "height": 16, + "left": "19", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { - "backgroundColor": "#fafafa", - "borderRadius": 100, - "height": 14, - "left": 16.5, + "backgroundColor": "#ffffff", + "borderRadius": 1600, + "height": 16, + "left": 19, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -1077,8 +1077,8 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -1098,11 +1098,11 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - { "backgroundColor": ""#2b2e33"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ @@ -1110,11 +1110,11 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - { "backgroundColor": "#2b2e33", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -1133,25 +1133,25 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#fafafa"", - "borderRadius": 100, - "height": 14, - "left": "16.5", + "backgroundColor": ""#ffffff"", + "borderRadius": 1600, + "height": 16, + "left": "19", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { - "backgroundColor": "#fafafa", - "borderRadius": 100, - "height": 14, - "left": 16.5, + "backgroundColor": "#ffffff", + "borderRadius": 1600, + "height": 16, + "left": 19, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -1193,8 +1193,8 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -1212,25 +1212,25 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#9A9A9A"", + "backgroundColor": ""#e2e2e4"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#9A9A9A", + "backgroundColor": "#e2e2e4", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -1249,25 +1249,25 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#fafafa"", - "borderRadius": 100, - "height": 14, - "left": "16.5", + "backgroundColor": ""#ffffff"", + "borderRadius": 1600, + "height": 16, + "left": "19", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { - "backgroundColor": "#fafafa", - "borderRadius": 100, - "height": 14, - "left": 16.5, + "backgroundColor": "#ffffff", + "borderRadius": 1600, + "height": 16, + "left": 19, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -1309,8 +1309,8 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -1328,25 +1328,25 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#9A9A9A"", + "backgroundColor": ""#e2e2e4"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#9A9A9A", + "backgroundColor": "#e2e2e4", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -1365,25 +1365,25 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#fafafa"", - "borderRadius": 100, - "height": 14, - "left": "16.5", + "backgroundColor": ""#ffffff"", + "borderRadius": 1600, + "height": 16, + "left": "19", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { - "backgroundColor": "#fafafa", - "borderRadius": 100, - "height": 14, - "left": 16.5, + "backgroundColor": "#ffffff", + "borderRadius": 1600, + "height": 16, + "left": 19, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -1425,8 +1425,8 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - f onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -1445,24 +1445,24 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - f jestInlineStyle={ { "backgroundColor": ""#2b2e33"", - "borderColor": ""#db3424"", - "borderRadius": 100, + "borderColor": ""#f47f77"", + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { "backgroundColor": "#2b2e33", - "borderColor": "#db3424", - "borderRadius": 100, + "borderColor": "#f47f77", + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -1481,25 +1481,25 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - f } jestInlineStyle={ { - "backgroundColor": ""#fafafa"", - "borderRadius": 100, - "height": 14, - "left": "16.5", + "backgroundColor": ""#ffffff"", + "borderRadius": 1600, + "height": 16, + "left": "19", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { - "backgroundColor": "#fafafa", - "borderRadius": 100, - "height": 14, - "left": 16.5, + "backgroundColor": "#ffffff", + "borderRadius": 1600, + "height": 16, + "left": 19, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -1541,8 +1541,8 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - f onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -1561,24 +1561,24 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - f jestInlineStyle={ { "backgroundColor": ""#2b2e33"", - "borderColor": ""#db3424"", - "borderRadius": 100, + "borderColor": ""#f47f77"", + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { "backgroundColor": "#2b2e33", - "borderColor": "#db3424", - "borderRadius": 100, + "borderColor": "#f47f77", + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -1597,25 +1597,25 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - f } jestInlineStyle={ { - "backgroundColor": ""#fafafa"", - "borderRadius": 100, - "height": 14, - "left": "16.5", + "backgroundColor": ""#ffffff"", + "borderRadius": 1600, + "height": 16, + "left": "19", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { - "backgroundColor": "#fafafa", - "borderRadius": 100, - "height": 14, - "left": 16.5, + "backgroundColor": "#ffffff", + "borderRadius": 1600, + "height": 16, + "left": 19, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -1657,8 +1657,8 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -1676,25 +1676,25 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t } jestInlineStyle={ { - "backgroundColor": ""#9A9A9A"", + "backgroundColor": ""#e2e2e4"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#9A9A9A", + "backgroundColor": "#e2e2e4", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -1713,25 +1713,25 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t } jestInlineStyle={ { - "backgroundColor": ""#fafafa"", - "borderRadius": 100, - "height": 14, - "left": "16.5", + "backgroundColor": ""#ffffff"", + "borderRadius": 1600, + "height": 16, + "left": "19", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { - "backgroundColor": "#fafafa", - "borderRadius": 100, - "height": 14, - "left": 16.5, + "backgroundColor": "#ffffff", + "borderRadius": 1600, + "height": 16, + "left": 19, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } @@ -1773,8 +1773,8 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t onStartShouldSetResponder={[Function]} style={ { - "height": 21, - "width": 35, + "height": 24, + "width": 40, } } > @@ -1792,25 +1792,25 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t } jestInlineStyle={ { - "backgroundColor": ""#9A9A9A"", + "backgroundColor": ""#e2e2e4"", "borderColor": ""transparent"", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, } } style={ [ { - "backgroundColor": "#9A9A9A", + "backgroundColor": "#e2e2e4", "borderColor": "transparent", - "borderRadius": 100, + "borderRadius": 1600, "borderWidth": 1, - "height": 21, - "padding": 3.5, - "width": 35, + "height": 24, + "padding": 4, + "width": 40, }, ] } @@ -1829,25 +1829,25 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t } jestInlineStyle={ { - "backgroundColor": ""#fafafa"", - "borderRadius": 100, - "height": 14, - "left": "16.5", + "backgroundColor": ""#ffffff"", + "borderRadius": 1600, + "height": 16, + "left": "19", "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, } } style={ [ { - "backgroundColor": "#fafafa", - "borderRadius": 100, - "height": 14, - "left": 16.5, + "backgroundColor": "#ffffff", + "borderRadius": 1600, + "height": 16, + "left": 19, "position": "absolute", - "top": 2.5, - "width": 14, + "top": 3, + "width": 16, }, ] } diff --git a/src/components/Input/InputSwitch/styles/useHandleStyles.ts b/src/components/Input/InputSwitch/styles/useHandleStyles.ts index 1349cbc2..93287f19 100644 --- a/src/components/Input/InputSwitch/styles/useHandleStyles.ts +++ b/src/components/Input/InputSwitch/styles/useHandleStyles.ts @@ -48,27 +48,27 @@ export const useHandleStyles = (checked: boolean) => { return { handleStyle } } -const handleStyles = StyleSheet.create(({ theme, border }) => ({ +const handleStyles = StyleSheet.create(({ components: { toggleswitch } }) => ({ handle: { - height: theme.Form.inputSwitch.inputSwitchHandleHeight, - width: theme.Form.inputSwitch.inputSwitchHandleWidth, - borderRadius: border.Radius['rounded-full'], - backgroundColor: theme.Form.inputSwitch.inputSwitchHandleOffBg, + height: toggleswitch.handle.size, + width: toggleswitch.handle.size, + borderRadius: toggleswitch.handle.borderRadius, + backgroundColor: toggleswitch.colorScheme.handle.background, position: 'absolute', - top: theme.Form.inputSwitch.inputSwitchSliderPadding - border.Width.border, + top: toggleswitch.root.gap - toggleswitch.root.borderWidth, }, handleOff: { - backgroundColor: theme.Form.inputSwitch.inputSwitchHandleOffBg, - left: theme.Form.inputSwitch.inputSwitchSliderPadding - border.Width.border, + backgroundColor: toggleswitch.colorScheme.handle.background, + left: toggleswitch.root.gap - toggleswitch.root.borderWidth, }, handleOn: { - backgroundColor: theme.Form.inputSwitch.inputSwitchHandleOnBg, + backgroundColor: toggleswitch.colorScheme.handle.checkedBackground, left: - theme.Form.inputSwitch.inputSwitchWidth - - theme.Form.inputSwitch.inputSwitchSliderPadding - - theme.Form.inputSwitch.inputSwitchHandleWidth - - 1, + toggleswitch.root.width - + toggleswitch.root.gap - + toggleswitch.handle.size - + toggleswitch.root.borderWidth, }, })) diff --git a/src/components/Input/InputSwitch/styles/useSliderStyles.ts b/src/components/Input/InputSwitch/styles/useSliderStyles.ts index 8739c29b..4741e796 100644 --- a/src/components/Input/InputSwitch/styles/useSliderStyles.ts +++ b/src/components/Input/InputSwitch/styles/useSliderStyles.ts @@ -102,45 +102,43 @@ export const useSliderStyles = ( } } -const switchStyles = StyleSheet.create(({ theme, border }) => ({ +const switchStyles = StyleSheet.create(({ components: { toggleswitch } }) => ({ container: { - height: theme.Form.inputSwitch.inputSwitchHeight, - width: theme.Form.inputSwitch.inputSwitchWidth, + height: toggleswitch.root.height, + width: toggleswitch.root.width, }, slider: { - padding: theme.Form.inputSwitch.inputSwitchSliderPadding, - height: theme.Form.inputSwitch.inputSwitchHeight, - width: theme.Form.inputSwitch.inputSwitchWidth, - borderRadius: border.Radius['rounded-full'], - borderWidth: border.Width.border, + padding: toggleswitch.root.gap, + height: toggleswitch.root.height, + width: toggleswitch.root.width, + borderRadius: toggleswitch.root.borderRadius, + borderWidth: toggleswitch.root.borderWidth, }, - sliderOff: { backgroundColor: theme.Form.inputSwitch.inputSwitchSliderOffBg }, + sliderOff: { backgroundColor: toggleswitch.colorScheme.root.background }, - sliderOn: { backgroundColor: theme.Form.inputSwitch.inputSwitchSliderOnBg }, + sliderOn: { + backgroundColor: toggleswitch.colorScheme.root.checkedBackground, + }, sliderPressed: { - backgroundColor: theme.Form.inputSwitch.inputSwitchSliderOffHoverBg, + backgroundColor: toggleswitch.colorScheme.root.hoverBackground, }, sliderOnPressed: { - backgroundColor: theme.Form.inputSwitch.inputSwitchSliderOnHoverBg, + backgroundColor: toggleswitch.colorScheme.root.checkedHoverBackground, }, sliderDisabled: { - backgroundColor: theme.custom.inputSwitch.inputSwitchSliderOffDisabledBg, + backgroundColor: toggleswitch.colorScheme.root.disabledBackground, }, sliderOnDisabled: { - backgroundColor: theme.custom.inputSwitch.inputSwitchSliderOnDisabledBg, + backgroundColor: toggleswitch.colorScheme.root.disabledBackground, }, - sliderNoDanger: { borderColor: 'transparent' }, + sliderNoDanger: { borderColor: toggleswitch.root.borderColor }, - sliderDanger: { - borderColor: theme.Form.InputText.inputErrorBorderColor, - outlineColor: theme.General.focusOutlineErrorColor, - outlineWidth: Math.round(theme.General.focusShadowWidth), - }, + sliderDanger: { borderColor: toggleswitch.root.invalidBorderColor }, })) From 0703aca6a6760d7507239d20cb5ffbe8b8498f56 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:45 +0300 Subject: [PATCH 24/60] =?UTF-8?q?feat(Input):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Input/InputGroupAddon.tsx | 33 +- src/components/Input/InputOtp/InputOtp.tsx | 4 +- .../Input/InputOtp/InputOtpItem.tsx | 45 +- .../__snapshots__/InputOtp.test.tsx.snap | 4848 ++++++++--------- .../Input/InputTextBase/InputTextBase.tsx | 14 +- .../Input/InputTextBase/useInputStyles.ts | 93 +- .../Input/__tests__/InputTextBase.test.tsx | 12 +- .../InputGroupAddon.test.tsx.snap | 38 +- .../__snapshots__/InputTextBase.test.tsx.snap | 6 +- 9 files changed, 2379 insertions(+), 2714 deletions(-) diff --git a/src/components/Input/InputGroupAddon.tsx b/src/components/Input/InputGroupAddon.tsx index dd11ac51..e16c1b8e 100644 --- a/src/components/Input/InputGroupAddon.tsx +++ b/src/components/Input/InputGroupAddon.tsx @@ -41,9 +41,9 @@ export const InputGroupAddon = memo( ({ - color: theme.Form.InputGroup.inputGroupTextColor, - })} + uniProps={({ components }) => { + return { color: components.inputgroup.colorScheme.addon.color } + }} /> )} @@ -51,15 +51,14 @@ export const InputGroupAddon = memo( } ) -const styles = StyleSheet.create(({ theme, typography, fonts }) => ({ +const styles = StyleSheet.create(({ components, semantic, fonts }) => ({ container: { - paddingVertical: theme.Form.InputText.inputPaddingTopBottom, - paddingHorizontal: theme.Form.InputText.inputPaddingLeftRight, + padding: components.inputgroup.addon.padding, justifyContent: 'center', - borderRadius: theme.General.borderRadiusXL, - borderWidth: 1, - borderColor: theme.Form.InputText.inputBorderColor, - backgroundColor: theme.Form.InputGroup.inputGroupBg, + borderRadius: components.inputgroup.addon.borderRadius, + borderWidth: components.inputgroup.extend.borderWidth, + borderColor: components.inputgroup.colorScheme.addon.borderColor, + backgroundColor: components.inputgroup.colorScheme.addon.background, }, left: { borderRightWidth: 0, @@ -73,18 +72,18 @@ const styles = StyleSheet.create(({ theme, typography, fonts }) => ({ borderBottomLeftRadius: 0, }, disabled: { - opacity: 0.6, - backgroundColor: theme.Button.Disabled.disabledButtonBg, + opacity: semantic.effects.opacity[60], + backgroundColor: semantic.colorScheme.color.bg.neutral.weak.disabled, }, text: { - fontSize: typography.Size['text-base'], - color: theme.Form.InputGroup.inputGroupTextColor, + fontSize: fonts.fontSize[300], + color: components.inputgroup.colorScheme.addon.color, includeFontPadding: false, verticalAlign: 'middle', - fontFamily: fonts.secondary, + fontFamily: fonts.fontFamily.base, }, icon: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], + width: components.inputgroup.extend.iconSize, + height: components.inputgroup.extend.iconSize, }, })) diff --git a/src/components/Input/InputOtp/InputOtp.tsx b/src/components/Input/InputOtp/InputOtp.tsx index a43155c3..3923463b 100644 --- a/src/components/Input/InputOtp/InputOtp.tsx +++ b/src/components/Input/InputOtp/InputOtp.tsx @@ -155,10 +155,10 @@ export const InputOtp = memo( } ) -const styles = StyleSheet.create(({ spacing }) => ({ +const styles = StyleSheet.create(({ semantic }) => ({ container: {}, - content: { flexDirection: 'row', gap: spacing.Gap['gap-2'] }, + content: { flexDirection: 'row', gap: semantic.dimension.space[200] }, input: { position: 'absolute', width: 1, height: 1, opacity: 0 }, })) diff --git a/src/components/Input/InputOtp/InputOtpItem.tsx b/src/components/Input/InputOtp/InputOtpItem.tsx index 0e685314..cb719a5c 100644 --- a/src/components/Input/InputOtp/InputOtpItem.tsx +++ b/src/components/Input/InputOtp/InputOtpItem.tsx @@ -5,6 +5,8 @@ import Animated, { type AnimatedStyle } from 'react-native-reanimated' import { StyleSheet } from 'react-native-unistyles' +import effects from '../../../theme/tokens/semantic/effects.json' + export interface InputOtpItemProps extends Pick { value?: string error: boolean @@ -15,8 +17,14 @@ export interface InputOtpItemProps extends Pick { const CURSOR_ANIMATION_DURATION = 500 +// Анимация не может жить в StyleSheet.create: Animated.Text из reanimated не +// принимает Unistyles-стиль. Шкала непрозрачности одинакова в обеих темах, +// поэтому токены берутся из сгенерированного файла напрямую. const cursorAnimationStyle = { - animationName: { from: { opacity: 1 }, to: { opacity: 0.2 } }, + animationName: { + from: { opacity: effects.opacity[100] }, + to: { opacity: effects.opacity[20] }, + }, animationDuration: CURSOR_ANIMATION_DURATION, animationDirection: 'alternate', animationIterationCount: 'infinite', @@ -60,14 +68,16 @@ export const InputOtpItem = memo( } ) -const styles = StyleSheet.create(({ theme, border, fonts, typography }) => ({ +// Рамка, цвет и отступы намеренно берутся у inputtext: поле OTP должно выглядеть +// как обычное поле ввода. Собственные токены inputotp описывают только отличия — +// тот же приём, что в пресете PrimeUIX lara, где inputotp задаёт лишь gap и width. +const styles = StyleSheet.create(({ components, semantic, fonts }) => ({ container: { - minHeight: theme.Button.Common.buttonHeight, - minWidth: theme.Button.Common.buttonHeight, - paddingHorizontal: theme.Form.InputText.inputPaddingLeftRight, - paddingVertical: theme.Form.InputText.inputPaddingTopBottom, - borderBottomWidth: border.Width.border, - borderColor: theme.Form.InputText.inputBorderColor, + minHeight: components.inputotp.extend.height, + minWidth: components.inputotp.extend.height, + paddingHorizontal: components.inputtext.root.paddingX, + borderBottomWidth: components.inputotp.extend.borderWidth, + borderColor: components.inputtext.root.borderColor, alignItems: 'center', justifyContent: 'center', }, @@ -75,18 +85,21 @@ const styles = StyleSheet.create(({ theme, border, fonts, typography }) => ({ textRow: { flexDirection: 'row', alignItems: 'center' }, text: { - fontSize: typography.Size['text-2xl'], - fontFamily: fonts.primary, - fontWeight: '400', - color: theme.Form.InputText.inputTextColor, + fontSize: fonts.fontSize[600], + fontFamily: fonts.fontFamily.heading, + fontWeight: fonts.fontWeight.regular, + color: components.inputtext.root.color, includeFontPadding: false, }, - pressed: { borderColor: theme.Form.InputText.inputHoverBorderColor }, + pressed: { borderColor: components.inputtext.root.hoverBorderColor }, - error: { borderColor: theme.Form.InputText.inputErrorBorderColor }, + error: { borderColor: components.inputtext.root.invalidBorderColor }, - disabled: { mixBlendMode: 'luminosity', opacity: 0.6 }, + disabled: { + mixBlendMode: 'luminosity', + opacity: semantic.effects.opacity[60], + }, - cursor: { color: theme.Form.InputText.inputTextColor, marginBottom: 3 }, + cursor: { color: components.inputtext.root.color, marginBottom: 3 }, })) diff --git a/src/components/Input/InputOtp/__tests__/__snapshots__/InputOtp.test.tsx.snap b/src/components/Input/InputOtp/__tests__/__snapshots__/InputOtp.test.tsx.snap index c48a2c5d..e07be575 100644 --- a/src/components/Input/InputOtp/__tests__/__snapshots__/InputOtp.test.tsx.snap +++ b/src/components/Input/InputOtp/__tests__/__snapshots__/InputOtp.test.tsx.snap @@ -37,7 +37,7 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -49,10 +49,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -63,10 +62,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p @@ -176,10 +174,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -190,10 +187,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p @@ -305,10 +301,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -319,10 +314,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p @@ -436,10 +430,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -452,10 +445,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p @@ -567,10 +559,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -583,10 +574,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p @@ -700,10 +690,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -716,10 +705,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - false, p @@ -835,10 +823,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -852,10 +839,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr @@ -968,10 +954,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -985,10 +970,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr @@ -1103,10 +1087,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -1120,10 +1103,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr @@ -1240,10 +1222,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -1259,10 +1240,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr @@ -1377,10 +1357,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -1396,10 +1375,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr @@ -1516,10 +1494,9 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -1535,10 +1512,10 @@ exports[`InputOtp component tests length - 2, error - false, disabled - true, pr @@ -1657,13 +1633,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, false, @@ -1673,10 +1648,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr @@ -1788,13 +1762,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, false, @@ -1804,10 +1777,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr @@ -1921,13 +1893,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, false, @@ -1937,10 +1908,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr @@ -2056,13 +2026,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -2074,10 +2043,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr @@ -2191,13 +2159,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -2209,10 +2176,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr @@ -2328,13 +2294,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -2346,10 +2311,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - false, pr @@ -2467,13 +2431,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, { @@ -2486,10 +2449,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre @@ -2604,13 +2566,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, { @@ -2623,10 +2584,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre @@ -2743,13 +2703,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, { @@ -2762,10 +2721,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre @@ -2884,13 +2842,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -2905,10 +2862,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre @@ -3025,13 +2981,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -3046,10 +3001,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre @@ -3168,13 +3122,12 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -3189,10 +3142,10 @@ exports[`InputOtp component tests length - 2, error - true, disabled - true, pre @@ -3313,10 +3265,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -3327,10 +3278,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p @@ -3504,10 +3452,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -3518,10 +3465,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p @@ -3697,10 +3641,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -3711,10 +3654,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p @@ -3892,10 +3832,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -3908,10 +3847,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p @@ -4091,10 +4027,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -4107,10 +4042,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p @@ -4292,10 +4224,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -4308,10 +4239,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - false, p @@ -4495,10 +4423,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -4512,10 +4439,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr @@ -4698,10 +4622,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -4715,10 +4638,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr @@ -4903,10 +4823,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -4920,10 +4839,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr @@ -5110,10 +5026,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -5129,10 +5044,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr @@ -5321,10 +5233,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -5340,10 +5251,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr @@ -5534,10 +5442,9 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -5553,10 +5460,10 @@ exports[`InputOtp component tests length - 4, error - false, disabled - true, pr @@ -5749,13 +5653,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, false, @@ -5765,10 +5668,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr @@ -5948,13 +5848,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, false, @@ -5964,10 +5863,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr @@ -6149,13 +6045,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, false, @@ -6165,10 +6060,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr @@ -6352,13 +6244,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -6370,10 +6261,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr @@ -6559,13 +6447,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -6577,10 +6464,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr @@ -6768,13 +6652,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -6786,10 +6669,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - false, pr @@ -6979,13 +6859,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, { @@ -6998,10 +6877,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre @@ -7190,13 +7066,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, { @@ -7209,10 +7084,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre @@ -7403,13 +7275,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, { @@ -7422,10 +7293,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre @@ -7618,13 +7486,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -7639,10 +7506,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre @@ -7837,13 +7701,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -7858,10 +7721,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre @@ -8058,13 +7918,12 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -8079,10 +7938,10 @@ exports[`InputOtp component tests length - 4, error - true, disabled - true, pre @@ -8281,10 +8137,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -8295,10 +8150,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p @@ -8600,10 +8448,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -8614,10 +8461,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p @@ -8921,10 +8761,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -8935,10 +8774,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p @@ -9244,10 +9076,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -9260,10 +9091,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p @@ -9579,10 +9403,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -9595,10 +9418,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p @@ -9916,10 +9732,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -9932,10 +9747,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - false, p @@ -10255,10 +10063,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -10272,10 +10079,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr @@ -10598,10 +10398,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -10615,10 +10414,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr @@ -10943,10 +10735,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, false, @@ -10960,10 +10751,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr @@ -11290,10 +11074,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -11309,10 +11092,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr @@ -11649,10 +11425,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -11668,10 +11443,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr @@ -12010,10 +11778,9 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, false, { @@ -12029,10 +11796,10 @@ exports[`InputOtp component tests length - 8, error - false, disabled - true, pr @@ -12373,13 +12133,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, false, @@ -12389,10 +12148,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr @@ -12708,13 +12460,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, false, @@ -12724,10 +12475,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr @@ -13045,13 +12789,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, false, @@ -13061,10 +12804,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr @@ -13384,13 +13120,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -13402,10 +13137,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr @@ -13735,13 +13463,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -13753,10 +13480,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr @@ -14088,13 +13808,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -14106,10 +13825,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - false, pr @@ -14443,13 +14155,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, { @@ -14462,10 +14173,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre @@ -14802,13 +14506,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, { @@ -14821,10 +14524,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre @@ -15163,13 +14859,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, false, { @@ -15182,10 +14877,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre @@ -15526,13 +15214,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -15547,10 +15234,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre @@ -15901,13 +15581,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -15922,10 +15601,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre @@ -16278,13 +15950,12 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre "borderBottomWidth": 1, "borderColor": "#cecfd2", "justifyContent": "center", - "minHeight": 35, - "minWidth": 35, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "minHeight": 40, + "minWidth": 40, + "paddingHorizontal": 14, }, { - "borderColor": "#db3424", + "borderColor": "#f47f77", }, { "borderColor": "#1dc831", @@ -16299,10 +15970,10 @@ exports[`InputOtp component tests length - 8, error - true, disabled - true, pre ({ - color: theme.Form.InputText.inputIconColor, -}) +const inputIconUniProps = ({ components }: SvgUniversalTheme) => { + return { color: components.inputtext.root.color } +} export const InputTextBase = memo< InputTextBaseProps & PrivateInputTextBaseProps @@ -306,7 +309,6 @@ export const InputTextBase = memo< isFocused && styles.containerFocused, containerStyle, state === 'danger' && styles.danger, - state === 'danger' && isFocused && styles.dangerFocused, disabled && styles.disabled, ]} testID={makeTestId(InputTextBaseTestId.pressableContainer)} diff --git a/src/components/Input/InputTextBase/useInputStyles.ts b/src/components/Input/InputTextBase/useInputStyles.ts index a4fa3689..042df69e 100644 --- a/src/components/Input/InputTextBase/useInputStyles.ts +++ b/src/components/Input/InputTextBase/useInputStyles.ts @@ -18,38 +18,33 @@ export const useInputContainerMinHeight = ( return { minHeight } } -const containerMinHeight = StyleSheet.create(({ theme }) => ({ - base: { minHeight: theme.InputSize.base['min-height'] }, - medium: { minHeight: theme.InputSize.medium['min-height'] }, - large: { minHeight: theme.InputSize.large['min-height'] }, - xlarge: { minHeight: theme.InputSize.xlarge['min-height'] }, +const containerMinHeight = StyleSheet.create(({ semantic }) => ({ + base: { minHeight: semantic.dimension.size[1100] }, + medium: { minHeight: semantic.dimension.size[1200] }, + large: { minHeight: semantic.dimension.size[1300] }, + xlarge: { minHeight: semantic.dimension.size[1400] }, })) export const inputStyles = StyleSheet.create( - ({ theme, border, typography, spacing, fonts }) => ({ + ({ components, semantic, fonts }) => ({ container: { flexDirection: 'row', - borderWidth: border.Width.border, - borderRadius: border.Radius['rounded-xl'], - borderColor: theme.Form.InputText.inputBorderColor, - backgroundColor: theme.Form.InputText.inputBg, + borderWidth: semantic.dimension.borderWidth[100], + borderRadius: components.inputtext.root.borderRadius, + borderColor: components.inputtext.root.borderColor, + backgroundColor: components.inputtext.root.background, }, containerFocused: { - outlineColor: theme.General.focusOutlineColor, - outlineWidth: Math.round(theme.General.focusShadowWidth), - borderColor: theme.General.focusBorderColor, + outlineColor: components.inputtext.root.focusRing.color, + outlineWidth: components.inputtext.root.focusRing.width, + borderColor: components.inputtext.root.focusBorderColor, }, - containerFloatLabel: { - minHeight: theme.Button.Common.buttonHeightXL, - maxHeight: theme.Button.Common.buttonHeightXL, - height: theme.Button.Common.buttonHeightXL, - }, - danger: { borderColor: theme.Form.InputText.inputErrorBorderColor }, - dangerFocused: { outlineColor: theme.General.focusOutlineErrorColor }, + containerFloatLabel: { minHeight: 56, maxHeight: 56, height: 56 }, + danger: { borderColor: components.inputtext.root.invalidBorderColor }, disabled: { - opacity: 0.6, - borderColor: theme.Form.InputText.inputBorderColor, - backgroundColor: theme.Button.Disabled.disabledButtonBg, + opacity: semantic.effects.opacity[60], + borderColor: components.inputtext.root.borderColor, + backgroundColor: semantic.colorScheme.color.bg.neutral.weak.disabled, }, inputContainer: { flex: 1, @@ -57,8 +52,8 @@ export const inputStyles = StyleSheet.create( justifyContent: 'center', }, input: { - padding: 0, - paddingHorizontal: theme.Form.InputText.inputPaddingLeftRight, + padding: semantic.dimension.space.none, + paddingHorizontal: components.inputtext.root.paddingX, position: 'absolute', left: 0, right: 0, @@ -68,40 +63,36 @@ export const inputStyles = StyleSheet.create( inputWithRightContent: { paddingRight: 0 }, floatLabelInput: { flex: 1, - paddingHorizontal: theme.Form.InputText.inputPaddingLeftRight, + paddingHorizontal: components.inputtext.root.paddingX, paddingTop: 26, paddingBottom: 12, - borderRadius: border.Radius['rounded-xl'], + borderRadius: semantic.dimension.borderRadius[300], overflow: 'hidden', }, inputFont: { - fontSize: typography.Size['text-base'], - color: theme.Form.InputText.inputTextColor, + fontSize: fonts.fontSize[300], + color: components.inputtext.root.color, includeFontPadding: false, - fontFamily: fonts.secondary, + fontFamily: fonts.fontFamily.base, verticalAlign: 'middle', }, - placeholder: { - paddingHorizontal: theme.Form.InputText.inputPaddingLeftRight, - }, - placeholderTextColor: { - color: theme.Form.InputText.inputPlaceholderTextColor, - }, + placeholder: { paddingHorizontal: components.inputtext.root.paddingX }, + placeholderTextColor: { color: components.inputtext.root.placeholderColor }, rightContainer: { flexDirection: 'row', - paddingHorizontal: theme.Form.InputText.inputPaddingLeftRight, - gap: theme.Form.InputText.inputPaddingLeftRight, + paddingHorizontal: components.inputtext.root.paddingX, + gap: components.inputtext.root.paddingX, overflow: 'hidden', alignItems: 'center', }, rightButtonContainer: { justifyContent: 'center' }, iconSize: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], + width: components.inputtext.extend.iconSize, + height: components.inputtext.extend.iconSize, }, iconSizeFloatLabel: { - width: typography.Size['text-xl'], - height: typography.Size['text-xl'], + width: components.inputtext.extend.iconSize, + height: components.inputtext.extend.iconSize, }, label: { @@ -109,20 +100,20 @@ export const inputStyles = StyleSheet.create( left: 7, right: 7, top: 19, - paddingVertical: 0, - paddingLeft: spacing.Padding['p-1'], - paddingRight: spacing.Padding['p-2'], - color: typography.Color.Common['text-color-secondary'], + paddingVertical: semantic.dimension.space.none, + paddingLeft: semantic.dimension.space[100], + paddingRight: semantic.dimension.space[200], + color: semantic.colorScheme.color.fg.muted, includeFontPadding: false, verticalAlign: 'middle', - fontSize: typography.Size['text-base'], - fontFamily: fonts.secondary, + fontSize: fonts.fontSize[300], + fontFamily: fonts.fontFamily.base, }, labelReducedSize: { - fontSize: typography.Size['text-sm'], - paddingVertical: spacing.Padding['p-1'], + fontSize: fonts.fontSize[100], + paddingVertical: semantic.dimension.space[100], top: 7, - fontFamily: fonts.primary, + fontFamily: fonts.fontFamily.heading, }, hidden: { opacity: 0 }, }) diff --git a/src/components/Input/__tests__/InputTextBase.test.tsx b/src/components/Input/__tests__/InputTextBase.test.tsx index 904989c6..076f6952 100644 --- a/src/components/Input/__tests__/InputTextBase.test.tsx +++ b/src/components/Input/__tests__/InputTextBase.test.tsx @@ -2,7 +2,7 @@ import { fireEvent, render, userEvent } from '@testing-library/react-native' import { TextInput } from 'react-native-gesture-handler' -import { lightTheme } from '../../../theme' +import { semanticTokens } from '../../../theme/tokens' import { InputTextBase } from '../InputTextBase/InputTextBase' import { InputTextBaseTestId } from '../InputTextBase/testIds' import type { RenderTextInputArgs } from '../InputTextBase/types' @@ -190,7 +190,7 @@ describe('InputTextBase component functionality tests', () => { const { getByTestId } = render() expect(getByTestId(containerTestId)).toHaveStyle({ - minHeight: lightTheme.theme.InputSize.base['min-height'], + minHeight: semanticTokens.dimension.size[1100], }) }) @@ -198,7 +198,7 @@ describe('InputTextBase component functionality tests', () => { const { getByTestId } = render() expect(getByTestId(containerTestId)).toHaveStyle({ - minHeight: lightTheme.theme.InputSize.base['min-height'], + minHeight: semanticTokens.dimension.size[1100], }) }) @@ -206,7 +206,7 @@ describe('InputTextBase component functionality tests', () => { const { getByTestId } = render() expect(getByTestId(containerTestId)).toHaveStyle({ - minHeight: lightTheme.theme.InputSize.large['min-height'], + minHeight: semanticTokens.dimension.size[1300], }) }) @@ -214,7 +214,7 @@ describe('InputTextBase component functionality tests', () => { const { getByTestId } = render() expect(getByTestId(containerTestId)).toHaveStyle({ - minHeight: lightTheme.theme.InputSize.xlarge['min-height'], + minHeight: semanticTokens.dimension.size[1400], }) }) @@ -222,7 +222,7 @@ describe('InputTextBase component functionality tests', () => { const { getByTestId } = render() expect(getByTestId(containerTestId)).toHaveStyle({ - minHeight: lightTheme.theme.InputSize.base['min-height'], + minHeight: semanticTokens.dimension.size[1100], }) }) diff --git a/src/components/Input/__tests__/__snapshots__/InputGroupAddon.test.tsx.snap b/src/components/Input/__tests__/__snapshots__/InputGroupAddon.test.tsx.snap index e751df44..4ea15dc6 100644 --- a/src/components/Input/__tests__/__snapshots__/InputGroupAddon.test.tsx.snap +++ b/src/components/Input/__tests__/__snapshots__/InputGroupAddon.test.tsx.snap @@ -8,11 +8,10 @@ exports[`InputGroup component tests content: icon, position: right 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#cecfd2", - "borderRadius": 10.5, + "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "padding": 14, }, { "borderBottomLeftRadius": 0, @@ -26,11 +25,11 @@ exports[`InputGroup component tests content: icon, position: right 1`] = ` > Date: Tue, 4 Aug 2026 17:05:45 +0300 Subject: [PATCH 25/60] =?UTF-8?q?feat(List):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/List/Base/ListBase.tsx | 84 ++++----- .../__snapshots__/ListBase.test.tsx.snap | 172 +++++++++--------- 2 files changed, 128 insertions(+), 128 deletions(-) diff --git a/src/components/List/Base/ListBase.tsx b/src/components/List/Base/ListBase.tsx index da4078aa..dfd1854e 100644 --- a/src/components/List/Base/ListBase.tsx +++ b/src/components/List/Base/ListBase.tsx @@ -141,45 +141,45 @@ const ListBaseTestId = { title: 'Title', } -const styles = StyleSheet.create( - ({ spacing, typography, theme, background }) => ({ - container: { - flexDirection: 'row', - paddingLeft: spacing.Padding['p-4'], - gap: spacing.Padding['p-4'], - alignItems: 'center', - }, - pressed: { backgroundColor: background.Common['bg-surface-ground-hover'] }, - disabled: { opacity: 0.6 }, - leftIcon: { paddingVertical: spacing.Padding['p-4'] }, - content: { - flex: 1, - flexDirection: 'row', - justifyContent: 'space-between', - paddingVertical: spacing.Padding['p-2'], - paddingEnd: spacing.Padding['p-4'], - gap: spacing.Gap['gap-4'], - }, - labelContainer: { - paddingVertical: spacing.Padding['p-2'], - gap: spacing.Gap['gap-2'], - flex: 1, - }, - titleContainer: { gap: spacing.Gap['gap-1'] }, - extraContainer: { paddingVertical: spacing.Padding['p-2'] }, - icon: { - width: typography.Size['text-2xl'], - height: typography.Size['text-2xl'], - }, - rightSection: { - flexDirection: 'row', - alignItems: 'center', - paddingVertical: spacing.Padding['p-2'], - gap: spacing.Gap['gap-4'], - }, - divider: { - borderTopColor: theme.Surface['surface-border'], - borderTopWidth: 1, - }, - }) -) +const styles = StyleSheet.create(({ semantic }) => ({ + container: { + flexDirection: 'row', + paddingLeft: semantic.dimension.space[400], + gap: semantic.dimension.space[400], + alignItems: 'center', + }, + pressed: { + backgroundColor: semantic.colorScheme.color.bg.neutral.weak.hover, + }, + disabled: { opacity: semantic.effects.opacity[60] }, + leftIcon: { paddingVertical: semantic.dimension.space[400] }, + content: { + flex: 1, + flexDirection: 'row', + justifyContent: 'space-between', + paddingVertical: semantic.dimension.space[200], + paddingEnd: semantic.dimension.space[400], + gap: semantic.dimension.space[400], + }, + labelContainer: { + paddingVertical: semantic.dimension.space[200], + gap: semantic.dimension.space[200], + flex: 1, + }, + titleContainer: { gap: semantic.dimension.space[100] }, + extraContainer: { paddingVertical: semantic.dimension.space[200] }, + icon: { + width: semantic.dimension.size[700], + height: semantic.dimension.size[700], + }, + rightSection: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: semantic.dimension.space[200], + gap: semantic.dimension.space[400], + }, + divider: { + borderTopColor: semantic.colorScheme.color.border.neutral.default, + borderTopWidth: 1, + }, +})) diff --git a/src/components/List/Base/__tests__/__snapshots__/ListBase.test.tsx.snap b/src/components/List/Base/__tests__/__snapshots__/ListBase.test.tsx.snap index 323012bf..0b16ef10 100644 --- a/src/components/List/Base/__tests__/__snapshots__/ListBase.test.tsx.snap +++ b/src/components/List/Base/__tests__/__snapshots__/ListBase.test.tsx.snap @@ -66,11 +66,11 @@ exports[`ListBase tests ListBase centered and full divider 1`] = ` > @@ -281,9 +281,9 @@ exports[`ListBase tests ListBase centered and full divider 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 10.5, + "fontSize": 12, "fontWeight": 700, - "lineHeight": 15, + "lineHeight": 18, "textTransform": "uppercase", }, { @@ -300,7 +300,7 @@ exports[`ListBase tests ListBase centered and full divider 1`] = ` @@ -309,16 +309,16 @@ exports[`ListBase tests ListBase centered and full divider 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, undefined, undefined, @@ -335,10 +335,10 @@ exports[`ListBase tests ListBase centered and full divider 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { @@ -361,14 +361,14 @@ exports[`ListBase tests ListBase centered and full divider 1`] = ` "alignItems": "center", "flexDirection": "row", "gap": 14, - "paddingVertical": 7, + "paddingVertical": 8, } } > @@ -450,11 +450,11 @@ exports[`ListBase tests ListBase centered and full divider 1`] = ` @@ -836,9 +836,9 @@ exports[`ListBase tests ListBase full disabled 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 10.5, + "fontSize": 12, "fontWeight": 700, - "lineHeight": 15, + "lineHeight": 18, "textTransform": "uppercase", }, { @@ -855,7 +855,7 @@ exports[`ListBase tests ListBase full disabled 1`] = ` @@ -864,16 +864,16 @@ exports[`ListBase tests ListBase full disabled 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, undefined, undefined, @@ -890,10 +890,10 @@ exports[`ListBase tests ListBase full disabled 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { @@ -916,14 +916,14 @@ exports[`ListBase tests ListBase full disabled 1`] = ` "alignItems": "center", "flexDirection": "row", "gap": 14, - "paddingVertical": 7, + "paddingVertical": 8, } } > @@ -1005,11 +1005,11 @@ exports[`ListBase tests ListBase full disabled 1`] = ` @@ -1398,9 +1398,9 @@ exports[`ListBase tests ListBase maximal config 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 10.5, + "fontSize": 12, "fontWeight": 700, - "lineHeight": 15, + "lineHeight": 18, "textTransform": "uppercase", }, { @@ -1417,7 +1417,7 @@ exports[`ListBase tests ListBase maximal config 1`] = ` @@ -1426,16 +1426,16 @@ exports[`ListBase tests ListBase maximal config 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, undefined, undefined, @@ -1452,10 +1452,10 @@ exports[`ListBase tests ListBase maximal config 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { @@ -1478,14 +1478,14 @@ exports[`ListBase tests ListBase maximal config 1`] = ` "alignItems": "center", "flexDirection": "row", "gap": 14, - "paddingVertical": 7, + "paddingVertical": 8, } } > @@ -1567,11 +1567,11 @@ exports[`ListBase tests ListBase maximal config 1`] = ` @@ -1760,16 +1760,16 @@ exports[`ListBase tests ListBase minimal config 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, undefined, undefined, @@ -1789,7 +1789,7 @@ exports[`ListBase tests ListBase minimal config 1`] = ` "alignItems": "center", "flexDirection": "row", "gap": 14, - "paddingVertical": 7, + "paddingVertical": 8, } } /> From a86663058298e2daadcd2cae25c5df135cce136e Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:45 +0300 Subject: [PATCH 26/60] =?UTF-8?q?feat(MenuItem):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/MenuItem/MenuItemAccessory.tsx | 12 +- .../MenuItem/Template/MenuItemTemplate.tsx | 46 +- .../MenuItemTemplate.test.tsx.snap | 398 +++++++++--------- 3 files changed, 229 insertions(+), 227 deletions(-) diff --git a/src/components/MenuItem/MenuItemAccessory.tsx b/src/components/MenuItem/MenuItemAccessory.tsx index 958f8e44..e106b745 100644 --- a/src/components/MenuItem/MenuItemAccessory.tsx +++ b/src/components/MenuItem/MenuItemAccessory.tsx @@ -29,19 +29,19 @@ export const MenuItemAccessory = memo( ({ - color: theme.Menu.Item.menuitemIconColor, - })} + uniProps={({ components }) => { + return { color: components.menu.item.icon.color } + }} /> ) } ) -const styles = StyleSheet.create(({ theme }) => ({ +const styles = StyleSheet.create(({ components }) => ({ container: { justifyContent: 'center' }, icon: { - width: theme.Menu.Item.menuitemSubmenuIconFontSize, - height: theme.Menu.Item.menuitemSubmenuIconFontSize, + width: components.menu.extend.iconSize, + height: components.menu.extend.iconSize, }, })) diff --git a/src/components/MenuItem/Template/MenuItemTemplate.tsx b/src/components/MenuItem/Template/MenuItemTemplate.tsx index fb2d4c05..f6733949 100644 --- a/src/components/MenuItem/Template/MenuItemTemplate.tsx +++ b/src/components/MenuItem/Template/MenuItemTemplate.tsx @@ -133,45 +133,47 @@ export const MenuItemTemplate = memo( } ) -const styles = StyleSheet.create(({ theme, spacing, typography, border }) => ({ +// `transparent` здесь — отсутствие фона и границы, а не цвет дизайн-системы: +// у menu.item нет background и borderColor, прозрачность не выражена semantic-токеном. +const styles = StyleSheet.create(({ components, semantic }) => ({ container: { - borderColor: theme.Menu.Item.menuitemBorderColor, - borderWidth: border.Width.border, - borderRadius: theme.Menu.Item.menuitemBorderRadius, - backgroundColor: theme.Menu.Item.menuitemBg, + borderColor: 'transparent', + borderWidth: semantic.dimension.borderWidth[100], + borderRadius: components.menu.item.borderRadius, + backgroundColor: 'transparent', }, - containerPressed: { backgroundColor: theme.Menu.Item.menuitemHoverBg }, + containerPressed: { backgroundColor: components.menu.item.focusBackground }, containerDisabled: { - borderColor: theme.Button.Disabled.disabledButtonBorderColor, - backgroundColor: theme.Button.Disabled.disabledButtonBg, - opacity: 0.6, + borderColor: 'transparent', + backgroundColor: semantic.colorScheme.color.bg.neutral.weak.disabled, + opacity: semantic.effects.opacity[60], }, separator: { borderTopWidth: 1, - borderTopColor: theme.Menu.Overlay.overlayMenuBorderColor, - paddingTop: theme.Menu.Common.menuSeparatorMarginTopBottom, + borderTopColor: components.menu.separator.borderColor, + paddingTop: components.menu.extend.extItem.caption.gap, }, contentContainer: { flexDirection: 'row', alignItems: 'center', - gap: theme.General.inlineSpacing, - paddingHorizontal: theme.Menu.Item.menuitemPaddingLeftRight, - paddingVertical: theme.Menu.Item.menuitemPaddingTopBottom, + gap: components.menu.item.gap, + paddingHorizontal: components.menu.item.paddingLeft, + paddingVertical: components.menu.item.paddingTop, }, accessory: { - color: theme.Menu.Item.menuitemIconColor, - width: theme.Menu.Item.menuitemSubmenuIconFontSize, - height: theme.Menu.Item.menuitemSubmenuIconFontSize, + color: components.menu.item.icon.color, + width: components.menu.extend.iconSize, + height: components.menu.extend.iconSize, }, templateContainer: { flexDirection: 'row', - gap: spacing.Gap['gap-2'], + gap: semantic.dimension.space[200], flex: 1, }, icon: { - width: typography.Size['text-xl'], - height: typography.Size['text-xl'], - color: theme.Menu.Item.menuitemIconColor, + width: components.menu.extend.iconSize, + height: components.menu.extend.iconSize, + color: components.menu.item.icon.color, }, - textContainer: { gap: spacing.Gap['gap-1'], flex: 1 }, + textContainer: { gap: semantic.dimension.space[100], flex: 1 }, })) diff --git a/src/components/MenuItem/Template/__tests__/__snapshots__/MenuItemTemplate.test.tsx.snap b/src/components/MenuItem/Template/__tests__/__snapshots__/MenuItemTemplate.test.tsx.snap index bc4546e9..ffadc7b0 100644 --- a/src/components/MenuItem/Template/__tests__/__snapshots__/MenuItemTemplate.test.tsx.snap +++ b/src/components/MenuItem/Template/__tests__/__snapshots__/MenuItemTemplate.test.tsx.snap @@ -6,7 +6,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate full disabled 1`] = ` { "borderTopColor": "#e2e2e4", "borderTopWidth": 1, - "paddingTop": 3.5, + "paddingTop": 4, } } > @@ -45,16 +45,16 @@ exports[`MenuItemTemplate tests MenuItemTemplate full disabled 1`] = ` style={ [ { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 7, + "backgroundColor": "transparent", + "borderColor": "transparent", + "borderRadius": 8, "borderWidth": 1, }, false, undefined, { "backgroundColor": "#e2e2e4", - "borderColor": "#a2a5a9", + "borderColor": "transparent", "opacity": 0.6, }, ] @@ -66,9 +66,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate full disabled 1`] = ` { "alignItems": "center", "flexDirection": "row", - "gap": 7, - "paddingHorizontal": 10.5, - "paddingVertical": 7, + "gap": 8, + "paddingHorizontal": 14, + "paddingVertical": 8, } } > @@ -77,7 +77,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate full disabled 1`] = ` { "flex": 1, "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -92,15 +92,15 @@ exports[`MenuItemTemplate tests MenuItemTemplate full disabled 1`] = ` @@ -242,20 +242,20 @@ exports[`MenuItemTemplate tests MenuItemTemplate full disabled 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, { - "fontSize": 12.25, - "lineHeight": 18, + "fontSize": 14, + "lineHeight": 20, }, undefined, undefined, @@ -271,10 +271,10 @@ exports[`MenuItemTemplate tests MenuItemTemplate full disabled 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { @@ -396,15 +396,15 @@ exports[`MenuItemTemplate tests MenuItemTemplate full disabled 1`] = ` > @@ -592,7 +592,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate minimal config 1`] = ` { "flex": 1, "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -600,7 +600,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate minimal config 1`] = ` style={ { "flex": 1, - "gap": 3.5, + "gap": 4, } } > @@ -609,20 +609,20 @@ exports[`MenuItemTemplate tests MenuItemTemplate minimal config 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, { - "fontSize": 12.25, - "lineHeight": 18, + "fontSize": 14, + "lineHeight": 20, }, undefined, undefined, @@ -679,9 +679,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate prefix,suffix = right 1`] = ` style={ [ { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 7, + "backgroundColor": "transparent", + "borderColor": "transparent", + "borderRadius": 8, "borderWidth": 1, }, false, @@ -696,9 +696,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate prefix,suffix = right 1`] = ` { "alignItems": "center", "flexDirection": "row", - "gap": 7, - "paddingHorizontal": 10.5, - "paddingVertical": 7, + "gap": 8, + "paddingHorizontal": 14, + "paddingVertical": 8, } } > @@ -711,15 +711,15 @@ exports[`MenuItemTemplate tests MenuItemTemplate prefix,suffix = right 1`] = ` > @@ -802,7 +802,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate prefix,suffix = right 1`] = ` style={ { "flex": 1, - "gap": 3.5, + "gap": 4, } } > @@ -811,20 +811,20 @@ exports[`MenuItemTemplate tests MenuItemTemplate prefix,suffix = right 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, { - "fontSize": 12.25, - "lineHeight": 18, + "fontSize": 14, + "lineHeight": 20, }, undefined, undefined, @@ -840,10 +840,10 @@ exports[`MenuItemTemplate tests MenuItemTemplate prefix,suffix = right 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { @@ -869,15 +869,15 @@ exports[`MenuItemTemplate tests MenuItemTemplate prefix,suffix = right 1`] = ` > @@ -1019,7 +1019,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with colored icon 1`] = ` { "flex": 1, "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -1034,11 +1034,11 @@ exports[`MenuItemTemplate tests MenuItemTemplate with colored icon 1`] = ` @@ -1149,20 +1149,20 @@ exports[`MenuItemTemplate tests MenuItemTemplate with colored icon 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, { - "fontSize": 12.25, - "lineHeight": 18, + "fontSize": 14, + "lineHeight": 20, }, undefined, undefined, @@ -1219,9 +1219,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with extra 1`] = ` style={ [ { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 7, + "backgroundColor": "transparent", + "borderColor": "transparent", + "borderRadius": 8, "borderWidth": 1, }, false, @@ -1236,9 +1236,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with extra 1`] = ` { "alignItems": "center", "flexDirection": "row", - "gap": 7, - "paddingHorizontal": 10.5, - "paddingVertical": 7, + "gap": 8, + "paddingHorizontal": 14, + "paddingVertical": 8, } } > @@ -1247,7 +1247,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with extra 1`] = ` { "flex": 1, "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -1255,7 +1255,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with extra 1`] = ` style={ { "flex": 1, - "gap": 3.5, + "gap": 4, } } > @@ -1264,20 +1264,20 @@ exports[`MenuItemTemplate tests MenuItemTemplate with extra 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, { - "fontSize": 12.25, - "lineHeight": 18, + "fontSize": 14, + "lineHeight": 20, }, undefined, undefined, @@ -1430,9 +1430,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon 1`] = ` style={ [ { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 7, + "backgroundColor": "transparent", + "borderColor": "transparent", + "borderRadius": 8, "borderWidth": 1, }, false, @@ -1447,9 +1447,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon 1`] = ` { "alignItems": "center", "flexDirection": "row", - "gap": 7, - "paddingHorizontal": 10.5, - "paddingVertical": 7, + "gap": 8, + "paddingHorizontal": 14, + "paddingVertical": 8, } } > @@ -1458,7 +1458,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon 1`] = ` { "flex": 1, "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -1473,15 +1473,15 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon 1`] = ` @@ -1588,20 +1588,20 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, { - "fontSize": 12.25, - "lineHeight": 18, + "fontSize": 14, + "lineHeight": 20, }, undefined, undefined, @@ -1658,9 +1658,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon and badge 1`] = ` style={ [ { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 7, + "backgroundColor": "transparent", + "borderColor": "transparent", + "borderRadius": 8, "borderWidth": 1, }, false, @@ -1675,9 +1675,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon and badge 1`] = ` { "alignItems": "center", "flexDirection": "row", - "gap": 7, - "paddingHorizontal": 10.5, - "paddingVertical": 7, + "gap": 8, + "paddingHorizontal": 14, + "paddingVertical": 8, } } > @@ -1686,7 +1686,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon and badge 1`] = ` { "flex": 1, "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -1701,15 +1701,15 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon and badge 1`] = ` @@ -1851,20 +1851,20 @@ exports[`MenuItemTemplate tests MenuItemTemplate with icon and badge 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, { - "fontSize": 12.25, - "lineHeight": 18, + "fontSize": 14, + "lineHeight": 20, }, undefined, undefined, @@ -1921,9 +1921,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with padding 1`] = ` style={ [ { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 7, + "backgroundColor": "transparent", + "borderColor": "transparent", + "borderRadius": 8, "borderWidth": 1, }, false, @@ -1941,9 +1941,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with padding 1`] = ` { "alignItems": "center", "flexDirection": "row", - "gap": 7, - "paddingHorizontal": 10.5, - "paddingVertical": 7, + "gap": 8, + "paddingHorizontal": 14, + "paddingVertical": 8, } } > @@ -1952,7 +1952,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with padding 1`] = ` { "flex": 1, "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -1960,7 +1960,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with padding 1`] = ` style={ { "flex": 1, - "gap": 3.5, + "gap": 4, } } > @@ -1969,20 +1969,20 @@ exports[`MenuItemTemplate tests MenuItemTemplate with padding 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, { - "fontSize": 12.25, - "lineHeight": 18, + "fontSize": 14, + "lineHeight": 20, }, undefined, undefined, @@ -2006,7 +2006,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with separator 1`] = ` { "borderTopColor": "#e2e2e4", "borderTopWidth": 1, - "paddingTop": 3.5, + "paddingTop": 4, } } > @@ -2045,9 +2045,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with separator 1`] = ` style={ [ { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 7, + "backgroundColor": "transparent", + "borderColor": "transparent", + "borderRadius": 8, "borderWidth": 1, }, false, @@ -2062,9 +2062,9 @@ exports[`MenuItemTemplate tests MenuItemTemplate with separator 1`] = ` { "alignItems": "center", "flexDirection": "row", - "gap": 7, - "paddingHorizontal": 10.5, - "paddingVertical": 7, + "gap": 8, + "paddingHorizontal": 14, + "paddingVertical": 8, } } > @@ -2073,7 +2073,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with separator 1`] = ` { "flex": 1, "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2081,7 +2081,7 @@ exports[`MenuItemTemplate tests MenuItemTemplate with separator 1`] = ` style={ { "flex": 1, - "gap": 3.5, + "gap": 4, } } > @@ -2090,20 +2090,20 @@ exports[`MenuItemTemplate tests MenuItemTemplate with separator 1`] = ` [ { "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, - "lineHeight": 20, + "lineHeight": 22, "verticalAlign": "middle", }, { "fontWeight": 400, }, { - "color": "#181a1f", + "color": "#2b2e33", }, { - "fontSize": 12.25, - "lineHeight": 18, + "fontSize": 14, + "lineHeight": 20, }, undefined, undefined, From 10a06d21df6647371076ff747a8299d5b8662408 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:46 +0300 Subject: [PATCH 27/60] =?UTF-8?q?feat(Message):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Message/Message.tsx | 133 +++++---- .../__snapshots__/Message.test.tsx.snap | 252 +++++++++--------- 2 files changed, 187 insertions(+), 198 deletions(-) diff --git a/src/components/Message/Message.tsx b/src/components/Message/Message.tsx index 728468fa..9000650e 100644 --- a/src/components/Message/Message.tsx +++ b/src/components/Message/Message.tsx @@ -16,7 +16,7 @@ import { import { StyleSheet } from 'react-native-unistyles' -import type { ThemeType } from '../../theme/types' +import type { ComponentTokens } from '../../theme/tokens/index' import { type SvgSource, SvgUniversal } from '../../utils/SvgUniversal' import { ButtonSeverity } from '../Button/ButtonSeverity' import { Timer } from '../Timer/Timer' @@ -88,12 +88,12 @@ type MessageSeverityKey = NonNullable const messageIconColor: Record< MessageSeverityKey, - (t: ThemeType['theme']) => string + (t: ComponentTokens) => string > = { - info: (t) => t.Message.Severities.Info.infoMessageIconColor, - success: (t) => t.Message.Severities.Success.successMessageIconColor, - warning: (t) => t.Message.Severities.Warning.warningMessageIconColor, - danger: (t) => t.Message.Severities.Danger.dangerMessageIconColor, + info: (t) => t.message.extend.extInfo.color, + success: (t) => t.message.extend.extSuccess.color, + warning: (t) => t.message.extend.extWarn.color, + danger: (t) => t.message.extend.extError.color, } /** @@ -180,9 +180,9 @@ export const Message = memo( {...messageStyles.iconSize} source={Icon} testID={TestId.Icon} - uniProps={({ theme }) => ({ - color: messageIconColor[severity](theme), - })} + uniProps={({ components }) => { + return { color: messageIconColor[severity](components) } + }} /> ) } @@ -218,73 +218,66 @@ export const Message = memo( } ) -const messageStyles = StyleSheet.create( - ({ theme, typography, spacing, border }) => ({ - container: { - borderRadius: theme.General.borderRadiusXL, - borderWidth: border.Width.border, - overflow: 'hidden', - variants: { - severity: { - info: { - borderColor: theme.Message.Severities.Info.infoMessageBorderColor, - backgroundColor: theme.Message.Severities.Info.infoMessageBg, - }, - success: { - borderColor: - theme.Message.Severities.Success.successMessageBorderColor, - backgroundColor: theme.Message.Severities.Success.successMessageBg, - }, - warning: { - borderColor: - theme.Message.Severities.Warning.warningMessageBorderColor, - backgroundColor: theme.Message.Severities.Warning.warningMessageBg, - }, - danger: { - borderColor: - theme.Message.Severities.Danger.dangerMessageBorderColor, - backgroundColor: theme.Message.Severities.Danger.dangerMessageBg, - }, +const messageStyles = StyleSheet.create(({ components, semantic }) => ({ + container: { + borderRadius: components.message.root.borderRadius, + borderWidth: semantic.dimension.borderWidth[100], + overflow: 'hidden', + variants: { + severity: { + info: { + borderColor: components.message.colorScheme.info.borderColor, + backgroundColor: components.message.colorScheme.info.background, + }, + success: { + borderColor: components.message.colorScheme.success.borderColor, + backgroundColor: components.message.colorScheme.success.background, + }, + warning: { + borderColor: components.message.colorScheme.warn.borderColor, + backgroundColor: components.message.colorScheme.warn.background, + }, + danger: { + borderColor: components.message.colorScheme.error.borderColor, + backgroundColor: components.message.colorScheme.error.background, }, }, }, - content: { - flexGrow: 1, - borderLeftWidth: border.Width['border-3'] - border.Width.border, - padding: spacing.Padding['p-4'], - paddingLeft: spacing.Padding['p-5'], - gap: spacing.Gap['gap-4'], - variants: { - severity: { - info: { - borderColor: theme.Message.Severities.Info.infoMessageIconColor, - }, - success: { - borderColor: - theme.Message.Severities.Success.successMessageIconColor, - }, - warning: { - borderColor: - theme.Message.Severities.Warning.warningMessageIconColor, - }, - danger: { - borderColor: theme.Message.Severities.Danger.dangerMessageIconColor, - }, + }, + content: { + flexGrow: 1, + borderLeftWidth: + components.message.extend.extAccentLine.width - + semantic.dimension.borderWidth[100], + padding: semantic.dimension.space[400], + paddingLeft: components.message.content.padding, + gap: semantic.dimension.space[400], + variants: { + severity: { + info: { borderColor: components.message.colorScheme.info.borderColor }, + success: { + borderColor: components.message.colorScheme.success.borderColor, + }, + warning: { + borderColor: components.message.colorScheme.warn.borderColor, + }, + danger: { + borderColor: components.message.colorScheme.error.borderColor, }, }, }, - titleRow: { flexDirection: 'row', gap: spacing.Gap['gap-4'] }, - titleTextContainer: { - flex: 1, - alignSelf: 'center', - gap: spacing.Gap['gap-1'], - }, - iconSize: { - width: typography.Size['text-4xl'], - height: typography.Size['text-4xl'], - }, - }) -) + }, + titleRow: { flexDirection: 'row', gap: semantic.dimension.space[400] }, + titleTextContainer: { + flex: 1, + alignSelf: 'center', + gap: components.message.extend.extText.gap, + }, + iconSize: { + width: components.message.icon.size, + height: components.message.icon.size, + }, +})) export enum TestId { Container = 'MessageContainer', diff --git a/src/components/Message/__tests__/__snapshots__/Message.test.tsx.snap b/src/components/Message/__tests__/__snapshots__/Message.test.tsx.snap index 06eed4f8..26df81f9 100644 --- a/src/components/Message/__tests__/__snapshots__/Message.test.tsx.snap +++ b/src/components/Message/__tests__/__snapshots__/Message.test.tsx.snap @@ -7,8 +7,8 @@ exports[`Message {"Icon": [Object], "timerValue": 5} 1`] = ` [ { "backgroundColor": "#fafdff", - "borderColor": "#d4ecfe", - "borderRadius": 10.5, + "borderColor": "#4496e8", + "borderRadius": 14, "borderWidth": 1, "overflow": "hidden", }, @@ -21,11 +21,11 @@ exports[`Message {"Icon": [Object], "timerValue": 5} 1`] = ` style={ { "borderColor": "#4496e8", - "borderLeftWidth": 2, + "borderLeftWidth": 3, "flexGrow": 1, "gap": 14, "padding": 14, - "paddingLeft": 17.5, + "paddingLeft": 14, } } > @@ -45,7 +45,7 @@ exports[`Message {"Icon": [Object], "timerValue": 5} 1`] = ` { "alignSelf": "center", "flex": 1, - "gap": 3.5, + "gap": 4, } } > @@ -69,8 +69,8 @@ exports[`Message {"Icon": [Object]} 1`] = ` [ { "backgroundColor": "#fafdff", - "borderColor": "#d4ecfe", - "borderRadius": 10.5, + "borderColor": "#4496e8", + "borderRadius": 14, "borderWidth": 1, "overflow": "hidden", }, @@ -83,11 +83,11 @@ exports[`Message {"Icon": [Object]} 1`] = ` style={ { "borderColor": "#4496e8", - "borderLeftWidth": 2, + "borderLeftWidth": 3, "flexGrow": 1, "gap": 14, "padding": 14, - "paddingLeft": 17.5, + "paddingLeft": 14, } } > @@ -101,11 +101,11 @@ exports[`Message {"Icon": [Object]} 1`] = ` > @@ -230,8 +230,8 @@ exports[`Message {"body": [Object], "caption": "caption", "severity": "info", "s [ { "backgroundColor": "#fafdff", - "borderColor": "#d4ecfe", - "borderRadius": 10.5, + "borderColor": "#4496e8", + "borderRadius": 14, "borderWidth": 1, "overflow": "hidden", }, @@ -246,11 +246,11 @@ exports[`Message {"body": [Object], "caption": "caption", "severity": "info", "s style={ { "borderColor": "#4496e8", - "borderLeftWidth": 2, + "borderLeftWidth": 3, "flexGrow": 1, "gap": 14, "padding": 14, - "paddingLeft": 17.5, + "paddingLeft": 14, } } > @@ -264,11 +264,11 @@ exports[`Message {"body": [Object], "caption": "caption", "severity": "info", "s > @@ -428,8 +428,8 @@ exports[`Message {"body": [Object], "footer": [Object], "severity": "warning"} 1 [ { "backgroundColor": "#fffdfa", - "borderColor": "#ffeed4", - "borderRadius": 10.5, + "borderColor": "#f5b83d", + "borderRadius": 14, "borderWidth": 1, "overflow": "hidden", }, @@ -442,11 +442,11 @@ exports[`Message {"body": [Object], "footer": [Object], "severity": "warning"} 1 style={ { "borderColor": "#f5b83d", - "borderLeftWidth": 2, + "borderLeftWidth": 3, "flexGrow": 1, "gap": 14, "padding": 14, - "paddingLeft": 17.5, + "paddingLeft": 14, } } > @@ -460,11 +460,11 @@ exports[`Message {"body": [Object], "footer": [Object], "severity": "warning"} 1 > @@ -622,8 +622,8 @@ exports[`Message {"closeLabel": "Close", "footer": [Object], "onClose": [Functio [ { "backgroundColor": "#fafffb", - "borderColor": "#d4fedc", - "borderRadius": 10.5, + "borderColor": "#44e858", + "borderRadius": 14, "borderWidth": 1, "overflow": "hidden", }, @@ -636,11 +636,11 @@ exports[`Message {"closeLabel": "Close", "footer": [Object], "onClose": [Functio style={ { "borderColor": "#44e858", - "borderLeftWidth": 2, + "borderLeftWidth": 3, "flexGrow": 1, "gap": 14, "padding": 14, - "paddingLeft": 17.5, + "paddingLeft": 14, } } > @@ -654,11 +654,11 @@ exports[`Message {"closeLabel": "Close", "footer": [Object], "onClose": [Functio > @@ -806,18 +806,16 @@ exports[`Message {"closeLabel": "Close", "footer": [Object], "onClose": [Functio [ { "alignItems": "center", - "backgroundColor": "rgba(255, 255, 255, 0.0001)", - "borderColor": "#44e858", - "borderRadius": 10.5, + "backgroundColor": "transparent", + "borderColor": "#1dc831", + "borderRadius": 14, "borderWidth": 1, "flexDirection": "row", - "gap": 7, - "height": 28, + "gap": 8, + "height": "auto", "justifyContent": "center", - "maxHeight": 28, - "minHeight": 28, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "paddingHorizontal": 14, + "paddingVertical": 8, }, false, ] @@ -827,9 +825,9 @@ exports[`Message {"closeLabel": "Close", "footer": [Object], "onClose": [Functio @@ -887,11 +885,11 @@ exports[`Message {"footer": [Object], "onClose": [Function mockConstructor], "se > @@ -1039,18 +1037,16 @@ exports[`Message {"footer": [Object], "onClose": [Function mockConstructor], "se [ { "alignItems": "center", - "backgroundColor": "rgba(255, 255, 255, 0.0001)", - "borderColor": "#44e858", - "borderRadius": 10.5, + "backgroundColor": "transparent", + "borderColor": "#1dc831", + "borderRadius": 14, "borderWidth": 1, "flexDirection": "row", - "gap": 7, - "height": 28, + "gap": 8, + "height": "auto", "justifyContent": "center", - "maxHeight": 28, - "minHeight": 28, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "paddingHorizontal": 14, + "paddingVertical": 8, }, { "aspectRatio": 1, @@ -1061,15 +1057,15 @@ exports[`Message {"footer": [Object], "onClose": [Function mockConstructor], "se > @@ -1209,11 +1205,11 @@ exports[`Message {"hiddenIcon": false} 1`] = ` > @@ -1361,8 +1357,8 @@ exports[`Message {"onTimerFinish": [Function mockConstructor], "timerValue": 5} [ { "backgroundColor": "#fafdff", - "borderColor": "#d4ecfe", - "borderRadius": 10.5, + "borderColor": "#4496e8", + "borderRadius": 14, "borderWidth": 1, "overflow": "hidden", }, @@ -1375,11 +1371,11 @@ exports[`Message {"onTimerFinish": [Function mockConstructor], "timerValue": 5} style={ { "borderColor": "#4496e8", - "borderLeftWidth": 2, + "borderLeftWidth": 3, "flexGrow": 1, "gap": 14, "padding": 14, - "paddingLeft": 17.5, + "paddingLeft": 14, } } > @@ -1400,7 +1396,7 @@ exports[`Message {"onTimerFinish": [Function mockConstructor], "timerValue": 5} { "alignSelf": "center", "flex": 1, - "gap": 3.5, + "gap": 4, } } > @@ -1424,8 +1420,8 @@ exports[`Message {"severity": "danger"} 1`] = ` [ { "backgroundColor": "#fffafa", - "borderColor": "#fed4d4", - "borderRadius": 10.5, + "borderColor": "#e85244", + "borderRadius": 14, "borderWidth": 1, "overflow": "hidden", }, @@ -1438,11 +1434,11 @@ exports[`Message {"severity": "danger"} 1`] = ` style={ { "borderColor": "#e85244", - "borderLeftWidth": 2, + "borderLeftWidth": 3, "flexGrow": 1, "gap": 14, "padding": 14, - "paddingLeft": 17.5, + "paddingLeft": 14, } } > @@ -1456,11 +1452,11 @@ exports[`Message {"severity": "danger"} 1`] = ` > @@ -1608,8 +1604,8 @@ exports[`Message {} 1`] = ` [ { "backgroundColor": "#fafdff", - "borderColor": "#d4ecfe", - "borderRadius": 10.5, + "borderColor": "#4496e8", + "borderRadius": 14, "borderWidth": 1, "overflow": "hidden", }, @@ -1622,11 +1618,11 @@ exports[`Message {} 1`] = ` style={ { "borderColor": "#4496e8", - "borderLeftWidth": 2, + "borderLeftWidth": 3, "flexGrow": 1, "gap": 14, "padding": 14, - "paddingLeft": 17.5, + "paddingLeft": 14, } } > @@ -1640,11 +1636,11 @@ exports[`Message {} 1`] = ` > From c4b629cc540c7652ae0d59fd4b5a4abc42c909e1 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:46 +0300 Subject: [PATCH 28/60] =?UTF-8?q?feat(ProgressBar):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ProgressBar/ProgressBar.tsx | 16 +-- .../__snapshots__/ProgressBar.test.tsx.snap | 100 +++++++++--------- 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/components/ProgressBar/ProgressBar.tsx b/src/components/ProgressBar/ProgressBar.tsx index 2b4630e6..de3c6667 100644 --- a/src/components/ProgressBar/ProgressBar.tsx +++ b/src/components/ProgressBar/ProgressBar.tsx @@ -89,28 +89,28 @@ export const ProgressBar = memo( } ) -const styles = StyleSheet.create(({ theme, typography, border, fonts }) => ({ +const styles = StyleSheet.create(({ components, fonts }) => ({ container: { - borderRadius: border.Radius['rounded-full'], - backgroundColor: theme.Misc.ProgressBar.progressBarBg, + borderRadius: components.progressbar.root.borderRadius, + backgroundColor: components.progressbar.root.background, overflow: 'hidden', }, indicator: { alignItems: 'center', justifyContent: 'center', - backgroundColor: theme.Misc.ProgressBar.progressBarValueBg, + backgroundColor: components.progressbar.value.background, height: '100%', overflow: 'hidden', }, - containerShowValue: { height: theme.Misc.ProgressBar.progressBarHeight }, + containerShowValue: { height: components.progressbar.root.height }, indicatorText: { - fontSize: typography.Size['text-xs'], + fontSize: components.progressbar.label.fontSize, textAlign: 'center', - color: theme.Misc.ProgressBar.progressBarValueTextColor, - fontFamily: fonts.primary, + color: components.progressbar.label.color, + fontFamily: fonts.fontFamily.heading, }, })) diff --git a/src/components/ProgressBar/__tests__/__snapshots__/ProgressBar.test.tsx.snap b/src/components/ProgressBar/__tests__/__snapshots__/ProgressBar.test.tsx.snap index f5afd78f..97a74194 100644 --- a/src/components/ProgressBar/__tests__/__snapshots__/ProgressBar.test.tsx.snap +++ b/src/components/ProgressBar/__tests__/__snapshots__/ProgressBar.test.tsx.snap @@ -7,7 +7,7 @@ exports[`ProgressBar component test value - -50, showValue - false, style - {"he [ { "backgroundColor": "#e2e2e4", - "borderRadius": 100, + "borderRadius": 14, "overflow": "hidden", }, { @@ -69,7 +69,7 @@ exports[`ProgressBar component test value - -50, showValue - false, style - {"he [ { "backgroundColor": "#e2e2e4", - "borderRadius": 100, + "borderRadius": 14, "overflow": "hidden", }, { @@ -131,7 +131,7 @@ exports[`ProgressBar component test value - -50, showValue - true, style - {"hei [ { "backgroundColor": "#e2e2e4", - "borderRadius": 100, + "borderRadius": 14, "overflow": "hidden", }, { @@ -139,7 +139,7 @@ exports[`ProgressBar component test value - -50, showValue - true, style - {"hei "width": 100, }, { - "height": 14, + "height": 16, }, ] } @@ -188,9 +188,9 @@ exports[`ProgressBar component test value - -50, showValue - true, style - {"hei Date: Tue, 4 Aug 2026 17:05:47 +0300 Subject: [PATCH 29/60] =?UTF-8?q?feat(ProgressSpinner):=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ProgressSpinner/ProgressSpinner.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/ProgressSpinner/ProgressSpinner.tsx b/src/components/ProgressSpinner/ProgressSpinner.tsx index 390467ac..0973a879 100644 --- a/src/components/ProgressSpinner/ProgressSpinner.tsx +++ b/src/components/ProgressSpinner/ProgressSpinner.tsx @@ -125,10 +125,12 @@ export const ProgressSpinner = memo( } ) -const styles = StyleSheet.create(({ theme, global }) => ({ - primary: { color: theme.General.primaryColor }, - white: { color: global.Neutrals.White['white-100'] }, -})) +const styles = StyleSheet.create( + ({ components: { progressspinner }, semantic }) => ({ + primary: { color: progressspinner.colorScheme.root.colorOne }, + white: { color: semantic.colorScheme.color.fg.on.fill.default }, + }) +) enum TestId { ProgressSpinner = 'ProgressSpinner', From 30c3968e6d50c6f35b3751a9c374638631a53e08 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:47 +0300 Subject: [PATCH 30/60] =?UTF-8?q?feat(RadioButton):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/RadioButton/RadioButton.tsx | 66 +-- .../__snapshots__/RadioButton.test.tsx.snap | 460 ++++-------------- 2 files changed, 108 insertions(+), 418 deletions(-) diff --git a/src/components/RadioButton/RadioButton.tsx b/src/components/RadioButton/RadioButton.tsx index 8eb0e7a6..e5fddbd0 100644 --- a/src/components/RadioButton/RadioButton.tsx +++ b/src/components/RadioButton/RadioButton.tsx @@ -52,7 +52,6 @@ export const RadioButton = memo( return ( - ( } ) -const radioStyles = StyleSheet.create(({ theme, border }) => ({ +const radioStyles = StyleSheet.create(({ components, semantic }) => ({ container: { - width: theme.Form.RadioButton.radiobuttonWidth, - height: theme.Form.RadioButton.radiobuttonHeight, - borderRadius: border.Radius['rounded-full'], - borderWidth: 1, + width: components.radiobutton.root.width, + height: components.radiobutton.root.height, + borderRadius: semantic.dimension.borderRadius.max, + borderWidth: semantic.dimension.borderWidth[100], alignItems: 'center', justifyContent: 'center', transitionProperty: ['borderColor', 'backgroundColor'], @@ -82,20 +81,20 @@ const radioStyles = StyleSheet.create(({ theme, border }) => ({ variants: { checked: { true: { - borderColor: theme.Form.RadioButton.radiobuttonActiveBorderColor, - backgroundColor: theme.Form.RadioButton.radiobuttonActiveBorderColor, + borderColor: components.radiobutton.root.checkedBorderColor, + backgroundColor: components.radiobutton.root.checkedBackground, }, false: { - borderColor: theme.Form.InputText.inputBorderColor, - backgroundColor: theme.Form.InputText.inputBg, + borderColor: components.radiobutton.root.borderColor, + backgroundColor: components.radiobutton.root.background, }, }, pressed: { true: {}, false: {} }, disabled: { true: { - borderColor: theme.Form.InputText.inputBorderColor, - backgroundColor: theme.Button.Disabled.disabledButtonBg, - opacity: 0.6, + borderColor: components.radiobutton.root.borderColor, + backgroundColor: components.radiobutton.root.disabledBackground, + opacity: semantic.effects.opacity[60], }, false: {}, }, @@ -106,59 +105,38 @@ const radioStyles = StyleSheet.create(({ theme, border }) => ({ checked: 'true', pressed: 'true', styles: { - borderColor: theme.Form.RadioButton.radiobuttonActiveHoverBorderColor, - backgroundColor: theme.Form.RadioButton.radiobuttonActiveHoverBg, + borderColor: components.radiobutton.root.checkedHoverBorderColor, + backgroundColor: components.radiobutton.root.checkedHoverBackground, }, }, { checked: 'true', disabled: 'true', styles: { - borderColor: theme.Form.RadioButton.radiobuttonActiveBorderColor, - backgroundColor: theme.Form.RadioButton.radiobuttonActiveBorderColor, + borderColor: components.radiobutton.root.checkedBorderColor, + backgroundColor: components.radiobutton.root.checkedBackground, }, }, { state: 'danger', disabled: 'false', checked: 'false', - styles: { borderColor: theme.Form.InputText.inputErrorBorderColor }, + styles: { borderColor: components.radiobutton.root.invalidBorderColor }, }, { checked: 'false', pressed: 'true', - styles: { - borderColor: theme.Form.RadioButton.radiobuttonActiveHoverBorderColor, - }, + styles: { borderColor: components.radiobutton.root.hoverBorderColor }, }, ], }, center: { - width: theme.Form.RadioButton.radiobuttonIconSize, - height: theme.Form.RadioButton.radiobuttonIconSize, - borderRadius: border.Radius['rounded-full'], - backgroundColor: theme.Form.InputText.inputBg, + width: components.radiobutton.icon.size, + height: components.radiobutton.icon.size, + borderRadius: semantic.dimension.borderRadius.max, + backgroundColor: components.radiobutton.root.background, transitionProperty: ['opacity'], transitionDuration: 100, variants: { checked: { false: { opacity: 0 }, true: { opacity: 1 } } }, }, - outline: { - position: 'absolute', - top: -theme.General.focusShadowWidth, - left: -theme.General.focusShadowWidth, - width: - theme.Form.RadioButton.radiobuttonWidth + - theme.General.focusShadowWidth * 2, - height: - theme.Form.RadioButton.radiobuttonHeight + - theme.General.focusShadowWidth * 2, - borderRadius: border.Radius['rounded-full'], - backgroundColor: theme.General.focusOutlineErrorColor, - transitionProperty: 'opacity', - transitionDuration: 100, - variants: { - state: { danger: { opacity: 1 }, default: { opacity: 0 } }, - disabled: { true: { opacity: 0 } }, - }, - }, })) diff --git a/src/components/RadioButton/__tests__/__snapshots__/RadioButton.test.tsx.snap b/src/components/RadioButton/__tests__/__snapshots__/RadioButton.test.tsx.snap index cb279583..43b79c4b 100644 --- a/src/components/RadioButton/__tests__/__snapshots__/RadioButton.test.tsx.snap +++ b/src/components/RadioButton/__tests__/__snapshots__/RadioButton.test.tsx.snap @@ -2,48 +2,6 @@ exports[`RadioButton snapshots checked = false, disabled = false, state = danger 1`] = ` - - - - - - - Date: Tue, 4 Aug 2026 17:05:48 +0300 Subject: [PATCH 31/60] =?UTF-8?q?feat(Rating):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Rating/Rating.tsx | 4 +- src/components/Rating/RatingClear.tsx | 22 +- src/components/Rating/RatingItem.tsx | 24 +- src/components/Rating/RatingItemContainer.tsx | 11 +- .../__snapshots__/Rating.test.tsx.snap | 294 ++++++++-------- .../__snapshots__/RatingClear.test.tsx.snap | 176 +++++----- .../__snapshots__/RatingItem.test.tsx.snap | 328 +++++++++--------- 7 files changed, 429 insertions(+), 430 deletions(-) diff --git a/src/components/Rating/Rating.tsx b/src/components/Rating/Rating.tsx index fed0e34e..5aaf52a8 100644 --- a/src/components/Rating/Rating.tsx +++ b/src/components/Rating/Rating.tsx @@ -100,10 +100,10 @@ export const Rating = memo( } ) -const styles = StyleSheet.create(({ theme }) => ({ +const styles = StyleSheet.create(({ components }) => ({ container: { flexDirection: 'row', - gap: theme.General.inlineSpacing, + gap: components.rating.root.gap, alignItems: 'center', }, })) diff --git a/src/components/Rating/RatingClear.tsx b/src/components/Rating/RatingClear.tsx index 5c6d47c1..7560ee92 100644 --- a/src/components/Rating/RatingClear.tsx +++ b/src/components/Rating/RatingClear.tsx @@ -32,22 +32,24 @@ export const RatingClear = memo(({ ...rest }) => { ({ - color: disabled - ? theme.custom.rating.ratingCancelIconDisabledColor - : pressed - ? theme.Form.Rating.ratingCancelIconHoverColor - : theme.Form.Rating.ratingCancelIconColor, - })} + uniProps={({ components }) => { + return { + color: disabled + ? components.rating.icon.color + : pressed + ? components.rating.icon.hoverColor + : components.rating.icon.color, + } + }} /> )} ) }) -const styles = StyleSheet.create(({ theme }) => ({ +const styles = StyleSheet.create(({ components }) => ({ icon: { - height: theme.Form.Rating.ratingIconFontSize, - width: theme.Form.Rating.ratingIconFontSize, + height: components.rating.icon.size, + width: components.rating.icon.size, }, })) diff --git a/src/components/Rating/RatingItem.tsx b/src/components/Rating/RatingItem.tsx index 92fffb31..0cdc6951 100644 --- a/src/components/Rating/RatingItem.tsx +++ b/src/components/Rating/RatingItem.tsx @@ -41,25 +41,25 @@ export const RatingItem = memo(({ checked, ...rest }) => { {...styles.icon} fillOpacity={checked ? 1 : 0} source={Icon} - uniProps={({ theme }) => { + uniProps={({ components }) => { const color = disabled ? checked - ? theme.custom.rating.ratingStarIconOnDisabledColor - : theme.custom.rating.ratingStarIconOffDisabledColor + ? components.rating.icon.activeColor + : components.rating.icon.color : pressed - ? theme.Form.Rating.ratingStarIconHoverColor + ? components.rating.icon.hoverColor : checked - ? theme.Form.Rating.ratingStarIconOnColor - : theme.Form.Rating.ratingStarIconOffColor + ? components.rating.icon.activeColor + : components.rating.icon.color return { color, fill: checked ? disabled - ? theme.custom.rating.ratingStarIconOnDisabledColor + ? components.rating.icon.activeColor : pressed - ? theme.Form.Rating.ratingStarIconHoverColor - : theme.Form.Rating.ratingStarIconOnColor + ? components.rating.icon.hoverColor + : components.rating.icon.activeColor : undefined, } }} @@ -69,9 +69,9 @@ export const RatingItem = memo(({ checked, ...rest }) => { ) }) -const styles = StyleSheet.create(({ theme }) => ({ +const styles = StyleSheet.create(({ components }) => ({ icon: { - height: theme.Form.Rating.ratingIconFontSize, - width: theme.Form.Rating.ratingIconFontSize, + height: components.rating.icon.size, + width: components.rating.icon.size, }, })) diff --git a/src/components/Rating/RatingItemContainer.tsx b/src/components/Rating/RatingItemContainer.tsx index 3776dbc7..c39eceff 100644 --- a/src/components/Rating/RatingItemContainer.tsx +++ b/src/components/Rating/RatingItemContainer.tsx @@ -55,16 +55,13 @@ export const RatingItemContainer = memo( } ) -const styles = StyleSheet.create(({ theme, sizing }) => ({ +const styles = StyleSheet.create(({ components }) => ({ container: { alignItems: 'center', justifyContent: 'center', - width: theme.Form.Rating.ratingIconFontSize, - height: theme.Form.Rating.ratingIconFontSize, + width: components.rating.icon.size, + height: components.rating.icon.size, }, - containerWithPaddings: { - width: sizing.Width['w-3'], - height: sizing.Height['h-3'], - }, + containerWithPaddings: { width: 42, height: 42 }, })) diff --git a/src/components/Rating/__tests__/__snapshots__/Rating.test.tsx.snap b/src/components/Rating/__tests__/__snapshots__/Rating.test.tsx.snap index 9a97587d..19ba0f8e 100644 --- a/src/components/Rating/__tests__/__snapshots__/Rating.test.tsx.snap +++ b/src/components/Rating/__tests__/__snapshots__/Rating.test.tsx.snap @@ -6,7 +6,7 @@ exports[`Rating component tests renders correctly with default props 1`] = ` { "alignItems": "center", "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -44,9 +44,9 @@ exports[`Rating component tests renders correctly with default props 1`] = ` [ { "alignItems": "center", - "height": 17.5, + "height": 24, "justifyContent": "center", - "width": 17.5, + "width": 24, }, false, ] @@ -55,11 +55,11 @@ exports[`Rating component tests renders correctly with default props 1`] = ` > @@ -827,9 +827,9 @@ exports[`Rating component tests renders the correct number of checked items - $r [ { "alignItems": "center", - "height": 17.5, + "height": 24, "justifyContent": "center", - "width": 17.5, + "width": 24, }, false, ] @@ -838,11 +838,11 @@ exports[`Rating component tests renders the correct number of checked items - $r > @@ -1610,9 +1610,9 @@ exports[`Rating component tests renders the correct number of checked items - $r [ { "alignItems": "center", - "height": 17.5, + "height": 24, "justifyContent": "center", - "width": 17.5, + "width": 24, }, false, ] @@ -1621,11 +1621,11 @@ exports[`Rating component tests renders the correct number of checked items - $r > Date: Tue, 4 Aug 2026 17:05:48 +0300 Subject: [PATCH 32/60] =?UTF-8?q?feat(SelectButton):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SelectButton/SelectButton.tsx | 29 ++-- .../SelectButton/SelectButtonItem.tsx | 129 ++++++++++-------- .../__tests__/SelectButtonItem.test.tsx | 36 +++-- 3 files changed, 101 insertions(+), 93 deletions(-) diff --git a/src/components/SelectButton/SelectButton.tsx b/src/components/SelectButton/SelectButton.tsx index 24fe6ab8..68f6fff5 100644 --- a/src/components/SelectButton/SelectButton.tsx +++ b/src/components/SelectButton/SelectButton.tsx @@ -271,25 +271,26 @@ export const SelectButton = memo((props) => ( )) -const styles = StyleSheet.create(({ theme }) => ({ +// Осознанный обход слоя components: цвет невыбранного пункта — семантическая +// роль «приглушённый текст». Собственного токена у selectbutton нет, а то же +// значение приходит в tabs.tab.color и menu.item.color. +const styles = StyleSheet.create(({ components, semantic }) => ({ container: { flexDirection: 'row', - padding: theme.Form.SelectButton.selectButtonGroupPadding, - gap: theme.Form.SelectButton.selectButtonGroupPadding, - borderRadius: theme.General.borderRadiusXL, - backgroundColor: theme.Form.SelectButton.selectButtonGroupBg, + padding: components.selectbutton.extend.paddingX, + gap: components.selectbutton.extend.paddingX, + borderRadius: components.selectbutton.root.borderRadius, + backgroundColor: components.selectbutton.colorScheme.extend.background, }, frame: { position: 'absolute', - top: theme.Form.SelectButton.selectButtonGroupPadding, - bottom: theme.Form.SelectButton.selectButtonGroupPadding, - left: theme.Form.SelectButton.selectButtonGroupPadding, - borderRadius: theme.Form.SelectButton.selectButtonBorderRadius, - backgroundColor: theme.Form.SelectButton.selectButtonActiveBg, + top: components.selectbutton.extend.paddingY, + bottom: components.selectbutton.extend.paddingY, + left: components.selectbutton.extend.paddingX, + borderRadius: components.selectbutton.extend.ext.borderRadius, + backgroundColor: components.selectbutton.extend.checkedBackground, zIndex: -1, }, - textColor: { color: theme.Form.SelectButton.selectButtonTextColor }, - checkedTextColor: { - color: theme.Form.SelectButton.selectButtonIconActiveColor, - }, + textColor: { color: semantic.colorScheme.color.fg.muted }, + checkedTextColor: { color: components.selectbutton.extend.checkedColor }, })) diff --git a/src/components/SelectButton/SelectButtonItem.tsx b/src/components/SelectButton/SelectButtonItem.tsx index 4c8ca4e6..3f7da2d7 100644 --- a/src/components/SelectButton/SelectButtonItem.tsx +++ b/src/components/SelectButton/SelectButtonItem.tsx @@ -127,13 +127,15 @@ export const SelectButtonItem = memo( {...iconSize} source={Icon} testID='SelectButtonItem_Icon' - uniProps={({ theme }) => ({ - color: disabled - ? theme.Button.Disabled.disabledButtonBorderColor - : isSelected - ? theme.Form.SelectButton.selectButtonIconActiveColor - : theme.Form.SelectButton.selectButtonTextColor, - })} + uniProps={({ components, semantic }) => { + return { + color: disabled + ? semantic.colorScheme.color.border.neutral.strong + : isSelected + ? components.selectbutton.extend.checkedColor + : semantic.colorScheme.color.fg.muted, + } + }} /> ) : null} ( } ) -const styles = StyleSheet.create( - ({ theme, typography, border, spacing, fonts }) => ({ - container: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - gap: theme.General.inlineSpacing, - borderWidth: border.Width.border, - borderColor: 'transparent', - }, - small: { height: theme.Button.Common.buttonHeightSM }, - base: { height: theme.Button.Common.buttonHeight }, - large: { - height: theme.Button.Common.buttonHeightLG, - gap: spacing.Gap['gap-3'], - }, - xlarge: { - height: theme.Button.Common.buttonHeightXL, - gap: spacing.Gap['gap-3'], - }, - disabledContainer: { - borderRadius: theme.Form.SelectButton.selectButtonBorderRadius, - borderWidth: 1, - borderColor: theme.Button.Disabled.disabledButtonBorderColor, - }, - iconSmall: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], - }, - iconBase: { - width: typography.Size['text-xl'], - height: typography.Size['text-xl'], - }, - iconLarge: { - width: typography.Size['text-2xl'], - height: typography.Size['text-2xl'], - }, - iconXLarge: { width: 28, height: 28 }, - label: { flexShrink: 1, fontWeight: 600, fontFamily: fonts.primary }, - labelSmall: { fontSize: typography.Size['text-sm'] }, - labelBase: { fontSize: typography.Size['text-base'] }, - labelLarge: { fontSize: typography.Size['text-xl'] }, - labelXLarge: { fontSize: typography.Size['text-2xl'] }, - textColor: { color: theme.Form.SelectButton.selectButtonTextColor }, - checkedTextColor: { - color: theme.Form.SelectButton.selectButtonIconActiveColor, - }, - disabledTextColor: { - color: theme.Button.Disabled.disabledButtonBorderColor, - }, - }) -) +// Осознанный обход слоя components: цвет невыбранного пункта — семантическая +// роль «приглушённый текст». Собственного токена у selectbutton нет, а то же +// значение приходит в tabs.tab.color и menu.item.color. +const styles = StyleSheet.create(({ components, semantic, fonts }) => ({ + container: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + gap: components.selectbutton.extend.gap, + borderWidth: semantic.dimension.borderWidth[100], + borderColor: 'transparent', + }, + small: { height: semantic.dimension.size[800] }, + base: { height: semantic.dimension.size[1100] }, + large: { + height: semantic.dimension.size[1300], + gap: components.selectbutton.extend.gap, + }, + xlarge: { + height: semantic.dimension.size[1400], + gap: components.selectbutton.extend.gap, + }, + disabledContainer: { + borderRadius: components.selectbutton.extend.ext.borderRadius, + borderWidth: semantic.dimension.borderWidth[100], + borderColor: semantic.colorScheme.color.border.neutral.strong, + }, + iconSmall: { + width: components.selectbutton.extend.iconSize.sm, + height: components.selectbutton.extend.iconSize.sm, + }, + iconBase: { + width: components.selectbutton.extend.iconSize.md, + height: components.selectbutton.extend.iconSize.md, + }, + iconLarge: { + width: components.selectbutton.extend.iconSize.lg, + height: components.selectbutton.extend.iconSize.lg, + }, + // Токена iconSize для xlarge в дизайн-системе нет — размер взят semantic-ролью. + iconXLarge: { + width: semantic.dimension.size[800], + height: semantic.dimension.size[800], + }, + label: { + flexShrink: 1, + fontWeight: fonts.fontWeight.demibold, + fontFamily: fonts.fontFamily.heading, + }, + labelSmall: { fontSize: fonts.fontSize[100] }, + labelBase: { fontSize: fonts.fontSize[300] }, + labelLarge: { fontSize: fonts.fontSize[500] }, + labelXLarge: { fontSize: fonts.fontSize[600] }, + textColor: { color: semantic.colorScheme.color.fg.muted }, + checkedTextColor: { color: components.selectbutton.extend.checkedColor }, + disabledTextColor: { + color: semantic.colorScheme.color.border.neutral.strong, + }, +})) diff --git a/src/components/SelectButton/__tests__/SelectButtonItem.test.tsx b/src/components/SelectButton/__tests__/SelectButtonItem.test.tsx index c0a9806a..14a2d4be 100644 --- a/src/components/SelectButton/__tests__/SelectButtonItem.test.tsx +++ b/src/components/SelectButton/__tests__/SelectButtonItem.test.tsx @@ -5,6 +5,8 @@ import { Pressable } from 'react-native' import { useSharedValue } from 'react-native-reanimated' import { lightTheme } from '../../../theme' +import { fontTokens, semanticTokens } from '../../../theme/tokens' +import lightComponentTokens from '../../../theme/tokens/components/light.json' import { type SelectButtonItemProps, SelectButtonItem, @@ -63,30 +65,30 @@ const sizeCases: Array<{ { name: 'маленький', size: 'small', - height: lightTheme.theme.Button.Common.buttonHeightSM, - iconSize: lightTheme.typography.Size['text-base'], - fontSize: lightTheme.typography.Size['text-sm'], + height: semanticTokens.dimension.size[800], + iconSize: fontTokens.fontSize[300], + fontSize: fontTokens.fontSize[100], }, { name: 'базовый', size: 'base', - height: lightTheme.theme.Button.Common.buttonHeight, - iconSize: lightTheme.typography.Size['text-xl'], - fontSize: lightTheme.typography.Size['text-base'], + height: semanticTokens.dimension.size[1100], + iconSize: fontTokens.fontSize[500], + fontSize: fontTokens.fontSize[300], }, { name: 'большой', size: 'large', - height: lightTheme.theme.Button.Common.buttonHeightLG, - iconSize: lightTheme.typography.Size['text-2xl'], - fontSize: lightTheme.typography.Size['text-xl'], + height: semanticTokens.dimension.size[1300], + iconSize: fontTokens.fontSize[600], + fontSize: fontTokens.fontSize[500], }, { name: 'самый большой', size: 'xlarge', - height: lightTheme.theme.Button.Common.buttonHeightXL, + height: semanticTokens.dimension.size[1400], iconSize: 28, - fontSize: lightTheme.typography.Size['text-2xl'], + fontSize: fontTokens.fontSize[600], }, ] @@ -192,12 +194,10 @@ describe('SelectButtonItem', () => { await waitFor(() => { expect(icon).toHaveProp( 'stroke', - lightTheme.theme.Form.SelectButton.selectButtonIconActiveColor + lightComponentTokens.selectbutton.extend.checkedColor ) expect(text).toHaveAnimatedStyle({ - color: toRgba( - lightTheme.theme.Form.SelectButton.selectButtonIconActiveColor - ), + color: toRgba(lightComponentTokens.selectbutton.extend.checkedColor), }) }) @@ -207,12 +207,10 @@ describe('SelectButtonItem', () => { await waitFor(() => { expect(icon).toHaveProp( 'stroke', - lightTheme.theme.Form.SelectButton.selectButtonTextColor + lightTheme.semantic.colorScheme.color.fg.muted ) expect(text).toHaveAnimatedStyle({ - color: toRgba( - lightTheme.theme.Form.SelectButton.selectButtonTextColor - ), + color: toRgba(lightTheme.semantic.colorScheme.color.fg.muted), }) }) }) From 40b4ce810529c8b838dd301fb5e31768647d410d Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:48 +0300 Subject: [PATCH 33/60] =?UTF-8?q?feat(Skeleton):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Skeleton/Skeleton.tsx | 10 ++++++---- .../__tests__/__snapshots__/Skeleton.test.tsx.snap | 12 ++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/Skeleton/Skeleton.tsx b/src/components/Skeleton/Skeleton.tsx index 1aa52ffe..3e0813d7 100644 --- a/src/components/Skeleton/Skeleton.tsx +++ b/src/components/Skeleton/Skeleton.tsx @@ -87,14 +87,16 @@ export const Skeleton = memo(({ style, testID, ...rest }) => { ) }) -const styles = StyleSheet.create(({ border, theme }) => ({ +const styles = StyleSheet.create(({ components: { skeleton } }) => ({ container: { - borderRadius: border.Radius['rounded-lg'], + borderRadius: skeleton.root.borderRadius, overflow: 'hidden', - backgroundColor: theme.Misc.Skeleton.skeletonBg, + backgroundColor: skeleton.colorScheme.root.background, }, gradientContainer: { position: 'absolute', height: '100%' }, - gradientColor: { backgroundColor: theme.Misc.Skeleton.skeletonAnimationBg }, + gradientColor: { + backgroundColor: skeleton.colorScheme.root.animationBackground, + }, })) export const SkeletonTestId = { diff --git a/src/components/Skeleton/__tests__/__snapshots__/Skeleton.test.tsx.snap b/src/components/Skeleton/__tests__/__snapshots__/Skeleton.test.tsx.snap index 2da3ca1f..14b2bb9d 100644 --- a/src/components/Skeleton/__tests__/__snapshots__/Skeleton.test.tsx.snap +++ b/src/components/Skeleton/__tests__/__snapshots__/Skeleton.test.tsx.snap @@ -7,7 +7,7 @@ exports[`Skeleton 50% animation 1`] = ` [ { "backgroundColor": "#e2e2e4", - "borderRadius": 7, + "borderRadius": 14, "overflow": "hidden", }, { @@ -100,7 +100,7 @@ exports[`Skeleton 50% animation 1`] = ` 0, 1726145252, 0.5, - 1728053247, + 1727066353, 1, 1726145252, ] @@ -144,7 +144,7 @@ exports[`Skeleton 100% animation 1`] = ` [ { "backgroundColor": "#e2e2e4", - "borderRadius": 7, + "borderRadius": 14, "overflow": "hidden", }, { @@ -237,7 +237,7 @@ exports[`Skeleton 100% animation 1`] = ` 0, 1726145252, 0.5, - 1728053247, + 1727066353, 1, 1726145252, ] @@ -281,7 +281,7 @@ exports[`Skeleton before animation started: before animation started 1`] = ` [ { "backgroundColor": "#e2e2e4", - "borderRadius": 7, + "borderRadius": 14, "overflow": "hidden", }, { @@ -374,7 +374,7 @@ exports[`Skeleton before animation started: before animation started 1`] = ` 0, 1726145252, 0.5, - 1728053247, + 1727066353, 1, 1726145252, ] From cd7a12d005b41274bf0f40f276675b70d52127d1 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:49 +0300 Subject: [PATCH 34/60] =?UTF-8?q?feat(Slider):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Slider/Slider.tsx | 73 +++--- .../__snapshots__/Slider.test.tsx.snap | 246 +++++++++--------- 2 files changed, 158 insertions(+), 161 deletions(-) diff --git a/src/components/Slider/Slider.tsx b/src/components/Slider/Slider.tsx index 8195b651..60c4a6cb 100644 --- a/src/components/Slider/Slider.tsx +++ b/src/components/Slider/Slider.tsx @@ -252,41 +252,38 @@ export const Slider = memo( } ) -const styles = StyleSheet.create(({ theme, border }) => { - return { - container: { - width: '100%', - justifyContent: 'center', - alignItems: 'center', - }, - track: { - height: theme.Form.Slider.sliderHorizontalHeight, - backgroundColor: theme.Form.Slider.sliderBg, - borderRadius: theme.Form.Slider.sliderHandleBorderRadius, - position: 'relative', - width: '100%', - justifyContent: 'center', - }, - - line: { - height: theme.Form.Slider.sliderHorizontalHeight, - borderRadius: theme.Form.Slider.sliderHandleBorderRadius, - position: 'absolute', - backgroundColor: theme.Form.Slider.sliderRangeBg, - }, - - point: { - width: theme.Form.Slider.sliderHandleWidth, - height: theme.Form.Slider.sliderHandleHeight, - borderRadius: theme.Form.Slider.sliderHandleHeight / 2, - position: 'absolute', - backgroundColor: theme.Form.Slider.sliderHandleBg, - borderWidth: border.Width['border-3'], - borderColor: theme.Form.Slider.sliderHandleBorder, - }, - - disabled: { opacity: 0.6, mixBlendMode: 'luminosity' }, - - hovered: { backgroundColor: theme.Form.Slider.sliderHandleHoverBg }, - } -}) +const styles = StyleSheet.create(({ components, semantic }) => ({ + container: { width: '100%', justifyContent: 'center', alignItems: 'center' }, + track: { + height: components.slider.track.size, + backgroundColor: components.slider.track.background, + borderRadius: components.slider.track.borderRadius, + position: 'relative', + width: '100%', + justifyContent: 'center', + }, + + line: { + height: components.slider.track.size, + borderRadius: components.slider.track.borderRadius, + position: 'absolute', + backgroundColor: components.slider.range.background, + }, + + point: { + width: components.slider.handle.width, + height: components.slider.handle.height, + borderRadius: components.slider.handle.borderRadius, + position: 'absolute', + backgroundColor: components.slider.colorScheme.handle.content.background, + borderWidth: semantic.dimension.borderWidth[300], + borderColor: components.slider.handle.background, + }, + + disabled: { + opacity: semantic.effects.opacity[60], + mixBlendMode: 'luminosity', + }, + + hovered: { backgroundColor: components.slider.handle.hoverBackground }, +})) diff --git a/src/components/Slider/__tests__/__snapshots__/Slider.test.tsx.snap b/src/components/Slider/__tests__/__snapshots__/Slider.test.tsx.snap index 0a400845..9079a675 100644 --- a/src/components/Slider/__tests__/__snapshots__/Slider.test.tsx.snap +++ b/src/components/Slider/__tests__/__snapshots__/Slider.test.tsx.snap @@ -19,7 +19,7 @@ exports[`Slider snapshots default 1`] = ` { "backgroundColor": "#e2e2e4", "borderRadius": 14, - "height": 3.5, + "height": 4, "justifyContent": "center", "position": "relative", "width": "100%", @@ -37,7 +37,7 @@ exports[`Slider snapshots default 1`] = ` { "value": { "left": 0, - "width": 8.75, + "width": 10, }, } } @@ -47,7 +47,7 @@ exports[`Slider snapshots default 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, @@ -59,13 +59,13 @@ exports[`Slider snapshots default 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, { "left": 0, - "width": 8.75, + "width": 10, }, ] } @@ -94,11 +94,11 @@ exports[`Slider snapshots default 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -110,11 +110,11 @@ exports[`Slider snapshots default 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -150,7 +150,7 @@ exports[`Slider snapshots disabled = false, range = false 1`] = ` { "backgroundColor": "#e2e2e4", "borderRadius": 14, - "height": 3.5, + "height": 4, "justifyContent": "center", "position": "relative", "width": "100%", @@ -168,7 +168,7 @@ exports[`Slider snapshots disabled = false, range = false 1`] = ` { "value": { "left": 0, - "width": 8.75, + "width": 10, }, } } @@ -178,7 +178,7 @@ exports[`Slider snapshots disabled = false, range = false 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, @@ -190,13 +190,13 @@ exports[`Slider snapshots disabled = false, range = false 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, { "left": 0, - "width": 8.75, + "width": 10, }, ] } @@ -225,11 +225,11 @@ exports[`Slider snapshots disabled = false, range = false 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -241,11 +241,11 @@ exports[`Slider snapshots disabled = false, range = false 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -281,7 +281,7 @@ exports[`Slider snapshots disabled = false, range = true 1`] = ` { "backgroundColor": "#e2e2e4", "borderRadius": 14, - "height": 3.5, + "height": 4, "justifyContent": "center", "position": "relative", "width": "100%", @@ -298,7 +298,7 @@ exports[`Slider snapshots disabled = false, range = true 1`] = ` jestAnimatedStyle={ { "value": { - "left": 8.75, + "left": 10, "width": 0, }, } @@ -309,7 +309,7 @@ exports[`Slider snapshots disabled = false, range = true 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, @@ -321,12 +321,12 @@ exports[`Slider snapshots disabled = false, range = true 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, { - "left": 8.75, + "left": 10, "width": 0, }, ] @@ -356,11 +356,11 @@ exports[`Slider snapshots disabled = false, range = true 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -372,11 +372,11 @@ exports[`Slider snapshots disabled = false, range = true 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -413,11 +413,11 @@ exports[`Slider snapshots disabled = false, range = true 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -429,11 +429,11 @@ exports[`Slider snapshots disabled = false, range = true 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -469,7 +469,7 @@ exports[`Slider snapshots disabled = false, range = true, maxPointerValueInit = { "backgroundColor": "#e2e2e4", "borderRadius": 14, - "height": 3.5, + "height": 4, "justifyContent": "center", "position": "relative", "width": "100%", @@ -486,7 +486,7 @@ exports[`Slider snapshots disabled = false, range = true, maxPointerValueInit = jestAnimatedStyle={ { "value": { - "left": 8.75, + "left": 10, "width": 0, }, } @@ -497,7 +497,7 @@ exports[`Slider snapshots disabled = false, range = true, maxPointerValueInit = { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, @@ -509,12 +509,12 @@ exports[`Slider snapshots disabled = false, range = true, maxPointerValueInit = { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, { - "left": 8.75, + "left": 10, "width": 0, }, ] @@ -544,11 +544,11 @@ exports[`Slider snapshots disabled = false, range = true, maxPointerValueInit = { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -560,11 +560,11 @@ exports[`Slider snapshots disabled = false, range = true, maxPointerValueInit = { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -601,11 +601,11 @@ exports[`Slider snapshots disabled = false, range = true, maxPointerValueInit = { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -617,11 +617,11 @@ exports[`Slider snapshots disabled = false, range = true, maxPointerValueInit = { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -660,7 +660,7 @@ exports[`Slider snapshots disabled = true, range = false 1`] = ` { "backgroundColor": "#e2e2e4", "borderRadius": 14, - "height": 3.5, + "height": 4, "justifyContent": "center", "position": "relative", "width": "100%", @@ -678,7 +678,7 @@ exports[`Slider snapshots disabled = true, range = false 1`] = ` { "value": { "left": 0, - "width": 8.75, + "width": 10, }, } } @@ -688,7 +688,7 @@ exports[`Slider snapshots disabled = true, range = false 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, @@ -700,13 +700,13 @@ exports[`Slider snapshots disabled = true, range = false 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, { "left": 0, - "width": 8.75, + "width": 10, }, ] } @@ -735,11 +735,11 @@ exports[`Slider snapshots disabled = true, range = false 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -751,11 +751,11 @@ exports[`Slider snapshots disabled = true, range = false 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -794,7 +794,7 @@ exports[`Slider snapshots disabled = true, range = true 1`] = ` { "backgroundColor": "#e2e2e4", "borderRadius": 14, - "height": 3.5, + "height": 4, "justifyContent": "center", "position": "relative", "width": "100%", @@ -811,7 +811,7 @@ exports[`Slider snapshots disabled = true, range = true 1`] = ` jestAnimatedStyle={ { "value": { - "left": 8.75, + "left": 10, "width": 0, }, } @@ -822,7 +822,7 @@ exports[`Slider snapshots disabled = true, range = true 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, @@ -834,12 +834,12 @@ exports[`Slider snapshots disabled = true, range = true 1`] = ` { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, { - "left": 8.75, + "left": 10, "width": 0, }, ] @@ -869,11 +869,11 @@ exports[`Slider snapshots disabled = true, range = true 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -885,11 +885,11 @@ exports[`Slider snapshots disabled = true, range = true 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -926,11 +926,11 @@ exports[`Slider snapshots disabled = true, range = true 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -942,11 +942,11 @@ exports[`Slider snapshots disabled = true, range = true 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -985,7 +985,7 @@ exports[`Slider snapshots disabled = true, range = true, maxPointerValueInit = 8 { "backgroundColor": "#e2e2e4", "borderRadius": 14, - "height": 3.5, + "height": 4, "justifyContent": "center", "position": "relative", "width": "100%", @@ -1002,7 +1002,7 @@ exports[`Slider snapshots disabled = true, range = true, maxPointerValueInit = 8 jestAnimatedStyle={ { "value": { - "left": 8.75, + "left": 10, "width": 0, }, } @@ -1013,7 +1013,7 @@ exports[`Slider snapshots disabled = true, range = true, maxPointerValueInit = 8 { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, @@ -1025,12 +1025,12 @@ exports[`Slider snapshots disabled = true, range = true, maxPointerValueInit = 8 { "backgroundColor": "#2b2e33", "borderRadius": 14, - "height": 3.5, + "height": 4, "position": "absolute", }, false, { - "left": 8.75, + "left": 10, "width": 0, }, ] @@ -1060,11 +1060,11 @@ exports[`Slider snapshots disabled = true, range = true, maxPointerValueInit = 8 { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -1076,11 +1076,11 @@ exports[`Slider snapshots disabled = true, range = true, maxPointerValueInit = 8 { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { @@ -1117,11 +1117,11 @@ exports[`Slider snapshots disabled = true, range = true, maxPointerValueInit = 8 { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, ], @@ -1133,11 +1133,11 @@ exports[`Slider snapshots disabled = true, range = true, maxPointerValueInit = 8 { "backgroundColor": "#ffffff", "borderColor": "#2b2e33", - "borderRadius": 8.75, - "borderWidth": 3, - "height": 17.5, + "borderRadius": 1600, + "borderWidth": 4, + "height": 20, "position": "absolute", - "width": 17.5, + "width": 20, }, false, { From fd292d01f46ebed87dd7a6906c3e0d012be8cbce Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:49 +0300 Subject: [PATCH 35/60] =?UTF-8?q?feat(Tabs):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Tabs/TabItem/TabItem.tsx | 59 +-- src/components/Tabs/Tabs.tsx | 12 +- .../__snapshots__/Tabs.test.tsx.snap | 466 +++++++++--------- 3 files changed, 270 insertions(+), 267 deletions(-) diff --git a/src/components/Tabs/TabItem/TabItem.tsx b/src/components/Tabs/TabItem/TabItem.tsx index 71168592..7f65a7c9 100644 --- a/src/components/Tabs/TabItem/TabItem.tsx +++ b/src/components/Tabs/TabItem/TabItem.tsx @@ -56,15 +56,17 @@ export const TabItem = memo( ({ - color: disabled - ? theme.Button.Disabled.disabledButtonTextColor - : pressed - ? theme.Panel.TabView.tabviewHeaderHoverTextColor - : active - ? theme.Panel.TabView.tabviewHeaderActiveTextColor - : theme.Panel.TabView.tabviewHeaderTextColor, - })} + uniProps={({ components, semantic }) => { + return { + color: disabled + ? semantic.colorScheme.color.fg.muted + : pressed + ? components.tabs.tab.hoverColor + : active + ? components.tabs.tab.activeColor + : components.tabs.tab.color, + } + }} /> ) : null} ( } ) -const styles = StyleSheet.create(({ theme, typography, fonts }) => ({ +const styles = StyleSheet.create(({ components, semantic, fonts }) => ({ container: { alignItems: 'center', flexDirection: 'row', - height: - theme.Misc.Badge.badgeHeight + - theme.Panel.TabView.tabviewHeaderPaddingTopBottom * 2, - gap: theme.General.inlineSpacing, - paddingHorizontal: theme.Panel.TabView.tabviewHeaderPaddingLeftRight, - paddingVertical: theme.Panel.TabView.tabviewHeaderPaddingTopBottom, + height: semantic.dimension.size[700] + components.tabs.tab.padding * 2, + gap: components.tabs.tab.gap, + paddingHorizontal: components.tabs.tab.padding, + paddingVertical: components.tabs.tab.padding, - backgroundColor: theme.Panel.TabView.tabviewHeaderBg, + backgroundColor: components.tabs.colorScheme.tab.background, }, pressedContainer: { - backgroundColor: theme.Panel.TabView.tabviewHeaderHoverBg, + backgroundColor: components.tabs.colorScheme.tab.hoverBackground, }, activeContainer: { - backgroundColor: theme.Panel.TabView.tabviewHeaderActiveBg, + backgroundColor: components.tabs.colorScheme.tab.activeBackground, + }, + disabledContainer: { + opacity: semantic.effects.opacity[60], + mixBlendMode: 'luminosity', }, - disabledContainer: { opacity: 0.6, mixBlendMode: 'luminosity' }, icon: { - width: theme.Menu.Item.menuitemSubmenuIconFontSize, - height: theme.Menu.Item.menuitemSubmenuIconFontSize, + width: semantic.dimension.size[600], + height: semantic.dimension.size[600], }, text: { - fontFamily: fonts.primary, - fontSize: typography.Size['text-base'], + fontFamily: fonts.fontFamily.heading, + fontSize: fonts.fontSize[300], verticalAlign: 'middle', includeFontPadding: false, - color: theme.Panel.TabView.tabviewHeaderTextColor, + color: components.tabs.tab.color, }, - pressedText: { color: theme.Panel.TabView.tabviewHeaderHoverTextColor }, - activeText: { color: theme.Panel.TabView.tabviewHeaderActiveTextColor }, - disabledText: { color: theme.Button.Disabled.disabledButtonTextColor }, + pressedText: { color: components.tabs.tab.hoverColor }, + activeText: { color: components.tabs.tab.activeColor }, + disabledText: { color: semantic.colorScheme.color.fg.muted }, })) export enum TestId { diff --git a/src/components/Tabs/Tabs.tsx b/src/components/Tabs/Tabs.tsx index 497546b6..3c94a134 100644 --- a/src/components/Tabs/Tabs.tsx +++ b/src/components/Tabs/Tabs.tsx @@ -91,19 +91,19 @@ export const Tabs = memo( } ) -const styles = StyleSheet.create(({ theme, border }) => ({ +const styles = StyleSheet.create(({ components, semantic }) => ({ container: { flexDirection: 'row', - gap: theme.Panel.TabView.tabviewHeaderSpacing, + gap: components.tabs.tab.margin, - borderBottomWidth: border.Width.border, - borderColor: theme.Panel.TabView.tabviewNavBorderColor, + borderBottomWidth: semantic.dimension.borderWidth[100], + borderColor: components.tabs.tablist.borderColor, }, line: { position: 'absolute', bottom: 0, - height: border.Width['border-2'], + height: semantic.dimension.borderWidth[200], - backgroundColor: theme.Panel.TabView.tabviewHeaderActiveBorderColor, + backgroundColor: components.tabs.activeBar.background, }, })) diff --git a/src/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap b/src/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap index 70574bf1..e4a3b881 100644 --- a/src/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap +++ b/src/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap @@ -39,16 +39,16 @@ exports[`TabItem component tests active: label 1`] = ` [ { "alignItems": "center", - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", "flexDirection": "row", - "gap": 7, - "height": 49, - "paddingHorizontal": 0, + "gap": 8, + "height": 52, + "paddingHorizontal": 14, "paddingVertical": 14, }, false, { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", }, undefined, ] @@ -61,12 +61,12 @@ exports[`TabItem component tests active: label 1`] = ` { "color": "#85888e", "fontFamily": "TT Fellows", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, "verticalAlign": "middle", }, { - "color": "#000000", + "color": "#2b2e33", }, false, undefined, @@ -118,16 +118,16 @@ exports[`TabItem component tests active: label, badge 1`] = ` [ { "alignItems": "center", - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", "flexDirection": "row", - "gap": 7, - "height": 49, - "paddingHorizontal": 0, + "gap": 8, + "height": 52, + "paddingHorizontal": 14, "paddingVertical": 14, }, false, { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", }, undefined, ] @@ -140,12 +140,12 @@ exports[`TabItem component tests active: label, badge 1`] = ` { "color": "#85888e", "fontFamily": "TT Fellows", - "fontSize": 14, + "fontSize": 16, "includeFontPadding": false, "verticalAlign": "middle", }, { - "color": "#000000", + "color": "#2b2e33", }, false, undefined, @@ -171,10 +171,10 @@ exports[`TabItem component tests active: label, badge 1`] = ` "backgroundColor": "#44e858", }, { - "borderRadius": 100, - "height": 21, + "borderRadius": 1600, + "height": 24, "justifyContent": "center", - "paddingHorizontal": 7, + "paddingHorizontal": 8, }, ] } @@ -184,9 +184,9 @@ exports[`TabItem component tests active: label, badge 1`] = ` style={ [ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", }, @@ -219,9 +219,9 @@ exports[`TabItem component tests active: label, badge 1`] = ` onLayout={[Function]} style={ { - "color": "#000000", + "color": "#2b2e33", "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", } @@ -275,16 +275,16 @@ exports[`TabItem component tests active: label, icon 1`] = ` [ { "alignItems": "center", - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", "flexDirection": "row", - "gap": 7, - "height": 49, - "paddingHorizontal": 0, + "gap": 8, + "height": 52, + "paddingHorizontal": 14, "paddingVertical": 14, }, false, { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", }, undefined, ] @@ -292,15 +292,15 @@ exports[`TabItem component tests active: label, icon 1`] = ` > @@ -2160,16 +2160,16 @@ exports[`Tabs component tests disabled 1`] = ` [ { "alignItems": "center", - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", "flexDirection": "row", - "gap": 7, - "height": 49, - "paddingHorizontal": 0, + "gap": 8, + "height": 52, + "paddingHorizontal": 14, "paddingVertical": 14, }, false, { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", }, { "mixBlendMode": "luminosity", @@ -2180,11 +2180,11 @@ exports[`Tabs component tests disabled 1`] = ` > @@ -2632,16 +2632,16 @@ exports[`Tabs component tests normal 1`] = ` [ { "alignItems": "center", - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", "flexDirection": "row", - "gap": 7, - "height": 49, - "paddingHorizontal": 0, + "gap": 8, + "height": 52, + "paddingHorizontal": 14, "paddingVertical": 14, }, false, { - "backgroundColor": "rgba(255, 255, 255, 0.0001)", + "backgroundColor": "transparent", }, false, ] @@ -2649,15 +2649,15 @@ exports[`Tabs component tests normal 1`] = ` > Date: Tue, 4 Aug 2026 17:05:50 +0300 Subject: [PATCH 36/60] =?UTF-8?q?feat(Tag):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Tag/Tag.tsx | 117 ++++++++-------- .../__tests__/__snapshots__/Tag.test.tsx.snap | 128 +++++++++--------- 2 files changed, 120 insertions(+), 125 deletions(-) diff --git a/src/components/Tag/Tag.tsx b/src/components/Tag/Tag.tsx index 8570055d..897a4493 100644 --- a/src/components/Tag/Tag.tsx +++ b/src/components/Tag/Tag.tsx @@ -10,7 +10,7 @@ import { import { StyleSheet } from 'react-native-unistyles' -import type { ThemeType } from '../../theme/types' +import type { ComponentTokens } from '../../theme/tokens/index' import { type SvgSource, SvgUniversal } from '../../utils/SvgUniversal' export interface TagProps @@ -42,13 +42,13 @@ export interface TagProps type TagSeverity = NonNullable -const tagIconColor: Record string> = { - basic: (t) => t.Misc.Badge.badgeTextColor, - info: (t) => t.Misc.Badge.badgeInfoTextColor, - success: (t) => t.Misc.Badge.badgeSuccessTextColor, - warning: (t) => t.Misc.Badge.badgeWarningTextColor, - danger: (t) => t.Misc.Badge.badgeDangerTextColor, - secondary: (t) => t.Misc.Badge.badgeTextColor, +const tagIconColor: Record string> = { + basic: (t) => t.tag.colorScheme.primary.color, + info: (t) => t.tag.colorScheme.info.color, + success: (t) => t.tag.colorScheme.success.color, + warning: (t) => t.tag.colorScheme.warn.color, + danger: (t) => t.tag.colorScheme.danger.color, + secondary: (t) => t.tag.colorScheme.secondary.color, } /** @@ -86,9 +86,9 @@ export const Tag = memo( {...tagStyles.icon} source={Icon} testID={TagTestId.icon} - uniProps={({ theme }) => ({ - color: tagIconColor[severity](theme), - })} + uniProps={({ components }) => { + return { color: tagIconColor[severity](components) } + }} /> ) : null} ( } ) -const tagStyles = StyleSheet.create( - ({ theme, border, spacing, typography, fonts }) => ({ - container: { - alignSelf: 'flex-start', - flexDirection: 'row', - alignItems: 'center', - gap: spacing.Gap['gap-1'], - paddingHorizontal: theme.Misc.Tag.tagPadding, - height: theme.Misc.Tag.tagHeight, - borderRadius: border.Radius['rounded-lg'], - variants: { - severity: { - basic: { backgroundColor: theme.Misc.Badge.badgeBg }, - info: { - backgroundColor: theme.Button.Severity.Info.Basic.infoButtonBg, - }, - success: { - backgroundColor: - theme.Button.Severity.Success.Basic.successButtonBg, - }, - warning: { - backgroundColor: - theme.Button.Severity.Warning.Basic.warningButtonBg, - }, - danger: { - backgroundColor: theme.Button.Severity.Danger.Basic.dangerButtonBg, - }, - secondary: { backgroundColor: theme.Surface['surface-border'] }, +const tagStyles = StyleSheet.create(({ components, fonts }) => ({ + container: { + alignSelf: 'flex-start', + flexDirection: 'row', + alignItems: 'center', + gap: components.tag.root.gap, + paddingHorizontal: components.tag.root.paddingLeft, + paddingVertical: components.tag.root.paddingTop, + borderRadius: components.tag.root.borderRadius, + variants: { + severity: { + basic: { + backgroundColor: components.tag.colorScheme.primary.background, + }, + info: { backgroundColor: components.tag.colorScheme.info.background }, + success: { + backgroundColor: components.tag.colorScheme.success.background, + }, + warning: { + backgroundColor: components.tag.colorScheme.warn.background, + }, + danger: { + backgroundColor: components.tag.colorScheme.danger.background, + }, + secondary: { + backgroundColor: components.tag.colorScheme.secondary.background, }, }, }, - roundedContainer: { borderRadius: border.Radius['rounded-full'] }, - icon: { - width: theme.Misc.Tag.tagFontSize, - height: theme.Misc.Tag.tagFontSize, - }, - text: { - flexShrink: 1, - fontSize: typography.Size['text-xs'], - includeFontPadding: false, - verticalAlign: 'middle', - fontFamily: fonts.primary, - variants: { - severity: { - basic: { color: theme.Misc.Badge.badgeTextColor }, - info: { color: theme.Misc.Badge.badgeInfoTextColor }, - success: { color: theme.Misc.Badge.badgeSuccessTextColor }, - warning: { color: theme.Misc.Badge.badgeWarningTextColor }, - danger: { color: theme.Misc.Badge.badgeDangerTextColor }, - secondary: { color: theme.Misc.Badge.badgeTextColor }, - }, + }, + roundedContainer: { borderRadius: components.tag.root.roundedBorderRadius }, + icon: { width: components.tag.icon.size, height: components.tag.icon.size }, + text: { + flexShrink: 1, + fontSize: components.tag.root.fontSize, + includeFontPadding: false, + verticalAlign: 'middle', + fontFamily: fonts.fontFamily.heading, + variants: { + severity: { + basic: { color: components.tag.colorScheme.primary.color }, + info: { color: components.tag.colorScheme.info.color }, + success: { color: components.tag.colorScheme.success.color }, + warning: { color: components.tag.colorScheme.warn.color }, + danger: { color: components.tag.colorScheme.danger.color }, + secondary: { color: components.tag.colorScheme.secondary.color }, }, }, - }) -) + }, +})) export const TagTestId = { root: 'Tag', diff --git a/src/components/Tag/__tests__/__snapshots__/Tag.test.tsx.snap b/src/components/Tag/__tests__/__snapshots__/Tag.test.tsx.snap index d41f7d70..ff2517c9 100644 --- a/src/components/Tag/__tests__/__snapshots__/Tag.test.tsx.snap +++ b/src/components/Tag/__tests__/__snapshots__/Tag.test.tsx.snap @@ -11,11 +11,11 @@ exports[`Tag snapshot: default 1`] = ` "alignItems": "center", "alignSelf": "flex-start", "backgroundColor": "#44e858", - "borderRadius": 7, + "borderRadius": 8, "flexDirection": "row", - "gap": 3.5, - "height": 21, - "paddingHorizontal": 7, + "gap": 4, + "paddingHorizontal": 8, + "paddingVertical": 4, }, undefined, ] @@ -26,10 +26,10 @@ exports[`Tag snapshot: default 1`] = ` numberOfLines={1} style={ { - "color": "#000000", + "color": "#2b2e33", "flexShrink": 1, "fontFamily": "TT Fellows", - "fontSize": 10.5, + "fontSize": 12, "includeFontPadding": false, "verticalAlign": "middle", } @@ -53,14 +53,14 @@ exports[`Tag snapshot: severity = basic, rounded = true, with Icon 1`] = ` "alignItems": "center", "alignSelf": "flex-start", "backgroundColor": "#44e858", - "borderRadius": 7, + "borderRadius": 8, "flexDirection": "row", - "gap": 3.5, - "height": 21, - "paddingHorizontal": 7, + "gap": 4, + "paddingHorizontal": 8, + "paddingVertical": 4, }, { - "borderRadius": 100, + "borderRadius": 1600, }, ] } @@ -68,15 +68,15 @@ exports[`Tag snapshot: severity = basic, rounded = true, with Icon 1`] = ` > Date: Tue, 4 Aug 2026 17:05:50 +0300 Subject: [PATCH 37/60] =?UTF-8?q?feat(Timer):=20=D0=BF=D0=BE=D0=B4=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Timer/Timer.tsx | 4 ++-- src/components/Timer/TimerFlip.tsx | 10 +++++----- .../__tests__/__snapshots__/Timer.test.tsx.snap | 16 ++++++++-------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/components/Timer/Timer.tsx b/src/components/Timer/Timer.tsx index 02699374..be194889 100644 --- a/src/components/Timer/Timer.tsx +++ b/src/components/Timer/Timer.tsx @@ -96,7 +96,7 @@ export const Timer = memo(({ countFrom, onFinish }) => { ) }) -const styles = StyleSheet.create(({ typography }) => ({ +const styles = StyleSheet.create(({ semantic }) => ({ container: { overflow: 'hidden', width: COUNTER_SIZE, @@ -111,7 +111,7 @@ const styles = StyleSheet.create(({ typography }) => ({ width: COUNTER_SIZE, height: COUNTER_SIZE, }, - circle: { color: typography.Color.Surface['text-surface-0'] }, + circle: { color: semantic.colorScheme.color.fg.active }, })) export enum TestId { diff --git a/src/components/Timer/TimerFlip.tsx b/src/components/Timer/TimerFlip.tsx index 88c72ad9..de57079b 100644 --- a/src/components/Timer/TimerFlip.tsx +++ b/src/components/Timer/TimerFlip.tsx @@ -64,7 +64,7 @@ export const TimerFlip = memo(({ value, duration = 300 }) => { ) }) -const styles = StyleSheet.create(({ typography, fonts }) => ({ +const styles = StyleSheet.create(({ semantic, fonts }) => ({ container: { overflow: 'hidden', width: COUNTER_SIZE, @@ -81,11 +81,11 @@ const styles = StyleSheet.create(({ typography, fonts }) => ({ position: 'absolute', }, text: { - fontSize: typography.Size['text-base'], - fontWeight: 700, + fontSize: fonts.fontSize[300], + fontWeight: fonts.fontWeight.bold, includeFontPadding: false, verticalAlign: 'middle', - color: typography.Color.Surface['text-surface-0'], - fontFamily: fonts.secondary, + color: semantic.colorScheme.color.fg.active, + fontFamily: fonts.fontFamily.base, }, })) diff --git a/src/components/Timer/__tests__/__snapshots__/Timer.test.tsx.snap b/src/components/Timer/__tests__/__snapshots__/Timer.test.tsx.snap index f5235f08..b7bbf37d 100644 --- a/src/components/Timer/__tests__/__snapshots__/Timer.test.tsx.snap +++ b/src/components/Timer/__tests__/__snapshots__/Timer.test.tsx.snap @@ -158,7 +158,7 @@ exports[`Timer should reset timer on changing countFrom prop: after 1 s 1`] = ` { "color": "#181a1f", "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", @@ -223,7 +223,7 @@ exports[`Timer should reset timer on changing countFrom prop: after 1 s 1`] = ` { "color": "#181a1f", "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", @@ -395,7 +395,7 @@ exports[`Timer should reset timer on changing countFrom prop: after reset 1`] = { "color": "#181a1f", "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", @@ -460,7 +460,7 @@ exports[`Timer should reset timer on changing countFrom prop: after reset 1`] = { "color": "#181a1f", "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", @@ -632,7 +632,7 @@ exports[`Timer snapshot: before start 1`] = ` { "color": "#181a1f", "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", @@ -697,7 +697,7 @@ exports[`Timer snapshot: before start 1`] = ` { "color": "#181a1f", "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", @@ -869,7 +869,7 @@ exports[`Timer snapshot: on finish 1`] = ` { "color": "#181a1f", "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", @@ -934,7 +934,7 @@ exports[`Timer snapshot: on finish 1`] = ` { "color": "#181a1f", "fontFamily": "Noto Sans", - "fontSize": 14, + "fontSize": 16, "fontWeight": 700, "includeFontPadding": false, "verticalAlign": "middle", From 215f68313132e8eb63d4d0a1f4d748fcd146bb3c Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Tue, 4 Aug 2026 17:05:51 +0300 Subject: [PATCH 38/60] =?UTF-8?q?feat(ToggleButton):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ToggleButton/ToggleButton.tsx | 314 +++++++++--------- .../__snapshots__/ToggleButton.test.tsx.snap | 176 +++++----- 2 files changed, 247 insertions(+), 243 deletions(-) diff --git a/src/components/ToggleButton/ToggleButton.tsx b/src/components/ToggleButton/ToggleButton.tsx index 5e5589d9..d3ca76c5 100644 --- a/src/components/ToggleButton/ToggleButton.tsx +++ b/src/components/ToggleButton/ToggleButton.tsx @@ -131,182 +131,186 @@ export const ToggleButton = memo( } ) -const toggleStyles = StyleSheet.create( - ({ theme, spacing, border, fonts, typography }) => ({ - container: { - alignSelf: 'flex-start', - borderRadius: border.Radius['rounded-full'], - borderWidth: border.Width.border, - overflow: 'hidden', - variants: { - checked: { - true: { - borderColor: theme.Form.ToggleButton.toggleButtonActiveBorderColor, - }, - false: { - borderColor: theme.Form.ToggleButton.toggleButtonBorderColor, - }, +const toggleStyles = StyleSheet.create(({ components, semantic, fonts }) => ({ + container: { + alignSelf: 'flex-start', + borderRadius: components.togglebutton.root.borderRadius, + borderWidth: semantic.dimension.borderWidth[100], + overflow: 'hidden', + variants: { + checked: { + true: { + borderColor: + components.togglebutton.colorScheme.root.checkedBorderColor, }, - pressed: { - true: { borderColor: theme.Form.ToggleButton.toggleButtonHoverBg }, - false: {}, - }, - disabled: { - true: { - borderColor: theme.Button.Disabled.disabledButtonBorderColor, - opacity: 0.6, - }, - false: {}, + false: { + borderColor: components.togglebutton.colorScheme.root.borderColor, }, }, - compoundVariants: [ - { - checked: 'true', - pressed: 'true', - styles: { - borderColor: - theme.Form.ToggleButton.toggleButtonActiveHoverBorderColor, - }, + pressed: { + true: { borderColor: components.togglebutton.extend.hoverBorderColor }, + false: {}, + }, + disabled: { + true: { + borderColor: + components.togglebutton.colorScheme.root.disabledBorderColor, + opacity: semantic.effects.opacity[60], }, - ], + false: {}, + }, }, - contentContainer: { - flexDirection: 'row', - alignItems: 'center', - alignSelf: 'flex-start', - borderRadius: border.Radius['rounded-full'], - paddingVertical: theme.Button.Common.buttonPaddingTopBottom, - paddingHorizontal: spacing.Padding['p-6'], - gap: spacing.Gap['gap-3'], - variants: { - size: { - xlarge: { minHeight: theme.Button.Common.buttonHeightXL }, - large: { minHeight: theme.Button.Common.buttonHeightLG }, - base: { - minHeight: theme.Button.Common.buttonHeight, - paddingHorizontal: theme.Button.Common.buttonPaddingLeftRight, - gap: theme.General.inlineSpacing, - }, - small: { - minHeight: theme.Button.Common.buttonHeightSM, - paddingHorizontal: spacing.Padding['p-3'], - gap: theme.General.inlineSpacing, - }, - }, - checked: { - true: { - backgroundColor: theme.Form.ToggleButton.toggleButtonActiveBg, - }, - false: { backgroundColor: theme.Form.ToggleButton.toggleButtonBg }, - }, - pressed: { - true: { - backgroundColor: theme.Form.ToggleButton.toggleButtonHoverBg, - }, - false: {}, - }, - disabled: { - true: { backgroundColor: theme.Button.Disabled.disabledButtonBg }, - false: {}, + compoundVariants: [ + { + checked: 'true', + pressed: 'true', + styles: { + borderColor: components.togglebutton.extend.checkedHoverBorderColor, }, }, - compoundVariants: [ - { - checked: 'true', - pressed: 'true', - styles: { - backgroundColor: theme.Form.ToggleButton.toggleButtonActiveHoverBg, - }, + ], + }, + contentContainer: { + flexDirection: 'row', + alignItems: 'center', + alignSelf: 'flex-start', + borderRadius: components.togglebutton.root.borderRadius, + paddingVertical: components.togglebutton.root.paddingTop, + paddingHorizontal: semantic.dimension.space[600], + gap: components.togglebutton.extend.ext.gap, + variants: { + size: { + xlarge: { minHeight: semantic.dimension.size[1400] }, + large: { minHeight: semantic.dimension.size[1300] }, + base: { + minHeight: semantic.dimension.size[1100], + paddingHorizontal: components.togglebutton.root.paddingLeft, + gap: components.togglebutton.root.gap, }, - ], - }, - iconOnly: { - aspectRatio: 1, - paddingHorizontal: 0, - paddingVertical: 0, - justifyContent: 'center', - }, - icon: { - variants: { - size: { - xlarge: { - width: typography.Size['text-4xl'], - height: typography.Size['text-4xl'], - }, - large: { - width: typography.Size['text-2xl'], - height: typography.Size['text-2xl'], - }, - base: { - width: typography.Size['text-xl'], - height: typography.Size['text-xl'], - }, - small: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], - }, + small: { + minHeight: semantic.dimension.size[800], + paddingHorizontal: components.togglebutton.root.sm.paddingRight, + gap: components.togglebutton.root.gap, }, - checked: { - true: { color: theme.Form.ToggleButton.toggleButtonActiveTextColor }, - false: { color: theme.Form.ToggleButton.toggleButtonTextColor }, + }, + checked: { + true: { + backgroundColor: + components.togglebutton.colorScheme.root.checkedBackground, }, - pressed: { - true: { color: theme.Form.ToggleButton.toggleButtonHoverTextColor }, - false: {}, + false: { + backgroundColor: components.togglebutton.colorScheme.root.background, }, - disabled: { - true: { color: theme.Button.Disabled.disabledButtonTextColor }, - false: {}, + }, + pressed: { + true: { + backgroundColor: + components.togglebutton.colorScheme.root.hoverBackground, }, + false: {}, }, - compoundVariants: [ - { - checked: 'true', - pressed: 'true', - styles: { - color: theme.Form.ToggleButton.toggleButtonTextActiveHoverColor, - }, + disabled: { + true: { + backgroundColor: + components.togglebutton.colorScheme.root.disabledBackground, }, - ], + false: {}, + }, }, - label: { - flexShrink: 1, - fontFamily: fonts.primary, - fontWeight: '600', - includeFontPadding: false, - verticalAlign: 'middle', - variants: { - size: { - xlarge: { fontSize: typography.Size['text-2xl'] }, - large: { fontSize: typography.Size['text-xl'] }, - base: { fontSize: typography.Size['text-base'] }, - small: { fontSize: typography.Size['text-sm'] }, + compoundVariants: [ + { + checked: 'true', + pressed: 'true', + styles: { + backgroundColor: + components.togglebutton.extend.checkedHoverBackground, }, - checked: { - true: { color: theme.Form.ToggleButton.toggleButtonActiveTextColor }, - false: { color: theme.Form.ToggleButton.toggleButtonTextColor }, + }, + ], + }, + iconOnly: { + aspectRatio: 1, + paddingHorizontal: semantic.dimension.space.none, + paddingVertical: semantic.dimension.space.none, + justifyContent: 'center', + }, + icon: { + variants: { + size: { + xlarge: { + // Токена iconSize.xlg в дизайн-системе нет — размер взят semantic-ролью. + width: semantic.dimension.size[1000], + height: semantic.dimension.size[1000], }, - pressed: { - true: { color: theme.Form.ToggleButton.toggleButtonHoverTextColor }, - false: {}, + large: { + width: components.togglebutton.extend.iconSize.lg, + height: components.togglebutton.extend.iconSize.lg, }, - disabled: { - true: { color: theme.Button.Disabled.disabledButtonTextColor }, - false: {}, + base: { + width: components.togglebutton.extend.iconSize.md, + height: components.togglebutton.extend.iconSize.md, }, - }, - compoundVariants: [ - { - checked: 'true', - pressed: 'true', - styles: { - color: theme.Form.ToggleButton.toggleButtonTextActiveHoverColor, - }, + small: { + width: components.togglebutton.extend.iconSize.sm, + height: components.togglebutton.extend.iconSize.sm, }, - ], + }, + checked: { + true: { color: components.togglebutton.colorScheme.root.checkedColor }, + false: { color: components.togglebutton.colorScheme.root.color }, + }, + pressed: { + true: { color: components.togglebutton.colorScheme.root.hoverColor }, + false: {}, + }, + disabled: { + true: { color: components.togglebutton.colorScheme.root.disabledColor }, + false: {}, + }, }, - }) -) + compoundVariants: [ + { + checked: 'true', + pressed: 'true', + styles: { color: components.togglebutton.extend.checkedHoverColor }, + }, + ], + }, + label: { + flexShrink: 1, + fontFamily: fonts.fontFamily.heading, + fontWeight: fonts.fontWeight.demibold, + includeFontPadding: false, + verticalAlign: 'middle', + variants: { + size: { + xlarge: { fontSize: fonts.fontSize[600] }, + large: { fontSize: fonts.fontSize[500] }, + base: { fontSize: fonts.fontSize[300] }, + small: { fontSize: fonts.fontSize[100] }, + }, + checked: { + true: { color: components.togglebutton.colorScheme.root.checkedColor }, + false: { color: components.togglebutton.colorScheme.root.color }, + }, + pressed: { + true: { color: components.togglebutton.colorScheme.root.hoverColor }, + false: {}, + }, + disabled: { + true: { color: components.togglebutton.colorScheme.root.disabledColor }, + false: {}, + }, + }, + compoundVariants: [ + { + checked: 'true', + pressed: 'true', + styles: { color: components.togglebutton.extend.checkedHoverColor }, + }, + ], + }, +})) export const ToggleButtonTestId = { root: 'ToggleButton', diff --git a/src/components/ToggleButton/__tests__/__snapshots__/ToggleButton.test.tsx.snap b/src/components/ToggleButton/__tests__/__snapshots__/ToggleButton.test.tsx.snap index d99139b2..88c04189 100644 --- a/src/components/ToggleButton/__tests__/__snapshots__/ToggleButton.test.tsx.snap +++ b/src/components/ToggleButton/__tests__/__snapshots__/ToggleButton.test.tsx.snap @@ -10,8 +10,8 @@ exports[`ToggleButton snapshots checked = false, disabled = false, iconOnly = fa [ { "alignSelf": "flex-start", - "borderColor": "rgba(255, 255, 255, 0.0001)", - "borderRadius": 100, + "borderColor": "#e2e2e4", + "borderRadius": 1600, "borderWidth": 1, "overflow": "hidden", }, @@ -27,12 +27,12 @@ exports[`ToggleButton snapshots checked = false, disabled = false, iconOnly = fa "alignItems": "center", "alignSelf": "flex-start", "backgroundColor": "#e2e2e4", - "borderRadius": 100, + "borderRadius": 1600, "flexDirection": "row", - "gap": 7, + "gap": 8, "minHeight": 28, - "paddingHorizontal": 10.5, - "paddingVertical": 0, + "paddingHorizontal": 14, + "paddingVertical": 8, }, false, ] @@ -41,15 +41,15 @@ exports[`ToggleButton snapshots checked = false, disabled = false, iconOnly = fa > Date: Tue, 4 Aug 2026 17:05:51 +0300 Subject: [PATCH 39/60] =?UTF-8?q?feat(Typography):=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Typography/Anchor.tsx | 36 +- src/components/Typography/Body.tsx | 31 +- src/components/Typography/Caption.tsx | 45 +- src/components/Typography/Service.tsx | 56 +- src/components/Typography/Subtitle.tsx | 20 +- src/components/Typography/Title.tsx | 28 +- .../__snapshots__/Anchor.test.tsx.snap | 132 +-- .../__snapshots__/Body.test.tsx.snap | 422 ++++---- .../__snapshots__/Caption.test.tsx.snap | 192 ++-- .../__snapshots__/Service.test.tsx.snap | 952 +++++++++--------- .../__snapshots__/Subtitle.test.tsx.snap | 76 +- .../__snapshots__/Title.test.tsx.snap | 24 +- 12 files changed, 1016 insertions(+), 998 deletions(-) diff --git a/src/components/Typography/Anchor.tsx b/src/components/Typography/Anchor.tsx index 475176e6..f8e79e26 100644 --- a/src/components/Typography/Anchor.tsx +++ b/src/components/Typography/Anchor.tsx @@ -68,10 +68,10 @@ export const Anchor = memo( }, [noWrapper, testID]) const iconSize = base ? styles.iconBase : styles.icon - const iconUniProps = ({ typography: t }: ThemeType) => ({ + const iconUniProps = ({ semantic }: ThemeType) => ({ color: visited - ? t.Color.Service['text-help'] - : t.Color.Service['text-info'], + ? semantic.colorScheme.color.fg.status.help.default + : semantic.colorScheme.color.fg.status.info.default, }) return ( @@ -133,35 +133,35 @@ export const Anchor = memo( } ) -const styles = StyleSheet.create(({ spacing, typography, fonts }) => ({ +const styles = StyleSheet.create(({ semantic, fonts }) => ({ container: { flexDirection: 'row', alignItems: 'center' }, text: { flexShrink: 1, - fontSize: typography.Size['text-sm'], + fontSize: fonts.fontSize[200], includeFontPadding: false, verticalAlign: 'middle', - color: typography.Color.Service['text-info'], - fontFamily: fonts.secondary, - lineHeight: 15, - letterSpacing: -0.25, + color: semantic.colorScheme.color.fg.status.info.default, + fontFamily: fonts.fontFamily.base, + lineHeight: fonts.lineHeight[300], + letterSpacing: fonts.letterSpacing[200], }, underlined: { textDecorationLine: 'underline' }, base: { - fontSize: typography.Size['text-base'], + fontSize: fonts.fontSize[300], lineHeight: undefined, - letterSpacing: 0, + letterSpacing: fonts.letterSpacing[500], }, - visited: { color: typography.Color.Service['text-help'] }, + visited: { color: semantic.colorScheme.color.fg.status.help.default }, icon: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], + width: semantic.dimension.size[450], + height: semantic.dimension.size[450], }, iconBase: { - width: typography.Size['text-xl'], - height: typography.Size['text-xl'], + width: semantic.dimension.size[600], + height: semantic.dimension.size[600], }, - leftIconContainer: { paddingRight: spacing.Padding['p-2'] }, - rightIconContainer: { paddingLeft: spacing.Padding['p-2'] }, + leftIconContainer: { paddingRight: semantic.dimension.space[200] }, + rightIconContainer: { paddingLeft: semantic.dimension.space[200] }, })) export const AnchorTestId = { diff --git a/src/components/Typography/Body.tsx b/src/components/Typography/Body.tsx index f223873e..c44d11ed 100644 --- a/src/components/Typography/Body.tsx +++ b/src/components/Typography/Body.tsx @@ -36,21 +36,26 @@ export const Body = ({ ) } -const styles = StyleSheet.create(({ theme, typography, fonts }) => ({ +// Осознанный обход слоя components: цвет текста — семантическая роль, и своего +// токена у Typography нет (компонент отсутствует в tokens.json). +const styles = StyleSheet.create(({ semantic, fonts }) => ({ text: { - fontSize: typography.Size['text-base'], + fontSize: fonts.fontSize[300], includeFontPadding: false, verticalAlign: 'middle', - fontFamily: fonts.secondary, - lineHeight: 20, + fontFamily: fonts.fontFamily.base, + lineHeight: fonts.lineHeight[450], }, - regular: { fontWeight: 400 }, - bold: { fontWeight: 700, letterSpacing: -0.5 }, - default: { color: theme.General.textColor }, - primary: { color: theme.General.primaryColor }, - secondary: { color: theme.General.textSecondaryColor }, - base: { fontSize: typography.Size['text-sm'], lineHeight: 18 }, - paragraph: { lineHeight: 24 }, - paragraphBase: { lineHeight: 21 }, - disabled: { opacity: 0.6 }, + regular: { fontWeight: fonts.fontWeight.regular }, + bold: { + fontWeight: fonts.fontWeight.bold, + letterSpacing: fonts.letterSpacing[400], + }, + default: { color: semantic.colorScheme.color.fg.default }, + primary: { color: semantic.colorScheme.color.fg.brand.default }, + secondary: { color: semantic.colorScheme.color.fg.muted }, + base: { fontSize: fonts.fontSize[200], lineHeight: fonts.lineHeight[400] }, + paragraph: { lineHeight: fonts.lineHeight[600] }, + paragraphBase: { lineHeight: fonts.lineHeight[500] }, + disabled: { opacity: semantic.effects.opacity[60] }, })) diff --git a/src/components/Typography/Caption.tsx b/src/components/Typography/Caption.tsx index 7795843a..c71c7c2b 100644 --- a/src/components/Typography/Caption.tsx +++ b/src/components/Typography/Caption.tsx @@ -39,13 +39,15 @@ export const Caption = ({ {...styles.icon} source={Icon} testID={CaptionTestId.icon} - uniProps={({ theme }) => ({ - color: { - default: theme.General.textColor, - primary: theme.General.primaryColor, - secondary: theme.General.textSecondaryColor, - }[color], - })} + uniProps={({ semantic }) => { + return { + color: { + default: semantic.colorScheme.color.fg.default, + primary: semantic.colorScheme.color.fg.brand.default, + secondary: semantic.colorScheme.color.fg.muted, + }[color], + } + }} /> {text} @@ -57,23 +59,28 @@ export const Caption = ({ const CaptionTestId = { text: 'CaptionText', icon: 'CaptionIcon' } -const styles = StyleSheet.create(({ theme, spacing, typography, fonts }) => ({ +// Осознанный обход слоя components: цвет текста — семантическая роль, и своего +// токена у Typography нет (компонент отсутствует в tokens.json). +const styles = StyleSheet.create(({ semantic, fonts }) => ({ text: { - fontSize: typography.Size['text-sm'], + fontSize: fonts.fontSize[200], includeFontPadding: false, verticalAlign: 'middle', - fontFamily: fonts.secondary, - lineHeight: 15, - letterSpacing: -0.25, + fontFamily: fonts.fontFamily.base, + lineHeight: fonts.lineHeight[300], + letterSpacing: fonts.letterSpacing[200], }, textWithIcon: { flexShrink: 1 }, - default: { color: theme.General.textColor }, - primary: { color: theme.General.primaryColor }, - secondary: { color: theme.General.textSecondaryColor }, - disabled: { opacity: 0.6 }, - withIconContainer: { flexDirection: 'row', gap: spacing.Gap['gap-1'] }, + default: { color: semantic.colorScheme.color.fg.default }, + primary: { color: semantic.colorScheme.color.fg.brand.default }, + secondary: { color: semantic.colorScheme.color.fg.muted }, + disabled: { opacity: semantic.effects.opacity[60] }, + withIconContainer: { + flexDirection: 'row', + gap: semantic.dimension.space[100], + }, icon: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], + width: semantic.dimension.size[450], + height: semantic.dimension.size[450], }, })) diff --git a/src/components/Typography/Service.tsx b/src/components/Typography/Service.tsx index 78ea369e..442dc22d 100644 --- a/src/components/Typography/Service.tsx +++ b/src/components/Typography/Service.tsx @@ -69,15 +69,17 @@ export const Service = ({ ({ - color: { - danger: t.Color.Service['text-danger'], - warning: t.Color.Service['text-warning'], - success: t.Color.Service['text-success'], - info: t.Color.Service['text-info'], - help: t.Color.Service['text-help'], - }[variant], - })} + uniProps={({ semantic }) => { + return { + color: { + danger: semantic.colorScheme.color.fg.status.danger.default, + warning: semantic.colorScheme.color.fg.status.warning.default, + success: semantic.colorScheme.color.fg.status.success.default, + info: semantic.colorScheme.color.fg.status.info.default, + help: semantic.colorScheme.color.fg.status.help.default, + }[variant], + } + }} /> ) : null} @@ -85,34 +87,34 @@ export const Service = ({ ) } -const styles = StyleSheet.create(({ typography, spacing, fonts }) => ({ +const styles = StyleSheet.create(({ semantic, fonts }) => ({ iconBase: { - width: typography.Size['text-xl'], - height: typography.Size['text-xl'], + width: semantic.dimension.size[600], + height: semantic.dimension.size[600], }, icon: { - width: typography.Size['text-base'], - height: typography.Size['text-base'], + width: semantic.dimension.size[450], + height: semantic.dimension.size[450], }, - containerBase: { flexDirection: 'row', gap: spacing.Gap['gap-2'] }, - container: { flexDirection: 'row', gap: spacing.Gap['gap-1'] }, + containerBase: { flexDirection: 'row', gap: semantic.dimension.space[200] }, + container: { flexDirection: 'row', gap: semantic.dimension.space[100] }, textCommon: { includeFontPadding: false, verticalAlign: 'middle', flexShrink: 1, - fontWeight: 400, - fontSize: typography.Size['text-sm'], - fontFamily: fonts.secondary, - lineHeight: 15, - letterSpacing: -0.25, + fontWeight: fonts.fontWeight.regular, + fontSize: fonts.fontSize[200], + fontFamily: fonts.fontFamily.base, + lineHeight: fonts.lineHeight[300], + letterSpacing: fonts.letterSpacing[200], }, - textBase: { lineHeight: undefined, fontSize: typography.Size['text-base'] }, + textBase: { lineHeight: undefined, fontSize: fonts.fontSize[300] }, - warning: { color: typography.Color.Service['text-warning'] }, - success: { color: typography.Color.Service['text-success'] }, - info: { color: typography.Color.Service['text-info'] }, - help: { color: typography.Color.Service['text-help'] }, - danger: { color: typography.Color.Service['text-danger'] }, + warning: { color: semantic.colorScheme.color.fg.status.warning.default }, + success: { color: semantic.colorScheme.color.fg.status.success.default }, + info: { color: semantic.colorScheme.color.fg.status.info.default }, + help: { color: semantic.colorScheme.color.fg.status.help.default }, + danger: { color: semantic.colorScheme.color.fg.status.danger.default }, })) diff --git a/src/components/Typography/Subtitle.tsx b/src/components/Typography/Subtitle.tsx index 99ff640b..bfacf93c 100644 --- a/src/components/Typography/Subtitle.tsx +++ b/src/components/Typography/Subtitle.tsx @@ -30,16 +30,18 @@ export const Subtitle = memo( ) ) -const styles = StyleSheet.create(({ theme, typography, fonts }) => ({ +// Осознанный обход слоя components: цвет текста — семантическая роль, и своего +// токена у Typography нет (компонент отсутствует в tokens.json). +const styles = StyleSheet.create(({ semantic, fonts }) => ({ text: { - fontSize: typography.Size['text-xs'], - fontWeight: 700, + fontSize: fonts.fontSize[100], + fontWeight: fonts.fontWeight.bold, textTransform: 'uppercase', - fontFamily: fonts.secondary, - lineHeight: 15, + fontFamily: fonts.fontFamily.base, + lineHeight: fonts.lineHeight[300], }, - base: { lineHeight: 18, fontSize: typography.Size['text-sm'] }, - default: { color: theme.General.textColor }, - primary: { color: theme.General.primaryColor }, - secondary: { color: theme.General.textSecondaryColor }, + base: { lineHeight: fonts.lineHeight[400], fontSize: fonts.fontSize[200] }, + default: { color: semantic.colorScheme.color.fg.default }, + primary: { color: semantic.colorScheme.color.fg.brand.default }, + secondary: { color: semantic.colorScheme.color.fg.muted }, })) diff --git a/src/components/Typography/Title.tsx b/src/components/Typography/Title.tsx index de6dd6d0..97946d4b 100644 --- a/src/components/Typography/Title.tsx +++ b/src/components/Typography/Title.tsx @@ -10,21 +10,23 @@ export const Title = ({ level, style, ...other }: TitleProps) => ( ) -const styles = StyleSheet.create(({ theme, typography, fonts }) => ({ +// Осознанный обход слоя components: цвет текста — семантическая роль, и своего +// токена у Typography нет (компонент отсутствует в tokens.json). +const styles = StyleSheet.create(({ semantic, fonts }) => ({ text: { - color: theme.General.textColor, - fontFamily: fonts.primary, - fontWeight: 700, + color: semantic.colorScheme.color.fg.default, + fontFamily: fonts.fontFamily.heading, + fontWeight: fonts.fontWeight.bold, includeFontPadding: false, verticalAlign: 'middle', }, - d1: { fontSize: typography.Size['text-5xl'] }, - d2: { fontSize: typography.Size['text-4xl'] }, - d3: { fontSize: typography.Size['text-3xl'] }, - h1: { fontSize: typography.Size['text-2xl'] }, - h2: { fontSize: typography.Size['text-xl'] }, - h3: { fontSize: typography.Size['text-lg'] }, - h4: { fontSize: typography.Size['text-base'] }, - h5: { fontSize: typography.Size['text-sm'] }, - h6: { fontSize: typography.Size['text-xs'] }, + d1: { fontSize: fonts.fontSize[750] }, + d2: { fontSize: fonts.fontSize[700] }, + d3: { fontSize: fonts.fontSize[650] }, + h1: { fontSize: fonts.fontSize[600] }, + h2: { fontSize: fonts.fontSize[500] }, + h3: { fontSize: fonts.fontSize[400] }, + h4: { fontSize: fonts.fontSize[300] }, + h5: { fontSize: fonts.fontSize[100] }, + h6: { fontSize: fonts.fontSize[100] }, })) diff --git a/src/components/Typography/__tests__/__snapshots__/Anchor.test.tsx.snap b/src/components/Typography/__tests__/__snapshots__/Anchor.test.tsx.snap index 53bf9367..1d37bed1 100644 --- a/src/components/Typography/__tests__/__snapshots__/Anchor.test.tsx.snap +++ b/src/components/Typography/__tests__/__snapshots__/Anchor.test.tsx.snap @@ -17,13 +17,13 @@ exports[`Body component tests default props 1`] = ` style={ [ { - "color": "#1e76cd", + "color": "#4496e8", "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, @@ -82,22 +82,22 @@ exports[`Body component tests левая иконка, base, visited, testID = C onStartShouldSetResponder={[Function]} style={ { - "paddingRight": 7, + "paddingRight": 8, } } testID="AnchorLeftPressable" > @@ -15,16 +15,16 @@ exports[`Service component tests base = false, showIcon = false, variant = dange { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#db3424", + "color": "#e85244", }, ] } @@ -39,7 +39,7 @@ exports[`Service component tests base = false, showIcon = false, variant = dange style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -49,16 +49,16 @@ exports[`Service component tests base = false, showIcon = false, variant = dange { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#db3424", + "color": "#e85244", }, ] } @@ -73,7 +73,7 @@ exports[`Service component tests base = false, showIcon = false, variant = help style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -83,16 +83,16 @@ exports[`Service component tests base = false, showIcon = false, variant = help { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#9457ea", + "color": "#a855f7", }, ] } @@ -107,7 +107,7 @@ exports[`Service component tests base = false, showIcon = false, variant = help style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -117,16 +117,16 @@ exports[`Service component tests base = false, showIcon = false, variant = help { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#9457ea", + "color": "#a855f7", }, ] } @@ -141,7 +141,7 @@ exports[`Service component tests base = false, showIcon = false, variant = info style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -151,16 +151,16 @@ exports[`Service component tests base = false, showIcon = false, variant = info { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#1e76cd", + "color": "#4496e8", }, ] } @@ -175,7 +175,7 @@ exports[`Service component tests base = false, showIcon = false, variant = info style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -185,16 +185,16 @@ exports[`Service component tests base = false, showIcon = false, variant = info { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#1e76cd", + "color": "#4496e8", }, ] } @@ -209,7 +209,7 @@ exports[`Service component tests base = false, showIcon = false, variant = succe style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -219,16 +219,16 @@ exports[`Service component tests base = false, showIcon = false, variant = succe { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#168322", + "color": "#44e858", }, ] } @@ -243,7 +243,7 @@ exports[`Service component tests base = false, showIcon = false, variant = succe style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -253,16 +253,16 @@ exports[`Service component tests base = false, showIcon = false, variant = succe { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#168322", + "color": "#44e858", }, ] } @@ -277,7 +277,7 @@ exports[`Service component tests base = false, showIcon = false, variant = warni style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -287,16 +287,16 @@ exports[`Service component tests base = false, showIcon = false, variant = warni { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#dc9710", + "color": "#f5b83d", }, ] } @@ -311,7 +311,7 @@ exports[`Service component tests base = false, showIcon = false, variant = warni style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -321,16 +321,16 @@ exports[`Service component tests base = false, showIcon = false, variant = warni { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, false, { - "color": "#dc9710", + "color": "#f5b83d", }, ] } @@ -345,21 +345,21 @@ exports[`Service component tests base = false, showIcon = true, variant = danger style={ { "flexDirection": "row", - "gap": 3.5, + "gap": 4, } } > @@ -2359,19 +2359,19 @@ exports[`Service component tests base = true, showIcon = false, variant = danger { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#db3424", + "color": "#e85244", }, ] } @@ -2386,7 +2386,7 @@ exports[`Service component tests base = true, showIcon = false, variant = danger style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2396,19 +2396,19 @@ exports[`Service component tests base = true, showIcon = false, variant = danger { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#db3424", + "color": "#e85244", }, ] } @@ -2423,7 +2423,7 @@ exports[`Service component tests base = true, showIcon = false, variant = help 1 style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2433,19 +2433,19 @@ exports[`Service component tests base = true, showIcon = false, variant = help 1 { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#9457ea", + "color": "#a855f7", }, ] } @@ -2460,7 +2460,7 @@ exports[`Service component tests base = true, showIcon = false, variant = help 2 style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2470,19 +2470,19 @@ exports[`Service component tests base = true, showIcon = false, variant = help 2 { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#9457ea", + "color": "#a855f7", }, ] } @@ -2497,7 +2497,7 @@ exports[`Service component tests base = true, showIcon = false, variant = info 1 style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2507,19 +2507,19 @@ exports[`Service component tests base = true, showIcon = false, variant = info 1 { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#1e76cd", + "color": "#4496e8", }, ] } @@ -2534,7 +2534,7 @@ exports[`Service component tests base = true, showIcon = false, variant = info 2 style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2544,19 +2544,19 @@ exports[`Service component tests base = true, showIcon = false, variant = info 2 { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#1e76cd", + "color": "#4496e8", }, ] } @@ -2571,7 +2571,7 @@ exports[`Service component tests base = true, showIcon = false, variant = succes style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2581,19 +2581,19 @@ exports[`Service component tests base = true, showIcon = false, variant = succes { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#168322", + "color": "#44e858", }, ] } @@ -2608,7 +2608,7 @@ exports[`Service component tests base = true, showIcon = false, variant = succes style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2618,19 +2618,19 @@ exports[`Service component tests base = true, showIcon = false, variant = succes { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#168322", + "color": "#44e858", }, ] } @@ -2645,7 +2645,7 @@ exports[`Service component tests base = true, showIcon = false, variant = warnin style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2655,19 +2655,19 @@ exports[`Service component tests base = true, showIcon = false, variant = warnin { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#dc9710", + "color": "#f5b83d", }, ] } @@ -2682,7 +2682,7 @@ exports[`Service component tests base = true, showIcon = false, variant = warnin style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > @@ -2692,19 +2692,19 @@ exports[`Service component tests base = true, showIcon = false, variant = warnin { "flexShrink": 1, "fontFamily": "Noto Sans", - "fontSize": 12.25, + "fontSize": 14, "fontWeight": 400, "includeFontPadding": false, - "letterSpacing": -0.25, - "lineHeight": 15, + "letterSpacing": -0.32, + "lineHeight": 18, "verticalAlign": "middle", }, { - "fontSize": 14, + "fontSize": 16, "lineHeight": undefined, }, { - "color": "#dc9710", + "color": "#f5b83d", }, ] } @@ -2719,21 +2719,21 @@ exports[`Service component tests base = true, showIcon = true, variant = danger style={ { "flexDirection": "row", - "gap": 7, + "gap": 8, } } > Date: Tue, 4 Aug 2026 18:24:35 +0300 Subject: [PATCH 40/60] =?UTF-8?q?refactor(theme):=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=81=D0=BB=D0=BE=D0=B9=20leg?= =?UTF-8?q?acy-=D1=81=D0=BE=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=B8=D0=BC?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MIGRATION.md | 4 +- README.md | 21 ++- src/hooks/useFonts.ts | 7 +- src/theme/ThemeContext.tsx | 66 ++------- src/theme/__tests__/ThemeContext.test.tsx | 114 +++++++++------ .../__tests__/easing.test.ts} | 2 +- .../{tokenAdapters.ts => adapters/easing.ts} | 0 src/theme/adapters/index.ts | 1 + src/theme/commonTheme.ts | 23 ---- src/theme/darkTheme.ts | 15 +- src/theme/index.ts | 5 +- .../InputSize/base.json | 0 .../InputSize/index.ts | 0 .../InputSize/large.json | 0 .../InputSize/medium.json | 0 .../InputSize/xlarge.json | 0 .../ModalSize/index.ts | 0 .../ModalSize/lg.json | 0 .../ModalSize/md.json | 0 .../ModalSize/sm.json | 0 .../ModalSize/xl.json | 0 src/theme/legacyTokens/README.md | 13 ++ .../{assets => legacyTokens}/background.json | 0 .../{assets => legacyTokens}/border.json | 0 .../{assets => legacyTokens}/customCommon.ts | 0 .../{assets => legacyTokens}/customDark.ts | 0 .../{assets => legacyTokens}/customLight.ts | 0 .../{assets => legacyTokens}/effects.json | 0 .../{assets => legacyTokens}/global.json | 0 src/theme/legacyTokens/index.ts | 130 ++++++++++++++++++ .../primaryColors.json | 0 src/theme/{assets => legacyTokens}/shadow.ts | 0 .../{assets => legacyTokens}/sizing.json | 0 .../{assets => legacyTokens}/spacing.json | 0 .../{assets => legacyTokens}/themeDark.json | 0 .../{assets => legacyTokens}/themeLight.json | 0 .../{assets => legacyTokens}/typography.json | 0 src/theme/lightTheme.ts | 15 +- src/theme/themes.ts | 29 ++++ src/theme/tokens/README.md | 12 +- src/theme/types.ts | 60 +++----- 41 files changed, 302 insertions(+), 215 deletions(-) rename src/theme/{__tests__/tokenAdapters.test.ts => adapters/__tests__/easing.test.ts} (87%) rename src/theme/{tokenAdapters.ts => adapters/easing.ts} (100%) create mode 100644 src/theme/adapters/index.ts delete mode 100644 src/theme/commonTheme.ts rename src/theme/{assets => legacyTokens}/InputSize/base.json (100%) rename src/theme/{assets => legacyTokens}/InputSize/index.ts (100%) rename src/theme/{assets => legacyTokens}/InputSize/large.json (100%) rename src/theme/{assets => legacyTokens}/InputSize/medium.json (100%) rename src/theme/{assets => legacyTokens}/InputSize/xlarge.json (100%) rename src/theme/{assets => legacyTokens}/ModalSize/index.ts (100%) rename src/theme/{assets => legacyTokens}/ModalSize/lg.json (100%) rename src/theme/{assets => legacyTokens}/ModalSize/md.json (100%) rename src/theme/{assets => legacyTokens}/ModalSize/sm.json (100%) rename src/theme/{assets => legacyTokens}/ModalSize/xl.json (100%) create mode 100644 src/theme/legacyTokens/README.md rename src/theme/{assets => legacyTokens}/background.json (100%) rename src/theme/{assets => legacyTokens}/border.json (100%) rename src/theme/{assets => legacyTokens}/customCommon.ts (100%) rename src/theme/{assets => legacyTokens}/customDark.ts (100%) rename src/theme/{assets => legacyTokens}/customLight.ts (100%) rename src/theme/{assets => legacyTokens}/effects.json (100%) rename src/theme/{assets => legacyTokens}/global.json (100%) create mode 100644 src/theme/legacyTokens/index.ts rename src/theme/{assets => legacyTokens}/primaryColors.json (100%) rename src/theme/{assets => legacyTokens}/shadow.ts (100%) rename src/theme/{assets => legacyTokens}/sizing.json (100%) rename src/theme/{assets => legacyTokens}/spacing.json (100%) rename src/theme/{assets => legacyTokens}/themeDark.json (100%) rename src/theme/{assets => legacyTokens}/themeLight.json (100%) rename src/theme/{assets => legacyTokens}/typography.json (100%) create mode 100644 src/theme/themes.ts diff --git a/MIGRATION.md b/MIGRATION.md index 074c690b..de792443 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -18,7 +18,7 @@ import { export const Root = () => ( @@ -45,7 +45,7 @@ const fonts = useFonts() import { StyleSheet } from 'react-native-unistyles' const styles = StyleSheet.create(({ fonts }) => ({ - title: { fontFamily: fonts.primary }, + title: { fontFamily: fonts.fontFamily.heading }, })) ``` diff --git a/README.md b/README.md index b95d6112..bf4be666 100644 --- a/README.md +++ b/README.md @@ -36,26 +36,25 @@ npm i @cdek-it/react-native-ui-kit UI kit использует следующие виды шрифтов. -| Тип шрифта | Используемые начертания | Рекомендуемый шрифт | Рекомендуемый аналог | -| ----------- | ---------------------------------------------- | ------------------- | -------------------- | -| `primary` | – regular
– demibold
– demibold italic | TT Fellows | Noto Sans | -| `secondary` | – regular
– bold | Noto Sans | — | +| Тип шрифта | Используемые начертания | Рекомендуемый шрифт | Рекомендуемый аналог | +| ---------- | ---------------------------------------------- | ------------------- | -------------------- | +| `heading` | – regular
– demibold
– demibold italic | TT Fellows | Noto Sans | +| `base` | – regular
– bold | Noto Sans | — | Исходники шрифтов не поставляются вместе с пакетом, их требуется подключать -отдельно. После подключения шрифтов в проект, необходимо указать их в -`ThemeContextProvider`. +отдельно под именами, указанными в токенах. ```tsx - + ``` После этого шрифты доступны через `useUnistyles().theme.fonts` или прямо в `StyleSheet.create(({ fonts }) => ...)`. -`ThemeContextProvider` настраивает активную тему и шрифты для `unistyles`. -`ThemeContext` остается пустым и всегда имеет значение `null`. +`ThemeContextProvider` только настраивает темы и шрифты для `unistyles`. +`ThemeContext` остается пустым и всегда имеет значение `null`. Deprecated-формат +`fonts={{ primary, secondary }}` временно сохраняется для обратной +совместимости. ### Пример подключения шрифтов с помощью expo-fonts через плагин diff --git a/src/hooks/useFonts.ts b/src/hooks/useFonts.ts index e83308db..348ee283 100644 --- a/src/hooks/useFonts.ts +++ b/src/hooks/useFonts.ts @@ -1,10 +1,9 @@ import { useUnistyles } from 'react-native-unistyles' -import type { FontsConfig } from '../theme' +import type { ThemeType } from '../theme/types' -export const useFonts = (): FontsConfig => { +export const useFonts = (): ThemeType['fonts'] => { const { theme } = useUnistyles() - const { primary, secondary } = theme.fonts - return { primary, secondary } + return theme.fonts } diff --git a/src/theme/ThemeContext.tsx b/src/theme/ThemeContext.tsx index f20afb5b..f528907e 100644 --- a/src/theme/ThemeContext.tsx +++ b/src/theme/ThemeContext.tsx @@ -4,56 +4,19 @@ import { StyleSheet, UnistylesRuntime } from 'react-native-unistyles' import { SkeletonContextProvider } from '../utils/SkeletonContext' -import { darkTheme } from './darkTheme' -import { lightTheme } from './lightTheme' -import { - componentTokens, - fontTokens, - semanticTokens, - type ComponentTokens, - type SemanticTokens, -} from './tokens' -import { - type FontsConfig, - type FontTokens, - type ThemeType, - ThemeVariant, -} from './types' - -type InternalTheme = Omit & { - components: ComponentTokens - fonts: FontsConfig & FontTokens - semantic: ThemeType['semantic'] & SemanticTokens -} - -const createInternalTheme = ( - theme: ThemeType, - components: ComponentTokens -): InternalTheme => ({ - ...theme, - components, - fonts: { - ...fontTokens, - ...theme.fonts, - fontFamily: { base: theme.fonts.secondary, heading: theme.fonts.primary }, - }, - semantic: { ...semanticTokens, ...theme.semantic }, -}) - -const internalThemes = { - light: createInternalTheme(lightTheme, componentTokens.light), - dark: createInternalTheme(darkTheme, componentTokens.dark), -} +import { applyFontConfig, type FontsConfig } from './legacyTokens' +import { darkTheme, lightTheme } from './themes' +import { ThemeVariant } from './types' StyleSheet.configure({ settings: { initialTheme: 'light' }, - themes: internalThemes, + themes: { light: lightTheme, dark: darkTheme }, }) declare module 'react-native-unistyles' { export interface UnistylesThemes { - light: (typeof internalThemes)['light'] - dark: (typeof internalThemes)['dark'] + light: typeof lightTheme + dark: typeof darkTheme } } @@ -79,17 +42,12 @@ export const ThemeContextProvider = ({ UnistylesRuntime.setTheme(THEME_NAME_MAP[initialTheme]) if (fonts) { - const updateFonts = (theme: InternalTheme): InternalTheme => ({ - ...theme, - fonts: { - ...theme.fonts, - ...fonts, - fontFamily: { base: fonts.secondary, heading: fonts.primary }, - }, - }) - - UnistylesRuntime.updateTheme('light', updateFonts) - UnistylesRuntime.updateTheme('dark', updateFonts) + UnistylesRuntime.updateTheme('light', (theme) => + applyFontConfig(theme, fonts) + ) + UnistylesRuntime.updateTheme('dark', (theme) => + applyFontConfig(theme, fonts) + ) } // eslint-disable-next-line react-hooks/exhaustive-deps -- initial* props применяем только на mount }, []) diff --git a/src/theme/__tests__/ThemeContext.test.tsx b/src/theme/__tests__/ThemeContext.test.tsx index 2edec632..c65f0d92 100644 --- a/src/theme/__tests__/ThemeContext.test.tsx +++ b/src/theme/__tests__/ThemeContext.test.tsx @@ -4,15 +4,10 @@ import { Text } from 'react-native' import { UnistylesRuntime } from 'react-native-unistyles' import { ThemeContextProvider } from '../ThemeContext' -import { darkTheme } from '../darkTheme' -import { lightTheme } from '../lightTheme' +import { darkTheme, lightTheme } from '../themes' import { componentTokens, fontTokens, semanticTokens } from '../tokens' -import darkComponentTokens from '../tokens/components/dark.json' -import lightComponentTokens from '../tokens/components/light.json' import darkSemanticColorSchemeTokens from '../tokens/semantic/colorScheme/dark.json' import lightSemanticColorSchemeTokens from '../tokens/semantic/colorScheme/light.json' -import semanticDimensions from '../tokens/semantic/dimensions.json' -import semanticEffects from '../tokens/semantic/effects.json' import { ThemeVariant } from '../types' describe('ThemeContextProvider', () => { @@ -40,7 +35,7 @@ describe('ThemeContextProvider', () => { expect(UnistylesRuntime.setTheme).toHaveBeenCalledWith('light') }) - test('при передаче fonts обновляет обе темы', () => { + test('при legacy-формате fonts обновляет обе темы', () => { const fonts = { primary: 'Roboto', secondary: 'Inter' } render( @@ -59,14 +54,41 @@ describe('ThemeContextProvider', () => { ) const [, updater] = jest.mocked(UnistylesRuntime.updateTheme).mock.calls[0] - const theme = UnistylesRuntime.getTheme('light') + const theme = lightTheme expect(updater(theme)).toStrictEqual({ ...theme, fonts: { ...theme.fonts, + fontFamily: { + ...theme.fonts.fontFamily, + heading: fonts.primary, + base: fonts.secondary, + }, ...fonts, - fontFamily: { base: fonts.secondary, heading: fonts.primary }, + }, + }) + }) + + test('при актуальном формате fonts обновляет обе темы', () => { + const fonts = { heading: 'Roboto', base: 'Inter' } + + render( + + child + + ) + + const [, updater] = jest.mocked(UnistylesRuntime.updateTheme).mock.calls[0] + const theme = lightTheme + + expect(updater(theme)).toStrictEqual({ + ...theme, + fonts: { + ...theme.fonts, + fontFamily: { ...theme.fonts.fontFamily, ...fonts }, + primary: fonts.heading, + secondary: fonts.base, }, }) }) @@ -81,51 +103,57 @@ describe('ThemeContextProvider', () => { expect(UnistylesRuntime.updateTheme).not.toHaveBeenCalled() }) - test('каждая тема содержит только соответствующую цветовую схему', () => { + test('каждая тема содержит соответствующие semantic-токены', () => { expect(lightTheme.semantic.colorScheme).toBe(lightSemanticColorSchemeTokens) expect(darkTheme.semantic.colorScheme).toBe(darkSemanticColorSchemeTokens) - expect(lightTheme.semantic).not.toHaveProperty('dimension') - expect(lightTheme.semantic).not.toHaveProperty('effects') + expect(lightTheme.semantic.dimension).toBe(semanticTokens.dimension) + expect(lightTheme.semantic.effects).toBe(semanticTokens.effects) }) test('общие semantic-токены не зависят от темы', () => { - expect(semanticTokens.dimension).toBe(semanticDimensions) - expect(semanticTokens.effects).toBe(semanticEffects) + expect(lightTheme.semantic.dimension).toBe(darkTheme.semantic.dimension) + expect(lightTheme.semantic.effects).toBe(darkTheme.semantic.effects) }) - test('component-токены не входят в публичные темы', () => { - expect(lightTheme).not.toHaveProperty('components') - expect(darkTheme).not.toHaveProperty('components') + test('каждая тема содержит соответствующие component-токены', () => { + expect(lightTheme.components).toBe(componentTokens.light) + expect(darkTheme.components).toBe(componentTokens.dark) }) - test('внутренняя карта component-токенов содержит обе темы', () => { - expect(componentTokens.light).toBe(lightComponentTokens) - expect(componentTokens.dark).toBe(darkComponentTokens) + test('каждая тема содержит общие шрифтовые токены', () => { + expect(lightTheme.fonts.fontSize).toBe(fontTokens.fontSize) + expect(darkTheme.fonts.fontSize).toBe(fontTokens.fontSize) }) - test('внутренняя тема Unistyles содержит сгенерированные токены', () => { - const internalLightTheme = UnistylesRuntime.getTheme('light') - const internalDarkTheme = UnistylesRuntime.getTheme('dark') - - expect(internalLightTheme).toMatchObject({ - components: lightComponentTokens, - fonts: fontTokens, - semantic: { - colorScheme: lightSemanticColorSchemeTokens, - dimension: semanticDimensions, - effects: semanticEffects, - }, - }) + test('публичные темы сохраняют legacy-алиасы шрифтов', () => { + expect(lightTheme.fonts).toStrictEqual( + expect.objectContaining({ + primary: fontTokens.fontFamily.heading, + secondary: fontTokens.fontFamily.base, + }) + ) + }) - expect(internalDarkTheme).toMatchObject({ - components: darkComponentTokens, - fonts: fontTokens, - semantic: { - colorScheme: darkSemanticColorSchemeTokens, - dimension: semanticDimensions, - effects: semanticEffects, - }, - }) - expect(internalLightTheme.fonts).toStrictEqual(internalDarkTheme.fonts) + test('публичные темы сохраняют legacy-токены', () => { + const legacyKeys = [ + 'background', + 'border', + 'colors', + 'custom', + 'effects', + 'global', + 'shadow', + 'sizing', + 'spacing', + 'theme', + 'typography', + ] + + expect(Object.keys(lightTheme)).toStrictEqual( + expect.arrayContaining(legacyKeys) + ) + expect(Object.keys(darkTheme)).toStrictEqual( + expect.arrayContaining(legacyKeys) + ) }) }) diff --git a/src/theme/__tests__/tokenAdapters.test.ts b/src/theme/adapters/__tests__/easing.test.ts similarity index 87% rename from src/theme/__tests__/tokenAdapters.test.ts rename to src/theme/adapters/__tests__/easing.test.ts index f11c67b4..c6218172 100644 --- a/src/theme/__tests__/tokenAdapters.test.ts +++ b/src/theme/adapters/__tests__/easing.test.ts @@ -1,4 +1,4 @@ -import { toEasing } from '../tokenAdapters' +import { toEasing } from '../easing' describe('toEasing', () => { test('создаёт Reanimated easing из коэффициентов токена', () => { diff --git a/src/theme/tokenAdapters.ts b/src/theme/adapters/easing.ts similarity index 100% rename from src/theme/tokenAdapters.ts rename to src/theme/adapters/easing.ts diff --git a/src/theme/adapters/index.ts b/src/theme/adapters/index.ts new file mode 100644 index 00000000..3c4cc4cc --- /dev/null +++ b/src/theme/adapters/index.ts @@ -0,0 +1 @@ +export { toEasing, type EasingToken } from './easing' diff --git a/src/theme/commonTheme.ts b/src/theme/commonTheme.ts deleted file mode 100644 index 8add2156..00000000 --- a/src/theme/commonTheme.ts +++ /dev/null @@ -1,23 +0,0 @@ -import background from './assets/background.json' -import border from './assets/border.json' -import { customCommon } from './assets/customCommon' -import effects from './assets/effects.json' -import global from './assets/global.json' -import primaryColors from './assets/primaryColors.json' -import { shadow } from './assets/shadow' -import sizing from './assets/sizing.json' -import spacing from './assets/spacing.json' -import typography from './assets/typography.json' - -export const commonTheme = { - background, - colors: { primary: primaryColors }, - border, - effects, - global, - sizing, - spacing, - typography, - custom: customCommon, - shadow, -} diff --git a/src/theme/darkTheme.ts b/src/theme/darkTheme.ts index bbc330fe..c3419e58 100644 --- a/src/theme/darkTheme.ts +++ b/src/theme/darkTheme.ts @@ -1,14 +1 @@ -import { InputSize } from './assets/InputSize' -import { ModalSize } from './assets/ModalSize' -import { customDark } from './assets/customDark' -import darkThemeAssets from './assets/themeDark.json' -import { commonTheme } from './commonTheme' -import darkSemanticColorSchemeTokens from './tokens/semantic/colorScheme/dark.json' -import type { ThemeType } from './types' - -export const darkTheme: ThemeType = { - semantic: { colorScheme: darkSemanticColorSchemeTokens }, - theme: { ...darkThemeAssets, InputSize, ModalSize, custom: customDark }, - ...commonTheme, - fonts: { primary: 'TT Fellows', secondary: 'Noto Sans' }, -} +export { darkTheme } from './themes' diff --git a/src/theme/index.ts b/src/theme/index.ts index 4266d324..76e8c11c 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -1,6 +1,5 @@ -export { darkTheme } from './darkTheme' -export { lightTheme } from './lightTheme' -export { toEasing, type EasingToken } from './tokenAdapters' +export { darkTheme, lightTheme } from './themes' +export { toEasing, type EasingToken } from './adapters' export { semanticTokens, type SemanticTokens } from './tokens' export { ThemeContext, diff --git a/src/theme/assets/InputSize/base.json b/src/theme/legacyTokens/InputSize/base.json similarity index 100% rename from src/theme/assets/InputSize/base.json rename to src/theme/legacyTokens/InputSize/base.json diff --git a/src/theme/assets/InputSize/index.ts b/src/theme/legacyTokens/InputSize/index.ts similarity index 100% rename from src/theme/assets/InputSize/index.ts rename to src/theme/legacyTokens/InputSize/index.ts diff --git a/src/theme/assets/InputSize/large.json b/src/theme/legacyTokens/InputSize/large.json similarity index 100% rename from src/theme/assets/InputSize/large.json rename to src/theme/legacyTokens/InputSize/large.json diff --git a/src/theme/assets/InputSize/medium.json b/src/theme/legacyTokens/InputSize/medium.json similarity index 100% rename from src/theme/assets/InputSize/medium.json rename to src/theme/legacyTokens/InputSize/medium.json diff --git a/src/theme/assets/InputSize/xlarge.json b/src/theme/legacyTokens/InputSize/xlarge.json similarity index 100% rename from src/theme/assets/InputSize/xlarge.json rename to src/theme/legacyTokens/InputSize/xlarge.json diff --git a/src/theme/assets/ModalSize/index.ts b/src/theme/legacyTokens/ModalSize/index.ts similarity index 100% rename from src/theme/assets/ModalSize/index.ts rename to src/theme/legacyTokens/ModalSize/index.ts diff --git a/src/theme/assets/ModalSize/lg.json b/src/theme/legacyTokens/ModalSize/lg.json similarity index 100% rename from src/theme/assets/ModalSize/lg.json rename to src/theme/legacyTokens/ModalSize/lg.json diff --git a/src/theme/assets/ModalSize/md.json b/src/theme/legacyTokens/ModalSize/md.json similarity index 100% rename from src/theme/assets/ModalSize/md.json rename to src/theme/legacyTokens/ModalSize/md.json diff --git a/src/theme/assets/ModalSize/sm.json b/src/theme/legacyTokens/ModalSize/sm.json similarity index 100% rename from src/theme/assets/ModalSize/sm.json rename to src/theme/legacyTokens/ModalSize/sm.json diff --git a/src/theme/assets/ModalSize/xl.json b/src/theme/legacyTokens/ModalSize/xl.json similarity index 100% rename from src/theme/assets/ModalSize/xl.json rename to src/theme/legacyTokens/ModalSize/xl.json diff --git a/src/theme/legacyTokens/README.md b/src/theme/legacyTokens/README.md new file mode 100644 index 00000000..f163ad42 --- /dev/null +++ b/src/theme/legacyTokens/README.md @@ -0,0 +1,13 @@ +# Legacy-токены + +Эти токены сохраняются только для обратной совместимости публичных `lightTheme`, +`darkTheme` и `ThemeType`. Компоненты библиотеки используют `components`, +`semantic` и сгенерированную структуру `fonts`. + +Единственная точка подключения legacy-токенов — `index.ts`. Компоненты не должны +импортировать отдельные файлы из этой директории. Удалить этот слой можно в +следующей мажорной версии. + +К этому же слою относятся deprecated-алиасы `fonts.primary` и `fonts.secondary`, +а также их преобразование в `fonts.fontFamily.heading` и +`fonts.fontFamily.base`. diff --git a/src/theme/assets/background.json b/src/theme/legacyTokens/background.json similarity index 100% rename from src/theme/assets/background.json rename to src/theme/legacyTokens/background.json diff --git a/src/theme/assets/border.json b/src/theme/legacyTokens/border.json similarity index 100% rename from src/theme/assets/border.json rename to src/theme/legacyTokens/border.json diff --git a/src/theme/assets/customCommon.ts b/src/theme/legacyTokens/customCommon.ts similarity index 100% rename from src/theme/assets/customCommon.ts rename to src/theme/legacyTokens/customCommon.ts diff --git a/src/theme/assets/customDark.ts b/src/theme/legacyTokens/customDark.ts similarity index 100% rename from src/theme/assets/customDark.ts rename to src/theme/legacyTokens/customDark.ts diff --git a/src/theme/assets/customLight.ts b/src/theme/legacyTokens/customLight.ts similarity index 100% rename from src/theme/assets/customLight.ts rename to src/theme/legacyTokens/customLight.ts diff --git a/src/theme/assets/effects.json b/src/theme/legacyTokens/effects.json similarity index 100% rename from src/theme/assets/effects.json rename to src/theme/legacyTokens/effects.json diff --git a/src/theme/assets/global.json b/src/theme/legacyTokens/global.json similarity index 100% rename from src/theme/assets/global.json rename to src/theme/legacyTokens/global.json diff --git a/src/theme/legacyTokens/index.ts b/src/theme/legacyTokens/index.ts new file mode 100644 index 00000000..991912d0 --- /dev/null +++ b/src/theme/legacyTokens/index.ts @@ -0,0 +1,130 @@ +import { InputSize } from './InputSize' +import { ModalSize } from './ModalSize' +import background from './background.json' +import border from './border.json' +import { customCommon } from './customCommon' +import { customDark } from './customDark' +import { customLight } from './customLight' +import effects from './effects.json' +import global from './global.json' +import primaryColors from './primaryColors.json' +import { shadow } from './shadow' +import sizing from './sizing.json' +import spacing from './spacing.json' +import darkTheme from './themeDark.json' +import lightTheme from './themeLight.json' +import typography from './typography.json' + +interface FontFamilyTokens { + base: string + heading: string +} + +export interface LegacyFontAliases { + /** @deprecated Используйте `fonts.fontFamily.heading`. */ + primary: string + /** @deprecated Используйте `fonts.fontFamily.base`. */ + secondary: string +} + +export type FontsConfig = FontFamilyTokens | LegacyFontAliases + +export interface FontsConfigType { + fonts: FontsConfig +} + +export interface LegacyTheme { + /** @deprecated Используйте `semantic` или `components`. */ + background: typeof background + /** @deprecated Используйте `semantic` или `components`. */ + colors: { primary: typeof primaryColors } + /** @deprecated Используйте `semantic` или `components`. */ + border: typeof border + /** @deprecated Используйте `semantic.effects`. */ + effects: typeof effects + /** @deprecated Используйте `semantic`, `components` или `fonts`. */ + global: typeof global + /** @deprecated Используйте `semantic` или `components`. */ + sizing: typeof sizing + /** @deprecated Используйте `semantic` или `components`. */ + spacing: typeof spacing + /** @deprecated Используйте `semantic` или `components`. */ + theme: typeof lightTheme & { + custom: typeof customLight + InputSize: typeof InputSize + ModalSize: typeof ModalSize + } + /** @deprecated Используйте `fonts`. */ + typography: typeof typography + /** @deprecated Используйте `semantic` или `components`. */ + custom: typeof customCommon + /** @deprecated Используйте `semantic.effects`. */ + shadow: typeof shadow +} + +const commonLegacyTokens: Omit = { + background, + colors: { primary: primaryColors }, + border, + effects, + global, + sizing, + spacing, + typography, + custom: customCommon, + shadow, +} + +const legacyThemes = { + light: { + theme: { ...lightTheme, InputSize, ModalSize, custom: customLight }, + ...commonLegacyTokens, + }, + dark: { + theme: { ...darkTheme, InputSize, ModalSize, custom: customDark }, + ...commonLegacyTokens, + }, +} satisfies Record<'light' | 'dark', LegacyTheme> + +const toFontFamilyTokens = (fonts: FontsConfig): FontFamilyTokens => { + if (!('primary' in fonts)) { + return fonts + } + + const aliases = fonts as Record<'primary' | 'secondary', string> + + return { base: aliases.secondary, heading: aliases.primary } +} + +const toLegacyFontAliases = ({ + base, + heading, +}: FontFamilyTokens): LegacyFontAliases => ({ + primary: heading, + secondary: base, +}) + +export const applyFontConfig = < + T extends { fonts: { fontFamily: FontFamilyTokens } }, +>( + theme: T, + fonts: FontsConfig +) => { + const fontFamily = { ...theme.fonts.fontFamily, ...toFontFamilyTokens(fonts) } + + return { + ...theme, + fonts: { ...theme.fonts, fontFamily, ...toLegacyFontAliases(fontFamily) }, + } +} + +export const withLegacyTokens = < + T extends { fonts: { fontFamily: FontFamilyTokens } }, +>( + theme: T, + colorScheme: keyof typeof legacyThemes +) => ({ + ...theme, + ...legacyThemes[colorScheme], + fonts: { ...theme.fonts, ...toLegacyFontAliases(theme.fonts.fontFamily) }, +}) diff --git a/src/theme/assets/primaryColors.json b/src/theme/legacyTokens/primaryColors.json similarity index 100% rename from src/theme/assets/primaryColors.json rename to src/theme/legacyTokens/primaryColors.json diff --git a/src/theme/assets/shadow.ts b/src/theme/legacyTokens/shadow.ts similarity index 100% rename from src/theme/assets/shadow.ts rename to src/theme/legacyTokens/shadow.ts diff --git a/src/theme/assets/sizing.json b/src/theme/legacyTokens/sizing.json similarity index 100% rename from src/theme/assets/sizing.json rename to src/theme/legacyTokens/sizing.json diff --git a/src/theme/assets/spacing.json b/src/theme/legacyTokens/spacing.json similarity index 100% rename from src/theme/assets/spacing.json rename to src/theme/legacyTokens/spacing.json diff --git a/src/theme/assets/themeDark.json b/src/theme/legacyTokens/themeDark.json similarity index 100% rename from src/theme/assets/themeDark.json rename to src/theme/legacyTokens/themeDark.json diff --git a/src/theme/assets/themeLight.json b/src/theme/legacyTokens/themeLight.json similarity index 100% rename from src/theme/assets/themeLight.json rename to src/theme/legacyTokens/themeLight.json diff --git a/src/theme/assets/typography.json b/src/theme/legacyTokens/typography.json similarity index 100% rename from src/theme/assets/typography.json rename to src/theme/legacyTokens/typography.json diff --git a/src/theme/lightTheme.ts b/src/theme/lightTheme.ts index e3c80bfb..a39341e9 100644 --- a/src/theme/lightTheme.ts +++ b/src/theme/lightTheme.ts @@ -1,14 +1 @@ -import { InputSize } from './assets/InputSize' -import { ModalSize } from './assets/ModalSize' -import { customLight } from './assets/customLight' -import lightThemeAssets from './assets/themeLight.json' -import { commonTheme } from './commonTheme' -import lightSemanticColorSchemeTokens from './tokens/semantic/colorScheme/light.json' -import type { ThemeType } from './types' - -export const lightTheme: ThemeType = { - semantic: { colorScheme: lightSemanticColorSchemeTokens }, - theme: { ...lightThemeAssets, InputSize, ModalSize, custom: customLight }, - ...commonTheme, - fonts: { primary: 'TT Fellows', secondary: 'Noto Sans' }, -} +export { lightTheme } from './themes' diff --git a/src/theme/themes.ts b/src/theme/themes.ts new file mode 100644 index 00000000..9f55ed97 --- /dev/null +++ b/src/theme/themes.ts @@ -0,0 +1,29 @@ +import { withLegacyTokens } from './legacyTokens' +import { componentTokens, fontTokens, semanticTokens } from './tokens' +import darkSemanticColorSchemeTokens from './tokens/semantic/colorScheme/dark.json' +import lightSemanticColorSchemeTokens from './tokens/semantic/colorScheme/light.json' +import type { RuntimeTheme, ThemeType } from './types' + +const createRuntimeTheme = ( + colorScheme: RuntimeTheme['semantic']['colorScheme'], + components: RuntimeTheme['components'] +): RuntimeTheme => ({ + semantic: { colorScheme, ...semanticTokens }, + components, + fonts: fontTokens, +}) + +const runtimeThemes = { + light: createRuntimeTheme( + lightSemanticColorSchemeTokens, + componentTokens.light + ), + dark: createRuntimeTheme(darkSemanticColorSchemeTokens, componentTokens.dark), +} + +export const lightTheme: ThemeType = withLegacyTokens( + runtimeThemes.light, + 'light' +) + +export const darkTheme: ThemeType = withLegacyTokens(runtimeThemes.dark, 'dark') diff --git a/src/theme/tokens/README.md b/src/theme/tokens/README.md index c4c6c42c..f7dd2729 100644 --- a/src/theme/tokens/README.md +++ b/src/theme/tokens/README.md @@ -1,11 +1,11 @@ # Сгенерированные токены -В публичный `ThemeType.semantic` подключается только выбранный `colorScheme`. -Общие `dimension`, `effects` и `fonts` добавляются во внутреннюю тему Unistyles и -не зависят от цветовой схемы. В неё же добавляются соответствующие светлой или -тёмной теме `components`. В публичные темы и экспорты component- и font-токены -не входят. Всё генерируется из `design-tokens/input/tokens.json` и не -редактируется вручную. +В `ThemeType`, `lightTheme` и `darkTheme` входят выбранный +`semantic.colorScheme`, общие `semantic.dimension`, `semantic.effects`, `fonts` +и соответствующие теме `components`. Отдельно из пакета экспортируются только +общие `semanticTokens`; карты component- и font-токенов остаются внутренними. +Всё генерируется из `design-tokens/input/tokens.json` и не редактируется +вручную. Подробности: [генератор токенов](../../../scripts/token-generator/README.md). diff --git a/src/theme/types.ts b/src/theme/types.ts index c0b3ad20..0402a101 100644 --- a/src/theme/types.ts +++ b/src/theme/types.ts @@ -1,59 +1,39 @@ import type { TextStyle } from 'react-native' -import type { InputSize } from './assets/InputSize' -import type { ModalSize } from './assets/ModalSize' -import type background from './assets/background.json' -import type border from './assets/border.json' -import type { customCommon } from './assets/customCommon' -import type { customLight } from './assets/customLight' -import type effects from './assets/effects.json' -import type global from './assets/global.json' -import type primaryColors from './assets/primaryColors.json' -import type { shadow } from './assets/shadow' -import type sizing from './assets/sizing.json' -import type spacing from './assets/spacing.json' -import type lightTheme from './assets/themeLight.json' -import type typography from './assets/typography.json' +import type { LegacyFontAliases, LegacyTheme } from './legacyTokens' +import type lightComponentTokens from './tokens/components/light.json' import type fontTokens from './tokens/fonts.json' import type lightSemanticColorSchemeTokens from './tokens/semantic/colorScheme/light.json' +import type semanticDimensions from './tokens/semantic/dimensions.json' +import type semanticEffects from './tokens/semantic/effects.json' -export interface ThemeType { - background: typeof background - colors: { primary: typeof primaryColors } - border: typeof border - effects: typeof effects - global: typeof global - sizing: typeof sizing - spacing: typeof spacing - semantic: { colorScheme: typeof lightSemanticColorSchemeTokens } - theme: typeof lightTheme & { - custom: typeof customLight - InputSize: typeof InputSize - ModalSize: typeof ModalSize +export interface RuntimeTheme { + semantic: { + colorScheme: typeof lightSemanticColorSchemeTokens + dimension: typeof semanticDimensions + effects: typeof semanticEffects } - typography: typeof typography - custom: typeof customCommon - shadow: typeof shadow - fonts: FontsConfig + components: typeof lightComponentTokens + fonts: FontTokens } +export type ThemeType = RuntimeTheme & + LegacyTheme & { fonts: FontTokens & LegacyFontAliases } + export enum ThemeVariant { Light = 'Light', Dark = 'Dark', } -export interface FontsConfig { - primary: string - secondary: string -} - -export interface FontsConfigType { - fonts: FontsConfig -} - export type FontTokens = Omit & { fontWeight: Record< keyof typeof fontTokens.fontWeight, TextStyle['fontWeight'] > } + +export type { + FontsConfig, + FontsConfigType, + LegacyFontAliases, +} from './legacyTokens' From b6d6bebd1f725dd54eaa32a0eb9c1c6bd2348192 Mon Sep 17 00:00:00 2001 From: fabulous-unicorn Date: Thu, 6 Aug 2026 10:07:24 +0000 Subject: [PATCH 41/60] chore: release v1.1.0-beta.0 --- CHANGELOG.md | 51 +++++++++++++++++++++++++++++++++++++++++++ ios/CDEKUI/Info.plist | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62a4ed71..87b13ae7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,57 @@ ### ♻️ Рефакторинг +## [1.1.0-beta.0](https://github.com/cdek-it/react-native-ui-kit/compare/v1.0.3...v1.1.0-beta.0) (2026-08-06) + +### 🚀 Новый функционал + +* **Accordion:** подключены сгенерированные токены ([1f05446](https://github.com/cdek-it/react-native-ui-kit/commit/1f05446129b7a224d6417cf700e5ea75f9de196a)) +* **Avatar:** подключены сгенерированные токены ([da7550e](https://github.com/cdek-it/react-native-ui-kit/commit/da7550e4be7bd49f900d17ebe84d10ab90764cb8)) +* **Badge:** подключены сгенерированные токены ([5f534f3](https://github.com/cdek-it/react-native-ui-kit/commit/5f534f326fe44c53b6211ca8c4518540cd160baf)) +* **Button:** подключены сгенерированные токены ([5a619a7](https://github.com/cdek-it/react-native-ui-kit/commit/5a619a7670d0eb56e7591e135c932cd41d7c8a01)) +* **Checkbox:** подключены сгенерированные токены ([706d49f](https://github.com/cdek-it/react-native-ui-kit/commit/706d49fc9e25773dab1cd063d767391b2d6495ac)) +* **Chip:** подключены сгенерированные токены ([7940416](https://github.com/cdek-it/react-native-ui-kit/commit/7940416299438daa6b6cf67f157b2297514bbe30)) +* **Dialog:** подключены сгенерированные токены ([f9acf57](https://github.com/cdek-it/react-native-ui-kit/commit/f9acf579c693ebc7ca62d8d41845eb3369b2e7d2)) +* **Divider:** подключены сгенерированные токены ([55d672f](https://github.com/cdek-it/react-native-ui-kit/commit/55d672f25676d15ac2d8110a554c166730aa602f)) +* **InputSwitch:** подключены сгенерированные токены ([ec5030f](https://github.com/cdek-it/react-native-ui-kit/commit/ec5030fce28a5de6385df38f3564c8c372b32d7d)) +* **Input:** подключены сгенерированные токены ([9e63339](https://github.com/cdek-it/react-native-ui-kit/commit/9e63339502e7ef6e377178b22c93b4bcffd60146)) +* **List:** подключены сгенерированные токены ([1c58202](https://github.com/cdek-it/react-native-ui-kit/commit/1c58202e36086865b9ee5164bd235c4a3fb099e4)) +* **MenuItem:** подключены сгенерированные токены ([74355e6](https://github.com/cdek-it/react-native-ui-kit/commit/74355e666247e0205aacb55f2f6cf2a6552c9a9a)) +* **Message:** подключены сгенерированные токены ([bb9c8de](https://github.com/cdek-it/react-native-ui-kit/commit/bb9c8de54fd30a6c69eef9c3e9716876939f465e)) +* **ProgressBar:** подключены сгенерированные токены ([1628475](https://github.com/cdek-it/react-native-ui-kit/commit/1628475a30b7bc16842b34b14c2998b2612805cb)) +* **ProgressSpinner:** подключены сгенерированные токены ([04fe461](https://github.com/cdek-it/react-native-ui-kit/commit/04fe46136a8ddf3f62c231641ff2ace6dbc85dfe)) +* **RadioButton:** подключены сгенерированные токены ([32bc17f](https://github.com/cdek-it/react-native-ui-kit/commit/32bc17fb083c36e4c830451e125fcd4bb6177643)) +* **Rating:** подключены сгенерированные токены ([1219e43](https://github.com/cdek-it/react-native-ui-kit/commit/1219e43a9068d081a19bcd96021d3d99b36e0f81)) +* **SelectButton:** подключены сгенерированные токены ([5e170ba](https://github.com/cdek-it/react-native-ui-kit/commit/5e170bae3e97cfe7f3604bc819c13f8d00602358)) +* **Skeleton:** подключены сгенерированные токены ([552b857](https://github.com/cdek-it/react-native-ui-kit/commit/552b8572912884b994bfe087c296a86d073868f3)) +* **Slider:** подключены сгенерированные токены ([1be33c0](https://github.com/cdek-it/react-native-ui-kit/commit/1be33c03f156b013228064db2dd2151e08f9f5b1)) +* **Tabs:** подключены сгенерированные токены ([42bf812](https://github.com/cdek-it/react-native-ui-kit/commit/42bf812b09da68e6023c3029749ff6f435007ea5)) +* **Tag:** подключены сгенерированные токены ([6cfc335](https://github.com/cdek-it/react-native-ui-kit/commit/6cfc335f6e06373f320b8d4d30865a30dd75aa05)) +* **Theme:** подключены сгенерированные токены ([8e5a257](https://github.com/cdek-it/react-native-ui-kit/commit/8e5a257cc2c1d90e27ab4e591a9a0ed969d2619b)) +* **Timer:** подключены сгенерированные токены ([0b74c4a](https://github.com/cdek-it/react-native-ui-kit/commit/0b74c4a5b5f030d3797eb4b29e48404af2f2ce3d)) +* **ToggleButton:** подключены сгенерированные токены ([82a4f40](https://github.com/cdek-it/react-native-ui-kit/commit/82a4f409fdda0641dcf001e2704850808e897def)) +* **Typography:** подключены сгенерированные токены ([b5e0ca1](https://github.com/cdek-it/react-native-ui-kit/commit/b5e0ca14ae4a9e77a2efff4e654dc2c937d223a2)) +* добавлен генератор дизайн-токенов ([83048a7](https://github.com/cdek-it/react-native-ui-kit/commit/83048a7bac41a41b516490aab4423f47b2fcd1e5)) +* добавлена генерация токенов шрифтов ([6838bb3](https://github.com/cdek-it/react-native-ui-kit/commit/6838bb37d6e25e2fd7911a55d71ba880648d1cbb)) +* добавлена поддержка focusRing-токенов ([566f0ec](https://github.com/cdek-it/react-native-ui-kit/commit/566f0ecf8b3fe7d0a57f97da04b609abb198309f)) +* добавлена поддержка токенов анимации ([6e81a29](https://github.com/cdek-it/react-native-ui-kit/commit/6e81a2951d00266371a3e4e0060e6139f541414b)) +* добавлены и подключены дизайн-токены ([a6ac14d](https://github.com/cdek-it/react-native-ui-kit/commit/a6ac14dceedd5d29de808896349e9606fce75548)) + +### 🐛 Исправления багов + +* доработан генератор дизайн-токенов ([d5c0ed5](https://github.com/cdek-it/react-native-ui-kit/commit/d5c0ed5be85c5cf6e403132dc1d0e48ef597f191)) +* исправлена нормализация радиусов в токенах ([b1b2b19](https://github.com/cdek-it/react-native-ui-kit/commit/b1b2b197a0e18e9bb3714597856a4ee1d62df2c3)) + +### 🧹 Другое + +* актуализирована документация тем и токенов ([0206449](https://github.com/cdek-it/react-native-ui-kit/commit/020644980ee011cacfcbaf23b2ebee9a5af9f34b)) + +### ♻️ Рефакторинг + +* **theme:** добавлен слой legacy-совместимости ([d55fbde](https://github.com/cdek-it/react-native-ui-kit/commit/d55fbde0f0d058b09bb152d696580845a76d68f2)) +* **tokens:** component-токены скрыты из публичного API ([5c4e4bd](https://github.com/cdek-it/react-native-ui-kit/commit/5c4e4bd087d2b407c498f5100a72a90b1f54b69a)) +* **tokens:** объединены проверка и форматирование генерации ([f60cbd6](https://github.com/cdek-it/react-native-ui-kit/commit/f60cbd61b01dd4d2d8c79247a191fb8f1ab1f5c6)) +* **tokens:** разделены semantic-токены ([8ab1759](https://github.com/cdek-it/react-native-ui-kit/commit/8ab17593587bf96488f9f41a7fae80e395f33431)) * улучшена читаемость конфигурации плагинов ([7e6bba9](https://github.com/cdek-it/react-native-ui-kit/commit/7e6bba95b87d1dc1b3a1fcf2414b6dee91b86c64)) ## [1.0.3](https://github.com/cdek-it/react-native-ui-kit/compare/v1.0.2...v1.0.3) (2026-07-30) diff --git a/ios/CDEKUI/Info.plist b/ios/CDEKUI/Info.plist index 654712ad..a9671707 100644 --- a/ios/CDEKUI/Info.plist +++ b/ios/CDEKUI/Info.plist @@ -68,4 +68,4 @@ UIViewControllerBasedStatusBarAppearance - \ No newline at end of file + From 1183436e2e98f157fbad565704dc0ba19bb5e5ff Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Wed, 12 Aug 2026 19:12:34 +0800 Subject: [PATCH 42/60] =?UTF-8?q?fix(tokens):=20=D0=BE=D0=B1=D0=B2=D0=BE?= =?UTF-8?q?=D0=B4=D0=BA=D0=B0=20Avatar=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2?= =?UTF-8?q?=D0=B5=D0=B4=D0=B5=D0=BD=D0=B0=20=D0=BD=D0=B0=20inverse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/input/tokens.json | 2 +- .../__snapshots__/Avatar.test.tsx.snap | 42 +++++++++---------- src/theme/tokens/components/dark.json | 2 +- src/theme/tokens/components/light.json | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/design-tokens/input/tokens.json b/design-tokens/input/tokens.json index 16993284..d8493c61 100644 --- a/design-tokens/input/tokens.json +++ b/design-tokens/input/tokens.json @@ -1331,7 +1331,7 @@ }, "avatar": { "extend": { - "borderColor": "{color.border.neutral.strong}", + "borderColor": "{color.border.neutral.inverse}", "circle": { "borderRadius": "{dimension.borderRadius.max}" } }, "root": { diff --git a/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap b/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap index 49469718..e1133de7 100644 --- a/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap +++ b/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap @@ -11,7 +11,7 @@ exports[`Avatar component tests Size: custom, shape: circle, type: icon, with cu { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -149,7 +149,7 @@ exports[`Avatar component tests Size: large, shape: circle, type: icon 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -287,7 +287,7 @@ exports[`Avatar component tests Size: large, shape: circle, type: image 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -336,7 +336,7 @@ exports[`Avatar component tests Size: large, shape: circle, type: label 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -389,7 +389,7 @@ exports[`Avatar component tests Size: large, shape: sqare, type: icon 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -525,7 +525,7 @@ exports[`Avatar component tests Size: large, shape: square, type: image 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -572,7 +572,7 @@ exports[`Avatar component tests Size: large, shape: square, type: label 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -623,7 +623,7 @@ exports[`Avatar component tests Size: nomal, shape: circle, type: icon 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -761,7 +761,7 @@ exports[`Avatar component tests Size: normal, shape: circle, type: image 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -810,7 +810,7 @@ exports[`Avatar component tests Size: normal, shape: circle, type: label 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -863,7 +863,7 @@ exports[`Avatar component tests Size: normal, shape: sqare, type: icon 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -999,7 +999,7 @@ exports[`Avatar component tests Size: normal, shape: square, type: image 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -1046,7 +1046,7 @@ exports[`Avatar component tests Size: normal, shape: square, type: label 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -1097,7 +1097,7 @@ exports[`Avatar component tests Size: xlarge, shape: circle, type: icon 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -1235,7 +1235,7 @@ exports[`Avatar component tests Size: xlarge, shape: circle, type: image 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -1284,7 +1284,7 @@ exports[`Avatar component tests Size: xlarge, shape: circle, type: label 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -1337,7 +1337,7 @@ exports[`Avatar component tests Size: xlarge, shape: sqare, type: icon 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -1473,7 +1473,7 @@ exports[`Avatar component tests Size: xlarge, shape: square, type: image 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -1520,7 +1520,7 @@ exports[`Avatar component tests Size: xlarge, shape: square, type: label 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -1571,7 +1571,7 @@ exports[`Avatar component tests With badge, showBadge: false 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", @@ -1624,7 +1624,7 @@ exports[`Avatar component tests With badge, showBadge: true 1`] = ` { "alignItems": "center", "backgroundColor": "#44e858", - "borderColor": "#cecfd2", + "borderColor": "#ffffff", "borderRadius": 14, "borderWidth": 1, "justifyContent": "center", diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json index 3bef7b42..3ecb0258 100644 --- a/src/theme/tokens/components/dark.json +++ b/src/theme/tokens/components/dark.json @@ -156,7 +156,7 @@ } }, "avatar": { - "extend": { "borderColor": "#56595f", "circle": { "borderRadius": 1600 } }, + "extend": { "borderColor": "#2b2e33", "circle": { "borderRadius": 1600 } }, "root": { "width": 32, "height": 32, diff --git a/src/theme/tokens/components/light.json b/src/theme/tokens/components/light.json index be686424..34ad530f 100644 --- a/src/theme/tokens/components/light.json +++ b/src/theme/tokens/components/light.json @@ -156,7 +156,7 @@ } }, "avatar": { - "extend": { "borderColor": "#cecfd2", "circle": { "borderRadius": 1600 } }, + "extend": { "borderColor": "#ffffff", "circle": { "borderRadius": 1600 } }, "root": { "width": 32, "height": 32, From 965d974162597d152c71d21d3506d25ed86f4284 Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Wed, 12 Aug 2026 18:29:53 +0800 Subject: [PATCH 43/60] =?UTF-8?q?fix(tokens):=20=D1=86=D0=B2=D0=B5=D1=82?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=BD=D1=82=D0=B0=20Divider?= =?UTF-8?q?=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=B5=D0=B4=D1=91=D0=BD=20?= =?UTF-8?q?=D0=BD=D0=B0=20fg.muted?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/input/tokens.json | 2 +- .../__tests__/__snapshots__/Divider.test.tsx.snap | 12 ++++++------ src/theme/tokens/components/dark.json | 2 +- src/theme/tokens/components/light.json | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/design-tokens/input/tokens.json b/design-tokens/input/tokens.json index d8493c61..da6a82b5 100644 --- a/design-tokens/input/tokens.json +++ b/design-tokens/input/tokens.json @@ -2716,7 +2716,7 @@ }, "content": { "background": "{color.bg.surface.default.default}", - "color": "{color.fg.default}" + "color": "{color.fg.muted}" }, "root": { "borderColor": "{color.border.neutral.default}" } }, diff --git a/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap b/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap index a632247d..c13e73ca 100644 --- a/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap +++ b/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap @@ -296,7 +296,7 @@ exports[`Divider {"Icon": [Object], "align": "end", "layout": "vertical", "text" meetOrSlice={0} minX={0} minY={0} - stroke="#2b2e33" + stroke="#85888e" strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} @@ -332,7 +332,7 @@ exports[`Divider {"Icon": [Object], "align": "end", "layout": "vertical", "text" } stroke={ { - "payload": 4281019955, + "payload": 4286941326, "type": 0, } } @@ -354,7 +354,7 @@ exports[`Divider {"Icon": [Object], "align": "end", "layout": "vertical", "text" } stroke={ { - "payload": 4281019955, + "payload": 4286941326, "type": 0, } } @@ -490,7 +490,7 @@ exports[`Divider {"Icon": [Object], "align": "start", "layout": "horizontal", "s meetOrSlice={0} minX={0} minY={0} - stroke="#2b2e33" + stroke="#85888e" strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} @@ -526,7 +526,7 @@ exports[`Divider {"Icon": [Object], "align": "start", "layout": "horizontal", "s } stroke={ { - "payload": 4281019955, + "payload": 4286941326, "type": 0, } } @@ -548,7 +548,7 @@ exports[`Divider {"Icon": [Object], "align": "start", "layout": "horizontal", "s } stroke={ { - "payload": 4281019955, + "payload": 4286941326, "type": 0, } } diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json index 3ecb0258..f1f8ee5e 100644 --- a/src/theme/tokens/components/dark.json +++ b/src/theme/tokens/components/dark.json @@ -1106,7 +1106,7 @@ "paddingLeft": 0 } }, - "content": { "background": "#404348", "color": "#ffffff" }, + "content": { "background": "#404348", "color": "#a2a5a9" }, "root": { "borderColor": "#404348" } }, "drawer": { diff --git a/src/theme/tokens/components/light.json b/src/theme/tokens/components/light.json index 34ad530f..402b61a4 100644 --- a/src/theme/tokens/components/light.json +++ b/src/theme/tokens/components/light.json @@ -1106,7 +1106,7 @@ "paddingLeft": 0 } }, - "content": { "background": "#ffffff", "color": "#2b2e33" }, + "content": { "background": "#ffffff", "color": "#85888e" }, "root": { "borderColor": "#e2e2e4" } }, "drawer": { From 0d3ca266425d307b3c4c86fa423f8bdc7e68485e Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Wed, 12 Aug 2026 20:08:29 +0800 Subject: [PATCH 44/60] =?UTF-8?q?fix(Slider):=20=D0=BB=D0=B5=D0=B9=D0=B1?= =?UTF-8?q?=D0=BB=D1=8B=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D0=B9?= =?UTF-8?q?=20=D0=B1=D0=B5=D1=80=D1=83=D1=82=20=D1=86=D0=B2=D0=B5=D1=82=20?= =?UTF-8?q?=D0=B8=D0=B7=20=D1=82=D0=B5=D0=BC=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Slider/Slider.stories.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/Slider/Slider.stories.tsx b/src/components/Slider/Slider.stories.tsx index 08a8ca35..acabcb08 100644 --- a/src/components/Slider/Slider.stories.tsx +++ b/src/components/Slider/Slider.stories.tsx @@ -2,6 +2,8 @@ import type { Meta, StoryObj } from '@storybook/react' import { useState } from 'react' import { Text, View } from 'react-native' +import { StyleSheet } from 'react-native-unistyles' + import { Slider, type SliderProps } from './Slider' const meta: Meta = { @@ -32,8 +34,8 @@ const Template = (args: SliderProps) => { return ( - {positionMinRange.toFixed(0)} - {positionMaxRange.toFixed(0)} + {positionMinRange.toFixed(0)} + {positionMaxRange.toFixed(0)} { - {positionMin.toFixed(0)} + {positionMin.toFixed(0)} { ) } +const styles = StyleSheet.create(({ semantic }) => ({ + label: { color: semantic.colorScheme.color.fg.default }, +})) + export default meta type Story = StoryObj From fbeb57031b940d7a1144c9aede6cdb478a2fef75 Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Wed, 12 Aug 2026 19:26:01 +0800 Subject: [PATCH 45/60] =?UTF-8?q?fix(tokens):=20=D0=B8=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D0=BA=D0=B0=20checked-=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20Checkbox=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2?= =?UTF-8?q?=D0=B5=D0=B4=D0=B5=D0=BD=D0=B0=20=D0=BD=D0=B0=20inverse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/input/tokens.json | 2 +- src/theme/tokens/components/dark.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/design-tokens/input/tokens.json b/design-tokens/input/tokens.json index da6a82b5..e7bafe2f 100644 --- a/design-tokens/input/tokens.json +++ b/design-tokens/input/tokens.json @@ -2146,7 +2146,7 @@ "icon": { "size": "{dimension.size.450}", "color": "{color.fg.active}", - "checkedColor": "{color.fg.on.fill.default}", + "checkedColor": "{color.fg.inverse.default}", "checkedHoverColor": "{color.fg.on.fill.hover}", "disabledColor": "{color.fg.muted}", "sm": { "size": "{dimension.size.350}" }, diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json index f1f8ee5e..805cd7d2 100644 --- a/src/theme/tokens/components/dark.json +++ b/src/theme/tokens/components/dark.json @@ -607,7 +607,7 @@ "icon": { "size": 16, "color": "#f0f0f1", - "checkedColor": "#ffffff", + "checkedColor": "#2b2e33", "checkedHoverColor": "#ffffff", "disabledColor": "#a2a5a9", "sm": { "size": 12 }, From b60dd59e48717e7a2d98d01a50c63fd5e8930e96 Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Wed, 12 Aug 2026 20:33:59 +0800 Subject: [PATCH 46/60] =?UTF-8?q?fix(tokens):=20=D1=81=D0=BA=D1=80=D1=83?= =?UTF-8?q?=D0=B3=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20Dialog=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=BE=20=D1=81=20max?= =?UTF-8?q?=20=D0=BD=D0=B0=20borderRadius.500?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/input/tokens.json | 2 +- .../Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap | 2 +- src/theme/tokens/components/dark.json | 2 +- src/theme/tokens/components/light.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/design-tokens/input/tokens.json b/design-tokens/input/tokens.json index e7bafe2f..da24a7fa 100644 --- a/design-tokens/input/tokens.json +++ b/design-tokens/input/tokens.json @@ -2682,7 +2682,7 @@ "background": "{color.bg.surface.default.default}", "borderColor": "{color.border.neutral.default}", "color": "{color.fg.default}", - "borderRadius": "{dimension.borderRadius.max}", + "borderRadius": "{dimension.borderRadius.500}", "shadow": "{effects.elevation.400}" }, "header": { diff --git a/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap b/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap index 8fd76ec3..c5d35859 100644 --- a/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap +++ b/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap @@ -128,7 +128,7 @@ exports[`Dialog component tests basic dialog with title, body and footer 1`] = ` { "backgroundColor": "#ffffff", "borderColor": "#e2e2e4", - "borderRadius": 1600, + "borderRadius": 20, }, { "maxHeight": 1234, diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json index 805cd7d2..b4aa69da 100644 --- a/src/theme/tokens/components/dark.json +++ b/src/theme/tokens/components/dark.json @@ -1052,7 +1052,7 @@ "background": "#404348", "borderColor": "#404348", "color": "#ffffff", - "borderRadius": 1600, + "borderRadius": 20, "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" }, "header": { diff --git a/src/theme/tokens/components/light.json b/src/theme/tokens/components/light.json index 402b61a4..3c6a59bb 100644 --- a/src/theme/tokens/components/light.json +++ b/src/theme/tokens/components/light.json @@ -1052,7 +1052,7 @@ "background": "#ffffff", "borderColor": "#e2e2e4", "color": "#2b2e33", - "borderRadius": 1600, + "borderRadius": 20, "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" }, "header": { From 09ca74ccae873a4ec1742cde1b11cfafbf5fef95 Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Wed, 12 Aug 2026 20:41:05 +0800 Subject: [PATCH 47/60] =?UTF-8?q?fix(Tabs):=20=D0=B0=D0=BA=D1=82=D0=B8?= =?UTF-8?q?=D0=B2=D0=BD=D0=B0=D1=8F=20=D0=BB=D0=B8=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B2=D1=8B=D1=80=D0=BE=D0=B2=D0=BD=D0=B5=D0=BD=D0=B0=20=D1=81?= =?UTF-8?q?=20=D0=BB=D0=B8=D0=BD=D0=B8=D0=B5=D0=B9=20=D1=82=D0=B0=D0=B1-?= =?UTF-8?q?=D0=BB=D0=B8=D1=81=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/input/tokens.json | 2 +- src/components/Tabs/Tabs.tsx | 9 +++++---- .../Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap | 12 ++++++------ src/theme/tokens/components/dark.json | 2 +- src/theme/tokens/components/light.json | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/design-tokens/input/tokens.json b/design-tokens/input/tokens.json index da24a7fa..c86d15c2 100644 --- a/design-tokens/input/tokens.json +++ b/design-tokens/input/tokens.json @@ -4444,7 +4444,7 @@ }, "root": { "transitionDuration": "{effects.transition.duration.200}" }, "tablist": { - "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.none}", + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.200} {dimension.borderWidth.none}", "background": "transparent", "borderColor": "{color.border.neutral.default}" }, diff --git a/src/components/Tabs/Tabs.tsx b/src/components/Tabs/Tabs.tsx index 3c94a134..9be5a3d3 100644 --- a/src/components/Tabs/Tabs.tsx +++ b/src/components/Tabs/Tabs.tsx @@ -91,18 +91,19 @@ export const Tabs = memo( } ) -const styles = StyleSheet.create(({ components, semantic }) => ({ +const styles = StyleSheet.create(({ components }) => ({ container: { flexDirection: 'row', gap: components.tabs.tab.margin, - borderBottomWidth: semantic.dimension.borderWidth[100], + borderBottomWidth: components.tabs.tablist.borderBottomWidth, borderColor: components.tabs.tablist.borderColor, }, line: { position: 'absolute', - bottom: 0, - height: semantic.dimension.borderWidth[200], + // Линия ложится поверх границы таб-листа: отрицательный сдвиг равен её толщине + bottom: components.tabs.activeBar.bottom, + height: components.tabs.activeBar.height, backgroundColor: components.tabs.activeBar.background, }, diff --git a/src/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap b/src/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap index e4a3b881..5fad356f 100644 --- a/src/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap +++ b/src/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap @@ -2114,7 +2114,7 @@ exports[`Tabs component tests disabled 1`] = ` Date: Wed, 12 Aug 2026 19:55:50 +0800 Subject: [PATCH 48/60] =?UTF-8?q?fix(tokens):=20=D1=84=D0=BE=D0=BD=20?= =?UTF-8?q?=D1=82=D1=80=D0=B5=D0=BA=D0=B0=20InputSwitch=20=D0=B2=20=D1=82?= =?UTF-8?q?=D1=91=D0=BC=D0=BD=D0=BE=D0=B9=20=D1=82=D0=B5=D0=BC=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D0=B2=D0=B5=D0=B4=D1=91=D0=BD=20=D0=BA=20?= =?UTF-8?q?=D0=BC=D0=B0=D0=BA=D0=B5=D1=82=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/input/tokens.json | 8 ++++---- src/theme/tokens/components/dark.json | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/design-tokens/input/tokens.json b/design-tokens/input/tokens.json index c86d15c2..080ce5c0 100644 --- a/design-tokens/input/tokens.json +++ b/design-tokens/input/tokens.json @@ -5102,10 +5102,10 @@ }, "root": { "background": "{color.bg.neutral.medium.active}", - "checkedBackground": "{color.bg.surface.canvas.default}", - "checkedHoverBackground": "{color.bg.surface.canvas.hover}", - "disabledBackground": "{color.bg.neutral.strong.hover}", - "hoverBackground": "{color.bg.surface.raised.active}" + "checkedBackground": "{color.bg.neutral.strong.default}", + "checkedHoverBackground": "{color.bg.neutral.strong.hover}", + "disabledBackground": "{color.bg.surface.canvas.hover}", + "hoverBackground": "{color.bg.neutral.medium.strong}" } } }, diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json index 9b640339..16dea6bc 100644 --- a/src/theme/tokens/components/dark.json +++ b/src/theme/tokens/components/dark.json @@ -2813,9 +2813,9 @@ }, "root": { "background": "#6d7076", - "checkedBackground": "#2b2e33", - "checkedHoverBackground": "#404348", - "disabledBackground": "#e2e2e4", + "checkedBackground": "#f0f0f1", + "checkedHoverBackground": "#e2e2e4", + "disabledBackground": "#404348", "hoverBackground": "#85888e" } }, From 3b20ea949222fcf8537141d7aaaaef2fb3326ee5 Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Wed, 12 Aug 2026 19:56:41 +0800 Subject: [PATCH 49/60] =?UTF-8?q?fix(tokens):=20=D1=84=D0=BE=D0=BD=20?= =?UTF-8?q?=D1=80=D1=83=D1=87=D0=BA=D0=B8=20InputSwitch=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B2=D0=B5=D0=B4=D1=91=D0=BD=20=D0=BD=D0=B0=20sem?= =?UTF-8?q?antic-=D1=80=D0=BE=D0=BB=D0=B8=20=D0=BF=D0=BE=20=D0=BC=D0=B0?= =?UTF-8?q?=D0=BA=D0=B5=D1=82=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/input/tokens.json | 18 +++++++++--------- src/theme/tokens/components/dark.json | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/design-tokens/input/tokens.json b/design-tokens/input/tokens.json index 080ce5c0..4f26c240 100644 --- a/design-tokens/input/tokens.json +++ b/design-tokens/input/tokens.json @@ -5077,11 +5077,11 @@ "checkedHoverBackground": "{color.bg.neutral.strong.hover}" }, "handle": { - "background": "{color.bg.surface.raised.default}", - "hoverBackground": "{color.bg.surface.raised.default}", + "background": "{color.fg.on.fill.default}", + "hoverBackground": "{color.fg.on.fill.default}", "disabledBackground": "{color.bg.neutral.medium.strong}", - "checkedBackground": "{color.bg.surface.raised.default}", - "checkedHoverBackground": "{color.bg.surface.raised.default}", + "checkedBackground": "{color.fg.inverse.active}", + "checkedHoverBackground": "{color.fg.inverse.active}", "color": "{color.fg.default}", "hoverColor": "{color.fg.default}", "checkedColor": "{color.fg.default}", @@ -5090,14 +5090,14 @@ }, "dark": { "handle": { - "background": "{color.bg.surface.raised.default}", - "checkedBackground": "{color.bg.surface.raised.default}", + "background": "{color.fg.on.fill.default}", + "checkedBackground": "{color.fg.inverse.active}", "checkedColor": "{color.fg.inverse.focus}", - "checkedHoverBackground": "{color.bg.surface.raised.default}", + "checkedHoverBackground": "{color.fg.inverse.active}", "checkedHoverColor": "{color.fg.on.brand.hover}", "color": "{color.fg.inverse.default}", - "disabledBackground": "{color.bg.surface.raised.active}", - "hoverBackground": "{color.bg.surface.raised.default}", + "disabledBackground": "{color.bg.neutral.medium.strong}", + "hoverBackground": "{color.fg.on.fill.default}", "hoverColor": "{color.fg.on.brand.hover}" }, "root": { diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json index 16dea6bc..9b6b1109 100644 --- a/src/theme/tokens/components/dark.json +++ b/src/theme/tokens/components/dark.json @@ -2801,14 +2801,14 @@ "toggleswitch": { "colorScheme": { "handle": { - "background": "#56595f", - "checkedBackground": "#56595f", + "background": "#ffffff", + "checkedBackground": "#181a1f", "checkedColor": "#2b2e33", - "checkedHoverBackground": "#56595f", + "checkedHoverBackground": "#181a1f", "checkedHoverColor": "#2b2e33", "color": "#2b2e33", "disabledBackground": "#85888e", - "hoverBackground": "#56595f", + "hoverBackground": "#ffffff", "hoverColor": "#2b2e33" }, "root": { From db6ce3ca5d0654a3c2bcc545f98451381dfa3e2e Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Wed, 12 Aug 2026 19:58:36 +0800 Subject: [PATCH 50/60] =?UTF-8?q?fix(InputSwitch):=20=D1=80=D1=83=D1=87?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B2=20disabled=20=D0=B1=D0=B5=D1=80=D1=91?= =?UTF-8?q?=D1=82=20=D1=86=D0=B2=D0=B5=D1=82=20=D0=B8=D0=B7=20=D1=82=D0=BE?= =?UTF-8?q?=D0=BA=D0=B5=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Input/InputSwitch/InputSwitch.tsx | 2 +- .../__snapshots__/InputSwitch.test.tsx.snap | 32 +++++++++---------- .../InputSwitch/styles/useHandleStyles.ts | 32 +++++++++++++++---- 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/components/Input/InputSwitch/InputSwitch.tsx b/src/components/Input/InputSwitch/InputSwitch.tsx index bb06abf2..8c27dc2c 100644 --- a/src/components/Input/InputSwitch/InputSwitch.tsx +++ b/src/components/Input/InputSwitch/InputSwitch.tsx @@ -21,7 +21,7 @@ export const InputSwitch = memo( }) => { const { containerStyle, sliderStyle, onPressIn, onPressOut } = useSliderStyles(checked, disabled, danger) - const { handleStyle } = useHandleStyles(checked) + const { handleStyle } = useHandleStyles(checked, disabled) const handlePress = useCallback(() => { onCheckedChange?.(!checked) diff --git a/src/components/Input/InputSwitch/__tests__/__snapshots__/InputSwitch.test.tsx.snap b/src/components/Input/InputSwitch/__tests__/__snapshots__/InputSwitch.test.tsx.snap index 9b89404e..5e788d96 100644 --- a/src/components/Input/InputSwitch/__tests__/__snapshots__/InputSwitch.test.tsx.snap +++ b/src/components/Input/InputSwitch/__tests__/__snapshots__/InputSwitch.test.tsx.snap @@ -321,7 +321,7 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#ffffff"", + "backgroundColor": ""#85888e"", "borderRadius": 1600, "height": 16, "left": "3", @@ -333,7 +333,7 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - style={ [ { - "backgroundColor": "#ffffff", + "backgroundColor": "#85888e", "borderRadius": 1600, "height": 16, "left": 3, @@ -437,7 +437,7 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#ffffff"", + "backgroundColor": ""#85888e"", "borderRadius": 1600, "height": 16, "left": "3", @@ -449,7 +449,7 @@ exports[`InputSwitch component tests checked - false, danger - false, disabled - style={ [ { - "backgroundColor": "#ffffff", + "backgroundColor": "#85888e", "borderRadius": 1600, "height": 16, "left": 3, @@ -785,7 +785,7 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - } jestInlineStyle={ { - "backgroundColor": ""#ffffff"", + "backgroundColor": ""#85888e"", "borderRadius": 1600, "height": 16, "left": "3", @@ -797,7 +797,7 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - style={ [ { - "backgroundColor": "#ffffff", + "backgroundColor": "#85888e", "borderRadius": 1600, "height": 16, "left": 3, @@ -901,7 +901,7 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - } jestInlineStyle={ { - "backgroundColor": ""#ffffff"", + "backgroundColor": ""#85888e"", "borderRadius": 1600, "height": 16, "left": "3", @@ -913,7 +913,7 @@ exports[`InputSwitch component tests checked - false, danger - true, disabled - style={ [ { - "backgroundColor": "#ffffff", + "backgroundColor": "#85888e", "borderRadius": 1600, "height": 16, "left": 3, @@ -1249,7 +1249,7 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#ffffff"", + "backgroundColor": ""#85888e"", "borderRadius": 1600, "height": 16, "left": "19", @@ -1261,7 +1261,7 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - style={ [ { - "backgroundColor": "#ffffff", + "backgroundColor": "#85888e", "borderRadius": 1600, "height": 16, "left": 19, @@ -1365,7 +1365,7 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - } jestInlineStyle={ { - "backgroundColor": ""#ffffff"", + "backgroundColor": ""#85888e"", "borderRadius": 1600, "height": 16, "left": "19", @@ -1377,7 +1377,7 @@ exports[`InputSwitch component tests checked - true, danger - false, disabled - style={ [ { - "backgroundColor": "#ffffff", + "backgroundColor": "#85888e", "borderRadius": 1600, "height": 16, "left": 19, @@ -1713,7 +1713,7 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t } jestInlineStyle={ { - "backgroundColor": ""#ffffff"", + "backgroundColor": ""#85888e"", "borderRadius": 1600, "height": 16, "left": "19", @@ -1725,7 +1725,7 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t style={ [ { - "backgroundColor": "#ffffff", + "backgroundColor": "#85888e", "borderRadius": 1600, "height": 16, "left": 19, @@ -1829,7 +1829,7 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t } jestInlineStyle={ { - "backgroundColor": ""#ffffff"", + "backgroundColor": ""#85888e"", "borderRadius": 1600, "height": 16, "left": "19", @@ -1841,7 +1841,7 @@ exports[`InputSwitch component tests checked - true, danger - true, disabled - t style={ [ { - "backgroundColor": "#ffffff", + "backgroundColor": "#85888e", "borderRadius": 1600, "height": 16, "left": 19, diff --git a/src/components/Input/InputSwitch/styles/useHandleStyles.ts b/src/components/Input/InputSwitch/styles/useHandleStyles.ts index 93287f19..bf7e4e68 100644 --- a/src/components/Input/InputSwitch/styles/useHandleStyles.ts +++ b/src/components/Input/InputSwitch/styles/useHandleStyles.ts @@ -4,7 +4,7 @@ import { useSharedValue, withTiming } from 'react-native-reanimated' import { StyleSheet } from 'react-native-unistyles' -export const useHandleStyles = (checked: boolean) => { +export const useHandleStyles = (checked: boolean, disabled: boolean) => { const styles = handleStyles const handleOnLeft = styles.handleOn.left const handleOffLeft = styles.handleOff.left @@ -15,23 +15,39 @@ export const useHandleStyles = (checked: boolean) => { ) const calculateHandleBackground = useCallback( - (checked: boolean) => - checked ? styles.handleOn.backgroundColor : styles.handle.backgroundColor, - [styles.handle.backgroundColor, styles.handleOn.backgroundColor] + (checked: boolean, disabled: boolean) => { + if (disabled) { + return styles.handleDisabled.backgroundColor + } + + return checked + ? styles.handleOn.backgroundColor + : styles.handle.backgroundColor + }, + [ + styles.handle.backgroundColor, + styles.handleDisabled.backgroundColor, + styles.handleOn.backgroundColor, + ] ) const handleLeftPosition = useSharedValue( calculateHandleLeftPosition(checked) ) - const handleBackground = useSharedValue(calculateHandleBackground(checked)) + const handleBackground = useSharedValue( + calculateHandleBackground(checked, disabled) + ) useEffect(() => { handleLeftPosition.value = withTiming(calculateHandleLeftPosition(checked)) - handleBackground.value = withTiming(calculateHandleBackground(checked)) + handleBackground.value = withTiming( + calculateHandleBackground(checked, disabled) + ) }, [ calculateHandleBackground, calculateHandleLeftPosition, checked, + disabled, handleLeftPosition, handleBackground, ]) @@ -63,6 +79,10 @@ const handleStyles = StyleSheet.create(({ components: { toggleswitch } }) => ({ left: toggleswitch.root.gap - toggleswitch.root.borderWidth, }, + handleDisabled: { + backgroundColor: toggleswitch.colorScheme.handle.disabledBackground, + }, + handleOn: { backgroundColor: toggleswitch.colorScheme.handle.checkedBackground, left: From b8c4978b2e2ca7fdf201c8a116840b2442d1a7af Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Thu, 13 Aug 2026 15:52:30 +0300 Subject: [PATCH 51/60] =?UTF-8?q?docs:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BD=D0=B0=D0=B2=D1=8B=D0=BA=20UI=20Kit?= =?UTF-8?q?=20Figma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agents/skills/ui-kit-figma/SKILL.md | 81 +++++++++++++++++++ .../skills/ui-kit-figma/agents/openai.yaml | 6 ++ .agents/skills/ui-kit-testing/SKILL.md | 18 +++-- .../references/test-authoring.md | 13 +-- AGENTS.md | 7 +- 5 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 .agents/skills/ui-kit-figma/SKILL.md create mode 100644 .agents/skills/ui-kit-figma/agents/openai.yaml diff --git a/.agents/skills/ui-kit-figma/SKILL.md b/.agents/skills/ui-kit-figma/SKILL.md new file mode 100644 index 00000000..bc19baca --- /dev/null +++ b/.agents/skills/ui-kit-figma/SKILL.md @@ -0,0 +1,81 @@ +--- +name: ui-kit-figma +description: > + Implement or sync React Native Prime UI Kit components from Figma + specifications. Use when a Figma node is provided, or when component variants, + local theme-token bindings, documentation links, or Storybook states must be + aligned with Figma. This is read-only toward Figma. +--- + +# UI Kit Figma + +Translate Figma component specifications into this repository's public API, +Unistyles implementation, local tokens, tests, and Storybook conventions. Use +the Figma design-to-code skill for tool workflow and `ui-kit-testing` when tests +change. + +## Workflow + +1. Inspect the component source, public types and barrels, nearest tests and + stories, and relevant files under `src/theme/tokens`. +2. Call Figma design context on the exact component or variant frame. If a page + or section returns sparse context, use metadata only to locate the inner + frame, then call design context on that frame. +3. Read variable definitions for the target frame and map each relevant Figma + variable to the existing runtime theme path. +4. Implement the smallest compatible source change, following the nearest + component pattern and root `AGENTS.md`. +5. Update focused behavioral tests and representative Storybook scenarios when + the public contract or material variants change. +6. Update the component documentation link when its exact Figma frame is known. +7. Run the verification required by root `AGENTS.md`. + +## Token Mapping + +- Treat Figma variable bindings as the source of token intent. Treat resolved + pixel and color values as inspection data, not values to copy into source. +- Reuse tokens from `src/theme/tokens`; do not hardcode a resolved value when a + matching local token exists. +- Prefer a component token when Figma explicitly binds the property to that + component variable. Use a semantic token only when the design intent is + semantic or no component binding exists. +- Do not edit generated token JSON or token-generator output unless the user + explicitly includes token-source changes in scope. +- Do not silently replace a missing component token with an approximate semantic + token. Report the gap and distinguish a component implementation change from a + token-source change. +- Apply severity, size, state, and theme bindings to every affected layer, not + only the outer container. Check text, background, border, icon, and shape + tokens independently. + +## Documentation Links + +- Link a component to its exact Figma component or variant frame, not merely the + file, page, or broad section containing it. +- In a bulk link update, inventory the component documentation first. Update + only confidently matched frames and keep unresolved components explicit. +- Before a requested commit, report updated links first and unresolved links + second. Commit only when the user explicitly asks. + +## Storybook + +- Model independently meaningful usage scenarios and interactions. Use controls + for simple variant axes that do not need dedicated documentation. +- Create separate stories or a composed comparison only when the scenario or + comparison itself adds documentation value. Do not impose a fixed number or + layout of stories per component. +- Keep every story's props valid for discriminated unions. Do not expose a + control that can create an invalid prop combination. +- Hide non-editable or internally composed props with + `parameters.controls.exclude`. Do not use `control: false` with React Native + on-device controls because it renders as `Invalid type`. +- Prefer `.tsx` when a story needs JSX composition. If an existing `.ts` file + must remain `.ts`, use `createElement` and construct typed discriminated props + before passing them to the component. + +## Tests + +Use `ui-kit-testing`. Assert rendered data, interaction logic, callbacks, +controlled behavior, accessibility, and public contracts. Do not assert exact +theme-token values, dimensions, colors, or style objects to prove a Figma +mapping. diff --git a/.agents/skills/ui-kit-figma/agents/openai.yaml b/.agents/skills/ui-kit-figma/agents/openai.yaml new file mode 100644 index 00000000..d5c000d2 --- /dev/null +++ b/.agents/skills/ui-kit-figma/agents/openai.yaml @@ -0,0 +1,6 @@ +interface: + display_name: 'UI Kit Figma' + short_description: 'Sync UI Kit components from Figma tokens' + default_prompt: + 'Use $ui-kit-figma to implement or sync a UI Kit component from its Figma + specification.' diff --git a/.agents/skills/ui-kit-testing/SKILL.md b/.agents/skills/ui-kit-testing/SKILL.md index 7f89c652..31ef73ae 100644 --- a/.agents/skills/ui-kit-testing/SKILL.md +++ b/.agents/skills/ui-kit-testing/SKILL.md @@ -2,9 +2,8 @@ name: ui-kit-testing description: > Write or refactor React Native Prime UI Kit Jest and RNTL tests for - components, hooks, controlled behavior, timers, animations, snapshots, - accessibility, and public TypeScript contracts. Do not use for whole-suite - audits + components, hooks, controlled behavior, timers, animations, accessibility, and + public TypeScript contracts. Do not use for whole-suite audits --- # UI Kit Testing @@ -18,8 +17,8 @@ inspect the implementation and nearest tests before choosing helpers or mocks. 1. Search existing tests and Jest setup before adding a helper, mock, provider, timer utility, or console suppression 2. Load only the references required by the test: - - test cases, render helpers, selectors, accessibility, snapshots, types, or - naming: `references/test-authoring.md` + - test cases, render helpers, selectors, accessibility, types, or naming: + `references/test-authoring.md` - child, external, native, animated, or console mocks: `references/mocks-and-native-ui.md` - timers, debounce, animations, delayed updates, or manual promises: @@ -34,6 +33,15 @@ inspect the implementation and nearest tests before choosing helpers or mocks. 5. Before finishing, remove avoidable mocks, oversized helpers, redundant waits, and assertions that do not prove the public contract +## Assertion Boundaries + +- Assert rendered data, presence or absence, callbacks, controlled behavior, + accessibility, and public contracts +- Do not assert exact colors, dimensions, theme-token values, or style objects +- Do not add or update snapshots to verify component appearance or structure. + Replace affected visual snapshots with explicit behavioral assertions +- Use the normal build to validate public TypeScript contracts and token access + ## Verification Run focused Jest and the applicable build or lint checks from `AGENTS.md`. diff --git a/.agents/skills/ui-kit-testing/references/test-authoring.md b/.agents/skills/ui-kit-testing/references/test-authoring.md index a8de0471..726bb857 100644 --- a/.agents/skills/ui-kit-testing/references/test-authoring.md +++ b/.agents/skills/ui-kit-testing/references/test-authoring.md @@ -1,7 +1,8 @@ # Test Authoring Read this reference when creating or changing test cases, render helpers, -selectors, accessibility assertions, snapshots, public types, or test names. +selectors, accessibility assertions, public types, test names, or replacing +snapshots with behavioral assertions. ## Placement And Helpers @@ -37,7 +38,9 @@ normal build. ## Snapshots -Snapshot only small, stable output whose complete structure is the behavior. -Prefer explicit assertions for interaction, state, accessibility, layout, and -animations. Update snapshots only for intentional UI changes. Do not snapshot -mocked child trees, large style objects, or ordinary prop forwarding. +Do not add or update snapshots for component appearance, structure, styles, or +theme-token values. When a change invalidates a visual snapshot, replace it with +explicit assertions for rendered data, presence or absence, interaction, +controlled state, callbacks, or accessibility. Use a snapshot only when the user +explicitly requests one and the contract cannot be stated more clearly with +behavioral assertions. diff --git a/AGENTS.md b/AGENTS.md index e1dd105d..f3003419 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,8 +15,11 @@ Use only top-level skills under `.agents/skills/`; nested `vendor/` skills are source material, not runtime instructions. - Use `$ui-kit-testing` to write or refactor focused Jest/RNTL tests, including - controlled behavior, accessibility, mocks, timers, animations, snapshots, and - public TypeScript contracts. + controlled behavior, accessibility, mocks, timers, animations, and public + TypeScript contracts. +- Use `$ui-kit-figma` to implement or sync components from Figma, map design + variables to local theme tokens, and align material variants and Storybook + scenarios. - Use `$ui-kit-review` for diffs and local changes or explicit architecture, onboarding, test-suite, debt, health, agent-instruction, and diagnostic audits. It is read-only unless the user requests fixes. From 436561541bbb090d77640fbbc8d38dc0626d4425 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Fri, 14 Aug 2026 11:03:59 +0300 Subject: [PATCH 52/60] =?UTF-8?q?docs(skill):=20=D0=B7=D0=B0=D0=BF=D1=80?= =?UTF-8?q?=D0=B5=D1=89=D0=B5=D0=BD=D0=BE=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=8F=D1=82=D1=8C=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D1=82?= =?UTF-8?q?=D0=BE=D0=BA=D0=B5=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agents/skills/ui-kit-figma/SKILL.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.agents/skills/ui-kit-figma/SKILL.md b/.agents/skills/ui-kit-figma/SKILL.md index bc19baca..56709c71 100644 --- a/.agents/skills/ui-kit-figma/SKILL.md +++ b/.agents/skills/ui-kit-figma/SKILL.md @@ -34,16 +34,18 @@ change. - Treat Figma variable bindings as the source of token intent. Treat resolved pixel and color values as inspection data, not values to copy into source. +- Treat `design-tokens/input/tokens.json` as the latest immutable export from + the designer. Never edit it during component or Figma synchronization work. +- Treat `src/theme/tokens/**` as immutable generated output. Never edit or + regenerate these files during component or Figma synchronization work. - Reuse tokens from `src/theme/tokens`; do not hardcode a resolved value when a matching local token exists. - Prefer a component token when Figma explicitly binds the property to that component variable. Use a semantic token only when the design intent is semantic or no component binding exists. -- Do not edit generated token JSON or token-generator output unless the user - explicitly includes token-source changes in scope. -- Do not silently replace a missing component token with an approximate semantic - token. Report the gap and distinguish a component implementation change from a - token-source change. +- If an exact Figma value has no matching existing token, do not hardcode it, + change token files, or silently substitute an approximate token. Report the + gap and explain which part cannot be matched exactly with the current tokens. - Apply severity, size, state, and theme bindings to every affected layer, not only the outer container. Check text, background, border, icon, and shape tokens independently. From 16f40c304b1b12ea9c823953fb52f8764f951a27 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Thu, 13 Aug 2026 16:08:14 +0300 Subject: [PATCH 53/60] =?UTF-8?q?docs:=20=D0=B7=D0=B0=D0=BA=D1=80=D0=B5?= =?UTF-8?q?=D0=BF=D0=BB=D1=91=D0=BD=20=D1=80=D1=83=D1=81=D1=81=D0=BA=D0=B8?= =?UTF-8?q?=D0=B9=20=D1=8F=D0=B7=D1=8B=D0=BA=20=D1=81=D0=BE=D0=BE=D0=B1?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B8?= =?UTF-8?q?=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index f3003419..5ec527aa 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -52,7 +52,8 @@ Do not load every skill preemptively; use the one matching the request. ## Git Do not commit or push unless explicitly asked. Use Conventional Commits for -requested commits. +requested commits. Keep the conventional type and optional scope in English; +write the commit subject in Russian. ## Safety From c34942aaa49128adde91bc20248061d03392651c Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Thu, 13 Aug 2026 15:08:01 +0300 Subject: [PATCH 54/60] =?UTF-8?q?chore(tokens):=20=D0=BE=D0=B1=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD?= =?UTF-8?q?=D1=8B=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design-tokens/input/tokens.json | 42 +++++++++++++------------- src/theme/tokens/components/dark.json | 30 +++++++++--------- src/theme/tokens/components/light.json | 8 ++--- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/design-tokens/input/tokens.json b/design-tokens/input/tokens.json index 4f26c240..0b157a6d 100644 --- a/design-tokens/input/tokens.json +++ b/design-tokens/input/tokens.json @@ -1331,14 +1331,14 @@ }, "avatar": { "extend": { - "borderColor": "{color.border.neutral.inverse}", + "borderColor": "{color.border.neutral.strong}", "circle": { "borderRadius": "{dimension.borderRadius.max}" } }, "root": { "width": "{dimension.size.900}", "height": "{dimension.size.900}", "fontSize": "{fonts.fontSize.300}", - "color": "{color.fg.default}", + "color": "{color.fg.on.brand.default}", "background": "{color.bg.brand.strong.default}", "borderRadius": "{dimension.borderRadius.400}" }, @@ -1427,7 +1427,7 @@ "color": "{color.fg.default}" }, "success": { - "background": "{color.bg.brand.strong.active}", + "background": "{color.bg.status.success.strong.default}", "color": "{color.fg.on.status.success.default}" }, "warn": { @@ -2146,7 +2146,7 @@ "icon": { "size": "{dimension.size.450}", "color": "{color.fg.active}", - "checkedColor": "{color.fg.inverse.default}", + "checkedColor": "{color.fg.on.fill.default}", "checkedHoverColor": "{color.fg.on.fill.hover}", "disabledColor": "{color.fg.muted}", "sm": { "size": "{dimension.size.350}" }, @@ -2679,10 +2679,10 @@ "backdrop": "{color.bg.surface.backdrop}" }, "root": { - "background": "{color.bg.surface.default.default}", + "background": "{color.bg.surface.raised.default}", "borderColor": "{color.border.neutral.default}", "color": "{color.fg.default}", - "borderRadius": "{dimension.borderRadius.500}", + "borderRadius": "{dimension.borderRadius.max}", "shadow": "{effects.elevation.400}" }, "header": { @@ -2716,7 +2716,7 @@ }, "content": { "background": "{color.bg.surface.default.default}", - "color": "{color.fg.muted}" + "color": "{color.fg.default}" }, "root": { "borderColor": "{color.border.neutral.default}" } }, @@ -4444,7 +4444,7 @@ }, "root": { "transitionDuration": "{effects.transition.duration.200}" }, "tablist": { - "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.200} {dimension.borderWidth.none}", + "borderWidth": "{dimension.borderWidth.none} {dimension.borderWidth.none} {dimension.borderWidth.100} {dimension.borderWidth.none}", "background": "transparent", "borderColor": "{color.border.neutral.default}" }, @@ -5077,11 +5077,11 @@ "checkedHoverBackground": "{color.bg.neutral.strong.hover}" }, "handle": { - "background": "{color.fg.on.fill.default}", - "hoverBackground": "{color.fg.on.fill.default}", + "background": "{color.bg.surface.raised.default}", + "hoverBackground": "{color.bg.surface.raised.default}", "disabledBackground": "{color.bg.neutral.medium.strong}", - "checkedBackground": "{color.fg.inverse.active}", - "checkedHoverBackground": "{color.fg.inverse.active}", + "checkedBackground": "{color.bg.surface.raised.default}", + "checkedHoverBackground": "{color.bg.surface.raised.default}", "color": "{color.fg.default}", "hoverColor": "{color.fg.default}", "checkedColor": "{color.fg.default}", @@ -5090,22 +5090,22 @@ }, "dark": { "handle": { - "background": "{color.fg.on.fill.default}", - "checkedBackground": "{color.fg.inverse.active}", + "background": "{color.bg.surface.raised.default}", + "checkedBackground": "{color.bg.surface.raised.default}", "checkedColor": "{color.fg.inverse.focus}", - "checkedHoverBackground": "{color.fg.inverse.active}", + "checkedHoverBackground": "{color.bg.surface.raised.default}", "checkedHoverColor": "{color.fg.on.brand.hover}", "color": "{color.fg.inverse.default}", - "disabledBackground": "{color.bg.neutral.medium.strong}", - "hoverBackground": "{color.fg.on.fill.default}", + "disabledBackground": "{color.bg.surface.raised.active}", + "hoverBackground": "{color.bg.surface.raised.default}", "hoverColor": "{color.fg.on.brand.hover}" }, "root": { "background": "{color.bg.neutral.medium.active}", - "checkedBackground": "{color.bg.neutral.strong.default}", - "checkedHoverBackground": "{color.bg.neutral.strong.hover}", - "disabledBackground": "{color.bg.surface.canvas.hover}", - "hoverBackground": "{color.bg.neutral.medium.strong}" + "checkedBackground": "{color.bg.surface.canvas.default}", + "checkedHoverBackground": "{color.bg.surface.canvas.hover}", + "disabledBackground": "{color.bg.neutral.strong.hover}", + "hoverBackground": "{color.bg.surface.raised.active}" } } }, diff --git a/src/theme/tokens/components/dark.json b/src/theme/tokens/components/dark.json index 9b6b1109..0412aaae 100644 --- a/src/theme/tokens/components/dark.json +++ b/src/theme/tokens/components/dark.json @@ -156,12 +156,12 @@ } }, "avatar": { - "extend": { "borderColor": "#2b2e33", "circle": { "borderRadius": 1600 } }, + "extend": { "borderColor": "#56595f", "circle": { "borderRadius": 1600 } }, "root": { "width": 32, "height": 32, "fontSize": 16, - "color": "#ffffff", + "color": "#2b2e33", "background": "#44e858", "borderRadius": 14 }, @@ -200,7 +200,7 @@ "info": { "background": "#18538d", "color": "#f0f9ff" }, "primary": { "background": "#44e858", "color": "#2b2e33" }, "secondary": { "background": "#2b2e33", "color": "#ffffff" }, - "success": { "background": "#aafbb7", "color": "#f0fff3" }, + "success": { "background": "#168322", "color": "#f0fff3" }, "warn": { "background": "#9d6d0e", "color": "#fff9f0" } }, "root": { @@ -607,7 +607,7 @@ "icon": { "size": 16, "color": "#f0f0f1", - "checkedColor": "#2b2e33", + "checkedColor": "#ffffff", "checkedHoverColor": "#ffffff", "disabledColor": "#a2a5a9", "sm": { "size": 12 }, @@ -1049,10 +1049,10 @@ "dialog": { "extend": { "borderWidth": 1, "backdrop": "rgba(0, 0, 0, 0.6000)" }, "root": { - "background": "#404348", + "background": "#56595f", "borderColor": "#404348", "color": "#ffffff", - "borderRadius": 20, + "borderRadius": 1600, "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" }, "header": { @@ -1106,7 +1106,7 @@ "paddingLeft": 0 } }, - "content": { "background": "#404348", "color": "#a2a5a9" }, + "content": { "background": "#404348", "color": "#ffffff" }, "root": { "borderColor": "#404348" } }, "drawer": { @@ -2387,7 +2387,7 @@ "tablist": { "borderTopWidth": 0, "borderRightWidth": 0, - "borderBottomWidth": 2, + "borderBottomWidth": 1, "borderLeftWidth": 0, "background": "transparent", "borderColor": "#404348" @@ -2801,21 +2801,21 @@ "toggleswitch": { "colorScheme": { "handle": { - "background": "#ffffff", - "checkedBackground": "#181a1f", + "background": "#56595f", + "checkedBackground": "#56595f", "checkedColor": "#2b2e33", - "checkedHoverBackground": "#181a1f", + "checkedHoverBackground": "#56595f", "checkedHoverColor": "#2b2e33", "color": "#2b2e33", "disabledBackground": "#85888e", - "hoverBackground": "#ffffff", + "hoverBackground": "#56595f", "hoverColor": "#2b2e33" }, "root": { "background": "#6d7076", - "checkedBackground": "#f0f0f1", - "checkedHoverBackground": "#e2e2e4", - "disabledBackground": "#404348", + "checkedBackground": "#2b2e33", + "checkedHoverBackground": "#404348", + "disabledBackground": "#e2e2e4", "hoverBackground": "#85888e" } }, diff --git a/src/theme/tokens/components/light.json b/src/theme/tokens/components/light.json index 2d6869f0..be686424 100644 --- a/src/theme/tokens/components/light.json +++ b/src/theme/tokens/components/light.json @@ -156,7 +156,7 @@ } }, "avatar": { - "extend": { "borderColor": "#ffffff", "circle": { "borderRadius": 1600 } }, + "extend": { "borderColor": "#cecfd2", "circle": { "borderRadius": 1600 } }, "root": { "width": 32, "height": 32, @@ -1052,7 +1052,7 @@ "background": "#ffffff", "borderColor": "#e2e2e4", "color": "#2b2e33", - "borderRadius": 20, + "borderRadius": 1600, "shadow": "0 4px 8px rgba(0, 0, 0, 0.2000)" }, "header": { @@ -1106,7 +1106,7 @@ "paddingLeft": 0 } }, - "content": { "background": "#ffffff", "color": "#85888e" }, + "content": { "background": "#ffffff", "color": "#2b2e33" }, "root": { "borderColor": "#e2e2e4" } }, "drawer": { @@ -2387,7 +2387,7 @@ "tablist": { "borderTopWidth": 0, "borderRightWidth": 0, - "borderBottomWidth": 2, + "borderBottomWidth": 1, "borderLeftWidth": 0, "background": "transparent", "borderColor": "#e2e2e4" From 5b59cba215025993a64575142715e6b0e51d4b0d Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Thu, 13 Aug 2026 15:40:53 +0300 Subject: [PATCH 55/60] =?UTF-8?q?feat(badge):=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5?= =?UTF-8?q?=D1=80=D1=8B=20Badge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Badge/Badge.stories.ts | 38 +- src/components/Badge/Badge.tsx | 94 ++- src/components/Badge/__tests__/Badge.test.tsx | 68 +- .../__snapshots__/Badge.test.tsx.snap | 657 ------------------ 4 files changed, 165 insertions(+), 692 deletions(-) delete mode 100644 src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap diff --git a/src/components/Badge/Badge.stories.ts b/src/components/Badge/Badge.stories.ts index c5b7857c..953b6c64 100644 --- a/src/components/Badge/Badge.stories.ts +++ b/src/components/Badge/Badge.stories.ts @@ -1,16 +1,48 @@ import type { Meta, StoryObj } from '@storybook/react' +import { createElement } from 'react' +import { StyleSheet, View } from 'react-native' -import { Badge } from './Badge' +import { Body } from '../Typography' + +import { Badge, type BadgeProps } from './Badge' + +const styles = StyleSheet.create({ + container: { gap: 16 }, + example: { gap: 8 }, +}) const meta: Meta = { title: 'Misc/Badge', component: Badge, - args: { severity: 'basic', dot: false, children: 'Test' }, + args: { children: 'Badge', severity: 'basic', size: 'base' }, argTypes: { + children: { control: 'text' }, severity: { control: 'radio', options: ['basic', 'info', 'success', 'warning', 'danger'], }, + size: { control: 'radio', options: ['base', 'large', 'xlarge'] }, + }, + parameters: { controls: { exclude: ['dot'] } }, + render: ({ children = 'Badge', severity, size }) => { + const textBadgeProps: BadgeProps = { children, dot: false, severity, size } + + return createElement( + View, + { style: styles.container }, + createElement( + View, + { style: styles.example }, + createElement(Body, null, 'Severity'), + createElement(Badge, textBadgeProps) + ), + createElement( + View, + { style: styles.example }, + createElement(Body, null, 'Dot'), + createElement(Badge, { dot: true, severity, size }) + ) + ) }, } @@ -18,6 +50,6 @@ export default meta type Story = StoryObj -const BadgeStory: Story = { args: { children: 'Test' }, argTypes: {} } +const BadgeStory: Story = {} export { BadgeStory as Badge } diff --git a/src/components/Badge/Badge.tsx b/src/components/Badge/Badge.tsx index 2cdf0052..eac73773 100644 --- a/src/components/Badge/Badge.tsx +++ b/src/components/Badge/Badge.tsx @@ -22,6 +22,11 @@ export interface BadgeBase * @default 'basic' */ severity?: BadgeSeverity + /** + * Выбор размера компонента + * @default 'base' + */ + size?: 'base' | 'large' | 'xlarge' /** Дополнительная стилизация для контейнера компонента */ style?: StyleProp } @@ -46,13 +51,22 @@ export type BadgeProps = BadgeText | BadgeDot * Компонент Badge * @param children - Текст внутри бейджа * @param dot - Отображать бейдж в форме точки - * @param severiy - Выбор варианта стиля компонента + * @param severity - Выбор варианта стиля компонента + * @param size - Выбор размера компонента * @param style - Дополнительная стилизация для контейнера компонента - * @link https://www.figma.com/design/4TYeki0MDLhfPGJstbIicf/UI-kit-PrimeFace-(DS)?node-id=484-4871&m=dev + * @link https://www.figma.com/design/Q1BWgZ7zoV5UzlBOnjW0cM/UI-Kit--DS--v2.1?node-id=24043-13668 */ export const Badge = memo( - ({ children, dot, severity = 'basic', style, testID, ...rest }) => { - badgeStyles.useVariants({ severity }) + ({ + children, + dot, + severity = 'basic', + size = 'base', + style, + testID, + ...rest + }) => { + badgeStyles.useVariants({ severity, size }) const [textLayout, setTextLayout] = useState() const onTextLayout = useCallback((e: LayoutChangeEvent) => { @@ -68,10 +82,7 @@ export const Badge = memo( /> ) : ( <> - + ({ dotShape: { width: components.badge.dot.size, height: components.badge.dot.size, - borderRadius: components.badge.root.borderRadius, + borderRadius: semantic.dimension.borderRadius.max, + borderWidth: components.overlaybadge.root.outline.width, + borderColor: components.overlaybadge.root.outline.color, + variants: { + size: { + base: {}, + large: { + width: components.badge.extend.extDot.lg.size, + height: components.badge.extend.extDot.lg.size, + }, + xlarge: { + width: components.badge.extend.extDot.xlg.size, + height: components.badge.extend.extDot.xlg.size, + }, + }, + }, }, textBadgeContainer: { height: components.badge.root.height, + minWidth: components.badge.root.minWidth, paddingHorizontal: components.badge.root.padding, justifyContent: 'center', - borderRadius: semantic.dimension.borderRadius.max, + borderRadius: components.badge.root.borderRadius, + borderWidth: components.overlaybadge.root.outline.width, + borderColor: components.overlaybadge.root.outline.color, + variants: { + severity: { + basic: { + backgroundColor: components.badge.colorScheme.primary.background, + }, + info: { backgroundColor: components.badge.colorScheme.info.background }, + success: { + backgroundColor: components.badge.colorScheme.success.background, + }, + warning: { + backgroundColor: components.badge.colorScheme.warn.background, + }, + danger: { + backgroundColor: components.badge.colorScheme.danger.background, + }, + }, + size: { + base: {}, + large: { + height: components.badge.lg.height, + minWidth: components.badge.lg.minWidth, + }, + xlarge: { + height: components.badge.xl.height, + minWidth: components.badge.xl.minWidth, + }, + }, + }, }, textBadge: { color: components.badge.colorScheme.primary.color, fontSize: components.badge.root.fontSize, + fontWeight: fonts.fontWeight.regular, + lineHeight: fonts.lineHeight[100], + letterSpacing: fonts.letterSpacing[500], includeFontPadding: false, verticalAlign: 'middle', fontFamily: fonts.fontFamily.heading, + variants: { + severity: { + basic: { color: components.badge.colorScheme.primary.color }, + info: { color: components.badge.colorScheme.info.color }, + success: { color: components.badge.colorScheme.success.color }, + warning: { color: components.badge.colorScheme.warn.color }, + danger: { color: components.badge.colorScheme.danger.color }, + }, + size: { + base: {}, + large: {}, + xlarge: { lineHeight: fonts.lineHeight[350] }, + }, + }, }, hiddenContainer: { width: Dimensions.get('window').width, diff --git a/src/components/Badge/__tests__/Badge.test.tsx b/src/components/Badge/__tests__/Badge.test.tsx index 0fcac425..8f3e605a 100644 --- a/src/components/Badge/__tests__/Badge.test.tsx +++ b/src/components/Badge/__tests__/Badge.test.tsx @@ -1,29 +1,53 @@ import { render } from '@testing-library/react-native' -import { Badge, type BadgeProps } from '../Badge' - -describe('Badge component tests', () => { - const snapshotCases: Array<[string, BadgeProps]> = [ - ['dot, severity: basic', { dot: true, severity: 'basic' }], - ['dot, severity: info', { dot: true, severity: 'info' }], - ['dot, severity: success', { dot: true, severity: 'success' }], - ['dot, severity: warning', { dot: true, severity: 'warning' }], - ['dot, severity: danger', { dot: true, severity: 'danger' }], - ['severity: basic', { children: '12', severity: 'basic' }], - ['severity: basic', { children: '12', severity: 'info' }], - ['severity: basic', { children: '12', severity: 'success' }], - ['severity: basic', { children: '12', severity: 'warning' }], - ['severity: basic', { children: '12', severity: 'danger' }], - ['severity: default', { children: '12' }], - [ - 'with custom style', - { dot: true, severity: 'basic', style: { margin: 10 } }, - ], +import { Badge, type BadgeSeverity } from '../Badge' + +describe('Badge', () => { + const severities: BadgeSeverity[] = [ + 'basic', + 'info', + 'success', + 'warning', + 'danger', ] - test.each(snapshotCases)('%s', (_, props) => { - const renderedBadge = render() + test.each(severities)( + 'отображает переданный текст для severity %s', + (severity) => { + const { getByText } = render(12) + + expect(getByText('12')).toBeOnTheScreen() + } + ) - expect(renderedBadge.toJSON()).toMatchSnapshot() + test.each(severities)('отображает dot для severity %s', (severity) => { + const { getByTestId, queryByText } = render( + + ) + + expect(getByTestId('Badge')).toBeOnTheScreen() + expect(queryByText('12')).not.toBeOnTheScreen() }) + + test.each(['large', 'xlarge'] as const)( + 'отображает переданный текст для размера %s', + (size) => { + const { getByText } = render( + + 12 + + ) + + expect(getByText('12')).toBeOnTheScreen() + } + ) + + test.each(['large', 'xlarge'] as const)( + 'отображает dot-вариант для размера %s', + (size) => { + const { getByTestId } = render() + + expect(getByTestId('Badge')).toBeOnTheScreen() + } + ) }) diff --git a/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap b/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap deleted file mode 100644 index c728269d..00000000 --- a/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap +++ /dev/null @@ -1,657 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Badge component tests dot, severity: basic 1`] = ` - - - -`; - -exports[`Badge component tests dot, severity: danger 1`] = ` - - - -`; - -exports[`Badge component tests dot, severity: info 1`] = ` - - - -`; - -exports[`Badge component tests dot, severity: success 1`] = ` - - - -`; - -exports[`Badge component tests dot, severity: warning 1`] = ` - - - -`; - -exports[`Badge component tests severity: basic 1`] = ` - - - - 12 - - - - - - 12 - - - - -`; - -exports[`Badge component tests severity: basic 2`] = ` - - - - 12 - - - - - - 12 - - - - -`; - -exports[`Badge component tests severity: basic 3`] = ` - - - - 12 - - - - - - 12 - - - - -`; - -exports[`Badge component tests severity: basic 4`] = ` - - - - 12 - - - - - - 12 - - - - -`; - -exports[`Badge component tests severity: basic 5`] = ` - - - - 12 - - - - - - 12 - - - - -`; - -exports[`Badge component tests severity: default 1`] = ` - - - - 12 - - - - - - 12 - - - - -`; - -exports[`Badge component tests with custom style 1`] = ` - - - -`; From dc2dc0840120995f12abc5d01037c3e06a0e84b4 Mon Sep 17 00:00:00 2001 From: Alesya Volosach Date: Thu, 13 Aug 2026 16:28:09 +0300 Subject: [PATCH 56/60] =?UTF-8?q?fix(button):=20=D0=B8=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D1=86=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D1=80=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B8?= =?UTF-8?q?=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B2=D0=B0=D1=80=D0=B8=D0=B0=D0=BD=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Button/Button.stories.ts | 51 +- src/components/Button/Button.tsx | 1 + src/components/Button/ButtonBadge.stories.ts | 52 +- src/components/Button/ButtonBadge.tsx | 36 +- .../Button/ButtonSeverity.stories.ts | 52 +- .../Button/__tests__/Button.test.tsx | 126 +- .../Button/__tests__/ButtonBadge.test.tsx | 18 +- .../Button/__tests__/ButtonSeverity.test.tsx | 20 +- .../__snapshots__/Button.test.tsx.snap | 139262 --------------- .../__snapshots__/ButtonBadge.test.tsx.snap | 298 - .../ButtonSeverity.test.tsx.snap | 277 - .../Button/utils/ButtonActivityIndicator.tsx | 8 +- .../Button/utils/ButtonContainer.tsx | 58 +- src/components/Button/utils/ButtonLabel.tsx | 21 +- 14 files changed, 288 insertions(+), 139992 deletions(-) delete mode 100644 src/components/Button/__tests__/__snapshots__/Button.test.tsx.snap delete mode 100644 src/components/Button/__tests__/__snapshots__/ButtonBadge.test.tsx.snap delete mode 100644 src/components/Button/__tests__/__snapshots__/ButtonSeverity.test.tsx.snap diff --git a/src/components/Button/Button.stories.ts b/src/components/Button/Button.stories.ts index 7c3d9298..8bb2a380 100644 --- a/src/components/Button/Button.stories.ts +++ b/src/components/Button/Button.stories.ts @@ -3,10 +3,19 @@ import { IconArrowDownRight, IconArrowDownLeft, } from '@tabler/icons-react-native' +import { createElement } from 'react' +import { StyleSheet, View } from 'react-native' + +import { Body } from '../Typography' import { Button } from './Button' +import type { ButtonBaseVariant, ButtonProps } from './types' const Icons = { IconArrowDownRight, IconArrowDownLeft, undefined } +const styles = StyleSheet.create({ + container: { gap: 16 }, + example: { gap: 8 }, +}) const meta: Meta = { title: 'Button', @@ -31,13 +40,45 @@ const meta: Meta = { disabled: { control: 'boolean' }, iconPosition: { control: 'radio', options: ['prefix', 'postfix'] }, onPress: { action: 'OnPress' }, - iconOnly: { - control: 'radio', - options: ['IconOnly', 'Not IconOnly'], - mapping: { IconOnly: true, 'Not IconOnly': undefined }, - }, Icon: { control: 'select', options: Object.keys(Icons), mapping: Icons }, }, + parameters: { controls: { exclude: ['iconOnly'] } }, + render: ({ + iconOnly: _iconOnly, + Icon, + iconPosition, + label = 'Button', + ...args + }) => { + const buttonProps: ButtonProps = { + ...args, + Icon, + iconPosition, + label, + } + const iconOnlyButtonProps: ButtonProps = { + ...args, + iconOnly: true, + Icon: Icon ?? IconArrowDownRight, + } + + return createElement( + View, + { style: styles.container }, + createElement( + View, + { style: styles.example }, + createElement(Body, null, 'С текстом'), + createElement(Button, buttonProps) + ), + createElement( + View, + { style: styles.example }, + createElement(Body, null, 'Только иконка'), + createElement(Button, iconOnlyButtonProps) + ) + ) + }, } export default meta diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 5e2ca5e7..bb3320ac 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -17,6 +17,7 @@ import { ButtonVariantContext } from './utils/ButtonVariantContext' * @param label - button label * @param style - external style control for component * @see BaseButton + * @link https://www.figma.com/design/Q1BWgZ7zoV5UzlBOnjW0cM/UI-Kit--DS--v2.1?node-id=160-5223 */ export const Button = memo>( ({ variant = 'primary', ...props }) => { diff --git a/src/components/Button/ButtonBadge.stories.ts b/src/components/Button/ButtonBadge.stories.ts index e84a14b1..675ce47f 100644 --- a/src/components/Button/ButtonBadge.stories.ts +++ b/src/components/Button/ButtonBadge.stories.ts @@ -3,10 +3,19 @@ import { IconArrowDownRight, IconArrowDownLeft, } from '@tabler/icons-react-native' +import { createElement } from 'react' +import { StyleSheet, View } from 'react-native' + +import { Body } from '../Typography' import { ButtonBadge } from './ButtonBadge' +import type { ButtonBadgeProps, ButtonBaseVariant, ButtonProps } from './types' const Icons = { IconArrowDownRight, IconArrowDownLeft, undefined } +const styles = StyleSheet.create({ + container: { gap: 16 }, + example: { gap: 8 }, +}) const meta: Meta = { title: 'Button/Badge', @@ -37,13 +46,46 @@ const meta: Meta = { control: 'radio', options: ['basic', 'info', 'success', 'warning', 'danger'], }, - iconOnly: { - control: 'radio', - options: ['IconOnly', 'Not IconOnly'], - mapping: { IconOnly: true, 'Not IconOnly': undefined }, - }, Icon: { control: 'select', options: Object.keys(Icons), mapping: Icons }, }, + parameters: { controls: { exclude: ['iconOnly'] } }, + render: ({ + iconOnly: _iconOnly, + Icon, + iconPosition, + label = 'Button', + ...args + }) => { + const buttonProps: ButtonProps & ButtonBadgeProps = { + ...args, + Icon, + iconPosition, + label, + } + const iconOnlyButtonProps: ButtonProps & + ButtonBadgeProps = { + ...args, + iconOnly: true, + Icon: Icon ?? IconArrowDownRight, + } + + return createElement( + View, + { style: styles.container }, + createElement( + View, + { style: styles.example }, + createElement(Body, null, 'С текстом'), + createElement(ButtonBadge, buttonProps) + ), + createElement( + View, + { style: styles.example }, + createElement(Body, null, 'Только иконка'), + createElement(ButtonBadge, iconOnlyButtonProps) + ) + ) + }, } export default meta diff --git a/src/components/Button/ButtonBadge.tsx b/src/components/Button/ButtonBadge.tsx index 9436f6f3..5519b079 100644 --- a/src/components/Button/ButtonBadge.tsx +++ b/src/components/Button/ButtonBadge.tsx @@ -3,7 +3,7 @@ import { View } from 'react-native' import { StyleSheet } from 'react-native-unistyles' -import { Badge } from '../Badge' +import { Badge, type BadgeProps } from '../Badge' import { BaseButton } from './BaseButton' import type { ButtonBadgeProps, ButtonBaseVariant, ButtonProps } from './types' @@ -30,39 +30,27 @@ export const ButtonBadge = memo< >(({ badgeLabel, badgeSeverity, variant = 'primary', ...props }) => { const variantContextValue = useMemo(() => ({ variant }), [variant]) - const badgeCommonProps = useMemo( - () => ({ severity: badgeSeverity, testID: ButtonBadgeTestId.badge }), - [badgeSeverity] - ) + const badgeCommonProps = { + severity: badgeSeverity, + testID: ButtonBadgeTestId.badge, + } + const badgeProps: BadgeProps = badgeLabel + ? { ...badgeCommonProps, children: badgeLabel, style: styles.badge } + : { ...badgeCommonProps, dot: true, style: styles.badgeDot } return ( - - - + + - {badgeLabel ? ( - - {badgeLabel} - - ) : ( - - )} - + ) }) const styles = StyleSheet.create(() => ({ - root: { flexDirection: 'row' }, - contentContainer: { flex: 1 }, - iconOnlyContainer: { flex: 0 }, + container: { alignSelf: 'flex-start' }, badgeDot: { position: 'absolute', top: 0, right: -0.5 }, badge: { position: 'absolute', diff --git a/src/components/Button/ButtonSeverity.stories.ts b/src/components/Button/ButtonSeverity.stories.ts index fe7b83f8..3d71b9ae 100644 --- a/src/components/Button/ButtonSeverity.stories.ts +++ b/src/components/Button/ButtonSeverity.stories.ts @@ -3,10 +3,23 @@ import { IconArrowDownRight, IconArrowDownLeft, } from '@tabler/icons-react-native' +import { createElement } from 'react' +import { StyleSheet, View } from 'react-native' + +import { Body } from '../Typography' import { ButtonSeverity } from './ButtonSeverity' +import type { + ButtonProps, + ButtonSeverityProps, + ButtonSeverityVariant, +} from './types' const Icons = { IconArrowDownRight, IconArrowDownLeft, undefined } +const styles = StyleSheet.create({ + container: { gap: 16 }, + example: { gap: 8 }, +}) const meta: Meta = { title: 'Button/Severity', @@ -33,13 +46,42 @@ const meta: Meta = { control: 'radio', options: ['info', 'success', 'warning', 'danger'], }, - iconOnly: { - control: 'radio', - options: ['IconOnly', 'Not IconOnly'], - mapping: { IconOnly: true, 'Not IconOnly': undefined }, - }, Icon: { control: 'select', options: Object.keys(Icons), mapping: Icons }, }, + parameters: { controls: { exclude: ['iconOnly'] } }, + render: ({ + iconOnly: _iconOnly, + Icon, + iconPosition, + label = 'Button', + ...args + }) => { + const buttonProps: ButtonProps & + ButtonSeverityProps = { ...args, Icon, iconPosition, label } + const iconOnlyButtonProps: ButtonProps & + ButtonSeverityProps = { + ...args, + iconOnly: true, + Icon: Icon ?? IconArrowDownRight, + } + + return createElement( + View, + { style: styles.container }, + createElement( + View, + { style: styles.example }, + createElement(Body, null, 'С текстом'), + createElement(ButtonSeverity, buttonProps) + ), + createElement( + View, + { style: styles.example }, + createElement(Body, null, 'Только иконка'), + createElement(ButtonSeverity, iconOnlyButtonProps) + ) + ) + }, } export default meta diff --git a/src/components/Button/__tests__/Button.test.tsx b/src/components/Button/__tests__/Button.test.tsx index c2abe708..024a869a 100644 --- a/src/components/Button/__tests__/Button.test.tsx +++ b/src/components/Button/__tests__/Button.test.tsx @@ -1,101 +1,73 @@ import { IconArrowDownRight } from '@tabler/icons-react-native' -import { render } from '@testing-library/react-native' +import { render, userEvent } from '@testing-library/react-native' import { Button } from '../Button' -import type { - ButtonBaseVariant, - IconOnlyButtonProps, - IconTextButton, -} from '../types' -describe('Button component tests', () => { - const buttonSnapshotCases = generatePropsCombinations< - IconTextButton - >({ - size: ['base', 'small', 'large', 'xlarge'], - shape: ['square', 'circle'], - loading: [true, false], - variant: ['primary', 'secondary', 'tertiary', 'text', 'link'], - disabled: [true, false], - label: ['Button'], - testOnly_pressed: [true, false], - }) - - test.each(buttonSnapshotCases)( - 'Button with text, size - $size, shape - $shape, variant - $variant, loading - $loading, disabled - $disabled', - (props) => { - const renderedButton = render(