pasika 0.1.4 → 0.1.6
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/dist/eslint/pasika/index.js +3 -0
- package/dist/eslint/pasika/rules/filename-case.d.ts +2 -0
- package/dist/eslint/pasika/rules/filename-case.js +90 -0
- package/docs/agent-conventions.md +6 -0
- package/docs/code-organization-guide/code-organization-guide.md +24 -20
- package/docs/code-organization-guide/references/application-architecture-reference.md +61 -19
- package/docs/code-organization-guide/rules/component-placement-rule.md +9 -25
- package/docs/code-organization-guide/rules/configuration-rule.md +9 -9
- package/docs/code-organization-guide/rules/constants-rule.md +5 -8
- package/docs/code-organization-guide/rules/exports-and-imports-rule.md +10 -7
- package/docs/code-organization-guide/rules/folder-nesting-rule.md +1 -2
- package/docs/code-organization-guide/rules/hook-extraction-rule.md +4 -5
- package/docs/code-organization-guide/rules/interactive-component-rule.md +7 -10
- package/docs/code-organization-guide/rules/jsx-hygiene-rule.md +2 -3
- package/docs/code-organization-guide/rules/locales-rule.md +2 -4
- package/docs/code-organization-guide/rules/no-mixed-concerns-rule.md +0 -1
- package/docs/code-organization-guide/rules/repeated-structure-rule.md +1 -1
- package/docs/code-organization-guide/rules/smart-vs-dumb-component-rule.md +2 -6
- package/docs/code-organization-guide/rules/sole-state-owner-rule.md +1 -2
- package/docs/code-organization-guide/rules/types-and-schemas-rule.md +7 -6
- package/docs/code-organization-guide/rules/utilities-rule.md +1 -2
- package/docs/documentation-guide/_templates/grouped-reference.md +11 -0
- package/docs/documentation-guide/_templates/guide.md +1 -1
- package/docs/documentation-guide/_templates/single-lookup-reference.md +5 -0
- package/docs/documentation-guide/references/documentation-types-reference.md +6 -6
- package/docs/documentation-guide/rules/guide-creation-rule.md +1 -0
- package/docs/documentation-guide/rules/reference-creation-rule.md +1 -1
- package/docs/documentation-guide/rules/template-usage-rule.md +2 -1
- package/docs/styling-guide/rules/arbitrary-value-rule.md +31 -0
- package/docs/styling-guide/rules/class-composition-rule.md +30 -10
- package/docs/styling-guide/rules/component-ui-state-rule.md +53 -0
- package/docs/styling-guide/rules/component-variant-rule.md +35 -38
- package/docs/styling-guide/rules/global-stylesheet-rule.md +67 -0
- package/docs/styling-guide/rules/theme-and-utility-definition-rule.md +39 -82
- package/docs/styling-guide/styling-guide.md +8 -11
- package/package.json +1 -1
- package/docs/code-organization-guide/rules/native-prop-forwarding-rule.md +0 -38
- package/docs/documentation-guide/_templates/reference.md +0 -17
- package/docs/styling-guide/rules/color-role-naming-rule.md +0 -115
- package/docs/styling-guide/rules/component-state-rule.md +0 -26
- package/docs/styling-guide/rules/global-style-system-rule.md +0 -63
- package/docs/styling-guide/rules/style-placement-rule.md +0 -49
- package/docs/styling-guide/rules/tailwind-utility-rule.md +0 -48
- package/docs/styling-guide/rules/theme-token-rule.md +0 -32
|
@@ -1,129 +1,86 @@
|
|
|
1
1
|
# Theme and Utility Definition Rule
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This rule decides when styling stays with one component or becomes a shared utility, and how project values are exposed through Tailwind.
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
- A
|
|
7
|
-
- A
|
|
8
|
-
- A
|
|
9
|
-
- A
|
|
10
|
-
- A
|
|
11
|
-
- Project-owned style declarations inside `@utility` and unavoidable global selectors MUST use `@apply`.
|
|
12
|
-
- A custom utility MUST use Tailwind custom-property or arbitrary-property utility syntax through `@apply` when no named built-in utility represents the property value.
|
|
13
|
-
- A custom utility that owns interaction behavior MUST keep its hover, active, focus, and disabled treatments in the same utility block.
|
|
14
|
-
- Component markup MUST NOT contain literal arbitrary values in place of missing project tokens or utilities.
|
|
5
|
+
- Styling used by only one component MUST stay in that component file as static Tailwind utility classes and MUST NOT be moved to the global stylesheet.
|
|
6
|
+
- A style or group of styles that two or more components use together and should change together MUST become one named custom utility. The group MAY include utilities generated by theme variables, built-in utilities, other custom utilities, and interaction styles.
|
|
7
|
+
- A value that needs at least two utility classes from the same [Tailwind theme-variable namespace](https://tailwindcss.com/docs/theme#theme-variable-namespaces) MUST use that namespace and have the same name in `:root`.
|
|
8
|
+
- A CSS variable intended only for a background MUST be named `--<role>-canvas`, and one intended only for readable text MUST be named `--<role>-ink`. When a named custom utility exposes one of those values by itself, it MUST use `bg-<role>-canvas` or `text-<role>-ink`.
|
|
9
|
+
- A repeated combination of canvas, ink, and related styles MUST become a `*-surface` custom Tailwind utility that owns the combination.
|
|
10
|
+
- A custom utility MUST use `@apply` for every styling declaration added by the project. When no named built-in utility represents a property value, it MUST apply the Tailwind custom-property or arbitrary-property utility instead.
|
|
15
11
|
|
|
16
|
-
## Incorrect —
|
|
12
|
+
## Incorrect — Property-Specific Color Exposed Broadly
|
|
17
13
|
|
|
18
14
|
```css
|
|
19
|
-
|
|
20
|
-
--color-header-ink:
|
|
15
|
+
:root {
|
|
16
|
+
--color-header-ink: #111827;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@theme inline {
|
|
20
|
+
--color-header-ink: var(--color-header-ink);
|
|
21
21
|
}
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
```tsx
|
|
25
25
|
<h1 className="text-header-ink">Title</h1>
|
|
26
|
-
<div className="bg-header-ink" />
|
|
27
26
|
```
|
|
28
27
|
|
|
29
|
-
Why:
|
|
28
|
+
Why: registering a text-only color in `--color-*` also creates unintended background, border, ring, and other color utilities.
|
|
30
29
|
|
|
31
|
-
## Correct —
|
|
30
|
+
## Correct — Property-Specific Utility
|
|
32
31
|
|
|
33
32
|
```css
|
|
34
33
|
:root {
|
|
35
34
|
--header-ink: #111827;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
@
|
|
39
|
-
--*: initial;
|
|
40
|
-
--spacing: 0.25rem;
|
|
41
|
-
--font-body: Inter, sans-serif;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@utility text-header {
|
|
37
|
+
@utility text-header-ink {
|
|
45
38
|
@apply text-(--header-ink);
|
|
46
39
|
}
|
|
47
40
|
```
|
|
48
41
|
|
|
49
42
|
```tsx
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Why: only explicitly defined theme values remain available, while the private header color exposes exactly one text utility.
|
|
54
|
-
|
|
55
|
-
## Incorrect — Runtime Theme Variable Mapped Without `inline`
|
|
56
|
-
|
|
57
|
-
```css
|
|
58
|
-
:root {
|
|
59
|
-
--primary: #7c3aed;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.dark {
|
|
63
|
-
--primary: #a78bfa;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
@theme {
|
|
67
|
-
--color-primary: var(--primary);
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Why: the public token uses runtime variable indirection without the inline mapping intended for selector-driven theme values.
|
|
72
|
-
|
|
73
|
-
## Correct — Runtime Theme Variable Mapped Inline
|
|
74
|
-
|
|
75
|
-
```css
|
|
76
|
-
:root {
|
|
77
|
-
--primary: #7c3aed;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.dark {
|
|
81
|
-
--primary: #a78bfa;
|
|
82
|
-
}
|
|
43
|
+
// SiteHeader.tsx
|
|
44
|
+
<h1 className="text-header-ink">Title</h1>
|
|
83
45
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
46
|
+
// PageHeader.tsx
|
|
47
|
+
<h2 className="text-header-ink">Settings</h2>
|
|
87
48
|
```
|
|
88
49
|
|
|
89
|
-
Why:
|
|
50
|
+
Why: both components use the same text-only color, so one named text utility owns it without creating background, border, or ring utilities.
|
|
90
51
|
|
|
91
|
-
## Incorrect —
|
|
52
|
+
## Incorrect — Property-Specific Colors Exposed Broadly
|
|
92
53
|
|
|
93
54
|
```css
|
|
94
|
-
@
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
@utility surface-primary-hover {
|
|
99
|
-
background-color: var(--primary-canvas-hover);
|
|
55
|
+
@theme {
|
|
56
|
+
--color-primary-canvas: #d87943;
|
|
57
|
+
--color-primary-ink: #ffffff;
|
|
100
58
|
}
|
|
101
59
|
```
|
|
102
60
|
|
|
103
61
|
```tsx
|
|
104
|
-
<button className="
|
|
62
|
+
<button className="bg-primary-canvas text-primary-ink">Save</button>
|
|
63
|
+
<button className="bg-primary-canvas text-primary-ink">Continue</button>
|
|
105
64
|
```
|
|
106
65
|
|
|
107
|
-
Why:
|
|
66
|
+
Why: property-specific colors are exposed as broad Tailwind colors, and the repeated combination has no named owner.
|
|
108
67
|
|
|
109
|
-
## Correct —
|
|
68
|
+
## Correct — Color Roles Expose Their Intended API
|
|
110
69
|
|
|
111
70
|
```css
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
@apply bg-(--primary-canvas-hover);
|
|
117
|
-
}
|
|
71
|
+
:root {
|
|
72
|
+
--primary-canvas: #d87943;
|
|
73
|
+
--primary-ink: #ffffff;
|
|
74
|
+
}
|
|
118
75
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
76
|
+
@utility primary-surface {
|
|
77
|
+
@apply bg-(--primary-canvas) text-(--primary-ink);
|
|
122
78
|
}
|
|
123
79
|
```
|
|
124
80
|
|
|
125
81
|
```tsx
|
|
126
|
-
<button className="surface
|
|
82
|
+
<button className="primary-surface">Save</button>
|
|
83
|
+
<button className="primary-surface">Continue</button>
|
|
127
84
|
```
|
|
128
85
|
|
|
129
|
-
Why:
|
|
86
|
+
Why: canvas and ink CSS variables are used only by `primary-surface`, and the repeated combination has one named owner.
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
# Styling Guide
|
|
2
2
|
|
|
3
|
-
This guide keeps component styling predictable without making consumers learn a component's DOM or a project's CSS internals.
|
|
3
|
+
This guide keeps component styling predictable without making consumers learn a component's DOM or a project's CSS internals. It applies whenever UI styling is added or changed.
|
|
4
4
|
|
|
5
5
|
## How To Style a Component
|
|
6
6
|
|
|
7
|
-
Use this workflow when implementing a component or changing
|
|
7
|
+
Use this workflow when implementing a component or changing its appearance.
|
|
8
8
|
|
|
9
|
-
1. Follow the [
|
|
10
|
-
2. Follow the [
|
|
11
|
-
3. Follow the [
|
|
12
|
-
4. Follow the [
|
|
13
|
-
5. Follow the [
|
|
14
|
-
6. Follow the [
|
|
15
|
-
7. Follow the [Global Style System Rule](rules/global-style-system-rule.md) so global CSS has one source of truth and a clear ownership boundary.
|
|
16
|
-
8. Follow the [Style Placement Rule](rules/style-placement-rule.md) so reusable styling has one appropriate owner.
|
|
17
|
-
9. Follow the [Component State Rule](rules/component-state-rule.md) so interaction, disabled, selected, loading, and error states stay coherent.
|
|
9
|
+
1. Follow the [Global Stylesheet Rule](rules/global-stylesheet-rule.md) so one stylesheet entry point owns all of the project's global CSS.
|
|
10
|
+
2. Follow the [Theme and Utility Definition Rule](rules/theme-and-utility-definition-rule.md) so CSS variables, Tailwind namespaces, and custom utilities expose only the intended API.
|
|
11
|
+
3. Follow the [Arbitrary Value Rule](rules/arbitrary-value-rule.md) so values used for the project's styling use named utilities or tokens instead of literal arbitrary classes.
|
|
12
|
+
4. Follow the [Class Composition Rule](rules/class-composition-rule.md) so conditional and consumer-supplied classes merge predictably.
|
|
13
|
+
5. Follow the [Component Variant Rule](rules/component-variant-rule.md) so supported internal appearances are a typed component API.
|
|
14
|
+
6. Follow the [Component UI State Rule](rules/component-ui-state-rule.md) so interaction, disabled, selected, loading, and error UI states stay coherent.
|
package/package.json
CHANGED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Native Prop Forwarding Rule
|
|
2
|
-
|
|
3
|
-
When a `src/shared/` component renders the same intrinsic root element in every rendered result, a smaller custom prop interface can hide capabilities that consumers need. This rule preserves native props while allowing focused component-specific props.
|
|
4
|
-
|
|
5
|
-
- A `src/shared/` component with the same intrinsic root element in every rendered result MUST include that element's native props in its props type.
|
|
6
|
-
- A `src/shared/` component with the same intrinsic root element in every rendered result MUST forward unconsumed native props to that element.
|
|
7
|
-
- A `src/shared/` component with the same intrinsic root element in every rendered result MAY add component-specific props alongside its native props.
|
|
8
|
-
|
|
9
|
-
## Incorrect — Native Props Replaced
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
// src/shared/button.tsx
|
|
13
|
-
type ButtonProps = {
|
|
14
|
-
label: string;
|
|
15
|
-
onClick(): void;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export function Button({ label, onClick }: ButtonProps) {
|
|
19
|
-
return <button onClick={onClick}>{label}</button>;
|
|
20
|
-
}
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Why: the custom interface leaves out native button props such as `disabled`, `type`, and accessible labels.
|
|
24
|
-
|
|
25
|
-
## Correct — Native Props Extended and Forwarded
|
|
26
|
-
|
|
27
|
-
```tsx
|
|
28
|
-
// src/shared/button.tsx
|
|
29
|
-
type ButtonProps = React.ComponentProps<"button"> & {
|
|
30
|
-
loading?: boolean;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export function Button({ className, loading, disabled, ...props }: ButtonProps) {
|
|
34
|
-
return <button className={cn("inline-flex items-center", className)} disabled={disabled || loading} {...props} />;
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Why: the component forwards its unused native props while adding the `loading` state it needs.
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# [Topic] Reference
|
|
2
|
-
|
|
3
|
-
[1-2 short sentences naming exactly what readers can look up here and when they should use this reference.]
|
|
4
|
-
|
|
5
|
-
[Single lookup content — table, glossary, hierarchy, catalog, or config block. Keep this branch only when the reference has exactly one lookup block; it has no section heading. Otherwise delete this branch and use one heading per lookup group below.]
|
|
6
|
-
|
|
7
|
-
## [First Lookup Group Name]
|
|
8
|
-
|
|
9
|
-
[1-2 short sentences explaining what this group contains and why it is included.]
|
|
10
|
-
|
|
11
|
-
[Place this group's lookup content here.]
|
|
12
|
-
|
|
13
|
-
## [Next Lookup Group Name]
|
|
14
|
-
|
|
15
|
-
[1-2 short sentences explaining what this group contains and why it is included.]
|
|
16
|
-
|
|
17
|
-
[Place this group's lookup content here. Repeat the heading, explanation, and lookup content for every remaining group; delete this multi-block branch when the reference has one lookup block.]
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# Color Role Naming Rule
|
|
2
|
-
|
|
3
|
-
Color names should reveal what a utility is safe to do, while keeping broadly reusable colors pleasant to use. This rule makes background-only colors, readable text colors, and complete treatments distinct without adding ceremony to general-purpose colors.
|
|
4
|
-
|
|
5
|
-
- A color that is intentionally reusable across background, text, border, ring, or other CSS properties MUST use its role name without a property suffix.
|
|
6
|
-
- A color intended only for a background MUST use the `-canvas` suffix, and a color intended only for readable text MUST use the `-ink` suffix.
|
|
7
|
-
- A `*-canvas` or `*-ink` value MUST remain a private CSS variable and be exposed only through its matching property-specific custom utility.
|
|
8
|
-
- `base-canvas` and `base-ink` MUST be applied only by the document body or the project's global base layer as the default page pair.
|
|
9
|
-
- A repeated canvas, ink, and related treatment MUST become a `surface-*` custom utility that owns the complete treatment.
|
|
10
|
-
- A general-purpose color backed by runtime-selectable theme variables MUST use `@theme inline` so Tailwind utilities remain stable while values change.
|
|
11
|
-
- A one-off background MAY use a `*-canvas` utility directly when it does not form a repeated named surface.
|
|
12
|
-
|
|
13
|
-
## Incorrect — Property-Specific Colors Exposed Broadly
|
|
14
|
-
|
|
15
|
-
```css
|
|
16
|
-
@theme {
|
|
17
|
-
--color-primary-background: #d87943;
|
|
18
|
-
--color-primary-text: #ffffff;
|
|
19
|
-
}
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
```tsx
|
|
23
|
-
<main className="bg-page text-page-text" />
|
|
24
|
-
<button className="bg-primary-background text-primary-text">Save</button>
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Why: the names are inconsistent, the document defaults can be applied anywhere, and the repeated button treatment has no single owner.
|
|
28
|
-
|
|
29
|
-
## Correct — Color Roles Expose Their Intended API
|
|
30
|
-
|
|
31
|
-
```css
|
|
32
|
-
:root {
|
|
33
|
-
--base-canvas: #ffffff;
|
|
34
|
-
--base-ink: #111827;
|
|
35
|
-
--primary: #d87943;
|
|
36
|
-
--primary-canvas: #d87943;
|
|
37
|
-
--primary-ink: #ffffff;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.dark {
|
|
41
|
-
--base-canvas: #111827;
|
|
42
|
-
--base-ink: #f9fafb;
|
|
43
|
-
--primary: #f1a06e;
|
|
44
|
-
--primary-canvas: #f1a06e;
|
|
45
|
-
--primary-ink: #111827;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
@theme {
|
|
49
|
-
--*: initial;
|
|
50
|
-
--shadow-sm: 0 1px 2px rgb(0 0 0 / 0.15);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
@theme inline {
|
|
54
|
-
--color-primary: var(--primary);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
@utility bg-base-canvas {
|
|
58
|
-
@apply bg-(--base-canvas);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
@utility text-base-ink {
|
|
62
|
-
@apply text-(--base-ink);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
@utility bg-primary-canvas {
|
|
66
|
-
@apply bg-(--primary-canvas);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
@utility text-primary-ink {
|
|
70
|
-
@apply text-(--primary-ink);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
@utility surface-primary {
|
|
74
|
-
@apply bg-primary-canvas text-primary-ink shadow-sm;
|
|
75
|
-
|
|
76
|
-
&:hover {
|
|
77
|
-
@apply brightness-105;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
@layer base {
|
|
82
|
-
body {
|
|
83
|
-
@apply bg-base-canvas text-base-ink;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
```tsx
|
|
89
|
-
// `primary` is useful for more than one CSS property.
|
|
90
|
-
<a className="text-primary" />
|
|
91
|
-
<button className="surface-primary">Save</button>
|
|
92
|
-
|
|
93
|
-
// This background is a one-off rather than a named surface.
|
|
94
|
-
<aside className="bg-primary-canvas text-primary-ink" />
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Why: general-purpose colors stay suffix-free, property-specific colors reveal their role, the page defaults have one owner, and the reusable primary treatment owns its colors and behavior together.
|
|
98
|
-
|
|
99
|
-
## Promotion Path
|
|
100
|
-
|
|
101
|
-
Promote styling only as its reuse or design meaning grows:
|
|
102
|
-
|
|
103
|
-
```txt
|
|
104
|
-
Tailwind utility -> theme color -> paired color -> surface utility -> component variant
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## When To Create a Named Surface
|
|
108
|
-
|
|
109
|
-
Create a named `surface-*` utility when one or more of these signals applies:
|
|
110
|
-
|
|
111
|
-
- The combination repeats in multiple places.
|
|
112
|
-
- The combination has a clear product or design meaning.
|
|
113
|
-
- Designers refer to the combination as a named treatment.
|
|
114
|
-
- The combination needs to stay consistent across components.
|
|
115
|
-
- The treatment includes more than color, such as a border, hover state, or shadow.
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Component State Rule
|
|
2
|
-
|
|
3
|
-
Visual state communicates whether a component can be used and what will happen when it is used. This rule keeps that feedback owned by the component rather than reconstructed by every caller.
|
|
4
|
-
|
|
5
|
-
- A component MUST provide a visually distinguishable treatment for every state it supports, including hover, focus, active, disabled, selected, loading, and error states when applicable.
|
|
6
|
-
- Components MUST keep state styling with the component or its variant definition when the state is intrinsic to its behavior.
|
|
7
|
-
- Components SHOULD use native semantic elements and attributes so browser, keyboard, and assistive-technology behavior matches the visual state.
|
|
8
|
-
- Components MAY accept state props when the state is controlled by their parent.
|
|
9
|
-
|
|
10
|
-
## Incorrect — State Styled Only with Classes
|
|
11
|
-
|
|
12
|
-
```tsx
|
|
13
|
-
<Button className={isSaving ? "pointer-events-none opacity-50" : ""}>Save</Button>
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Why: every caller has to reconstruct the saving or disabled treatment, and the button does not receive a semantic disabled state.
|
|
17
|
-
|
|
18
|
-
## Correct — State Exposed Through Component Props
|
|
19
|
-
|
|
20
|
-
```tsx
|
|
21
|
-
<Button disabled={isSaving} loading={isSaving}>
|
|
22
|
-
Save
|
|
23
|
-
</Button>
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Why: the component owns its loading and disabled treatment through a stable API, and the same ownership applies to every other state it supports.
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# Global Style System Rule
|
|
2
|
-
|
|
3
|
-
Global CSS is the integration point for Tailwind registration, the project theme, base styles, and imported style domains. This rule keeps one active entry point and a predictable ownership order.
|
|
4
|
-
|
|
5
|
-
- A repository MUST have one active global stylesheet that owns Tailwind registration and imports every global style domain it uses.
|
|
6
|
-
- The global stylesheet MUST reset the default Tailwind theme and register the project's explicit theme values.
|
|
7
|
-
- Static theme values MUST live directly in `@theme`, while selector-driven variable mappings MUST live in `@theme inline`.
|
|
8
|
-
- Global CSS MUST be ordered as imports, Tailwind and custom-variant registration, theme definitions and selectors, custom utilities, base styles, keyframes, then unavoidable global selectors.
|
|
9
|
-
- Imported global style domains MUST have one owner and MUST NOT duplicate theme values or utilities defined by another domain.
|
|
10
|
-
|
|
11
|
-
## Incorrect — Global Styles Split Across Unrelated Files
|
|
12
|
-
|
|
13
|
-
```css
|
|
14
|
-
/* Theme values and component recipes compete across unrelated files. */
|
|
15
|
-
.save-button {
|
|
16
|
-
@apply bg-primary;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
@theme {
|
|
20
|
-
--color-primary: #7c3aed;
|
|
21
|
-
}
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Why: a component recipe sits globally beside an unreset theme, and the stylesheet does not establish a clear integration order.
|
|
25
|
-
|
|
26
|
-
## Correct — One Global Stylesheet Owns the System
|
|
27
|
-
|
|
28
|
-
```css
|
|
29
|
-
@import "tailwindcss";
|
|
30
|
-
|
|
31
|
-
@custom-variant dark (&:where(.dark, .dark *));
|
|
32
|
-
|
|
33
|
-
@theme {
|
|
34
|
-
--*: initial;
|
|
35
|
-
--spacing: 0.25rem;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
:root {
|
|
39
|
-
--base-canvas: #ffffff;
|
|
40
|
-
--base-ink: #111827;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.dark {
|
|
44
|
-
--base-canvas: #111827;
|
|
45
|
-
--base-ink: #ffffff;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
@utility bg-base-canvas {
|
|
49
|
-
@apply bg-(--base-canvas);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
@utility text-base-ink {
|
|
53
|
-
@apply text-(--base-ink);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
@layer base {
|
|
57
|
-
body {
|
|
58
|
-
@apply bg-base-canvas text-base-ink;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Why: one entry point registers Tailwind, resets the theme, defines selector-driven values, exposes intended utilities, and applies document defaults in a predictable order.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Style Placement Rule
|
|
2
|
-
|
|
3
|
-
Every project-owned style needs one implementation owner. This rule decides whether styling belongs beside component markup, in a named custom utility, or behind an unavoidable global selector.
|
|
4
|
-
|
|
5
|
-
- Single-use component styling MUST stay colocated in the component through Tailwind utility classes or a local class constant.
|
|
6
|
-
- A reusable behavior or treatment that has a stable design meaning MUST become a named custom utility.
|
|
7
|
-
- A third-party selector, rich-content selector, document-state selector, browser selector, or pseudo-element-heavy effect that controlled JSX cannot own MAY use an unavoidable global selector.
|
|
8
|
-
- An unavoidable global selector MUST compose project-owned declarations with `@apply`.
|
|
9
|
-
- Component recipes MUST NOT become global selectors merely to shorten markup.
|
|
10
|
-
- Literal arbitrary values MUST NOT replace missing project tokens or named utilities in component markup.
|
|
11
|
-
|
|
12
|
-
## Incorrect — Component Recipe Defined Globally
|
|
13
|
-
|
|
14
|
-
```css
|
|
15
|
-
/* globals.css */
|
|
16
|
-
.settings-save-button {
|
|
17
|
-
@apply inline-flex rounded-lg px-3 py-2;
|
|
18
|
-
}
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Why: a one-off component recipe is separated from the markup that owns it and creates a global selector to maintain.
|
|
22
|
-
|
|
23
|
-
## Correct — Single-Use Styling Kept with the Component
|
|
24
|
-
|
|
25
|
-
```tsx
|
|
26
|
-
<button className="inline-flex rounded-lg px-3 py-2">Save</button>
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Why: the local treatment stays with its component, while global selectors remain reserved for markup or browser behavior that controlled JSX cannot own.
|
|
30
|
-
|
|
31
|
-
## Incorrect — Raw Declarations in an Unavoidable Selector
|
|
32
|
-
|
|
33
|
-
```css
|
|
34
|
-
.external-player .controls {
|
|
35
|
-
display: none;
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Why: third-party markup justifies the global selector, but the project-owned declaration still bypasses Tailwind composition.
|
|
40
|
-
|
|
41
|
-
## Correct — Global Selector Uses `@apply`
|
|
42
|
-
|
|
43
|
-
```css
|
|
44
|
-
.external-player .controls {
|
|
45
|
-
@apply hidden;
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Why: the global selector owns an unavoidable third-party boundary while its declaration stays inside the project's Tailwind system.
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# Tailwind Utility Rule
|
|
2
|
-
|
|
3
|
-
Utility classes are most useful when they describe a component's local layout and appearance directly beside the element they affect. This rule prevents abstractions from hiding simple styling decisions.
|
|
4
|
-
|
|
5
|
-
- Component markup MUST use static Tailwind utility classes for local layout, spacing, typography, and straightforward visual styling.
|
|
6
|
-
- Components MUST NOT construct Tailwind class names from runtime fragments such as `bg-${color}`.
|
|
7
|
-
- Components MUST use the closest project token or built-in utility for a static design value.
|
|
8
|
-
- Components MUST NOT use literal arbitrary-value classes such as `top-[13px]` or `text-[#50d71e]` for project-owned styling.
|
|
9
|
-
- A missing static design value MUST become an explicit project token or a named custom utility instead of an arbitrary literal in markup.
|
|
10
|
-
- A CSS custom property MAY use Tailwind's custom-property shorthand when a named utility intentionally exposes that property-specific value.
|
|
11
|
-
|
|
12
|
-
## Incorrect — Tailwind Classes Constructed at Runtime
|
|
13
|
-
|
|
14
|
-
```tsx
|
|
15
|
-
<div className={`p-${spacing} bg-${tone}`} />
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Why: the class scanner cannot reliably see runtime-built utility names, and the available styles depend on runtime string construction.
|
|
19
|
-
|
|
20
|
-
## Correct — Static Tailwind Classes
|
|
21
|
-
|
|
22
|
-
```tsx
|
|
23
|
-
<div className="bg-muted p-4" />
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Why: the utilities are statically discoverable and show the element's local treatment where it is rendered.
|
|
27
|
-
|
|
28
|
-
## Incorrect — Literal Arbitrary Design Value
|
|
29
|
-
|
|
30
|
-
```tsx
|
|
31
|
-
<div className="top-[13px]" />
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Why: the design value is hidden in markup and cannot be tracked as part of the project's explicit token set.
|
|
35
|
-
|
|
36
|
-
## Correct — Explicit Project Token
|
|
37
|
-
|
|
38
|
-
```css
|
|
39
|
-
@theme {
|
|
40
|
-
--spacing-floating-offset: 0.8125rem;
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
```tsx
|
|
45
|
-
<div className="top-floating-offset" />
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Why: the named token makes the static design value searchable and gives every consumer one stable utility.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Theme Token Rule
|
|
2
|
-
|
|
3
|
-
Application chrome must remain themeable, while artwork, user content, data, and faithful external visuals may carry color as content. This rule gives shared interface decisions semantic names without turning content colors into interface tokens.
|
|
4
|
-
|
|
5
|
-
- Application chrome MUST use semantic project tokens and readable canvas/ink pairs.
|
|
6
|
-
- Shared interface colors, surfaces, borders, typography roles, and reusable measurements MUST use semantic project tokens.
|
|
7
|
-
- Components MUST NOT use palette utilities or literal colors for ordinary navigation, forms, dialogs, controls, status feedback, or focus treatment when a semantic role exists.
|
|
8
|
-
- A new semantic token MUST represent a recurring interface meaning that existing roles cannot express.
|
|
9
|
-
- Token names SHOULD describe purpose rather than a palette value or one component's implementation.
|
|
10
|
-
- Content, artwork, user-selected media, data visualization, and faithful third-party visual reproductions MAY use literal colors when color is part of the content itself.
|
|
11
|
-
- Opacity modifiers SHOULD express interaction and layering differences without creating a new semantic token.
|
|
12
|
-
|
|
13
|
-
## Incorrect — Palette Colors Used for Interface Controls
|
|
14
|
-
|
|
15
|
-
```tsx
|
|
16
|
-
<Button className="bg-purple-600 text-white hover:bg-purple-500">Save</Button>
|
|
17
|
-
<input className="border-[#6b7280] focus:ring-[#7c3aed]" />
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
Why: ordinary controls are tied to palette and literal values instead of the project's semantic action, canvas, ink, border, and focus roles.
|
|
21
|
-
|
|
22
|
-
## Correct — Semantic Tokens Used for Interface Controls
|
|
23
|
-
|
|
24
|
-
```tsx
|
|
25
|
-
<Button tone="primary">Save</Button>
|
|
26
|
-
<input className="border-border focus-visible:ring-focus/50" />
|
|
27
|
-
|
|
28
|
-
// A product preview preserves the external brand color as content.
|
|
29
|
-
<ProductPreview brandColor="#1db954" />
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Why: ordinary interface styling uses the component API and semantic roles, while the faithful external visual retains the content color that defines it.
|