alouette
Version:
A modern, customizable design system built on top of NativeWind v5 with configurable defaults
414 lines (386 loc) • 12.9 kB
CSS
/* Generated by scripts/build-css.ts. DO NOT EDIT. */
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css";
@import "nativewind/theme";
@theme {
/* The paired --text-*--line-height is what gives the text-* utility a default
line-height (Tailwind v4 convention). Ratios are unitless: web treats them as
font-size-relative and NativeWind multiplies a unitless lineHeight by
fontSize, so both platforms agree. The display sizes (2xl and up) are
heading-only and take tighter ratios; a heading at a shared size
(text-lg/text-xl) tightens with an explicit leading-* class. */
--text-xs: 0.75rem; /* 12px */
--text-xs--line-height: 1.4;
--text-sm: 0.875rem; /* 14px */
--text-sm--line-height: 1.4;
--text-base: 1rem; /* 16px */
--text-base--line-height: 1.4;
--text-lg: 1.125rem; /* 18px */
--text-lg--line-height: 1.4;
--text-xl: 1.5rem; /* 24px */
--text-xl--line-height: 1.4;
--text-2xl: 2rem; /* 32px */
--text-2xl--line-height: 1.2;
--text-3xl: 2.5rem; /* 40px */
--text-3xl--line-height: 1.1;
--text-4xl: 3rem; /* 48px */
--text-4xl--line-height: 1.1;
--text-5xl: 4rem; /* 64px */
--text-5xl--line-height: 1.1;
--text-6xl: 5rem; /* 80px */
--text-6xl--line-height: 1.1;
/* radius */
--radius-xs: 0.5rem;
--radius-sm: 1rem;
--radius-md: 2rem;
--radius-lg: 3rem;
/* box-shadows — the layer colors are palette tokens, so each mode tunes them: Tailwind
inlines this value into the utility (only its colors stay var()s), so a theme
block redeclaring --shadow-* would change nothing. Each var() has a fixed
fallback so a palette generated without the shadow tokens still yields a
valid box-shadow. */
--shadow-s:
inset 0 1px 2px var(--color-shadow-highlight, #ffffff40),
0 1px 2px var(--color-dark-shadow, #00000040),
0 2px 4px var(--color-soft-shadow, #00000025);
--shadow-m:
inset 0 1px 2px var(--color-shadow-highlight, #ffffff40),
0 2px 4px var(--color-dark-shadow, #00000040),
0 4px 8px var(--color-soft-shadow, #00000025);
--shadow-l:
inset 0 1px 2px var(--color-shadow-highlight, #ffffff40),
0 4px 6px var(--color-dark-shadow, #00000040),
0 6px 10px var(--color-soft-shadow, #00000025);
--shadow-lowered:
inset 0 1px 2px var(--color-shadow-lowered-dark, #00000040),
inset 0 -2px 2px var(--color-shadow-lowered-highlight, #ffffff15);
/* downward-only and no inset highlight: a screen-spanning bar (app header)
casts a shadow on the page below it, it is not a raised control. */
--shadow-bar:
0 1px 2px var(--color-bar-dark-shadow, #00000020),
0 6px 16px var(--color-bar-soft-shadow, #00000018);
/* spacing */
--spacing-xxs: 4px;
--spacing-xs: 8px;
--spacing-sm: 12px;
--spacing-m: 16px;
--spacing-md: 16px;
--spacing-l: 24px;
--spacing-lg: 24px;
--spacing-xl: 32px;
--spacing-xxl: 48px;
--spacing-3xl: 64px;
--spacing-4xl: 128px;
/* breakpoints — must match Breakpoints.ts */
--breakpoint-sm: 480px;
--breakpoint-md: 768px;
--breakpoint-lg: 1024px;
--breakpoint-xl: 1280px;
/* animations — NativeWind runs the @keyframes on native via Reanimated. A CSS animation
cannot play on unmount: pair an exit animation with <Presence>, which keeps
the outgoing child mounted. */
--animate-slide-in: slide-in 600ms cubic-bezier(0.16, 1, 0.3, 1);
--animate-slide-out: slide-out 600ms cubic-bezier(0.16, 1, 0.3, 1);
--animate-collapse-in: collapse-in 800ms ease-out;
--animate-collapse-out: collapse-out 800ms ease-out;
}
@layer theme {
/* font-family tokens — overridable from an app's own @layer theme :root.
The web values are a fallback list because the two web targets load different families:
- Expo web: expo-font registers weight-specific families
('SoraRegular'/'SoraBold'/'SoraExtraBold', 'ChivoMono*'), no 'Sora'.
- Vite Storybook: Google Fonts loads the single 'Sora'/'Chivo Mono'
families, weight via font-weight.
Native takes single names (React Native has no fallback list) under
@variant native, which web drops. */
:root {
--font-body: "SoraRegular", "Sora", ui-sans-serif, system-ui, sans-serif;
--font-body-bold: "SoraBold", "Sora", ui-sans-serif, system-ui, sans-serif;
--font-body-extrabold:
"SoraExtraBold", "Sora", ui-sans-serif, system-ui, sans-serif;
--font-heading: "SoraRegular", "Sora", ui-sans-serif, system-ui, sans-serif;
--font-heading-bold:
"SoraBold", "Sora", ui-sans-serif, system-ui, sans-serif;
--font-heading-extrabold:
"SoraExtraBold", "Sora", ui-sans-serif, system-ui, sans-serif;
--font-mono:
"ChivoMonoRegular", "ChivoMono", "Chivo Mono", ui-monospace,
SFMono-Regular, Menlo, monospace;
--font-mono-bold:
"ChivoMonoBold", "ChivoMono", "Chivo Mono", ui-monospace, SFMono-Regular,
Menlo, monospace;
--font-mono-extrabold:
"ChivoMonoExtraBold", "ChivoMono", "Chivo Mono", ui-monospace,
SFMono-Regular, Menlo, monospace;
@variant native {
--font-body: "SoraRegular";
--font-body-bold: "SoraBold";
--font-body-extrabold: "SoraExtraBold";
--font-heading: "SoraRegular";
--font-heading-bold: "SoraBold";
--font-heading-extrabold: "SoraExtraBold";
--font-mono: "ChivoMonoRegular";
--font-mono-bold: "ChivoMonoBold";
--font-mono-extrabold: "ChivoMonoExtraBold";
}
}
}
@layer base {
/* hotpink flags any text rendered outside a <Text> */
body {
color: hotpink;
}
/* reset - equivalent to ScrollViewStyleReset */
#root,
#storybook-root,
body,
html {
height: 100%;
display: flex;
flex-direction: column;
}
body {
overflow: hidden;
}
/* let height/width keyframes interpolate to/from auto (collapse-in/out) on web */
:root {
interpolate-size: allow-keywords;
}
/* scrollbar-width/-color have no native equivalent, so this sits behind the
@supports guard the native compiler cannot evaluate and therefore drops.
Global rather than a utility: ScrollView maps className to the style prop,
so a raw CSS class would not reach the DOM node that scrolls.
The track is opaque: a scroll container's background paints across its whole
padding box, gutter included, while its content container stops at the
gutter's inner edge — so a transparent track bares the scroller's own ground
(half of each color of a two-tone gradient frame such as AppShell's).
`lowered` is the inset ground a track should have. The *
selector re-declares the property on every element, so a nested scroller
resolves its own theme's `lowered` rather than inheriting an ancestor's
track. */
@supports (display: contents) {
* {
scrollbar-width: thin;
scrollbar-color: var(--color-border-sharp) var(--color-lowered);
}
}
}
/* keyframes */
@keyframes slide-in {
from {
opacity: 0;
transform: translateX(-100%) rotateY(-90deg);
}
to {
opacity: 1;
transform: translateX(0) rotateY(0deg);
}
}
@keyframes slide-out {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(100%);
}
}
@keyframes collapse-in {
from {
opacity: 0;
height: 0;
}
to {
opacity: 1;
height: auto;
}
}
@keyframes collapse-out {
from {
opacity: 1;
height: auto;
}
to {
opacity: 0;
height: 0;
}
}
/* named transition durations */
@utility duration-slide {
transition-duration: 600ms;
}
@utility duration-collapse {
transition-duration: 800ms;
}
@utility duration-progress {
transition-duration: 600ms;
}
@utility duration-fade {
transition-duration: 300ms;
}
@utility duration-fast {
transition-duration: 200ms;
}
/* font-family + weight utilities.
font-synthesis: none — on Expo web the weight-specific family ('SoraBold') is a
single registered face, so the font-weight must not faux-bold already-bold
glyphs. On Vite 'Sora' is a variable font, where the font-weight selects the
real weight. */
@utility font-body {
font-family: var(--font-body);
font-weight: 400;
font-synthesis: none;
}
@utility font-body-bold {
font-family: var(--font-body-bold);
font-weight: 700;
font-synthesis: none;
}
@utility font-body-extrabold {
font-family: var(--font-body-extrabold);
font-weight: 800;
font-synthesis: none;
}
@utility font-heading {
font-family: var(--font-heading);
font-weight: 400;
font-synthesis: none;
}
@utility font-heading-bold {
font-family: var(--font-heading-bold);
font-weight: 700;
font-synthesis: none;
}
@utility font-heading-extrabold {
font-family: var(--font-heading-extrabold);
font-weight: 800;
font-synthesis: none;
}
@utility font-mono {
font-family: var(--font-mono);
font-weight: 400;
font-synthesis: none;
}
@utility font-mono-bold {
font-family: var(--font-mono-bold);
font-weight: 700;
font-synthesis: none;
}
@utility font-mono-extrabold {
font-family: var(--font-mono-extrabold);
font-weight: 800;
font-synthesis: none;
}
/* tripwire — a standalone font-weight has no effect on native, where each weight
is its own font file (font-body-bold, …). These render visibly thin and cramped
on web so an accidental use is easy to spot. */
@utility font-thin {
font-weight: 100;
letter-spacing: -0.1em;
}
@utility font-extralight {
font-weight: 100;
letter-spacing: -0.1em;
}
@utility font-light {
font-weight: 100;
letter-spacing: -0.1em;
}
@utility font-normal {
font-weight: 100;
letter-spacing: -0.1em;
}
@utility font-medium {
font-weight: 100;
letter-spacing: -0.1em;
}
@utility font-semibold {
font-weight: 100;
letter-spacing: -0.1em;
}
@utility font-bold {
font-weight: 100;
letter-spacing: -0.1em;
}
@utility font-extrabold {
font-weight: 100;
letter-spacing: -0.1em;
}
@utility font-black {
font-weight: 100;
letter-spacing: -0.1em;
}
/* text-base-size-only — the body size without the line-height text-base
pairs with it. A single-line native TextInput must not carry a line-height:
iOS pins the field's line box to min == max == that height and leaves the
extra leading above the glyphs, so the value renders below the middle of the
box while the placeholder — drawn without those attributes — stays centered.
Web needs no such thing (an <input> centers its text whatever the
line-height is), so pair it as `web:text-base native:text-base-size-only`. */
@utility text-base-size-only {
font-size: var(--text-base);
}
/* lowered — one class so the recessed ground and its inset shadow cannot
drift apart */
@utility lowered {
@apply bg-lowered shadow-lowered;
}
/* surface — the raised card. overflow-hidden clips children to the rounded
corners. Any class written after it wins: it sorts ahead of bg-*, shadow-*,
p-*, rounded-*, lowered and the surface-{size} utilities. The transition
fades the ground when the accent or the mode swaps the theme variables
under it. */
@utility surface {
@apply overflow-hidden bg-surface shadow-s surface-md transition-colors duration-fast;
}
/* surface-{size} — padding and radius as one class so the pair cannot drift
apart between call sites. A single p-* / rounded-* written after it still
overrides one side. */
@utility surface-xxs {
@apply p-xs rounded-xs;
}
@utility surface-xs {
@apply p-sm rounded-xs;
}
@utility surface-sm {
@apply p-m rounded-sm;
}
@utility surface-md {
@apply p-xl rounded-sm;
}
@utility surface-lg {
@apply p-xxl rounded-md;
}
/* surface-popover — the panel of Menu, Select and InputTextAutocomplete. Its
rows are rounded-xs, so p-xs + rounded-sm keeps their corners concentric
with the panel's. */
@utility surface-popover {
@apply overflow-hidden bg-highlight shadow-l rounded-sm p-xs;
}
/* flex-center — not `center`, which would clash with a text-align /
place-* shorthand */
@utility flex-center {
align-items: center;
justify-content: center;
}
/* flex-wrap-balance — `balance` evens out the item count across lines, so
the last row is never a lone orphan. Only Safari 26+ implements it;
elsewhere (and on native, where the compiler drops the feature query) it
stays plain `wrap`. */
@utility flex-wrap-balance {
flex-wrap: wrap;
@supports (flex-wrap: balance) {
flex-wrap: balance;
}
}
/* An all-caps label (Avatar initials) centered on its line box sits ~1px high:
the box spans ascender + descender, and caps have no descender. Trimming it to
cap height over baseline centers the ink. Web only: native (where the compiler
drops the feature query) and browsers without `text-box` keep the line box. */
@utility text-trim-cap {
@supports (text-box: trim-both cap alphabetic) {
text-box: trim-both cap alphabetic;
}
}