{"id":13620979,"url":"https://github.com/pveyes/theme-in-css","last_synced_at":"2025-10-26T04:35:08.714Z","repository":{"id":42005480,"uuid":"260652861","full_name":"pveyes/theme-in-css","owner":"pveyes","description":"Type-safe CSS custom properties (CSS variables) for theming purpose","archived":false,"fork":false,"pushed_at":"2023-01-06T04:57:30.000Z","size":1191,"stargazers_count":66,"open_issues_count":7,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-03T21:22:40.378Z","etag":null,"topics":["css","css-properties","css-variables","oss","theme","typescript"],"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/pveyes.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":"2020-05-02T09:21:52.000Z","updated_at":"2024-10-14T13:52:20.000Z","dependencies_parsed_at":"2023-02-05T09:00:43.576Z","dependency_job_id":null,"html_url":"https://github.com/pveyes/theme-in-css","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/pveyes/theme-in-css","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pveyes%2Ftheme-in-css","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pveyes%2Ftheme-in-css/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pveyes%2Ftheme-in-css/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pveyes%2Ftheme-in-css/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pveyes","download_url":"https://codeload.github.com/pveyes/theme-in-css/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pveyes%2Ftheme-in-css/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281059640,"owners_count":26437056,"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","status":"online","status_checked_at":"2025-10-26T02:00:06.575Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["css","css-properties","css-variables","oss","theme","typescript"],"created_at":"2024-08-01T21:01:01.398Z","updated_at":"2025-10-26T04:35:08.686Z","avatar_url":"https://github.com/pveyes.png","language":"TypeScript","readme":"\u003c!-- markdownlint-disable MD026 MD033 MD041 --\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![theme-in-css](https://user-images.githubusercontent.com/1614415/80961549-5ba25e80-8e35-11ea-8ee3-0a709439f15a.png)](.)\n\n[![npm](https://badgen.net/npm/v/theme-in-css)](https://www.npmjs.com/package/theme-in-css)\n[![npm-dl](https://badgen.net/npm/dt/theme-in-css)](https://www.npmjs.com/package/theme-in-css)\n\n\u003c/div\u003e\n\n---\n\n- [Why?](#why)\n- [Usage](#usage)\n- [CSS Integration](#css-integration)\n  - [.css.string: `string`](#cssstring-string)\n  - [.css.properties: `Array\u003c[key: string, value: string]\u003e`](#cssproperties-arraykey-string-value-string)\n- [License](#license)\n\n---\n\n## Why?\n\n- **Strictly-typed design token, no more typo**. As you might know: CSS is forgiving, but in this case we don't want that. We want it to fail at compile time and this library gives you that\n- **Works in CSS and JS**. Using CSS custom properties means you can reference your design token in both CSS and JS. Separation of concern!\n- **UI Library agnostic**. The only purpose of this library is to provide type-safe CSS custom properties in your TS modules, nothing less, nothing more.\n\n## Usage\n\nFirst create your theme object, you can group theme variables by its function (color, spacing, etc). Think of it as design token\n\n```ts\nimport { createTheme } from 'theme-in-css';\n\nexport const Theme = createTheme({\n  color: {\n    lightPrimary: '#fff',\n    darkPrimary: '#000',\n  },\n  spacing: {\n    xs: 2,\n    s: 4,\n    m: 8,\n    l: 16,\n    xl: 32,\n  },\n  typography: {\n    family: {\n      serif: 'Times New Roman',\n      sans: 'Calibri',\n      mono: 'Menlo',\n    },\n  }\n});\n\n// If you hate typing you can also use a shorter property name\n// const t = createTheme({ c: { l1: '#fff', d1: '#000' } });\n```\n\nYou can use any any UI libraries/framework that can define style in JS/TS, for example [React](https://reactjs.org) and [Lit](https://lit.dev/).\n\n```tsx\n// React\nimport React from 'react';\nimport { Theme } from './theme';\n\nexport default function Component() {\n  // use css prop via emotion/styled-components\n  // of course inline style works as well\n  return (\n    \u003cdiv\n      css={{\n        backgroundColor: Theme.color.darkPrimary,\n        color: Theme.color.lightPrimary,\n        margin: Theme.spacing.m,\n        fontFamily: Theme.typography.family.serif,\n      }}\n    \u003e\n      \u003ch1\u003eIt works\u003c/h1\u003e\n    \u003c/div\u003e\n  );\n}\n\n// Lit\n// You need to wrap Theme inside `unsafeCSS`\nimport { LitElement, html, css, unsafeCSS as cv } from 'lit';\nimport { Theme } from './theme';\n\nexport default class Component extends LitElement {\n  static styles = css`\n    div {\n      background-color: ${cv(Theme.color.darkPrimary)};\n      color: ${cv(Theme.color.lightPrimary)};\n      margin: ${cv(Theme.spacing.m)};\n      font-family: ${cv(Theme.typography.family.serif)};\n    }\n  `;\n\n  render() {\n    return html`\n      \u003cdiv\u003e\n        \u003ch1\u003eIt works\u003c/h1\u003e\n      \u003c/div\u003e\n    `;\n  }\n}\n```\n\n## CSS Integration\n\nIf you only create theme and use them in your app, you'll notice that your app now uses CSS variables to reference a value, but it doesn't work properly yet because you need to add the CSS into your stylesheet.\n\n### .css.string: `string`\n\n`theme-in-css` provides `.css.string` property to dump all theme values as CSS properties. You can create 2 themes light and dark and output them in different style declaration, like this:\n\n```ts\nimport { Theme, DarkTheme } from './theme';\n\nconst html = `\n\u003c!doctype head\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cstyle\u003e\n      :root {\n        ${Theme.css.string}\n      }\n\n      @media (prefers-color-scheme: dark) {\n        ${DarkTheme.css.string}\n      }\n    \u003c/style\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n`;\n```\n\nYou can open [example](example) to see it in action.\n\n### .css.properties: `Array\u003c[key: string, value: string]\u003e`\n\nYou can also use `.css.properties` if you want to update the CSS custom property manually using JS.\n\n```js\nconst root = document.documentElement;\n\ntheme.css.properties.forEach(([key, value]) =\u003e {\n  root.style.setProperty(key, value);\n});\n```\n\nIf you prefer `Record\u003cstring, string\u003e` instead, you can use `Object.fromEntries`\n\n```js\nconst obj = Object.fromEntries(theme.css.properties);\n```\n\n## License\n\nMIT\n","funding_links":[],"categories":["TypeScript","T"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpveyes%2Ftheme-in-css","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpveyes%2Ftheme-in-css","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpveyes%2Ftheme-in-css/lists"}