You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by as...@apache.org on 2026/09/12 03:21:19 UTC

(maka) 01/02: fix(desktop): align project and task rail hover fills

This is an automated email from the ASF dual-hosted git repository.

Astro-Han pushed a commit to branch fix/desktop-model-row-order-and-rail-hover
in repository https://gitbox.apache.org/repos/asf/maka.git

commit ee1e4fce868277548c5c5dca0aa9ee42d23dd92c
Author: AstroHan <le...@outlook.com>
AuthorDate: Sat Sep 12 11:17:36 2026 +0800

    fix(desktop): align project and task rail hover fills
    
    The project group inset session rows by 8px, which shifted only the task
    row's hover/selected fill (titles already shared one x). Zero the inset and
    give the leading status gutter the project folder's 1rem, so both fills and
    titles sit on one left edge.
    
    Generated-by: Maka
---
 .../session-project-hierarchy-contract.test.ts     | 22 ++++++++++----
 apps/desktop/src/renderer/styles/sidebar.css       | 35 ++++++++++++----------
 packages/ui/src/session-history-list.tsx           | 22 +++++++-------
 packages/ui/stories/session-list-panel.stories.tsx | 11 ++++---
 4 files changed, 54 insertions(+), 36 deletions(-)

diff --git a/apps/desktop/src/main/__tests__/session-project-hierarchy-contract.test.ts b/apps/desktop/src/main/__tests__/session-project-hierarchy-contract.test.ts
index 3cba90553e..3450e265f7 100644
--- a/apps/desktop/src/main/__tests__/session-project-hierarchy-contract.test.ts
+++ b/apps/desktop/src/main/__tests__/session-project-hierarchy-contract.test.ts
@@ -31,18 +31,30 @@ if (!sidebarCssUrl) throw new Error('Could not locate renderer/styles/sidebar.cs
 const sidebarCss = readFileSync(sidebarCssUrl, 'utf8');
 
 describe('project-grouped session hierarchy', () => {
-  it('aligns session titles with the project name', () => {
+  it('shares the project row left edge with its sessions', () => {
     const projectChildrenRule = sidebarCss.match(
       /\.maka-project-row\s*>\s*div\s*>\s*\[role=["']group["']\]\s*>\s*div\s*\{([^}]*)\}/,
     );
 
     assert.ok(projectChildrenRule, 'project children must have an explicit hierarchy rule');
-    // Product contract: 8px nest so session titles share the project title's x.
-    // SideNav's default spacing-6 is a fixed child inset, not that alignment.
+    // Product contract: session rows sit on the project row's left edge, so
+    // the two hover/selected fills start on the same x rather than the 8px
+    // nest that used to offset only the session rows. SideNav's default
+    // spacing-6 is a fixed child inset, not that alignment.
     assert.match(
       projectChildrenRule[1] ?? '',
-      /padding-inline-start:\s*var\(--spacing-2\)\s*!important;/,
-      'project sessions must keep an 8px hierarchical nest',
+      /padding-inline-start:\s*0\s*!important;/,
+      'project sessions must not be inset from the project row',
+    );
+
+    // The gutter that replaces the nest: the same 1rem box as the project
+    // folder icon, so titles still share one x.
+    const signalRule = sidebarCss.match(/\.maka-session-row-signal\s*\{([^}]*)\}/);
+    assert.ok(signalRule, 'the session status gutter must be declared');
+    assert.match(
+      signalRule[1] ?? '',
+      /width:\s*1rem;/,
+      'the session status gutter must match the project folder icon width',
     );
   });
 });
diff --git a/apps/desktop/src/renderer/styles/sidebar.css b/apps/desktop/src/renderer/styles/sidebar.css
index a548a737ce..031e11b3ea 100644
--- a/apps/desktop/src/renderer/styles/sidebar.css
+++ b/apps/desktop/src/renderer/styles/sidebar.css
@@ -239,20 +239,19 @@
 }
 
 /*
- * Project groups are a parent-child hierarchy. SideNav always nests children
- * by spacing-6; that is a fixed inset, not a title-alignment rule. Project
- * rows lead with a 16px folder, session rows with an 8px StatusDot, so the
- * default 24px inset puts session titles 16px right of the project name.
- * Product intent: keep an 8px hierarchical inset (spacing-2) so titles share
- * one x. The whole session button, including hover/selected fill, moves with
- * that inset; the right edge stays on the rail. Pin the value because StyleX
+ * Project groups are a parent-child hierarchy, and SideNav indents children by
+ * spacing-6 by default. That inset shifted the whole session button — its
+ * hover/selected fill included — 24px right of the project row, so the two
+ * fills began on different x. Zero it: session rows sit on the project row's
+ * left edge, and the leading status gutter below is the same 1rem as the
+ * project folder, so titles still share one x. Pin the value because StyleX
  * owns the unlayered default. Child combinator only — do not use a descendant
  * selector that would indent deeper nest levels twice if any appear later.
  * DOM: .maka-project-row > SideNavItem root > [role=group] > childrenInner
  */
 .maka-project-row > div > [role="group"] > div {
   /* !important: StyleX childrenInner paddingInlineStart is unlayered. */
-  padding-inline-start: var(--spacing-2) !important;
+  padding-inline-start: 0 !important;
 }
 
 /*
@@ -368,15 +367,19 @@
 /*
  * Slot 1: the leading status gutter.
  *
- * Astryx's StatusDot is a fixed 8px box (StatusDot.tsx), so only the empty case
- * needs declaring: a row with no dot must still hold the column, or titles would
- * start at a different x depending on whether the task has a state. The dot is
- * present or absent; the gutter is not.
+ * A fixed box every row pays for, whether or not it has a dot, so state reads
+ * as one column down the rail instead of a mark that drifts with each title's
+ * length. 1rem, the same box Astryx gives the project row's `size="sm"` folder
+ * icon: with the group inset zeroed above, the equal gutters are what keep
+ * session titles on the project name's x, and the session hover/selected fill
+ * on the project row's left edge.
  */
-.maka-session-row .maka-session-row-signal-empty {
-  display: block;
-  width: 8px;
-  height: 8px;
+.maka-session-row-signal {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 1rem;
+  height: 1rem;
   flex: none;
 }
 
diff --git a/packages/ui/src/session-history-list.tsx b/packages/ui/src/session-history-list.tsx
index b85529633f..c256da96d9 100644
--- a/packages/ui/src/session-history-list.tsx
+++ b/packages/ui/src/session-history-list.tsx
@@ -799,17 +799,17 @@ const SessionNavRow = memo(function SessionNavRow(props: {
         // whether or not it has a dot, so state reads as one column down the
         // rail instead of a mark that drifts with each title's length.
         icon={
-          signal ? (
-            <StatusDot
-              variant={signal.variant}
-              label={signal.label}
-              isPulsing={signal.isPulsing}
-              tooltip={signal.tooltip}
-              data-session-status={props.session.status}
-            />
-          ) : (
-            <span className="maka-session-row-signal-empty" aria-hidden="true" />
-          )
+          <span className="maka-session-row-signal">
+            {signal ? (
+              <StatusDot
+                variant={signal.variant}
+                label={signal.label}
+                isPulsing={signal.isPulsing}
+                tooltip={signal.tooltip}
+                data-session-status={props.session.status}
+              />
+            ) : null}
+          </span>
         }
         onClick={(event) => {
           // Shift- and ⌘-clicks are answered by the list, which has already
diff --git a/packages/ui/stories/session-list-panel.stories.tsx b/packages/ui/stories/session-list-panel.stories.tsx
index 7ff2767752..2a136d5833 100644
--- a/packages/ui/stories/session-list-panel.stories.tsx
+++ b/packages/ui/stories/session-list-panel.stories.tsx
@@ -519,8 +519,9 @@ export const PinnedAndRecentSections: Story = {
   ),
 };
 
-// Real path: group-by-project — collapsible project rows, sessions nested 8px
-// under the project so titles share one x, worktree mark + project actions.
+// Real path: group-by-project — collapsible project rows, sessions on the
+// project row's left edge so both titles and hover fills share one x, worktree
+// mark + project actions.
 export const ProjectGroups: Story = {
   render: () => {
     const maka = makeProject({
@@ -642,9 +643,11 @@ export const ProjectGroups: Story = {
     expect(projectRow.querySelectorAll('button button')).toHaveLength(0);
     const projectBox = navigation.getBoundingClientRect();
     const taskBox = taskControl.getBoundingClientRect();
+    // The task row sits on the project row's left edge, so the two
+    // hover/selected fills start on the same x — not the 8px nest that used to
+    // offset only the task rows.
     const sessionInset = taskBox.x - projectBox.x;
-    expect(sessionInset).toBeGreaterThanOrEqual(6);
-    expect(sessionInset).toBeLessThan(16);
+    expect(Math.abs(sessionInset)).toBeLessThanOrEqual(1);
     expect(Math.abs(
       projectTitle.getBoundingClientRect().x - taskTitle.getBoundingClientRect().x,
     )).toBeLessThanOrEqual(2);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org