@ai.all/ds7 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/01-architecture/ATOMIC-DESIGN.md +48 -42
- package/01-architecture/COMPONENT-ANATOMY.md +14 -30
- package/01-architecture/MODIFIER-SYSTEM.md +24 -35
- package/02-design-system/BRANDBOOK-SANDBOX.md +34 -34
- package/02-design-system/NAMING-CONVENTIONS.md +21 -19
- package/02-design-system/TOKENS-SPEC.md +65 -51
- package/03-performance-web-vitals/ASSETS-PIPELINE.md +40 -49
- package/03-performance-web-vitals/CRITICAL-CSS.md +20 -27
- package/03-performance-web-vitals/FONTS-ZERO-CLS.md +30 -34
- package/03-performance-web-vitals/HYDRATION-STRATEGY.md +38 -21
- package/04-seo-ai-optimization/AEO-GEO-AI-SEARCH.md +28 -45
- package/04-seo-ai-optimization/GOOGLE-LOCAL-EEAT.md +20 -25
- package/04-seo-ai-optimization/STRUCTURED-DATA.md +42 -37
- package/05-internationalization/I18N-ARCHITECTURE.md +27 -25
- package/05-internationalization/LOCALE-TEMPLATE.json +23 -22
- package/06-business-conversion/B2C-B2B-MODELS.md +22 -21
- package/06-business-conversion/CONTEXTUAL-LEADS.md +17 -22
- package/06-business-conversion/EV-SOLAR-ECOSYSTEM.md +21 -21
- package/07-testing/TESTING-STRATEGY.md +45 -83
- package/08-token-optimization/TOKEN-STRATEGY.md +54 -103
- package/ALL.md +203 -52
- package/CHANGELOG.md +27 -0
- package/README.md +92 -97
- package/SPEC.md +81 -37
- package/bin/ds7.js +183 -100
- package/package.json +10 -11
- package/templates/component.vue +10 -16
- package/templates/nuxt.config.ts +19 -25
- package/templates/theme.css +17 -10
- package/ANDALUSIA.md +0 -89
- package/ff.md +0 -112
|
@@ -1,62 +1,68 @@
|
|
|
1
|
-
# 01
|
|
1
|
+
# 01 · Atomic Design and component levels
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Components are organised in five levels, after [Brad Frost's Atomic Design](https://atomicdesign.bradfrost.com/chapter-2/). Each level depends only on the levels below it. The goal is that a block works anywhere: on a page, in a sidebar, in a modal, or nested inside another block.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 1.
|
|
7
|
+
## 1. Levels
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
[1.
|
|
11
|
-
|
|
12
|
-
[2.
|
|
13
|
-
|
|
14
|
-
[3.
|
|
15
|
-
|
|
16
|
-
[4.
|
|
17
|
-
|
|
18
|
-
[5.
|
|
10
|
+
[1. Atoms] indivisible parts: button, icon, badge, field, price
|
|
11
|
+
│
|
|
12
|
+
[2. Molecules] small groups of atoms: product card, plan card, slider controls
|
|
13
|
+
│
|
|
14
|
+
[3. Organisms] self-contained widgets: card slider, feature grid, FAQ, calculator
|
|
15
|
+
│
|
|
16
|
+
[4. Templates] section layouts that compose organisms
|
|
17
|
+
│
|
|
18
|
+
[5. Pages] routes: fetch data, set SEO, pass props
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
## 2.
|
|
23
|
+
## 2. Rules per level
|
|
24
24
|
|
|
25
|
-
###
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
25
|
+
### Atoms — `app/components/ui/`
|
|
26
|
+
- Examples: `UiButton`, `UiIcon`, `UiPrice`, `UiBadge`, `UiField`, `UiLink`.
|
|
27
|
+
- Know nothing about pages, products or application state.
|
|
28
|
+
- Styled with a base class and short modifiers: `.btn.-sun`, `.btn.-sm`, `.btn.-outline`.
|
|
29
29
|
|
|
30
|
-
###
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
30
|
+
### Molecules — `app/components/ui/`
|
|
31
|
+
- Examples: `UiProductCard`, `UiSectionHeading`, `UiFeatureCard`, `UiPlanCard`, `UiSliderNav`.
|
|
32
|
+
- Built only from atoms and plain markup. Typed props and slots. No side effects.
|
|
33
|
+
- Must look right in a four-column grid and in a narrow sidebar. Use container queries.
|
|
34
34
|
|
|
35
|
-
###
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
35
|
+
### Organisms — `app/components/ui/`, `sections/`, `site/`
|
|
36
|
+
- Examples: `UiCardSlider`, `UiFeatureGrid`, `UiFaq`, `CalcPanel`, `SiteHeader`, `SiteFooter`.
|
|
37
|
+
- Own their local state: scroll position, active tab, open accordion item.
|
|
38
|
+
- Work through slots. A slider does not know that it shows products; it shows whatever molecules it receives.
|
|
39
39
|
|
|
40
|
-
###
|
|
41
|
-
-
|
|
42
|
-
-
|
|
40
|
+
### Templates and sections — `app/components/sections/`
|
|
41
|
+
- Compose organisms into a complete block of a page.
|
|
42
|
+
- No URL-specific logic and no hard-coded page content.
|
|
43
43
|
|
|
44
|
-
###
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
### Pages — `app/pages/`
|
|
45
|
+
Pages do three things only:
|
|
46
|
+
1. Call composables that read data from `app/data/`.
|
|
47
|
+
2. Set page metadata (`usePageSeo`).
|
|
48
|
+
3. Pass data to sections as props.
|
|
49
|
+
|
|
50
|
+
Pages do not contain inline card markup, custom sliders or bespoke grids.
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
-
## 3.
|
|
54
|
+
## 3. Embedding rule
|
|
55
|
+
|
|
56
|
+
Every component must be placeable:
|
|
57
|
+
1. in normal page flow;
|
|
58
|
+
2. inside a modal;
|
|
59
|
+
3. inside a tab or a calculator panel;
|
|
60
|
+
4. inside a narrow sidebar or a drawer.
|
|
61
|
+
|
|
62
|
+
Size comes from the parent box (`@container`), not from the screen (`@media`).
|
|
63
|
+
|
|
64
|
+
---
|
|
55
65
|
|
|
56
|
-
|
|
57
|
-
1. В обычный поток страницы;
|
|
58
|
-
2. Внутрь модального окна `UiModal`;
|
|
59
|
-
3. Внутрь вкладки калькулятора или табов;
|
|
60
|
-
4. Внутрь узкого сайдбара или всплывающей шторки.
|
|
66
|
+
## 4. Brand first
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
Levels are built top-down from the brandbook. Atoms come from tokens and the sandbox entries in `02-design-system/BRANDBOOK-SANDBOX.md`. A component that exists only in a page is not finished until it is in the sandbox.
|
|
@@ -1,27 +1,24 @@
|
|
|
1
|
-
# 01
|
|
1
|
+
# 01 · Component anatomy and container queries
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The reference shape of a Vue 3 single-file component in DS7. The template file is in `templates/component.vue`.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 1.
|
|
7
|
+
## 1. Shape
|
|
8
8
|
|
|
9
9
|
```vue
|
|
10
10
|
<script setup lang="ts">
|
|
11
11
|
/**
|
|
12
|
-
* UiProductCard
|
|
13
|
-
*
|
|
14
|
-
* Поддерживает адаптивность по контейнеру и каскадные модификаторы.
|
|
12
|
+
* UiProductCard — product card molecule.
|
|
13
|
+
* Container-aware. Modifiers are separate classes.
|
|
15
14
|
*/
|
|
16
15
|
|
|
17
|
-
// 1. Входные типизированные пропсы
|
|
18
16
|
const props = withDefaults(defineProps<{
|
|
19
17
|
title: string
|
|
20
18
|
description?: string
|
|
21
19
|
price?: number | null
|
|
22
20
|
badge?: 'top' | 'new' | 'sale'
|
|
23
21
|
specs?: Array<{ label: string; value: string }>
|
|
24
|
-
// Булевые пропсы-модификаторы для удобства в шаблонах:
|
|
25
22
|
top?: boolean
|
|
26
23
|
compact?: boolean
|
|
27
24
|
dark?: boolean
|
|
@@ -31,32 +28,27 @@ const props = withDefaults(defineProps<{
|
|
|
31
28
|
specs: () => [],
|
|
32
29
|
top: false,
|
|
33
30
|
compact: false,
|
|
34
|
-
dark: false
|
|
31
|
+
dark: false,
|
|
35
32
|
})
|
|
36
33
|
|
|
37
|
-
// 2. Вычисляемые классы-модификаторы
|
|
38
34
|
const rootClasses = computed(() => [
|
|
39
35
|
'p-card',
|
|
40
36
|
props.top && '-top',
|
|
41
37
|
props.compact && '-compact',
|
|
42
38
|
props.dark && '-dark',
|
|
43
|
-
props.badge && `-${props.badge}
|
|
39
|
+
props.badge && `-${props.badge}`,
|
|
44
40
|
])
|
|
45
41
|
</script>
|
|
46
42
|
|
|
47
43
|
<template>
|
|
48
44
|
<article :class="rootClasses" data-ref="CARD-01">
|
|
49
|
-
<!-- Слот для изображения или графического арта -->
|
|
50
45
|
<div class="p-card__art">
|
|
51
46
|
<slot name="art" />
|
|
52
47
|
</div>
|
|
53
48
|
|
|
54
|
-
<!-- Информационная часть -->
|
|
55
49
|
<div class="p-card__body">
|
|
56
50
|
<h3 class="p-card__title">{{ title }}</h3>
|
|
57
51
|
<p v-if="description" class="p-card__desc">{{ description }}</p>
|
|
58
|
-
|
|
59
|
-
<!-- Список характеристик (одна колонка) -->
|
|
60
52
|
<dl v-if="specs.length" class="p-card__specs">
|
|
61
53
|
<div v-for="s in specs" :key="s.label">
|
|
62
54
|
<dt>{{ s.label }}</dt>
|
|
@@ -65,7 +57,6 @@ const rootClasses = computed(() => [
|
|
|
65
57
|
</dl>
|
|
66
58
|
</div>
|
|
67
59
|
|
|
68
|
-
<!-- Футер с ценой и действием -->
|
|
69
60
|
<div class="p-card__footer">
|
|
70
61
|
<UiPrice v-if="price !== null" :amount="price" />
|
|
71
62
|
<slot name="action" />
|
|
@@ -74,10 +65,6 @@ const rootClasses = computed(() => [
|
|
|
74
65
|
</template>
|
|
75
66
|
|
|
76
67
|
<style>
|
|
77
|
-
/*
|
|
78
|
-
* Стили объявляются без scoped, но строго изолируются через префикс компонента.
|
|
79
|
-
* Это позволяет внешним родителям каскадно переопределять CSS-переменные.
|
|
80
|
-
*/
|
|
81
68
|
.p-card {
|
|
82
69
|
--card-bg: var(--color-white);
|
|
83
70
|
--card-ink: var(--color-ink);
|
|
@@ -91,7 +78,6 @@ const rootClasses = computed(() => [
|
|
|
91
78
|
padding: var(--space-4);
|
|
92
79
|
}
|
|
93
80
|
|
|
94
|
-
/* Контейнерный запрос: адаптация под размер родительского блока */
|
|
95
81
|
@container (max-width: 320px) {
|
|
96
82
|
.p-card {
|
|
97
83
|
padding: var(--space-2);
|
|
@@ -105,13 +91,11 @@ const rootClasses = computed(() => [
|
|
|
105
91
|
|
|
106
92
|
---
|
|
107
93
|
|
|
108
|
-
## 2.
|
|
94
|
+
## 2. Rules
|
|
109
95
|
|
|
110
|
-
1.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
4. **Слоты с фоллбэками:**
|
|
117
|
-
Для медиа (`#art`) и кнопок (`#action`) используются слоты, позволяя переиспользовать разметку под любые типы контента.
|
|
96
|
+
1. **Typed props.** Booleans for modifiers keep templates readable; `rootClasses` turns them into classes.
|
|
97
|
+
2. **`container-type: inline-size`** on any component with responsive states. It reacts to its box, not to the screen.
|
|
98
|
+
3. **Component-level custom properties** (`--card-bg`, `--card-ink`). Modifiers change the variables, not ten child selectors.
|
|
99
|
+
4. **Stable ID** in `data-ref` (`CARD-01`). It links the live component to its entry in the brandbook.
|
|
100
|
+
5. **Slots with fallbacks** for media and actions. The component works with any content in those slots.
|
|
101
|
+
6. **A one-line summary** at the top of the file, as in the example.
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
# 01
|
|
1
|
+
# 01 · Modifier system and ancestry scoping
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
One base component, many variants, no duplicate components.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 1.
|
|
7
|
+
## 1. Syntax
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Use a base class plus separate modifier classes. Each modifier starts with a dash:
|
|
10
10
|
|
|
11
11
|
```html
|
|
12
|
-
<!-- Карточка товара: топовая, новинка, компактный размер -->
|
|
13
12
|
<article class="p-card -top -new -compact">
|
|
14
|
-
<div class="p-card__art"
|
|
15
|
-
<h3 class="p-card__title">Panel
|
|
16
|
-
<div class="p-card__price"
|
|
13
|
+
<div class="p-card__art">…</div>
|
|
14
|
+
<h3 class="p-card__title">Panel 450 W</h3>
|
|
15
|
+
<div class="p-card__price">…</div>
|
|
17
16
|
</article>
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
Why:
|
|
20
|
+
- **Short class names** keep HTML and CSS small.
|
|
21
|
+
- **Modifiers combine** freely: `-top -compact`, `-dark -lg`.
|
|
22
|
+
- **Modifiers cascade:** a modifier on the root can change every child.
|
|
23
|
+
|
|
24
|
+
Avoid long compound names such as `catalog-product-card--featured-large-dark`.
|
|
24
25
|
|
|
25
26
|
---
|
|
26
27
|
|
|
27
|
-
## 2.
|
|
28
|
+
## 2. Cascade from a modifier
|
|
28
29
|
|
|
29
30
|
```css
|
|
30
|
-
/* Базовый компонент */
|
|
31
31
|
.p-card {
|
|
32
32
|
--card-bg: var(--color-white);
|
|
33
33
|
--card-text: var(--color-ink);
|
|
@@ -38,10 +38,8 @@
|
|
|
38
38
|
border: 1px solid var(--card-border);
|
|
39
39
|
border-radius: var(--radius-md);
|
|
40
40
|
padding: var(--space-4);
|
|
41
|
-
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
/* Модификатор: TOP товар */
|
|
45
43
|
.p-card.-top {
|
|
46
44
|
--card-border: var(--color-sun);
|
|
47
45
|
box-shadow: var(--shadow-lift);
|
|
@@ -50,52 +48,43 @@
|
|
|
50
48
|
font-weight: 700;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
/* Модификатор: Компактный режим */
|
|
54
51
|
.p-card.-compact {
|
|
55
52
|
padding: var(--space-2);
|
|
56
53
|
}
|
|
57
|
-
.p-card.-compact .p-card__title {
|
|
58
|
-
font-size: 0.85rem;
|
|
59
|
-
}
|
|
60
54
|
|
|
61
|
-
/* Модификатор: Темная тема */
|
|
62
55
|
.p-card.-dark {
|
|
63
56
|
--card-bg: var(--color-ink-950);
|
|
64
57
|
--card-text: var(--color-white);
|
|
65
|
-
--card-border:
|
|
58
|
+
--card-border: rgba(255, 255, 255, 0.12);
|
|
66
59
|
}
|
|
67
60
|
```
|
|
68
61
|
|
|
69
|
-
|
|
62
|
+
Modifiers change custom properties where possible. That keeps the number of selectors small.
|
|
70
63
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Если один и тот же рабочий компонент (слайдер, форма, плашка хука) должен выглядеть иначе на определенной странице (например, на странице для бизнеса `/empresas` фон должен быть графитовым, а на главной — песочным):
|
|
64
|
+
---
|
|
74
65
|
|
|
75
|
-
|
|
76
|
-
Создавать два разных файла: `HookHome.vue` и `HookEmpresas.vue`.
|
|
66
|
+
## 3. Context from an ancestor
|
|
77
67
|
|
|
78
|
-
|
|
79
|
-
Использовать единый компонент `UiHeroHook`, а различия задавать через родительский контекст — класс страницы на теге `<body>`:
|
|
68
|
+
Sometimes a shared component must look different on one page. Do not create a second component. Scope the difference by an ancestor:
|
|
80
69
|
|
|
81
70
|
```css
|
|
82
|
-
/*
|
|
71
|
+
/* the hook everywhere */
|
|
83
72
|
.hero-hook {
|
|
84
73
|
background: var(--color-paper);
|
|
85
74
|
color: var(--color-ink);
|
|
86
75
|
}
|
|
87
76
|
|
|
88
|
-
/*
|
|
89
|
-
body.page-
|
|
77
|
+
/* the same hook on a dark page */
|
|
78
|
+
body.page-business .hero-hook {
|
|
90
79
|
background: var(--color-ink-950);
|
|
91
80
|
color: var(--color-white);
|
|
92
81
|
}
|
|
93
82
|
|
|
94
|
-
/*
|
|
83
|
+
/* the same hook inside a modal */
|
|
95
84
|
.site-modal-box .hero-hook {
|
|
96
85
|
background: transparent;
|
|
97
86
|
padding: 0;
|
|
98
87
|
}
|
|
99
88
|
```
|
|
100
89
|
|
|
101
|
-
|
|
90
|
+
The page class on `<body>` is set by `usePageSeo` (`page-home`, `page-residential`, `page-business`, …). Wrong: `HookHome.vue` and `HookBusiness.vue`. Right: one `UiHeroHook` with context rules.
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
# 02
|
|
1
|
+
# 02 · Brandbook and sandbox (`/ui`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The `/ui` page of a project is a live sandbox: every foundation token and every base component, shown in its real code. It is the shared vocabulary between people and agents.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 1.
|
|
7
|
+
## 1. Stable component IDs
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Every reusable pattern has one short ID:
|
|
10
10
|
|
|
11
|
-
| ID |
|
|
11
|
+
| ID | Name | Use |
|
|
12
12
|
|---|---|---|
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
13
|
+
| `BTN-01` | Primary button | main action; sun fill with an arrow |
|
|
14
|
+
| `BTN-02` | Outline button | secondary action |
|
|
15
|
+
| `CTL-01` | Segmented switch | tabs or periods |
|
|
16
|
+
| `COUNTER-01` | Bounded numeric counter | number input with − / + buttons; variant `-inner` |
|
|
17
|
+
| `PRICE-01` | Formatted price | amount with currency suffix and optional "from" label |
|
|
18
|
+
| `CARD-01` | Base product card | catalogue item with modifiers |
|
|
19
|
+
| `CARD-02` | Plan / tariff card | package with a list of options |
|
|
20
|
+
| `SLD-01` | Card slider | scroll-snap slider with navigation |
|
|
21
|
+
| `HOOK-01` | Overlap hook | panel that overlaps a cover image |
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
Вместо того чтобы писать разработчику или ИИ:
|
|
24
|
-
> *«Сделай мне карточку товара, где сверху картинка, снизу цена, обведи желтой рамочкой и поставь скругление 12px...»*
|
|
23
|
+
**How it is used.** Instead of describing a card in full, say:
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
> *«Поставь в этот блок `CARD-01 -top` и кнопку `BTN-01`»*.
|
|
25
|
+
> "Put `CARD-01 -top` in this block, with `BTN-01` as the action."
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
Both a person and an agent understand that without a second description.
|
|
30
28
|
|
|
31
29
|
---
|
|
32
30
|
|
|
33
|
-
## 2.
|
|
31
|
+
## 2. What the sandbox shows
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- `[x] -top`
|
|
39
|
-
- `[x] -new`
|
|
40
|
-
- `[x] -compact`
|
|
41
|
-
- `[x] -dark`
|
|
42
|
-
2. **Контекстный переключатель фона:**
|
|
43
|
-
Кнопки переключения подложки («На светлом фоне», «На темном фоне», «В модалке»), чтобы сразу видеть контрастность и поведение текста.
|
|
44
|
-
3. **Кнопка «Скопировать код»:**
|
|
45
|
-
Рядом с каждым образцом расположена кнопка копирования эталонного Vue-сниппета для быстрой вставки в проект.
|
|
33
|
+
1. **Modifier toggles** for each component: `-top`, `-new`, `-compact`, `-dark`.
|
|
34
|
+
2. **Background switch:** light, dark, inside a modal. Contrast is visible on each.
|
|
35
|
+
3. **Copy code** next to each example: the reference snippet for pasting into a project.
|
|
46
36
|
|
|
47
37
|
---
|
|
48
38
|
|
|
49
|
-
## 3.
|
|
39
|
+
## 3. Update rule
|
|
50
40
|
|
|
51
|
-
|
|
52
|
-
|
|
41
|
+
Every new atom, molecule or token must appear in the sandbox before it is used on a page. A component that is missing from `/ui` is not finished. The sandbox is excluded from search indexing (`noindex, nofollow`) and from `sitemap.xml`.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 4. Brand-first workflow
|
|
46
|
+
|
|
47
|
+
1. Add or change foundations in `theme.css`.
|
|
48
|
+
2. Add or change the entry in the sandbox.
|
|
49
|
+
3. Build or change the component.
|
|
50
|
+
4. Use the component on a page.
|
|
51
|
+
|
|
52
|
+
Changing a token changes the sandbox first; the sandbox is the visual reference for review.
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
# 02
|
|
1
|
+
# 02 · Naming conventions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Short, semantic class names keep HTML small and make CSS readable. The formula and the rules are the same for every project.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 1.
|
|
7
|
+
## 1. Examples
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
Мы используем краткие, интуитивно понятные сокращения:
|
|
11
|
-
|
|
12
|
-
| Было (громоздко) | Стало в DS7 (минималистично и чисто) |
|
|
9
|
+
| Long name | DS7 name |
|
|
13
10
|
|---|---|
|
|
14
11
|
| `.catalog-product-card` | `.p-card` |
|
|
15
12
|
| `.catalog-product-card--featured` | `.p-card.-top` |
|
|
@@ -21,23 +18,28 @@
|
|
|
21
18
|
|
|
22
19
|
---
|
|
23
20
|
|
|
24
|
-
## 2.
|
|
21
|
+
## 2. Formula
|
|
25
22
|
|
|
26
23
|
```
|
|
27
|
-
.[
|
|
24
|
+
.[component] base name, short kebab-case
|
|
25
|
+
.[component]__[part] element, double underscore
|
|
26
|
+
.-[modifier] modifier, separate class with a leading dash
|
|
27
|
+
.is-[state] state
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
3.
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 3. Rules
|
|
33
|
+
|
|
34
|
+
1. **No word appended to a base name.** `.btn-lg`, `.card-big`, `.hero-active` are wrong. Write `.btn.-lg`, `.card.-big`, `.hero.is-active`.
|
|
35
|
+
2. **Size and colour words are modifiers.** `-sm`, `-lg`, `-sun`, `-dark`. Not `-big`, `-red`, `-orange`.
|
|
36
|
+
3. **Element names describe the part.** `__title`, `__price`, `__art`, not `__text2` or `__left`.
|
|
37
|
+
4. **Only tokens in values.** Naming does not replace the token rule in `TOKENS-SPEC.md`.
|
|
33
38
|
|
|
34
39
|
---
|
|
35
40
|
|
|
36
|
-
##
|
|
41
|
+
## 4. Build-time minification
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Минификатор удаляет комментарии, склеивает правила, сокращает цвета (`#ffffff` → `#fff`, `0px` → `0`) и преобразует повторяющиеся структуры в сжатый бинарный вид для передачи по gzip/brotli.
|
|
42
|
-
3. **Разделение критических и второстепенных стилей:**
|
|
43
|
-
Критический CSS встраивается в HTML, а вторичные стили сжимаются и кэшируются на год (`Cache-Control: immutable`).
|
|
43
|
+
- Unused styles are removed when the site is generated. Only classes that appear in the output ship.
|
|
44
|
+
- The CSS minifier removes comments and shortens values (`#ffffff` → `#fff`).
|
|
45
|
+
- Critical CSS is inlined; the rest is a cached file with a content hash in its name.
|