app-studio 0.8.0 → 0.8.1

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/docs/Animation.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Animation
2
2
 
3
+ > **React Native:** the entire animation system on this page compiles to CSS keyframes and `animation-timeline` rules, which **don't run** in React Native. The `Animation.*` helpers and the `animate` / `animateIn` / `animateOut` / `animateOn` props are accepted on native but have no visual effect. For motion on native, use `Animated` (RN core), `react-native-reanimated`, `LayoutAnimation`, or `moti`. See [Native.md → Animations](Native.md#animations).
4
+
3
5
  ## 1. Introduction
4
6
 
5
7
  App-Studio provides a powerful animation system through the `Animation` object and the `Element` component. This system allows you to easily add dynamic and engaging animations, including:
@@ -2,6 +2,8 @@
2
2
 
3
3
  App-Studio provides a comprehensive set of components built on the `Element` base component. This guide covers all the available components and their usage.
4
4
 
5
+ > **React Native:** every component on this page also ships in the native build, rendered with the matching RN primitive (`View`, `Pressable`, `Text`, `Image`, `TextInput`, `ScrollView`, `SafeAreaView`). See [Native.md](Native.md) for the full mapping table and a list of native-only / web-only props.
6
+
5
7
  ## Element
6
8
 
7
9
  The `Element` component is the foundation of App-Studio. It is responsible for handling a large part of the styles of the other components. It takes care of responsiveness, shadow, margins, and padding among other properties.
@@ -75,6 +77,8 @@ import { Vertical, Horizontal, Center } from 'app-studio';
75
77
  ### Text
76
78
  For displaying text content with theme support. Extends the basic `span` HTML element.
77
79
 
80
+ > **React Native:** renders `<Text>`. Adds `maxLines` (→ `numberOfLines`), `toUpperCase`, `isItalic`, `isStriked`, `isUnderlined`, `isSub`/`isSup`.
81
+
78
82
  ```tsx
79
83
  import { Text } from 'app-studio';
80
84
 
@@ -117,6 +121,8 @@ import { Image } from 'app-studio';
117
121
  />
118
122
  ```
119
123
 
124
+ > **React Native:** `src` is translated to `{ uri: src }` automatically. To use a bundled asset, pass `source={require('./logo.png')}` instead. `alt` becomes `accessibilityLabel`.
125
+
120
126
  ## Form Components
121
127
 
122
128
  ### Form
@@ -129,6 +135,8 @@ Extends the basic `form` HTML element. It's used for creating forms and provides
129
135
  </Form>
130
136
  ```
131
137
 
138
+ > **React Native:** `Form` is an alias for `View` — there is no `form` element on native. Drive submission manually from a `Button`'s `onPress` handler.
139
+
132
140
  ### Input
133
141
  Extends the basic `input` HTML element with additional styling properties.
134
142
 
@@ -150,6 +158,8 @@ import { Input } from 'app-studio';
150
158
  />
151
159
  ```
152
160
 
161
+ > **React Native:** renders `<TextInput>`. Prefer `onChangeText={value => ...}` over `onChange`. The `on` map (hover/focus/etc.) is a no-op — use `TextInput`'s `onFocus`/`onBlur` props for focus styling.
162
+
153
163
  ### Button
154
164
  Interactive button component with built-in states and animations.
155
165
 
@@ -172,6 +182,8 @@ import { Button } from 'app-studio';
172
182
  </Button>
173
183
  ```
174
184
 
185
+ > **React Native:** renders `<Pressable accessibilityRole="button">`. Use `onPress` (or keep `onClick` — it is forwarded to `onPress`). String/number children are wrapped in `<Text>` automatically. The `on` map is dropped — express press feedback via `Pressable`'s `({ pressed }) => style` callback or RN's `Animated` API.
186
+
175
187
  ## Feedback Components
176
188
 
177
189
  ### Skeleton
package/docs/Design.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  The `app-studio` library provides a set of design props that simplify styling and enhance design integration. These props offer a more streamlined and efficient way to manage styling compared to using inline styles or CSS classes directly. They are particularly beneficial for implementing responsive and theme-aware styling, allowing you to easily adapt your components to different screen sizes and themes.
6
6
 
7
+ > **React Native:** the design props on this page (direct style props, `widthHeight`, `shadow`, `media`, theme color strings, the component-level `theme` override) all work the same on native. The `shadow` prop expands to RN's `shadowColor` / `shadowOffset` / `shadowOpacity` / `shadowRadius` plus an Android `elevation`. See [Native.md → Styling Props on Native](Native.md#styling-props-on-native) for the supported-property list and native-only behavior.
8
+
7
9
  Here is an example:
8
10
 
9
11
  ```jsx
package/docs/Events.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  App-Studio provides intuitive ways to manage events in your CSS through the `on` prop and underscore-prefixed properties. These features are designed to offer convenient ways to style elements based on various interactive states, represented by CSS pseudo-classes like `hover`, `active`, and `focus`.
4
4
 
5
+ > **React Native:** the `on={{ hover, active, focus, ... }}` map and every underscore-prefixed state modifier (`_hover`, `_focus`, `_active`, `_disabled`, `_checked`, …) are **web-only** — they're accepted on native but produce no visual change. RN drives interaction state through `Pressable`'s render-prop API (`style={({ pressed, hovered }) => ...}`) and its `onPressIn` / `onPressOut` / `onHoverIn` / `onHoverOut` callbacks; for input focus, use `<TextInput>`'s `onFocus` / `onBlur` directly. The full list of no-op props is in [Native.md → Web-Only Props](Native.md#web-only-props-no-ops-on-native).
6
+
5
7
  ---
6
8
 
7
9
  ## 1. Introduction to Event-Based Styling
package/docs/Hooks.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  App-Studio provides a comprehensive set of React hooks to help you build interactive and responsive applications. This guide covers all the available hooks and their usage.
4
4
 
5
+ > **React Native:** the hooks below are listed by their web behavior. Most have native counterparts; some are exported as **no-op stubs** so shared component code keeps compiling (e.g. `useHover`, `useFocus`, `useClickOutside`, `useElementPosition`, `useKeyPress`, `useOnScreen`, `useInView`, `useIframeStyles`, `useScroll`). The full per-hook breakdown lives in [Native.md → Hooks on Native](Native.md#hooks-on-native).
6
+
5
7
  ## Iframe Support
6
8
 
7
9
  Many hooks in App-Studio support working inside iframes for micro-frontend architectures, preview environments, and embedded widgets.
@@ -1,5 +1,7 @@
1
1
  # Iframe Support
2
2
 
3
+ > **React Native:** iframes don't exist on native — everything on this page is **web-only**. The hooks listed below (`useScroll`, `useScrollAnimation`, `useScrollDirection`, `useSmoothScroll`, `useClickOutside`, `useIframeStyles`) and the `targetWindow` provider option have no native counterpart. On native, drive scroll behavior from `ScrollView` / `FlatList` `onScroll` callbacks instead. See [Native.md → Hooks on Native](Native.md#hooks-on-native).
4
+
3
5
  App-Studio provides first-class support for rendering components inside iframes. This enables use cases like:
4
6
 
5
7
  - **Micro-frontend architectures** - Isolate different parts of your application
package/docs/Native.md ADDED
@@ -0,0 +1,428 @@
1
+ # React Native
2
+
3
+ App-Studio ships a dedicated React Native build alongside its web build. The same import paths and prop-based styling API work in both environments — Metro picks the correct build automatically through the `react-native` export condition.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Setup](#setup)
8
+ 2. [Component Mapping](#component-mapping)
9
+ 3. [Styling Props on Native](#styling-props-on-native)
10
+ 4. [Web-Only Props (No-ops on Native)](#web-only-props-no-ops-on-native)
11
+ 5. [Theme & Color Resolution](#theme--color-resolution)
12
+ 6. [Responsive & Media Queries](#responsive--media-queries)
13
+ 7. [Hooks on Native](#hooks-on-native)
14
+ 8. [Accessibility & Test IDs](#accessibility--test-ids)
15
+ 9. [Animations](#animations)
16
+ 10. [Differences Cheat Sheet](#differences-cheat-sheet)
17
+
18
+ ---
19
+
20
+ ## Setup
21
+
22
+ ### Requirements
23
+
24
+ - React Native `>= 0.79` (Metro must support [package exports](https://reactnative.dev/blog/2023/06/21/package-exports-support); enabled by default in 0.79+).
25
+ - React `>= 17`.
26
+
27
+ ### Install
28
+
29
+ ```bash
30
+ npm install app-studio
31
+ # or
32
+ yarn add app-studio
33
+ ```
34
+
35
+ App-Studio's only runtime dependencies (`color-convert`, `hyphenate-style-name`) are shared between web and native and require no extra Metro configuration.
36
+
37
+ ### Import paths
38
+
39
+ Use the bare package name from any RN file — Metro resolves it to the native build:
40
+
41
+ ```tsx
42
+ import {
43
+ View,
44
+ Text,
45
+ Button,
46
+ ThemeProvider,
47
+ ResponsiveProvider,
48
+ WindowSizeProvider,
49
+ } from 'app-studio';
50
+ ```
51
+
52
+ Two explicit subpaths are also available if you ever need to force a build:
53
+
54
+ - `app-studio/native` — always loads the native build (useful for inspecting the API in a web tool, or for monorepos with non-standard resolvers).
55
+ - `app-studio/web` — always loads the web build.
56
+
57
+ You should not need these subpaths in normal application code.
58
+
59
+ ### Provider tree
60
+
61
+ The provider API is identical to web. A typical RN entrypoint looks like:
62
+
63
+ ```tsx
64
+ import React from 'react';
65
+ import {
66
+ ThemeProvider,
67
+ ResponsiveProvider,
68
+ WindowSizeProvider,
69
+ AnalyticsProvider,
70
+ } from 'app-studio';
71
+ import RootScreen from './RootScreen';
72
+
73
+ export default function App() {
74
+ return (
75
+ <ThemeProvider>
76
+ <WindowSizeProvider>
77
+ <ResponsiveProvider>
78
+ <AnalyticsProvider trackEvent={(event) => console.log(event)}>
79
+ <RootScreen />
80
+ </AnalyticsProvider>
81
+ </ResponsiveProvider>
82
+ </WindowSizeProvider>
83
+ </ThemeProvider>
84
+ );
85
+ }
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Component Mapping
91
+
92
+ Every cross-platform primitive renders a familiar React Native node under the hood. Children are wrapped or forwarded as needed.
93
+
94
+ | App-Studio component | Native renders as | Notes |
95
+ | :---------------------------------- | :------------------------------------------------------------------------- | :---- |
96
+ | `Element`, `View`, `Div`, `Span` | `<View>` — or `<Pressable>` when `onPress`/`onClick` is provided | Children are wrapped between optional `before` / `after` slots. |
97
+ | `Horizontal` | `<View flexDirection="row">` | |
98
+ | `Vertical` | `<View flexDirection="column">` | |
99
+ | `Center` | `<View justifyContent="center" alignItems="center">` | |
100
+ | `HorizontalResponsive` | `<View flexDirection="row">` → `column` at `mobile` breakpoint | Uses `useWindowDimensions` + `ResponsiveProvider`. |
101
+ | `VerticalResponsive` | `<View flexDirection="column">` → `row` at `mobile` breakpoint | |
102
+ | `Scroll` | `<ScrollView>` | Pass standard RN scroll props (e.g. `contentContainerStyle`, `horizontal`). |
103
+ | `SafeArea` | `<SafeAreaView>` (from `react-native`) | For richer behavior use `react-native-safe-area-context` directly. |
104
+ | `Text` | `<Text>` | See [Text-specific props](#text). |
105
+ | `Image` | `<Image>` | `src` is translated to `{ uri: src }` automatically; `source` is also accepted. |
106
+ | `ImageBackground` | `<ImageBackground>` | Same `src` / `source` handling as `Image`. |
107
+ | `Form` | `<View>` | Form semantics don't exist in RN; treat it as an alias for `View`. |
108
+ | `Input` | `<TextInput>` | Use `onChangeText` (not `onChange`). |
109
+ | `Button` | `<Pressable accessibilityRole="button">` | String / number children are wrapped in `<Text>` automatically. |
110
+ | `Skeleton` | `<View accessibilityRole="progressbar">` | Static placeholder — see [Animations](#animations) for shimmer notes. |
111
+
112
+ ### Text
113
+
114
+ Native `Text` accepts a few extra typographic props that translate to RN-friendly equivalents:
115
+
116
+ | Prop | Mapping |
117
+ | :-------------- | :----------------------------------------------------------------------- |
118
+ | `toUpperCase` | Converts string children to uppercase before rendering. |
119
+ | `isItalic` | Sets `fontStyle: 'italic'`. |
120
+ | `isStriked` | Sets `textDecorationLine: 'line-through'`. |
121
+ | `isUnderlined` | Sets `textDecorationLine: 'underline'`. |
122
+ | `isSub` / `isSup` | Forces `fontSize` to 12 unless an explicit size is provided. |
123
+ | `maxLines` | Sets RN's `numberOfLines` prop. |
124
+
125
+ ```tsx
126
+ <Text fontSize={16} fontWeight="bold" maxLines={2} toUpperCase>
127
+ Important headline
128
+ </Text>
129
+ ```
130
+
131
+ ### Image
132
+
133
+ Pass either a remote URL via `src` (web-style) or a native `ImageSourcePropType` via `source`:
134
+
135
+ ```tsx
136
+ <Image src="https://example.com/avatar.png" width={48} height={48} borderRadius={24} alt="User avatar" />
137
+
138
+ // or with a bundled asset
139
+ <Image source={require('./logo.png')} width={120} height={32} />
140
+ ```
141
+
142
+ `alt` is forwarded as `accessibilityLabel`.
143
+
144
+ ### Button
145
+
146
+ Wraps `Pressable`. A `disabled` prop short-circuits both `onPress` and `onClick`:
147
+
148
+ ```tsx
149
+ <Button
150
+ paddingHorizontal={20}
151
+ paddingVertical={12}
152
+ backgroundColor="theme-primary"
153
+ borderRadius={8}
154
+ onPress={handleSubmit}
155
+ disabled={isSubmitting}
156
+ >
157
+ Submit
158
+ </Button>
159
+ ```
160
+
161
+ String children become `<Text>` automatically; pass JSX directly for anything more complex.
162
+
163
+ ---
164
+
165
+ ## Styling Props on Native
166
+
167
+ All cross-platform style props you already use on web work the same way on native, with the same theme-aware color resolution. The native style engine accepts the subset of CSS properties that React Native supports.
168
+
169
+ ### Supported style props
170
+
171
+ The following props are read by the native style engine and applied to the underlying `View` / `Text` / `Image` style. Anything not in this list is passed through to React Native as-is.
172
+
173
+ ```
174
+ Layout & Flex: flex, flexDirection, flexBasis, flexGrow, flexShrink, flexWrap,
175
+ alignContent, alignItems, alignSelf, justifyContent, gap,
176
+ rowGap, columnGap, aspectRatio, direction, display, position,
177
+ top, right, bottom, left, start, end, zIndex, overflow,
178
+
179
+ Box model: width, height, minWidth, minHeight, maxWidth, maxHeight,
180
+ margin*, padding*, (including marginHorizontal/Vertical
181
+ and paddingHorizontal/Vertical), borderWidth*,
182
+ borderRadius*, borderColor*, borderStyle, borderCurve,
183
+
184
+ Typography: color, fontFamily, fontSize, fontStyle, fontWeight,
185
+ fontVariant, lineHeight, letterSpacing, textAlign,
186
+ textAlignVertical, textDecorationLine, textDecorationColor,
187
+ textDecorationStyle, textShadow*, textTransform,
188
+ verticalAlign, writingDirection, includeFontPadding,
189
+
190
+ Visual: backgroundColor, opacity, transform, transformOrigin,
191
+ shadowColor, shadowOffset, shadowOpacity, shadowRadius,
192
+ elevation, boxShadow, overlayColor, tintColor,
193
+ backfaceVisibility, objectFit, resizeMode
194
+ ```
195
+
196
+ ### Native-only convenience props
197
+
198
+ Two cross-platform props are expanded on native (they also exist on web with the same meaning):
199
+
200
+ | Prop | Behavior |
201
+ | :------------ | :------------------------------------------------------------------------------------ |
202
+ | `widthHeight` | Sets both `width` and `height` to the same value. |
203
+ | `shadow` | `true` or a number `0..1` — applies `shadowColor #000`, `shadowRadius 4`, `shadowOffset {0,1}`, `shadowOpacity` (defaulting to `0.2`), and a matching Android `elevation`. |
204
+
205
+ ```tsx
206
+ <View widthHeight={48} backgroundColor="theme-primary" borderRadius={24} shadow={0.3} />
207
+ ```
208
+
209
+ ### `media`, `css`, and `style`
210
+
211
+ The native style engine reads styles from four sources, merged in this order (later sources override earlier ones):
212
+
213
+ 1. Top-level style props on the component.
214
+ 2. `media={{ breakpoint: { ... } }}` entries matching the current width.
215
+ 3. `css={{ ... }}` (plain object only — raw CSS strings have no effect on native).
216
+ 4. `style={{ ... }}` (standard RN `StyleProp`, including arrays). `StyleSheet.flatten` is applied automatically.
217
+
218
+ ```tsx
219
+ <View
220
+ padding={12}
221
+ backgroundColor="color-gray-100"
222
+ media={{ tablet: { padding: 24 }, desktop: { padding: 32 } }}
223
+ css={{ borderColor: 'theme-primary', borderWidth: 1 }}
224
+ style={{ borderRadius: 12 }}
225
+ />
226
+ ```
227
+
228
+ ### `onPress` & `onClick`
229
+
230
+ Native components accept both. If either is set on a non-pressable primitive (`Element`/`View`), the component automatically renders as `Pressable`. `onClick` is forwarded to `Pressable`'s `onPress` so web code that uses `onClick` keeps working.
231
+
232
+ ---
233
+
234
+ ## Web-Only Props (No-ops on Native)
235
+
236
+ To keep the prop API uniform across platforms, the native build *accepts* the following props but does nothing with them — they're silently dropped before reaching the underlying RN component. Code that targets both platforms can leave them in place.
237
+
238
+ **State modifiers (underscore-prefixed):** `_hover`, `_active`, `_focus`, `_visited`, `_disabled`, `_enabled`, `_checked`, `_unchecked`, `_invalid`, `_valid`, `_required`, `_optional`, `_selected`, `_target`, `_firstChild`, `_lastChild`, `_onlyChild`, `_firstOfType`, `_lastOfType`, `_empty`, `_focusVisible`, `_focusWithin`, `_placeholder`, `_groupHover`, `_groupFocus`, `_groupActive`, `_groupDisabled`, `_peerHover`, `_peerFocus`, `_peerActive`, `_peerDisabled`, `_peerChecked`.
239
+
240
+ **Pseudo-elements:** `_before`, `_after`, `_firstLetter`, `_firstLine`, `_selection`, `_backdrop`, `_marker`.
241
+
242
+ **`on={{ ... }}`** — the `on` map (hover/focus/active/etc.) is also a no-op. RN drives interactions through `Pressable` props (`onPressIn`, `onPressOut`, `onHoverIn`, etc.); use those directly when you need interaction-driven style changes.
243
+
244
+ **Other web-only props:**
245
+
246
+ - `as` — RN components don't have HTML tags; the underlying primitive is fixed.
247
+ - `className` — ignored.
248
+ - `css` raw CSS strings — only object-form `css` is read on native.
249
+ - CSS animations declared via `animate` / `animateIn` / `animateOut` / `animateOn` — see [Animations](#animations).
250
+
251
+ If you write a component that's truly platform-divergent, the cleanest path is to split it into `MyComponent.tsx` (web) and `MyComponent.native.tsx` (native) — Metro will pick the `.native` file automatically.
252
+
253
+ ---
254
+
255
+ ## Theme & Color Resolution
256
+
257
+ `ThemeProvider`, `useTheme`, and all the theme prop syntax work on native just like web. Pass color strings (`color-blue-500`, `theme-primary`, `light-white`, `dark-red-200`, `theme-primary-300` for 30% alpha, etc.) directly into any color-accepting prop and they resolve through the theme — no `getColor` call required:
258
+
259
+ ```tsx
260
+ <View backgroundColor="theme-primary" padding={16}>
261
+ <Text color="color-white">Hello, native!</Text>
262
+ </View>
263
+ ```
264
+
265
+ ### Implementation detail
266
+
267
+ On web, alpha colors compile to `color-mix(...)` CSS. On native, the theme provider's `getColor` returns the resolved color string directly (hex or rgba), and the style engine substitutes it into any prop whose name contains `color` (case-insensitive) — `backgroundColor`, `borderColor`, `tintColor`, `shadowColor`, and so on.
268
+
269
+ ### `useTheme` API
270
+
271
+ The native theme context exposes the same surface as web:
272
+
273
+ ```tsx
274
+ const {
275
+ getColor, // (name) => resolved color string
276
+ getColorHex, // (name) => normalized hex
277
+ getColorRGBA, // (name, alpha?: 0..1000) => rgba(...)
278
+ getColorScheme, // (name) => palette or theme token name
279
+ getContrastColor, // (name) => 'black' | 'white'
280
+ theme,
281
+ colors,
282
+ themeMode,
283
+ setThemeMode,
284
+ } = useTheme();
285
+ ```
286
+
287
+ `getColor` returns concrete color values (hex/rgba), so you can pass them to third-party RN libraries that expect a plain string.
288
+
289
+ ### Scoped theme override
290
+
291
+ `Element`, `View`, etc. accept a `theme` prop that locally overrides theme tokens for that subtree. The override applies only to `theme-*` color tokens consumed by *that* component's style props — it does not propagate to child components.
292
+
293
+ ```tsx
294
+ <Element backgroundColor="theme-primary" theme={{ primary: 'color-purple-500' }}>
295
+ ...
296
+ </Element>
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Responsive & Media Queries
302
+
303
+ The native `ResponsiveProvider` is powered by `useWindowDimensions()` from React Native, so it reacts to device rotation and split-screen mode automatically.
304
+
305
+ **Default breakpoints (px):** `xs: 0`, `sm: 340`, `md: 560`, `lg: 1080`, `xl: 1300`.
306
+ **Default devices:** `mobile: [xs, sm]`, `tablet: [md, lg]`, `desktop: [lg, xl]`.
307
+
308
+ Pass `breakpoints` and `devices` props to `ResponsiveProvider` to customize them.
309
+
310
+ ### `media` prop
311
+
312
+ Works the same as on web — keys can be breakpoint names or device names. On native, `media` styles are merged into the inline RN style object whenever the active breakpoint matches.
313
+
314
+ ```tsx
315
+ <View
316
+ padding={12}
317
+ media={{
318
+ mobile: { padding: 12, flexDirection: 'column' },
319
+ tablet: { padding: 24, flexDirection: 'row' },
320
+ }}
321
+ />
322
+ ```
323
+
324
+ ### `useResponsive`
325
+
326
+ ```tsx
327
+ import { useResponsive } from 'app-studio';
328
+
329
+ function AdaptiveCard() {
330
+ const { screen, currentDevice, orientation, on } = useResponsive();
331
+
332
+ return (
333
+ <View flexDirection={on('mobile') ? 'column' : 'row'}>
334
+ <Text>{screen} · {currentDevice} · {orientation}</Text>
335
+ </View>
336
+ );
337
+ }
338
+ ```
339
+
340
+ `screen` (alias for `currentBreakpoint`), `currentDevice`, `orientation`, `on(name)`, and `is(name)` behave identically to web.
341
+
342
+ ---
343
+
344
+ ## Hooks on Native
345
+
346
+ Some hooks are inherently web-only (DOM events, IntersectionObserver, keyboard listeners). On native they are exported as **safe stubs** so that shared component code keeps compiling — but you should not rely on them returning meaningful values.
347
+
348
+ | Hook | Native behavior |
349
+ | :-------------------- | :--------------------------------------------------------------------------------------------- |
350
+ | `useWindowSize` | ✅ Works. Backed by RN's `useWindowDimensions`. |
351
+ | `useWindowDimensions` | ✅ Works. Same data as `useWindowSize`. |
352
+ | `useResponsive` | ✅ Works. Reads from `ResponsiveProvider`. |
353
+ | `useBreakpoint` | ✅ Works. Same as `useResponsive` minus width/height. |
354
+ | `useTheme` | ✅ Works (covered above). |
355
+ | `useAnalytics` | ✅ Works. |
356
+ | `useMount` | ✅ Works. |
357
+ | `useHover` | ⚠️ Stub. Returns `{ isHovered: false, hoverProps: {} }`. Use RN's `Pressable` `onHoverIn`/`onHoverOut` if you need hover on a mouse-capable device. |
358
+ | `useActive` | ⚠️ Stub. Returns `{ isActive: false, activeProps: {} }`. Use `Pressable` `onPressIn`/`onPressOut`. |
359
+ | `useFocus` | ⚠️ Stub. Returns `{ isFocused: false, focusProps: {} }`. Use `TextInput`'s `onFocus`/`onBlur` directly. |
360
+ | `useClickOutside` | ⚠️ Stub. Returns a ref and `isOutside: false`. Patterns like outside-tap dismissal need a `Pressable` overlay in RN. |
361
+ | `useElementPosition` | ⚠️ Stub. RN equivalent is `measure()` on a `ref`. |
362
+ | `useKeyPress` | ⚠️ Stub. Returns `false`. Use `react-native-keyboard-events` or platform-specific code. |
363
+ | `useOnScreen` | ⚠️ Stub. Returns `{ ref, isOnScreen: true }` — assume always visible. |
364
+ | `useInView` | ⚠️ Stub. Returns `{ ref, inView: true }`. For real visibility tracking inside lists, prefer `FlatList`'s `viewabilityConfig` / `onViewableItemsChanged`. |
365
+ | `useIframeStyles` | ⚠️ Stub. iframes don't exist on native. |
366
+ | `useScroll` | ⚠️ Stub. Returns zeroed values and no-op scroll methods. Drive scroll behavior from `ScrollView`/`FlatList`'s `onScroll`. |
367
+ | `useScrollDirection`, `useSmoothScroll`, `useScrollAnimation`, `useInfiniteScroll` | ❌ Not exported on native. Build with RN's own scroll events. |
368
+
369
+ The stubs exist so a single component body can run on both platforms without conditionals — but on native you should branch when meaningful interaction state is required.
370
+
371
+ ---
372
+
373
+ ## Accessibility & Test IDs
374
+
375
+ The native build automatically rewrites two common web attributes to their RN equivalents:
376
+
377
+ | Web prop | Native prop |
378
+ | :------------- | :--------------------- |
379
+ | `data-testid` | `testID` |
380
+ | `aria-label` | `accessibilityLabel` |
381
+
382
+ So shared component code can keep using `data-testid="submit"` and it will be picked up by Detox/Maestro/Appium without any changes.
383
+
384
+ ```tsx
385
+ <Button data-testid="submit" aria-label="Submit form" onPress={handleSubmit}>
386
+ Submit
387
+ </Button>
388
+ ```
389
+
390
+ For RN-specific a11y APIs (`accessibilityRole`, `accessibilityState`, `accessibilityHint`, etc.) pass them through directly — they're forwarded untouched to the underlying primitive.
391
+
392
+ ---
393
+
394
+ ## Animations
395
+
396
+ The `Animation.*` presets and the `animate` / `animateIn` / `animateOut` / `animateOn` props compile to CSS keyframes, which **don't run** in React Native. On native these props are accepted but have no visual effect.
397
+
398
+ For motion on native, use one of:
399
+
400
+ - **`Animated` API** (`react-native` core) for simple interpolations.
401
+ - **`react-native-reanimated`** for performant, gesture-driven animations.
402
+ - **`LayoutAnimation`** for automatic layout transitions.
403
+ - **`moti`** for a declarative API similar to App-Studio's `animate` prop.
404
+
405
+ A native-flavored animation system is on the roadmap — see [next.md](../next.md) for status. Until then, drop down to the libraries above for native motion.
406
+
407
+ ---
408
+
409
+ ## Differences Cheat Sheet
410
+
411
+ | Concern | Web | Native |
412
+ | :---------------------------- | :--------------------------------------------- | :---------------------------------------------------------------------- |
413
+ | Underlying primitive | HTML elements (`div`, `span`, `button`, …) | RN primitives (`View`, `Pressable`, `Text`, `Image`, `TextInput`, …) |
414
+ | `as` prop | Selects HTML tag | Ignored |
415
+ | Pseudo-classes (`_hover`, `on`) | Compiled to CSS | Silently dropped — use `Pressable` event props instead |
416
+ | Pseudo-elements (`_before`, `_after`) | Compiled to CSS | Silently dropped — render real components instead |
417
+ | `className` | Applied to DOM element | Ignored |
418
+ | `css` raw string | Injected into stylesheet | Ignored (object form still works) |
419
+ | `style` | Standard CSSProperties | RN `StyleProp` (object, array, or `StyleSheet` reference) |
420
+ | Animations | CSS keyframes via `Animation.*` | No-op — bring `Animated` / Reanimated / Moti |
421
+ | `Image` source | `src` / `srcSet` | `src` (URI shorthand) or `source={...}` |
422
+ | `Input` change handler | `onChange` | `onChangeText` (RN-native) — `onChange` is also forwarded |
423
+ | Click handlers | `onClick` | `onPress` (preferred); `onClick` forwards to `onPress` |
424
+ | Test IDs | `data-testid` | `data-testid` (rewritten to `testID`) — or `testID` directly |
425
+ | A11y label | `aria-label` | `aria-label` (rewritten to `accessibilityLabel`) — or `accessibilityLabel` directly |
426
+ | `useScroll` family | Reads from `window` / scroll containers | Stubbed; use `ScrollView`/`FlatList` `onScroll` |
427
+ | `useInView` / `useOnScreen` | `IntersectionObserver` | Stubbed; use `FlatList` viewability |
428
+ | `useKeyPress` | DOM key events | Stubbed |
package/docs/Providers.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  App-Studio includes several context providers to manage global state and functionality.
4
4
 
5
+ > **React Native:** all four providers (`ThemeProvider`, `ResponsiveProvider`, `WindowSizeProvider`, `AnalyticsProvider`) are exported from the native build with the same API. On native, `ResponsiveProvider` and `WindowSizeProvider` are driven by RN's `useWindowDimensions()`, so they react to rotation and split-screen automatically. See [Native.md → Setup](Native.md#setup) for the recommended provider tree.
6
+
5
7
  ## ThemeProvider
6
8
 
7
9
  Manages theme context including colors, dark/light mode, and design tokens.
package/docs/README.md CHANGED
@@ -58,6 +58,8 @@ import { View, Text, Button, ThemeProvider, ResponsiveProvider } from 'app-studi
58
58
 
59
59
  Metro resolves the package to App-Studio's native build through the `react-native` export condition. Use `app-studio/native` or `app-studio/web` only when you need an explicit platform subpath. Native exposes the cross-platform primitives/providers; web-only props such as `_hover`, pseudo-elements, CSS animations, and HTML `as` values are accepted as no-ops.
60
60
 
61
+ See the [React Native guide](Native.md) for component mapping, native-only props, hook behavior on native, and a side-by-side cheat sheet.
62
+
61
63
  ## Core Concepts
62
64
 
63
65
  ### Element Component
@@ -90,13 +92,14 @@ Explore these guides to learn more about App-Studio:
90
92
 
91
93
  - [Components](Components.md) - Detailed documentation of all available components
92
94
  - [Hooks](Hooks.md) - Guide to the React hooks provided by App-Studio
93
- - [Theming](Theming.md) - How to customize colors and themes with theme colors and color palettes
95
+ - [Theming](Theming.md) - Customize colors, theme tokens, color palettes, and component-level sub-theming via the `theme` prop
94
96
  - [Styling](Styling.md) - Advanced styling guide covering state modifiers, pseudo-elements, media queries, and the CSS system
95
97
  - [Animation](Animation.md) - Creating animations with App-Studio
96
98
  - [Responsive Design](Responsive.md) - Building responsive layouts
97
99
  - [Design System](Design.md) - Understanding the design system
98
100
  - [Event Handling](Events.md) - Working with events and interactions
99
101
  - [Providers](Providers.md) - Context providers for global state
102
+ - [React Native](Native.md) - Using App-Studio in React Native projects (component mapping, native-only props, hook differences)
100
103
  - [Migration Guide](../codemod/README.md) - Migrating to App-Studio
101
104
 
102
105
  ---
@@ -2,6 +2,8 @@
2
2
 
3
3
  Creating a responsive design is an essential part of modern web development. In App-Studio, two primary features help you achieve this: `useResponsive` hook and the `media` prop. This document provides an overview and examples for both approaches.
4
4
 
5
+ > **React Native:** both the `media` prop and `useResponsive` work on native. Width tracking is backed by RN's `useWindowDimensions`, so values update on rotation and split-screen. The default breakpoints (`xs: 0`, `sm: 340`, `md: 560`, `lg: 1080`, `xl: 1300`) and devices (`mobile`, `tablet`, `desktop`) are shared with web — override them by passing `breakpoints` / `devices` to `ResponsiveProvider`. See [Native.md → Responsive & Media Queries](Native.md#responsive--media-queries).
6
+
5
7
  ---
6
8
 
7
9
  ## 1. Media Prop for Responsive Design
package/docs/Styling.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  This guide covers advanced styling techniques in App-Studio, including state modifiers, pseudo-elements, media queries, and the underlying CSS system.
4
4
 
5
+ > **React Native:** state modifiers (`_hover`, `_focus`, `_disabled`, …), pseudo-elements (`_before`, `_after`, …), the `on={{ ... }}` map, and raw-string `css` are **web-only**. They are accepted on native but produce no output — express equivalent behavior with `Pressable`'s event props or RN's `Animated` API. Direct style props, the `media` map, object-form `css`, theme color strings, the `widthHeight` shorthand, and the `shadow` prop all work the same on native. See [Native.md → Styling Props on Native](Native.md#styling-props-on-native).
6
+
5
7
  ## Table of Contents
6
8
 
7
9
  1. [State Modifiers](#state-modifiers)
package/docs/Theming.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Theming is an essential part of any application. It allows you to maintain a consistent look and feel across your app. With App-Studio, theming becomes effortless through its `ThemeProvider` component. This document shows you how to set up theming in App-Studio.
4
4
 
5
+ > **React Native:** the entire color system documented here (singletons, palettes, theme tokens, `light-`/`dark-` prefixes, alpha shorthand, component-level `theme` overrides) works identically on native. The only implementation difference: on web, alpha colors compile to `color-mix(...)` CSS; on native the theme provider returns concrete hex/rgba strings that get substituted into RN style props. See [Native.md → Theme & Color Resolution](Native.md#theme--color-resolution).
6
+
5
7
  ## Available Colors Reference
6
8
 
7
9
  App-Studio provides an extensive color system with three types of colors:
@@ -413,6 +415,57 @@ function Example() {
413
415
 
414
416
  This direct access syntax works with all color-related properties and can be used with both singleton colors (like `white`, `black`) and palette colors (like `red-200`, `blue-500`). It provides a convenient way to reference specific theme colors without having to use the `getColor` function from the `useTheme` hook.
415
417
 
418
+ ### Component-Level Sub-Theming
419
+
420
+ Any component that extends `Element` (`View`, `Text`, `Button`, etc.) accepts a `theme` prop that remaps `theme-*` tokens **for that single component**, without touching the global `ThemeProvider`. Useful when a screen needs one "branded" element (a Startup Studio launch button, a special card, a colored chip) while the rest of the UI keeps the global palette.
421
+
422
+ ```javascript
423
+ import { View, Text } from 'app-studio';
424
+
425
+ function Example() {
426
+ return (
427
+ <View>
428
+ {/* Global theme-primary (no override) */}
429
+ <View backgroundColor="theme-primary" padding={20}>
430
+ <Text color="color-white">Global primary</Text>
431
+ </View>
432
+
433
+ {/* Same component, locally remapped to red */}
434
+ <View
435
+ backgroundColor="theme-primary"
436
+ theme={{ primary: 'color-red-500' }}
437
+ padding={20}
438
+ >
439
+ <Text color="color-white">Local primary = red-500</Text>
440
+ </View>
441
+
442
+ {/* Multiple slots at once */}
443
+ <View
444
+ backgroundColor="theme-primary"
445
+ borderColor="theme-secondary"
446
+ borderWidth={2}
447
+ borderStyle="solid"
448
+ theme={{
449
+ primary: 'color-indigo-600',
450
+ secondary: 'color-yellow-400',
451
+ }}
452
+ padding={20}
453
+ >
454
+ <Text color="color-white">indigo bg, yellow border</Text>
455
+ </View>
456
+ </View>
457
+ );
458
+ }
459
+ ```
460
+
461
+ **What the `theme` prop accepts**: a `Partial<Theme>` where each value is itself a color token (`'color-red-500'`, `'theme-secondary'`) or a direct color string (`'#ff0000'`). The keys match the global `Theme` shape (`primary`, `secondary`, `success`, `error`, `warning`, `disabled`, `loading`).
462
+
463
+ **Alpha suffix works**: `theme-primary-200` on a component with `theme={{ primary: 'color-red-500' }}` resolves to `color-red-500` at 20% opacity via `color-mix()`.
464
+
465
+ **Dark mode**: overrides that point at palette tokens (e.g., `'color-red-500'`) keep responding to global dark-mode switching, because the resolution returns the underlying CSS variable. Overrides that point at raw hex literals (`'#ff0000'`) bypass the palette and do **not** swap with dark mode — use palette tokens whenever you need dark-mode reactivity.
466
+
467
+ **Scope**: the override applies only to the Element receiving the `theme` prop. Children that re-use `theme-primary` resolve against the global theme, not the parent's override. To remap an entire subtree, wrap it in a nested `ThemeProvider` instead, or set the `theme` prop on each child.
468
+
416
469
  ### Smart Text Contrast
417
470
 
418
471
  For text that needs to be visible on any background color (light, dark, or dynamic gradients), App-Studio provides a smart contrast feature.