{"id":13804910,"url":"https://github.com/master-co/styled","last_synced_at":"2025-04-09T16:20:17.173Z","repository":{"id":57751917,"uuid":"513185621","full_name":"master-co/styled","owner":"master-co","description":"Create reusable and extensible styled elements in one line","archived":false,"fork":false,"pushed_at":"2024-12-02T19:26:17.000Z","size":2074,"stargazers_count":37,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-01T09:29:22.260Z","etag":null,"topics":["component","css","element","react","styled"],"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/master-co.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","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}},"created_at":"2022-07-12T14:58:14.000Z","updated_at":"2024-12-02T19:24:37.000Z","dependencies_parsed_at":"2024-05-28T17:17:03.978Z","dependency_job_id":"9d67bdc8-7c60-43b6-b297-d9f2becf2dc7","html_url":"https://github.com/master-co/styled","commit_stats":{"total_commits":179,"total_committers":5,"mean_commits":35.8,"dds":"0.44692737430167595","last_synced_commit":"d9925d8aca08d9c475568a57cc40f4e8c38855d4"},"previous_names":["master-co/styled","master-co/style-element","master-co/style-element.react"],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/master-co%2Fstyled","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/master-co%2Fstyled/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/master-co%2Fstyled/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/master-co%2Fstyled/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/master-co","download_url":"https://codeload.github.com/master-co/styled/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065281,"owners_count":21041872,"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":["component","css","element","react","styled"],"created_at":"2024-08-04T01:00:55.305Z","updated_at":"2025-04-09T16:20:17.155Z","avatar_url":"https://github.com/master-co.png","language":"TypeScript","readme":"\u003cbr\u003e\n\u003cdiv align=\"center\"\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cpicture\u003e\n        \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://user-images.githubusercontent.com/33840671/205238939-3cf526f7-8d92-4fa0-8ca3-6c7e4c545f9c.svg\"\u003e\n        \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://user-images.githubusercontent.com/33840671/205238945-3295c4f5-a88a-4b58-bca9-770fe7bf894e.svg\"\u003e\n        \u003cimg alt=\"Master\" src=\"https://user-images.githubusercontent.com/33840671/205238945-3295c4f5-a88a-4b58-bca9-770fe7bf894e.svg\" width=\"100%\"\u003e\n    \u003c/picture\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003eCreate reusable and extensible styled elements in one line\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca aria-label=\"GitHub release (latest by date including pre-releases)\" href=\"https://github.com/master-co/styled/releases\"\u003e\n        \u003cpicture\u003e\n            \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://img.shields.io/github/v/release/master-co/styled?include_prereleases\u0026color=212022\u0026label=\u0026style=for-the-badge\u0026logo=github\u0026logoColor=fff\"\u003e\n            \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/github/v/release/master-co/styled?include_prereleases\u0026color=f6f7f8\u0026label=\u0026style=for-the-badge\u0026logo=github\u0026logoColor=%23000\"\u003e\n            \u003cimg alt=\"NPM Version\" src=\"https://img.shields.io/github/v/release/master-co/styled?include_prereleases\u0026color=f6f7f8\u0026label=\u0026style=for-the-badge\u0026logo=github\"\u003e\n        \u003c/picture\u003e\n    \u003c/a\u003e\n    \u003ca aria-label=\"NPM Package\" href=\"https://www.npmjs.com/package/class-variant\"\u003e\n        \u003cpicture\u003e\n            \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://img.shields.io/npm/dm/class-variant?color=212022\u0026label=%20\u0026logo=npm\u0026style=for-the-badge\"\u003e\n            \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/npm/dm/class-variant?color=f6f7f8\u0026label=%20\u0026logo=npm\u0026style=for-the-badge\"\u003e\n            \u003cimg alt=\"NPM package ( download / month )\" src=\"https://img.shields.io/npm/dm/class-variant?color=f6f7f8\u0026label=%20\u0026logo=npm\u0026style=for-the-badge\"\u003e\n        \u003c/picture\u003e\n    \u003c/a\u003e\n    \u003ca aria-label=\"Discord Community\" href=\"https://discord.gg/sZNKpAAAw6\"\u003e\n        \u003cpicture\u003e\n            \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://img.shields.io/discord/917780624314613760?color=212022\u0026label=%20\u0026logo=discord\u0026style=for-the-badge\"\u003e\n            \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/discord/917780624314613760?color=f6f7f8\u0026label=%20\u0026logo=discord\u0026style=for-the-badge\"\u003e\n            \u003cimg alt=\"Discord online\" src=\"https://img.shields.io/discord/917780624314613760?color=f6f7f8\u0026label=%20\u0026logo=discord\u0026style=for-the-badge\"\u003e\n        \u003c/picture\u003e\n    \u003c/a\u003e\n    \u003ca aria-label=\"Follow @mastercorg\" href=\"https://twitter.com/mastercorg\"\u003e\n        \u003cpicture\u003e\n            \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://img.shields.io/static/v1?label=%20\u0026message=twitter\u0026color=212022\u0026logo=twitter\u0026style=for-the-badge\"\u003e\n            \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/static/v1?label=%20\u0026message=twitter\u0026color=f6f7f8\u0026logo=twitter\u0026style=for-the-badge\"\u003e\n            \u003cimg alt=\"Follow @mastercorg\" src=\"https://img.shields.io/static/v1?label=%20\u0026message=twitter\u0026color=f6f7f8\u0026logo=twitter\u0026style=for-the-badge\"\u003e\n        \u003c/picture\u003e\n    \u003c/a\u003e\n    \u003ca aria-label=\"Github Actions\" href=\"https://github.com/master-co/styled/actions/workflows/release.yml\"\u003e\n        \u003cpicture\u003e\n            \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://img.shields.io/github/actions/workflow/status/master-co/styled/release.yml?branch=rc\u0026label=%20\u0026message=twitter\u0026color=212022\u0026logo=githubactions\u0026style=for-the-badge\"\u003e\n            \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/github/actions/workflow/status/master-co/styled/release.yml?branch=rc\u0026label=%20\u0026message=twitter\u0026color=f6f7f8\u0026logo=githubactions\u0026style=for-the-badge\u0026logoColor=%23000\"\u003e\n            \u003cimg alt=\"Github release actions\" src=\"https://img.shields.io/github/actions/workflow/status/master-co/styled/release.yml?branch=rc\u0026label=%20\u0026message=twitter\u0026color=f6f7f8\u0026logo=githubactions\u0026style=for-the-badge\u0026logoColor=%23000\"\u003e\n        \u003c/picture\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n\u003c/div\u003e\n\n## Features\nVanilla, Next, React, Vue, Tailwind CSS, and [Master CSS](https://rc.css.master.co/docs/installation) are available:\n\n* ⚡️ Ultra-lightweight **~1.5KB**, powered by [`Proxy`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy)\n* 🛡️ Type safety\n* 🌈 Dynamically change styles based on properties\n* 💫 Re-expand existing elements, like `NextLink`\n* 🧩 Compatible with server and client components\n* 🪄 Built-in first-class [`clsx`](https://github.com/lukeed/clsx) handling\n\n## Why?\n😰 **Before**: Creating a simple styled element using a FunctionalComponent is unpleasant.\n```tsx\nfunction Button(props) {\n    return (\n        \u003cbutton {...props} className={\"inline-flex font:14\" + (props.className ? ' ' + props.className : '')}\u003e\n            {props.children}\n        \u003c/button\u003e\n    )\n}\n```\n🥳 **After**: It's in one line and ~80% code less.\n```tsx\nimport styled from '@master/styled.react' // or .vue\n\nconst Button = styled.button`inline-flex font:14`\n```\nApply it as usual:\n```tsx\nexport default function App() {\n    return (\n        \u003cButton className=\"uppercase\"\u003esubmit\u003c/Button\u003e\n    )\n}\n```\nIt will be rendered as:\n```html\n\u003cbutton class=\"inline-flex font:14 uppercase\"\u003esubmit\u003c/button\u003e\n```\n\n## Getting Started\nInstall the package depending on your framework:\n\n### Vanilla\n```bash\nnpm install class-variant\n```\n```js\nimport cv from 'class-variant'\n\nconst btn = cv(...params)\nconst btn = cv`...` // or\n\nbtn(props) // -\u003e string\n```\n\n### React\n```bash\nnpm install @master/styled.react\n```\n```js\nimport styled from '@master/styled.react'\n\nconst Button = styled.button(...params)\nconst Button = styled.button`...` // or\n\n\u003cButton {...props}\u003e\n```\n\n### Vue\n```bash\nnpm install @master/styled.vue\n```\n```js\nimport styled from '@master/styled.vue'\n\nconst Button = styled.button(...params)\nconst Button = styled.button`...` // or\n\n\u003cButton {...props}\u003e\n```\n\n## Basic usage\n### Create a styled element\nDeclared in two ways: function or template literal, and parameters inherit all features of [`clsx`](https://github.com/lukeed/clsx).\n```tsx\nconst Element = styled.div`flex text:center`\nconst Element = styled.div('flex text:center') // or\n\nreturn (\n    \u003cElement className=\"uppercase\"\u003eHello World\u003c/Element\u003e\n)\n```\n```html\n\u003cdiv class=\"flex text:center uppercase\"\u003eHello World\u003c/div\u003e\n```\n\n### Apply based on predefined variants\nPredefine the class variant corresponding to the property.\n```tsx\nconst Button = styled.button('flex', {\n    $size: {\n        sm: 'font:12 size:8x',\n        md: 'font:14 size:12x'\n    },\n    disabled: 'opacity:.5',\n    ...\n})\n\nreturn (\n    \u003cButton $size=\"sm\" disabled /\u003e\n)\n```\n```html\n\u003cbutton class=\"flex font:12 size:8x opacity:.5\" disabled\u003e\u003c/button\u003e\n```\n\u003e ⚠️ Custom properties that are not element-owned properties must be prefixed with `$prop`, otherwise they will be reflected on the final element and an error may be thrown.\n\nYou can set default properties for elements.\n```tsx\nButton.default = {\n    $size: 'md'\n}\n\nreturn (\n    \u003cButton /\u003e\n)\n```\n```html\n\u003cbutton class=\"font:14 size:12x\"\u003e\u003c/button\u003e\n```\n\n### Apply based on function properties\nDynamically apply class names based on function properties.\n```tsx\nconst Element = styled.div('fg:white',\n    ({ $color }) =\u003e $color \u0026\u0026 `bg:${$color}`\n)\n\nreturn (\n    \u003cElement $color=\"blue\" /\u003e\n)\n```\n```html\n\u003cdiv class=\"inline-flex text:center fg:white bg:blue\"\u003e\u003c/div\u003e\n```\n\n### Apply based on matching properties\nApplies the target class name matching all specified property keys and their values.\n```tsx\nconst Button = styled.button('inline-flex',\n    ['uppercase', { $intent: 'primary', $size: 'md' }]\n)\n\nreturn (\n    \u003cButton $intent=\"primary\"\u003eNot matched\u003c/button\u003e\n    \u003cButton $size=\"md\"\u003eNot matched\u003c/button\u003e\n    \u003cButton $intent=\"primary\" $size=\"md\"\u003eMatched\u003c/button\u003e\n)\n```\n```html\n\u003cbutton class=\"inline-flex\"\u003eNot matched\u003c/button\u003e\n\u003cbutton class=\"inline-flex\"\u003eNot matched\u003c/button\u003e\n\u003cbutton class=\"inline-flex uppercase\"\u003eMatched\u003c/button\u003e\n```\n\n## Extended\n### Extend a styled element\nExtend an existing styled element and add additional classes or conditions.\n```tsx\nconst A = styled.p('a')\nconst B = styled.p(A)`b`\n\nreturn (\n    \u003cA\u003eA\u003c/A\u003e\n    \u003cB\u003eB\u003c/B\u003e\n)\n```\n```html\n\u003cp class=\"a\"\u003eA\u003c/p\u003e\n\u003cp class=\"a b\"\u003eB\u003c/p\u003e\n```\nIt also supports client components, taking Next.js’s `Link` as an example:\n```tsx\n'use client'\n\nimport styled from '@master/styled.react';\nimport Link from 'next/link';\n\nconst Button = styled(Link)`inline-flex text:center`\n\nreturn (\n    \u003cButton\u003eSubmit\u003c/Button\u003e\n)\n```\n\u003e ⚠️ If the extended target contains client components, the `'use client'` directive is required.\n\n### Change an element's tag name\nChanging the original tag name of an element, such as `\u003cbutton\u003e` to `\u003ca\u003e`. Left empty '' even if there are no additional classes.\n```tsx\nconst Button = styled.button('inline-flex')\nconst Link = styled.a(Button)``\n\nreturn (\n    \u003cButton\u003ebutton\u003c/Button\u003e\n    \u003cLink href=\"#example\"\u003elink\u003c/Link\u003e\n)\n```\n```html\n\u003cbutton class=\"inline-flex\"\u003ebutton\u003c/button\u003e\n\u003ca class=\"inline-flex\" href=\"#example\"\u003elink\u003c/a\u003e\n```\n\n### Extend multiple styled elements\nExtend multiple style elements at once.\n```tsx\nconst A = styled.p`a`\nconst B = styled.p`b`\nconst C = styled.p`c`\nconst D = styled(A)(B)(C)`d`\n\nreturn (\n    \u003cA\u003eA\u003c/A\u003e\n    \u003cB\u003eB\u003c/B\u003e\n    \u003cC\u003eC\u003c/C\u003e\n    \u003cD\u003eD\u003c/D\u003e\n)\n```\n```html\n\u003cp class=\"a\"\u003eA\u003c/p\u003e\n\u003cp class=\"b\"\u003eB\u003c/p\u003e\n\u003cp class=\"c\"\u003eC\u003c/p\u003e\n\u003cp class=\"a b c d\"\u003eD\u003c/p\u003e\n```\n\n## Typings\n```ts\ndeclare type Props = {\n    $size: 'sm' | 'md'\n}\n\nconst Button = styled.button\u003cProps\u003e('flex', {\n    $size: {\n        sm: 'font:12 size:8x',\n        md: 'font:14 size:12x'\n    },\n    disabled: 'opacity:.5'\n})\n```\n\n## Overview `class-variant` APIs\n```ts\nimport cv from 'class-variant'\n\nconst btn = cv(\n    'inline-flex rounded',\n    {\n        intent: {\n            primary: 'bg:blue fg:white bg:blue-60:hover',\n            secondary: 'bg:white fg:slate-30 bg:slate-90:hover',\n        },\n        size: {\n            sm: 'text:14 p:5|15',\n            md: 'text:16 p:10|25'\n        }\n    },\n    ['uppercase', { intent: 'primary', size: 'md' }],\n    ({ indent, size }) =\u003e indent \u0026\u0026 size \u0026\u0026 'font:semibold'\n)\n\nbtn.default = {\n    intent: 'primary',\n    size: 'sm'\n}\n\nbtn()\n// inline-flex rounded bg:blue fg:white bg:blue-55:hover text:14 p:5|8 font:semibold\n\nbtn({ indent: 'secondary', size: 'sm' })\n// inline-flex rounded bg:white fg:slate-30 bg:slate-90:hover text:14 p:5|8 font:semibold\n\nbtn({ indent: 'primary', size: 'md' })\n// inline-flex rounded bg:blue fg:white bg:blue-55:hover text:16 p:10|25 uppercase font:semibold\n```\n\n## Community\nThe Master community can be found here:\n\n- [Discuss on GitHub](https://github.com/master-co/styled/discussions) - Ask questions, voice ideas, and do any other discussion\n- [Join our Discord Server](https://discord.com/invite/sZNKpAAAw6) - Casually chat with other people using the language \u003csup\u003e\u003csub\u003e✓ 中文\u003c/sub\u003e\u003c/sup\u003e\n\n\u003csub\u003eOur [《 Code of Conduct 》](https://github.com/master-co/styled/blob/main/.github/CODE_OF_CONDUCT.md) applies to all Master community channels.\u003c/sub\u003e\n\n## Contributing\nPlease see our [CONTRIBUTING](https://github.com/master-co/styled/blob/main/.github/CONTRIBUTING.md) for workflow.\n\n## Inspiration\nSome of our core concepts and designs are inspired by these giants.\n- **Template Literal** - The use of template literals as syntactic sugar for reusing components is inspired by [Styled Components](https://styled-components.com/).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaster-co%2Fstyled","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaster-co%2Fstyled","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaster-co%2Fstyled/lists"}