{"id":16528188,"url":"https://github.com/ilyalesik/react-overrides","last_synced_at":"2025-03-16T19:31:25.017Z","repository":{"id":33883401,"uuid":"163287033","full_name":"ilyalesik/react-overrides","owner":"ilyalesik","description":"Pass props to internal elements of React component","archived":false,"fork":false,"pushed_at":"2023-01-03T16:22:25.000Z","size":925,"stargazers_count":28,"open_issues_count":23,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-20T14:32:37.801Z","etag":null,"topics":["react"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ilyalesik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-27T11:33:44.000Z","updated_at":"2023-01-11T09:43:22.000Z","dependencies_parsed_at":"2023-01-15T03:08:50.841Z","dependency_job_id":null,"html_url":"https://github.com/ilyalesik/react-overrides","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilyalesik%2Freact-overrides","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilyalesik%2Freact-overrides/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilyalesik%2Freact-overrides/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilyalesik%2Freact-overrides/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ilyalesik","download_url":"https://codeload.github.com/ilyalesik/react-overrides/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221667252,"owners_count":16860580,"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":["react"],"created_at":"2024-10-11T17:38:35.325Z","updated_at":"2024-10-27T11:09:28.680Z","avatar_url":"https://github.com/ilyalesik.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-overrides\n\n[![Build Status](https://travis-ci.org/ilyalesik/react-overrides.svg?branch=master)](https://travis-ci.org/ilyalesik/react-overrides)\n[![npm version](https://img.shields.io/npm/v/react-overrides.svg)](https://www.npmjs.com/package/react-overrides)\n[![npm downloads](https://img.shields.io/npm/dt/react-overrides.svg)](https://www.npmjs.com/package/react-overrides)\n\nLet's create `CommonButton` component with `react-overrides`:\n```javascript\nimport o from \"react-overrides\";\n\nexport const CommonButton = props =\u003e (\n    \u003cContainer {...o} onClick={props.onClick}\u003e\n        \u003cText {...o}\u003e{props.children}\u003c/Text\u003e\n    \u003c/Container\u003e\n);\n```\n\nNext, we can pass props to internal elements of `CommonButton` by passing `overrides` prop:\n```javascript\nexport const LinkButton = props =\u003e (\n  \u003cCommonButton\n    {...props}\n    overrides={{\n      Container: { // 'Container' element of CommonButton\n        props: {\n          as: \"a\", // say the component to display itself as \u003ca\u003e tag. Typical for CSS-in-JS solutions.\n          href: props.href // add href attribute to element\n        }\n      }\n    }}\n  /\u003e\n);\n```\nSo we extend the `CommonButton` by creating a `LinkButton` that has *link* behavior.\n\nTry at CodeSandbox:\n\n[![Edit react-overrides](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/n8m65940l)\n\n\nIt is also possible to replace the entire component:\n```javascript\nexport const LinkButton = props =\u003e (\n  \u003cCommonButton\n    {...props}\n    overrides={{\n      Text: {\n          component: BigText\n      }\n    }}\n  /\u003e\n);\n```\n\n\u003ca href=\"https://lessmess.agency/?utm_source=react-overrides\"\u003e\n  \u003cimg src=\"https://lessmess.agency/badges/sponsored_by_lessmess.svg\"\n       alt=\"Sponsored by Lessmess\" width=\"236\" height=\"54\"\u003e\n\u003c/a\u003e\n\n\n## Motivation\n\nThere is a need for pass props directly to elements, or replace his component. \nHere's some examples of when you need it:\n* You create UI library, and want to provide wide customization abilities for components. [Base UI](https://baseui.design/) library used this approach.\n* You need *unified* way to pass any props (for example, ARIA attributes) to elements of components. \n* Your components can have many internal elements and it can be inconvenient to add a prop to component every time you just need to forward the prop to an internal element.\n\n## Installation\n\nInstall core package and babel plugin with yarn:\n\n```\nyarn add react-overrides\nyarn add babel-plugin-react-overrides --dev\n```\n\nOr with npm:\n\n```\nnpm i react-overrides --save\nnpm i babel-plugin-react-overrides --save-dev\n```\n\nFurther, add `react-overrides` to your `.babelrc` configuration:\n```json\n{\n  \"plugins\": [\"babel-plugin-react-overrides\"]\n}\n```\n\n## Usage\n\nCreate extendable component by passing the default export \nfrom `react-overrides` package to the component to be extended. \n\n*Example*:\n\n```javascript\nimport React, {useState} from \"react\";\nimport o from \"react-overrides\";\nimport {Container, Value, OptionsContainer, Option} from \"...\";\n\nexport const Select = (props) =\u003e {\n    const {opened, setOpened} = useState(false);\n    \n    return \u003cContainer {...o} onClick={() =\u003e setOpened(!opened)}\u003e\n        \u003cValue {...o}\u003e{props.currentValue}\u003c/Value\u003e\n        {opened \u0026\u0026 \u003cOptionsContainer {...o}\u003e\n            {props.values.map(({label, id}) =\u003e (\n                \u003cOption {...o} onClick={() =\u003e props.onSelect(id)} key={id}\u003e{label}\u003c/Option\u003e\n            ))}\n        \u003c/OptionsContainer\u003e}\n    \u003c/Container\u003e\n};\n```\n\nExtend with component through passing props of internal component:\n```javascript\nimport React from \"react\";\nimport {Select} from \"./Select\"\n\nconst BigOptionSelect = (props) =\u003e {\n    return \u003cSelect {...props} overrides={{\n        Option: {\n            props: {\n                className: \"big-option-select__option\",\n                \"aria-role\": \"button\"\n            }\n        }\n    }} /\u003e\n}\n```\n\n#### Replace internal components\n\nYou can replace the internal component with a custom one:\n```javascript\nimport React from \"react\";\nimport {Select} from \"./Select\"\nimport {FancyGrid} from \"./fancy-grid\";\n\nconst FancyGridSelect = (props) =\u003e {\n    return \u003cSelect {...props} overrides={{\n        OptionsContainer: {\n            component: FancyGrid\n        }\n    }} /\u003e\n}\n```\n\n#### Access to individual props\n\n```javascript\nimport React from \"react\";\nimport o from \"react-overrides\";\nimport c from \"classnames\";\nimport \"./button.scss\";\n\nconst Button = props =\u003e {\n    const Container = (props) =\u003e \u003cbutton {...props) /\u003e;\n    const Text = (props) =\u003e \u003cspan {...props) /\u003e;\n    \n    return (\n        \u003cContainer {...o} className={c(\"button\", o.className)} onClick={props.onClick}\u003e\n            \u003cText className={c(\"button__text\", o.className)} /\u003e\n                {props.children}\n            \u003c/Text\u003e\n        \u003c/Input\u003e\n    );\n};\n```\n\n#### Flow support\nYou can use `ExtractOverrides` type props helper for infer overrides prop type from components types.\n```javascript\n// @flow\nimport * as React from \"react\";\nimport o, { type ExtractOverridesProps } from \"react-overrides\";\n\nconst Option = (props: { a: 1 | 2, b: string }) =\u003e {\n    return \u003cdiv\u003e{props.b + 2 * props.a}\u003c/div\u003e;\n};\n\nconst Container = (props: { children?: React.Node }) =\u003e {\n    return \u003cdiv\u003e{props.children}\u003c/div\u003e;\n};\n\nconst OverridableProps = {\n    Option,\n    Container\n};\ntype TOverridesProps = ExtractOverridesProps\u003ctypeof OverridableProps\u003e;\n\nconst Select = (props: { overrides: TOverridesProps }) =\u003e {\n    return (\n        \u003cContainer {...o}\u003e\n            {/* For access to individual prop used o().\u003cprop\u003e, o.\u003cprop\u003e throw Flow error */}\n            \u003cOption {...o} a={1} b={o().b || \"x\"} /\u003e\n        \u003c/Container\u003e\n    );\n};\n\nconst OverridedSelect = () =\u003e {\n    return (\n        \u003cSelect\n            overrides={{\n                Option: {\n                    props: {\n                        a: 1,\n                    }\n                }\n            }}\n        /\u003e\n    );\n};\n\n// throw flow error:\nconst OverridedSelectWrong = () =\u003e {\n    return (\n        \u003cSelect\n            overrides={{\n                Option: {\n                    props: {\n                        a: 3\n                    }\n                }\n            }}\n        /\u003e\n    );\n};\n```\n\n# Acknowledgements\nThis library inspired by article \n[Better Reusable React Components with the Overrides Pattern](https://medium.com/@dschnr/better-reusable-react-components-with-the-overrides-pattern-9eca2339f646).\n\nThanks [@ai](https://github.com/ai) for review the documentation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filyalesik%2Freact-overrides","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filyalesik%2Freact-overrides","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filyalesik%2Freact-overrides/lists"}