Просмотр исходного кода

Menus: the header More list's rows in every popup, the account panel and side menus (#5916)

* Menus: the header More list's rows in every popup, the account panel and side menus

The header's More list got 44px rows with 8px corners, inset 8px inside the
popup. The other menus kept older rows: square and edge to edge in popups (a
global rounded-none rule), 32-42px tall, 14px labels in item menus, gaps in
side menus.

- Popups: one rule for every vertical menu in a popup (add content, More,
  timeline and comment item menus, language and design switchers). 44px rows,
  12px on the icon side and 16px on the other, 8px corners, 16px medium labels,
  the list inset 8px with 8px above and below. Rows are matched by structure in
  plain CSS (naming the bx-stl-mil* classes makes their @apply circular). It
  replaces the More-only rules, and Artificer's menu.css drops its two rules
  that squared More rows.
- Account panel (menu_floating_blocks_wide): the same rows, 24px icons.
- Side menus (menu_vertical_more_less: profile stats, categories, tags): 44px
  rows, 8px corners, no gaps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Menus: no second row padding in the account list; test the popup section alone

The account panel's list (menu_floating_blocks_wide) pads its rows on the li.
If it were ever shown inside a popup, the popup rule would pad its links again,
so the popup rule now skips that list.

ArtificerMenuRowsTest checks the popup section of tailwind.css on its own:
height, corners and icon-side padding, so the side menus' rule (same height)
can no longer satisfy it. Removing the popup rows' min-height now fails it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Menus: the same rows in the sidebars and the profile stats card

- Account sidebar: its list's 8px inset is a CSS rule, since Artificer's
  menu.css zeroes the padding of that list and beat the px-2 class.
- Main menu sidebar (sidebar_site): 44px rows, 12px/16px padding, 8px
  corners, 16px labels, and no gaps between rows or submenu rows.
- Profile stats card: the profile row has 8px corners, and it and the menu
  rows sit 8px from the card's edges (the bleed margin is -0.5rem instead of
  -0.75rem against the block's 16px padding). Side menus in other padded
  blocks get the same 8px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Block tabs: capsules, in line with the block's content

The tabs in block headers ("Add new...", Feed / Public / Hot and the like)
had 6px corners and 4px of side padding on each tab, so the last tab stopped
4px short of the content's edge. They are now capsules like the header tabs,
with no side padding and an 8px gap between them, so the first and last tab
line up with the content.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Andrey Yasko 2 дней назад
Родитель
Сommit
3d49b0436d

+ 9 - 1
modules/boonex/artificer/data/template/system/css/common.css

@@ -186,6 +186,7 @@ import url(../../../../../../../template/css/common.css);
     display: inline-flex;
     -webkit-justify-content: flex-end;
     justify-content: flex-end;
+    gap: 0.5rem; /* between the tabs, so the first and last line up with the block's content */
 }
 .bx-db-menu ul.bx-menu-hor > li:not(.bx-stl-mil-sm),
 .bx-db-menu ul.bx-menu-custom.bx-menu-custom-hor > li:not(.bx-stl-mil-sm) {
@@ -195,10 +196,17 @@ import url(../../../../../../../template/css/common.css);
     -ms-flex:  0 1 auto; 
     flex:  0 1 auto;
 
-    padding: 0 0.25rem;
+    padding: 0;
 
     border-bottom: 1px solid transparent;
 }
+/* Block tabs are capsules, like the header's tabs. Child combinators keep the More list inside a tab out of it. */
+.bx-db-menu ul.bx-menu-hor > li > a.bx-stl-mil-sm,
+.bx-db-menu ul.bx-menu-hor > li > div > a.bx-stl-mil-sm,
+.bx-db-menu ul.bx-menu-custom.bx-menu-custom-hor > li > a.bx-stl-mil-sm,
+.bx-db-menu ul.bx-menu-custom.bx-menu-custom-hor > li > div > a.bx-stl-mil-sm {
+    border-radius: 9999px;
+}
 .bx-db-menu .bx-menu-custom.bx-menu-custom-hor > li:not(.bx-stl-mil-sm) > span {
     display: block;
 

+ 1 - 12
modules/boonex/artificer/data/template/system/css/menu.css

@@ -59,13 +59,6 @@ li.bx-mi-hidden {
     padding-right: 1.0rem;
 }
 
-/* --- Horizontal, Custom Horizontal Menus --- */
-.bx-menu-custom .bx-menu-item.bx-menu-item-more-auto .bx-popup .bx-menu-custom .bx-menu-item,
-.bx-menu-custom .bx-menu-item.bx-menu-item-more-auto .bx-popup .bx-menu-custom .bx-menu-item a,
-.bx-menu-custom .bx-menu-item.bx-menu-item-more-auto .bx-popup .bx-menu-custom .bx-menu-item > span {
-    border-radius: 0;
-}
-
 /*--- Interactive Menu ---*/
 .bx-menu-inter li.bx-menu-inter-hidden,
 .bx-menu-inter-vert li.bx-menu-inter-hidden {
@@ -101,10 +94,6 @@ li.bx-mi-hidden {
         opacity: 1;
     }
 }
-.bx-menu-main .bx-menu-item.bx-menu-item-more-auto .bx-popup .bx-menu-custom .bx-menu-item,
-.bx-menu-main .bx-menu-item.bx-menu-item-more-auto .bx-popup .bx-menu-custom .bx-menu-item a {
-    border-radius: 0;
-}
 
 /*--- Page Submenu ---*/
 .bx-menu-main-submenu {
@@ -190,7 +179,7 @@ div.bx-popup-menu-main.sys-add-content ul {
 .bx-db-content .bx-profile-stats .bx-menu-vertical-more-less,
 .bx-db-container:not(.bx-dbc-nopadding) .bx-menu-vertical-more-less,
 .bx-db-container:not(.bx-dbc-nopadding) .bx-menu-profile-followings {
-    margin: -0.75rem;
+    margin: -0.5rem; /* rows 8px from the block's edge, like menu rows in popups */
 }
 .bx-db-container:not(.bx-dbc-notitle) .bx-menu-vertical-more-less,
 .bx-db-container:not(.bx-dbc-notitle) .bx-menu-profile-followings {

+ 4 - 4
modules/boonex/artificer/data/template/system/menu_floating_blocks_wide.html

@@ -1,10 +1,10 @@
 <ul class="bx-menu-floating-blocks-wide bx-menu-object-__object__">
     <bx_repeat:menu_items>
-        <li class="bx-menu-item bx-menu-item-__name__ __class_add__ bx-stl-mil-hover group relative flex justify-between items-center px-4 text-gray-600 dark:text-gray-300 text-sm font-medium">
-            <a class="flex flex-1 items-center py-2" href="__link__" <bx_if:onclick>onclick="__onclick__"</bx_if:onclick> __attrs__>
-                <div class="bx-menu-floating-blocks-icon flex items-center justify-center h-5 w-5 ltr:mr-2 rtl:ml-2">
+        <li class="bx-menu-item bx-menu-item-__name__ __class_add__ bx-stl-mil-hover group relative flex justify-between items-center min-h-11 ltr:pl-3 ltr:pr-4 rtl:pr-3 rtl:pl-4 rounded-lg text-gray-600 dark:text-gray-300 text-base font-medium">
+            <a class="flex flex-1 items-center self-stretch" href="__link__" <bx_if:onclick>onclick="__onclick__"</bx_if:onclick> __attrs__>
+                <div class="bx-menu-floating-blocks-icon flex items-center justify-center h-6 w-6 ltr:mr-2 rtl:ml-2">
                     <bx_if:icon><i class="sys-icon __icon__"></i></bx_if:icon>
-                    <bx_if:image><img class="h-5 w-5 bg-contain" style="background-image:url(__icon_url__)" src="<bx_icon_url:spacer.gif />" /></bx_if:image>
+                    <bx_if:image><img class="h-6 w-6 bg-contain" style="background-image:url(__icon_url__)" src="<bx_icon_url:spacer.gif />" /></bx_if:image>
                     <bx_if:icon-html>__icon__</bx_if:icon-html>
                 </div>
                 <bx_if:title>

+ 1 - 1
modules/boonex/artificer/data/template/system/menu_sidebar_site.html

@@ -10,7 +10,7 @@
             </span>
         </a>
         <bx_if:show_submenu>
-            <ul class="bx-sidebar-dropdown-content space-y-1 hidden">
+            <ul class="bx-sidebar-dropdown-content hidden">
                 <bx_repeat:submenu_items>
                     <li class="group flex items-center pl-6 text-sm font-medium">
                         <a class="bx-stl-mil flex-1" href="__link__" onclick="__onclick__"__attrs__>

+ 2 - 2
modules/boonex/artificer/data/template/system/menu_vertical_more_less.html

@@ -1,6 +1,6 @@
-<ul class="bx-menu-vertical-more-less bx-menu-ver bx-menu-object-__object__ space-y-2">
+<ul class="bx-menu-vertical-more-less bx-menu-ver bx-menu-object-__object__">
     <bx_repeat:menu_items>
-        <li class="bx-menu-item-__name__ __class_add__ rounded-md">
+        <li class="bx-menu-item-__name__ __class_add__ rounded-lg">
             <div class="bx-menu-item-cnt bx-stl-mil-wo-gaps">
                 <a class="bx-stl-mil-gaps group flex flex-auto items-center truncate" href="__link__" <bx_if:onclick>onclick="__onclick__"</bx_if:onclick> __attrs__>
                     <span class="bx-menu-item-icon bx-stl-mii flex-none group-hover:text-gray-700 dark:group-hover:text-gray-300">

+ 1 - 1
modules/boonex/artificer/data/template/system/profile_stats.html

@@ -1,7 +1,7 @@
 <div class="bx-profile-stats bx-def-border-radius-block">
     <div class="bx-profile-stats-cnt bx-def-padding">
         <div class="bx-ps-user">
-            <div class="bx-profile-avatar-cnt bx-stl-mil-hover group flex items-center px-2 py-1.5 rounded-md cursor-pointer" onclick="window.location.href='__profile_url__'">
+            <div class="bx-profile-avatar-cnt bx-stl-mil-hover group flex items-center px-2 py-1.5 rounded-lg cursor-pointer" onclick="window.location.href='__profile_url__'">
                 <div class="bx-pa-img absolute">__profile_unit__</div>
                 <div class="bx-pa-info w-full">
                     <div class="bx-pa-info-cnt flex flex-col justify-center h-10 pl-10 box-border">

+ 1 - 1
modules/boonex/artificer/data/template/system/sidebar_site.html

@@ -12,7 +12,7 @@
         </div>
         <div class="bx-sidebar-site-logo flex-shrink-0 flex items-center px-4">__main_logo__</div>
         <div class="mt-5 flex-1 h-0 overflow-y-auto">
-            <nav class="px-2 space-y-1">
+            <nav class="px-2">
                 <bx_menu:bx_artificer_sidebar_site />
             </nav>
         </div>

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
scripts/tailwind.max.css


+ 67 - 8
template/css/tailwind.css

@@ -1373,16 +1373,75 @@
         max-height: calc(100dvh - 5.5rem);
         @apply overflow-y-auto overscroll-contain;
     }
-    /* More list: 44px rows like the tabs they continue (same icon and text size), inset 8px so each row's 8px radius sits inside the popup's 16px corner. */
-    #bx-toolbar .bx-popup-menu ul.bx-menu-submenu-more-auto {
-        @apply px-2;
+    /*
+     * Menus in popups (More, add content, item menus, language and design switchers) all take the header More list's
+     * look: 44px rows like the header tabs, 12px on the icon side and 16px on the other, 8px corners, 16px medium labels,
+     * no gaps. The list is inset 8px, so each row's 8px corner sits inside the popup's 16px one. Horizontal menus
+     * (share icons and the like) keep their own layout, and the account panel's list pads its own rows (its template).
+     * The rows are matched by structure and styled in plain CSS:
+     * naming the bx-stl-mil* classes here would make Tailwind's @apply of them circular.
+     */
+    .bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) {
+        padding-left: 0.5rem;
+        padding-right: 0.5rem;
+    }
+    /* The indent wrapper already gives these popups 8px above and below the list. */
+    .bx-artificer .bx-popup .bx-popup-content-indent ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) {
+        margin-top: 0;
+        margin-bottom: 0;
+    }
+    .bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) > li,
+    .bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) > li > a,
+    .bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) > li > span > a,
+    .bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) > li .sys-action-element-holder > a {
+        border-radius: 0.5rem;
+        font-size: 1rem;
+        line-height: 1.5rem;
+    }
+    .bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) > li {
+        border-width: 0;
     }
-    #bx-toolbar ul.bx-menu-submenu-more-auto > .bx-menu-item,
-    #bx-toolbar ul.bx-menu-submenu-more-auto > .bx-menu-item > .bx-stl-mil {
-        @apply rounded-lg;
+    .bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) > li > a,
+    .bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) > li > span > a,
+    .bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"]):not(.bx-menu-hor):not(.bx-menu-custom-hor):not(.bx-menu-floating-blocks-wide) > li .sys-action-element-holder > a {
+        display: flex;
+        align-items: center;
+        width: 100%;
+        min-height: 2.75rem; /* 44px */
+        padding-top: 0;
+        padding-bottom: 0;
+        padding-inline-start: 0.75rem; /* 12px on the icon side */
+        padding-inline-end: 1rem;
+    }
+    /* Account panel: its list is inset 8px like the popups (Artificer's menu.css zeroes list padding, so not a class). */
+    .bx-artificer ul.bx-menu-floating-blocks-wide {
+        padding-left: 0.5rem;
+        padding-right: 0.5rem;
+    }
+    /* Main menu sidebar (sidebar_site): the same rows, inset 8px by its nav, no gaps. */
+    .bx-artificer .bx-sidebar-item > a,
+    .bx-artificer .bx-sidebar-dropdown-content > li > a {
+        min-height: 2.75rem; /* 44px */
+        padding-top: 0;
+        padding-bottom: 0;
+        padding-inline-start: 0.75rem;
+        padding-inline-end: 1rem;
+        border-radius: 0.5rem;
+        font-size: 1rem;
+        line-height: 1.5rem;
+    }
+    /* Side menus (profile stats, categories, tags): the same rows, on the block's own padding. */
+    .bx-artificer ul.bx-menu-vertical-more-less > li,
+    .bx-artificer ul.bx-menu-vertical-more-less > li > div {
+        border-radius: 0.5rem;
+        border-width: 0;
     }
-    #bx-toolbar ul.bx-menu-submenu-more-auto > .bx-menu-item > .bx-stl-mil {
-        @apply h-11 py-0 ltr:pl-3 ltr:pr-4 rtl:pr-3 rtl:pl-4 bx-stl-mil-hover-text;
+    .bx-artificer ul.bx-menu-vertical-more-less > li > div > a {
+        min-height: 2.75rem; /* 44px */
+        padding-top: 0;
+        padding-bottom: 0;
+        padding-inline-start: 0.75rem; /* 12px on the icon side */
+        padding-inline-end: 1rem;
     }
 
     /* Common elements: Page Submenu */

+ 76 - 0
tests/units/template/scripts/ArtificerMenuRowsTest.php

@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * Menu rows in Artificer's popups, account panel and side menus share the header More list's look: 44px rows,
+ * 8px corners, 16px labels, no gaps. Read from the template and CSS files, so a row style that drifts back fails here.
+ */
+class ArtificerMenuRowsTest extends \PHPUnit\Framework\TestCase
+{
+    private static function read(string $sPath): string
+    {
+        $s = file_get_contents(__DIR__ . '/../../../../' . $sPath);
+        if ($s === false)
+            self::fail($sPath . ' is not readable.');
+
+        return str_replace("\r\n", "\n", $s);
+    }
+
+    public function testAccountPanelRowsAre44pxWith16pxLabels(): void
+    {
+        $s = self::read('modules/boonex/artificer/data/template/system/menu_floating_blocks_wide.html');
+
+        $this->assertMatchesRegularExpression('/\.bx-artificer ul\.bx-menu-floating-blocks-wide \{\s*padding-left: 0\.5rem;/', self::read('template/css/tailwind.css'), 'The list is inset 8px (a class would lose to Artificer\'s menu.css).');
+        $this->assertMatchesRegularExpression('/<li class="[^"]*\bmin-h-11\b[^"]*\brounded-lg\b[^"]*\btext-base\b/', $s, 'Rows are 44px with 8px corners and 16px labels.');
+        $this->assertStringNotContainsString('text-sm', $s, 'No small labels left.');
+        $this->assertStringNotContainsString('py-2', $s, 'The row sets the height, not the link\'s padding.');
+    }
+
+    public function testSideMenuRowsHaveNoGaps(): void
+    {
+        $s = self::read('modules/boonex/artificer/data/template/system/menu_vertical_more_less.html');
+
+        $this->assertStringNotContainsString('space-y-2', $s, 'Rows sit right under each other, as in the More list.');
+        $this->assertStringContainsString('rounded-lg', $s);
+    }
+
+    public function testMainMenuSidebarAndStatsCardFollow(): void
+    {
+        $this->assertStringNotContainsString('space-y-1', self::read('modules/boonex/artificer/data/template/system/sidebar_site.html'), 'Main menu sidebar rows have no gaps.');
+        $this->assertStringNotContainsString('space-y-1', self::read('modules/boonex/artificer/data/template/system/menu_sidebar_site.html'), 'Nor do its submenus.');
+        $this->assertStringNotContainsString('rounded-md', self::read('modules/boonex/artificer/data/template/system/profile_stats.html'), 'The profile row has 8px corners like the menu rows.');
+
+        $sCss = self::read('template/css/tailwind.css');
+        $this->assertMatchesRegularExpression('/\.bx-artificer \.bx-sidebar-item > a,[^{]*\{[^}]*min-height: 2\.75rem;[^}]*border-radius: 0\.5rem;/', $sCss, 'Main menu sidebar rows are 44px with 8px corners.');
+        $this->assertMatchesRegularExpression('/\.bx-profile-stats \.bx-profile-avatar-cnt,[^{]*\{\s*margin: -0\.5rem;/', self::read('modules/boonex/artificer/data/template/system/css/menu.css'), 'The stats card\'s rows, the profile one included, sit 8px from its edges (16px block padding less 8px).');
+    }
+
+    public function testBlockTabsAreCapsulesInLineWithContent(): void
+    {
+        $s = self::read('modules/boonex/artificer/data/template/system/css/common.css');
+
+        $this->assertMatchesRegularExpression('/\.bx-db-menu ul\.bx-menu-custom\.bx-menu-custom-hor > li:not\(\.bx-stl-mil-sm\) \{[^}]*padding: 0;/', $s, 'Tabs have no side padding, so the first and last line up with the block content.');
+        $this->assertMatchesRegularExpression('/gap: 0\.5rem;/', $s, 'The tab list spaces its tabs with a gap.');
+        $this->assertMatchesRegularExpression('/\.bx-db-menu ul\.bx-menu-hor > li > a\.bx-stl-mil-sm,[^{]*\{\s*border-radius: 9999px;/', $s, 'Block tabs are capsules like the header tabs.');
+    }
+
+    public function testPopupMenuRowsAreRoundedNotSquare(): void
+    {
+        $sCss = self::read('template/css/tailwind.css');
+
+        // Only the popup section, so the side menus' rule (with the same height) can't satisfy these checks.
+        $iStart = strpos($sCss, 'Menus in popups (More');
+        $iEnd = strpos($sCss, '/* Side menus (profile stats');
+        $this->assertNotFalse($iStart, 'tailwind.css has the popup menu rows section.');
+        $this->assertNotFalse($iEnd, 'tailwind.css has the side menu rows section after it.');
+        $sPopup = substr($sCss, $iStart, $iEnd - $iStart);
+
+        $this->assertStringContainsString('.bx-artificer .bx-popup ul:is(.bx-menu-ver, .bx-menu-custom-ver, [class*="bx-menu-object-"])', $sPopup, 'One rule styles every vertical menu in a popup.');
+        $this->assertStringContainsString(':not(.bx-menu-floating-blocks-wide)', $sPopup, 'The account panel pads its own rows, so links there get no second padding.');
+        $this->assertMatchesRegularExpression('/min-height: 2\.75rem;/', $sPopup, 'Popup rows are 44px.');
+        $this->assertMatchesRegularExpression('/border-radius: 0\.5rem;/', $sPopup, 'Popup rows have 8px corners.');
+        $this->assertMatchesRegularExpression('/padding-inline-start: 0\.75rem;/', $sPopup, '12px on the icon side.');
+
+        $sMenuCss = self::read('modules/boonex/artificer/data/template/system/css/menu.css');
+        $this->assertDoesNotMatchRegularExpression('/more-auto \.bx-popup \.bx-menu-custom \.bx-menu-item[^{]*\{\s*border-radius: 0;/', $sMenuCss, 'No legacy rule squares the More rows again.');
+    }
+}

Некоторые файлы не были показаны из-за большого количества измененных файлов