feat: refine branded operator experience
Add the MBN-branded startup intro, semantic sidebar icons, and refined card-based operator visuals. Strengthen packaged UI and input smoke coverage for the updated experience.
This commit is contained in:
@@ -95,8 +95,9 @@ test("appearance themes expose explicit light, dark, and Windows-following palet
|
||||
/:root\[data-color-theme="dark"\],[\s\S]*?body\[data-color-theme="dark"\]\s*\{[\s\S]*?color-scheme:\s*dark/);
|
||||
assert.match(styles,
|
||||
/@media \(prefers-color-scheme:\s*dark\)\s*\{[\s\S]*?:root\[data-color-theme="system"\],[\s\S]*?body\[data-color-theme="system"\]/);
|
||||
assert.match(styles, /--ui-brand:\s*#dc5826/i);
|
||||
assert.match(styles, /\.brand-lockup strong\s*\{[^}]*color:\s*var\(--ui-brand\)/s);
|
||||
assert.match(styles, /--ui-brand:\s*#f47b20/i);
|
||||
assert.match(styles, /\.brand-wordmark-plate\s*\{[^}]*background:\s*#fff/s);
|
||||
assert.match(styles, /\.brand-wordmark\s*\{[^}]*filter:\s*none/s);
|
||||
assert.match(styles,
|
||||
/\.playlist-state-legend \.legend-selected\s*\{\s*color:\s*var\(--ui-accent\)/);
|
||||
assert.match(styles,
|
||||
@@ -141,8 +142,8 @@ test("light palette keeps hints and small semantic labels readable", () => {
|
||||
assert.ok(contrast(token("ui-warning"), token("ui-warning-soft")) >= 4.5);
|
||||
});
|
||||
|
||||
test("view modes change catalog paint without changing operator row geometry", () => {
|
||||
const start = styles.indexOf("/* View-mode presentation is paint-only:");
|
||||
test("visual card mode creates a responsive graphic-action grid without touching operator rows", () => {
|
||||
const start = styles.indexOf("/* View modes affect graphic actions only.");
|
||||
const end = styles.indexOf("/* End view-mode presentation. */", start);
|
||||
assert.ok(start >= 0 && end > start, "view-mode CSS must have an auditable boundary");
|
||||
const viewModeRules = styles.slice(start, end);
|
||||
@@ -151,11 +152,43 @@ test("view modes change catalog paint without changing operator row geometry", (
|
||||
assert.ok(viewModeRules.includes(`data-view-mode="${mode}"`),
|
||||
`${mode} mode must have explicit presentation rules`);
|
||||
}
|
||||
assert.match(viewModeRules, /\.catalog-section/);
|
||||
assert.match(viewModeRules, /\.operator-catalog-results button/);
|
||||
assert.doesNotMatch(viewModeRules, /\.playlist-(?:row|data-row|grid)/);
|
||||
assert.match(viewModeRules, /\[data-visual-card-list="true"\]\s*\{/);
|
||||
assert.match(viewModeRules, /grid-template-columns:\s*minmax\(0, 1fr\)/);
|
||||
assert.match(viewModeRules,
|
||||
/@container operator-workspace \(min-width:\s*520px\)[\s\S]*?repeat\(2, minmax\(0, 1fr\)\)/);
|
||||
assert.match(viewModeRules,
|
||||
/@container operator-workspace \(min-width:\s*820px\)[\s\S]*?repeat\(3, minmax\(0, 1fr\)\)/);
|
||||
assert.match(viewModeRules,
|
||||
/data-visual-card-context="comparison-actions"[\s\S]*?repeat\(auto-fit, minmax\(min\(230px, 100%\), 1fr\)\)/);
|
||||
assert.match(viewModeRules,
|
||||
/data-visual-card-context="theme-actions"[\s\S]*?repeat\(2, minmax\(0, 1fr\)\)/);
|
||||
assert.doesNotMatch(viewModeRules,
|
||||
/(?:^|[;{]\s*)(?:height|min-height|padding|margin|grid-template(?:-columns|-rows)?|display)\s*:/m);
|
||||
/data-visual-card-context="expert-actions"[\s\S]{0,180}?repeat\([23],/);
|
||||
assert.match(viewModeRules, /button\.visual-card\s*\{[\s\S]*?min-height:\s*62px/);
|
||||
assert.doesNotMatch(viewModeRules, /grid-auto-rows:\s*minmax\(62px/);
|
||||
assert.match(viewModeRules,
|
||||
/\.comparison-actions\s*\{\s*display:\s*block;/);
|
||||
assert.match(viewModeRules,
|
||||
/@container operator-workspace \(max-width:\s*759px\)[\s\S]*?\.comparison-actions\s*\{\s*display:\s*grid;/);
|
||||
assert.doesNotMatch(viewModeRules, /\.visual-card-(?:kicker|preview|state)/,
|
||||
"generic previews, repeated category labels, and decorative state tiles add no information");
|
||||
assert.match(viewModeRules,
|
||||
/button\.visual-card:is\(\.selected,[\s\S]*?box-shadow:\s*inset 3px 0 var\(--ui-accent\)/);
|
||||
assert.match(viewModeRules,
|
||||
/summary\[data-tree-root\]\.tree-node-selected/);
|
||||
assert.match(viewModeRules,
|
||||
/summary\[data-tree-root\]:focus-visible\s*\{[\s\S]*?outline:\s*3px solid var\(--ui-accent\)/);
|
||||
assert.match(viewModeRules,
|
||||
/button\.visual-card:is\(\.unavailable, :disabled\):is\(/);
|
||||
assert.match(viewModeRules, /@container operator-workspace \(max-width:\s*759px\)/);
|
||||
assert.match(viewModeRules, /body\[data-view-mode="compact"\]/);
|
||||
assert.doesNotMatch(viewModeRules,
|
||||
/(?:#|\.)(?:stock-results|stock-result|cut-list|cut-row|playlist-row|playlist-data-row|playlist-grid|operator-catalog-draft|operator-catalog-results|operator-catalog-stock-results|overseas-period-actions|overseas-result-area)\b/);
|
||||
assert.doesNotMatch(viewModeRules, /grid-auto-flow:\s*dense|\border\s*:/);
|
||||
const cardButtonRule = viewModeRules.match(/button\.visual-card\s*\{([\s\S]*?)\n\}/);
|
||||
assert.ok(cardButtonRule, "visual cards need one stable geometry rule");
|
||||
assert.doesNotMatch(cardButtonRule[1], /transform\s*:/,
|
||||
"hover or selection must not move the double-click hit target");
|
||||
});
|
||||
|
||||
test("appearance controls and accessibility preferences retain clear feedback", () => {
|
||||
@@ -170,7 +203,8 @@ test("appearance controls and accessibility preferences retain clear feedback",
|
||||
|
||||
test("workspace header keeps one concise title and the live native connection state", () => {
|
||||
assert.match(markup,
|
||||
/class="brand"[^>]*role="img"[^>]*aria-label="매일경제TV VRi"[\s\S]*?class="brand-symbol"[\s\S]*?<svg/);
|
||||
/class="brand"[\s\S]*?class="brand-wordmark-plate"[\s\S]*?<img class="brand-wordmark" src="Brand\/logo\.png" width="176" height="43"[\s\S]*?alt="매일경제TV" draggable="false">[\s\S]*?class="brand-divider" aria-hidden="true"[\s\S]*?class="brand-product">V-STOCK<\/span>/);
|
||||
assert.doesNotMatch(markup, /class="brand-symbol"|class="brand-lockup"|>VRi</);
|
||||
assert.match(markup,
|
||||
/class="workspace-heading"[\s\S]*?class="workspace-heading-icon"[\s\S]*?<div class="workspace-heading-copy">[\s\S]*?<h1 id="workspace-title">[^<]+<\/h1>/);
|
||||
assert.doesNotMatch(markup, /<small>현재 작업<\/small>/);
|
||||
|
||||
Reference in New Issue
Block a user