alouette 19.0.0-beta.3 → 19.0.0-beta.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.
- package/README.md +173 -62
- package/package.json +3 -2
- package/skills/alouette-setup/SKILL.md +74 -13
- package/src/global.css +6 -0
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
</h1>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
A modern, customizable design system built on top of
|
|
6
|
+
A modern, customizable design system built on top of NativeWind v5 with configurable defaults
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
@@ -13,78 +13,196 @@
|
|
|
13
13
|
<a href="https://npmjs.org/package/alouette"><img src="https://img.shields.io/npm/types/alouette.svg?style=flat-square" alt="types"></a>
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
|
+
Alouette provides a comprehensive set of universal components that render on both
|
|
17
|
+
web and React Native, styled entirely through Tailwind `className` via
|
|
18
|
+
[NativeWind v5](https://www.nativewind.dev/). Themes, accents, and design tokens
|
|
19
|
+
ship as CSS custom properties that cascade through the tree, so components stay
|
|
20
|
+
declarative and consistent across platforms.
|
|
21
|
+
|
|
16
22
|
## 🚀 Getting Started
|
|
17
23
|
|
|
18
24
|
### Prerequisites
|
|
19
25
|
|
|
20
|
-
- Node.js >=
|
|
26
|
+
- Node.js >= 22.18.0 (includes Corepack for package management)
|
|
27
|
+
- A React Native / Expo app using Metro, or a web app using NativeWind v5
|
|
21
28
|
|
|
22
29
|
### Installation
|
|
23
30
|
|
|
24
|
-
1. Enable Corepack (if not already enabled):
|
|
25
|
-
|
|
26
31
|
```bash
|
|
27
|
-
|
|
32
|
+
npm install alouette
|
|
33
|
+
# or with yarn
|
|
34
|
+
yarn add alouette
|
|
28
35
|
```
|
|
29
36
|
|
|
30
|
-
|
|
37
|
+
`alouette-icons` is installed automatically as a dependency.
|
|
38
|
+
|
|
39
|
+
Install the peer dependencies if your app does not already provide them:
|
|
31
40
|
|
|
32
41
|
```bash
|
|
33
|
-
npm install
|
|
34
|
-
|
|
35
|
-
yarn add alouette
|
|
42
|
+
npm install nativewind@5.0.0-preview.4 tailwindcss@^4 \
|
|
43
|
+
react-native-reanimated react-native-svg
|
|
36
44
|
```
|
|
37
45
|
|
|
38
|
-
|
|
46
|
+
`expo-web-browser`, `react-dom`, and `react-native-reanimated` are optional peers
|
|
47
|
+
— add them only if your target needs them (`react-dom` for web, `react-native-reanimated`
|
|
48
|
+
for native animations, `expo-web-browser` for `ExternalLink`).
|
|
39
49
|
|
|
40
50
|
### Configuration
|
|
41
51
|
|
|
42
|
-
|
|
52
|
+
Alouette relies on NativeWind v5's Metro + PostCSS pipeline. NativeWind discovers
|
|
53
|
+
themes and utilities from the imported `global.css` and scans your sources via
|
|
54
|
+
`@source` directives — there is no JS config to maintain.
|
|
55
|
+
|
|
56
|
+
1. **Metro** — wrap your config with the Alouette helper:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
// metro.config.cjs
|
|
60
|
+
const { withAlouetteConfig } = require("alouette/metro");
|
|
61
|
+
const { getDefaultConfig } = require("expo/metro-config.js");
|
|
62
|
+
|
|
63
|
+
module.exports = withAlouetteConfig(getDefaultConfig(__dirname));
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
2. **CSS entry** — create a `global.css` that re-exports Alouette's tokens and
|
|
67
|
+
points `@source` at the directories NativeWind should scan for class names:
|
|
68
|
+
|
|
69
|
+
```css
|
|
70
|
+
/* global.css */
|
|
71
|
+
@import "alouette/global.css";
|
|
72
|
+
|
|
73
|
+
@source './src'; /* your own className / tv() literals */
|
|
74
|
+
@source '../node_modules/alouette/src'; /* alouette's source — required */
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Tailwind only emits classes it finds while scanning `@source` paths, so both
|
|
78
|
+
your app's source **and** alouette's source must be covered or the matching
|
|
79
|
+
utilities are silently purged. In a monorepo where alouette is hoisted to the
|
|
80
|
+
repo root `node_modules`, adjust the depth (e.g.
|
|
81
|
+
`@source '../../../node_modules/alouette/src'`); a path that resolves to nothing
|
|
82
|
+
fails silently with no error.
|
|
83
|
+
|
|
84
|
+
Import it once at your app's entry point:
|
|
43
85
|
|
|
44
86
|
```ts
|
|
45
|
-
import
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
87
|
+
import "./global.css";
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
3. **PostCSS** — NativeWind compiles Tailwind through PostCSS on both web and
|
|
91
|
+
native. `@tailwindcss/postcss` ships as a dependency of `alouette`, so you
|
|
92
|
+
only add the config file (use `.mjs` so it loads as ESM regardless of your
|
|
93
|
+
package's `"type"`):
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
// postcss.config.mjs
|
|
97
|
+
export default {
|
|
98
|
+
plugins: {
|
|
99
|
+
"@tailwindcss/postcss": {},
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
4. **Babel** — use the Expo preset and the Reanimated/worklets plugin:
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
// babel.config.js
|
|
108
|
+
export default function (api) {
|
|
109
|
+
api.cache(true);
|
|
110
|
+
return {
|
|
111
|
+
presets: [["babel-preset-expo", { reanimated: false }]],
|
|
112
|
+
plugins: ["react-native-worklets/plugin"],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
5. **Provider** — wrap your app in `AlouetteProvider`. It applies the OS
|
|
118
|
+
light/dark scheme as the root theme so base tokens resolve app-wide:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import { AlouetteProvider } from "alouette";
|
|
51
122
|
|
|
52
|
-
|
|
53
|
-
|
|
123
|
+
export function App() {
|
|
124
|
+
return <AlouetteProvider>{/* your app */}</AlouetteProvider>;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
54
127
|
|
|
55
|
-
|
|
128
|
+
6. **Fonts** — Alouette's typography uses Sora (body/heading) and Chivo Mono
|
|
129
|
+
(mono). On native, load the weight-specific font files (the standalone
|
|
130
|
+
`font-weight` utility has no effect because each weight is a distinct file):
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import {
|
|
134
|
+
Sora_400Regular as SoraRegular,
|
|
135
|
+
Sora_700Bold as SoraBold,
|
|
136
|
+
Sora_800ExtraBold as SoraExtraBold,
|
|
137
|
+
useFonts,
|
|
138
|
+
} from "@expo-google-fonts/sora";
|
|
139
|
+
import {
|
|
140
|
+
ChivoMono_400Regular as ChivoMonoRegular,
|
|
141
|
+
ChivoMono_700Bold as ChivoMonoBold,
|
|
142
|
+
ChivoMono_800ExtraBold as ChivoMonoExtraBold,
|
|
143
|
+
} from "@expo-google-fonts/chivo-mono";
|
|
144
|
+
|
|
145
|
+
const [fontsLoaded] = useFonts({
|
|
146
|
+
SoraRegular,
|
|
147
|
+
SoraBold,
|
|
148
|
+
SoraExtraBold,
|
|
149
|
+
ChivoMonoRegular,
|
|
150
|
+
ChivoMonoBold,
|
|
151
|
+
ChivoMonoExtraBold,
|
|
152
|
+
});
|
|
56
153
|
```
|
|
57
154
|
|
|
58
155
|
## 🎨 Core Features
|
|
59
156
|
|
|
60
157
|
### Components
|
|
61
158
|
|
|
62
|
-
Alouette
|
|
159
|
+
Alouette ships a universal component set styled through `className`:
|
|
63
160
|
|
|
64
|
-
|
|
161
|
+
- **Actions** — `Button`, `ExternalLinkButton`, `InternalLinkButton`, `IconButton`
|
|
162
|
+
- **Containers** — `Box`, `InteractiveBox`, `SafeAreaBox`, `Surface`, `ScopedTheme`, `AccentScope`, `PresenceOne`, `PresenceList`
|
|
163
|
+
- **Inputs** — `InputText`, `TextArea`, `Switch`
|
|
164
|
+
- **Feedback** — `Message`, `InfoMessage`, `ConfirmationMessage`, `WarningMessage`
|
|
165
|
+
- **Data** — `PressableBox`, `PressableListItem`
|
|
166
|
+
- **Layout** — `GradientBackground`, `GradientScrollView`
|
|
167
|
+
- **Primitives** — `View`, `Text`, `Paragraph`, `Icon`, `ScrollView`, `Stack`, `HStack`, `VStack`, `Separator`
|
|
168
|
+
- **Responsive** — `SwitchBreakpointsUsingDisplayNone`, `SwitchBreakpointsUsingNull`, `useCurrentBreakpointName`
|
|
65
169
|
|
|
66
|
-
|
|
67
|
-
- `IconButton`: Circular button optimized for icon display
|
|
170
|
+
For detailed examples and API documentation, visit our [Storybook](https://www.chromatic.com/library?appId=679f9e8df3edc5f07975b64a).
|
|
68
171
|
|
|
69
|
-
|
|
172
|
+
### Text styling
|
|
70
173
|
|
|
71
|
-
|
|
72
|
-
|
|
174
|
+
`<Text>` has no variant props — style it entirely via `className`. Family and
|
|
175
|
+
weight are combined into a single utility (`font-body`, `font-body-bold`,
|
|
176
|
+
`font-heading-extrabold`, `font-mono`, …); size uses standard Tailwind
|
|
177
|
+
`text-*`; color uses tokens like `text-sharp`, `text-muted`, `text-accent`.
|
|
73
178
|
|
|
74
|
-
|
|
179
|
+
```tsx
|
|
180
|
+
import { Text } from "alouette";
|
|
75
181
|
|
|
76
|
-
-
|
|
182
|
+
<Text className="text-base">Body</Text>;
|
|
183
|
+
<Text className="font-heading-extrabold text-4xl">Title</Text>;
|
|
184
|
+
<Text className="font-mono text-xs text-muted">Code</Text>;
|
|
185
|
+
```
|
|
77
186
|
|
|
78
|
-
|
|
187
|
+
### Theming and accents
|
|
79
188
|
|
|
80
|
-
|
|
81
|
-
|
|
189
|
+
Themes are sets of CSS variables (`light`, `dark`, `light_brand`, `dark_info`, …)
|
|
190
|
+
applied by `ScopedTheme`. Child components use **base tokens** (`bg-surface`,
|
|
191
|
+
`text-accent`, `border-muted`, …) and inherit the correct values from the nearest
|
|
192
|
+
theme scope. Components that introduce an accent wrap their children in
|
|
193
|
+
`AccentScope`:
|
|
82
194
|
|
|
83
|
-
|
|
195
|
+
```tsx
|
|
196
|
+
import { AccentScope, Surface } from "alouette";
|
|
197
|
+
|
|
198
|
+
<AccentScope accent="info">
|
|
199
|
+
<Surface>{/* children use base tokens */}</Surface>
|
|
200
|
+
</AccentScope>;
|
|
201
|
+
```
|
|
84
202
|
|
|
85
203
|
### Icons
|
|
86
204
|
|
|
87
|
-
Icons
|
|
205
|
+
Icons come from the integrated `alouette-icons` package:
|
|
88
206
|
|
|
89
207
|
```tsx
|
|
90
208
|
import { ArrowLeftRegularIcon } from "alouette-icons/phosphor-icons/ArrowLeftRegularIcon";
|
|
@@ -94,24 +212,6 @@ function MyComponent() {
|
|
|
94
212
|
}
|
|
95
213
|
```
|
|
96
214
|
|
|
97
|
-
## 🏗️ Architecture
|
|
98
|
-
|
|
99
|
-
### Core Principles
|
|
100
|
-
|
|
101
|
-
1. **Universal Design**: Components work seamlessly across web and native platforms
|
|
102
|
-
2. **Performance First**: Optimized bundle size and runtime performance through Tamagui
|
|
103
|
-
3. **Accessibility**: WCAG 2.1 compliant components with proper ARIA attributes
|
|
104
|
-
4. **Customization**: Flexible theming system with sensible defaults
|
|
105
|
-
5. **Type Safety**: Built with TypeScript for enhanced developer experience
|
|
106
|
-
|
|
107
|
-
### Technical Architecture
|
|
108
|
-
|
|
109
|
-
- **Component Structure**: Atomic design pattern with atoms, molecules, and organisms
|
|
110
|
-
- **Styling System**: Tamagui's compile-time styling with runtime fallbacks
|
|
111
|
-
- **Theme System**: Token-based design system with support for light/dark modes
|
|
112
|
-
- **Responsive Design**: Mobile-first approach with flexible breakpoint system
|
|
113
|
-
- **Icon System**: Based on Phosphor Icons with optimized bundle size
|
|
114
|
-
|
|
115
215
|
## 🎯 Examples
|
|
116
216
|
|
|
117
217
|
### Basic Button
|
|
@@ -121,11 +221,7 @@ import { Button } from "alouette";
|
|
|
121
221
|
|
|
122
222
|
function MyComponent() {
|
|
123
223
|
return (
|
|
124
|
-
<Button
|
|
125
|
-
theme="brand"
|
|
126
|
-
text="Click me"
|
|
127
|
-
onPress={() => console.log("Clicked!")}
|
|
128
|
-
/>
|
|
224
|
+
<Button accent="brand" text="Click me" onPress={() => console.log("Clicked!")} />
|
|
129
225
|
);
|
|
130
226
|
}
|
|
131
227
|
```
|
|
@@ -137,15 +233,30 @@ import { Button } from "alouette";
|
|
|
137
233
|
import { ArrowLeftRegularIcon } from "alouette-icons/phosphor-icons/ArrowLeftRegularIcon";
|
|
138
234
|
|
|
139
235
|
function MyComponent() {
|
|
140
|
-
return
|
|
141
|
-
<Button theme="brand" icon={<ArrowLeftRegularIcon />} text="Go Back" />
|
|
142
|
-
);
|
|
236
|
+
return <Button accent="brand" icon={<ArrowLeftRegularIcon />} text="Go Back" />;
|
|
143
237
|
}
|
|
144
238
|
```
|
|
145
239
|
|
|
146
|
-
##
|
|
240
|
+
## 🤖 Using an AI agent?
|
|
241
|
+
|
|
242
|
+
Alouette ships [skills](https://www.npmjs.com/package/@tanstack/intent) that teach
|
|
243
|
+
AI coding agents how to use the design system correctly:
|
|
147
244
|
|
|
148
|
-
|
|
245
|
+
```bash
|
|
246
|
+
npx @tanstack/intent@latest install
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## 🏗️ Architecture
|
|
250
|
+
|
|
251
|
+
- **Universal Design** — components render across web and native from one API
|
|
252
|
+
- **NativeWind v5 styling** — Tailwind `className`; animations are CSS
|
|
253
|
+
`@keyframes` + `--animate-*` tokens, run on native via Reanimated
|
|
254
|
+
- **Token-based theming** — CSS custom properties cascade through `ScopedTheme`;
|
|
255
|
+
light/dark + accent scopes
|
|
256
|
+
- **Accessibility** — proper ARIA / accessibility attributes
|
|
257
|
+
- **Type Safety** — built with TypeScript
|
|
258
|
+
|
|
259
|
+
## 📚 Documentation
|
|
149
260
|
|
|
150
261
|
- [Component Documentation](https://www.chromatic.com/library?appId=679f9e8df3edc5f07975b64a)
|
|
151
262
|
- [GitHub Repository](https://github.com/christophehurpeau/alouette)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alouette",
|
|
3
|
-
"version": "19.0.0-beta.
|
|
4
|
-
"description": "A modern, customizable design system built on top of
|
|
3
|
+
"version": "19.0.0-beta.4",
|
|
4
|
+
"description": "A modern, customizable design system built on top of NativeWind v5 with configurable defaults",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tanstack-intent"
|
|
7
7
|
],
|
|
@@ -123,6 +123,7 @@
|
|
|
123
123
|
}
|
|
124
124
|
},
|
|
125
125
|
"dependencies": {
|
|
126
|
+
"@tailwindcss/postcss": "4.3.1",
|
|
126
127
|
"alouette-icons": "8.0.7",
|
|
127
128
|
"expo-web-browser": "~15.0.10",
|
|
128
129
|
"react-native-safe-area-context": "5.6.2",
|
|
@@ -8,9 +8,10 @@ description: >
|
|
|
8
8
|
fonts/bold weights look wrong. Covers ios, android and web.
|
|
9
9
|
type: lifecycle
|
|
10
10
|
library: alouette
|
|
11
|
-
library_version: "19.0.0-beta.
|
|
11
|
+
library_version: "19.0.0-beta.3"
|
|
12
12
|
sources:
|
|
13
13
|
- "christophehurpeau/alouette:packages/storybook-native-app/metro.config.cjs"
|
|
14
|
+
- "christophehurpeau/alouette:packages/storybook-native-app/postcss.config.mjs"
|
|
14
15
|
- "christophehurpeau/alouette:packages/storybook-native-app/src/global.css"
|
|
15
16
|
- "christophehurpeau/alouette:packages/storybook-native-app/src/App.tsx"
|
|
16
17
|
- "christophehurpeau/alouette:packages/alouette/src/core/AlouetteProvider.tsx"
|
|
@@ -19,10 +20,10 @@ sources:
|
|
|
19
20
|
|
|
20
21
|
# alouette — Setup
|
|
21
22
|
|
|
22
|
-
alouette is styled with NativeWind v5 / Tailwind CSS v4. An app needs
|
|
23
|
-
things wired before any component renders correctly: the metro plugin, the
|
|
24
|
-
entry with source globs, the provider, and the fonts.
|
|
25
|
-
ios/android/web from the same code.
|
|
23
|
+
alouette is styled with NativeWind v5 / Tailwind CSS v4. An app needs five
|
|
24
|
+
things wired before any component renders correctly: the metro plugin, the
|
|
25
|
+
PostCSS config, the CSS entry with source globs, the provider, and the fonts.
|
|
26
|
+
Everything targets ios/android/web from the same code.
|
|
26
27
|
|
|
27
28
|
## Setup
|
|
28
29
|
|
|
@@ -37,14 +38,39 @@ const config = getDefaultConfig(__dirname);
|
|
|
37
38
|
module.exports = withAlouetteConfig(config);
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
`
|
|
41
|
+
`postcss.config.mjs` at the **app package root** — this is what actually runs
|
|
42
|
+
Tailwind. `@tailwindcss/postcss` ships as a dependency of `alouette`, so apps do
|
|
43
|
+
not install it; they only add this config file:
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
export default { plugins: { "@tailwindcss/postcss": {} } };
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Use the `.mjs` extension so it loads as ESM regardless of the package's `"type"`
|
|
50
|
+
field.
|
|
51
|
+
|
|
52
|
+
`src/global.css` (imported once, at the app entry). Add an `@source` for
|
|
53
|
+
**alouette's source** and one for **your own app source** — both are scanned
|
|
54
|
+
independently of the JS bundle, and anything not covered is purged:
|
|
41
55
|
|
|
42
56
|
```css
|
|
43
57
|
@import "alouette/global.css";
|
|
44
58
|
|
|
45
|
-
@source "
|
|
59
|
+
@source "./**/*.{ts,tsx}"; /* the app's own className / tv() literals */
|
|
60
|
+
@source "../node_modules/alouette/src/**/*.{ts,tsx,js}"; /* alouette source */
|
|
46
61
|
```
|
|
47
62
|
|
|
63
|
+
In a monorepo where alouette is hoisted to the **repo root** `node_modules`
|
|
64
|
+
(Yarn `node-modules` linker, pnpm hoisted, etc.), the path resolves from the
|
|
65
|
+
repo root, not the app — adjust the depth accordingly:
|
|
66
|
+
|
|
67
|
+
```css
|
|
68
|
+
@source "../../../node_modules/alouette/src/**/*.{ts,tsx,js}";
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
A wrong glob matches zero files and fails **silently** (no error) — utilities
|
|
72
|
+
are simply purged and components render unstyled.
|
|
73
|
+
|
|
48
74
|
App entry — load fonts (native), then wrap the tree in `AlouetteProvider`:
|
|
49
75
|
|
|
50
76
|
```tsx
|
|
@@ -136,9 +162,31 @@ Append `&family=Chivo+Mono:wght@400;700;800` to the URL if you use `font-mono`.
|
|
|
136
162
|
|
|
137
163
|
## Common Mistakes
|
|
138
164
|
|
|
139
|
-
### CRITICAL
|
|
165
|
+
### CRITICAL Missing postcss.config — Tailwind never runs
|
|
140
166
|
|
|
141
|
-
|
|
167
|
+
Symptom: components render unstyled (only alouette's hotpink `body` fallback
|
|
168
|
+
shows), and the build logs spam `Warning: Unknown at rule: @utility` /
|
|
169
|
+
`@source` / `@theme`. Those warnings are the diagnostic signature — Tailwind
|
|
170
|
+
directives are reaching lightningcss un-expanded because Tailwind never ran.
|
|
171
|
+
|
|
172
|
+
Mechanism: `withAlouetteConfig` → `withNativewind` delegates CSS compilation to
|
|
173
|
+
Expo's Metro transform worker, which runs Tailwind **only if it finds a
|
|
174
|
+
`postcss.config` file at the project root**. Absent → CSS passes straight to
|
|
175
|
+
lightningcss verbatim and zero utilities are emitted.
|
|
176
|
+
|
|
177
|
+
Fix — add `postcss.config.mjs` at the app package root:
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
export default { plugins: { "@tailwindcss/postcss": {} } };
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`@tailwindcss/postcss` is a dependency of `alouette`, so no install is needed.
|
|
184
|
+
|
|
185
|
+
Source: packages/storybook-native-app/postcss.config.mjs
|
|
186
|
+
|
|
187
|
+
### CRITICAL global.css missing @source, or wrong path in a monorepo
|
|
188
|
+
|
|
189
|
+
Wrong (no `@source`, or a path that resolves to nothing):
|
|
142
190
|
|
|
143
191
|
```css
|
|
144
192
|
@import "alouette/global.css";
|
|
@@ -149,12 +197,25 @@ Correct:
|
|
|
149
197
|
```css
|
|
150
198
|
@import "alouette/global.css";
|
|
151
199
|
|
|
152
|
-
@source "
|
|
200
|
+
@source "./**/*.{ts,tsx}"; /* the app's own classes */
|
|
201
|
+
@source "../node_modules/alouette/src/**/*.{ts,tsx,js}"; /* alouette source */
|
|
153
202
|
```
|
|
154
203
|
|
|
155
|
-
Tailwind v4 only emits classes it finds in scanned files.
|
|
156
|
-
|
|
157
|
-
|
|
204
|
+
Tailwind v4 only emits classes it finds in scanned files. Two failure modes,
|
|
205
|
+
both producing the same silent unstyled result with **no error**:
|
|
206
|
+
|
|
207
|
+
1. No `@source` for alouette's source → every alouette utility is purged.
|
|
208
|
+
2. No `@source` for the app's own source → the app's own classes (e.g.
|
|
209
|
+
arbitrary values like `from-[#f39c12]`, `bg-linear-to-t`) are purged while
|
|
210
|
+
alouette's still work — easy to misdiagnose.
|
|
211
|
+
3. In a monorepo where alouette is hoisted to the **repo root**
|
|
212
|
+
`node_modules`, `../node_modules/alouette/src` resolves to nothing. Use the
|
|
213
|
+
correct depth, e.g. `@source "../../../node_modules/alouette/src/**/*.{ts,tsx,js}"`.
|
|
214
|
+
|
|
215
|
+
Note: `@source` is a text-scan of alouette's shipped `src/*.tsx` (the verbatim
|
|
216
|
+
`className` / `tv()` string literals) — independent of the JS bundle, which
|
|
217
|
+
Metro resolves to the compiled `dist`. The two pipelines are decoupled, which is
|
|
218
|
+
why the scan targets `src` and not the build output.
|
|
158
219
|
|
|
159
220
|
Source: packages/storybook-native-app/src/global.css
|
|
160
221
|
|
package/src/global.css
CHANGED
|
@@ -616,6 +616,12 @@
|
|
|
616
616
|
|
|
617
617
|
/* let height/width keyframes interpolate to/from auto (collapse-in/out) on web */
|
|
618
618
|
:root { interpolate-size: allow-keywords; }
|
|
619
|
+
|
|
620
|
+
body, #root {
|
|
621
|
+
display: flex;
|
|
622
|
+
flex-direction: column;
|
|
623
|
+
min-height: 100vh;
|
|
624
|
+
}
|
|
619
625
|
}
|
|
620
626
|
|
|
621
627
|
/* keyframes referenced by the --animate-* theme tokens above. */
|