diff --git a/AGENTS.md b/AGENTS.md
index 9e5fb101..4ea91cb2 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -29,13 +29,14 @@
- `packages/react/`: `@cocso-ui/react` — React component library.
- `packages/css/`: `@cocso-ui/css` — design tokens and CSS.
- `packages/react-icons/`: `@cocso-ui/react-icons` — icon set (re-exports generated components from `@cocso-ui/icons`).
+ - `packages/react-native-icons/`: `@cocso-ui/react-native-icons` — React Native icon set (re-exports generated react-native-svg components from `@cocso-ui/icons`).
- `packages/baseframe-sources/`: `@cocso-ui/baseframe-sources` — YAML component source definitions.
- `packages/recipe/`: `@cocso-ui/recipe` — component visual spec recipes (single source of truth for variant→token mappings, consumed by codegen at build time and Figma generation).
- `packages/figma/`: `@cocso-ui/figma` — Figma plugin for syncing design tokens to Figma Variables and generating components from recipes.
- `ecosystem/`: Tooling that wraps or consumes packages for developer workflows.
- `ecosystem/baseframe/`: `@cocso-ui/baseframe` — CLI for scaffolding components from YAML.
- `ecosystem/codegen/`: `@cocso-ui/codegen` — build-time code generation from recipe definitions (CSS classes, className functions, TypeScript types). Generated output consumed by `@cocso-ui/react`.
- - `ecosystem/icons/`: `@cocso-ui/icons` — canonical SVG icon sources, SVGO optimization, and code generation (SVG → React TSX, SVG → Figma template strings).
+ - `ecosystem/icons/`: `@cocso-ui/icons` — canonical SVG icon sources, SVGO optimization, and code generation (SVG → React TSX, SVG → React Native TSX, SVG → Figma template strings).
- `ecosystem/mcp/`: `@cocso-ui/mcp` — MCP server for design-system-aware component discovery and guidance.
- `AGENTS.md`: This file — repository-wide rules.
- `biome.jsonc`: Lint and format configuration (Biome).
diff --git a/docs/project-icons.md b/docs/project-icons.md
index 91832994..faccfb79 100644
--- a/docs/project-icons.md
+++ b/docs/project-icons.md
@@ -2,7 +2,7 @@
## Goal
-Provide a single source of truth for all SVG icons in the cocso design system. All downstream consumers (`@cocso-ui/react-icons`, `@cocso-ui/figma`) generate their icon representations from this canonical SVG source, eliminating duplication and synchronization bugs.
+Provide a single source of truth for all SVG icons in the cocso design system. All downstream consumers (`@cocso-ui/react-icons`, `@cocso-ui/react-native-icons`, `@cocso-ui/figma`) generate their icon representations from this canonical SVG source, eliminating duplication and synchronization bugs.
## Path
@@ -17,6 +17,7 @@ Node.js (TypeScript). Build-time only — no runtime dependency.
## Users
- `@cocso-ui/react-icons` — consumes generated React icon components via `@cocso-ui/icons/react`.
+- `@cocso-ui/react-native-icons` — consumes generated React Native icon components via `@cocso-ui/icons/react-native`.
- `@cocso-ui/figma` — consumes generated SVG template strings via `@cocso-ui/icons/figma`.
- `@cocso-ui/recipe` — references icons by canonical name in component specs.
- Frontend engineers — browse and discover available icons via Storybook and documentation site.
@@ -27,6 +28,7 @@ Node.js (TypeScript). Build-time only — no runtime dependency.
- Icon metadata registry (`registry.json`): name, category, colorStrategy, componentName, source, tags, viewBox.
- SVGO optimization with conservative configuration (`scripts/optimize.ts`).
- Code generation: SVG to React TSX components (`scripts/generate-react.ts` → `dist/react/`).
+- Code generation: SVG to React Native TSX components (`scripts/generate-react-native.ts` → `dist/react-native/`).
- Code generation: SVG to Figma `{color}` template strings (`scripts/generate-figma.ts` → `dist/figma/`).
- CLI: fetch icons from Tabler Icons (`scripts/fetch-tabler.ts`).
- CLI: add custom SVG icons with metadata auto-detection (`scripts/add-icon.ts`).
@@ -35,7 +37,7 @@ Node.js (TypeScript). Build-time only — no runtime dependency.
## Out of Scope
- Icon design or SVG authoring.
-- Non-React framework bindings (Vue, Angular, Svelte).
+- Non-React/React-Native framework bindings (Vue, Angular, Svelte).
- Webfont or sprite sheet generation.
- Figma plugin icon sync (handled by `@cocso-ui/figma`).
@@ -48,9 +50,11 @@ ecosystem/icons/
│ └── brand/ # 15 brand logos (mixed color strategies, custom viewBox)
├── registry.json # Icon metadata (84 entries)
├── templates/react/ # Shared React source files (icon.tsx, child.tsx, types.ts)
+├── templates/react-native/ # Shared React Native source files (icon.tsx, types.ts)
├── scripts/
│ ├── optimize.ts # SVGO optimization
│ ├── generate-react.ts # SVG → React TSX components
+│ ├── generate-react-native.ts # SVG → React Native TSX components
│ ├── generate-figma.ts # SVG → Figma SVG template strings
│ ├── fetch-tabler.ts # Fetch icons from Tabler Icons
│ ├── add-icon.ts # Add custom SVG icons
@@ -65,6 +69,12 @@ ecosystem/icons/
│ │ ├── child.tsx # Child helper component
│ │ ├── types.ts # IconProps type
│ │ └── index.ts # Barrel export
+│ ├── react-native/ # Generated React Native components (committed to git)
+│ │ ├── semantic/ # 71 TSX files
+│ │ ├── brand/ # 15 TSX files
+│ │ ├── icon.tsx # Icon wrapper component
+│ │ ├── types.ts # IconProps type (extends SvgProps)
+│ │ └── index.ts # Barrel export
│ └── figma/
│ └── icon-svgs.ts # ICON_SVGS record (84 primary + 7 aliases)
└── package.json
@@ -76,6 +86,7 @@ ecosystem/icons/
svg/semantic/*.svg + svg/brand/*.svg
↓ optimize.ts (SVGO)
├── generate-react.ts → dist/react/ → consumed by @cocso-ui/react-icons (re-export)
+ ├── generate-react-native.ts → dist/react-native/ → consumed by @cocso-ui/react-native-icons (re-export)
└── generate-figma.ts → dist/figma/ → consumed by @cocso-ui/figma (import ICON_SVGS)
```
@@ -102,6 +113,9 @@ Public package: `@cocso-ui/icons`
// React components (re-exported by @cocso-ui/react-icons)
import { SearchIcon, CheckIcon } from '@cocso-ui/icons/react';
+// React Native components (re-exported by @cocso-ui/react-native-icons)
+import { SearchIcon, CheckIcon } from '@cocso-ui/icons/react-native';
+
// Figma SVG templates (consumed by @cocso-ui/figma)
import { ICON_SVGS } from '@cocso-ui/icons/figma';
diff --git a/docs/project-react-native-icons.md b/docs/project-react-native-icons.md
new file mode 100644
index 00000000..e6fcf32d
--- /dev/null
+++ b/docs/project-react-native-icons.md
@@ -0,0 +1,111 @@
+# project-react-native-icons
+
+## Goal
+
+Provide a tree-shakable set of SVG icons as React Native components using `react-native-svg`, giving mobile product teams a consistent icon vocabulary aligned with the cocso design system.
+
+## Path
+
+```
+packages/react-native-icons/
+```
+
+## Runtime and Language
+
+React Native (TypeScript), bundled via Rollup into CJS and ESM. Requires `react-native-svg` as a peer dependency.
+
+## Users
+
+- Mobile engineers consuming `@cocso-ui/react-native-icons` in React Native apps.
+- Expo projects using `react-native-svg`.
+
+## In Scope
+
+- Re-export of all generated React Native icon components from `@cocso-ui/icons/react-native`.
+- Dual package output: CJS (`dist/cjs/`) and ESM (`dist/esm/`).
+- Full tree-shaking support (`sideEffects: false`).
+
+## Out of Scope
+
+- Icon SVG sources, metadata, or code generation — owned by `@cocso-ui/icons`.
+- Icon design or SVG authoring.
+- Web React icon components — owned by `@cocso-ui/react-icons`.
+- Expo vector icon font integration.
+
+## Architecture
+
+```
+packages/react-native-icons/
+├── src/
+│ └── index.ts # Re-exports from @cocso-ui/icons/react-native
+├── dist/
+│ ├── cjs/ # CommonJS bundle (single file)
+│ └── esm/ # ESM bundle (single file)
+├── rollup.config.cjs # Build configuration
+└── tsconfig.json
+```
+
+Build pipeline: `src/index.ts` re-exports `@cocso-ui/icons/react-native` → Rollup resolves and bundles all generated TSX components from `@cocso-ui/icons/dist/react-native/` → CJS + ESM + `.d.ts` output.
+
+`@cocso-ui/icons` is a `devDependency` so Rollup bundles the components inline rather than marking them as external. Consumers of the published package do not need `@cocso-ui/icons` installed.
+
+## Interfaces
+
+Public entry point: `@cocso-ui/react-native-icons`
+
+All icons exported as named React Native components:
+
+```tsx
+import { SearchIcon, CheckIcon, COCSOLogo } from '@cocso-ui/react-native-icons';
+
+
+```
+
+Each component accepts `IconProps`:
+
+```ts
+import type { SvgProps } from 'react-native-svg';
+
+type IconProps = {
+ size?: number | string;
+ width?: number | string;
+ height?: number | string;
+} & Omit;
+```
+
+The `color` prop (inherited from `SvgProps`) controls `currentColor` resolution in child SVG elements.
+
+## Storage
+
+No runtime storage. Build output written to `dist/`.
+
+## Security
+
+- No network calls.
+- No secrets or credentials handled.
+- Peer dependencies: `react >=18.0.0`, `react-native >=0.72.0`, `react-native-svg >=13.0.0`.
+
+## Logging
+
+Not applicable.
+
+## Build and Test
+
+```sh
+# Build (CJS + ESM)
+pnpm --filter @cocso-ui/react-native-icons build
+
+# Lint
+pnpm --filter @cocso-ui/react-native-icons lint
+```
+
+CI expects: `build`, `lint` to pass.
+
+## Roadmap
+
+- Add example app or Storybook React Native integration for visual testing.
+- Consider Expo Snack examples for documentation.
+
+## Open Questions
+
+- None at this time.
diff --git a/ecosystem/icons/package.json b/ecosystem/icons/package.json
index 343e13b7..4bb6bc8a 100644
--- a/ecosystem/icons/package.json
+++ b/ecosystem/icons/package.json
@@ -5,6 +5,7 @@
"private": true,
"exports": {
"./react": "./dist/react/index.ts",
+ "./react-native": "./dist/react-native/index.ts",
"./figma": "./dist/figma/icon-svgs.ts",
"./registry.json": "./registry.json"
},
@@ -16,10 +17,11 @@
"scripts": {
"optimize": "tsx scripts/optimize.ts",
"generate:react": "tsx scripts/generate-react.ts",
+ "generate:react-native": "tsx scripts/generate-react-native.ts",
"generate:figma": "tsx scripts/generate-figma.ts",
"validate": "tsx scripts/validate.ts",
"validate:compat": "tsx scripts/validate-compat.ts",
- "build": "tsx scripts/optimize.ts && tsx scripts/generate-react.ts && tsx scripts/generate-figma.ts",
+ "build": "tsx scripts/optimize.ts && tsx scripts/generate-react.ts && tsx scripts/generate-react-native.ts && tsx scripts/generate-figma.ts",
"add-icon": "tsx scripts/add-icon.ts",
"fetch:tabler": "tsx scripts/fetch-tabler.ts",
"lint": "biome check ."
diff --git a/ecosystem/icons/scripts/generate-react-native.ts b/ecosystem/icons/scripts/generate-react-native.ts
new file mode 100644
index 00000000..417b94e7
--- /dev/null
+++ b/ecosystem/icons/scripts/generate-react-native.ts
@@ -0,0 +1,339 @@
+import {
+ cpSync,
+ existsSync,
+ mkdirSync,
+ readFileSync,
+ rmSync,
+ writeFileSync,
+} from "node:fs";
+import { dirname, join } from "node:path";
+import { fileURLToPath } from "node:url";
+import type { Registry, RegistryIcon } from "./types";
+
+const PKG_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
+const SVG_DIR = join(PKG_ROOT, "svg");
+const DIST_DIR = join(PKG_ROOT, "dist");
+const RN_DIST = join(DIST_DIR, "react-native");
+const TEMPLATES_DIR = join(PKG_ROOT, "templates", "react-native");
+
+const SVG_ATTR_MAP: Record = {
+ "alignment-baseline": "alignmentBaseline",
+ "baseline-shift": "baselineShift",
+ "clip-path": "clipPath",
+ "clip-rule": "clipRule",
+ "color-interpolation": "colorInterpolation",
+ "color-interpolation-filters": "colorInterpolationFilters",
+ "dominant-baseline": "dominantBaseline",
+ "fill-opacity": "fillOpacity",
+ "fill-rule": "fillRule",
+ "flood-color": "floodColor",
+ "flood-opacity": "floodOpacity",
+ "font-family": "fontFamily",
+ "font-size": "fontSize",
+ "font-style": "fontStyle",
+ "font-weight": "fontWeight",
+ "letter-spacing": "letterSpacing",
+ "lighting-color": "lightingColor",
+ "paint-order": "paintOrder",
+ "pointer-events": "pointerEvents",
+ "shape-rendering": "shapeRendering",
+ "stop-color": "stopColor",
+ "stop-opacity": "stopOpacity",
+ "stroke-dasharray": "strokeDasharray",
+ "stroke-dashoffset": "strokeDashoffset",
+ "stroke-linecap": "strokeLinecap",
+ "stroke-linejoin": "strokeLinejoin",
+ "stroke-miterlimit": "strokeMiterlimit",
+ "stroke-opacity": "strokeOpacity",
+ "stroke-width": "strokeWidth",
+ "text-anchor": "textAnchor",
+ "text-decoration": "textDecoration",
+ "text-rendering": "textRendering",
+ "vector-effect": "vectorEffect",
+ "word-spacing": "wordSpacing",
+};
+
+const SVG_ATTR_REGEXES = Object.entries(SVG_ATTR_MAP).map(
+ ([svgAttr, jsxAttr]) => ({
+ regex: new RegExp(`(?<=\\s)${svgAttr.replace(/-/g, "\\-")}=`, "g"),
+ replacement: `${jsxAttr}=`,
+ })
+);
+
+function convertAttrsToJsx(content: string): string {
+ let result = content;
+ for (const { regex, replacement } of SVG_ATTR_REGEXES) {
+ result = result.replace(regex, replacement);
+ }
+ return result;
+}
+
+/** Map of HTML SVG element names to react-native-svg component names. */
+const ELEMENT_MAP: Record = {
+ circle: "Circle",
+ clipPath: "ClipPath",
+ defs: "Defs",
+ ellipse: "Ellipse",
+ g: "G",
+ line: "Line",
+ linearGradient: "LinearGradient",
+ mask: "Mask",
+ path: "Path",
+ polygon: "Polygon",
+ polyline: "Polyline",
+ radialGradient: "RadialGradient",
+ rect: "Rect",
+ stop: "Stop",
+ symbol: "Symbol",
+ text: "Text",
+ tspan: "TSpan",
+ use: "Use",
+};
+
+/** Sorted entries with longer names first to avoid partial matches (e.g. "clipPath" before "path"). */
+const ELEMENT_ENTRIES = Object.entries(ELEMENT_MAP).sort(
+ (a, b) => b[0].length - a[0].length
+);
+
+function convertElements(content: string): string {
+ let result = content;
+ for (const [html, rn] of ELEMENT_ENTRIES) {
+ // Opening / self-closing tags
+ result = result.replace(new RegExp(`<${html}([\\s/>])`, "g"), `<${rn}$1`);
+ // Closing tags
+ result = result.replace(new RegExp(`${html}>`, "g"), `${rn}>`);
+ }
+ return result;
+}
+
+function detectUsedElements(inner: string): string[] {
+ const used: string[] = [];
+ for (const [html, rn] of ELEMENT_ENTRIES) {
+ if (new RegExp(`<${html}[\\s/>]`).test(inner)) {
+ used.push(rn);
+ }
+ }
+ return used.sort();
+}
+
+const SVG_RE = /