Кроссплатформенный и мобильный интерфейс · Новый ресурс
Дизайн-система Tamagui.
Изучите актуальные категории токенов Tamagui версии v5 и светлую и тёмную синие темы на примере полноценной доски привычек из нативных компонентов: с валидацией, прогрессом и восстановлением после пустого состояния.
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
size.$2
28
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
size.$3
36
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
size.$4
44
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
size.$5
52
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
size.$6
64
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
space.$1.5
4
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
space.$2
7
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
space.$2.5
10
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
space.$3
13
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
space.$3.5
16
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
space.$4
18
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
space.$5
24
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
space.$6
32
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
radius.1
3
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
radius.2
5
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
radius.3
7
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
radius.4
9
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
radius.5
10
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
radius.6
16
Фактическое значение конфигурации v5. Одинаковая числовая метка токена имеет разный смысл для размера, интервала и радиуса; не считайте $4 универсальным значением в пикселях.
Дизайн-система Tamagui: версионируемая конфигурация и CSS
Используйте предустановку с указанной версией v5
В этом примере версии tamagui и @tamagui/config зафиксированы на 2.7.7, а defaultConfig импортируется из @tamagui/config/v5. Имя конфигурации — v5, а не номер основной версии npm-пакета. Если смешать эти два номера, читатель получит неверную команду установки. createTamagui вызывается один раз за пределами компонента, а сгенерированный CSS добавляется до отрисовки доски, чтобы переменные темы и стили native имели реальное определение для веба.
Явно укажите небольшое переопределение конфигурации
В предоставленном исходном коде для onlyAllowShorthands задано значение false, поскольку в этом учебном примере используются понятные свойства с полными названиями, например padding и backgroundColor. Это решение приложения поверх предустановки. Базовая конфигурация v5 не включает драйвер анимации, и в примере он не придумывается и не заявляется наличие анимированных переходов. Простые действия с прогрессом и флажками работают без отдельной зависимости для анимации.
Дизайн-система Tamagui: токены размера, интервалов и скругления
Не путайте одинаковые метки токенов
В зафиксированной конфигурации v5 размер $4 равен 44, интервал $4 — 18, а радиус 4 — 9. Поэтому для размера компонента, промежутка в компоновке и радиуса скругления нельзя использовать одно общее правило пересчёта. В справочнике эти категории приведены отдельно, а в примере их значения используются с учётом категории через реальные свойства Tamagui. Это полезнее, чем список универсальных шагов по 4px, которых в конфигурации нет.
size.$4 = 44
space.$4 = 18
radius.4 = 9
Основной шрифт $4: 15px, высота строки — 23px
Типографическую шкалу тоже учитывайте отдельно
Основной шрифт $4 имеет размер 15px и высоту строки 23px, а размер компонента $4 по-прежнему равен 44. Системный стек шрифтов входит в v5, поэтому загружать шрифт не нужно. Для H1, H2 и Text заданы собственные контексты шрифтов; иерархию исходной доски определяют явно указанные в коде значения fontSize и lineHeight. Ширина внешнего контейнера 880px — локальное решение для компоновки, а не глобальный токен Tamagui.
Tamagui Семантические темы и внешний вид дизайн-системы
Сочетайте светлую или тёмную тему с синей дочерней темой
TamaguiProvider получает выбранное значение defaultTheme, а Theme name="blue" разрешает соответствующую дочернюю тему. Вместо повторения буквальных hex-значений по всему дереву компонентов в исходном коде используются роли background, backgroundHover, color и borderColor. В таблице приведены фактические значения light_blue и dark_blue, чтобы читатель мог сравнить разрешённую конфигурацию, а не предполагать, что палитра бренда всегда одна и та же.
Сохраняйте состояние доски при смене оформления
Флаг dark не зависит от строк, черновика в поле ввода и фильтра. При переключении оформления обновляются native-компоненты, а содержимое доски сохраняется. Для кнопок и флажков могут выбираться собственные значения дочерних тем компонентов, поэтому вычисленный цвет не обязательно совпадает с токеном фона родительской темы. Перед сведением иерархии к пользовательским CSS проверьте отрисованное состояние.
Дизайн-система Tamagui: флажки и вычисляемый прогресс
Храните состояние выполнения в коллекции строк
У каждой строки есть стабильный ID, понятный текст и логическое значение done. Для Checkbox задаются checked и onCheckedChange; задача считается выполненной только при значении true. Checkbox.Indicator отображает отметку. Соседний текст и доступное имя обозначают одну и ту же привычку, а зачёркивание дополнительно показывает её выполнение. В исходном коде отдельный счётчик, который мог бы рассинхронизироваться со строками, не создаётся.
Рассчитывайте прогресс по всей доске
Дизайн-система Tamagui: проверка черновика и обработка дубликатов
Добавьте полноценное контролируемое поле ввода
Input хранит текущий черновик в value и onChangeText. Действие «Добавить привычку» удаляет пробелы по краям и отклоняет пустое значение, показывая сообщение, aria-invalid и описание ошибки. После отправки пустого значения фокус возвращается в поле ввода. Проверка на дубликаты без учёта регистра не позволяет добавить ещё одну строку с тем же текстом и оставляет черновик для исправления. Эти правила относятся к исходной доске, а не к библиотеке.
Обновляйте доску только после успешной проверки
Валидный черновик добавляет новую незавершённую строку, очищает поле ввода и убирает сообщение об ошибке. Знаменатель для прогресса сразу меняется, поскольку он вычисляется по новой коллекции. Добавление привычки не создаёт напоминание и не регистрирует учётную запись. Доска намеренно хранится в локальном состоянии React; после перезагрузки документа снова отобразится пример.
Дизайн-система Tamagui: отфильтрованные представления и выход из пустого состояния
Уточните, к чему применяется фильтр
Фильтр «Показывать только незавершённые» скрывает выполненные строки, сохраняя их в коллекции. Если в этом представлении ничего не осталось, текст пустого состояния поясняет, что полный список по-прежнему доступен, и предлагает прямой переход обратно. Такое пустое состояние возникает в результате выбора пользователя, а не из-за декоративного переключателя, произвольно заменяющего карточки-заполнители.
Отделите сброс от смены оформления
Действие «Сбросить доску к исходному виду» восстанавливает три начальные строки, очищает черновик и сообщение об ошибке, а также возвращает полный список. Текущее оформление не меняется. Поскольку каждое изменение хранится как явное состояние, для сброса не нужно перезагружать документ или удалять настроенный provider. Восстановление темы и содержимого можно проверять независимо.
Дизайн-система Tamagui: адаптивные стеки и удобство чтения
Позвольте содержимому стека определять его высоту
YStack задаёт основную последовательность содержимого, а XStack выравнивает элементы управления в заголовке, строки с флажками и кнопки действий. Группы элементов управления переносятся, а не требуют фиксированной ширины для настольного экрана. Ширина внешнего контейнера не превышает 880px; для внутренних отступов используется реальный токен интервалов $4. Текст в каждой строке может сжиматься и переноситься, а элементы управления остаются доступными при ширине 280px и на более широких экранах.
Проверьте взаимодействие после изменения компоновки
При проверке в браузере добавляют привычку, отмечают её выполненной, фильтруют список и переключают оформление, а затем измеряют переполнение. Один снимок начального состояния не покажет, не нарушают ли узкую компоновку сообщение об ошибке, длинная подпись или отфильтрованное представление. Семантику native-флажков и видимый текст проверяли вместе с вычисляемым прогрессом, а не считали их работающими только на основании наличия в интерфейсе.
Дизайн-система Tamagui: полная сборка для браузера
Добавьте provider, CSS и определения сборки
Для локального изучения веб-версии достаточно трёх предоставленных файлов. JSX содержит провайдер, одну конфигурацию, сгенерированную тему CSS и всю доску. build.mjs фиксирует целевую веб-платформу и производственное окружение, а также задаёт пустое значение по умолчанию для process.env на случай других обращений к переменным окружения, доступным только в браузере. Без этого последнего определения обычная сборка может завершиться ошибкой process is not defined, даже если компиляция проходит.
Сохраните tamagui.jsx, build.mjs и index.html в одной папке.
Установите зафиксированные версии пакетов React и Tamagui.
Соберите и запустите локальную папку.
Проверьте добавление пустых и повторяющихся элементов, выполнение, фильтры, тему и сброс.
Разделяйте внедрение для нативных приложений и веба
Примеры компонентов дизайн-системы Tamagui
tamagui.jsx
Конфигурация, сгенерированная CSS, нативные компоненты и полное состояние доски.
jsx
import React,{useState} from 'react';import{createRoot}from'react-dom/client';
import{createTamagui,TamaguiProvider,Theme,YStack,XStack,Text,H1,H2,Button,Input,Checkbox,Progress,Separator}from'tamagui';import{defaultConfig}from'@tamagui/config/v5';
const config=createTamagui({...defaultConfig,settings:{...defaultConfig.settings,onlyAllowShorthands:false}});const sheet=document.createElement('style');sheet.textContent=config.getCSS();document.head.append(sheet);
const initial=[{id:1,text:'Read ten pages',done:false},{id:2,text:'Step outside for a break',done:true},{id:3,text:'Write one useful note',done:false}];
function App(){const[dark,setDark]=useState(false),[rows,setRows]=useState(initial),[draft,setDraft]=useState(''),[error,setError]=useState(''),[filter,setFilter]=useState(false);const done=rows.filter(x=>x.done).length;let shown=rows.filter(x=>!filter||!x.done);function add(){let text=draft.trim();if(!text){setError('Write a small habit before adding it.');document.querySelector('#habit-input')?.focus();return}if(rows.some(x=>x.text.toLowerCase()===text.toLowerCase())){setError('That habit is already in this list.');return}setRows([...rows,{id:Date.now(),text,done:false}]);setDraft('');setError('')}return <TamaguiProvider config={config} defaultTheme={dark?'dark':'light'}><Theme name="blue"><YStack backgroundColor="$background" color="$color" padding="$4" gap="$4" maxWidth={880} margin="auto" width="100%" minHeight={0}><XStack justifyContent="space-between" alignItems="center" flexWrap="wrap" gap="$3"><Text fontSize="$2" fontWeight="700">TAMAGUI / ORIGINAL HABIT BOARD</Text><Button size="$3" onPress={()=>setDark(!dark)}>{dark?'Light appearance':'Dark appearance'}</Button></XStack><H1 fontSize="$8" lineHeight="$8">A little progress, every day.</H1><Text fontSize="$4" lineHeight="$5">A local board built with Tamagui 2.7.7 and its v5 blue theme. Your changes stay in this page; no account or daily reminder is connected.</Text><YStack backgroundColor="$backgroundHover" borderWidth={1} borderColor="$borderColor" borderRadius="$4" padding="$4" gap="$3"><XStack justifyContent="space-between" gap="$3" flexWrap="wrap"><H2 fontSize="$5">Today’s small steps</H2><Text id="progress-count" aria-live="polite">{done} of {rows.length} complete</Text></XStack><Progress value={rows.length?done/rows.length*100:0} size="$2" aria-label="Completed habits"><Progress.Indicator animation={undefined}/></Progress><Button size="$3" alignSelf="flex-start" onPress={()=>setFilter(!filter)}>{filter?'Show all habits':'Show unfinished only'}</Button><Separator/>{shown.length?shown.map(row=><XStack key={row.id} gap="$3" alignItems="center" paddingVertical="$2"><Checkbox id={'habit-'+row.id} checked={row.done} onCheckedChange={value=>setRows(rows.map(x=>x.id===row.id?{...x,done:value===true}:x))} aria-label={row.text} size="$4"><Checkbox.Indicator><Text fontWeight="700">✓</Text></Checkbox.Indicator></Checkbox><Text flex={1} fontSize="$4" lineHeight="$5" textDecorationLine={row.done?'line-through':'none'} opacity={row.done?.65:1}>{row.text}</Text></XStack>):<YStack gap="$3"><Text fontWeight="700">Nothing unfinished in this view</Text><Text>All your habits remain in the full list. You can revisit any completed item.</Text><Button onPress={()=>setFilter(false)}>Return to all habits</Button></YStack>}</YStack><YStack gap="$3"><Text htmlFor="habit-input" tag="label" fontWeight="700">Add one small habit</Text><Input id="habit-input" value={draft} onChangeText={v=>{setDraft(v);setError('')}} placeholder="For example, stretch for five minutes" aria-describedby={error?'habit-error':undefined} aria-invalid={!!error} onKeyPress={e=>{if(e.nativeEvent.key==='Enter')add()}}/><Text id="habit-error" color="$color" aria-live="polite">{error}</Text><XStack gap="$3" flexWrap="wrap"><Button theme="active" onPress={add}>Add habit</Button><Button onPress={()=>{setRows(initial);setDraft('');setError('');setFilter(false)}}>Reset sample board</Button></XStack></YStack><Text fontSize="$2" lineHeight="$3">Native Checkbox, Input, Button and Progress components; original board content and state. Theme changes preserve the current board.</Text></YStack></Theme></TamaguiProvider>}
createRoot(document.getElementById('root')).render(<App/>);
Реализуйте полноценную веб-доску привычек на Tamagui 2.7.7 с пресетом v5. Разделяйте категории токенов размера, пространства, радиуса и шрифта; сохраните сгенерированную тему CSS, дочерние светлую и тёмную синие темы, управляемые флажки, проверку с обрезкой пробелов и дубликатов, знаменатель прогресса по всем строкам, восстановление в представлении незавершённых задач и сброс без изменения внешнего вида.
05
Источники и область применения дизайн-системы Tamagui
Реальные веб-компоненты Tamagui 2.7.7 с пресетом v5. Доска привычек и правила состояния — оригинальный код OpenDesign; функции учётных записей, напоминаний и взаимодействия с нативными устройствами не подключены.