{"id":18681733,"url":"https://github.com/stowball/react-native-bem","last_synced_at":"2025-04-12T04:09:43.632Z","repository":{"id":57335734,"uuid":"81697391","full_name":"stowball/react-native-bem","owner":"stowball","description":"A tiny, fast, BEM-inspired method to styling React Native components","archived":false,"fork":false,"pushed_at":"2018-07-06T01:26:39.000Z","size":43,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-12T04:09:38.366Z","etag":null,"topics":["javascript","react-native"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/react-native-bem","language":"JavaScript","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/stowball.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}},"created_at":"2017-02-12T02:20:10.000Z","updated_at":"2025-02-06T04:47:23.000Z","dependencies_parsed_at":"2022-09-07T16:04:47.377Z","dependency_job_id":null,"html_url":"https://github.com/stowball/react-native-bem","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stowball%2Freact-native-bem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stowball%2Freact-native-bem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stowball%2Freact-native-bem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stowball%2Freact-native-bem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stowball","download_url":"https://codeload.github.com/stowball/react-native-bem/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248514222,"owners_count":21116903,"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":["javascript","react-native"],"created_at":"2024-11-07T10:09:10.561Z","updated_at":"2025-04-12T04:09:43.609Z","avatar_url":"https://github.com/stowball.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-native-bem\n\n**A tiny, fast, BEM-inspired method to styling React Native components.**\n\n[![npm version](https://badge.fury.io/js/react-native-bem.svg)](https://badge.fury.io/js/react-native-bem)\n[![Build Status](https://travis-ci.org/stowball/react-native-bem.svg?branch=master)](https://travis-ci.org/stowball/react-native-bem)\n\nThe [BEM](http://getbem.com) methodology and naming convention allows us to reduce the complexity of styling, and develop with speed and predictability. By following a similar approach to naming, modifiers and states (not to be confused with a component's internal state), we can create self-contained, easily styled components in any situation.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Features](#features)\n  - [Modifiers](#modifiers)\n  - [States](#states)\n- [Usage](#usage)\n  - [Creating Components](#creating-components)\n    - [Component Architecture](#component-architecture)\n  - [Styling Components](#styling-components)\n    - [styles.js](#stylesjs)\n    - [Common Usage](#common-usage)\n      - [Component Definition](#component-definition)\n      - [Styles Definition](#styles-definition)\n    - [Usage within a View](#usage-within-a-view)\n    - [Advanced Usage](#advanced-usage)\n      - [Manipulating Children](#manipulating-children)\n        - [Using a Component's Internal State](#using-a-components-internal-state)\n\n## Installation\n\n`npm install react-native-bem --save`\n\n## Features\n\nreact-native-bem allows us to style (the Block and Child) elements of a component based on a kebab-cased name, with optional modifier and state attributes.\n\nIt exports three functions:\n\n* `bem()`:  exported as the `default` function, which is used to apply styling to components.\n\n    Its signature is `bem (selector: string, props: Object, rules: Object)`. `selector` is the kebab-cased name of the component to style, `props` is the component's props and `rules` is the style object (from styles.js).\n\n* `renderBemChild()`: exported as a named function, this can be used in place of rendering `{props.children}` to pass a BEM selector to a specific child.\n\n    Its signature is `renderBemChild (props: Object, style: Array\u003cany\u003e, index: number = 0)`. `props` is the component's props, `style` is the result of calling `bem()` with a [BEM Mix](https://csswizardry.com/2017/02/code-smells-in-css-revisited/#bem-mixes) selector, and `index` is the index of the child element to style.\n\n* `renderBemChildren()`: exported as a named function, this can be used in place of rendering `{props.children}` to pass a BEM selector to *all* children.\n\n    Its signature is `renderBemChildren (props: Object, style: Array\u003cany\u003e)` and is identical to `renderBemChild()` but without `index`.\n\n*Note: As of v0.2.0, react-native-bem now utilizes `StyleSheet`s instead of plain JavaScript objects for improved performance*.\n\n### Modifiers\n\nAs with BEM in CSS, a modifier is a flag on a block or element, which is used to change an element's (or multiple elements') appearance.\n\nreact-native-bem supports two types of modifiers with the `M` prefix:\n\n1. Boolean: The prop `MalignCenter={true}` uses the `--align-center` style definition.\n2. String: The prop `Malign=\"right\"` uses the `--align-right` style definition.\n\n### States\n\nWhile not a part of BEM per se, [states](https://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/#stateful-namespaces-is-has-) are an elegant addition to signify that the piece of UI in question is currently styled a certain way because of specific condition.\n\nCommon stateful namespaces begin with `is` and `has`.\n\nreact-native-bem state props uses the `S` prefix, like so `SisDisabled={true}` which uses the `.is-disabled` style definition.\n\n## Usage\n\n### Creating Components\n\nUnless a component requires internal state or life-cycle hooks, a component should use the Stateless Functional Component (SFC) pattern to increase performance. It is trivial to convert an SFC to as class-based component later on where necessary.\n\n#### Component Architecture\n\nGenerally:\n\n* Each Component resides in a PascalCase directory under `components` that matches the BlockName.\n* `index.js`: contains the component.\n* `styles.js`: contains styles (if necessary).\n\nHowever, if a Block requires multiple child components:\n\n* `BlockName.js`: contains the outermost block component.\n* `BlockName__Element.js`: contains a child component.\n* `index.js`: imports `BlockName` and all `BlockName__Element`s, and exports them as named exports.\n* `styles.js`: contains styles for `BlockName` and all `BlockName__Element`s.\n\n### Styling Components\n\n#### styles.js\n\nThis file `export`s  a `default` [`StyleSheet`](https://facebook.github.io/react-native/docs/stylesheet.html) object which contains keys and style properties for each component.\n\nA component with child components, modifiers and states may look like this:\n\n```js\nimport { StyleSheet } from 'react-native';\n\nexport default StyleSheet.create({\n    'component-name': {\n        KEY: VALUE\n    },\n    'component-name--modifier': {\n        KEY: VALUE_WHEN_MODIFIED\n    },\n    'component-name.state': {\n        KEY: VALUE_WHEN_IN_THIS_STATE\n    },\n    'component-name__element': {\n        KEY: VALUE_OF_ELEMENT\n    },\n    'component-name--modifier component-name__element': {\n        KEY: VALUE_OF_ELEMENT_WHEN_MODIFIED\n    },\n    'component-name.state component-name__element': {\n        KEY: VALUE_OF_ELEMENT_WHEN_IN_THIS_STATE\n    }\n});\n```\n\nSimilar to using BEM in CSS, component styles are encapsulated within a namespace, and developers can clearly see the styles for all components, children and variations.\n\n#### Common Usage\n\n##### Component Definition\n\n`components/HelloWorld/index.js`\n\n```js\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport { View, Text } from 'react-native';\nimport bem from 'react-native-bem';\nimport styles from './styles';\n\nconst HelloWorld = (props) =\u003e {\n    const b = (selector) =\u003e bem(selector, props, styles);\n\n    return (\n        \u003cView style={b('hello-world')}\u003e\n            \u003cText style={b('hello-world__text')}\u003e\n                Hello, world\n            \u003c/Text\u003e\n        \u003c/View\u003e\n    );\n};\n\nHelloWorld.propTypes = {\n    MbooleanModifier: PropTypes.bool,\n    MstringModifier: PropTypes.string,\n    SaStateName: PropTypes.bool\n};\n\nexport default HelloWorld;\n```\n\n##### Styles Definition\n\n`components/HelloWorld/styles.js`\n\n```js\nimport { StyleSheet } from 'react-native';\n\nexport default StyleSheet.create({\n    'hello-world': {\n        backgroundColor: '#000',\n        marginBottom: 5,\n        padding: 5\n    },\n    'hello-world--boolean-modifier': {\n        borderColor: '#f00',\n        borderWidth: 4\n    },\n    'hello-world--string-modifier-foo': {\n        padding: 20\n    },\n    'hello-world.a-state-name': {\n        opacity: 0.5\n    },\n    'hello-world__text': {\n        color: '#fff',\n        fontSize: 20\n    },\n    'hello-world.a-state-name hello-world__text': {\n        color: '#ff0'\n    }\n});\n```\n\n#### Usage within a View\n\n`View.js`\n\n```js\nimport HelloWorld from './components/HelloWorld';\n\n…\n\nrender() {\n    return (\n        \u003cHelloWorld /\u003e\n        \u003cHelloWorld MbooleanModifier={true} /\u003e\n        \u003cHelloWorld MstringModifier=\"foo\" /\u003e\n        \u003cHelloWorld SaStateName={true} /\u003e\n        \u003cHelloWorld MbooleanModifier={true} MstringModifier=\"foo\" SaStateName={true} /\u003e\n    );\n}\n```\n\nwhich results in:\n\n\u003cimg src=\"https://s27.postimg.cc/qn6dilyr7/react-native-bem-1.png\" width=\"300\" alt=\"Demonstrating the Hello World component with all the modifiers and states applied\" /\u003e\n\nSo, you can see that with adding and removing props, either at run-time or by default, you will be able to quickly adapt your components' appearance to reflect the current state of the application.\n\n#### Advanced Usage\n\n##### Manipulating Children\n\nThere may be times where you wish to pass in child components from within your view, like so:\n\n```js\nrender() {\n    return (\n        \u003cHelloWorld\u003e\n            \u003cHelloWorld__Text /\u003e\n        \u003c/HelloWorld\u003e\n        \u003cHelloWorld MbooleanModifier={true}\u003e\n            \u003cHelloWorld__Text /\u003e\n        \u003c/HelloWorld\u003e\n        \u003cHelloWorld MstringModifier=\"foo\"\u003e\n            \u003cHelloWorld__Text /\u003e\n        \u003c/HelloWorld\u003e\n        \u003cHelloWorld SaStateName={true}\u003e\n            \u003cHelloWorld__Text /\u003e\n        \u003c/HelloWorld\u003e\n        \u003cHelloWorld MbooleanModifier={true} MstringModifier=\"foo\" SaStateName={true}\u003e\n            \u003cHelloWorld__Text /\u003e\n        \u003c/HelloWorld\u003e\n    );\n}\n```\n\nOut of the box, the children wouldn't be affected by parent modifier and state props (meaning the text color would always be white in the above example). however, by changing the `HelloWorld` component to accept children enhanced with BEM like so:\n\n```js\nimport bem, { renderBemChild } from 'react-native-bem';\n\nconst HelloWorld = (props) =\u003e {\n    const b = (selector) =\u003e bem(selector, props, styles);\n\n    return (\n        \u003cView style={b('hello-world')}\u003e\n            {renderBemChild(props)}\n        \u003c/View\u003e\n    );\n};\n```\n\nwhere `HelloWorld__Text` is:\n\n```js\nimport React from 'react';\nimport { Text } from 'react-native';\nimport bem from 'react-native-bem';\nimport styles from './styles';\n\nconst HelloWorld__Text = (props) =\u003e {\n    const b = (selector) =\u003e bem(selector, props, styles);\n\n    return (\n        \u003cText style={b('hello-world__text')}\u003e\n            Hello, world\n        \u003c/Text\u003e\n    );\n};\n\nexport default HelloWorld__Text;\n```\n\nwe get the exact same output as before, just with the added flexibility of being able to control which child components are rendered from within the view.\n\nAs mentioned earlier, `renderBemChild()` also accepts a second parameter of a styles object (like those returned from a `bem()` selector) and an `index`.\n\nThis allows us to render children with additional styles applied, which can be useful when a component is consumed by another (known as a BEM Mix), and its appearance needs to change to reflect that.\n\nIf we update our existing files to this:\n\n`styles.js`\n\n```js\nimport { StyleSheet } from 'react-native';\n\nexport default StyleSheet.create({\n    … existing styles\n    'bem-mix__text': {\n        color: '#0ff'\n    }\n});\n```\n\n`HelloWorld.js`\n\n```js\nconst HelloWorld = (props) =\u003e {\n    const b = (selector) =\u003e bem(selector, props, styles);\n\n    return (\n        \u003cView style={b('hello-world')}\u003e\n            {renderBemChild(props, b('bem-mix__text'))}\n        \u003c/View\u003e\n    );\n};\n```\n\nWe can see that the additional styles were applied to the `HelloWorld__Text` components, turning them cyan.\n\n\u003cimg src=\"https://s14.postimg.cc/w3alwgoox/react-native-bem-2.png\" width=\"300\" alt=\"Demonstrating the Hello World__Text component has inherited styles from the BEM mix\" /\u003e\n\n###### Using a Component's Internal State\n\nSome components, such as a `\u003cTextInput /\u003e`, need to be styled differently based on an internal state, like when it has focus. Instead of cumbersomely alerting parent components to whether it's focused or not and changing a state prop in the view, we can merge in the component's state to `bem()` at `render()` time.\n\nWith the following component:\n\n`components/TextBox/index.js`\n\n```js\nimport React, { Component } from 'react';\nimport { TextInput } from 'react-native';\nimport bem from 'react-native-bem';\nimport styles from './styles';\n\nclass TextBox extends Component {\n    constructor () {\n        super();\n\n        this.state = {\n            SisFocused: false\n        };\n    }\n\n    _onBlur = () =\u003e {\n        this.setState({\n            SisFocused: false\n        });\n    }\n\n    _onFocus = () =\u003e {\n        this.setState({\n            SisFocused: true\n        });\n    }\n\n    b = (selector) =\u003e bem(selector, { ...this.props, ...this.state }, styles)\n\n    render () {\n        return (\n            \u003cTextInput\n                {...this.props}\n                style={this.b('text-box')}\n                onBlur={this._onBlur}\n                onFocus={this._onFocus}\n            /\u003e\n        );\n    }\n}\n\nexport default TextBox;\n```\n\nand its related `styles.js`\n\n```js\nimport { StyleSheet } from 'react-native';\n\nexport default StyleSheet.create({\n    'text-box': {\n        backgroundColor: '#fff',\n        borderColor: '#000',\n        borderWidth: 2,\n        color: '#333',\n        fontSize: 14,\n        height: 40,\n        paddingHorizontal: 10,\n        paddingVertical: 0\n    },\n    'text-box.is-focused': {\n        borderColor: '#00f'\n    }\n});\n```\n\nBecause the `TextBox` component's `b()` helper merges the component's props with its internal state (which has a correctly named `SisFocused` property), it apply styles for when the `TextInput` is focused!\n\n\u003cimg src=\"https://s24.postimg.cc/lr1je8bz9/react-native-bem-3.gif\" width=\"400\" alt=\"Using BEM with internal state to set a TextInput's focus style\" /\u003e\n\n---\n\nCopyright (c) 2018 [Matt Stow](http://mattstow.com)  \nLicensed under the MIT license *(see [LICENSE](https://github.com/stowball/react-native-bem/blob/master/LICENSE) for details)*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstowball%2Freact-native-bem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstowball%2Freact-native-bem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstowball%2Freact-native-bem/lists"}