From 967fc2d4d356ff580321707acdb16f6dda3e4ca0 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Thu, 1 Oct 2026 14:14:14 -0700 Subject: [PATCH] style(connectors): make refusal links recognizable Style anchors in both connector refusal slots with the existing cobalt, underlined treatment. The linked manual-revoke notice shipped in #2074; this PR supplies its styling. This change only styles anchors and does not create the link or change copy. The CSSOM check parses the stylesheet, verifies both refusal selectors, their declarations, and their order after `.v2-root a`. It does not pin unrelated stylesheet size or tail. Written by sprint-impl, a Commonly agent Pod thread: https://commonly.me/pods/6a692a1be833c668acdb84cf?task=TASK-230 --- .../v2/__tests__/v2-layout-invariants.test.ts | 35 +++++++++++++++++++ frontend/src/v2/v2.css | 2 ++ 2 files changed, 37 insertions(+) diff --git a/frontend/src/v2/__tests__/v2-layout-invariants.test.ts b/frontend/src/v2/__tests__/v2-layout-invariants.test.ts index 734d1ea94..b6b539f85 100644 --- a/frontend/src/v2/__tests__/v2-layout-invariants.test.ts +++ b/frontend/src/v2/__tests__/v2-layout-invariants.test.ts @@ -2086,6 +2086,41 @@ describe('v2 layout invariants (CSS rule presence)', () => { expect(connectorCss).not.toContain('v2-connector-row--dead):not(.v2-connector-row--not-enabled) .v2-connector-row__detail'); }); + it('connector refusal links keep the in-text link treatment in the parsed stylesheet', () => { + const style = document.createElement('style'); + style.textContent = v2; + document.head.appendChild(style); + + try { + const sheet = style.sheet; + expect(sheet).not.toBeNull(); + const rules = Array.from(sheet!.cssRules); + + // This covers links in any refusal slot. Parsing before these assertions + // catches malformed CSS without pinning unrelated stylesheet size/tail. + + const styleRules = rules.filter((rule) => rule.type === CSSRule.STYLE_RULE) as CSSStyleRule[]; + const linkRules = styleRules.filter((rule) => { + const selectors = rule.selectorText.split(',').map((selector) => selector.trim()); + return selectors.includes('.v2-connector-row__refusal a') + && selectors.includes('.v2-connector-aside__refusal a'); + }); + expect(linkRules).toHaveLength(1); + expect(linkRules[0].selectorText.split(',').map((selector) => selector.trim())).toEqual([ + '.v2-connector-row__refusal a', + '.v2-connector-aside__refusal a', + ]); + expect(linkRules[0].style.getPropertyValue('color')).toBe('var(--v2-accent-text)'); + expect(linkRules[0].style.getPropertyValue('text-decoration')).toBe('underline'); + + const resetIndex = styleRules.findIndex((rule) => rule.selectorText === '.v2-root a'); + const linkIndex = styleRules.indexOf(linkRules[0]); + expect(linkIndex).toBeGreaterThan(resetIndex); + } finally { + style.remove(); + } + }); + describe('TASK-122 Phase A — the ruled restyle (Sam, 2026-09-03; spec on TASK-122)', () => { const v2Root = ruleBody(v2, '.v2-root'); diff --git a/frontend/src/v2/v2.css b/frontend/src/v2/v2.css index 03520d6d2..ab1326a4c 100644 --- a/frontend/src/v2/v2.css +++ b/frontend/src/v2/v2.css @@ -10090,6 +10090,8 @@ body.modern-ui.v2-canvas { .v2-connector-code code { overflow-wrap: anywhere; color: var(--v2-on-ink); font-family: var(--v2-font-mono); font-size: 14px; line-height: 20px; } .v2-root button.v2-connector-code__copy { min-height: 30px; padding: 5px 9px; border: 1px solid var(--v2-accent); border-radius: var(--v2-radius-sm); background: var(--v2-accent); color: var(--v2-on-ink); font: 600 12px/16px var(--v2-font); cursor: pointer; } .v2-connector-row__refusal { grid-column: 1 / -1; margin: 10px 0 0; padding: 8px 10px; border: 1px solid var(--v2-border); border-radius: var(--v2-radius-sm); background: var(--v2-surface-tint); color: var(--v2-ink); font-size: 13px; line-height: 18px; overflow-wrap: anywhere; } +.v2-connector-row__refusal a, +.v2-connector-aside__refusal a { color: var(--v2-accent-text); text-decoration: underline; } .v2-connectors__error { padding: 10px 12px; border: 1px solid var(--v2-border); border-radius: var(--v2-radius-sm); color: var(--v2-ink); font-size: 13px; } .v2-connector-aside__note { margin-top: 12px !important; color: var(--v2-text-tertiary) !important; font-size: 12px !important; }