Repository navigation
v1.0.0
Major Changes
-
#138
c150389- Stop generating IDs for items without one: theiridis nowundefinedinstead of a positional ID like'1-0'. Give an item anidif you look it up by ID. The positional ID moves to the newkeyproperty. -
#311
999feaf- Size label plates to their text instead of a fixed 120 px width. Set--mm-plate-min-widthand--mm-plate-max-widthto120pxto keep the fixed, truncated width. Plates also default to more padding and rounder corners, with no square corner toward the center. -
#273
2381311-createMarkingMenuthrows when items in a level are less than 45° apart, such as a level with more than 8 items, because directions that close together can't be told apart. Move extra items into submenus, or space stated angles at least 45° apart. -
#233
ab83b8b-createMarkingMenureturns a controller instead of an RxJSObservable, so you no longer installrxjs. The menu is active as soon as you create it. Listen withon(type, listener), and stop the menu withdispose()orusing.// 0.10.1 const subscription = MarkingMenu(items, parent).subscribe((selection) => { console.log(selection.name); }); subscription.unsubscribe(); // 1.0 const menu = createMarkingMenu({ items, parent }); menu.on('select', (event) => console.log(event.selection.label)); menu.dispose();
The controller emits
start,open,move,change,select, andcancelevents, exported as classes such asMarkingMenuSelectEvent. Their fields are getters, so spreading an event orJSON.stringify()doesn't copy them. They replace thenotifyStepsoption, with these differences:drawbecomesmove,movealso fires alongsidechange,cancelhas noselection,activeis nowactiveItemand only onmove,change, andcancel, and no event hastimeStamp.menu.statereports what the menu is doing between events:modeisidle,startup,expert,novice, orstandalone, andnoviceandstandalonealso carry the displayedmenuand theactiveItem. Inside a listener it already reflects the event being dispatched. The package exports the newMarkingMenuStatetype.menu.open()displays the menu without a gesture. Mouse, touch, pen, and keyboard all operate it, andmenu.close()closes it. Pass{ position }, in viewport pixels, to center it somewhere other than the parent's center. Events from such a menu havemode: 'standalone', and, like novice mode, firemoveon pointer movement. Every event has asource:'pointer','keyboard','gesture'(drawing a mark),'api'(anopen()orclose()call, or the focusopen()gives the first item), or'focus-loss'(the menu lost focus).positionis a viewport point whensourceis'pointer', andundefinedotherwise. Checksource, notmode, to know which. When a stroke was recognized,open,select, andcancelevents have arecognitionwith the stroke and how it was cut into corners and segments.cancelevents have areason:no-selection,interruptedwhen the browser cancels the pointer, ordismissedwhen a menu shown withopen()is closed. The package exports the newMarkingMenuCancelReason,MarkingMenuEventSource,MarkingMenuOpenOptions,MarkingMenuRecognition,MarkingMenuStrokeAnalysis, andMarkingMenuStrokeSegmenttypes. -
#144
1580c6e- Ship only an ES module. The UMD build is gone, with its CommonJS, AMD, andwindow.MarkingMenuglobal loading. Every supported browser loads ES modules natively: useimportor<script type="module">. -
#260
195d2dd- Spread items evenly around the circle for every item count. Menus with 2, 3, 5, 6, or 7 items change: 3 items sit 120° apart instead of 90°. A learned gesture can now select a different item, without any error. Set each item'sangleto keep its old direction. -
#138
c150389- Replace theisLeaf()andisRoot()item methods withisLeafandisRootproperties. -
#138
c150389- Items expose their fields through getters instead of own properties, so spreading an item,Object.keys(), orstructuredClone()no longer copies them. Read the fields you need explicitly. -
#126
5a46547- Rename the itemnameproperty tolabel, andgetChildrenByName()togetChildrenByLabel(). -
#277
ca594cd- Raise the defaultsubmenuOpeningDelayfrom 100 ms to1000 / 3ms, the same asnoviceDwellingTime, so opening a submenu takes the same pause as opening the menu. SetsubmenuOpeningDelay: 100to keep the old delay. -
#118
80d15d6- Require Chrome and Edge 111, Firefox 115, or Safari and iOS 16.4, or newer. Dark mode colors, which you opt into withcolor-scheme, need Chrome and Edge 123, Firefox 120, or Safari 17.5. Firefox 115 to 118 don't expose the menu's accessibility roles. -
#138
c150389- Replace the default export with the namedcreateMarkingMenuexport:import { createMarkingMenu } from 'marking-menu'. -
#262
3d2d200- Render labels as plain text instead of HTML, so a label can't inject markup into the page. A label containing HTML now shows the tags as text. Labels are text only. -
#126
5a46547- Remove the string shorthand for menu items, so every item has the same shape. Write{ label: 'Copy' }instead of'Copy'. -
#126
5a46547- Pass a single configuration object instead of positional arguments:createMarkingMenu({ items, parent, ...options })instead ofMarkingMenu(items, parent, options). -
#138
c150389- The root has noid,label, orangleinstead of having them set tonull. -
#302
6ca5e42- Render the menu in an open shadow root on the.marking-menuelement, so page styles, such as abox-sizing: border-boxreset, can't break its layout. Page CSS can no longer reach the menu's inner elements, and the theme properties are renamed to--mm-*, set on.marking-menu. Check the documentation for the replacements. -
#277
ca594cd- ReplaceminSelectionDist(default 40) andminMenuSelectionDist(default 80) with onedeadZoneRadiusoption (default 40). An item becomes active past this radius, and pausing on it opens its submenu. Before, a submenu only opened pastminMenuSelectionDist. RenameminSelectionDisttodeadZoneRadiusand removeminMenuSelectionDist; JavaScript silently ignores the old names. -
#383
1c836d8- In novice mode, move focus to the menu and then to the active item, so screen readers announce it. Focus returns where it was when the gesture ends. The focused element getsblurandfocusoutevents during the gesture.A menu shown with
menu.open()takes focus the same way. Each arrow key moves focus that way around the ring rather than along the item order, so the key you press matches the direction you see. Home and End jump to the ends of the item order, Enter selects a leaf or opens a submenu, Escape goes back up a level or closes the menu from the root, and Tab closes it from any level. It also closes when focus moves elsewhere, leaving focus there. Pass{ autoFocus: false }to open it without moving focus; it closes on focus loss only after focus enters it. Entering a submenu always leaves focus in the menu.openevents carrywillAutoFocus,falseonly for a menu opened this way. -
#474
6db62d0- A menu shown withmenu.open()now also answers the mouse, touch, and pen, alongside the keyboard, and shows a pointer cursor over its items. Hovering an item makes it active without moving focus, and moving off the menu clears it. Clicking a leaf selects it and clicking a submenu item opens it, both giving focus to the new level. Clicking outside the menu, or releasing a drag there, dismisses it. -
#319
f90a2db- Replace the nine stroke options, such asstrokeColorandlowerStrokeWidth, with--mm-stroke-*custom properties, so you style strokes in CSS like the rest of the menu. Check the documentation for the replacements. -
#138
c150389- Renamechildrentoitems, on the items you pass and on the items the menu returns, to match the top-levelitemsoption. Items without sub-items returnitems: []instead ofundefined. -
#124
de5942f- Rename thesubMenuOpeningDelayoption tosubmenuOpeningDelay. -
#334
3413aa3- Strokes are no longer clipped to the parent, like the menu itself. Setoverflow: hiddenon the parent to keep both inside it. The.marking-menuelement now stays in the parent until you dispose the menu, so its presence no longer means a menu is open. -
#150
c7ad8ad- Handle input with Pointer Events. Only the primary mouse button, touch, or pen starts a gesture, so right and middle clicks no longer open the menu, and a second touch no longer ends it. A gesture keeps tracking when the pointer leaves the parent, and always cancels when the browser cancels the pointer. The parent getstouch-action: noneuntil you dispose the menu, except while a menu shown withmenu.open()is displayed. Then pointer input goes to the page and no gesture starts. -
#455
6bae798- Default item positions now start at the top instead of the right: a menu level where no item states ananglespreads its items 90 degrees counterclockwise from the previous default. Levels with at least one stated angle are unaffected. A learned gesture can now select a different item, without any error. Set each item'sangleto keep its old direction. -
#410
b862390- TypeMarkingMenuLogger'sinfo,warn, anddebugas(message: string) => voidinstead ofunknown, so the library can start calling them without a later breaking change. Makeerroroptional too, matching every other method. -
#138
c150389- Require item IDs to be unique across the whole menu.createMarkingMenuthrows on duplicates, and TypeScript rejects duplicate literal IDs.
Minor Changes
-
#474
6db62d0- Add--mm-inner-connector-thickness(default0) and--mm-outer-connector-thickness(default4px) to size each connector on its own, and--mm-connector-color/--mm-connector-color-active, a shared fallback color for both connectors. -
#261
b93d497- Let items set an optionalangle, in degrees clockwise from the right. Items without one fill the gaps between stated angles. -
#290
1b2b563- Place labels so they don't overlap, instead of at one fixed distance from the center. Tune the spacing with the--mm-plate-gap-*properties. -
#370
aa25858- Expose the menu to assistive technologies with themenuandmenuitemroles. Items take their label as their name, and items with a submenu havearia-haspopup="menu". -
#386
06f9ae4- Add--mm-muted-color, the default color of earlier gesture segments. Earlier segments are lighter than 0.10.1's[#777](https://github.com/QuentinRoy/Marking-Menu/issues/777). -
#345
55d8361- Show a dot growing inside a circle during the pause before a menu or submenu opens. It fades in instead when the user prefers reduced motion. Style it with--mm-indicator-filland--mm-indicator-background. -
#382
fc6b7c5- Draw a 1px gray inset outline on wedges, blue on the active one. Change it with--mm-outline-widthand--mm-outline-color, their-activevariants, and per-part variants, which can also outline plates. -
#147
9c46198- Ship TypeScript declarations. Items in events are typed from the items you pass, so theiridandlabelnarrow to the values you wrote. -
#382
fc6b7c5- Change the default colors: wedges and plates have a pale fill with black labels, and the active item turns blue. Set--mm-filland--mm-fill-activeto recolor wedges, plates, and connectors together. Colors follow dark mode when the page declarescolor-scheme: light dark. -
#304
f8594c1- Draw a ring of wedges around the menu center, one per item. Style it with the--mm-wedge-*properties. Connectors now start at the ring; set--mm-inner-connector-colorand--mm-inner-connector-thicknessto draw them from the center.
Patch Changes
-
#188
fe933d7- Alogoption without anerrormethod falls back toconsole.error, anderroralways receives anError. -
#233
ab83b8b- After a gesture switches from expert to novice mode, events reportmode: 'novice'instead ofundefined. -
#344
7e7b3fb- Support aparentowned by another document, such as an iframe's. -
#193
a872408- Hide the cursor during gestures instead of showing a crosshair, and restore the parent's own inlinecursorafterward instead of clearing it. -
#253
7d6704b- Fix strokes drawn away from the pointer when the parent is not at the top-left corner of the viewport. -
#409
b7cbb41- Fix the submenu-opening dwell never rearming once it fires on a leaf item, so a submenu right next to that leaf could no longer open by dwelling.
All notable changes to this project will be documented in this file. Entries are generated from Changesets — see .changeset/README.md for how to add one.