index.rst (6590B)
1 .. _components/sidebar: 2 3 ========= 4 Sidebar 5 ========= 6 7 The new sidebar builds on existing legacy sidebar code treating ``browser-sidebar.js`` as a `SidebarController`. As part of the new sidebar and vertical tabs project, we've added new components including top-level system module `SidebarManager.sys.mjs` and a per window state manager, `SidebarState.sys.ms`. We've added new UI components that use a combination of moz components and custom lit components. The sidebar team maintains the existing synced tabs and history panels. 8 9 Introducing a new panel 10 ----------------------- 11 12 Every panel that is registered and enabled in ``browser-sidebar.js``` and the ``toolsNameMap`` map will show as an option in the Customize Sidebar menu (which is a sidebar panel that contains settings). 13 14 The launcher is a container for tools (ie, icons that when clicked open or close the associated panel). Registering a panel - which should be behind a pref until it is ready to be introduced - does not automatically add a new icon to the launcher. 15 16 A tool can be added once for all users by adding it to the designated pref branch ``sidebar.newTool.migration.`` in ``profile/firefox.js``. So an example would be ``pref("sidebar.newTool.migration.bookmarks", '{}')``. The pref suffix (``bookmarks`` in this example) is the ``toolID`` that should match what you added as the value portion of the relevant entry in the ``toolsNameMap`` map in ``browser-sidebar.js``. It's important to note that if you have a pref governing the visibility of your sidebar panel, it will need to be enabled at the same time in order to be shown in a user's launcher - either via a nimbus rollout or in-tree. 17 18 If you only want to add this item if the pref governing visibility is true, you can pass the pref you want to observe, e.g. ``pref("sidebar.newTool.migration.reviewchecker", '{ "visibilityPref": "browser.shopping.experience2023.integratedSidebar"}')`` where ``browser.shopping.experience2023.integratedSidebar`` is the pref controlling the visibility of the review checker panel. 19 20 In both cases, the tool will be introduced to the launcher one time (appended to a user's customized list of tools) and any customization after that (ie, removing it) takes precedence. If it's not removed, it will persist after that session. 21 22 If you only want to introduce a tool to new users, you can do so by adding it to the ``DEFAULT_LAUNCHER_TOOLS`` list in ``SidebarManager`` and the ``toolsNameMap``. You can do this even if you have previously introduced a tool via a pref branch migration as there is logic that will prevent a tool from being added twice, however the expectation is that when adding it to ``defaultTools`` the pref governing panel visibility is also enabled in-tree. 23 24 State Management 25 ---------------- 26 27 The sidebar includes a variety of options that users can customize, such as: 28 29 - Sidebar visibility (e.g., expand on hover, hide tabs and sidebar) 30 - Sidebar position (left or right) 31 - Tab strip orientation (vertical or horizontal) 32 - Available tools (which can be enabled or disabled) 33 34 These options are stored internally as preference values, meaning they persist across 35 browser windows. For example, if you have two windows open and move the sidebar to the 36 right in one of them, the other window's sidebar will also move to the right. 37 38 In addition to these preferences, there are also *state* values that depend on user 39 interaction, such as: 40 41 - Whether the launcher is expanded, collapsed, or hidden 42 - Which panel is currently open 43 - The width of the launcher and panel 44 45 These state values are usually stored in ``SessionStore``. However, if the user has 46 disabled session restore (e.g., via permanent private browsing mode), they are serialized 47 and stored under the ``sidebar.backupState`` preference instead. 48 49 State values are per-window and do not carry over between windows. For example, if you 50 load a panel in one window, other windows will not display that same panel. 51 52 SidebarState: Per-Window State 53 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 55 ``SidebarState`` tracks and updates sidebar-related UI state within a specific browser 56 window. It acts as the single source of truth for the sidebar's current state in that 57 window. In practice, it functions as a "reactive controller," handling user interactions, 58 maintaining internal state values, and determining the appropriate DOM updates. 59 60 When state values are changed, ``SidebarState`` immediately applies corresponding 61 adjustments to the UI. For example: 62 63 - When ``launcherVisible`` is set to ``false``, the launcher is hidden, and the sidebar's 64 inline padding is adjusted accordingly. 65 - When ``launcherWidth`` or ``panelWidth`` are updated, inline CSS is modified to ensure 66 that the sidebar does not occupy more than 75% of the browser's width. 67 68 SidebarManager: Global State 69 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70 71 ``SidebarManager`` handles listening to preference values, global events, and loading the 72 "backup state" if necessary. When such handlers are triggered, ``SidebarManager`` delegates 73 tasks to each instance of ``SidebarController`` (a per-window module). 74 75 Use cases for ``SidebarManager`` include: 76 77 - Updating visibility preferences when the tab orientation changes. 78 - Managing the default set of tools for new sidebar users. 79 - Detecting when the sidebar button is removed from ``CustomizableUI``, thereby signaling 80 all ``SidebarController`` instances to close the sidebar if it is open. 81 82 .. note:: 83 ``SidebarManager`` should also be responsible for updating the customize panel when 84 preferences are changed from another source, but that is currently not the case. This 85 should be addressed in `Bug 1945530 <https://bugzil.la/1945530>`_. 86 87 Example Workflows 88 ~~~~~~~~~~~~~~~~~ 89 90 Per-Window State Change 91 ^^^^^^^^^^^^^^^^^^^^^^^ 92 93 Suppose a user clicks the toolbar button to show the sidebar. This is how the interaction 94 is handled: 95 96 1. ``SidebarController.handleToolbarButtonClick()`` is called, which sets ``state.launcherVisible``. 97 2. ``SidebarState`` calls the setter for ``launcherVisible``, removing the ``hidden`` 98 attribute from the launcher element. 99 100 Global State Change 101 ^^^^^^^^^^^^^^^^^^^ 102 103 Suppose a user removes the toolbar button. Since ``CustomizableUI`` changes are synced 104 across windows, this is treated as a global state change. The interaction is handled as 105 follows: 106 107 1. ``CustomizableUI`` notifies listeners (including ``SidebarManager``) about a widget 108 removal. 109 2. ``SidebarManager.onWidgetRemoved()`` is called to handle the event. 110 3. ``onWidgetRemoved`` calls the ``hide()`` function on every ``SidebarController`` instance.