{"id":16868025,"url":"https://github.com/jens-ox/tailwind-components","last_synced_at":"2026-04-10T01:38:44.398Z","repository":{"id":96757559,"uuid":"266827520","full_name":"jens-ox/tailwind-components","owner":"jens-ox","description":"Framework-agnostic Tailwind UI elements using Web Components","archived":false,"fork":false,"pushed_at":"2020-05-26T22:15:24.000Z","size":188,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-24T21:43:30.727Z","etag":null,"topics":["lit-html","tailwindcss","tailwindui","web-components"],"latest_commit_sha":null,"homepage":"https://sad-austin-fb8742.netlify.app","language":"TypeScript","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/jens-ox.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-25T16:26:50.000Z","updated_at":"2023-08-08T09:18:01.000Z","dependencies_parsed_at":"2023-05-04T20:01:56.781Z","dependency_job_id":null,"html_url":"https://github.com/jens-ox/tailwind-components","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jens-ox%2Ftailwind-components","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jens-ox%2Ftailwind-components/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jens-ox%2Ftailwind-components/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jens-ox%2Ftailwind-components/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jens-ox","download_url":"https://codeload.github.com/jens-ox/tailwind-components/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244284343,"owners_count":20428348,"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":["lit-html","tailwindcss","tailwindui","web-components"],"created_at":"2024-10-13T14:56:40.495Z","updated_at":"2025-12-31T00:14:26.370Z","avatar_url":"https://github.com/jens-ox.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tailwind Components\n\nFirst of all, this is more of an experiment. Obviously, only the Tailwind UI components with publicly available source are considered here. Actually, this is currently only the [header example](https://tailwindui.com/components/marketing/elements/headers).\n\nIn the [Full-Stack Developer job post](https://jobs.tailwindui.com/full-stack-developer), one of the tasks is building official Tailwind UI components for React and Vue. Why not leverage Web Components? [According to custom-elements-everywhere](https://custom-elements-everywhere.com/), Web Components are starting to become natively usable in most frontend frameworks (or libraries).\n\n## Trying it out\n\nThe menu object from the example looks something like this:\n\n```js\nconst menu = {\n  buttons: [{\n    name: 'Sign in',\n    link: '#',\n    type: 'secondary'\n  }, {\n    name: 'Sign up',\n    link: '#',\n    type: 'primary'\n  }],\n  entries: [{\n    name: 'Solutions',\n    entries: [{\n      name: 'Analytics',\n      description: 'Get a better understanding of where your traffic is coming from.',\n      icon: '/assets/img/analytics.svg',\n      link: '#'\n    } /* ... */],\n    footer: {\n      entries: [{\n        name: 'Watch Demo',\n        icon: '/assets/img/watch-demo.svg',\n        link: '#'\n      }, {\n        name: 'Contact Sales',\n        icon: '/assets/img/contact-sales.svg',\n        link: '#'\n      }]\n    }\n  }, {\n    name: 'Pricing',\n    link: '#'\n  }, {\n    name: 'Docs',\n    link: '#'\n  }, {\n    name: 'More',\n    entries: [{\n      name: 'Help Center',\n      description: 'Get all of your questions answered in our forums or contact support.',\n      icon: '/assets/img/help-center.svg',\n      link: '#'\n    } /* ... */],\n    footer: {\n      name: 'Recent Posts',\n      link: {\n        name: 'View all posts →',\n        link: '#'\n      },\n      entries: [{\n        name: 'Boost your conversion rate',\n        link: '#'\n      } /* ... */]\n    }\n  }]\n}\n```\n\nA native Web Component would then look something like this:\n\n```html\n\u003ctw-menu .entries=${menu.entries} .buttons=${menu.buttons}\u003e\u003c/tw-menu\u003e\n```\n\nThe same would look like this in preact:\n\n```jsx\n\u003ctw-menu entries={menu.entries} buttons={menu.buttons}\u003e\u003c/tw-menu\u003e\n```\n\nOr in Vue:\n\n```vue\n\u003ctw-menu :entries=\"menu.entries\" :buttons=\"menu.buttons\"\u003e\u003c/tw-menu\u003e\n```\n\nSee [the menu example](src/components/examples/menu.js) for the full code.\n\n## Development\n\n```bash\ngit clone [repo] \u0026\u0026 cd [repo]\nnpm install # or yarn\nnpm run dev # or yarn dev\n```\n\n### Testing with Karma\nTo run the suite of karma tests, run\n```bash\nnpm run test\n```\n\nTo run the tests in watch mode (for \u003cabbr title=\"test driven development\"\u003eTDD\u003c/abbr\u003e, for example), run\n\n```bash\nnpm run test:watch\n```\n\n### Demoing with Storybook\nTo run a local instance of Storybook for your component, run\n```bash\nnpm run storybook\n```\n\nTo build a production version of Storybook, run\n```bash\nnpm run storybook:build\n```\n\n\n### Tooling configs\n\nFor most of the tools, the configuration is in the `package.json` to reduce the amount of files in your project.\n\nIf you customize the configuration a lot, you can consider moving them to individual files.\n\n### Local Demo with `es-dev-server`\n```bash\nnpm start\n```\nTo run a local development server that serves the basic demo located in `demo/index.html`\n\n## Pain Points and Future Work\n\n### Shared Styles\n\nThe usage of shared CSS in Web Components -- see [this article from 2016](https://www.smashingmagazine.com/2016/12/styling-web-components-using-a-shared-style-sheet/), apparently not too much has changed since then, but I didn't really dig deep.\nCurrently, each component includes the CDN version of Tailwind, which is kind of the worst way to use Tailwind I guess.\n\n### Building as a library\n\nPurging out unused CSS from the components might turn out to be quite difficult. I don't know if there's any tooling for this.\n\n### Handling icons\n\nThe two ways of passing data to a UI library -- through attributes/properties or through slots -- are both kinda awkward for passing icons. For example, a menu entry might look something like this as an object:\n\n```js\n{\n  title: 'Analytics',\n  description: 'Get a better understanding of where your traffic is coming from.',\n  link: '#',\n  icon: '/assets/img/analytics.svg'\n}\n```\n\nThis makes sense, but now styling the SVG is hard -- even with `stroke=\"currentColor\"` set in the SVG file, the color won't be inherited, as the embedded SVG is its own document.\n\nThe alternative would be to use components with a slot:\n\n```html\n\u003cmenu-entry\n  title=\"Analytics\"\n  description=\"Get a better understanding of where your traffic is coming from.\"\n  link=\"#\"\n\u003e\n  \u003csvg\u003e\n    ...\n  \u003c/svg\u003e\n\u003c/menu-entry\u003e\n```\n\nThis makes the markup way harder to maintain.\n\n**Possible solutions**:\n\n* ship icons with the library, like [Vuetify](https://vuetifyjs.com/en/customization/icons/) does\n* use a library like [SVGInject](https://github.com/iconfu/svg-inject) to inject svg files into the DOM\n* use the SVG as filter\n\nFor now, SVGInject is used. A native solution would be nicer.\n\n### TypeScript\n\nUI libraries heavily rely on passing quite complex objects around. Having type support for those is nice.\n\n## Credits\n\nAll credit goes to @adamwathan and @sschoger for creating TailwindCSS and TailwindUI. I'm really grateful for those tools making frontend development so much more enjoyable.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjens-ox%2Ftailwind-components","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjens-ox%2Ftailwind-components","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjens-ox%2Ftailwind-components/lists"}