{"id":18003723,"url":"https://github.com/matvp91/stylemug","last_synced_at":"2025-03-26T09:32:40.556Z","repository":{"id":40768484,"uuid":"263692744","full_name":"matvp91/stylemug","owner":"matvp91","description":"CSS in JS with support for static / atomic CSS extraction.","archived":false,"fork":false,"pushed_at":"2023-01-06T05:49:02.000Z","size":3839,"stargazers_count":54,"open_issues_count":28,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-13T17:15:33.157Z","etag":null,"topics":["atomic-css","css","javascript","react"],"latest_commit_sha":null,"homepage":null,"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/matvp91.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-13T17:02:55.000Z","updated_at":"2023-08-18T09:02:36.000Z","dependencies_parsed_at":"2023-02-05T11:15:34.022Z","dependency_job_id":null,"html_url":"https://github.com/matvp91/stylemug","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matvp91%2Fstylemug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matvp91%2Fstylemug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matvp91%2Fstylemug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matvp91%2Fstylemug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matvp91","download_url":"https://codeload.github.com/matvp91/stylemug/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222137442,"owners_count":16937411,"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":["atomic-css","css","javascript","react"],"created_at":"2024-10-30T00:10:38.599Z","updated_at":"2024-10-30T00:10:39.155Z","avatar_url":"https://github.com/matvp91.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stylemug ⚛️\n\nA fast css-in-js library that extracts atomic CSS rules to a .css file.\n\n- [Getting started](#getting-started)\n- [Features](#features)\n- [How it works](#how-it-works)\n\nWe try to limit the functionality of this package in order to do the following key features really well:\n\n- It generates **Atomic CSS** from the static stylesheets defined in your component.\n- The compiled rules are **extracted to a .css file**.\n- The stylesheet code in your bundle is replaced (**no CSS in your JS**) with a hash map for classnames lookup at runtime.\n\nHeavily inspired by Facebook's internal `stylex` and the \"[Building the new Facebook](https://developers.facebook.com/videos/2019/building-the-new-facebookcom-with-react-graphql-and-relay/)\" presentation, at ~28:00.\n\n## Getting started\n\nAdd the package as a dependency.\n\n```\nnpm i stylemug\n```\n\nThe example below uses `stylemug.create` to define your stylesheet and will provide a `styles` function used to resolve your class names.\n\n```javascript\nimport React from 'react';\nimport stylemug from 'stylemug';\n\nconst styles = stylemug.create({\n  default: {\n    backgroundColor: 'red',\n    color: 'black',\n  },\n  large: {\n    fontSize: '32px',\n  },\n});\n\nfunction App() {\n  const [large, toggleLarge] = useToggle(true);\n\n  return (\n    \u003cdiv className={styles('default', large \u0026\u0026 'large')}\u003e\n      \u003cbutton onClick={toggleLarge}\u003eToggle me\u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nAdd `stylemug/compiler`'s babel and webpack plugin in your `webpack.config.js` config file.\n\n```javascript\nconst stylemugCompiler = require('stylemug/compiler');\n\nmodule.exports = {\n  ...\n  module: {\n    rules: [\n      {\n        test: /\\.m?js$/,\n        exclude: /(node_modules|bower_components)/,\n        use: {\n          loader: 'babel-loader',\n          options: {\n            // The babel plugin will collect each schematic from `stylemug.create`\n            // and rewrite the schema to a lookup table.\n            plugins: [stylemugCompiler.babel],\n          },\n        },\n      },\n    ],\n  },\n  plugins: [\n    new stylemugCompiler.webpack({\n      // The CSS rules extracted by babel will be written to\n      // this file.\n      name: 'bundle.css',\n    }),\n  ],\n};\n```\n\n## Features\n\n### Generic rules\n\nA style rule can be shared from one file to another, aslong as the stylesheet itself remains static.\n\n```javascript\n// foo.js\nexport default stylemug.create({\n  container: {\n    width: '720px',\n  },\n});\n\n// bar.js\nimport foo from './foo';\n\nconst styles = stylemug.create({\n  default: {\n    color: 'green',\n  },\n});\n\nconst classNames = styles('default', foo.container);\n```\n\n### Pseudo classes \u0026 media queries\n\n```javascript\nconst styles = stylemug.create({\n  button: {\n    ...\n\n    // pseudo classes\n    '\u0026:hover': {\n      color: 'green',\n    },\n\n    // media queries\n    '@media (min-width: 720px)': {\n      width: '100px',\n    },\n  },\n});\n```\n\n## How it works\n\nWhen `webpack` bundles your code, `babel-loader` is used to parse your JS files through Babel and perform a variety of transformations (one of the most common ones is converting ES6 to ES5). One of these transformations is part of the Babel plugin in `stylemug/compiler`.\n\nThe plugin looks for the import statement:\n\n```javascript\nimport stylemug from 'stylemug';\n```\n\nand searches for occurances of `stylemug.create`.\n\n```javascript\nconst styles = stylemug.create({\n  className1: {\n    color: 'red',\n    backgroundColor: 'blue',\n  },\n  className2: {\n    color: 'yellow';\n  },\n});\n```\n\nAfterwards, it compiles the stylesheet by generating a classname for each rule. This concept is called atomic CSS, offering single-purpose units of style, but applied via classes.\n\n```css\n.c8938 { color: 'red'; }\n.e79cd { color: 'blue'; }\n.aaddb { color: 'yellow'; }\n```\n\nFinally, the stylesheet is replaced with a hash map in your code. At this point, the stylesheet is gone from your JS bundle.\n\n```javascript\nconst styles = stylemug.create({\n  className1: {\n    color: 'c8938',\n    backgroundColor: 'e79cd',\n  },\n  className2: {\n    color: 'aaddb',\n  },\n});\n```\n\nInternally, the `styles` function uses `Object.assign` to avoid duplication of rules.\n\n```javascript\n// 1.\nconst classes = styles('className1', 'className2');\n\n// 2.\nconst classes = Object.assign(\n  {},\n  {\n    color: 'c8938',\n    backgroundColor: 'e79cd',\n  },\n  {\n    color: 'aaddb',\n  }\n);\n\n// 3.\nconst classes = ['e79cd', 'aaddb'];\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatvp91%2Fstylemug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatvp91%2Fstylemug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatvp91%2Fstylemug/lists"}