From fedb7770411917520a3ff641f921ed969722aa00 Mon Sep 17 00:00:00 2001 From: Dustin Do Date: Mon, 10 Aug 2026 17:39:05 +0700 Subject: [PATCH] docs: fix inaccurate readme claims and document bundle size --- README.md | 118 +++++++++++++++++++++++++++++++++++++++------------- global.d.ts | 4 +- 2 files changed, 92 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 5f936f940..4a4a513bc 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,14 @@ # phosphor-react-native +[![npm version](https://img.shields.io/npm/v/phosphor-react-native.svg)](https://www.npmjs.com/package/phosphor-react-native) +[![npm downloads](https://img.shields.io/npm/dm/phosphor-react-native.svg)](https://www.npmjs.com/package/phosphor-react-native) +[![license](https://img.shields.io/npm/l/phosphor-react-native.svg)](LICENSE) + Phosphor is a flexible icon family for interfaces, diagrams, presentations — whatever, really. Explore all our icons at [phosphoricons.com](https://phosphoricons.com). -Inspired by [phosphor-react](https://github.com/phosphor-icons/phosphor-react). +Inspired by [@phosphor-icons/react](https://github.com/phosphor-icons/react). + +This package ships 1512 icons in 6 weights, generated from [@phosphor-icons/core](https://github.com/phosphor-icons/core). @@ -28,9 +34,15 @@ or npm install --save phosphor-react-native react-native-svg ``` +Expo: + +```bash +npx expo install phosphor-react-native react-native-svg +``` + ## Usage -Simply import the icons you need, and add them anywhere in your render method. Phosphor supports tree-shaking, so your bundle only includes code for the icons you use. +Import the icons you need, and add them anywhere in your render method. ```tsx import React from 'react'; @@ -48,6 +60,31 @@ const App = () => { }; ``` +### Bundle size + +Metro does not tree-shake by default, so the import above pulls **all 1512 icons** into your bundle even if you use three of them. See [#61](https://github.com/duongdev/phosphor-react-native/issues/61). + +Two ways to avoid that: + +**1. Import each icon directly** — works on every setup, no configuration: + +```tsx +import { StarIcon } from 'phosphor-react-native/src/icons/Star'; +``` + +**2. Enable Expo's experimental tree-shaking** — see [the Expo guide](https://docs.expo.dev/guides/tree-shaking/). Then the barrel import is just as small. + +Measured with `yarn bundle-bench` (real Metro, iOS, minified, v3.0.5): + +| Scenario | Bundle | vs baseline | +| --- | --- | --- | +| Barrel import, 1 icon, no tree-shaking | 8597 kB | +182% | +| Barrel import, 3 icons, no tree-shaking | 8598 kB | +182% | +| Direct import, 1 icon, no tree-shaking | 1876 kB | +10% | +| Barrel import, 1 icon, tree-shaking on | 1854 kB | +10% | + +Icons are generated per icon, not per weight, so a single icon always carries all 6 weights. + ### Typescript support If you get this error... ``` @@ -55,33 +92,39 @@ Property 'className' does not exist on type 'IntrinsicAttributes & IntrinsicClas ``` Add this code to your `global.d.ts` file ```ts -import type { SvgProps as DefaultSvgProps } from 'react-native-svg'; +import 'react-native-svg'; +import 'phosphor-react-native'; declare module 'react-native-svg' { - interface SvgProps extends DefaultSvgProps { + interface SvgProps { className?: string; } } -declare module "phosphor-react-native" { - interface IconProps extends DefaultIconProps { +declare module 'phosphor-react-native' { + interface IconProps { className?: string; } } ``` +Module augmentation merges into the existing interface, so declare only the extra members — writing `interface SvgProps extends DefaultSvgProps` makes the type reference itself (`TS2310`). + ### Props -Icon components accept all props that you can pass to a normal SVG element, including inline `style` objects, `onClick` handlers, and more. The main way of styling them will usually be with the following props: +Icons are styled with the following props: -- **color?**: `string` – Icon stroke/fill color. Can be any CSS color string, including `hex`, `rgb`, `rgba`, `hsl`, `hsla`, named colors. -- **size?**: `number | string` – Icon height & width. As with standard React elements, this can be a number, or a string with units in `px`, `%`, `em`, `rem`, `pt`, `cm`, `mm`, `in`. -- **weight?**: `"thin" | "light" | "regular" | "bold" | "fill" | "duotone"` – Icon weight/style. Can also be used, for example, to "toggle" an icon's state: a rating component could use Stars with `weight="regular"` to denote an empty star, and `weight="fill"` to denote a filled star. -- **mirrored?**: `boolean` – Flip the icon horizontally. Can be useful in RTL languages where normal icon orientation is not appropriate. +- **color?**: `string` – Icon stroke/fill color. Any color string React Native accepts, including `hex`, `rgb`, `rgba`, `hsl`, `hsla`, named colors. Default `#000`. +- **size?**: `number | string` – Icon height & width. Default `24`. Use a number, or a percentage string such as `"50%"`. Other unit suffixes are parsed with `parseInt`, so `"24px"` is `24` — but `"2rem"` is also `2`, not 32. +- **weight?**: `"thin" | "light" | "regular" | "bold" | "fill" | "duotone"` – Icon weight/style. Default `regular`. Can also be used, for example, to "toggle" an icon's state: a rating component could use Stars with `weight="regular"` to denote an empty star, and `weight="fill"` to denote a filled star. +- **mirrored?**: `boolean` – Flip the icon horizontally. Default `false`. Can be useful in RTL languages where normal icon orientation is not appropriate. +- **style?**: `StyleProp>` – Style applied to the underlying `Svg`. - **title?**: `string` – Accessibility label - **titleId?**: `string` – Accessibility label ID -- **testID?**: `string` – testID for tests -- **duotoneColor?**: `string` – Duotone fill color. Can be any CSS color string, including `hex`, `rgb`, `rgba`, `hsl`, `hsla`, named colors. Default value to black. -- **duotoneOpacity?**: `number` – The opacity of the duotoneColor. Default value to 0.2. +- **testID?**: `string` – testID for tests. Falls back to `phosphor-react-native--`, where `` is the weight you passed explicitly. +- **duotoneColor?**: `string` – Fill color of the duotone background layer. Defaults to `color`, so an icon with `color="teal"` gets a teal background layer — not a black one. +- **duotoneOpacity?**: `number` – The opacity of the duotoneColor. Default `0.2`. + +`IconProps` is a closed type: props outside this list (`onPress`, `fill`, …) are forwarded to the underlying `Svg` at runtime, but TypeScript rejects them. Widen `IconProps` with [module augmentation](#typescript-support) if you need more. ### Context @@ -111,11 +154,13 @@ const App = () => { }; ``` +Every styling prop is context-able: `color`, `size`, `weight`, `mirrored`, `style`, `duotoneColor` and `duotoneOpacity`. Props set on an icon win over the Context. Defaults when neither is set: `color: '#000'`, `size: 24`, `weight: 'regular'`, `mirrored: false`, `duotoneOpacity: 0.2`. + You may create multiple Contexts for styling icons differently in separate regions of an application; icons use the nearest Context above them to determine their style. ### Imports -You may wish to import all icons at once for use in your project, though depending on your bundler this could prevent tree-shaking and make your app's bundle larger. +You may wish to import all icons at once for use in your project. Without tree-shaking this pulls every icon into your bundle — see [Bundle size](#bundle-size). ```tsx import * as Icon from "phosphor-react-native"; @@ -129,25 +174,42 @@ import * as Icon from "phosphor-react-native"; In cases where tree shaking does not work (resulting in large bundle size), you can import icons individually in this format: ```tsx -// Javascript -import { StarIcon } from "phosphor-react-native/lib/commonjs/icons/Star"; - -// Typescript import { StarIcon } from 'phosphor-react-native/src/icons/Star'; - + +``` + +The file name is the icon name in PascalCase (`arrow-left` → `ArrowLeft`), and the export is that name suffixed with `Icon`. `src/icons/*` is the only subpath this package exports — importing from `lib/commonjs/...` fails with `ERR_PACKAGE_PATH_NOT_EXPORTED` on any bundler that honours `exports`, which Metro does by default since React Native 0.79. + +### Migrating from v2 + +Since v3 every icon is exported with an `Icon` suffix: `Horse` → `HorseIcon`. The old names still work but are marked `@deprecated`, except for three whose bare names collide with other identifiers and were removed outright: + +| v2 | v3 | +| --- | --- | +| `Circle` | `CircleIcon` | +| `Path` | `PathIcon` | +| `Infinity` | `InfinityIcon` | + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow. A runnable Expo app lives in [`example/`](example). Icons are generated from the `core` git submodule, so start with: + +```bash +git submodule update --init --recursive ``` ## Related Projects -- [phosphor-home](https://github.com/phosphor-icons/phosphor-home) ▲ Phosphor homepage and general info -- [phosphor-react](https://github.com/phosphor-icons/phosphor-react) ▲ Phosphor icon component library for React -- [phosphor-vue](https://github.com/phosphor-icons/phosphor-vue) ▲ Phosphor icon component library for Vue -- [phosphor-icons](https://github.com/phosphor-icons/phosphor-icons) ▲ Phosphor icons for Vanilla JS -- [phosphor-flutter](https://github.com/phosphor-icons/phosphor-flutter) ▲ Phosphor IconData library for Flutter -- [phosphor-webcomponents](https://github.com/phosphor-icons/phosphor-webcomponents) ▲ Phosphor icons as Web Components -- [phosphor-figma](https://github.com/phosphor-icons/phosphor-figma) ▲ Phosphor icons Figma plugin -- [phosphor-sketch](https://github.com/phosphor-icons/phosphor-sketch) ▲ Phosphor icons Sketch plugin +- [homepage](https://github.com/phosphor-icons/homepage) ▲ Phosphor homepage and general info +- [core](https://github.com/phosphor-icons/core) ▲ Phosphor icon assets, the source this package generates from +- [react](https://github.com/phosphor-icons/react) ▲ Phosphor icon component library for React +- [vue](https://github.com/phosphor-icons/vue) ▲ Phosphor icon component library for Vue +- [web](https://github.com/phosphor-icons/web) ▲ Phosphor icons for Vanilla JS +- [flutter](https://github.com/phosphor-icons/flutter) ▲ Phosphor IconData library for Flutter +- [webcomponents](https://github.com/phosphor-icons/webcomponents) ▲ Phosphor icons as Web Components +- [figma](https://github.com/phosphor-icons/figma) ▲ Phosphor icons Figma plugin +- [sketch](https://github.com/phosphor-icons/sketch) ▲ Phosphor icons Sketch plugin ## License diff --git a/global.d.ts b/global.d.ts index 88840e3cf..72f73dd8d 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,7 +1,7 @@ -import type { SvgProps as DefaultSvgProps } from 'react-native-svg'; +import 'react-native-svg'; declare module 'react-native-svg' { - interface SvgProps extends DefaultSvgProps { + interface SvgProps { className?: string; } }