BarShelf

Hide your action bars and access them on-demand through compact popup shelves. Reparents Blizzard's own buttons — full cooldown/range support in combat. Fully configurable via Blizzard Settings.

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_DEFS entry — ProfessionMicroButton, HousingMicroButton, and LFDMicroButton (retail and Mists Classic use LFDMicroButton; only LFGMicroButton had a def, so retail's group-finder entry silently dropped out). Added defs for all three. Order now mirrors Blizzard_MicroMenu/Mainline/MicroMenuContainerOverrides.lua's GenerateButtonInfos exactly, minus HelpMicroButton.
  • 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. New ApplyMicroIcon pulls the source button's normal atlas / file texture / Portrait child and applies it to our cloned icon — so retail picks up the real UI-HUD-MicroMenu-*-Up art 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's Portrait is 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) and PLAYER_GUILD_UPDATE / NEUTRAL_FACTION_SELECT_RESULT / PLAYER_ENTERING_WORLD (Guild), re-running ApplyMicroIcon for 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_HEIGHT to 30 and LIST_ICON_SIZE to 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 keep 0,1,0,1 since 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. HandleCustomDrop now captures the slot's prior contents and puts them on the cursor after the new action is applied, mirroring how Blizzard's PlaceAction displaces 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), and Barshelf_Mists.toc (Interface 50503) load the addon on the matching Classic clients. Per-flavor Data_Vanilla.lua / Data_TBC.lua / Data_Mists.lua carry the right bar count, action-page IDs, and binding prefixes for each expansion. A new Compat.lua layer 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 actionpage attribute (not retail's actionButtonOffset). BarShelf.lua now sets popup:SetAttribute("actionpage", info.page) for static bars and subscribes to ACTIONBAR_PAGE_CHANGED / UPDATE_BONUS_ACTIONBAR for 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.lua builds 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 touching MainMenuBar directly — 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 / v chrome that mirrors Blizzard's classic MainMenuBarPageNumber + ActionBarUpButton/DownButton (32×32 textures with 6/6/7/7 hit-insets, page label as GameFontNormalSmall). Clicks dispatch via SecureActionButtonTemplate macros that /click Blizzard'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 blocks SecureActionButtonTemplate creation, the widget mounts on PLAYER_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). SetOverrideBindingClick for 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 MicroMenu widgets 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 via GetBindingKey(action) and formatted with GetBindingText. 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-KeyRing with the correct SetTexCoord crop) 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; SetFont falls 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.lua picks 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 bag slash 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, and Handle Alignment defaults moved from Appearance to General → Shelf Defaults.

Bug Fixes

  • Retail: MultiBarBottomLeftButton*Cooldown:SetCooldown blew up with Secret values are only allowed during untainted execution after activating any bar 2-5 shelf. ActivateBarShelf reasserted both the bare button.action field and the protected SetAttribute("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 own ActionButton_ApplyCooldowncooldown:SetCooldown the next time a cooldown event fires. The reassertion was added as a Classic-only fix (Classic clients sometimes leave button.action stale from a hidden-bar init) — gated to Compat.isClassic so retail's parentBar.actionButtonOffset is 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. ActivateBarShelf wrote parentBar.actionButtonOffset = info.offset on every reparent, which taints the bar — actionButtonOffset is read by the bar's secure update path, and once an addon writes it from insecure code the bar is marked tainted. The next ActionBarController_UpdateAll call hits bar: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-derives button.action from parentBar.actionButtonOffset per event); on retail Blizzard sets actionButtonOffset itself per bar via Edit Mode. Gated to Compat.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()'. ActivateBarShelf always set popup:SetAttribute("actionpage", page) and subscribed to ACTIONBAR_PAGE_CHANGED to re-write it. That attribute is a Classic-only mechanism (useparent-actionpage = true causes ActionButton_CalculateAction to 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-written actionpage taints the click context — UseAction then refuses to fire. Gated the entire actionpage block (and the matching cleanup in DeactivateBarShelf) to Compat.isClassic. Retail uses parentBar.actionButtonOffset exclusively.
  • Mouseout on hover-trigger shelves was unreliable. OnLeave + 0.2s timer regularly missed the cursor leaving the popup. Replaced with an OnUpdate watcher that polls IsMouseOver() 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 × bsz box 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-runs LayoutMicroPopup if 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 via C_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 /outfit slash command consumes playerFacingOutfitIndex, which shifts whenever the outfit list changes; outfitID is the only stable handle. Registered TRANSMOG_OUTFITS_CHANGED and re-resolve the macrotext from outfitID for 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:UpdateCustomCooldown queried C_Item.GetItemCooldown(itemID) for bc.type == "item", but toys aren't in the player's bags or equipped slots — they live in the Toy Box — so that API reports 0, 0, 0 for 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 via UseToy). The item branch now falls back to GetItemSpell(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:SetHeight hook tainted the addon (and Titan Panel) with attempt to perform arithmetic on local 'h' (a secret number value, while execution tainted by 'Titan'). v1.4.6 hooks QueueStatusFrame:SetHeight to 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 into totalHeight and passes that to SetHeight — and when the queue contains hidden data (Raid Finder etc.) the entry heights are secret values, so our h + HINT_PADDING propagated taint up the call chain. Both the hook and the immediate-bump call site now guard with issecretvalue(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-secret SetHeight.

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, formerly MainMenuBar) carries decorative children — BorderArt, EndCaps (gryphons), and ActionBarPageNumber — 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. ActivateBarShelf now hides those three elements directly and sets bar.hideBarArt = true (a runtime flag, not the user's saved Edit Mode setting). Originals are captured per-shelf and restored in DeactivateBarShelf.
  • Bar UI fragments stuck wherever the first shelf opened. MainActionBarMixin:UpdateDividers (Blizzard_ActionBar/Shared/MainActionBar.lua) anchors each divider directly to an actionButton via SetPoint("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. Setting bar.hideBarArt = true makes UpdateDividers early-return after its ReleaseAll call, 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:SetParent to catch Blizzard's vehicle/zone/stance reparent flow. 12.0.5 added a second path: MicroMenuMixin:Layout (Blizzard_MicroMenu/Shared/MicroMenuContainer.lua) → UpdateQueueStatusAnchorsQueueStatusButton:UpdatePosition (Blizzard_QueueStatusFrame/Mainline/QueueStatusFrame.lua), which runs ClearAllPoints + SetPoint(point, MicroMenu/MicroMenuContainer, ...) without ever calling SetParent. The SetParent hook missed it entirely, and every MicroMenu:Layout pass (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 second hooksecurefunc on QueueStatusButton.UpdatePosition that overrides the anchor back to the saved UIParent point after Blizzard's pass.
  • BAR_INFO[1].frame pointed at the removed MainMenuBar global. Updated to MainActionBar so 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 (NewAddon name), the LibDataBroker object + LibDBIcon registration key, the Masque group name, the minimap tooltip, the empty-dock hint, chat error lines, and the ## Title in the TOC. The Lua table Barshelf, the BarshelfDB / BarshelfGlobalDB saved-variable names, the frame globals (BarshelfDock_*, BarshelfHandle_*, BarshelfBackdrop, etc.), the .pkgmeta package folder name, and Barshelf.toc stay 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 Shelves group will need to re-pick the skin under the new BarShelf / Custom Shelves group. Minimap visibility persists via db.profile.minimap (the LDBI key is in-memory only).

Patch 12.0.5 compatibility

  • TOC Interface bumped to 120001, 120005 so 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 HousingMicroButton to the micro menu shelf. Blizzard added the Housing Dashboard button in 11.2.7 and it's still present in 12.0.5's Blizzard_MicroMenu/Mainline/MicroMenuContainerOverrides.lua → MicroMenuMixin:GenerateButtonInfos. Users running a micro shelf lost access to it because it wasn't in MICRO_BUTTON_NAMES. Inserted after QuestLogMicroButton to match Blizzard's native order.
  • Removed obsolete SpellbookMicroButton and TalentMicroButton entries from MICRO_BUTTON_NAMES. Both were consolidated into PlayerSpellsMicroButton during Dragonflight/TWW and no longer exist as globals — they were silently skipped anyway.
  • Cooldown handling in CustomShelf.lua already uses issecretvalue() guards and pcall, so the tightened secret-value rules in 12.0.5 (new Cooldown:SetCountdownFormatter / SetCountdownMillisecondsThreshold, aura-field secrecy refinements, UnitName no longer accepting secret unit tokens) do not affect the addon — the only UnitName call 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 by LayoutHandles with the same grip / icon / label geometry used for populated handles — instead of collapsing to a tiny unlabeled SetSize(10, 10) square in the middle of the screen. CreateDock calls LayoutHandles at the end of construction so the hint renders on fresh installs where AddShelf is never called.
  • Right-click-to-configure on any dock. CreateDock wires an OnMouseUp handler that, on RightButton, calls Barshelf: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. openOptions gained an optional dockID parameter that writes selectedDock before routing to the Shelves & Docks subcategory.
  • Per-dock "Enabled" checkbox. Each dock's detail panel has an Enabled checkbox (with an OnEnter tooltip 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 in RebuildAll / 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 in GameFontDisable with a " (hidden)" suffix in the tree view.

Bug Fixes

  • Dock and handles rendering above the Blizzard Settings panel. CreateDock / CreateHandle used SetFrameStrata("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 keep DIALOG so 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-slot Hide() in the OnShow hook (to guard against transiently-nil self.action on populated buttons). That one-frame defer was the blink — Blizzard's action-button cycle would Show() 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 in Blizzard_ActionBar/Shared/ActionBar.lua, the architecture became clear: ActionBarMixin:UpdateShownButtons iterates a Lua table reference (self.actionButtons), NOT ButtonContainer: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 matching UnregisterStateDriver
    • The OnShow hook that re-hid empty slots (source of the v1.4.7 blink)
    • The ACTIONBAR_SHOWGRID/ACTIONBAR_HIDEGRID event frame (Blizzard's ActionBarMixin:ActionBar_OnEvent already handles this, routed through self.actionButtons)
    • The _barshelfDragShowing module flag and _barshelfManaged button marker
    • The alwaysShowActionBars cvar check and Show()/Hide() branching in LayoutBarPopup (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 the showgrid attribute REASON_CVAR bit through EditModeActionBarSystemMixin:UpdateSystemSettingAlwaysShowButtonsActionBarMixin:SetShowGridUpdateShownButtons)
  • 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: OnMouseUp was correctly writing db.profile.queueStatusButtonPoint to disk, but Blizzard's reparent flow (fired on vehicle/zone/stance transitions and other UI refreshes) does SetParent(MicroMenuContainer); SetPoint(..., MicroMenuContainer, ...) — our SetParent hook caught the parent change, but Blizzard's subsequent SetPoint ran immediately afterwards and overwrote the button's anchor back to MicroMenuContainer coordinates. The save was fine; the live position was being clobbered. The SetParent hook now schedules a C_Timer.After(0) deferred restore that reads db.profile.queueStatusButtonPoint and 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): LayoutBarPopup unconditionally Show()ed every managed slot, and Blizzard's ActionBarActionButtonMixin:OnShowUpdateActionHideGridHide cycle 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: LayoutBarPopup gates Show() on HasAction(button.action) or the alwaysShowActionBars CVar, matching Blizzard's native rule. A defensive HookScript("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 _barshelfDragShowing flag, toggled by the ACTIONBAR_SHOWGRID/HIDEGRID handler, lets drag-time Show through.
  • Custom Shelf list mode broken when Masque is enabled: list mode builds a wide rowWidth × bsz button with the icon texture anchored LEFT at bsz × bsz, but Masque skin definitions assume a square button and SetAllPoints(button) the Icon region — so the icon and border stretched across the entire row. Custom-shelf buttons now skip Masque registration when config.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 for ActionButton, MultiBar*, MicroButton*, and bag slots (reparenting doesn't break them), so no registration is needed there. A callback on SkinID/Scale changes re-runs the popup layout so button-dimension changes take effect immediately. Declared via ## OptionalDeps: Masque in the TOC.

v1.4.4

Bug Fixes

  • Bar shelf leaving orphaned slots on the original bar: AddBarShelf counted visible buttons via IsShown() and ActivateBarShelf only reparented that many, leaving any button Blizzard had hidden (e.g. via Edit Mode "Num Icons" < 12) in its original MultiBar*ButtonContainer. When EditModeActionBarMixin:UpdateVisibility / UpdateShownButtons re-ran (combat end, Edit Mode toggle, zone change), those orphaned buttons reappeared at the native bar position. Now iterates 1..info.count unconditionally; 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 its OnShow to re-call :Hide(). Because MultiBar*:Hide() is intercepted by SetShownOverride, Blizzard's UpdateVisibility would call ShowBase → fire OnShow → our hook → :Hide() → recalc → loop. Removed the state driver and OnShow hook 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 (no UpdateMicroButtonsParent equivalent), 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: QueueStatusButton is declared as a child of MicroMenuContainer in Blizzard's QueueStatusFrame.xml, so hiding the container also hid the Group Finder eye. The eye is now reparented to UIParent while a micro shelf is active and survives Blizzard's UpdateMicroButtonsParent() via a hooksecurefunc on SetParent (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/OnMouseUp instead of OnDragStart for instant response (no movement-threshold wait). Position persists per-profile in db.profile.queueStatusButtonPoint. Default location is BOTTOMRIGHT -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 QueueStatusFrame while the micro shelf is active. hooksecurefunc on SetHeight reserves 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_INFO used the legacy MULTIACTIONBAR1..4 ordering, so picking "Action Bar 5" reparented MultiBarBottomRightButton (Blizzard's Action Bar 3) and "Action Bar 4" reparented MultiBarLeftButton (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 their barID and 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 ShowGrid broadcast (sent to action bar children only). Now listens for ACTIONBAR_SHOWGRID/ACTIONBAR_HIDEGRID events and forwards ShowGrid/HideGrid to 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 Button with EnableMouse(true), consuming all mouse events including right-click even though only left-click was processed. Changed to a Frame with SetPropagateMouseClicks(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 Rows slider 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 swallow RightButtonUp events 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 uses isActive (boolean, never secret) to branch, and issecretvalue() 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 BackdropTemplate to InputBoxTemplate which 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 /cast macro 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_COOLDOWN for 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 SecureActionButtonTemplate item attribute format — now uses "item:ID" string instead of raw numeric ID.
  • Item cooldowns not displaying: Fixed C_Item.GetItemCooldown return value unpacking — returns three separate values, not a table (unlike C_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 from ToggleAllBags() 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 OnEditModeExit to just call RebuildAll() 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 $keyword placeholders 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 BarshelfGlobalDB with 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 dockMouseoverHide boolean auto-converted to dockIdleAlpha at 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 ActionButtonTemplate interference 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-type2 attributes.
  • 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.lua and 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 ActionButtonTemplate which was overriding secure action attributes via its PreClick handler. Buttons now use only SecureActionButtonTemplate with 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 SecureActionButtonTemplate consumes the event before OnReceiveDrag fires.
  • 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-type2 attributes, 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