English · Русский
Warning
Поскольку библиотека находится в активной разработке, большинство функций, удобных для разработчиков и организационных функций ещё не реализованы, например:
- Вебсайт с документацией
- Комментарии с документацией
- Примеры
- Рабочий процесс разработки
Документация · Сообщить об ошибке · Запросить функцию
- 🧰 Поддержка нескольких фреймворков
- 🎨 Дизайн основан на Material Design 3
- 🧱 Простые и комплексные компоненты
- 🧩 Модульная структура
-
Добавьте Vanilla Extract plugin в проект
Эта библиотека может быть использована в любом проекте, который поддерживает Vanilla Extract. Все доступные интеграции расположены по ссылке: "Bundler Integration". Вот список интеграций, поддерживающихся на момент написания:- Astro (при помощи
@vanilla-extract/vite-plugin
) - esbuild (при помощи
@vanilla-extract/esbuild-plugin
) - Gatsby (при помощи
gatsby-plugin-vanilla-extract
) - Next.js (при помощи
@vanilla-extract/next-plugin
) - Parcel (при помощи
@vanilla-extract/parcel-transformer
) - Remix (при помощи
@vanilla-extract/vite-plugin
) - Rollup (при помощи
@vanilla-extract/rollup-plugin
) - Vite (при помощи
@vanilla-extract/vite-plugin
) - Webpack (при помощи
@vanilla-extract/webpack-plugin
)
- Astro (при помощи
-
Добавьте основную библиотеку Vanilla Extract (
@vanilla-extract/css
):npm
npm install @vanilla-extract/css
pnpm
pnpm add @vanilla-extract/css
Yarn
yarn add @vanilla-extract/css
Bun
bun add @vanilla-extract/css
-
Установите пакет star4 с утилитами для Vanilla Extract (
@star4/vanilla-extract
):npm
npm install @star4/vanilla-extract
pnpm
pnpm add @star4/vanilla-extract
Yarn
yarn add @star4/vanilla-extract
Bun
bun add @star4/vanilla-extract
-
Установите пакет star4 для выбранного фреймворка:
-
React (
@star4/react
):npm
npm install @star4/react
pnpm
pnpm add @star4/react
Yarn
yarn add @star4/react
Bun
bun add @star4/react
-
Solid (
@star4/solid
):npm
npm install @star4/solid
pnpm
pnpm add @star4/solid
Yarn
yarn add @star4/solid
Bun
bun add @star4/solid
-
Для того, что начать использовать star4, необходимо настроить тему. Это может сделано при помощи пакета @star4/vanilla-extract
.
A theme object can be created in an ordinary (non .css.*
) file using the createTheme
helper function:
import { createTheme } from "@star4/vanilla-extract";
export const { contract, theme } = createTheme({/* ... */});
This function accepts an options argument, which is an object specifying theme configuration. Some of its fields are required. Here's a minimalist example:
import { createTheme } from "@star4/vanilla-extract";
export const { contract, theme } = createTheme({
// Use a static color scheme
color: {},
// Specify font families for different font styles
typeface: {
plain: "system-ui",
brand: "sans-serif",
},
// Specify the font family used for Material Symbols icons
component: {
materialSymbol: {
font: "Material Symbols Outlined",
},
},
});
Функция createTheme
возвращает объект, содержащий две функции: contract
и theme
.
Сначала создайте "контракт", используя вспомогательную функцию contract
:
// ДАННЫЙ ПРИМЕР ПРЕДПОЛАГАЕТ:
// - тема star4 была создана
// - `contract` был импортирован в файл
export const THEME = contract();
Вспомогательная функция theme
возвращает объект, заполненный CSS значениями, готовый к применению при помощи (@vanilla-extract/css
) внутри .css.*
файла. Можно использовать любой API Vanilla Extract, в зависимости от ваших нужд.
Example creating a theme which follows system preference, using globalStyle
and assignVars
APIs:
// ДАННЫЙ ПРИМЕР ПРЕДПОЛАГАЕТ:
// - a star4 theme was created
// - a theme contract named `THEME` was created
// - `theme` helper and `THEME` were imported into this file
import { assignVars, globalStyle } from "@vanilla-extract/css";
const LIGHT_THEME = theme("light");
const DARK_THEME = theme("dark");
globalStyle(
":root, ::backdrop",
{
colorScheme: "light dark",
"@media": {
"(prefers-color-scheme: light)": {
vars: assignVars(THEME, LIGHT_THEME),
},
"(prefers-color-scheme: dark)": {
vars: assignVars(THEME, DARK_THEME),
},
},
},
);
Here is a more complicated example, allowing overriding the current theme mode using a data attribute:
// ДАННЫЙ ПРИМЕР ПРЕДПОЛАГАЕТ:
// - a star4 theme was created
// - a theme contract named `THEME` was created
// - `theme` helper and `THEME` were imported into this file
import { assignVars, globalStyle } from "@vanilla-extract/css";
// A helper function for creating attribute selectors
const createThemeSelector = (
themes: string | string[],
not: boolean = false,
) => {
const values = typeof themes === "string" ? [themes] : themes;
const attributes = values.map(
theme => `[data-theme="${theme}"]`,
);
let is = `:is(${attributes.join(",")})`;
if(not) is = `:not(${is})`;
return `:root${is}, ${is} ::backdrop`;
}
// Store filled theme objects for reuse
const LIGHT_THEME = theme("light");
const DARK_THEME = theme("dark");
// Possible data-theme attribute values
const DATA_THEME_LIGHT = "light";
const DATA_THEME_DARK = "dark";
// Follow system theme mode if no
// [data-theme="light"] or [data-theme="dark"]
// attribute was found
globalStyle(
createThemeSelector([DATA_THEME_LIGHT, DATA_THEME_DARK], true),
{
colorScheme: "light dark",
"@media": {
"(prefers-color-scheme: light)": {
vars: assignVars(THEME, LIGHT_THEME),
},
"(prefers-color-scheme: dark)": {
vars: assignVars(THEME, DARK_THEME),
},
},
},
);
// If <html> has a [data-theme="light"]
// attribute, apply the light theme
globalStyle(
createThemeSelector(DATA_THEME_LIGHT),
{
colorScheme: "light",
vars: assignVars(THEME, LIGHT_THEME),
}
);
// If <html> has a [data-theme="dark"]
// attribute, apply the dark theme
globalStyle(
createThemeSelector(DATA_THEME_DARK),
{
colorScheme: "dark",
vars: assignVars(THEME, DARK_THEME),
}
);
star4 uses the Material You color system, which provides two options for creating color schemes: static and dynamic. See Choosing a scheme for advice.
Warning
Поведение свойства color
может быть изменено в будущем.
The color
property is responsible for color scheme configuration. Settings it to an empty object {}
will assert a static scheme, while creating a dynamic scheme requires specifying a few properties.
Пример статической цветовой схемы:
export const { contract, theme } = createTheme({
// Empty object - using a static color scheme
color: {},
/* ... other fields... */
});
Пример динамической цветовой схемы:
export const { contract, theme } = createTheme({
color: {
// A total of 9 variants are available
variant: "tonalSpot"
// Can be a hex, rgb CSS color, or an Hct instance
sourceColor: "#00ff00",
// Defaults to 0. Allows changing color scheme contrast
contrastLevel: 0,
},
/* ... other fields... */
});
Font family names containing spaces must be quoted in CSS.
Here is a helper function for merging CSS font names:
type FontFamily = (string | FontFamily)[];
const fontFamily = (...args: FontFamily): string => {
return args
.map(
value => typeof value === "string"
? value.includes(" ")
? `"${value}"`
: value
: fontFamily(...value),
)
.join(", ");
}
If using variable fonts from FontSource, their font family names have Variable
appended to them, e.g. Open Sans Variable
, so here is a helper for FontSource fonts:
// Use system font if available,
// otherwise load the FontSource font
const fontSource = (family: string) => {
return [`${family}`, `${family} Variable`];
};
Here's an example showcasing both helpers in action:
// Gets transformed to:
// "Roboto Flex", "Roboto Flex Variable", "Open Sans", "Open Sans Variable", Roboto, system-ui, Arial, sans-serif
const TYPEFACE_PLAIN = fontFamily(
fontSource("Roboto Flex"),
fontSource("Open Sans"),
"Roboto",
"system-ui",
"Arial",
"sans-serif",
);
// Gets transformed to:
// Raleway, "Raleway Variable", Manrope, "Manrope Variable", sans-serif
const TYPEFACE_BRAND = fontFamily(
fontSource("Raleway"),
fontSource("Manrope"),
"sans-serif",
);
export const { contract, theme } = createTheme({
typeface: {
plain: TYPEFACE_PLAIN,
brand: TYPEFACE_BRAND,
},
/* other fields */
});
star4 framework packages export all available components, most of them contain documentation comments and code samples, so documentation for each component will not be provided here.
Пакет @star4/react
содержит вспомогательную функцию .is()
для каждого компонента. Эта функция может быть использована для определения, является ли React элемент экземпляром конкретного компонента. Она прекрасно подходит для фильтрации дочерних элементов:
import { Children, type ReactNode } from "react";
import { Button } from "@star4/react";
// Данный компонент отображает только экземпляры Button
// Выводит предупреждение, если передаются прочие элементы
export function OnlyButtons({ children }: { children: ReactNode }) {
const buttons = Children.toArray(children)
.filter(node => {
const is = Button.is(node);
if(!is) console.warn(
"Invalid JSX Element passed to token resolver:",
node,
);
return is;
});
return buttons;
}
Warning
Название и возвращаемое значение функции createIdentifiableElement
могут измениться в будущем
Свои компоненты можно сделать идентифицируемыми, используя функцию createIdentifiableElement
. Мы рекомендуем именовать ваши компоненты, как в примере:
import { createIdentifiableElement } from "@star4/react";
// forwardRef также может быть использована вместо прямого присвоения
const ExampleComponent = function Example() {
}
export const Example = Object.assign(
// memo(ExampleComponent) также может быть использовано для мемоизации
ExampleComponent,
// IS_EXAMPLE - это описание объекта Symbol,
// созданного для идентификации элемента
createIdentifiableElement("IS_EXAMPLE"),
);
// Используйте компонент
<Example />
// Идентифицируйте элемент
Example.is(something)
star4 был возможен только благодаря следующим замечательным проектам:
- Solid Primitives - GitHub
Настоящий "швейцарский нож" для SolidJS.
-
Material Web - GitHub
Официальная библиотека web компонентов Material Design 3. -
usehooks-ts - GitHub
Замечательная библиотека React хуков.