Library / SDK
jsartisan/react-native-magnus avatar
jsartisan/react-native-magnus

Magnus UI: a utility-first React Native component set with theming built in

A Utility-First React Native UI Framework 🚀🧩

1,216 stars81 forksTypeScriptMIT

At a glance

What is it?
Magnus UI is a React Native framework that takes a utility-first approach, where components are styled through props like fontSize and color rather than through style objects, with nineteen components, theme variants and TypeScript support. It suits a team that wants a consistent look across iOS, Android and web, and the version history raises a question about how much to trust it.
Who is it for?
Magnus UI fits a React Native project that wants one styled component set across mobile and web without maintaining a theme by hand, because the theme system, the variants and the TypeScript types come as one package. Skip it if you want an actively developed dependency, because the version history is confusing: the last push was on 2026-10-14 but the latest tagged release is 1.0.63 from 2022-09-22, and you should check that gap yourself before depending on it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Props for styling instead of style objects

Magnus UI is described as a Utility-First React Native UI Framework, and the tagline is Build UI in React Native, without the tears.

The utility-first label usually means a styling approach where you compose classes, as Tailwind does for the web. In React Native there are no CSS classes, so the mechanism has to be different, and here it is props. The example in the documentation is a text element with its typography and colour given as named values rather than as a style object:

jsx
<Text fontSize="md" color="pink500">

So `fontSize` takes a scale token such as `md`, and `color` takes a palette token such as `pink500`. Those names come from a scale and a palette, which means the theme defines the vocabulary and the component decides how to apply it.

That is the design decision with consequences. In a typical React Native codebase, every screen builds a StyleSheet and a value like `fontSize: 14` is written out in as many places as there are text elements, and the same colour appears in a dozen files. Here, `md` and `pink500` are shared vocabulary, so changing the scale in the theme changes every screen at once, and a designer and a developer are talking about the same names.

The feature list calls the API super simple, which is a low bar for a component library but the right bar for this one. The usage example is a named import and a component:

jsx
import { Button } from 'react-native-magnus';

<Button />;

There is no provider to wrap your app in and no context to configure, which is the main reason adoption is cheap if it works for you.

Twenty components, and the ones that are not there

The component list is worth reading as a scope statement, because nineteen components is a small catalogue and the omissions are as informative as the inclusions.

What is there: Div, Text, Button, Checkbox, Drawer, Icon, Input, Avatar, Image, Modal, Radio, Skeleton, Snackbar, Tag, Dropdown, Fab, Select, Tooltip and Overlay.

What is not there is the interesting part. There is no List, no FlatList wrapper, no ScrollView, no Pressable, no Switch, no DatePicker, no Tabs, no Accordion, no FlatList with an empty state, no navigation component, no form library.

So this is a set of leaf components, the ones you put inside a layout, rather than a complete UI kit. A screen that needs a tabbed interface or a form with validation still brings its own solution for that, and the value of Magnus UI is in the parts it does cover, the typography, the buttons, the inputs, the overlays and the feedback components.

Two components in the list tell you the level of ambition. Skeleton is a loading placeholder, which is the component most apps end up writing by hand and is a nice thing to have provided. Overlay is a low level primitive, which suggests the higher level pieces like Modal and Snackbar and Drawer are built on it rather than each reimplementing their own scrim and animation.

The two unusual ones are Drawer and Fab. A drawer is a navigation pattern and a floating action button is a material design pattern, so the library is not trying to be a strict implementation of either platform's design language, it is trying to be a consistent set of components that work everywhere.

Themes, variants, and the dependency list that is three packages long

The theming is the feature list's centre of gravity, with full theme support and custom theme variants as separate entries.

The dependency list is what makes that credible. The runtime dependencies are `color` at ^4.2.3, `deepmerge` at ^4.2.2 and `validate-color` at ^2.2.1. That is the entire runtime surface of a component library with nineteen components and a theming system, and reading it tells you how the theming works.

`color` is a colour manipulation library, which is what a theme engine needs in order to lighten, darken and mix palette entries without hardcoding a shade for every combination. `deepmerge` is how a custom theme merges with the default one, so a user who overrides three colours inherits the rest. And `validate-color` is the interesting one, because it is how a theme with a typo in a colour value fails loudly at configuration time rather than rendering an invisible or black element.

That last point is a real design decision. A theme system that silently accepts an invalid colour produces a bug that is hard to trace, since the component is fine, the theme is fine, and the value is wrong. Validating at the boundary turns it into a startup error.

The three dependencies also explain why the library is not enormous. A component library that ships a colour picker, a date picker and an icon set needs native modules, and native modules are where React Native libraries become painful to install. This one has none.

The type of a design system is also worth noting. The `types` field points at `lib/typescript/src/index.d.ts` and the package carries a `typescript` script running `tsc --noEmit`, and TypeScript support is in the feature list. For a utility-prop API, that is more than cosmetic, since the whole point is that `fontSize` accepts a token from a known set, and a type can enforce exactly that.

The build, the example app, and the version gap

The package layout is the standard react-native-builder-bob arrangement, and the scripts make that clear.

The `main` field points at `lib/commonjs/index.js`, `module` at `lib/module/index.js` and `types` at `lib/typescript/src/index.d.ts`, while the `react-native` and `source` fields point at `src/index.tsx`. The `prepare` script runs `bob build && husky install`, and the published `files` list is `src`, `lib`, `android`, `ios` and `react-native-magnus.podspec`.

The `android` and `ios` entries in the published files are worth a second look. A library with no native code of its own does not usually need platform directories, so their presence suggests either leftover scaffolding or a native dependency that is not visible in the runtime dependencies. Either way, it is the kind of thing to check when a component library turns out to need a pod install, since that is the point at which a dependency stops being drop in.

The `example/` directory is a full Expo app, with `App.js` and a separate `App.web.js`, an `app.json`, a `metro.config.js` and a `webpack.config.js`, plus its own `package.json` and `yarn.lock`. The separate web entry file and the webpack config are the concrete evidence for the Universal feature claim, since web support in React Native is not free and usually shows up as extra build configuration. There is also a `docs/` directory with its own package, and the `bootstrap` script runs `yarn example && yarn docs && yarn` to set all three up together.

The tooling is conventional and competently set up. Tests are jest with `@testing-library/react-native` at ^11.0.0, linting is eslint with the React Native community config, formatting is prettier through a `pretty-quick` pre-commit hook, commit messages are checked with commitlint and the conventional config, and releases are cut with `release-it` and `@release-it/conventional-changelog`.

And then there is the version history, which is the part to think about before you depend on this. The last push was on 2026-10-14 and the repository is not archived, so somebody is committing. The recent releases are v1.0.61 and v1.0.62 on 2021-03-04, and v1.0.63 on 2022-09-22, and the package manifest carries version 1.0.63. So the most recent tagged release is more than three years old, while the working tree is being touched. Whether that means unreleased fixes are sitting on master, or that the commits are housekeeping, is not something the repository states, and it is worth checking before you pin a version.

Where a utility-first component set stops being the answer

There are three cases where this kind of library is the wrong choice, and they are worth being concrete about.

The first is a design that needs to match one platform exactly. If the product is meant to look like a native iOS app to the point where a reviewer would not notice it was React Native, then a cross platform component set with its own scale and palette is a liability. Every component you replace with a platform one introduces a visual difference you then have to reconcile, and the palette tokens in a shared theme are by definition a compromise between the platforms. The Universal claim is a feature when you want one look everywhere and a problem when you want to look native.

The second is a team that has already invested in a design system of its own. If the tokens and the components already exist, this library is a second source of truth, and adding it is a migration rather than a shortcut.

The third is the catalogue size, mentioned earlier. Nineteen components leaves the larger part of a typical screen to other libraries, so the dependency count does not go down the way a single framework might suggest. The upside of a small dependency surface is that you can add more later without much cost, but the honest version is that this is a partial set, not a replacement for a full kit.

There is also a question about the version gap that deserves more than a footnote. A component library whose last release was in 2022 and whose source tree has been touched since then is in an unusual state. The npm package people will install is 1.0.63, and that is what the documentation describes, but it is a build from 2022. If the recent commits are substantive, they are not in the published package unless a new release is cut, and if they are not substantive, the activity is not evidence of maintenance. The only way to tell is to look at the commits and the CHANGELOG, which is the first thing to do before making a decision.

The alternative approach is the platform components with a StyleSheet and your own theme object, which is more code and gives you full control. The difference in approach is that this library provides the mapping from tokens to styles and the catalogue to apply them to, while the hand rolled version provides neither and costs you the tokens as well. For a small app with a dozen screens, the hand rolled version is often less work. For an app with a design system and a team that needs to talk about spacing in the same words, the token approach pays for itself.

The licence is MIT, and the project is described as open to pull requests.

Editorial conclusion

Magnus UI fits a React Native project that wants one styled component set across mobile and web without maintaining a theme by hand, because the theme system, the variants and the TypeScript types come as one package. Skip it if you want an actively developed dependency, because the version history is confusing: the last push was on 2026-10-14 but the latest tagged release is 1.0.63 from 2022-09-22, and you should check that gap yourself before depending on it. Before you commit, look at the component list against what your app actually needs, since nineteen components is a small catalogue, and confirm the utility props cover the styling decisions you would otherwise make in a StyleSheet.

Frequently asked questions

How do I install Magnus UI in a React Native project?

Run `npm install react-native-magnus` or `yarn add react-native-magnus`. It works with Expo and with vanilla React Native, and the runtime dependencies are just color, deepmerge and validate-color.

What does utility-first mean in Magnus UI?

Components are styled through props like `fontSize="md"` and `color="pink500"` rather than through style objects, so the theme defines a scale and a palette of named values that every screen shares.

Which components does Magnus UI provide?

Div, Text, Button, Checkbox, Drawer, Icon, Input, Avatar, Image, Modal, Radio, Skeleton, Snackbar, Tag, Dropdown, Fab, Select, Tooltip and Overlay, with documentation for each.

Is Magnus UI still maintained?

The repository is not archived and the last push was on 2026-10-14, but the latest tagged release is v1.0.63 from 2022-09-22, so check the commit history and the changelog to see what has changed since that release.

Does Magnus UI support theming and TypeScript?

Yes. The feature list includes full theme support and custom theme variants, and the package ships TypeScript declarations with a `typescript` script running `tsc --noEmit`.

Official sources

  1. jsartisan/react-native-magnus on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jsartisan-react-native-magnus.svg)](https://hysenlabs.com/projects/jsartisan-react-native-magnus)

Was this useful?