npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mlightcad/ribbon

v0.1.10

Published

A Vue 3 + TypeScript Ribbon UI component library aligned with Syncfusion Ribbon concepts, implemented on top of Element Plus.

Readme

ML Ribbon (Vue3 + Element Plus)

A Vue 3 + TypeScript Ribbon UI component library aligned with Syncfusion Ribbon concepts, implemented on top of Element Plus.

Ribbon

Live Demo

What This Project Provides

  • Ribbon container/state orchestration (MlRibbon)
  • Tabs, groups, collections, and item host composition
  • Advanced Ribbon-only items:
    • MlRibbonButton
    • MlRibbonButtonGroup
    • MlRibbonDropdown
    • MlRibbonSegmented
    • MlRibbonToggleButton
    • MlRibbonGallery
    • Schema-driven custom items for embedding host Vue components in groups
    • MlRibbonTemplateItem
  • File menu and backstage shells; file menu items support optional nested children (hover right-start submenus; @file-menu-select emits the chosen leaf item id)
  • Contextual tabs and key tips overlays
  • Runtime dynamic API for tab/group/item mutations
  • Size unification with Element Plus (large/default/small) via MlRibbon size prop or global ElConfigProvider
  • Theme alignment with Element Plus light/dark mode (via html.dark class)
  • Internationalization-ready UI text model via MlRibbon texts prop (no built-in hard-coded visible strings in Ribbon components)
  • Icon-only command rendering via RibbonItemModel.hideLabel
  • Per-item tooltip support via RibbonItemModel.tooltip; when omitted, the item label is used as the tooltip fallback
  • Global tooltip timing control via MlRibbon tooltip-show-after and tooltip-hide-after
  • Grouped command buttons via buttonGroup items; each button remains a stateless command, emits its own option value, and supports independent tooltip text via option.tooltip
  • Dense command-row configuration for buttonGroup: set hideLabel: true, props.wrap: false, and optional props.buttonSize; by default button width follows content, set props.equalWidth: true to force equal widths
  • Two-state toggle commands via toggle items with props.modelValue, activeIcon, and inactiveIcon
  • comboBox width configuration via props.width/props.comboWidth (supports 'full'), plus optional props.emitValueOnChange payload mode
  • MlRibbonInputNumber / inputNumber items based on Element Plus Input Number, with props.width/props.inputNumberWidth, native min/max/step/controlsPosition props, optional props.emitValueOnChange, and compact props.prefixLabel/props.prefixIcon
  • Large button multi-line label support via props.labelWrapLines and optional props.labelWrapWidth
  • Controlled segmented selectors via segmented items with props.modelValue; options render icon-first and fall back to text only when no icon exists; each option supports its own tooltip via option.tooltip (with label/value fallbacks like buttonGroup)
  • Gallery items support standard text previews, Vue/CSS icon previews, SVG preview references, per-item custom Vue components or the MlRibbonGallery #item slot, plus a picker panel for overflow items and collapsed large-button mode for tight ribbon widths; schema gallery items accept props.inlineItemLimit (inline slots before overflow) and props.inlineItemWidthMode: 'fixed' | 'auto' (auto widens columns from the default minimum to fit labels and text previews; default fixed)
  • Group footer command popover via RibbonGroupModel.footerMenuItems
  • Group width is auto-sized when RibbonGroupModel.width is omitted; provide width for a fixed pixel width
  • Dropdown command memory: selected option updates trigger icon, icon click executes current option command, label/arrow opens menu; set props.syncLabelWithSelection = true to also update label
  • Dropdown menu separators: per-option divided: true on RibbonDropdownOption maps to Element Plus ElDropdownItem divided, drawing a horizontal rule above that row (for example before a trailing “Other…” / character-map entry)
  • Customizable tab-right extension area via MlRibbon #tabs-extra slot
  • Custom Vue components can be mounted directly from the ribbon schema with type: 'custom', props.component, and props.componentProps
  • Custom ribbon controls can reuse MlRibbonButton and MlRibbonDropdown for consistent icon, label, dropdown, theme, and size behavior.

Naming Conventions

  • Component names use Ml prefix.
  • CSS classes use ml- prefix.

Tech Stack

  • Vue 3
  • TypeScript
  • Vite
  • Element Plus
  • Vitest + Vue Test Utils
  • Playwright

Quick Start

pnpm install
pnpm dev

Consumer projects need to install peer dependencies explicitly:

pnpm add vue element-plus @element-plus/icons-vue

Component Usage

1. Import

import { MlRibbon } from '@mlightcad/ribbon'
import '@mlightcad/ribbon/style.css'
import type { RibbonTabModel } from '@mlightcad/ribbon'

2. Basic Example

<script setup lang="ts">
import { ref } from 'vue'
import { MlRibbon } from './src/ribbon'
import type { RibbonLayout, RibbonTabModel } from './src/ribbon'

const activeTab = ref('home')
const layout = ref<RibbonLayout>('classic')
const minimized = ref(false)
const ribbonDisabled = ref(false)

const tabs = ref<RibbonTabModel[]>([
  {
    id: 'home',
    title: 'Home',
    groups: [
      {
        id: 'clipboard',
        title: 'Clipboard',
        collections: [
          {
            id: 'clipboard-actions',
            items: [
              { id: 'paste', type: 'button', label: 'Paste', size: 'large' },
              {
                id: 'copy',
                type: 'button',
                label: 'Copy',
                tooltip: 'Copy selection',
                size: 'small',
              },
              {
                id: 'grid-snap',
                type: 'toggle',
                label: 'Grid Snap',
                props: {
                  modelValue: true,
                  activeValue: 'grid-snap-on',
                  inactiveValue: 'grid-snap-off',
                  activeIcon: 'ml-icon-grid-snap-on',
                  inactiveIcon: 'ml-icon-grid-snap-off',
                },
              },
            ],
          },
        ],
      },
    ],
  },
])

function handleItemClick(payload: {
  tabId: string
  groupId: string
  itemId: string
}) {
  console.log('Ribbon item clicked:', payload)
}
</script>

<template>
  <MlRibbon
    v-model:active-tab="activeTab"
    v-model:layout="layout"
    v-model:minimized="minimized"
    :disabled="ribbonDisabled"
    :tabs="tabs"
    @item-click="handleItemClick"
  />
</template>

3. Common Props

  • tabs: RibbonTabModel[] Ribbon data source (required)
  • v-model:active-tab active tab id
  • v-model:layout ribbon layout (classic | simplified)
  • v-model:minimized minimize state
  • disabled disables the full ribbon interaction surface
  • size uses Element Plus size (large | default | small)
  • hide-layout-switcher whether to hide layout switcher, default false
  • hide-minimize-button whether to hide minimize button, default false
  • hide-key-tips-toggle whether to hide key tips toggle, default false
  • show-file-menu whether to show file menu, default true
  • show-open-backstage whether to show Open backstage command in File menu, default true
  • file-menu-items FileMenuItemModel[] — each item has id, label, optional disabled, and optional recursive children for hover submenus (see §4.5)
  • texts localized UI text overrides
  • tooltip-show-after global tooltip show delay in milliseconds, default 1000
  • tooltip-hide-after global tooltip hide delay in milliseconds, default 0

4. Common Events

  • @tab-change="(tabId) => {}" tab switched
  • @layout-change="(layout) => {}" layout switched
  • @item-click="({ tabId, groupId, itemId }) => {}" item clicked
  • @file-menu-select="(id) => {}" file menu command selected
  • @overflow-open / @overflow-close
  • @backstage-open / @backstage-close

4.1 Tab-Right Custom Slot

Use #tabs-extra to render custom controls at the far-right side of the ribbon header (for example language switchers). Slot props include activeTab, layout, minimized, and disabled.

<MlRibbon :tabs="tabs">
  <template #tabs-extra="{ disabled }">
    <MyLanguageSwitcher :disabled="disabled" />
  </template>
</MlRibbon>

Contextual tabs support two interaction modes through RibbonTabModel.contextualMode:

  • selection keeps regular tabs and their commands interactive while selection-specific UI is visible.
  • exclusive keeps tab headers selectable but disables command content in all non-exclusive contextual tabs, which is useful while creating or editing a modal object.

Optional RibbonTabModel.contextualTitle: when set to a non-empty string, a small label is shown above that contextual tab’s colored block; if omitted, only the tab strip (with title) is shown—there is no default block label.

4.2 Custom Backstage Slot (Recommended)

Use #backstage to fully customize backstage content.

Slot props:

  • close: close backstage panel
  • open: current backstage open state
  • size: current ribbon size (large | default | small)
  • backLabel, title, description: default backstage text data
<MlRibbon :tabs="tabs" :file-menu-items="fileMenuItems">
  <template #backstage="{ close, size }">
    <section :class="`ml-my-backstage ml-my-backstage--size-${size}`">
      <button type="button" @click="close">Back</button>
      <h2>My Backstage</h2>
      <p>Render any custom UI here.</p>
    </section>
  </template>
</MlRibbon>

4.3 Custom Vue Components Inside Groups

Use type: 'custom' to mount a host component directly from your ribbon schema. The custom component receives:

  • item
  • groupId
  • disabled
  • emitItemClick(payload?)
<script setup lang="ts">
import MyInspectorCard from './MyInspectorCard.vue'

const tabs = [
  {
    id: 'home',
    title: 'Home',
    groups: [
      {
        id: 'inspector',
        title: 'Inspector',
        collections: [
          {
            id: 'inspector-main',
            items: [
              {
                id: 'selection-panel',
                type: 'custom',
                size: 'large',
                props: {
                  component: MyInspectorCard,
                  componentProps: {
                    title: 'Selection',
                  },
                },
              },
            ],
          },
        ],
      },
    ],
  },
]
</script>

4.4 Dropdown option dividers

MlRibbonDropdown / schema type: 'dropdown' items accept props.options entries shaped as RibbonDropdownOption. Set divided: true on an option to show a divider line above that item (same behavior as Element Plus divided on el-dropdown-item).

{
  id: 'symbols',
  type: 'dropdown',
  label: 'Symbol',
  props: {
    icon: MySymbolIcon,
    options: [
      { value: 'sym-degree', label: 'Degree' },
      { value: 'sym-diameter', label: 'Diameter' },
      { value: 'sym-other', label: 'Other…', divided: true },
    ],
  },
}

4.5 Nested file menu items

Pass file-menu-items as FileMenuItemModel[]. Items with a non-empty children array render as hover submenus to the right; leaf items without children behave like plain commands. @file-menu-select always receives the selected leaf command id (parents with children do not emit on their own).

import type { FileMenuItemModel } from '@mlightcad/ribbon'

const fileMenuItems: FileMenuItemModel[] = [
  { id: 'new', label: 'New' },
  { id: 'open', label: 'Open' },
  {
    id: 'export',
    label: 'Export',
    children: [
      { id: 'export-dxf', label: 'Export to DXF' },
      { id: 'export-pdf', label: 'Export to PDF' },
    ],
  },
]
<MlRibbon :tabs="tabs" :file-menu-items="fileMenuItems" @file-menu-select="onFileMenuSelect" />

5. Dynamic Runtime API (Component Ref)

MlRibbon exposes RibbonDynamicApi via ref, allowing runtime mutations:

  • Tab operations: addTab, removeTab, showTab, hideTab, selectTab
  • Group operations: addGroup, removeGroup, showGroup, hideGroup
  • Item operations: addItem, removeItem, updateItem, enableItem, disableItem
  • Layout operations: refreshLayout, minimize, toggleSimplified

Scripts

pnpm dev
pnpm build
pnpm build:demo
pnpm test
pnpm test:watch
pnpm test:e2e
pnpm preview
  • pnpm build: library build (src/ribbon/index.ts) with vue and element-plus externalized.
  • pnpm build:demo: demo app build from index.html.

Project Structure

src/
  ribbon/
    components/    # MlRibbon core structure components
    items/         # advanced ribbon-only items
    modules/       # file menu/backstage/keytips/contextual tabs
    composables/   # state and runtime api logic
    styles/        # ml-prefixed styles
    index.ts       # public exports
docs/
  requirements.en.md
AGENTS.md

Documentation

  • Requirements document: docs/requirements.md
  • Agent coding conventions: AGENTS.md

Current Status

  • V1 baseline is implemented and buildable.
  • Core APIs and tests are available.
  • Key tips now support Alt activation, sequence matching, and command dispatch via itemClick.