{"id":13393442,"url":"https://github.com/Temzasse/stitches-native","last_synced_at":"2025-03-13T19:31:36.230Z","repository":{"id":38384705,"uuid":"363656313","full_name":"Temzasse/stitches-native","owner":"Temzasse","description":"React Native implementation of Stitches (CSS-in-JS library)","archived":false,"fork":false,"pushed_at":"2024-04-12T15:49:35.000Z","size":793,"stargazers_count":255,"open_issues_count":9,"forks_count":11,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-08T12:20:08.003Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Temzasse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-02T13:22:10.000Z","updated_at":"2025-02-11T21:35:19.000Z","dependencies_parsed_at":"2024-06-18T21:29:42.959Z","dependency_job_id":"72d5e67a-e67b-4dc8-9b84-4fdc2c970134","html_url":"https://github.com/Temzasse/stitches-native","commit_stats":{"total_commits":111,"total_committers":10,"mean_commits":11.1,"dds":"0.10810810810810811","last_synced_commit":"bd795a8d62007aa505463fdaa8e0d5258f668026"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Temzasse%2Fstitches-native","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Temzasse%2Fstitches-native/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Temzasse%2Fstitches-native/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Temzasse%2Fstitches-native/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Temzasse","download_url":"https://codeload.github.com/Temzasse/stitches-native/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243345591,"owners_count":20275871,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T17:00:52.830Z","updated_at":"2025-03-13T19:31:36.193Z","avatar_url":"https://github.com/Temzasse.png","language":"TypeScript","funding_links":[],"categories":["JavaScript","TypeScript"],"sub_categories":[],"readme":"\u003cp align='center'\u003e\n  \u003cimg src=\"media/logo.jpg\" alt=\"Stitches Native logo\"/\u003e\n\u003cp/\u003e\n\n\u003cdiv align=\"center\" \u003e\n  \u003ch1\u003e\n    Stitches Native\n  \u003c/h1\u003e\n  \u0026middot;\n  \u003ci\u003eReact Native implementation of the popular CSS-in-JS library Stitches\u003c/i\u003e\n  \u0026middot;\n  \u003cbr/\u003e\n  \u003cbr/\u003e\n\u003c/div\u003e\n\n## Installation\n\n```sh\nnpm install stitches-native\n```\n\nor if you use `yarn`:\n\n```sh\nyarn add stitches-native\n```\n\n## Documentation\n\nFor the most part Stitches Native behaves exactly as Stitches so you should follow the [Stitches documentation](https://stitches.dev/) to learn the basic principles and how to setup everything.\n\n## Differences\n\nDue to the inherit differences between the Web and native platforms (iOS + Android) the implementation of Stitches Native differs slightly from the original Web version of Stitches.\n\nFirst of all, CSS in React Native doesn't have CSS Variables, cascade, inheritance, keyframes, pseudo elements/classes, or global styles which means that some features that are available in Stitches are not possible to implement in Stitches Native.\n\nBelow you can see a list of all supported and unsupported features of Stitches Native.\n\n### Feature comparison\n\n| Feature               | Supported                                 |\n| --------------------- | ----------------------------------------- |\n| `styled`              | ✅                                        |\n| `createStitches`      | ✅                                        |\n| `defaultThemeMap`     | ✅                                        |\n| `css`                 | ✅ _(Simplified version)_                 |\n| `theme`               | ✅ _(Use `useTheme` in components/hooks)_ |\n| `createTheme`         | ✅ _(Only returned by `createStitches`)_  |\n| `useTheme`            | 🆕 (Stitches Native specific)             |\n| `ThemeProvider`       | 🆕 (Stitches Native specific)             |\n| `styled().attrs()`    | 🆕 (Stitches Native specific)             |\n| `globalCss`           | ❌ _(No global styles in RN)_             |\n| `keyframes`           | ❌ _(No CSS keyframes in RN)_             |\n| `getCssText`          | ❌ _(SSR not applicable to RN)_           |\n| Nesting               | ❌ _(No CSS cascade in RN)_               |\n| Selectors             | ❌ _(No CSS selectors in RN)_             |\n| Locally scoped tokens | ❌ _(No CSS variables in RN)_             |\n| Pseudo elements       | ❌ _(No pseudo elements/classes in RN)_   |\n\n### Using `createStitches` function\n\nThe `createStitches` function doesn't need `prefix` or `insertionMethod` since they are not used in the native implementation.\n\n```js\nimport { createStitches } from 'stitches-native';\n\ncreateStitches({\n  theme: object,\n  media: object,\n  utils: object,\n  themeMap: object,\n});\n```\n\nThe return value of `createStitches` doesn't include `globalCss`, `keyframes`, or `getCssText` since they are not available in native platforms. React Native doesn't have any CSS keyframes based animations and all animations should be handled by the [Animated API](https://reactnative.dev/docs/animated) or with libraries such as [react-native-reanimated](https://github.com/software-mansion/react-native-reanimated).\n\nThe return value of `createStitches` consist of the following:\n\n```js\nconst { styled, css, theme, createTheme, useTheme, ThemeProvider, config } =\n  createStitches({\n    /*...*/\n  });\n```\n\n#### Supported token types\n\nThe following token types are supported in React Native: `borderStyles`, `borderWidths`, `colors`, `fonts`, `fontSizes`, `fontWeights`, `letterSpacings`, `lineHeights`, `radii`, `sizes`, `space`, `zIndices`.\n\nThe only unsupported token types are `shadows` and `transitions`. Shadows in React Native cannot be expressed with a single string token like on the Web where CSS `box-shadow` accepts a string that fully describes the shadow. In React Native shadows are defined differently on iOS and Android. On [iOS](https://reactnative.dev/docs/shadow-props) you need to set the various shadow properties separately:\n\n```ts\nshadowOffset: {\n  width: number,\n  height: number\n},\nshadowOpacity: number,\nshadowRadius: number\n```\n\nOn [Android](https://developer.android.com/training/material/shadows-clipping#Elevation) there is a completely different elevation system that doesn't let you alter individual shadow properties but instead you have to set a single number as the elevation level:\n\n```ts\nelevation: number;\n```\n\nSo, instead of having shadows as part of the design tokens in the `theme` we can quite easily define shadow utilities inside `utils`:\n\n```js\ncreateStitches({\n  utils: {\n    shadow: (level: 'small' | 'medium' | 'large') =\u003e {\n      return {\n        small: {\n          elevation: 2,\n          shadowOffset: { width: 0, height: 1 },\n          shadowRadius: 3,\n          shadowOpacity: 0.1,\n          shadowColor: '#000',\n        },\n        medium: {\n          elevation: 5,\n          shadowOffset: { width: 0, height: 3 },\n          shadowRadius: 6,\n          shadowOpacity: 0.2,\n          shadowColor: '#000',\n        },\n        large: {\n          elevation: 10,\n          shadowOffset: { width: 0, height: 6 },\n          shadowRadius: 12,\n          shadowOpacity: 0.4,\n          shadowColor: '#000',\n        },\n      }[level];\n    },\n  },\n});\n```\n\nYou can then use the shadow util like this:\n\n```js\nconst Comp = styled('View', {\n  shadow: 'medium',\n});\n```\n\nThe other unsupported token type is `transitions` which conflicts with how animations are handled in React Native. Read more about animations in the [Animations docs](https://reactnative.dev/docs/animations).\n\n### Using `css` helper\n\nUnlike on the Web there is no concept of `className` in React Native so the `css` function is basically an identity function providing only TS types for the style object and returning exactly the same object back (or if given multiple objects merges them together). The returned object can be appended after the first argument of a styled component.\n\n```jsx\nconst styles = css({\n  backgroundColor: '$background', // \u003c- get autocomplete for theme values\n});\n\nconst SomeComp = styled(\n  'View',\n  {\n    /* ...other styles... */\n  },\n  styles // \u003c- you can add as many shared styles as you want\n);\n\n\u003cAnotherComp css={styles} /\u003e;\n```\n\n### Theming with `createTheme`\n\nStitches Native handles theming differently than Stitches. Since there are no CSS Variables in React Native theming is handled via React Context in a similar way as other CSS-in-JS libraries such as [styled-components](https://styled-components.com/docs/advanced#theming) handle theming.\n\n```tsx\nconst { theme, createTheme, ThemeProvider } = createStitches({\n  colors: {\n    background: '#fff',\n    text: '#000',\n  },\n});\n\nconst darkTheme = createTheme({\n  colors: {\n    background: '#000',\n    text: '#fff',\n  },\n});\n\nfunction App() {\n  // In a real world scenario this value should probably live in React Context\n  const [darkMode, setDarkMode] = useState(false);\n\n  return (\n    \u003cThemeProvider theme={darkMode ? darkTheme : theme}\u003e\n      {/*...*/}\n    \u003c/ThemeProvider\u003e\n  );\n}\n```\n\n### Accessing the theme\n\nYou can get the current theme via the `useTheme` hook:\n\n```tsx\nimport { useTheme } from '../your-stitches-config';\n\nfunction Example() {\n  const theme = useTheme();\n\n  // Access theme tokens\n  // theme.colors|space|radii|etc.x\n\n  return (\n    \u003cView style={{ backgroundColor: theme.colors.background }}\u003e{/*...*/}\u003c/View\u003e\n  );\n}\n```\n\n### Typing token aliases\n\nStitches Native supports theme token aliases the same way as Stitches with a minor difference related to TypeScript support:\n\n```ts\ncreateStitches({\n  colors: {\n    black: '#000',\n    primary: '$black' as const,\n  },\n  space: {\n    1: 8,\n    2: 16,\n    3: 32,\n    max: '$3' as const,\n  },\n});\n```\n\nNote the usage of `as const` for token alias values. It is required if you want to have the correct type for the theme token value when accessing it via `useTheme` hook:\n\n```tsx\nimport { useTheme } from '../your-stitches-config';\n\nfunction Example() {\n  const theme = useTheme();\n\n  const x = theme.colors.primary; // \u003c-- type of `x` is `string`\n  const y = theme.space.max; // \u003c--- type of `y` is `number` even though the value in the theme is `'$3'`, yey 😎\n\n  return \u003cView style={{ backgroundColor: x, padding: y }}\u003e{/*...*/}\u003c/View\u003e;\n}\n```\n\n\u003e ⚠️ NOTE: without `as const` the type of the token will always be `string`!\n\nFor `string` type tokens, you don't necessarily need to use `as const` since the types align correctly without it, but you might want to do so anyway to be consistent.\n\n### Responsive styles with `media`\n\nResponsive styles are not very common in React Native applications since you usually have a clearly constrained device environment where the app is used. However, some times you might need to tweak a style for very small or large phones or build an app that needs to adapt to tablet devices. For these use cases Stitches Native has support for two kinds of responsive styles:\n\n1. Device types based media flags\n2. Device dimensions based media queries\n\n#### Device types based media flags\n\nSimple boolean flags in the `media` config can be used to distinguish between device types, eg. phone vs. tablet. You can utilize [`getDeviceType()`](https://github.com/react-native-device-info/react-native-device-info#getDeviceType) or [`isTablet()`](https://github.com/react-native-device-info/react-native-device-info#istablet) from [react-native-device-info](https://github.com/react-native-device-info/react-native-device-info) to get the device type.\n\n```js\nconst isTablet = DeviceInfo.isTablet();\n\nconst { ... } = createStitches({\n  media: {\n    phone: !isTablet,\n    tablet: isTablet,\n  },\n});\n```\n\nThen you can apply different prop values for variants of a styled components based on the device type:\n\n```tsx\nconst ButtonText = styled('Text', {\n  // base styles\n\n  variants: {\n    color: {\n      primary: {\n        color: '$primary',\n      },\n      secondary: {\n        color: '$secondary',\n      },\n    },\n  },\n});\n\n\u003cButtonText color={{ '@phone': 'primary', '@tablet': 'secondary' }}\u003e\n  Hello\n\u003c/ButtonText\u003e;\n```\n\n#### Device dimensions based media queries\n\nIt's also possible to have a more Web-like breakpoint system based on the dimensions of the device. The syntax for the queries follows the CSS [range queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries#syntax_improvements_in_level_4) syntax which means that there is no need to use `min-width` or `max-width`.\n\nExamples of supported range queries:\n\n- `(width \u003e 750px)`\n- `(width \u003e= 750px)`\n- `(width \u003c 1080px)`\n- `(width \u003c= 1080px)`\n- `(750px \u003e width \u003e= 1080px)`\n\n\u003e ⚠️ NOTE: Only width based media queries are currently supported.\n\n```js\nconst { ... } = createStitches({\n  media: {\n    md: '(width \u003e= 750px)',\n    lg: '(width \u003e= 1080px)',\n    xl: '(width \u003e= 1284px)',\n    xxl: '(width \u003e= 1536px)',\n  },\n});\n```\n\n\u003e ⚠️ NOTE: The order of the media query keys matters and the responsive styles are applied in the order determined by `Object.entries` method.\n\nUsing media queries works the same way as device type flags:\n\n```tsx\nconst ButtonText = styled('Text', {\n  // base styles\n\n  variants: {\n    color: {\n      primary: {\n        color: '$primary',\n      },\n      secondary: {\n        color: '$secondary',\n      },\n    },\n  },\n});\n\n\u003cButtonText\n  color={{\n    '@initial': 'primary',\n    '@md': 'secondary',\n    '@lg': 'tertiary',\n  }}\n\u003e\n  Hello\n\u003c/ButtonText\u003e;\n```\n\n### Additional props with `.attrs`\n\nIn React Native it is quite common that a component exposes props (other than `style`) that accept a style object - a good example of this is the `ScrollView` component that has `contentContainerStyle` prop. Using theme tokens with these kind of props can be accomplished with the `useTheme` hook:\n\n```tsx\nfunction Comp() {\n  const theme = useTheme();\n\n  return (\n    \u003cScrollView contentContainerStyle={{ padding: theme.space[2] }}\u003e\n      {/* ... */}\n    \u003c/ScrollView\u003e\n  );\n}\n\nconst ScrollView = styled('ScrollView', {\n  flex: 1,\n});\n```\n\nThis approach is fine but a bit convoluted since you have to import a hook just to access the theme tokens. There is a better way with the chainable `.attrs` method which can be used to attach additional props to a Stitches styled component (this method was popularized by [styled-components](https://styled-components.com/docs/api#attrs)).\n\n\u003e ⚠️ NOTE: this method does not exist in the original Web version of Stitches.\n\n```tsx\nfunction Example() {\n  return \u003cScrollView\u003e{/*...*/}\u003c/ScrollView\u003e;\n}\n\nconst ScrollView = styled('ScrollView', {\n  flex: 1,\n}).attrs((props) =\u003e ({\n  contentContainerStyle: {\n    padding: props.theme.space[2],\n  },\n}));\n```\n\nIt is also possible to access the variants of the component within `.attrs`:\n\n```tsx\nfunction Example() {\n  return \u003cScrollView spacious\u003e{/*...*/}\u003c/ScrollView\u003e;\n}\n\nconst ScrollView = styled('ScrollView', {\n  flex: 1,\n  variants: {\n    spacious: {\n      true: {\n        // some styles...\n      },\n      false: {\n        // some styles...\n      },\n    },\n  },\n}).attrs((props) =\u003e ({\n  contentContainerStyle: {\n    padding: props.theme.space[props.spacious ? 4 : 2],\n  },\n}));\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTemzasse%2Fstitches-native","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTemzasse%2Fstitches-native","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTemzasse%2Fstitches-native/lists"}