Вёрстка сайту із використанням Chakra UI
Chakra UI — React-компонентна бібліотека, орієнтована на accessibility-first підхід та style props API. Кожен компонент — це styled div з Emotion під капотом. Сильні сторони: responsive props прямо в JSX, вбудована темна тема, строга WCAG-сумісність з коробки.
Установка (Chakra v3)
У версії 3.x архітектура змінилась — провайдер спрощено, знята залежність від ChakraBaseProvider:
npm install @chakra-ui/react @emotion/react
// src/main.tsx
import { ChakraProvider, defaultSystem } from '@chakra-ui/react';
import system from './theme/system';
function Root() {
return (
<ChakraProvider value={system}>
<App />
</ChakraProvider>
);
}
// src/theme/system.ts
import { createSystem, defaultConfig, defineConfig } from '@chakra-ui/react';
const customConfig = defineConfig({
theme: {
tokens: {
fonts: {
heading: { value: '"Inter", sans-serif' },
body: { value: '"Inter", sans-serif' },
mono: { value: '"JetBrains Mono", monospace' },
},
colors: {
brand: {
50: { value: '#eff6ff' },
100: { value: '#dbeafe' },
500: { value: '#3b82f6' },
600: { value: '#2563eb' },
700: { value: '#1d4ed8' },
800: { value: '#1e40af' },
},
},
radii: {
card: { value: '12px' },
button: { value: '8px' },
},
},
semanticTokens: {
colors: {
'bg.canvas': {
value: { base: '#f9fafb', _dark: '#0f172a' },
},
'bg.surface': {
value: { base: '#ffffff', _dark: '#1e293b' },
},
'text.primary': {
value: { base: '#111827', _dark: '#f1f5f9' },
},
'text.muted': {
value: { base: '#6b7280', _dark: '#94a3b8' },
},
'border.default': {
value: { base: '#e5e7eb', _dark: '#334155' },
},
},
},
},
});
const system = createSystem(defaultConfig, customConfig);
export default system;
Style props API — основа вёрстки
Chakra UI передає CSS-властивості прямо через props з підтримкою адаптивних об'єктів:
import { Box, Flex, Grid, Text, Heading, Button, Stack } from '@chakra-ui/react';
const HeroSection = () => (
<Box
as="section"
bg="bg.canvas"
py={{ base: '12', md: '20', lg: '28' }}
px={{ base: '4', md: '8', lg: '12' }}
>
<Flex
maxW="7xl"
mx="auto"
direction={{ base: 'column', lg: 'row' }}
align="center"
gap={{ base: '10', lg: '16' }}
>
<Box flex="1">
<Heading
as="h1"
size={{ base: '2xl', md: '3xl', lg: '4xl' }}
color="text.primary"
mb="4"
fontWeight="700"
lineHeight="1.2"
>
Заголовок вашого продукту
</Heading>
<Text
fontSize={{ base: 'md', md: 'lg' }}
color="text.muted"
mb="8"
maxW="480px"
>
Підзаголовок з описанням ключової цінності для потенційного клієнта.
</Text>
<Stack direction={{ base: 'column', sm: 'row' }} gap="3">
<Button
colorPalette="brand"
size="lg"
borderRadius="button"
px="8"
>
Почати безплатно
</Button>
<Button
variant="outline"
size="lg"
borderRadius="button"
px="8"
>
Подивитись демо
</Button>
</Stack>
</Box>
<Box flex="1">
<Box
as="img"
src="/img/hero.webp"
alt="Знімок екрана продукту"
w="100%"
borderRadius="card"
shadow="2xl"
/>
</Box>
</Flex>
</Box>
);
Сітка карточок
import { SimpleGrid, Card, Icon } from '@chakra-ui/react';
import { LuCode, LuCloud, LuShield } from 'react-icons/lu';
const features = [
{ icon: LuCode, title: 'Розробка', text: '...' },
{ icon: LuCloud, title: 'Хмара', text: '...' },
{ icon: LuShield, title: 'Безпека', text: '...' },
];
const FeaturesGrid = () => (
<SimpleGrid columns={{ base: 1, sm: 2, lg: 3 }} gap="6">
{features.map(({ icon, title, text }) => (
<Card.Root
key={title}
bg="bg.surface"
border="1px solid"
borderColor="border.default"
borderRadius="card"
_hover={{ shadow: 'md', transform: 'translateY(-2px)' }}
transition="all 200ms ease"
>
<Card.Body p="6">
<Box
w="10"
h="10"
bg="brand.50"
borderRadius="lg"
display="flex"
alignItems="center"
justifyContent="center"
mb="4"
>
<Icon as={icon} boxSize="5" color="brand.600" />
</Box>
<Heading as="h3" size="md" mb="2">
{title}
</Heading>
<Text color="text.muted" fontSize="sm">
{text}
</Text>
</Card.Body>
</Card.Root>
))}
</SimpleGrid>
);
Форма з валідацією (React Hook Form + Zod)
import { Field, Input, Textarea, Button } from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({
name: z.string().min(2, 'Мінімум 2 символи'),
email: z.string().email('Некоректний email'),
message: z.string().min(10, 'Мінімум 10 символів'),
});
type FormData = z.infer<typeof schema>;
const ContactForm = () => {
const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<FormData>({
resolver: zodResolver(schema),
});
return (
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
<Stack gap="5">
<Field.Root invalid={!!errors.name}>
<Field.Label>Ім'я</Field.Label>
<Input {...register('name')} placeholder="Іван Сидоренко" />
{errors.name && <Field.ErrorText>{errors.name.message}</Field.ErrorText>}
</Field.Root>
<Field.Root invalid={!!errors.email}>
<Field.Label>Email</Field.Label>
<Input {...register('email')} type="email" placeholder="[email protected]" />
{errors.email && <Field.ErrorText>{errors.email.message}</Field.ErrorText>}
</Field.Root>
<Field.Root invalid={!!errors.message}>
<Field.Label>Повідомлення</Field.Label>
<Textarea {...register('message')} rows={4} />
{errors.message && <Field.ErrorText>{errors.message.message}</Field.ErrorText>}
</Field.Root>
<Button type="submit" colorPalette="brand" loading={isSubmitting} w="full">
Відправити
</Button>
</Stack>
</Box>
);
};
Колірний режим
Chakra v3 управляє темним режимом через семантичні токени — варіант _dark задається при визначенні токена:
import { useColorMode } from '@chakra-ui/react';
const ThemeToggle = () => {
const { colorMode, toggleColorMode } = useColorMode();
return (
<Button onClick={toggleColorMode} variant="ghost" size="sm">
{colorMode === 'light' ? 'Темна тема' : 'Світла тема'}
</Button>
);
};
Терміни
Налаштування системи та теми: 3–4 години. Chakra UI особливо ефективний при розробці сайтів з формами, дашбордами та SaaS-інтерфейсами — адаптивні props в JSX виключають переключення файлів. Посадочна сторінка: 1–2 дні. Повний продуктовий сайт із кількома розділами: 4–7 днів.







