File Details
v1.7.1
- R
- May 8, 2026
- 529.04 KB
- 67
- 12.0.5+4
- Classic + 3
File Name
Barshelf-v1.7.1.zip
Supported Versions
- 12.0.5
- 12.0.1
- 5.5.3
- 2.5.5
- 1.15.8
v1.7.1
Custom Micro Menu (retail)
- Roster matches Blizzard's actual retail micro menu now. Three buttons in the active list had no
MICRO_DEFSentry —ProfessionMicroButton,HousingMicroButton, andLFDMicroButton(retail and Mists Classic useLFDMicroButton; onlyLFGMicroButtonhad a def, so retail's group-finder entry silently dropped out). Added defs for all three. Order now mirrorsBlizzard_MicroMenu/Mainline/MicroMenuContainerOverrides.lua'sGenerateButtonInfosexactly, minusHelpMicroButton. - Icons cloned from the live Blizzard buttons. Previously the micro shelf rendered hand-picked
Interface\Icons\…substitutes that didn't resemble Blizzard's real artwork. NewApplyMicroIconpulls the source button's normal atlas / file texture /Portraitchild and applies it to our cloned icon — so retail picks up the realUI-HUD-MicroMenu-*-Upart and Classic gets the file textures. Vertex color is mirrored too, so dynamic tints (GuildMicroButton's tabard-color swap) carry through. - Character Info uses the player portrait. Special-cased to call
SetPortraitTexture(iconTex, "player")directly, since the source button'sPortraitis an engine-rendered model rather than a file path —GetTexture()returns nil for it, so the previous clone path silently fell back to the chrome. - Dynamic icons stay in sync. Shared event frame listens to
UNIT_PORTRAIT_UPDATE/PORTRAITS_UPDATED/PLAYER_ENTERING_WORLD(Character) andPLAYER_GUILD_UPDATE/NEUTRAL_FACTION_SELECT_RESULT/PLAYER_ENTERING_WORLD(Guild), re-runningApplyMicroIconfor any cloned icons registered for those sources. Cloned icons unregister on shelf teardown so the watch list doesn't leak. - Aspect ratio preserved. Cloned icons used to render in 18×18 (list) / 28×28 (grid) squares, but the source artwork is designed for a 29×37 button (aspect ~0.78), so forcing a 1:1 box stretched icons horizontally — visible especially on Classic. List mode now sizes icons to the row height with aspect-correct width (centered in a fixed-width column so labels still line up); grid mode fits within the cell while keeping aspect.
- Bigger, cleaner list-mode icons. Bumped
LIST_ROW_HEIGHTto 30 andLIST_ICON_SIZEto 26 so the cloned glyph reads at a comparable visual weight to the player portrait. Light 0.07/0.93 bevel trim for file textures (Classic); retail atlases keep0,1,0,1since they're chrome-free by design.
Custom Shelves
- Drop-to-swap. Dropping an action on a custom shelf slot that already had something just overwrote the existing entry — the displaced spell / item / macro silently disappeared.
HandleCustomDropnow captures the slot's prior contents and puts them on the cursor after the new action is applied, mirroring how Blizzard'sPlaceActiondisplaces existing actions onto the cursor. Drop onto an empty slot still works the same way (nothing to displace).
v1.7.0
Classic Support (Vanilla / TBC / MoP)
- Shipping Classic flavor TOCs.
Barshelf_Vanilla.toc(Interface 11508),Barshelf_TBC.toc(Interface 20505), andBarshelf_Mists.toc(Interface 50503) load the addon on the matching Classic clients. Per-flavorData_Vanilla.lua/Data_TBC.lua/Data_Mists.luacarry the right bar count, action-page IDs, and binding prefixes for each expansion. A newCompat.lualayer lifts version-specific API checks (Keyring presence, retail-only paths, etc.) out of feature code. - Fixed MultiBar action-ID collapse on Classic. All shelves used to mirror Bar 1 because Vanilla/TBC/MoP read action IDs via the secure
actionpageattribute (not retail'sactionButtonOffset).BarShelf.luanow setspopup:SetAttribute("actionpage", info.page)for static bars and subscribes toACTIONBAR_PAGE_CHANGED/UPDATE_BONUS_ACTIONBARfor dynamic Bar 1 paging — Bars 2–5 now show their own buttons. - Per-bar drag/show/scale controller (Classic only). Retail has Edit Mode; Classic doesn't.
BarOverrides.luabuilds a per-bar wrapper anchor (BarshelfBarAnchor_<id>) sized to the bounding box of each bar's action buttons, reparents the buttons into it, and applies user overrides (Show, Position, Scale) on the wrapper rather than touchingMainMenuBardirectly — so dragging "Bar 1" doesn't grab the gryphons, bags, keyring, micro menu, and XP bar with it. Right-click a wrapped bar in drag mode to jump straight to the Action Bars settings panel. - Page Controls floating widget. A draggable
^ / N / vchrome that mirrors Blizzard's classicMainMenuBarPageNumber+ActionBarUpButton/DownButton(32×32 textures with 6/6/7/7 hit-insets, page label asGameFontNormalSmall). Clicks dispatch viaSecureActionButtonTemplatemacros that/clickBlizzard's hidden up/down buttons (Bartender4 pattern) — paging works even with the bar chrome hidden. Snap to ActionButton1's left or ActionButton12's right to follow Bar 1 wherever it lives (chrome shown, chrome hidden, or shelved); free-drag otherwise. Combat-deferred build: if combat blocksSecureActionButtonTemplatecreation, the widget mounts onPLAYER_REGEN_ENABLED. - Quick keybind mode. Bartender / Edit-Mode style hover-and-press. Toggle from Action Bars; mouse over any action button and press a key to bind it (modifiers supported).
SetOverrideBindingClickfor the live capture,SaveBindings(GetCurrentBindingSet())to persist. Auto-disables when entering combat (PLAYER_REGEN_DISABLED) so capture frames never taint protected paths. - Custom micro menu for Classic. Retail's
MicroMenuwidgets don't ship on Classic, so the legacy plate-style detection had to be rebuilt. Two layouts (list / grid). List rows render[icon] Label (Keybind)— keybind read live viaGetBindingKey(action)and formatted withGetBindingText. Selectable from the Micro Shelf settings.
New Features
- Keyring shelf. A clickable shelf type (Vanilla / TBC / Wrath only — gated on
Compat.has.Keyring) that opens Blizzard's keyring container. The Bag Shelf popup also includes a custom keyring slot that uses Blizzard's native vertical-pouch art (Interface\Buttons\UI-Button-KeyRingwith the correctSetTexCoordcrop) and scales to match the popup's bag-slot height. Keyring code is no-op on retail/Cataclysm+ where the feature was removed. - Latency widget on the status shelf. Reports world / home latency via
GetNetStats(). - Action Bars settings panel. Consolidates Hide Chrome, Drag Mode, Quick Keybind, Show Page Controls (+ snap dropdown), and per-bar Show/Hide checkboxes. Sits above Shelves & Docs in the settings tree.
- Handle font and label color are configurable via LibSharedMedia-3.0 (now embedded under
Libs/). Install the SharedMedia addon to expand the font dropdown beyond the client built-ins. Color picker defaults to gold to match Blizzard's standard label palette;SetFontfalls back to Friz Quadrata if the configured path fails to load. - Handle alignment (LEFT / CENTER / RIGHT). RIGHT mirrors the icon to the right side of the handle instead of the label, matching the handle's visual direction.
- Popup open direction is auto-picked.
Popup.luapicks the direction perpendicular to the dock's axis (top/bottom for horizontal docks, left/right for vertical docks) with the most margin, falling back to the parallel axis only when neither perpendicular side fits. Replaces the previous orientation-only logic so a vertical dock pinned to the bottom-right opens up-left, and a bottom horizontal dock opens up rather than sideways. - Vertical-dock drag grip is rotated. A vertical dock now renders the 3×2 portrait grip pattern; horizontal docks keep the 2×3 landscape pattern.
- Bag Shelf bag slots feature with
/bs debug bagslash diagnostic for inspecting per-slot state. - Per-shelf popup-trigger override (click vs. hover) on top of the global default. The global
Popup Trigger,Display Mode, andHandle Alignmentdefaults moved from Appearance to General → Shelf Defaults.
Bug Fixes
- Retail:
MultiBarBottomLeftButton*Cooldown:SetCooldownblew up withSecret values are only allowed during untainted executionafter activating any bar 2-5 shelf.ActivateBarShelfreasserted both the barebutton.actionfield and the protectedSetAttribute("action", ...)on each reparented button. The bare-field write is harmless; the SetAttribute write taints the SecureActionButton on retail because "action" is a protected attribute, and the taint propagates into Blizzard's ownActionButton_ApplyCooldown→cooldown:SetCooldownthe next time a cooldown event fires. The reassertion was added as a Classic-only fix (Classic clients sometimes leavebutton.actionstale from a hidden-bar init) — gated toCompat.isClassicso retail'sparentBar.actionButtonOffsetis the only mechanism touching protected state. - Retail: Bar 1 froze (no slot updates, no visibility changes) and
ADDON_ACTION_BLOCKED: Barshelf tried to call the protected function 'MainActionBar:SetShownBase()'fired on zone changes / mounts / spec swaps.ActivateBarShelfwroteparentBar.actionButtonOffset = info.offseton every reparent, which taints the bar —actionButtonOffsetis read by the bar's secure update path, and once an addon writes it from insecure code the bar is marked tainted. The nextActionBarController_UpdateAllcall hitsbar:Show()→UpdateVisibility()→SetShownBase()and the protected method refuses, freezing the bar in whatever state. The write was originally added as a Classic-only fix (Classic re-derivesbutton.actionfromparentBar.actionButtonOffsetper event); on retail Blizzard setsactionButtonOffsetitself per bar via Edit Mode. Gated toCompat.isClassic. The popup-side write (shelf.popup.actionButtonOffset = info.offset) stays for both flavors — the popup is our own frame and writing to it doesn't taint anything; reparented buttons resolve their action ID against the popup as the new parent. - Retail: clicking any shelved action button raised
ADDON_ACTION_FORBIDDEN: Barshelf tried to call the protected function 'UseAction()'.ActivateBarShelfalways setpopup:SetAttribute("actionpage", page)and subscribed toACTIONBAR_PAGE_CHANGEDto re-write it. That attribute is a Classic-only mechanism (useparent-actionpage = truecausesActionButton_CalculateActionto read it from the parent chain). Retail's SecureActionButton click handler still walks the parent chain to resolve action attributes for the click, so finding our insecurely-writtenactionpagetaints the click context —UseActionthen refuses to fire. Gated the entireactionpageblock (and the matching cleanup inDeactivateBarShelf) toCompat.isClassic. Retail usesparentBar.actionButtonOffsetexclusively. - Mouseout on hover-trigger shelves was unreliable.
OnLeave+ 0.2s timer regularly missed the cursor leaving the popup. Replaced with anOnUpdatewatcher that pollsIsMouseOver()until the cursor has been off for 0.2s straight. - Custom shelf list-mode mouseover effect was stretched. The action-button highlight texture filled the whole row instead of just the icon. Highlight now anchors to the icon's
bsz × bszbox in list layout. - Micro menu items rendered outside the popup container after the layout pass. Reverted to TOPLEFT cell layout with
cellH = maxH; a watchdog re-runsLayoutMicroPopupif Blizzard reparents any micro button between frames. - Right-click on a wrapped bar in drag mode opens the BarShelf options to the Action Bars panel (was: nothing).
- Removed third-party addon name from comments and UI so the addon stands on its own.
Removed
- Hardcoded font fallback table in the font dropdown — LSM is now always embedded and returns the same client built-ins, so the duplicate hardcoded list was dead code.
v1.6.0
New Features
- Transmog outfits can be dropped onto custom shelf slots. Drag any saved outfit out of the Wardrobe (cursor type
outfit) onto a custom shelf slot to bind it to a/outfit <index>macro — clicking the slot equips the outfit, just like dragging it to the action bar. Tooltip shows the outfit name; the slot uses the outfit's icon. Shift-drag picks the outfit back up onto the cursor viaC_TransmogOutfitInfo.PickupOutfit. The slash command was added in 12.0.5, so this requires that patch or newer. - Outfit slots stay in sync when the player reorders or deletes outfits. The
/outfitslash command consumesplayerFacingOutfitIndex, which shifts whenever the outfit list changes;outfitIDis the only stable handle. RegisteredTRANSMOG_OUTFITS_CHANGEDand re-resolve the macrotext fromoutfitIDfor every outfit slot when the event fires (queued for combat exit if needed).
v1.5.3
Bug Fixes
- Toy cooldowns never showed on a custom shelf.
Barshelf:UpdateCustomCooldownqueriedC_Item.GetItemCooldown(itemID)forbc.type == "item", but toys aren't in the player's bags or equipped slots — they live in the Toy Box — so that API reports0, 0, 0for toys regardless of the real cooldown state. The shared toy timer lives on the toy's spell (the one Blizzard's secure click handler triggers viaUseToy). The item branch now falls back toGetItemSpell(itemID)→C_Spell.GetSpellCooldown(spellID)when the item path found nothing — toys now display their cooldown swirl, and real items (potions, trinkets, equipped gear) keep using the item-cooldown API as before.
v1.5.2
Bug Fixes
QueueStatusFrame:SetHeighthook tainted the addon (and Titan Panel) withattempt to perform arithmetic on local 'h' (a secret number value, while execution tainted by 'Titan'). v1.4.6 hooksQueueStatusFrame:SetHeightto reserve room at the bottom of the queue tooltip for the "Shift-drag the eye to move" hint. On 12.0.5,QueueStatusFrame:Update(Blizzard_QueueStatusFrame/Mainline/QueueStatusFrame.lua:752) sums queue-entry heights intototalHeightand passes that toSetHeight— and when the queue contains hidden data (Raid Finder etc.) the entry heights are secret values, so ourh + HINT_PADDINGpropagated taint up the call chain. Both the hook and the immediate-bump call site now guard withissecretvalue(h)and skip the bump when the height is secret. The hint may briefly overlap content during those queue states, but the bump resumes on the next non-secretSetHeight.
v1.5.1
Bug Fixes (Patch 12.0.5)
- Main action bar always visible after the buttons are reparented onto a shelf.
MainActionBar(the 12.0.5 frame, formerlyMainMenuBar) carries decorative children —BorderArt,EndCaps(gryphons), andActionBarPageNumber— that live on the bar frame independently of the buttons. v1.4.7's "the bar's ButtonContainer children are empty and it renders nothing" assumption only held for the buttons themselves; the chrome stayed visible at the bottom of the screen.ActivateBarShelfnow hides those three elements directly and setsbar.hideBarArt = true(a runtime flag, not the user's saved Edit Mode setting). Originals are captured per-shelf and restored inDeactivateBarShelf. - Bar UI fragments stuck wherever the first shelf opened.
MainActionBarMixin:UpdateDividers(Blizzard_ActionBar/Shared/MainActionBar.lua) anchors each divider directly to anactionButtonviaSetPoint("TOP", actionButton, "TOP", 0, 0). Once a button is reparented into our popup, the divider — still a child of the bar — renders at the popup's location instead of the bar's. Settingbar.hideBarArt = truemakesUpdateDividersearly-return after itsReleaseAllcall, so existing dividers are released and no new ones are created while the shelf owns the bar. - Group finder eye flickering and drifting across the screen. v1.4.6 fixed this by hooking
QueueStatusButton:SetParentto catch Blizzard's vehicle/zone/stance reparent flow. 12.0.5 added a second path:MicroMenuMixin:Layout(Blizzard_MicroMenu/Shared/MicroMenuContainer.lua) →UpdateQueueStatusAnchors→QueueStatusButton:UpdatePosition(Blizzard_QueueStatusFrame/Mainline/QueueStatusFrame.lua), which runsClearAllPoints+SetPoint(point, MicroMenu/MicroMenuContainer, ...)without ever callingSetParent. The SetParent hook missed it entirely, and everyMicroMenu:Layoutpass (there are many) re-anchored the eye to the hidden MicroMenu/Container, leaving the visible glyph drifting wherever Blizzard's last anchor target landed. Added a secondhooksecurefunconQueueStatusButton.UpdatePositionthat overrides the anchor back to the saved UIParent point after Blizzard's pass. BAR_INFO[1].framepointed at the removedMainMenuBarglobal. Updated toMainActionBarso the bar-art-hide path above can resolve the right frame on 12.0.5. The reference was previously dead-stored on the shelf, so this was silent.
v1.5.0
Rebrand: Barshelf → BarShelf
- User-visible name is now BarShelf (camel case) everywhere it appears to players: the Blizzard Settings canvas category, the AceConsole chat prefix (
NewAddonname), the LibDataBroker object + LibDBIcon registration key, the Masque group name, the minimap tooltip, the empty-dock hint, chat error lines, and the## Titlein the TOC. The Lua tableBarshelf, theBarshelfDB/BarshelfGlobalDBsaved-variable names, the frame globals (BarshelfDock_*,BarshelfHandle_*,BarshelfBackdrop, etc.), the.pkgmetapackage folder name, andBarshelf.tocstay lowercase — renaming any of those would cascade through every call site and / or break existing user data. - Users with an existing Masque skin on the
Barshelf / Custom Shelvesgroup will need to re-pick the skin under the newBarShelf / Custom Shelvesgroup. Minimap visibility persists viadb.profile.minimap(the LDBI key is in-memory only).
Patch 12.0.5 compatibility
- TOC Interface bumped to
120001, 120005so the addon loads cleanly on both current retail (12.0.1) and the 12.0.5 PTR / Apr 21 live patch without the "Out of Date" warning. - Added
HousingMicroButtonto the micro menu shelf. Blizzard added the Housing Dashboard button in 11.2.7 and it's still present in 12.0.5'sBlizzard_MicroMenu/Mainline/MicroMenuContainerOverrides.lua → MicroMenuMixin:GenerateButtonInfos. Users running a micro shelf lost access to it because it wasn't inMICRO_BUTTON_NAMES. Inserted afterQuestLogMicroButtonto match Blizzard's native order. - Removed obsolete
SpellbookMicroButtonandTalentMicroButtonentries fromMICRO_BUTTON_NAMES. Both were consolidated intoPlayerSpellsMicroButtonduring Dragonflight/TWW and no longer exist as globals — they were silently skipped anyway. - Cooldown handling in
CustomShelf.luaalready usesissecretvalue()guards andpcall, so the tightened secret-value rules in 12.0.5 (newCooldown:SetCountdownFormatter/SetCountdownMillisecondsThreshold, aura-field secrecy refinements,UnitNameno longer accepting secret unit tokens) do not affect the addon — the onlyUnitNamecall passes"player".
New Features
- Empty-dock hint styled like a shelf handle. A brand-new profile (or any dock whose shelves are all deleted) now renders a grip + BarShelf logo +
"BarShelf: right-click to configure"hint — laid out byLayoutHandleswith the same grip / icon / label geometry used for populated handles — instead of collapsing to a tiny unlabeledSetSize(10, 10)square in the middle of the screen.CreateDockcallsLayoutHandlesat the end of construction so the hint renders on fresh installs whereAddShelfis never called. - Right-click-to-configure on any dock.
CreateDockwires anOnMouseUphandler that, onRightButton, callsBarshelf:openOptions("Shelves & Docks", nil, self.config.id)— so right-clicking an empty dock or the padding / grip area of a populated dock opens the options panel with that dock preselected.openOptionsgained an optionaldockIDparameter that writesselectedDockbefore routing to the Shelves & Docks subcategory. - Per-dock "Enabled" checkbox. Each dock's detail panel has an Enabled checkbox (with an
OnEntertooltip explaining "Uncheck to hide this dock and its shelves without deleting them" — replacing the cramped inline description text). Unchecking skips the dock and all of its shelves inRebuildAll/OnEnable— Blizzard's bars stay where they are, the micro menu / bag / status shelves don't reparent anything, and the config is preserved for re-enabling. This gives users a "hide without deleting" option, including for the default dock 1. Disabled docks render inGameFontDisablewith a" (hidden)"suffix in the tree view.
Bug Fixes
- Dock and handles rendering above the Blizzard Settings panel.
CreateDock/CreateHandleusedSetFrameStrata("DIALOG"), which meant right-clicking an empty dock to open options left the dock still floating on top of the Settings window. Both are now at"MEDIUM"— alongside action bars and the minimap in the HUD layer. Popups keepDIALOGso opened shelves still render above the HUD.
v1.4.7
Bug Fixes
- Empty bar shelf slots still blinking on popup open: v1.4.5's fix introduced a deferred
C_Timer.After(0, ...)wrapper around the empty-slotHide()in theOnShowhook (to guard against transiently-nilself.actionon populated buttons). That one-frame defer was the blink — Blizzard's action-button cycle wouldShow()an empty slot, our hook would wait a frame, then hide it, rendering the button for exactly one game frame each time the popup opened. Fixed by removing the entire visibility-fight stack.
Refactors
- Removed the bar shelf visibility fight loop entirely (~100 lines deleted from
BarShelf.lua). After reading Blizzard's actual source inBlizzard_ActionBar/Shared/ActionBar.lua, the architecture became clear:ActionBarMixin:UpdateShownButtonsiterates a Lua table reference (self.actionButtons), NOTButtonContainer:GetChildren(). Reparenting a button does not detach it from this table, so Blizzard's native visibility rule (numButtonsShowable AND not statehidden AND (GetShowGrid OR HasAction)) still applies to our reparented buttons and gives the correct behavior for free. Removed:RegisterStateDriver(button, "visibility", "show")and its matchingUnregisterStateDriver- The
OnShowhook that re-hid empty slots (source of the v1.4.7 blink) - The
ACTIONBAR_SHOWGRID/ACTIONBAR_HIDEGRIDevent frame (Blizzard'sActionBarMixin:ActionBar_OnEventalready handles this, routed throughself.actionButtons) - The
_barshelfDragShowingmodule flag and_barshelfManagedbutton marker - The
alwaysShowActionBarscvar check andShow()/Hide()branching inLayoutBarPopup(the cvar is legacy and not referenced anywhere in Blizzard's current UI source — the per-bar "Always Show Buttons" Edit Mode checkbox is the real mechanism, and it propagates to reparented buttons via theshowgridattributeREASON_CVARbit throughEditModeActionBarSystemMixin:UpdateSystemSettingAlwaysShowButtons→ActionBarMixin:SetShowGrid→UpdateShownButtons)
- All six native scenarios verified in-game: populated slots always visible, empty slots hidden by default, drag grid shows/hides correctly, per-bar "Always Show Buttons" propagates through the popup, Edit Mode transitions are clean, combat in/out is taint-free.
v1.4.6
Bug Fixes
- LFG eye saved position wasn't sticking:
OnMouseUpwas correctly writingdb.profile.queueStatusButtonPointto disk, but Blizzard's reparent flow (fired on vehicle/zone/stance transitions and other UI refreshes) doesSetParent(MicroMenuContainer); SetPoint(..., MicroMenuContainer, ...)— ourSetParenthook caught the parent change, but Blizzard's subsequentSetPointran immediately afterwards and overwrote the button's anchor back toMicroMenuContainercoordinates. The save was fine; the live position was being clobbered. TheSetParenthook now schedules aC_Timer.After(0)deferred restore that readsdb.profile.queueStatusButtonPointand re-applies it on the next frame, after Blizzard's full reparent + reposition pass. Guarded against active drags (self._barshelfMoving) so it never fights the user's in-progress move.
v1.4.5
Bug Fixes
- Empty action bar slots blinking when opening a shelf (long-standing):
LayoutBarPopupunconditionallyShow()ed every managed slot, and Blizzard'sActionBarActionButtonMixin:OnShow→UpdateAction→HideGrid→Hidecycle caused a one-frame flash of visible empty slots every time the popup opened. Most visible on non-12-slot layouts (e.g. a 3×3 bar) where internal state churn is more frequent. Now:LayoutBarPopupgatesShow()onHasAction(button.action)or thealwaysShowActionBarsCVar, matching Blizzard's native rule. A defensiveHookScript("OnShow")on each managed button also re-Hide()s empty slots that Blizzard shows outside of an active drag — same game frame, nothing renders between Show and Hide. A module-level_barshelfDragShowingflag, toggled by theACTIONBAR_SHOWGRID/HIDEGRIDhandler, lets drag-timeShowthrough. - Custom Shelf list mode broken when Masque is enabled: list mode builds a wide
rowWidth × bszbutton with the icon texture anchoredLEFTatbsz × bsz, but Masque skin definitions assume a square button andSetAllPoints(button)the Icon region — so the icon and border stretched across the entire row. Custom-shelf buttons now skip Masque registration whenconfig.layout == "list". Switching layouts triggers a rebuild, so the decision is re-made each toggle.
New Features
- Masque integration for Custom Shelves: Barshelf registers its custom
SecureActionButtons with Masque under a dedicated "Custom Shelves" group, so users can skin them independently of their main bars. Bar / Micro / Bag shelves are already skinned natively by Masque's built-in hooks forActionButton,MultiBar*,MicroButton*, and bag slots (reparenting doesn't break them), so no registration is needed there. A callback onSkinID/Scalechanges re-runs the popup layout so button-dimension changes take effect immediately. Declared via## OptionalDeps: Masquein the TOC.
v1.4.4
Bug Fixes
- Bar shelf leaving orphaned slots on the original bar:
AddBarShelfcounted visible buttons viaIsShown()andActivateBarShelfonly reparented that many, leaving any button Blizzard had hidden (e.g. via Edit Mode "Num Icons" < 12) in its originalMultiBar*ButtonContainer. WhenEditModeActionBarMixin:UpdateVisibility/UpdateShownButtonsre-ran (combat end, Edit Mode toggle, zone change), those orphaned buttons reappeared at the native bar position. Now iterates1..info.countunconditionally; managed buttons go in the popup, excess buttons are parked in a per-shelf hidden holder frame. - Visibility feedback loop with
EditModeActionBarMixin: the previous approach registered a"hide"visibility state driver on the Blizzard bar frame and hooked itsOnShowto re-call:Hide(). BecauseMultiBar*:Hide()is intercepted bySetShownOverride, Blizzard'sUpdateVisibilitywould callShowBase→ fireOnShow→ our hook →:Hide()→ recalc → loop. Removed the state driver andOnShowhook entirely; since all 12 buttons are now reparented out, the bar's containers are empty and nothing visible is left to hide. - Removed unused bar-shelf watchdog
OnUpdate: Blizzard doesn't reparent action buttons the way it reparents micro buttons (noUpdateMicroButtonsParentequivalent), so the 1 s reparent-reassert loop on each bar popup was dead weight and contributed to the "frequent polling" feel.
v1.4.3
Bug Fixes
- LFG "eye" icon disappearing with the micro menu shelf:
QueueStatusButtonis declared as a child ofMicroMenuContainerin Blizzard'sQueueStatusFrame.xml, so hiding the container also hid the Group Finder eye. The eye is now reparented toUIParentwhile a micro shelf is active and survives Blizzard'sUpdateMicroButtonsParent()via ahooksecurefunconSetParent(with reentrancy guard). Reattached to its original parent on deactivate, profile change, and Edit Mode entry.
New Features
- Movable LFG eye: Shift + left-click-drag the Group Finder eye to reposition it. Uses
OnMouseDown/OnMouseUpinstead ofOnDragStartfor instant response (no movement-threshold wait). Position persists per-profile indb.profile.queueStatusButtonPoint. Default location isBOTTOMRIGHT -40, 200. - Smart info panel anchor:
QueueStatusFrame(the queue info panel) now flips anchor based on which screen quadrant the eye is in, so it always extends toward screen center instead of flying off-screen when the eye is dragged to an edge. - Move hint in the info panel: A small "Shift-drag the eye to move" line is added to the bottom of
QueueStatusFramewhile the micro shelf is active.hooksecurefunconSetHeightreserves bottom padding so the hint never collides with Blizzard's dynamic queue content.
v1.4.2
Bug Fixes
- Action Bar 3/4/5 mapped to the wrong Blizzard bar:
BAR_INFOused the legacyMULTIACTIONBAR1..4ordering, so picking "Action Bar 5" reparentedMultiBarBottomRightButton(Blizzard's Action Bar 3) and "Action Bar 4" reparentedMultiBarLeftButton(Blizzard's Action Bar 5). Remapped indices 3/4/5 to match Edit Mode: Action Bar 3 → BottomRight, Action Bar 4 → Right, Action Bar 5 → Left. Existing saved shelves keep theirbarIDand will now show the bar their label claims.
v1.4.1
Bug Fixes
- Empty bar shelf slots not showing during drag: Reparented action buttons were missing Blizzard's
ShowGridbroadcast (sent to action bar children only). Now listens forACTIONBAR_SHOWGRID/ACTIONBAR_HIDEGRIDevents and forwardsShowGrid/HideGridto reparented buttons, keeping the internal counter in sync so empty slots stay visible while dragging. - Right mouse button stuck when entering combat: The click-outside-to-close backdrop was a
ButtonwithEnableMouse(true), consuming all mouse events including right-click even though only left-click was processed. Changed to aFramewithSetPropagateMouseClicks(true)so right-clicks always pass through to the game world.
v1.4.0
New Features
- List layout mode for custom shelves: New per-shelf "Layout" dropdown (Grid / List). List mode shows buttons in a vertical single-column layout with icon, spell/item name, and hotkey per row. Popup width auto-adjusts to label lengths (150–300px). The
# of Rowsslider is hidden in list mode.
Bug Fixes
- Shelf rename not saving: Edit boxes now save on focus-lost (blur) in addition to Enter, fixing rename inside the Blizzard Settings panel where Enter/Backspace/arrow keys were intercepted. Escape reverts to the previous value.
- Arrow/Backspace keys not working in edit boxes: Keybind capture buttons were consuming keyboard events even when not in listening mode. They now propagate keys through when inactive.
- Flyout spells silently rejected: Dragging a flyout spell (e.g. Hunter Pet Skills, Mage Portals) onto a custom shelf now shows a helpful message instead of silently ignoring the drop.
v1.3.3
Bug Fixes
- Right mouse button getting stuck: The click-outside-to-close backdrop was registering for all mouse buttons (
AnyUp), which could swallowRightButtonUpevents before the game received them — causing the right mouse button to appear stuck. Now only listens for left-click.
v1.3.2
Bug Fixes
- Cooldown taint errors in combat: Fixed "secret values are only allowed during untainted execution" errors. In 12.0.1, addon code cannot pass secret cooldown values to ANY display function (
SetCooldown,CooldownFrame_Set,SetTimeFromStart— all reject secrets from tainted code). Now usesisActive(boolean, never secret) to branch, andissecretvalue()to detect secret values before passing them. Cooldowns display normally outside combat; gracefully degrade during combat when values are secret.
v1.3.1
Bug Fixes
- Shelf rename not working: Fixed label edit box not responding to Enter/Backspace. Switched from
BackdropTemplatetoInputBoxTemplatewhich properly handles keyboard input inside the Blizzard Settings panel.
v1.3.0
New Features
- Mount support on custom shelves: Drag mounts from the Collections journal onto custom shelf buttons. Uses
/castmacro for reliable summoning. - Battle pet support on custom shelves: Drag companion pets from the Pet Journal onto custom shelf buttons. Summons via
/summonpet. - Keybindings for custom shelves: Assign key bindings to individual custom shelf slots via the per-shelf settings panel. Bindings work even when the popup is closed (via invisible proxy buttons). Keybind text shown on each button.
Improvements
- Cooldown display on custom shelves: Proper dark "pizza" sweep overlay with countdown text, matching Blizzard's native action buttons. Uses
issecretvalue()to handle 12.0.1 secret combat values gracefully. - GCD animation: Global cooldown sweep now shows on all custom shelf buttons. Event-driven via
SPELL_UPDATE_COOLDOWN/ACTIONBAR_UPDATE_COOLDOWNfor instant response. Off-GCD abilities (defensives, some trinkets) correctly skip the sweep. - Handle icon for mounts, macros, and battle pets: Dock handle now picks up icons from all custom shelf action types, not just spells and items.
Bug Fixes
- Items not activating on click: Fixed
SecureActionButtonTemplateitem attribute format — now uses"item:ID"string instead of raw numeric ID. - Item cooldowns not displaying: Fixed
C_Item.GetItemCooldownreturn value unpacking — returns three separate values, not a table (unlikeC_Spell.GetSpellCooldown). Added bag/equipment scan fallback with location caching for combat safety.
v1.2.1
New Options
- Click outside to close popups: Toggle in General settings. When disabled, shelf popups stay open until their handle is clicked again — useful for dragging spells from the spellbook onto action bar shelves without the shelf auto-closing.
- Center popups on dock: Toggle in General settings. Centers shelf popups horizontally on the dock instead of aligning them to their individual handle. Both options are off by default (existing behavior preserved).
Improvements
- Pinned popup drag grip: The grip is now a visible tab that protrudes above the popup frame (16px, with background and dot pattern). Hidden at idle and appears on mouseover for a cleaner look.
- Grip integrated with popup fade: Hovering the grip keeps the pinned popup at full opacity; the grip shares the same enter/leave polling as the popup itself.
Bug Fixes
- Blizzard Action Bar 1 appearing over shelves: Added an aggressive OnShow hook on hidden bar frames to immediately re-hide them when Blizzard's TWW action bar code tries to show them. Properly managed through activate/deactivate/Edit Mode cycles.
- Bags not opening in combat: Removed unnecessary
InCombatLockdown()guard fromToggleAllBags()call. Also set the bag handle's secure snippet to a no-op to prevent popup toggle side-effects during combat. - Edit Mode exit redundancy: Simplified
OnEditModeExitto just callRebuildAll()instead of manually re-hiding bars then rebuilding (the rebuild already handles everything).
v1.2.0
New Shelf Types
- Bags shelf: Click handle to toggle all bags open/closed. Handle displays used/total bag space using template keywords (
$used/$total). No popup — pure handle convenience. - Status shelf: Custom XP and reputation progress bars in a popup. Purple XP bar with level/percentage, green reputation bar with faction/standing. Handle shows compact template text (e.g.,
Lv$level $xp%). Hides Blizzard's status tracking bars. - Micro menu shelf: Reparent Blizzard's micro menu buttons into a shelf popup. Auto-detects available buttons, native sizing, configurable rows.
- Multi-faction tracking: Track multiple reputations beyond Blizzard's watched faction. Hierarchical faction picker organized by expansion with search. Each tracked faction gets its own colored bar in the status popup.
Pinned Popups
- Pin any shelf as an always-visible bar via the "Pin as bar" checkbox.
- Drag pinned popups anywhere on screen via the grip handle at the top.
- Per-shelf idle opacity with mouseover reveal (reuses dock fade pattern).
- Handle click toggles pinned popup visibility without unpinning.
- Pinned popups survive ESC, backdrop clicks, and close-others.
- Hidden during Edit Mode, restored after.
Icon Picker
- Click the shelf icon preview to browse all WoW icons in a scrollable grid.
- 32K+ icon name database (auto-updated monthly from Townlong Yak via CI).
- Search by icon filename, spell name (from spellbook), or FileDataID.
- FauxScrollFrame virtual scrolling — only visible buttons exist in memory.
- Drag spell/item/macro onto the icon preview as an alternative.
- Right-click the icon preview to reset to auto-detect.
Options Panel Overhaul
- Unified "Shelves & Docks" panel: Tree view shows docks as headers with shelves grouped underneath. Click a dock to configure its name, orientation, and appearance.
- Simplified add buttons: Two buttons ("+ Add Dock", "+ Add Shelf") with a type picker dropdown replacing 6 separate buttons.
- Override Appearance: Per-shelf checkbox to customize Open Direction, Handle Style, and handle sizing. Unchecked = inherits from global Appearance tab. Existing per-shelf customizations auto-detected and preserved.
- Shelf Defaults in Appearance tab: Global defaults for Open Direction and Handle Style.
- Template label system: Status and Bags shelves support
$keywordplaceholders in handle labels ($level,$xp,$used,$total, etc.). - Defaults button: Resets shelf/dock settings with confirmation dialog.
- Proper arrow buttons: Blizzard scroll arrow templates for move up/down with tooltips.
- Detail panel layout: Title, controls row (Enabled/Move/Delete/Defaults), Pinning, then Layout & Sizing.
Profiles & Migration
- Account-wide AceDB profiles via
BarshelfGlobalDBwith cross-character sharing. - Automatic per-character → account-wide migration on first login per character.
- Each character's data migrates under its own profile name (no shared "Default").
- Old data preserved as fallback (marked
_migrated, not wiped). - Legacy
dockMouseoverHideboolean auto-converted todockIdleAlphaat runtime. - Migration test suite with 21 assertions across 7 scenarios, runs in CI.
Localization
- Full translations: German, French, Spanish, Brazilian Portuguese.
- Partial translations: Italian, Russian, Korean, Simplified/Traditional Chinese.
- Localized .toc Notes for all supported locales.
- All UI strings use the
L[]localization system with metatable fallback.
Bug Fixes
- Custom shelf buttons not casting: Removed
ActionButtonTemplateinterference with secure action attributes. - Custom shelf icon/slot misalignment: Icons fill the full button area.
- Drag-and-drop onto custom shelves: Click-based drop handling as fallback.
- Bar shelf tiny icons: Safety floor for button size reads (< 10px → 36px fallback).
- Shift+click no longer casts: Secure handler bypassed via
shift-type1/shift-type2attributes. - Edit Mode ADDON_ACTION_BLOCKED: Deferred handlers with
C_Timer.After(0). - Dock invisible during drag:
FadeTo(1)properly stops running fade animation. - Grid blinking on mouseover: Bar shelf watchdog throttled to 1 check/second.
- Combat safety: Popup anchor/stacking, SetFrameLevel, and bags Hide all guarded with
InCombatLockdown(). - Popup z-ordering: Most recently shown popup renders on top (20-level gap clears child frames).
- Icon size mismatch: Slider default matches native TWW button size (45px for bars).
Infrastructure
- Custom addon logo (
assets/logo.tga) for addon list and minimap icon. TextureNames.lua: 32K+ icon FileDataID → name mappings from Townlong Yak.scripts/update-texture-names.sh: Downloads and regenerates texture names.- Monthly CI job auto-updates
TextureNames.luaand opens a PR if data changed. - Migration test suite in CI (
tests/test_migration.lua).
v1.1.0
New Features
- Dock idle fade: docks can fade to a configurable opacity when idle (no popup open, mouse not hovering). Slider from 0% (fully hidden) to 100% (disabled). Configurable fade animation duration.
- Popup stacking: when "Close other popups" is off, multiple open popups now stack sequentially instead of overlapping. Direction follows the first popup's anchor.
- Shift+click pickup: shift+click or shift+drag a custom shelf button to pick up the spell/item/macro (like Blizzard action bars). Shift+right-click still clears.
Bug Fixes
- Custom shelf buttons not casting spells: removed
ActionButtonTemplatewhich was overriding secure action attributes via its PreClick handler. Buttons now use onlySecureActionButtonTemplatewith manual visual elements. - Custom shelf icon/slot misalignment: icons now fill the full button area instead of using ActionButtonTemplate's inset positioning.
- Drag-and-drop onto custom shelves: added click-based drop handling as fallback, since
SecureActionButtonTemplateconsumes the event beforeOnReceiveDragfires. - Bar shelf tiny icons: added safety floor for button size reads — buttons reporting < 10px during early TWW load now fall back to 36px instead of producing broken micro-scale popups.
- Shift+click no longer casts: secure handler is bypassed on shift+click via
shift-type1/shift-type2attributes, preventing unintended spell casts when picking up or clearing slots.
v1.0.0
Initial release.
- Bar shelves: reparent Blizzard action bars 1-8 into popup grids
- Custom shelves: drag-and-drop spells, items, macros (OPie-like)
- Multiple docks with horizontal/vertical orientation
- Auto-detect Blizzard Edit Mode settings (icons, rows, size, padding)
- Popup auto-anchor with screen-edge flip
- Dock/shelf/popup appearance settings (opacity, border, padding, sizing)
- Handle display modes (icon, label, or both)
- Shelf reordering via config panel
- ESC-to-close, click-outside-to-close
- Edit Mode integration: shows original bars during Edit Mode
- Ace3 integration: AceDB profiles, Blizzard Settings panel with subcategories
- Minimap icon via LibDBIcon
- Combat-safe secure handlers and queue system