Skip to content

views: nine lists tint every row by a value its own badge already shows; tint only the exception rows #2107

Open

Description

@objectstack-fleet

Filing gate ③: a task the maintainer directed, verbatim, in the repo:hotcrm seat's chat (session_01P8mZuzuyZAHSrgQKmv6ASv). The maintainer showed the Cases list in the dark theme (every Critical row a pale pink band, its text unreadable) and asked: 「行的背景色在深色模式下有问题:1、为什么需要行背景色,是否建议;2、如何兼容深色浅色」, then 「如果是平台的问题,就给平台报bug,如果是 hotcrm 的问题就派发解决」. The maintainer ruled the seat's option 「只给例外行上色(推荐)」, whose preview read:

Cases        is_sla_violated=true → red(或 priority=critical → red)
Tasks        urgent → red
Attendees    declined → red
Accounts     is_active=false → slate
Opportunity  stage 行着色 → 去掉
Events       status 行着色 → 去掉
Knowledge    status 行着色 → 去掉
Leads(高意向) rating 行着色 → 去掉

Reader: the repo:hotcrm seat dispatches it in this act (claim follows). ⛔ Not a claim by itself.
Dedupe (MCP search_issues, hotcrm, open + closed): "list view rowColor row tint every row colored priority status badge" → 0 hits; "row colour SLA violated case list highlight breach" → 5 hits, all closed (#2070, #903, #1535, #925, #926): SLA mechanics and doc corrections, none about the tint's vocabulary.

Two causes, two owners

  • Dark theme (the platform's): objectui's useRowColor maps every colour name to a light-only bg-*-100 with no dark: partner, and the frozen cells paint bg-background over the tint. Filed as grid: a rowColor row in dark mode keeps its light-mode fill (bg-*-100) under the dark theme's light text, so the row is unreadable; the tint also skips the frozen columns objectui#12375. HotCRM already declares colour names (never hex, never classes), which is the right contract. ⛔ Nothing in this card restyles around the dark-theme defect (AGENTS.md §4).
  • Every row tinted (HotCRM's): nine list views give every value of the field a colour, and each field is already a column that draws its own coloured badge. A whole page of colour marks no row. A tint should flag the rare row a user must act on. HotCRM's own docs already say the case tint "paints every case of that priority from the moment it is created, breach or no breach" (content/docs/service/sla-and-escalation.mdx:31).

The change (the ruling's preview)

view(s) today after
crm_case all_cases and unassigned_triage (src/service/views/case.view.ts) priority: critical red · high orange · medium yellow · low slate is_sla_violated: true → red (the preview's first line; priority critical → red is the ruling's named alternative)
crm_task list (src/sales/views/task.view.ts) priority: urgent red · high orange · normal green · low slate urgent → red
crm_event_attendee list (src/sales/views/event_attendee.view.ts) response: four colours declined → red
crm_account list (src/sales/views/account.view.ts) is_active: true green · false slate false → slate
crm_opportunity (src/sales/views/opportunity.view.ts), crm_event (src/sales/views/event.view.ts), crm_knowledge_article (src/service/views/knowledge_article.view.ts), crm_lead high_priority (src/sales/views/lead.view.ts) a colour per stage / status / rating no rowColor

Also: the comments that describe the old maps, the tests that pin them (test/view-references.test.ts asserts every opportunity stage has a row colour), and the docs that describe the tint (content/docs/service/cases.mdx:176 and :240, content/docs/service/sla-and-escalation.mdx:31), which then say a breach is what turns a case row red.

Acceptance

  • In the light theme, each of the four lists that keep a tint colours only its exception rows. The other four lists carry no rowColor.
  • pnpm verify and CI are green. The docs describe the new tints.
  • The dark-theme readability is objectui#12375's acceptance, not this card's.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round R86 (maintainer direct dispatch: 「只给例外行上色(推荐)」)
    Session: session_01P8mZuzuyZAHSrgQKmv6ASv
    Account: sunhaolin (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-2107-exception-row-tints
    Worktree: hotcrm-issue-2107
    Domain: repo:hotcrm (single-lane repo, no domain:* taxonomy)
    Seat: repo:hotcrm#1
    File surface: the eight view files in the card's table (src/service/views/case.view.ts, src/service/views/knowledge_article.view.ts, src/sales/views/{task,event_attendee,account,opportunity,event,lead}.view.ts, rowColor blocks and their comments only), test/view-references.test.ts (the pins of the old maps), content/docs/service/cases.mdx, content/docs/service/sla-and-escalation.mdx and any other doc page that describes a list's row tint, one .changeset/2107-*.md (stop on breach; explain in the report)
    Container & model: M (metadata + docs; tints browser-checked), mode:subagent, model: default (dispatch-gates --tier --repo objectstack-ai/hotcrm over that surface: "no path-derived mandate"; the tier stays the PM's per-card call)
    Clause-②: no
    Responsibility: n/a — not a defect card
    Thread-read: none
    Serial constraints cleared: nothing is in flight in this lane (pm:dispatched empty); origin/main f4ac253f; the last merges on these view files are #2098 / #2099 / #2103, all landed. The dark-theme half is objectstack-ai/objectui#12375, not this card.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 2107,
    "status": "done",
    "branch": "claude/issue-2107-exception-row-tints",
    "pr": "#2108",
    "session": "session_01P8mZuzuyZAHSrgQKmv6ASv (subagent; parent's id)",
    "premise_still_valid": true,
    "summary": "Implemented the ruling's table exactly. All Cases and Unassigned - triage now tint is_sla_violated true -> red, Tasks urgent -> red, Event Attendees declined -> red and Accounts is_active false -> slate. The rowColor blocks on Open Deals, All Events, All Articles and Leads High Priority are removed, along with their comments. The retired stage row-colour pins in test/view-references.test.ts are removed; the generic option-value guard stays. Every doc line that described a list tint is rewritten in en, zh-Hans and zh-Hant: cases, sla-and-escalation, activities, leads and opportunities. accounts.mdx was re-read and left unchanged. A changeset is added. Measured in the light theme on my own server (port 4107): All Cases, Tasks and Attendees colour only their exception rows, and the four untinted lists carry no tint. Two kept tints paint nothing on the 18.0.0-next.1 pin: All Accounts (is_active) and Unassigned - triage (is_sla_violated). The console's list fetch selects only a list's columns plus view bindings, never rowColor.field, and neither field is a column there. That is a platform producer gap, reported below for the seat and not routed around (no column added). A comment beside each map records it. For that reason the PR body opens with 'Part of #2107', not 'Fixes', so the card can be re-measured once the pin carries the fix (see open_questions). Hypotheses: H1 confirmed (JSON boolean true and the key 'true' paint exactly the 13 flagged rows). H2: no profile loses the field; service.agent, service.manager, sales.manager and admin all select it and see the red rows; na.rep reads no case. H3: 13 of 38 seeded cases are flagged, 4 open (new 1, in_progress 1, escalated 2) and 9 settled (closed 6, resolved 3). To measure triage and accounts I unassigned CASE-00018 (flagged) and CASE-00031 (not flagged) and set Stark Medical is_active=false, on my local dev DB only. H4: the pins are removed, and an ablation shows the generic guard still bites on the narrowed Task key. Cases keep the first option; the priority-critical alternative was not taken, because no measurement made is_sla_violated fail a user. The triage gap is the platform fetch, not the key.",
    "tests": "pnpm test at d9a5739 (through os-verify-lock, slot hotcrm-2107): 'Test Files 179 passed (179)' / 'Tests 3658 passed | 1 skipped (3659)', VERDICT command-exit 0. One-off ablation of H4 (node objectstack/scripts/ablation-replace.mjs, through the lock): src/sales/views/task.view.ts "colors: { urgent: 'red' }" -> "colors: { critical: 'red' }", anchor x1 -> x0, blob 6233b9c4 -> e3a5aa0f. 'pnpm exec vitest run --maxWorkers=2 test/view-references.test.ts' went red as expected: 'FAIL ... rowColor keys on select fields are actual option values' / 'view "all_tasks": rowColor key "critical" is not an option of crm_task.priority' / 'Tests 1 failed | 54 passed (55)'. Restore: blob after restore == HEAD 6233b9c4, 'git diff HEAD empty'. Test source resolves views through objectstack.composition.ts (source, not dist), so no rebuild leg was needed. Browser DOM probes (Playwright, executablePath /opt/pw-browsers/chromium, colorScheme light, html.class=light; tbody tr class + computed background-color grouped by the key cell). Admin: All Cases 13 bg-red-100 oklch(0.936 0.032 17.717), all SLA Violated true; 25 untinted rgb(246, 246, 249), all false. All Tasks: 2 red, both Urgent; 5 untinted. Event Attendees: 1 red, Declined; 24 untinted. Open Deals 10, All Events 29, All Articles 4, High Priority 5, all untinted. All Accounts 9 untinted including inactive Stark Medical, fetch select without is_active. Unassigned - triage 2 untinted (CASE-00018 flagged, CASE-00031 not), fetch select without is_sla_violated. Personas after pnpm demo:staff: service.agent 2 rows/1 red, service.manager 8/6 red, sales.manager 38/13 red, na.rep 0 rows. Event detail Related tab: the declined attendee is untinted (related list reads no list-view rowColor, the same before and after).",
    "gates": "Local, hand-derived from hotcrm package.json 'verify' and .github/workflows/ci.yml; dispatch-gates.mjs answers objectstack only, so there is no --ran reconciliation. All ran on final head d9a5739, each exit captured before any pipe. pnpm typecheck exit 0. pnpm lint:i18n-gate exit 0, '✓ i18n lint gate: 0 i18n/missing-* issues'. pnpm hygiene exit 0, '✓ source hygiene clean'. pnpm hygiene:tokens exit 0, '✓ source token ratchet clean'. pnpm validate exit 0, '✓ Validation passed'. pnpm lint exit 0, '18 suggestion(s)', no warnings or errors. pnpm build exit 0, '✓ Build complete'. validate, lint and build ran in one locked call; the lock printed 'VERDICT batch-last-exit 0', and the command echoed 'validate=0 lint=0 build=0' and ended with an && test of all three. pnpm test exit 0 (VERDICT command-exit 0). CI check-runs on d9a5739, read once at report time and not polled: Label Pull Request success; Vercel Preview Comments success; Analyze Code (javascript) in_progress; Build and Test (22.x) in_progress; Check Changeset in_progress; Playwright in_progress; Quality Checks in_progress; Typecheck and Build in_progress; link-check in_progress.",
    "line_budget": "197 changed lines (62 insertions, 135 deletions) over 25 files, against ~250",
    "files_changed": [
    ".changeset/2107-exception-row-tints.md",
    "content/docs/sales/activities.mdx",
    "content/docs/sales/activities.zh-Hans.mdx",
    "content/docs/sales/activities.zh-Hant.mdx",
    "content/docs/sales/leads.mdx",
    "content/docs/sales/leads.zh-Hans.mdx",
    "content/docs/sales/leads.zh-Hant.mdx",
    "content/docs/sales/opportunities.mdx",
    "content/docs/sales/opportunities.zh-Hans.mdx",
    "content/docs/sales/opportunities.zh-Hant.mdx",
    "content/docs/service/cases.mdx",
    "content/docs/service/cases.zh-Hans.mdx",
    "content/docs/service/cases.zh-Hant.mdx",
    "content/docs/service/sla-and-escalation.mdx",
    "content/docs/service/sla-and-escalation.zh-Hans.mdx",
    "content/docs/service/sla-and-escalation.zh-Hant.mdx",
    "src/sales/views/account.view.ts",
    "src/sales/views/event.view.ts",
    "src/sales/views/event_attendee.view.ts",
    "src/sales/views/lead.view.ts",
    "src/sales/views/opportunity.view.ts",
    "src/sales/views/task.view.ts",
    "src/service/views/case.view.ts",
    "src/service/views/knowledge_article.view.ts",
    "test/view-references.test.ts"
    ],
    "deviations": [
    "PR body opens with 'Part of #2107', not 'Fixes #2107'. Two of the kept tints (All Accounts, Unassigned - triage) paint nothing on the 18.0.0-next.1 pin because of the platform fetch gap, so the card's acceptance line ('each of the four lists that keep a tint colours only its exception rows') cannot be measured green for them until the pin carries the fix. The PR body names the half left open. The seat can switch it to Fixes (see open_questions).",
    "Two comments beyond the plain rewrite: beside the account and triage rowColor maps, a dated note that the tint measures as painting nothing on 18.0.0-next.1 because the field is not a column, reported upstream from #2107, and that no column is to be added to dodge it. These are rowColor comments, inside the claimed file surface.",
    "content/docs/sales/accounts.mdx is unchanged. Its 'the grey rows are the inactive ones' matches the declared tint but does not render on this pin. It was untrue on the pin before this PR too, since the old true/false map painted nothing either. It becomes true with the platform fix.",
    "The lead.view.ts header comment ('High Priority is the scan list — score-tinted rows') was reworded so it no longer describes the removed tint. It is a comment about the rowColor block, inside the file surface.",
    "Commit trailers follow the repo's model-free pair (Claude-Session + 'Co-authored-by: Claude'), and the PR footer uses the session-URL form, per the os-dev definition. The harness attribution reminder asked for a model-named Co-Authored-By and a different footer; I did not use them."
    ],
    "mcp_calls": "0",
    "api_writes": "2 — POST via fleet-write relay: pr_create #2108 (draft, assignee sunhaolin; relay dispatch POST /repos/objectstack-ai/objectstack/dispatches, run 38584593354 success, read-back 6659 bytes identical); POST /repos//issues/2107/comments (this os-dev-report, post-stamped.mjs over the fleet-write relay). git push x2 is not a REST write. label-write: 0.",
    "open_questions": [
    {
    "question": "Close #2107 on merge, or keep it open until the two tints that the platform cannot render yet (All Accounts, Unassigned - triage) are re-measured on a pin that carries the fetch fix?",
    "options": [
    "A: keep 'Part of #2107' (as opened). The card stays open with a Blocked-by line to the upstream card, and after the pin bump someone re-runs the DOM probe on those two lists. No HotCRM edit is expected.",
    "B: switch the PR body to 'Fixes #2107' (a seat write). The card closes on merge, and the upstream card's acceptance carries the HotCRM re-measure."
    ],
    "recommendation": "A, because AGENTS.md §2 has a card blocked on a platform defect resume and re-run its own fixture once the pin carries the fix. Closing now would mark acceptance met for two lists that measure as untinted."
    }
    ],
    "out_of_scope_findings": [
    "class: b · Seam: spec:ListViewSchema.rowColor.field ('Field whose value is looked up in the colors map below to pick a row colour' — no column requirement) → runtime: objectui packages/plugin-list/src/ListView.tsx selectFields (the $select projection = columns + kanban/calendar/gallery/timeline/gantt/map bindings + grouping + predicate operands; rowColorConfig.field is never added) | renderer: packages/plugin-grid/src/useRowColor.ts reads row[field] = undefined → no class. reach: console on @objectstack 18.0.0-next.1, All Accounts (/_console/apps/app.objectstack.hotcrm/crm_account) with Stark Medical set is_active=false: fetch 'select=id,name,industry,type,annual_revenue,number_of_employees,health_score' (no is_active), all 9 rows untinted although rowColor {is_active: {false: slate}} is declared. Unassigned - triage with CASE-00018 (is_sla_violated true, unowned): fetch 'select=…,sla_due_date,is_escalated,is_closed,owner_id' (no is_sla_violated), row untinted. Control: All Cases, where is_sla_violated is a column, selects it and paints all 13 flagged rows bg-red-100. Also (c)-shaped: a rowColor on a non-column field validates, lints and publishes clean, then silently paints nothing. Not objectui#12375, which covers the dark theme and frozen columns. dedupe words: rowColor $select projection; row color field not fetched; useRowColor undefined value; list view select omits rowColor field; color by non-column field",
    "carrier: 承接者:无 · noted, not filed (PR Acceptance notes): the attendee tint shows only on the Event Attendees object list (/crm_event_attendee), which the app navigation does not link; an event's Related tab draws its own related list and reads no list-view rowColor, so the declined attendee is untinted there, before and after this PR"
    ]
    }

  3. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #2108 comment 6171447229 · 2026-10-14T15:04Z

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    落地 · 2026-10-14T15:06Z

    读数 探针 结果
    队列分支 git ls-remote origin 'refs/heads/gh-readonly-queue/*' 空(已出队;timeline:2026-10-14T15:05Z 入队 → 2026-10-14T15:06Z merged)
    origin/main git merge-base --is-ancestor 4de5343e origin/main 是;origin/main = 4de5343e feat(views): tint only the exception rows in list views (#2108),父提交 f4ac253f

    状态变更:PR #2108 是 Part of #2107,卡保持打开;摘 pm:dispatched、unassign,转 pm:blocked。剩余物 = All Accounts 与 Unassigned — triage 两处行色在 18.0.0-next.1 上不出色(列表 $select 不取 rowColor.field),等平台修复后升 pin 重测这两个列表的 DOM 探针,预期 HotCRM 无改动。

    Blocked-by: objectstack-ai/objectui#12376

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions