pasika 0.1.0 → 0.1.4

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.
Files changed (59) hide show
  1. package/README.md +31 -25
  2. package/claude/hooks/.vulyk +3 -0
  3. package/claude/hooks/AGENTS.md +3 -0
  4. package/claude/hooks/claude-hooks.md +30 -0
  5. package/claude/{.claude/hooks → hooks}/notification.sh +0 -0
  6. package/claude/{.claude/hooks → hooks}/protect-files.sh +0 -0
  7. package/claude/scripts/render-settings.ts +25 -9
  8. package/dist/claude/scripts/render-settings.js +22 -9
  9. package/dist/eslint/pasika/index.d.ts +2 -0
  10. package/dist/eslint/pasika/index.js +14 -0
  11. package/dist/eslint/pasika/rules/organization-imports.d.ts +2 -0
  12. package/dist/eslint/pasika/rules/organization-imports.js +124 -0
  13. package/docs/agent-conventions.md +21 -0
  14. package/docs/code-organization-guide/code-organization-guide.md +65 -0
  15. package/docs/code-organization-guide/references/application-architecture-reference.md +107 -0
  16. package/docs/code-organization-guide/rules/component-placement-rule.md +135 -0
  17. package/docs/code-organization-guide/rules/configuration-rule.md +42 -0
  18. package/docs/code-organization-guide/rules/constants-rule.md +77 -0
  19. package/docs/code-organization-guide/rules/exports-and-imports-rule.md +81 -0
  20. package/docs/code-organization-guide/rules/folder-nesting-rule.md +83 -0
  21. package/docs/code-organization-guide/rules/hook-extraction-rule.md +142 -0
  22. package/docs/code-organization-guide/rules/interactive-component-rule.md +100 -0
  23. package/docs/code-organization-guide/rules/jsx-hygiene-rule.md +68 -0
  24. package/docs/code-organization-guide/rules/locales-rule.md +55 -0
  25. package/docs/code-organization-guide/rules/nameable-visual-concept-rule.md +66 -0
  26. package/docs/code-organization-guide/rules/native-prop-forwarding-rule.md +38 -0
  27. package/docs/code-organization-guide/rules/no-mixed-concerns-rule.md +64 -0
  28. package/docs/code-organization-guide/rules/repeated-structure-rule.md +93 -0
  29. package/docs/code-organization-guide/rules/smart-vs-dumb-component-rule.md +116 -0
  30. package/docs/code-organization-guide/rules/sole-state-owner-rule.md +102 -0
  31. package/docs/code-organization-guide/rules/types-and-schemas-rule.md +138 -0
  32. package/docs/code-organization-guide/rules/utilities-rule.md +87 -0
  33. package/docs/documentation-guide/_templates/guide.md +19 -0
  34. package/docs/documentation-guide/_templates/reference.md +17 -0
  35. package/docs/documentation-guide/_templates/rule.md +21 -0
  36. package/docs/documentation-guide/documentation-guide.md +13 -0
  37. package/docs/documentation-guide/references/documentation-types-reference.md +9 -0
  38. package/docs/documentation-guide/rules/guide-creation-rule.md +112 -0
  39. package/docs/documentation-guide/rules/reference-creation-rule.md +132 -0
  40. package/docs/documentation-guide/rules/rule-creation-rule.md +81 -0
  41. package/docs/documentation-guide/rules/template-usage-rule.md +48 -0
  42. package/docs/shadcn-theme.md +121 -0
  43. package/docs/styling-guide/rules/class-composition-rule.md +32 -0
  44. package/docs/styling-guide/rules/color-role-naming-rule.md +115 -0
  45. package/docs/styling-guide/rules/component-state-rule.md +26 -0
  46. package/docs/styling-guide/rules/component-variant-rule.md +128 -0
  47. package/docs/styling-guide/rules/global-style-system-rule.md +63 -0
  48. package/docs/styling-guide/rules/style-placement-rule.md +49 -0
  49. package/docs/styling-guide/rules/tailwind-utility-rule.md +48 -0
  50. package/docs/styling-guide/rules/theme-and-utility-definition-rule.md +129 -0
  51. package/docs/styling-guide/rules/theme-token-rule.md +32 -0
  52. package/docs/styling-guide/styling-guide.md +17 -0
  53. package/package.json +24 -10
  54. package/AGENTS.md +0 -15
  55. package/docs/common/merge-behavior.md +0 -17
  56. package/docs/common/overview.md +0 -20
  57. /package/{CLAUDE.md → claude/hooks/CLAUDE.md} +0 -0
  58. /package/claude/{.claude/hooks → hooks}/status-line/index.js +0 -0
  59. /package/claude/{.claude/settings.base.json → settings.base.json} +0 -0
@@ -0,0 +1,121 @@
1
+ # shadcn Theme
2
+
3
+ Use this profile when a project uses shadcn UI tokens as its theme baseline.
4
+
5
+ ## File structure
6
+
7
+ Read the theme file by section:
8
+
9
+ 1. `@theme inline` exposes CSS variables to Tailwind utilities.
10
+ 2. `:root` defines light-mode token values.
11
+ 3. `.dark` defines dark-mode token values.
12
+ 4. `@layer base` applies default page, border, and outline styling.
13
+
14
+ Component authors write utilities such as `bg-primary`, `text-primary-foreground`, and `rounded-lg`. Tailwind resolves those utilities through the tokens registered in `@theme inline`. Do not write generated CSS by hand.
15
+
16
+ ## Registered Tailwind tokens
17
+
18
+ `@theme inline` maps project CSS variables to Tailwind token names. The categories below mirror the groups in a standard shadcn `globals.css`.
19
+
20
+ | Category | CSS variables | Utility examples |
21
+ |---|---|---|
22
+ | Page defaults | `--color-background`, `--color-foreground` | `bg-background`, `text-foreground` |
23
+ | Content surfaces | `--color-card`, `--color-card-foreground`, `--color-popover`, `--color-popover-foreground` | `bg-card text-card-foreground`, `bg-popover text-popover-foreground` |
24
+ | Action and state surfaces | `--color-primary`, `--color-primary-foreground`, `--color-secondary`, `--color-secondary-foreground`, `--color-muted`, `--color-muted-foreground`, `--color-accent`, `--color-accent-foreground`, `--color-destructive` | `bg-primary text-primary-foreground`, `bg-muted text-muted-foreground`, `bg-destructive text-white` |
25
+ | Borders, form fields, focus | `--color-border`, `--color-input`, `--color-ring` | `border`, `border-input`, `ring-ring`, `outline-ring/50` |
26
+ | Charts | `--color-chart-1` through `--color-chart-5` | `bg-chart-1`, `text-chart-2` |
27
+ | Sidebar | `--color-sidebar`, `--color-sidebar-foreground`, `--color-sidebar-primary`, `--color-sidebar-primary-foreground`, `--color-sidebar-accent`, `--color-sidebar-accent-foreground`, `--color-sidebar-border`, `--color-sidebar-ring` | `bg-sidebar`, `text-sidebar-foreground`, `border-sidebar-border` |
28
+ | Radius | `--radius-sm`, `--radius-md`, `--radius-lg`, `--radius-xl`, `--radius-2xl`, `--radius-3xl`, `--radius-4xl` | `rounded-sm`, `rounded-md`, `rounded-lg`, `rounded-xl`, `rounded-2xl`, `rounded-3xl`, `rounded-4xl` |
29
+
30
+ ## Value tokens
31
+
32
+ `:root` and `.dark` define the actual values for the same semantic tokens. The token names stay stable; only the values change between theme modes.
33
+
34
+ ### Page defaults
35
+
36
+ | Token | Use |
37
+ |---|---|
38
+ | `background` | App/page background |
39
+ | `foreground` | Default app text |
40
+
41
+ Use together as `bg-background text-foreground`.
42
+
43
+ ### Content surfaces
44
+
45
+ | Token pair | Use |
46
+ |---|---|
47
+ | `card` / `card-foreground` | Card or elevated surface content |
48
+ | `popover` / `popover-foreground` | Floating surfaces like menus, tooltips, dialogs |
49
+
50
+ Use as `bg-card text-card-foreground` and `bg-popover text-popover-foreground`.
51
+
52
+ ### Action and state surfaces
53
+
54
+ | Token pair | Use |
55
+ |---|---|
56
+ | `primary` / `primary-foreground` | Main action or selected/high-emphasis filled state |
57
+ | `secondary` / `secondary-foreground` | Supporting action or lower-emphasis filled state |
58
+ | `muted` / `muted-foreground` | Subtle surface and de-emphasized content |
59
+ | `accent` / `accent-foreground` | Transient hover, active, or current-row surface |
60
+ | `destructive` | Destructive action or error surface |
61
+
62
+ Fresh shadcn components use fixed white foreground on destructive filled surfaces:
63
+
64
+ ```tsx
65
+ <Button className="bg-destructive text-white" />
66
+ ```
67
+
68
+ ### Borders, form fields, and focus
69
+
70
+ | Token | shadcn use | Utility examples |
71
+ |---|---|---|
72
+ | `border` | Default borders and separators | `border`, `border-b` |
73
+ | `input` | Form-control border color and input-like surface treatment | `border-input`, `dark:bg-input/30`, `dark:border-input`, `dark:hover:bg-input/50` |
74
+ | `ring` | Focus border, ring, and outline color | `focus-visible:border-ring`, `focus-visible:ring-ring/50`, `focus-visible:outline-ring`, `outline-ring/50` |
75
+
76
+ The base layer already applies `border-border` and `outline-ring/50`; component code usually needs only the structural border utility (`border`, `border-b`, etc.) unless it is using another border role or overriding a competing border-color class.
77
+
78
+ ### Charts
79
+
80
+ `chart-1` through `chart-5` are palette slots for charts and data visualizations. They are not app surface tokens and do not imply foreground pairs.
81
+
82
+ ### Sidebar
83
+
84
+ Sidebar tokens are scoped versions of the same shadcn roles for sidebar UI:
85
+
86
+ - `sidebar` / `sidebar-foreground`
87
+ - `sidebar-primary` / `sidebar-primary-foreground`
88
+ - `sidebar-accent` / `sidebar-accent-foreground`
89
+ - `sidebar-border`
90
+ - `sidebar-ring`
91
+
92
+ ### Radius
93
+
94
+ `radius` is the base radius value. `@theme inline` derives Tailwind radius utilities from it.
95
+
96
+ ## Base layer
97
+
98
+ shadcn applies default app chrome in `@layer base`:
99
+
100
+ ```css
101
+ @layer base {
102
+ * {
103
+ @apply border-border outline-ring/50;
104
+ }
105
+ body {
106
+ @apply bg-background text-foreground;
107
+ }
108
+ }
109
+ ```
110
+
111
+ The base layer applies `border-border` and `outline-ring/50` globally. Plain `border`, `border-b`, etc. inherit the default border color when no competing border-color class is present. Add an explicit border color for another role, such as `border-input`, `border-primary`, `border-destructive`, or `focus-visible:border-ring`, or when overriding a component variant such as `border-transparent`.
112
+
113
+ ## Adding tokens
114
+
115
+ Treat fresh shadcn tokens as the baseline. Add project-specific tokens only when the project explicitly adopts an extension beyond shadcn defaults, and document that extension outside this baseline profile.
116
+
117
+ ## Update trigger
118
+
119
+ Re-check this document when the [shadcn changelog](https://ui.shadcn.com/docs/changelog) changes the theme token contract, default theme CSS, or generated component styling conventions.
120
+
121
+ When re-checking, verify the affected claims against current shadcn docs and generated registry components before editing this document.
@@ -0,0 +1,32 @@
1
+ # Class Composition Rule
2
+
3
+ Class conditions and caller overrides need one consistent merge point so ordering stays understandable and conflicting Tailwind utilities resolve correctly.
4
+
5
+ - Components MUST use `cn` or the project's equivalent class-merging helper for conditional classes and a consumer-provided `className`.
6
+ - Components MUST NOT concatenate class strings with template literals or `+` when any part is conditional.
7
+ - A consumer-provided `className` MUST contain only outer-layout utilities: margins, width constraints, permitted height constraints, and flex or grid item placement.
8
+ - Permitted height constraints MUST be limited to `h-full`, `h-auto`, `min-h-*`, and `max-h-*`; fixed component heights MUST use a typed component API or an external wrapper.
9
+ - A consumer-provided `className` MUST NOT change padding, internal gaps, fixed height, colors, typography, borders, radius, shadows, effects, positioning, inset, or z-index.
10
+ - A component MUST expose supported internal appearance and fixed-size choices through typed props rather than consumer classes.
11
+ - Components SHOULD group long static class lists by concern inside `cn`.
12
+ - Components MAY keep a short, fully static `className` string inline.
13
+
14
+ ## Incorrect — Conditional Classes Concatenated Manually
15
+
16
+ ```tsx
17
+ <button className={"rounded px-3 " + (active ? "bg-primary" : "bg-muted")} />
18
+ ```
19
+
20
+ Why: the condition and merge order are embedded in a string expression, which becomes difficult to extend with consumer overrides.
21
+
22
+ ## Correct — Conditional Classes Merged with `cn`
23
+
24
+ ```tsx
25
+ export default function Card({ className, ...props }: CardProps): React.JSX.Element {
26
+ return <article className={cn("surface-card rounded-lg p-4", className)} {...props} />;
27
+ }
28
+
29
+ <Card className="w-full max-w-lg self-center" />;
30
+ ```
31
+
32
+ Why: every class source is explicit, and a consumer can add outer layout such as `w-full max-w-lg self-center` without reconstructing the card's internal treatment.
@@ -0,0 +1,115 @@
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.
@@ -0,0 +1,26 @@
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.
@@ -0,0 +1,128 @@
1
+ # Component Variant Rule
2
+
3
+ When callers choose between a component's visual appearances, the styling definition and TypeScript API need one source of truth. This rule uses CVA for named choices and reserves `cn` for standalone boolean conditions.
4
+
5
+ - A component that lets callers choose between named visual appearances MUST define those choices with `cva`.
6
+ - Component variant prop types MUST be derived with `VariantProps<typeof componentVariants>`.
7
+ - Component props MUST NOT manually duplicate a union already defined by the CVA configuration.
8
+ - A boolean appearance input MUST use conditional `cn()` when it only adds or removes one standalone class treatment.
9
+ - A boolean appearance input MUST use a CVA variant when both boolean values have explicit treatments or when the boolean participates in a compound variant.
10
+ - A component MUST NOT expose separate class-name props for internal elements to vary their appearance.
11
+ - A component MAY expose structured content slots when callers need to provide content rather than alter internal styling.
12
+
13
+ ## Incorrect — Variant Union Duplicated by Hand
14
+
15
+ ```tsx
16
+ const buttonVariants = cva("inline-flex items-center", {
17
+ variants: {
18
+ size: {
19
+ sm: "h-8 px-3",
20
+ lg: "h-11 px-5",
21
+ },
22
+ },
23
+ });
24
+
25
+ type ButtonProps = React.ComponentProps<"button"> & {
26
+ size?: "sm" | "lg";
27
+ };
28
+ ```
29
+
30
+ Why: the accepted `size` values now live in both CVA and a handwritten prop union, so either side can change without the other.
31
+
32
+ ## Correct — Props Derived from CVA
33
+
34
+ ```tsx
35
+ const buttonVariants = cva("inline-flex items-center", {
36
+ variants: {
37
+ size: {
38
+ sm: "h-8 px-3",
39
+ lg: "h-11 px-5",
40
+ },
41
+ tone: {
42
+ primary: "surface-primary",
43
+ danger: "surface-danger",
44
+ },
45
+ },
46
+ defaultVariants: {
47
+ size: "sm",
48
+ tone: "primary",
49
+ },
50
+ });
51
+
52
+ type ButtonProps = React.ComponentProps<"button"> & VariantProps<typeof buttonVariants>;
53
+
54
+ export default function Button({ size, tone, className, ...props }: ButtonProps): React.JSX.Element {
55
+ return <button className={cn(buttonVariants({ size, tone }), className)} {...props} />;
56
+ }
57
+ ```
58
+
59
+ Why: the CVA definition owns the accepted values, defaults, and classes, while `VariantProps` derives the public TypeScript API from the same source.
60
+
61
+ ## Incorrect — Standalone Boolean Added to CVA
62
+
63
+ ```tsx
64
+ const buttonVariants = cva("inline-flex", {
65
+ variants: {
66
+ loading: {
67
+ true: "cursor-wait opacity-70",
68
+ false: "",
69
+ },
70
+ },
71
+ });
72
+ ```
73
+
74
+ Why: one boolean merely adds a standalone treatment and has no compound relationship, so CVA adds configuration without a styling matrix.
75
+
76
+ ## Correct — Standalone Boolean Uses `cn`
77
+
78
+ ```tsx
79
+ <button className={cn(buttonVariants({ size, tone }), loading && "cursor-wait opacity-70", className)} />
80
+ ```
81
+
82
+ Why: the named appearance choices stay in CVA while the independent boolean remains a direct conditional class.
83
+
84
+ ## Incorrect — Compound Boolean Styling Split Across Conditions
85
+
86
+ ```tsx
87
+ <button
88
+ className={cn(
89
+ buttonVariants({ tone }),
90
+ loading && "cursor-wait",
91
+ loading && tone === "primary" && "surface-primary-loading",
92
+ loading && tone === "danger" && "surface-danger-loading",
93
+ )}
94
+ />
95
+ ```
96
+
97
+ Why: the boolean changes treatment according to another variant, but the styling matrix is spread across conditional expressions outside CVA.
98
+
99
+ ## Correct — Boolean with Compound Styling Uses CVA
100
+
101
+ ```tsx
102
+ const buttonVariants = cva("inline-flex", {
103
+ variants: {
104
+ tone: {
105
+ primary: "surface-primary",
106
+ danger: "surface-danger",
107
+ },
108
+ loading: {
109
+ true: "cursor-wait",
110
+ false: "cursor-default",
111
+ },
112
+ },
113
+ compoundVariants: [
114
+ {
115
+ tone: "primary",
116
+ loading: true,
117
+ className: "surface-primary-loading",
118
+ },
119
+ {
120
+ tone: "danger",
121
+ loading: true,
122
+ className: "surface-danger-loading",
123
+ },
124
+ ],
125
+ });
126
+ ```
127
+
128
+ Why: both boolean values have explicit treatment and loading changes by tone, so CVA owns the complete styling matrix.
@@ -0,0 +1,63 @@
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.
@@ -0,0 +1,49 @@
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.
@@ -0,0 +1,48 @@
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.