Files
qwen3-6-lora/data/raw/sanitized/plans/puedes-leer-de-jira-dapper-stream.md
T

14 KiB
Raw Blame History

Fix: GFIBER-663 — Attendance horizontal scrollbar disappears on desktop PCs

Context

GFIBER-663 (Crítica, To Do, assigned to Alejandro Lembke): "When an admin tries to update the attendance, the horizontal scrollbar disappears. This feature works perfectly on laptops (using the trackpad), but when users are on a desktop PC using a standard mouse and want to scroll horizontally, the bar vanishes, making it impossible to navigate."

Root cause (confirmed by code exploration): the Attendance Grid at /dashboard renders through app/(protected)/dashboard/page.tsxcomponents/dashboard/AttendanceGrid.tsx (thin stateful wrapper) → the real markup/CSS in packages/design-system/src/components/AttendanceGrid/index.tsx + style.module.scss. The scrollable container (.scroll, overflow-x/y: auto) has zero scrollbar styling anywhere in the app or design-system package (confirmed by repo-wide grep — no ::-webkit-scrollbar, scrollbar-width, scrollbar-color, or scrollbar-gutter rules exist, and no JS toggles scrollbar visibility). The horizontal bar is therefore the raw browser/OS-default scrollbar. On systems with auto-hiding overlay scrollbars (the Windows "Automatically hide scroll bars" setting, on by default in many configurations, plus trackpad-first macOS setups), that bar only flashes during active scroll/hover and never renders as a persistent, draggable element. Trackpad users pan via a two-finger gesture and never need to see it; desktop-mouse users have no default horizontal-scroll gesture and depend on seeing/dragging a visible bar that the app never forces to appear.

Two sibling design-system components (DataTable, UserTable) share the identical un-styled overflow-x: auto idiom and have the same latent bug if ever rendered wide enough to overflow — tracked as a fast-follow, not fixed here (see Scope below).

Root cause verified in code

packages/design-system/src/components/AttendanceGrid/style.module.scss:57-62:

.scroll {
  position: relative;
  max-height: 520px;
  overflow-x: auto;
  overflow-y: auto;
}

No scrollbar-appearance rules follow it. Sticky columns inside .scroll: .agentHead/.agentCell (left: 0, 200px wide) and .summaryHead/.summaryCell (left: 200px, 88px wide) — line 81-182. The decorative .scrollHint right-edge fade (lines 199-207) only signals horizontal overflow; it is not a real scrollbar affordance and is unconditionally rendered regardless of actual overflow.

Fix

Chosen mechanism: style the existing .scroll container with both standards-track scrollbar properties — no new elements, no JS, no scrollbar-gutter (rejected: it only reserves layout space for a scrollbar that already renders; it does not force an OS-overlay scrollbar to become persistently visible/draggable, and it would add an unconditional gutter that isn't accounted for in the precise 200px sticky-offset math).

  • Firefox: scrollbar-width: thin + scrollbar-color: <thumb> <track> — setting scrollbar-color alone switches Firefox off the OS overlay style onto a classic, always-rendered scrollbar.
  • Chromium/WebKit (Chrome, Edge, Safari — the reported Windows/mouse environment): declaring any ::-webkit-scrollbar rule flips these engines from native OS overlay/auto-hide scrollbars to a classic, always-reserved, always-visible scrollbar, independent of the user's OS scrollbar setting. This is the actual fix for the reported bug.

Both axes get styled together (WebKit doesn't let the "become classic" trigger apply to only one axis without declaring size for both) — this is a deliberate, low-risk side effect that also fixes vertical-scrollbar visibility consistency; call it out in the PR description, not scope creep.

Colors — existing tokens only (verified present in packages/design-system/src/tokens/tokens.css, both :root and .dark): thumb var(--fiber-gray-700) (light #5f6368, ~6.05:1 — already the project's validated safe replacement for the previously-blocked --fiber-gray-500), thumb hover/active var(--fiber-gray-900), track/corner var(--fiber-gray-100). Dark mode needs no separate override block — the class-based .dark token overrides cascade automatically.

Scope decision: fix AttendanceGrid only in this change. Repo-wide grep confirmed zero @use/@import exist across any DS component's SCSS today — every stylesheet is self-contained by convention. Introducing a new shared-partial/mixin pattern would be the first use of that mechanism and needs its own validation across three build pipelines (Next transpilePackages, Storybook webpack, Cypress component-test webpack) — not worth the risk under a Crítica-priority hotfix. File a fast-follow ticket to mechanically copy the same rule block into DataTable/UserTable's .wrap selector.

.scrollHint: keep unchanged — it signals "there's more to scroll" (a different affordance than "you can drag here") and removing it would force rewriting an existing passing Cypress test for no benefit in a hotfix.

Exact CSS — packages/design-system/src/components/AttendanceGrid/style.module.scss

Append after the existing .scroll { ... } block (lines 57-62):

.scroll {
  position: relative;
  max-height: 520px;
  overflow-x: auto;
  overflow-y: auto;

  // Force a persistently visible, styled scrollbar instead of relying on the
  // browser/OS default. Auto-hiding overlay scrollbars (Windows "Automatically
  // hide scroll bars", trackpad-first macOS) never render a draggable bar for
  // desktop-mouse users, who have no horizontal-scroll gesture. GFIBER-663.
  scrollbar-width: thin;
  scrollbar-color: var(--fiber-gray-700) var(--fiber-gray-100);
}

// Chromium/WebKit: declaring ::-webkit-scrollbar switches the element from
// native OS overlay scrollbars to a classic, always-reserved, always-visible
// scrollbar — the actual fix for the reported Windows/Chrome bug.
.scroll::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

.scroll::-webkit-scrollbar-track {
  background-color: var(--fiber-gray-100);
}

.scroll::-webkit-scrollbar-thumb {
  background-color: var(--fiber-gray-700);
  border-radius: var(--radius-input);
}

.scroll::-webkit-scrollbar-thumb:hover,
.scroll::-webkit-scrollbar-thumb:active {
  background-color: var(--fiber-gray-900);
}

.scroll::-webkit-scrollbar-corner {
  background-color: var(--fiber-gray-100);
}

Tests (TDD — write these first, they should fail against current CSS, then pass after the fix)

Do not touch AttendanceGrid.test.tsx (Jest). Verified: packages/design-system/jest.config.js maps .scss to identity-obj-proxy, so Jest/RTL never loads real CSS — getComputedStyle assertions there would be meaningless (pass/fail independent of the actual fix).

Add to AttendanceGrid.test.cy.tsx, inside/after the existing describe('AttendanceGrid (component) — scroll & sticky' block (reuses FULL_MONTH/fullGet fixtures already defined there, lines 54-64) — Cypress runs real Chromium with the real compiled SCSS, so getComputedStyle reflects the actual fix:

  1. Assert ::-webkit-scrollbar width/height (10px) and a non-transparent thumb background — proves the classic scrollbar is forced.
  2. Assert overflowX/overflowY remain auto — proves the fix didn't change overflow behavior.
  3. New vertical-scroll regression (none of today's fixtures force vertical overflow — today's AGENTS array only has 2 entries): add a local ~15-agent fixture, mount, assert scrollHeight > clientHeight, scroll to bottom, confirm the last agent is visible AND the agent-name header (.agentHead) stays pinned — proves the scrollbar fix didn't break sticky columns or vertical scroll.

Add to AttendanceGrid.stories.tsx: a DenseGridBothScrollbars story (15 agents × the existing 31-day FULL_MONTH, already defined above FullMonthScroll) forcing both scrollbars simultaneously — the manual-QA scenario, following the same precedent as the BarChart DenseDailySeries regression story used for a prior overflow hotfix in this project.

Manual verification (cannot be automated — no headless engine validates real OS scrollbar chrome/paint)

  • Windows 10/11 + Chrome/Edge with "Automatically hide scroll bars in Windows" on (the exact reported condition) — confirm the bar is persistently visible without hover, and mouse-draggable.
  • macOS Safari/Chrome with trackpad-based auto-hide scrollbars — confirm no regression for the working trackpad case.
  • Firefox (Windows/macOS) — confirm scrollbar-color renders and is draggable.
  • Both light and dark Storybook themes (DenseGridBothScrollbars story) — confirm thumb/track contrast.
  • Sticky agent/summary columns stay glued while horizontal-dragging in a real browser.

Files to touch

  • packages/design-system/src/components/AttendanceGrid/style.module.scss — the CSS fix (only production-code change).
  • packages/design-system/src/components/AttendanceGrid/AttendanceGrid.test.cy.tsx — 3 new Cypress assertions (webkit-scrollbar, overflow-auto, vertical-scroll-unaffected).
  • packages/design-system/src/components/AttendanceGrid/AttendanceGrid.stories.tsxDenseGridBothScrollbars story.
  • Not touched now, tracked as fast-follow: packages/design-system/src/components/DataTable/style.module.scss, packages/design-system/src/components/UserTable/style.module.scss.

Verification (end-to-end)

  1. npm run test --workspace=@gfiber/design-system (Jest) — unaffected, still green (no changes to .test.tsx).
  2. Cypress component tests for AttendanceGrid — new assertions fail on main (pre-fix) and pass after the SCSS change.
  3. npm run storybook --workspace=@gfiber/design-system → open DenseGridBothScrollbars, toggle light/dark — visually confirm persistent, styled scrollbar with adequate contrast, sticky columns intact.
  4. Manual checklist above (Windows/Chrome is the priority — it's the reported environment) before closing the ticket as Crítica.
  5. CI: warden/harden/jorden (design/a11y review) must pass — this change deliberately reuses only already-AA-validated tokens to avoid a repeat of past jorden-blocked contrast issues.

Execution — delegated to a background agent (background-orchestrator skill)

Per the user's request, this plan is not executed directly in this session. It hands off to the background-orchestrator skill, following the same pattern already used for prior tickets in this repo (see Docmost Agentes_Activos: agente-gfiber-649-pending, agente-gfiber-658-is-enabled, etc.):

  1. Create a dedicated git worktree + branch (e.g. agente-gfiber-663-attendance-scrollbar) off dev, per the project's branch-per-feature convention.
  2. Launch an autonomous agent in tmux inside that worktree, briefed with this plan verbatim: write the failing Cypress tests first (TDD — they must fail against the current, un-styled .scroll CSS), then the SCSS fix, then the Storybook story, then run the full verification checklist above.
  3. Monitor the agent, answer any blocking questions it raises.
  4. On completion, the agent opens a PR to dev via the aleleba-pr skill — never auto-merges.
  5. Record the agent's lifecycle (start, ticket, status, PR link) on the Docmost Agentes_Activos page, matching the existing history format.

This session's job ends at handing off a decision-complete plan; the orchestrator skill owns spawning, monitoring, and PR creation from here.


Fix: docmost-context SessionStart hook not triggering

Context

The original ask ("¿puedes leer de Jira el ticket GFIBER-663?") was a read-only lookup — already completed. GFIBER-663 ("Admin Attendance page: Horizontal scrollbar disappears on desktop PCs", Crítica, To Do, assigned to Alejandro Lembke) was fetched via the atlassian MCP and reported above.

The user then raised a separate, real problem: the global docmost-context skill — which is supposed to auto-load project context from Docmost at the start of every conversation via a SessionStart hook — appears to never fire. This matters because CLAUDE.md and the docmost-context skill both assume this happens automatically; if it silently doesn't, every session starts without Docmost context and nobody notices until something is missed.

Root cause

Found by inspecting ~/.claude/settings.json and the hook script directly (read-only):

  • ~/.claude/settings.json correctly registers the hook for SessionStart on matchers startup, resume, and clear, pointing at /home/aleleba/.claude/hooks/docmost-session-start.sh.
  • The script itself is correct — it detects the git project name and instructs the model to invoke the docmost-context skill.
  • The file is not executable: ls -la shows -rw-rw-rw- (no x bit) on /home/aleleba/.claude/hooks/docmost-session-start.sh. Claude Code's hook runner invokes the command path directly; without the execute bit, the OS refuses to run it (Permission denied), so the hook silently produces no output and the model never sees the instruction to load Docmost context. This fully explains "la skill global la estás ignorando, ¿el hook no se hace trigger?" — it's not a skill-detection issue, it's a filesystem permissions issue on the hook script.

Fix

Single command, no code change:

chmod +x /home/aleleba/.claude/hooks/docmost-session-start.sh

This is a global (~/.claude) file, not part of the gfiber-pilot-extension repo — no commit/PR involved.

Verification

  1. ls -la /home/aleleba/.claude/hooks/docmost-session-start.sh → confirm x bits present (e.g. -rwxrwxrwx or -rwxr-xr-x).
  2. Start a fresh Claude Code session (or /clear) inside a git repo → confirm the [docmost-context] Nueva conversación detectada... message appears in the hook output, and that the model subsequently invokes the docmost-context skill before responding to the first user message.
  3. Optionally run the hook manually to sanity-check output before relying on the harness: bash /home/aleleba/.claude/hooks/docmost-session-start.sh from within this repo — should print the instructional block referencing gfiber-pilot-extension.