alouette
Version:
A modern, customizable design system built on top of NativeWind v5 with configurable defaults
275 lines (207 loc) ⢠8.58 kB
Markdown
<h1 align="center">
alouette
</h1>
<p align="center">
A modern, customizable design system built on top of NativeWind v5 with configurable defaults
</p>
<p align="center">
<a href="https://npmjs.org/package/alouette"><img src="https://img.shields.io/npm/v/alouette.svg?style=flat-square" alt="npm version"></a>
<a href="https://npmjs.org/package/alouette"><img src="https://img.shields.io/npm/dw/alouette.svg?style=flat-square" alt="npm downloads"></a>
<a href="https://npmjs.org/package/alouette"><img src="https://img.shields.io/node/v/alouette.svg?style=flat-square" alt="node version"></a>
<a href="https://npmjs.org/package/alouette"><img src="https://img.shields.io/npm/types/alouette.svg?style=flat-square" alt="types"></a>
</p>
## Introduction
Alouette provides a comprehensive set of universal components that render on both
web and React Native, styled entirely through Tailwind `className` via
[NativeWind v5](https://www.nativewind.dev/). Themes, accents, and design tokens
ship as CSS custom properties that cascade through the tree, so components stay
declarative and consistent across platforms.
## š Getting Started
### Prerequisites
- Node.js >= 22.18.0 (includes Corepack for package management)
- A React Native / Expo app using Metro, or a web app using NativeWind v5
### Installation
```bash
npm install alouette
# or with yarn
yarn add alouette
```
`alouette-icons` is installed automatically as a dependency.
Install the peer dependencies if your app does not already provide them:
```bash
npm install nativewind@5.0.0-preview.4 tailwindcss@^4 \
react-native-reanimated react-native-svg
```
`expo-web-browser`, `react-dom`, and `react-native-reanimated` are optional peers
ā add them only if your target needs them (`react-dom` for web, `react-native-reanimated`
for native animations, `expo-web-browser` for `ExternalLink`).
### Configuration
Alouette relies on NativeWind v5's Metro + PostCSS pipeline. NativeWind discovers
themes and utilities from the imported `global.css` and scans your sources via
`@source` directives ā there is no JS config to maintain.
1. **Metro** ā wrap your config with the Alouette helper:
```js
// metro.config.cjs
const { withAlouetteConfig } = require("alouette/metro.cjs");
const { getDefaultConfig } = require("expo/metro-config.js");
module.exports = withAlouetteConfig(getDefaultConfig(__dirname));
```
2. **CSS entry** ā create a `global.css` that re-exports Alouette's tokens and
points `@source` at the directories NativeWind should scan for class names:
```css
/* global.css */
@import "alouette/global.css";
@source './src'; /* your own className / tv() literals */
@source '../node_modules/alouette/src'; /* alouette's source ā required */
```
Tailwind only emits classes it finds while scanning `@source` paths, so both
your app's source **and** alouette's source must be covered or the matching
utilities are silently purged. In a monorepo where alouette is hoisted to the
repo root `node_modules`, adjust the depth (e.g.
`@source '../../../node_modules/alouette/src'`); a path that resolves to nothing
fails silently with no error.
Import it once at your app's entry point:
```ts
import "./global.css";
```
3. **PostCSS** ā NativeWind compiles Tailwind through PostCSS on both web and
native. `@tailwindcss/postcss` ships as a dependency of `alouette`, so you
only add the config file (use `.mjs` so it loads as ESM regardless of your
package's `"type"`):
```js
// postcss.config.mjs
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
```
4. **Babel** ā use the Expo preset and the Reanimated/worklets plugin:
```js
// babel.config.js
export default function (api) {
api.cache(true);
return {
presets: [["babel-preset-expo", { reanimated: false }]],
plugins: ["react-native-worklets/plugin"],
};
}
```
5. **Provider** ā wrap your app in `AlouetteProvider`. It applies the OS
light/dark scheme as the root theme so base tokens resolve app-wide:
```tsx
import { AlouetteProvider } from "alouette";
export function App() {
return <AlouetteProvider>{/* your app */}</AlouetteProvider>;
}
```
6. **Fonts** ā Alouette's typography uses Sora (body/heading) and Chivo Mono
(mono). On native, load the weight-specific font files (the standalone
`font-weight` utility has no effect because each weight is a distinct file):
```tsx
import {
Sora_400Regular as SoraRegular,
Sora_700Bold as SoraBold,
Sora_800ExtraBold as SoraExtraBold,
useFonts,
} from "@expo-google-fonts/sora";
import {
ChivoMono_400Regular as ChivoMonoRegular,
ChivoMono_700Bold as ChivoMonoBold,
ChivoMono_800ExtraBold as ChivoMonoExtraBold,
} from "@expo-google-fonts/chivo-mono";
const [fontsLoaded] = useFonts({
SoraRegular,
SoraBold,
SoraExtraBold,
ChivoMonoRegular,
ChivoMonoBold,
ChivoMonoExtraBold,
});
```
## šØ Core Features
### Components
Alouette ships a universal component set styled through `className`:
- **Actions** ā `Button`, `ExternalLinkButton`, `InternalLinkButton`, `IconButton`
- **Containers** ā `Box`, `InteractiveBox`, `SafeAreaBox`, `Surface`, `ScopedTheme`, `AccentScope`, `PresenceOne`, `PresenceList`
- **Inputs** ā `InputText`, `TextArea`, `Switch`
- **Feedback** ā `Message`, `InfoMessage`, `ConfirmationMessage`, `WarningMessage`
- **Data** ā `PressableBox`, `PressableListItem`
- **Layout** ā `GradientBackground`, `GradientScrollView`
- **Primitives** ā `View`, `Text`, `Paragraph`, `Icon`, `ScrollView`, `Stack`, `HStack`, `VStack`, `Separator`
- **Responsive** ā `SwitchBreakpointsUsingDisplayNone`, `SwitchBreakpointsUsingNull`, `useCurrentBreakpointName`
For detailed examples and API documentation, visit our [Storybook](https://www.chromatic.com/library?appId=679f9e8df3edc5f07975b64a).
### Text styling
`<Text>` has no variant props ā style it entirely via `className`. Family and
weight are combined into a single utility (`font-body`, `font-body-bold`,
`font-heading-extrabold`, `font-mono`, ā¦); size uses standard Tailwind
`text-*`; color uses tokens like `text-sharp`, `text-muted`, `text-accent`.
```tsx
import { Text } from "alouette";
<Text className="text-base">Body</Text>;
<Text className="font-heading-extrabold text-4xl">Title</Text>;
<Text className="font-mono text-xs text-muted">Code</Text>;
```
### Theming and accents
Themes are sets of CSS variables (`light`, `dark`, `light_brand`, `dark_info`, ā¦)
applied by `ScopedTheme`. Child components use **base tokens** (`bg-surface`,
`text-accent`, `border-muted`, ā¦) and inherit the correct values from the nearest
theme scope. Components that introduce an accent wrap their children in
`AccentScope`:
```tsx
import { AccentScope, Surface } from "alouette";
<AccentScope accent="info">
<Surface>{/* children use base tokens */}</Surface>
</AccentScope>;
```
### Icons
Icons come from the integrated `alouette-icons` package:
```tsx
import { ArrowLeftRegularIcon } from "alouette-icons/phosphor-icons/ArrowLeftRegularIcon";
function MyComponent() {
return <ArrowLeftRegularIcon />;
}
```
## šÆ Examples
### Basic Button
```tsx
import { Button } from "alouette";
function MyComponent() {
return (
<Button
accent="brand"
text="Click me"
onPress={() => console.log("Clicked!")}
/>
);
}
```
### Button with Icon
```tsx
import { Button } from "alouette";
import { ArrowLeftRegularIcon } from "alouette-icons/phosphor-icons/ArrowLeftRegularIcon";
function MyComponent() {
return (
<Button accent="brand" icon={<ArrowLeftRegularIcon />} text="Go Back" />
);
}
```
## š¤ Using an AI agent?
Alouette ships [skills](https://www.npmjs.com/package/@tanstack/intent) that teach
AI coding agents how to use the design system correctly:
```bash
npx @tanstack/intent@latest install
```
## šļø Architecture
- **Universal Design** ā components render across web and native from one API
- **NativeWind v5 styling** ā Tailwind `className`; animations are CSS
`@keyframes` + `--animate-*` tokens, run on native via Reanimated
- **Token-based theming** ā CSS custom properties cascade through `ScopedTheme`;
light/dark + accent scopes
- **Accessibility** ā proper ARIA / accessibility attributes
- **Type Safety** ā built with TypeScript
## š Documentation
- [Component Documentation](https://www.chromatic.com/library?appId=679f9e8df3edc5f07975b64a)
- [GitHub Repository](https://github.com/christophehurpeau/alouette)
## š License
ISC Ā© [Christophe Hurpeau](https://christophe.hurpeau.com)