{"id":21404709,"url":"https://github.com/eightyfive/react-native-themesheet","last_synced_at":"2026-01-28T15:05:00.468Z","repository":{"id":41526474,"uuid":"509787666","full_name":"eightyfive/react-native-themesheet","owner":"eightyfive","description":"Lightweight alternative to @shopify/restyle","archived":false,"fork":false,"pushed_at":"2024-11-14T12:48:15.000Z","size":173,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-13T23:36:48.365Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/eightyfive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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,"zenodo":null}},"created_at":"2022-07-02T15:11:48.000Z","updated_at":"2024-11-14T12:48:20.000Z","dependencies_parsed_at":"2025-07-13T23:30:58.849Z","dependency_job_id":"9abfea3c-59e8-4912-a370-60eaa90f12a6","html_url":"https://github.com/eightyfive/react-native-themesheet","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/eightyfive/react-native-themesheet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eightyfive%2Freact-native-themesheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eightyfive%2Freact-native-themesheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eightyfive%2Freact-native-themesheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eightyfive%2Freact-native-themesheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eightyfive","download_url":"https://codeload.github.com/eightyfive/react-native-themesheet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eightyfive%2Freact-native-themesheet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28846103,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T13:02:32.985Z","status":"ssl_error","status_checked_at":"2026-01-28T13:02:04.945Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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-11-22T16:17:40.251Z","updated_at":"2026-01-28T15:05:00.447Z","avatar_url":"https://github.com/eightyfive.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `react-native-themesheet`\n\nLightweight alternative to [@shopify/restyle](https://github.com/Shopify/restyle).\n\n## Install\n\n```bash\nyarn add react-native-themesheet\n```\n\n## Usage\n\n### Create theme\n\nA Theme consist of a set of `colors` \u0026 a set of `sizes`.\n\n```ts\n// src/views/theme.ts\n\nexport const { createBox, createStyles, createVariants } = createTheme(\n  {\n    primary: 'black',\n    accent: 'white',\n    //\n    onPrimary: 'white',\n    onAccent: 'black',\n  },\n  {\n    s: 4,\n    m: 8,\n    l: 16,\n    roundness: 10,\n  },\n);\n```\n\n### Create styles\n\n`createStyles` allows you to create normal `react-native` styles with spacing shorthands \u0026 Theme color mapping.\n\n```ts\n// src/views/home.tsx\n\nimport { createStyles } from './theme';\n\nconst $ = createStyles({\n  container: {\n    backgroundColor: 'primary', // \u003c-- color name\n    borderColor: 'accent', // \u003c-- color name\n    borderRadius: 'roundness', // \u003c-- size name\n    px: 's', // \u003c-- `paddingHorizontal` shorthand + size name\n    my: 'm', // \u003c-- `marginVertical` shorthand + size name\n    marginLeft: 30, // \u003c-- no shorthand, normal `number` value\n    col: 5, // \u003c-- Flex positioning (see API)\n  },\n  text: {\n    color: 'onPrimary', // \u003c-- color name\n    pl: 'l', // \u003c-- `paddingLeft` shorthand + size name\n  },\n});\n\nexport function Home(props) {\n  return (\n    \u003cView style={$.container}\u003e\n      \u003cText style={$.text}\u003eHello !\u003c/Text\u003e\n    \u003c/View\u003e\n  );\n}\n```\n\n### Create variants\n\n`createVariants` allows you to easily compose a component \"variant\" style.\n\n```ts\n// src/views/lib/button.tsx\n\nimport { createVariants } from '../theme';\n\nconst $ = createVariants(\n  // defaults\n  {\n    borderRadius: 'roundness',\n    borderWidth: 1,\n    p: 'm',\n  },\n  // variants\n  {\n    primary: {\n      backgroundColor: 'onPrimary',\n      borderColor: 'onPrimary',\n    },\n    accent: {\n      backgroundColor: 'accent',\n      borderColor: 'accent',\n    },\n    secondary: {\n      backgroundColor: 'transparent',\n      borderColor: 'onPrimary',\n    },\n  },\n  // modifiers\n  {\n    disabled: {\n      opacity: 0.75,\n    },\n    compact: {\n      p: 's',\n    },\n  },\n);\n\ntype Props = {\n  children: string;\n  compact?: boolean;\n  disabled?: boolean;\n  loading?: boolean;\n  variant?: 'primary' | 'accent' | 'secondary';\n};\n\nexport function Button({\n  children,\n  compact = false,\n  disabled = false,\n  loading = false,\n  variant = 'primary',\n}: Props) {\n  //\n  // ¡¡ `$` is function here !! (see API)\n  const styles = $(variant, {\n    disabled: disabled || loading,\n    compact,\n  });\n\n  // styles = [\n  //   \u003cdefaults style\u003e,\n  //   \u003cprimary style\u003e | \u003caccent style\u003e | \u003csecondary style\u003e,\n  //   (disabled || loading) \u0026\u0026 \u003cdisabled style\u003e,\n  //   compact \u0026\u0026 \u003ccompact style\u003e\n  // ]\n\n  return (\n    \u003cPressable style={styles}\u003e\n      \u003cText\u003e{children}\u003c/Text\u003e\n    \u003c/Pressable\u003e\n  );\n}\n```\n\n### Create boxes\n\n`createBox` enhance a component with spacing shorthand properties.\n\n```ts\n// src/views/lib.ts\n\nimport { Text as RNText, TextProps, View, ViewProps } from 'react-native';\n\nimport { createBox } from './theme';\n\nexport const Col = createBox\u003cViewProps\u003e(View);\n\nexport const Text = createBox\u003cTextProps\u003e(RNText);\n\nexport const Title = createBox\u003cTextProps\u003e((props: TextProps) =\u003e (\n  \u003cRNText {...props} style={{ fontSize: 22 }}\u003e\u003c/RNText\u003e\n));\n```\n\nLater in app:\n\n```ts\n// src/views/header.tsx\n\nimport { Col, Text, Title } from './lib';\n\ntype Props = {\n  title: string;\n  subtitle?: string;\n};\n\nexport function Header({ title, subtitle }: Props) {\n  return (\n    \u003cCol py=\"m\"\u003e\n      \u003cTitle px=\"m\"\u003e{title}\u003c/Title\u003e\n      {subtitle ? (\n        \u003cText px=\"l\" mt=\"s\"\u003e\n          {subtitle}\n        \u003c/Text\u003e\n      ) : null}\n    \u003c/Col\u003e\n  );\n}\n```\n\n## API\n\n### `createTheme(colors, sizes)`\n\n```ts\ntype Colors = Record\u003cstring, ColorValue\u003e\n\ntype Sizes = Record\u003cstring, number\u003e\n\ncreateTheme\u003cC extends Colors, S extends Sizes\u003e(colors: C, sizes: S): {\n  colors,\n  sizes,\n  //\n  createBox,\n  createStyles,\n  createVariants\n}\n```\n\nThis is the only public API available. All utility functions are exported from it.\n\n```ts\n// src/views/theme.ts\n\nimport { createTheme } from 'react-native-themesheet';\n\nexport const { colors, createBox, createStyles, createVariants, sizes } =\n  createTheme(\n    {\n      primary: '#000',\n      accent: '#ffffff',\n    },\n    {\n      s: 4,\n      m: 8,\n    },\n  );\n```\n\n### `Theme.createBox(BaseComponent)`\n\n```ts\ncreateBox\u003cBaseComponentProps\u003e(BaseComponent: ComponentType\u003cany\u003e)\n```\n\nEnhance `BaseComponent` with spacing shorthand properties:\n\n| Shorthand | Property            |\n| --------- | ------------------- |\n| `m`       | `margin`            |\n| `mt`      | `marginTop`         |\n| `mr`      | `marginRight`       |\n| `mb`      | `marginBottom`      |\n| `ml`      | `marginLeft`        |\n| `my`      | `marginVertical`    |\n| `mx`      | `marginHorizontal`  |\n| `ms`      | `marginStart`       |\n| `me`      | `marginEnd`         |\n| `p`       | `padding`           |\n| `pt`      | `paddingTop`        |\n| `pr`      | `paddingRight`      |\n| `pb`      | `paddingBottom`     |\n| `pl`      | `paddingLeft`       |\n| `py`      | `paddingVertical`   |\n| `px`      | `paddingHorizontal` |\n| `ps`      | `paddingStart`      |\n| `pe`      | `paddingEnd`        |\n\n```ts\nimport { Text, TextProps, View, ViewProps } from 'react-native';\n\nimport { createBox } from './theme';\n\nconst Box = createBox\u003cViewProps\u003e(View);\n\nconst Title = createBox\u003cTextProps\u003e(Text);\n```\n\n### `Theme.createStyles(styles)`\n\n```ts\ncreateStyles(styles: Record\u003cstring, Style\u003e)\n```\n\nA `Style` accepts all normal `react-native` style properties as well as `FlexStyle` \u0026 `SpacingStyle` properties:\n\n```ts\ntype FlexStyle = {\n  col?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;\n  row?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;\n};\n\ntype SpacingStyle\u003cS extends Sizes\u003e = Partial\u003cRecord\u003cSpacingProp, keyof S\u003e\u003e;\n```\n\nThe following \"color\" properties will only accepts color names from the Theme:\n\n- `backgroundColor`\n- `borderColor`\n- `color`\n- `tintColor`\n\nFinally `borderRadius` accepts both a size name from the Theme, as well as a normal `number` value.\n\n```ts\nimport { createStyles } from './theme';\n\nconst $ = createStyles({\n  card: {\n    col: 5,\n    backgroundColor: 'primary',\n    borderRadius: 'roundness', // | 100\n    p: 'm',\n  },\n});\n```\n\n#### Note about `FlexStyle`\n\nA `FlexStyle` is a shorthand describing Flexbox properties.\n\nIt's based on the clever \"dial\" idea initially brought by [`react-native-row`](https://github.com/hyrwork/react-native-row).\n\nBasically you can think of a Flex container as a dial number pad:\n\n```\n┌─────────────┐\n│ 1    2    3 │\n│             │\n│ 4    5    6 │\n│             │\n│ 7    8    9 │\n└─────────────┘\n```\n\nAnd when creating styles using the `{ (col|row): [1-9] }` shorthand, it will generate the corresponding Flexbox style:\n\n```ts\nconst $ = createStyles({\n  colC: {\n    col: 5,\n  },\n  // $.colC = { flexDirection: 'column', justifyContent: 'center', alignItems: 'center' }\n\n  rowBR: {\n    row: 9,\n  },\n  // $.rowL = { flexDirection: 'row', justifyContent: 'flex-end', alignItems: 'flex-end' }\n\n  rowLR: {\n    row: 4,\n    justifyContent: 'space-between',\n  },\n  // $.rowLR = { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }\n\n  colLRB: {\n    col: 8,\n    alignItems: 'stretch',\n  },\n  // $.colLRB = { flexDirection: 'column', justifyContent: 'flex-end', alignItems: 'stretch' }\n});\n```\n\nFor an even more semantic way to express Flexbox positioning, check out [`react-native-col`](https://github.com/eightyfive/react-native-col).\n\n### `Theme.createVariants(defaults, variants, modifiers)`\n\n```ts\ncreateVariants(defaults: Style, variants: Record\u003cstring, Style\u003e, modifiers: Record\u003cstring, Style\u003e)\n```\n\n`createVariants` returns a function helper to easily pick a component \"variant\" style:\n\n```ts\nimport { createVariants } from './theme';\n\nconst $ = createVariants(\n  // defaults\n  {\n    borderWidth: 1,\n  },\n  // variants\n  {\n    primary: {\n      borderColor: 'primary',\n    },\n    accent: {\n      borderColor: 'accent',\n    },\n  },\n  // modifiers\n  {\n    disabled: {\n      opacity: 0.5,\n    },\n  },\n);\n\n$('primary', { disabled: false }); // --\u003e [{ borderWidth: 1}, { borderColor: colors.primary }]\n\n$('accent', { disabled: true }); // --\u003e [{ borderWidth: 1}, { borderColor: colors.accent }, { opacity: 0.5 }]\n\n$('secondary', { disabled: true }); // TS error (variant not found)\n\n$('primary', { compact: true }); // TS error (modifier not found)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feightyfive%2Freact-native-themesheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feightyfive%2Freact-native-themesheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feightyfive%2Freact-native-themesheet/lists"}