{"id":28540559,"url":"https://github.com/todovue/tv-button","last_synced_at":"2026-01-27T16:03:46.815Z","repository":{"id":278991493,"uuid":"937377298","full_name":"TODOvue/tv-button","owner":"TODOvue","description":"TvButton is a custom button component for web applications.","archived":false,"fork":false,"pushed_at":"2025-05-09T02:55:31.000Z","size":98,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-09T19:48:14.374Z","etag":null,"topics":["button","buttonkit","todovue","vue","vue3"],"latest_commit_sha":null,"homepage":"https://tv-button.netlify.app/","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/TODOvue.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"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,"zenodo":null}},"created_at":"2025-02-22T22:37:55.000Z","updated_at":"2025-05-09T02:55:34.000Z","dependencies_parsed_at":"2025-05-05T21:27:37.670Z","dependency_job_id":"c82df546-5f91-4ee6-9c11-1f59c20408f1","html_url":"https://github.com/TODOvue/tv-button","commit_stats":null,"previous_names":["todovue/todovue-button","todovue/tv-button"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/TODOvue/tv-button","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-button","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-button/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-button/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-button/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TODOvue","download_url":"https://codeload.github.com/TODOvue/tv-button/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-button/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264069169,"owners_count":23552555,"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":["button","buttonkit","todovue","vue","vue3"],"created_at":"2025-06-09T19:31:39.293Z","updated_at":"2026-01-27T16:03:46.808Z","avatar_url":"https://github.com/TODOvue.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg width=\"150\" src=\"https://res.cloudinary.com/dcdfhi8qz/image/upload/v1763663056/uqqtkgp1lg3xdplutpga.png\" alt=\"TODOvue logo\"\u003e\n\u003c/p\u003e\n\n# TODOvue Button (TvButton)\nA flexible, framework‑agnostic Vue 3 button component with variants, sizes, icons, loading state, and customization utilities. Ship it in Single Page Apps or Server-Side Rendered (SSR) environments (e.g. Nuxt 3) with zero DOM assumptions.\n\n[![npm](https://img.shields.io/npm/v/@todovue/tv-button.svg)](https://www.npmjs.com/package/@todovue/tv-button)\n[![npm downloads](https://img.shields.io/npm/dm/@todovue/tv-button.svg)](https://www.npmjs.com/package/@todovue/tv-button)\n[![npm total downloads](https://img.shields.io/npm/dt/@todovue/tv-button.svg)](https://www.npmjs.com/package/@todovue/tv-button)\n![License](https://img.shields.io/github/license/TODOvue/tv-button)\n![Release Date](https://img.shields.io/github/release-date/TODOvue/tv-button)\n![Bundle Size](https://img.shields.io/bundlephobia/minzip/@todovue/tv-button)\n![Node Version](https://img.shields.io/node/v/@todovue/tv-button)\n![Last Commit](https://img.shields.io/github/last-commit/TODOvue/tv-button)\n![Stars](https://img.shields.io/github/stars/TODOvue/tv-button?style=social)\n\n\u003e Demo: https://ui.todovue.blog/button/\n\n## Table of Contents\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start (SPA)](#quick-start-spa)\n- [Style usage](#style-usage)\n- [Nuxt 4 / SSR Usage](#nuxt-4--ssr-usage)\n- [Component Registration Options](#component-registration-options)\n- [Props](#props)\n- [Events](#events)\n- [Icons](#icons)\n- [Customization (Styles / Theming)](#customization-styles--theming)\n- [Icon-only \u0026 Variant Notes](#icon-only--variant-notes)\n- [Accessibility](#accessibility)\n- [SSR Notes](#ssr-notes)\n- [Development](#development)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n- **Variants**: primary, secondary, success, info, warning, error\n- **Sizes**: sm, md, lg, full-width option\n- Icon support (pre-bundled SVG set via `import.meta.glob`)\n- Icon-only and pure icon modes (`type=\"icon\"` + `iconOnly`)\n- Loading state with spinner\n- Custom inline style override via `customStyle`\n- Emits both a custom event and the native click\n- Works in SPA and SSR (Nuxt 3) contexts\n- Tree-shake friendly (Vue marked external in library build)\n\n## Installation\nUsing npm:\n```bash\nnpm install @todovue/tv-button\n```\nUsing yarn:\n```bash\nyarn add @todovue/tv-button\n```\nUsing pnpm:\n```bash\npnpm add @todovue/tv-button\n```\n\n## Quick Start (SPA)\nGlobal registration (main.js / main.ts):\n```js\nimport { createApp } from 'vue'\nimport App from './App.vue'\nimport '@todovue/tv-button/style.css'\nimport TvButton from '@todovue/tv-button'\n\ncreateApp(App)\n  .use(TvButton) // enables \u003cTvButton /\u003e globally\n  .mount('#app')\n```\nLocal import inside a component:\n```vue\n\u003cscript setup\u003e\nimport '@todovue/tv-button/style.css'\nimport { TvButton } from '@todovue/tv-button'\n\nfunction onSubmit() {\n  console.log('Clicked')\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cTvButton variant=\"success\" icon=\"check\" @click-button=\"onSubmit\"\u003eSubmit\u003c/TvButton\u003e\n\u003c/template\u003e\n```\n\n## Style usage\n\n### Vue 3 SPA with Vite\n```ts\n// main.ts\nimport { createApp } from 'vue'\nimport App from './App.vue'\n\nimport '@todovue/tv-button/style.css'\nimport { TvButton } from '@todovue/tv-button'\n\nconst app = createApp(App)\napp.component('TvButton', TvButton)\napp.mount('#app')\n```\n\n### Nuxt 3/4\n```ts\n// nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: [\n    '@todovue/tv-button/nuxt'\n  ]\n})\n```\n\n## Nuxt 4 / SSR Usage\nCreate a plugin file: `plugins/tv-button.client.ts` (client-only is fine, or without suffix for SSR as it is safe):\n```ts\nimport { defineNuxtPlugin } from '#app'\nimport TvButton from '@todovue/tv-button'\n\nexport default defineNuxtPlugin(nuxtApp =\u003e {\n  nuxtApp.vueApp.use(TvButton)\n})\n```\nUse anywhere:\n```vue\n\u003cTvButton outlined icon=\"info\"\u003eDetails\u003c/TvButton\u003e\n```\nOptional direct import (no plugin):\n```vue\n\u003cscript setup\u003e\nimport { TvButton } from '@todovue/tv-button'\n\u003c/script\u003e\n```\n\n## Component Registration Options\n| Approach                                                          | When to use                                    |\n|-------------------------------------------------------------------|------------------------------------------------|\n| Global via `app.use(TvButton)`                                    | Many usages across app / design system install |\n| Local named import `{ TvButton }`                                 | Isolated / code-split contexts                 |\n| Direct default import `import TvButton from '@todovue/tv-button'` | Single usage or manual registration            |\n\n## Props\nAll boolean style props have two interchangeable forms: a long form (`isSomething`) and a short alias.\n\n| Prop         | Type                                      | Default   | Description                                            |\n|--------------|-------------------------------------------|-----------|--------------------------------------------------------|\n| buttonText   | string                                    | ''        | Optional text (alternative to slot).                   |\n| variant      | 'primary' \\| 'secondary' \\| 'success' ... | 'primary' | Visual style variant.                                  |\n| size         | 'sm' \\| 'md' \\| 'lg'                      | 'md'      | Button size.                                           |\n| customStyle  | object                                    | {}        | Inline style overrides (`{ backgroundColor, color }`). |\n| icon         | string                                    | null      | Name of bundled icon.                                  |\n| iconColor    | string                                    | 'white'   | Icon color override.                                   |\n| iconPosition | 'left' \\| 'right'                         | 'right'   | Icon position relative to text.                        |\n| type         | 'button' \\| 'submit' \\| 'reset' \\| 'icon' | 'button'  | Native button type. Use 'icon' for icon-only styling.  |\n| ariaLabel    | string                                    | ''        | Accessibility label (required if no text / icon-only). |\n| iconOnly     | boolean                                   | false     | Renders only the icon (no padding/background).         |\n| outlined     | boolean                                   | false     | Outlined style.                                        |\n| rounded      | boolean                                   | false     | Rounded corners.                                       |\n| disabled     | boolean                                   | false     | Disables interaction.                                  |\n| loading      | boolean                                   | false     | Shows spinner \u0026 disables.                              |\n| full         | boolean                                   | false     | Full width.                                            |\n| text         | boolean                                   | false     | Text (minimal) style.                                  |\n| href         | string                                    | null      | URL for native anchor tag.                             |\n| to           | string \\| object                          | null      | Route for RouterLink / NuxtLink.                       |\n| target       | string                                    | null      | Anchor target (e.g. '_blank').                         |\n| rel          | string                                    | null      | Anchor rel attribute.                                  |\n\n\u003e Note: Because `type` is bound to the native `\u003cbutton type=\"...\"\u003e`, using `type=\"icon\"` produces a non-standard button attribute. This does not break rendering but is semantically incorrect in forms. A future release will introduce `variant` and keep `htmlType` separate (see Roadmap).\n\n## Events\n| Event name (kebab) | Emits (camel) | Description                                 |\n|--------------------|---------------|---------------------------------------------|\n| `click-button`     | `clickButton` | Custom semantic click event.                |\n| `click`            | `click`       | Native passthrough (also emitted manually). |\n\nUsage:\n```vue\n\u003cTvButton @click-button=\"onAction\" /\u003e\n\u003cTvButton @click=\"onNative\" /\u003e\n```\n\n## Icons\nSet with the `icon` prop. Available names:\n`account`, `add-user`, `alert`, `arrow-down`, `arrow-left`, `arrow-right`, `arrow-up`, `block`, `calendar`, `cancel`, `check`, `clone`, `dark`, `download`, `edit`, `external-link`, `favorite`, `filter`, `help`, `info`, `light`, `loading`, `lock`, `login`, `logout`, `menu`, `minus`, `notification`, `plus`, `remove`, `search`, `settings`, `share`, `star`, `todovue`, `unlock`, `update`, `view` `double-arrow-left`, `double-arrow-right`, `home`, `dots-vertical`, `eye-off`, `trash`, `upload`, `dashboard`, `folder`, `link`, `mail` and `save`.\n\nExample:\n```vue\n\u003cTvButton icon=\"check\" variant=\"success\"\u003eSaved\u003c/TvButton\u003e\n\u003cTvButton icon=\"info\" iconPosition=\"left\" outlined\u003eInfo\u003c/TvButton\u003e\n```\n\n## Customization (Styles / Theming)\nInline overrides via `customStyle`:\n```vue\n\u003cTvButton :customStyle=\"{ backgroundColor: '#0f2e5b', color: '#fff' }\"\u003eBranded\u003c/TvButton\u003e\n```\nOutlined variant adapts automatically:\n```vue\n\u003cTvButton outlined :customStyle=\"{ backgroundColor: '#ff4081', color: '#fff' }\"\u003ePink Outline\u003c/TvButton\u003e\n```\n\u003e A subtle hover darkening is auto-generated when `customStyle.backgroundColor` exists.\n\n## Icon-only \u0026 Variant Notes\nPure icon button:\n```vue\n\u003cTvButton type=\"icon\" icon=\"edit\" /\u003e\n```\nInline icon-only action (no background / padding):\n```vue\n\u003cTvButton type=\"icon\" icon=\"edit\" :iconOnly=\"true\" aria-label=\"Edit item\" /\u003e\n```\nLoading state:\n```vue\n\u003cTvButton loading icon=\"download\"\u003eProcessing...\u003c/TvButton\u003e\n```\n\nLink usage:\n```vue\n\u003c!-- Native anchor --\u003e\n\u003cTvButton href=\"https://todovvue.blog\" target=\"_blank\"\u003eExternal Link\u003c/TvButton\u003e\n\n\u003c!-- Router link --\u003e\n\u003cTvButton to=\"/dashboard\"\u003eGo to Dashboard\u003c/TvButton\u003e\n```\n\n## Accessibility\n- Always provide visible text OR `aria-label`.\n- Mandatory: add `aria-label` when using `iconOnly` or when slot content is empty.\n- Disabled state uses both `disabled` attribute and styling classes.\n\n## SSR Notes\n- No direct DOM (`window` / `document`) access in source → safe for SSR.\n- Styles are now served from a separate CSS file generated by Vite (`dist/tv-button.css`). You need to import it explicitly in your app (SPA or Nuxt) using `@todovue/tv-button/style.css`.\n- SVG icons are bundled via Vite's `import.meta.glob` (works in Vite + Nuxt).\n\n## Development\n```bash\ngit clone https://github.com/TODOvue/tv-button.git\ncd tv-button\nyarn install\nyarn dev     # run demo playground\nyarn build   # build library\n```\nLocal demo served from Vite using `index.html` + `src/demo` examples.\n\n## Contributing\nPRs and issues welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).\n\n## License\nMIT © TODOvue\n\n### Attributions\nCrafted for the TODOvue component ecosystem\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftodovue%2Ftv-button","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftodovue%2Ftv-button","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftodovue%2Ftv-button/lists"}