{"id":46553894,"url":"https://github.com/todovue/tv-sidebar","last_synced_at":"2026-03-07T04:01:29.687Z","repository":{"id":319773868,"uuid":"1079511373","full_name":"TODOvue/tv-sidebar","owner":"TODOvue","description":"A versatile sidebar component for TODOvue, offering customizable layouts, themes, and responsive design options.","archived":false,"fork":false,"pushed_at":"2026-01-21T01:59:02.000Z","size":164,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-21T12:52:23.819Z","etag":null,"topics":["component","sidebar-component","todovue","vuejs"],"latest_commit_sha":null,"homepage":"https://ui.todovue.blog/sidebar","language":"Vue","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-20T00:10:38.000Z","updated_at":"2026-01-21T01:51:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"255b969c-330d-409a-8d81-29ef22ff69d9","html_url":"https://github.com/TODOvue/tv-sidebar","commit_stats":null,"previous_names":["todovue/tv-sidebar"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/TODOvue/tv-sidebar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-sidebar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-sidebar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-sidebar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-sidebar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TODOvue","download_url":"https://codeload.github.com/TODOvue/tv-sidebar/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TODOvue%2Ftv-sidebar/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30207390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T03:24:23.086Z","status":"ssl_error","status_checked_at":"2026-03-07T03:23:11.444Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["component","sidebar-component","todovue","vuejs"],"created_at":"2026-03-07T04:01:28.139Z","updated_at":"2026-03-07T04:01:29.656Z","avatar_url":"https://github.com/TODOvue.png","language":"Vue","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 Sidebar (TvSidebar)\nA versatile and flexible Vue 3 sidebar component with multiple display modes: lists, categories (labels), and images. Perfect for blogs, documentation sites, and web applications requiring sidebar navigation or content display. Compatible with both SPA and SSR environments (e.g. Nuxt 3).\n\n[![npm](https://img.shields.io/npm/v/@todovue/tv-sidebar.svg)](https://www.npmjs.com/package/@todovue/tv-sidebar)\n[![npm downloads](https://img.shields.io/npm/dm/@todovue/tv-sidebar.svg)](https://www.npmjs.com/package/@todovue/tv-sidebar)\n[![npm total downloads](https://img.shields.io/npm/dt/@todovue/tv-sidebar.svg)](https://www.npmjs.com/package/@todovue/tv-sidebar)\n![License](https://img.shields.io/github/license/TODOvue/tv-sidebar)\n![Release Date](https://img.shields.io/github/release-date/TODOvue/tv-sidebar)\n![Bundle Size](https://img.shields.io/bundlephobia/minzip/@todovue/tv-sidebar)\n![Node Version](https://img.shields.io/node/v/@todovue/tv-sidebar)\n![Last Commit](https://img.shields.io/github/last-commit/TODOvue/tv-sidebar)\n![Stars](https://img.shields.io/github/stars/TODOvue/tv-sidebar?style=social)\n\n\u003e Demo: https://ui.todovue.blog/sidebar\n\n## Table of Contents\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start (SPA)](#quick-start-spa)\n- [Nuxt 4 / SSR Usage](#nuxt-4--ssr-usage)\n- [Component Registration Options](#component-registration-options)\n- [Props](#props)\n- [Events](#events)\n- [Usage Examples](#usage-examples)\n  - [Default List Mode](#default-list-mode)\n  - [Categories (Labels) Mode](#categories-labels-mode)\n  - [Image Mode](#image-mode)\n  - [With Limit](#with-limit)\n- [Data Structure](#data-structure)\n- [Styling](#styling)\n- [Navigation Handling](#navigation-handling)\n- [Accessibility](#accessibility)\n- [SSR Notes](#ssr-notes)\n- [Development](#development)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n- **Four display modes**: List, Categories (labels), Image, and Grouped/Categorized\n- **Hierarchical grouping**: Organize content with collapsible sections and item counters\n- **Event-driven interactions**: No built-in navigation; emits click events with full objects\n- **Item limit**: Control how many items to display with the `limit` prop\n- **Search/Filter**: Real-time filtering across all display modes including grouped content\n- **Optional clickable images**: Enable with `clickable` to emit click events for images\n- **Label/Category support**: Display colored category labels with click events\n- **Responsive design**: Adapts to different screen sizes\n- **SSR compatible**: Works seamlessly in Nuxt 3 and SSR contexts\n- **Customizable styling**: Built with SCSS for easy theming\n- **Tree-shakeable**: Vue marked as external dependency\n\n## Installation\nUsing npm:\n```bash\nnpm install @todovue/tv-sidebar\n```\nUsing yarn:\n```bash\nyarn add @todovue/tv-sidebar\n```\nUsing pnpm:\n```bash\npnpm add @todovue/tv-sidebar\n```\n\n\u003e **Note**: This component depends on `@todovue/tv-label` for the categories mode.\n\n## Quick Start (SPA)\nGlobal registration (main.js / main.ts):\n```js\nimport { createApp } from 'vue'\nimport App from './App.vue'\nimport TvSidebar from '@todovue/tv-sidebar'\nimport '@todovue/tv-sidebar/style.css' // import styles\nimport '@todovue/tv-label/style.css' // import styles\n\ncreateApp(App)\n  .use(TvSidebar) // enables \u003cTvSidebar /\u003e globally\n  .mount('#app')\n```\nLocal import inside a component:\n```vue\n\u003cscript setup\u003e\nimport { TvSidebar } from '@todovue/tv-sidebar'\nimport '@todovue/tv-sidebar/style.css' // import styles\nimport '@todovue/tv-label/style.css' // import styles\n\nconst sidebarData = {\n  title: \"Most Popular Blogs\",\n  list: [\n    {\n      id: 1,\n      title: \"10 Tips for Creating a Successful YouTube Channel\",\n      link: \"/blog/youtube-tips\",\n    },\n    {\n      id: 2,\n      title: \"The Benefits of Meditation\",\n      link: \"/blog/meditation\",\n    }\n  ]\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cTvSidebar :data=\"sidebarData\" /\u003e\n\u003c/template\u003e\n```\n\n## Nuxt 4 / SSR Usage\nAdd the stylesheet to your `nuxt.config.ts`:\n```ts\n// nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: [\n    '@todovue/tv-card/nuxt'\n  ]\n})\n```\n\nCreate a plugin file: `plugins/tv-sidebar.client.ts` (or without `.client` suffix for SSR):\n```ts\nimport { defineNuxtPlugin } from '#app'\nimport TvSidebar from '@todovue/tv-sidebar'\n\nexport default defineNuxtPlugin(nuxtApp =\u003e {\n  nuxtApp.vueApp.use(TvSidebar)\n})\n```\nUse anywhere (no router dependency required):\n```vue\n\u003cscript setup\u003e\nimport { TvSidebar } from '@todovue/tv-sidebar'\n\u003c/script\u003e\n```\n\n## Component Registration Options\n| Approach                                                            | When to use                                    |\n|---------------------------------------------------------------------|------------------------------------------------|\n| Global via `app.use(TvSidebar)`                                     | Many usages across app / design system install |\n| Local named import `{ TvSidebar }`                                  | Isolated / code-split contexts                 |\n| Direct default import `import TvSidebar from '@todovue/tv-sidebar'` | Single usage or manual registration            |\n\n## Props\n| Prop              | Type    | Default       | Description                                                                                                                              |\n|-------------------|---------|---------------|------------------------------------------------------------------------------------------------------------------------------------------|\n| data              | Object  | `{}`          | Main data object containing title and content (list, labels, or image).                                                                  |\n| isImage           | Boolean | `false`       | Enables image display mode.                                                                                                              |\n| isLabel           | Boolean | `false`       | Enables categories/labels display mode.                                                                                                  |\n| isOutline         | Boolean | `false`       | Apply outline style to labels (only works with `isLabel`).                                                                               |\n| size              | String  | `'md'`        | Sets size of labels (`sm`, `md`, `lg`). Only works with `isLabel`.                                                                       |\n| limit             | Number  | `0`           | Maximum number of items to display (0 = show all).                                                                                       |\n| clickable         | Boolean | `false`       | When `true` and `isImage`, the image becomes interactive and emits a `click` event with the image object. When `false`, image is static. |\n| searchable        | Boolean | `false`       | Enables search/filter input for filtering items in real-time across all display modes.                                                   |\n| searchPlaceholder | String  | `'Search...'` | Placeholder text for the search input field.                                                                                             |\n| grouped           | Boolean | `false`       | Enables grouped/categorized mode with collapsible sections. Requires `data.groups` array instead of `data.list` or `data.labels`.        |\n| newLabelText      | String  | `'New'`       | Text to display in the \"New\" badge when `isNew` is true on an item.                                                                      |\n| newLabelColor     | String  | `'#FF3B30'`   | Hex color code for the \"New\" badge background.                                                                                           |\n\n## Events\n| Event name (kebab) | Emits (camel) | Description                                                                                                                                         |\n|--------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|\n| `click`            | `click`       | Emitted when a list item is clicked, when a label is clicked, and when an image is clicked (if `clickable`). The payload is always the full object. |\n| `search`           | `search`      | Emitted when the search query changes. The payload is the search string.                                                                            |\n\nUsage:\n```vue\n\u003cTvSidebar \n  isLabel \n  searchable\n  :data=\"categoriesData\" \n  @click=\"handleAnyClick\"\n  @search=\"handleSearch\"\n/\u003e\n```\n\n## Usage Examples\n\n### Default List Mode\nDisplay a numbered list of items that emit the full object on click:\n```vue\n\u003cscript setup\u003e\nimport { TvSidebar } from '@todovue/tv-sidebar'\n\nconst listData = {\n  title: \"Most Popular Blogs\",\n  list: [\n    {id: 1, title: \"10 Tips for Creating a Successful YouTube Channel\", link: \"/blog/youtube-tips\"},\n    {id: 2, title: \"The Benefits of Meditation and How to Get Started\", link: \"/blog/meditation\"},\n    {id: 3, title: \"The Top 5 Destinations for Adventure Travel\", link: \"/blog/adventure-travel\"}\n  ],\n}\nfunction handleItemClick(item) {\n  console.log('Item clicked:', item)\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cTvSidebar :data=\"listData\" @click=\"handleItemClick\" /\u003e\n\u003c/template\u003e\n```\n\n### Categories (Labels) Mode\nDisplay colored category labels:\n```vue\n\u003cscript setup\u003e\nimport { TvSidebar } from '@todovue/tv-sidebar'\n\nconst categoriesData = {\n  title: \"Categories\",\n  labels: [\n    {\n      id: 1,\n      name: \"Vue.js\",\n      color: \"#4FC08D\",\n    },\n    {\n      id: 2,\n      name: \"JavaScript\",\n      color: \"#F0DB4F\",\n    },\n    {\n      id: 3,\n      name: \"HTML\",\n      color: \"#E34F26\",\n    },\n    {\n      id: 4,\n      name: \"CSS\",\n      color: \"#1572B6\",\n    }\n  ]\n}\n\nfunction handleCategoryClick(category) {\n  console.log('Category clicked:', category)\n  // Navigate or filter by category\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cTvSidebar \n    isLabel \n    :data=\"categoriesData\" \n    @clickLabel=\"handleCategoryClick\"\n  /\u003e\n\u003c/template\u003e\n```\n\n### Image Mode\nDisplay an image with title. Make it interactive with `clickable` if desired:\n```vue\n\u003cscript setup\u003e\nimport { TvSidebar } from '@todovue/tv-sidebar'\n\nconst imageData = {\n  title: \"TODOvue Blog\",\n  image: {\n    src: \"https://todovue.com/vue.webp\",\n    alt: \"TODOvue Logo\",\n    link: \"https://todovue.com/\"\n  },\n}\nfunction handleImageClick(image) {\n  console.log('Image clicked:', image)\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003c!-- Non-clickable image --\u003e\n  \u003cTvSidebar isImage :data=\"imageData\" /\u003e\n  \n  \u003c!-- Clickable image that emits the image object --\u003e\n  \u003cTvSidebar isImage clickable :data=\"imageData\" @click=\"handleImageClick\" /\u003e\n\u003c/template\u003e\n```\n\n### With Limit\nLimit the number of displayed items:\n```vue\n\u003ctemplate\u003e\n  \u003c!-- Show only first 5 items --\u003e\n  \u003cTvSidebar :data=\"listData\" :limit=\"5\" /\u003e\n  \n  \u003c!-- Show only first 8 categories --\u003e\n  \u003cTvSidebar isLabel :data=\"categoriesData\" :limit=\"8\" /\u003e\n\u003c/template\u003e\n```\n\n### With Search/Filter\nEnable real-time search and filtering across all display modes:\n```vue\n\u003cscript setup\u003e\nimport { TvSidebar } from '@todovue/tv-sidebar'\n\nconst listData = {\n  title: 'Blog Posts',\n  list: [\n    { id: 1, title: 'Getting Started with Vue 3', link: '/blog/vue-3' },\n    { id: 2, title: 'Understanding Composition API', link: '/blog/composition-api' },\n    { id: 3, title: 'Building Reactive Forms', link: '/blog/reactive-forms' }\n  ]\n}\n\nconst categoriesData = {\n  title: 'Categories',\n  labels: [\n    { id: 1, name: 'Vue.js', color: '#4FC08D' },\n    { id: 2, name: 'JavaScript', color: '#F0DB4F' },\n    { id: 3, name: 'TypeScript', color: '#007ACC' }\n  ]\n}\n\nfunction handleSearch(query) {\n  console.log('Search query:', query)\n  // Optionally perform additional actions\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003c!-- Searchable list with default placeholder --\u003e\n  \u003cTvSidebar \n    :data=\"listData\" \n    searchable \n    @search=\"handleSearch\"\n  /\u003e\n  \n  \u003c!-- Searchable labels with custom placeholder --\u003e\n  \u003cTvSidebar \n    isLabel \n    :data=\"categoriesData\" \n    searchable \n    search-placeholder=\"Filter categories...\"\n    @search=\"handleSearch\"\n  /\u003e\n  \n  \u003c!-- Searchable with limit (filtering applied before limiting) --\u003e\n  \u003cTvSidebar \n    :data=\"listData\" \n    searchable \n    :limit=\"5\"\n  /\u003e\n\u003c/template\u003e\n```\n\n### Grouped/Categorized Mode\nOrganize content hierarchically with collapsible groups and item counters:\n```vue\n\u003cscript setup\u003e\nimport { TvSidebar } from '@todovue/tv-sidebar'\n\nconst groupedData = {\n  title: 'Blog Posts',\n  groups: [\n    {\n      id: 1,\n      name: 'Technical',\n      collapsed: false,\n      items: [\n        { id: 1, title: '10 Tips for Creating a Successful YouTube Channel', link: '/blog/youtube' },\n        { id: 2, title: 'How to Create High-Quality Visual Content', link: '/blog/visual-content' },\n        { id: 3, title: 'The Power of Email Marketing', link: '/blog/email-marketing' }\n      ]\n    },\n    {\n      id: 2,\n      name: 'Lifestyle',\n      collapsed: true,\n      items: [\n        { id: 4, title: 'Why You Should Consider a Plant-Based Diet', link: '/blog/plant-based' },\n        { id: 5, title: 'The Pros and Cons of Remote Work', link: '/blog/remote-work' }\n      ]\n    },\n    {\n      id: 3,\n      name: 'Travel',\n      collapsed: false,\n      items: [\n        { id: 6, title: 'The Top 5 Destinations for Adventure Travel', link: '/blog/adventure' }\n      ]\n    }\n  ]\n}\n\nfunction handleItemClick(item) {\n  console.log('Item clicked:', item)\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003c!-- Basic grouped mode --\u003e\n  \u003cTvSidebar \n    grouped \n    :data=\"groupedData\" \n    @click=\"handleItemClick\"\n  /\u003e\n  \n  \u003c!-- Grouped mode with search --\u003e\n  \u003cTvSidebar \n    grouped \n    searchable \n    search-placeholder=\"Search posts...\"\n    :data=\"groupedData\" \n    @click=\"handleItemClick\"\n  /\u003e\n  \n  \u003c!-- Grouped mode with limit (applies to items per group) --\u003e\n  \u003cTvSidebar \n    grouped \n    :limit=\"2\"\n    :data=\"groupedData\" \n    @click=\"handleItemClick\"\n  /\u003e\n\u003c/template\u003e\n```\n\n### New Items Indicator\nMark items as new by adding `isNew: true` to the item object. Customize the label text with `newLabelText`.\n\n```vue\n\u003cscript setup\u003e\nimport { TvSidebar } from '@todovue/tv-sidebar'\n\nconst listData = {\n  title: \"Updates\",\n  list: [\n    { id: 1, title: \"Stable Release\", link: \"/v1\", isNew: true },\n    { id: 2, title: \"Beta Release\", link: \"/beta\" }\n  ]\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cTvSidebar :data=\"listData\" new-label-text=\"UPDATED\" /\u003e\n\u003c/template\u003e\n```\n```\n\n### Nuxt Integration\n```diff\n- Using with Nuxt routing:\n- \u003cTvSidebar linkTag=\"nuxt-link\" :data=\"blogPosts\" /\u003e\n```\nNuxt works without router integration in the component. Handle navigation in your click handlers (see Navigation Handling below).\n\n## Data Structure\n\n### List Mode Data\n```typescript\n{\n  title: string,\n  list: Array\u003c{\n    id: number | string,\n    title: string,\n    link?: string, // optional; use in your click handler if you want to navigate\n    isNew?: boolean // optional; displays a 'New' badge\n  }\u003e\n}\n```\n\n### Labels/Categories Mode Data\n```typescript\n{\n  title: string,\n  labels: Array\u003c{\n    id: number | string,\n    name: string,\n    color: string // Hex color code\n  }\u003e\n}\n```\n\n### Image Mode Data\n```typescript\n{\n  title: string,\n  image: {\n    src: string,    // Image URL\n    alt: string,    // Alt text for accessibility\n    link?: string   // optional; use in your click handler for manual navigation\n  }\n}\n```\n\n### Grouped Mode Data\n```typescript\n{\n  title: string,\n  groups: Array\u003c{\n    id: number | string,\n    name: string,           // Group/category name\n    collapsed: boolean,     // Initial collapsed state\n    items: Array\u003c{\n      id: number | string,\n      title: string,\n      link?: string,       // optional; use in your click handler if you want to navigate\n      isNew?: boolean      // optional; displays a 'New' badge\n    }\u003e\n  }\u003e\n}\n```\n\n## Styling\nThe component uses SCSS for styling. Styles are automatically included when you import the component. The sidebar includes:\n- Clean, minimal design\n- Responsive layout\n- Title with separator line\n- Hover effects on interactive items\n- Proper spacing and typography\n\nTo customize styles, you can override the CSS classes:\n```css\n.tv-sidebar-body {\n  /* Container styles */\n}\n\n.tv-sidebar {\n  /* Main sidebar styles */\n}\n\n.tv-sidebar-title h1 {\n  /* Title styles */\n}\n\n.tv-sidebar-content-li {\n  /* List item styles */\n}\n```\n\n## Navigation Handling\nSince the component does not perform navigation, handle it in your click handlers. Example with Vue Router:\n```vue\n\u003cscript setup\u003e\nimport { TvSidebar } from '@todovue/tv-sidebar'\nimport { useRouter } from 'vue-router'\n\nconst router = useRouter()\n\nconst listData = {\n  title: 'Recent Posts',\n  list: [\n    { id: 1, title: 'Getting Started with Nuxt 3', link: '/blog/nuxt-3' },\n    { id: 2, title: 'Vue Composition API', link: '/blog/composition-api' }\n  ]\n}\n\nfunction handleClick(item) {\n  if (item?.link) router.push(item.link)\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cTvSidebar :data=\"listData\" @click=\"handleClick\" /\u003e\n\u003c/template\u003e\n```\n\n## Accessibility\n- Semantic structure with clear headings\n- Alt text support for images\n- Interactive items emit click events; if you need keyboard accessibility, consider handling `keydown` (Enter/Space) on your side or wrapping with accessible elements/roles\n- Color contrast considerations for labels\n\n## SSR Notes\n- No direct DOM access (`window` / `document`) → safe for SSR\n- Compatible with Nuxt 3 out of the box\n- Styles are bundled and auto-imported\n- No router/nuxt-link dependency inside the component\n\n## Development\n```bash\ngit clone https://github.com/TODOvue/tv-sidebar.git\ncd tv-sidebar\nnpm install\nnpm run dev     # run demo playground\nnpm run 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## Dependencies\n- `vue` (^3.0.0) - Peer dependency\n- `@todovue/tv-label` - Used for category/label display mode\n\n### Attributions\nCrafted with ❤️ for the TODOvue component ecosystem by Cristhian Daza\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftodovue%2Ftv-sidebar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftodovue%2Ftv-sidebar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftodovue%2Ftv-sidebar/lists"}