merge: 최신 로컬 main을 Vue 드래그 리팩터링에 통합

This commit is contained in:
2026-08-21 02:36:32 +00:00
2 changed files with 109 additions and 5 deletions
+80 -1
View File
@@ -1048,6 +1048,9 @@ const persistArtifact = async (page: Page, name: string) => {
gameHeader: describe('.game-shell__header'),
gameTitle: describe('.game-shell__title'),
gameHeaderActions: describe('.desktop-action-controls'),
headerRealtime: describe('.desktop-action-controls__realtime'),
headerRefresh: describe('.desktop-action-controls__refresh'),
headerLobby: describe('.desktop-action-controls__lobby'),
legacyGameInfo: describe('.legacy-game-info'),
activityStatus: describe('.activity-status'),
executionStatus: describe('.execution-status'),
@@ -2390,7 +2393,9 @@ test('the 939/940 boundary switches to the Ref-style 500px single document', asy
const headerActionsRect = headerActions.getBoundingClientRect();
return {
headerHeight: headerRect.height,
headerLeft: headerRect.left,
headerRight: headerRect.right,
headerActionsLeft: headerActionsRect.left,
headerActionsRight: headerActionsRect.right,
width: element.getBoundingClientRect().width,
executionWidth: execution.getBoundingClientRect().width,
@@ -2399,7 +2404,9 @@ test('the 939/940 boundary switches to the Ref-style 500px single document', asy
columns: getComputedStyle(element).gridTemplateColumns,
};
});
expect(activityGeometry.headerHeight).toBeLessThan(60);
expect(activityGeometry.headerHeight).toBeGreaterThan(90);
expect(activityGeometry.headerHeight).toBeLessThan(110);
expect(activityGeometry.headerActionsLeft).toBeGreaterThanOrEqual(activityGeometry.headerLeft);
expect(activityGeometry.headerActionsRight).toBeLessThanOrEqual(activityGeometry.headerRight);
expect(activityGeometry.width).toBe(500);
expect(activityGeometry.executionWidth).toBeCloseTo(166.67, 0);
@@ -3179,6 +3186,78 @@ test('all main Lumen button families share the rounded pressed geometry', async
await persistArtifact(page, `${basePath.slice(1)}-main-lumen-button-families`);
});
test('lobby action is separated on desktop and anchors opposite the refresh action on mobile', async ({ page }) => {
const state: NavigationFixture = {
officerLevel: 5,
permission: 2,
nationLevel: 3,
stage: 0,
npcMode: 1,
generalMeCalls: 0,
operations: [],
};
await installFixture(page, state);
await page.setViewportSize({ width: 1200, height: 900 });
await waitForMain(page);
const actions = page.locator('.desktop-action-controls');
const realtime = page.locator('.desktop-action-controls__realtime');
const refresh = page.locator('.desktop-action-controls__refresh');
const lobby = page.locator('.desktop-action-controls__lobby');
const measure = () =>
page.evaluate(() => {
const rect = (selector: string) => {
const element = document.querySelector<HTMLElement>(selector);
if (!element) throw new Error(`${selector} is missing`);
const box = element.getBoundingClientRect();
return { left: box.left, right: box.right, top: box.top, bottom: box.bottom, width: box.width };
};
const actionStyle = getComputedStyle(document.querySelector<HTMLElement>('.desktop-action-controls')!);
return {
actions: rect('.desktop-action-controls'),
realtime: rect('.desktop-action-controls__realtime'),
refresh: rect('.desktop-action-controls__refresh'),
lobby: rect('.desktop-action-controls__lobby'),
title: rect('.game-shell__title'),
display: actionStyle.display,
columns: actionStyle.gridTemplateColumns,
};
});
await expect(actions).toHaveCSS('display', 'flex');
let layout = await measure();
expect(layout.lobby.left - layout.refresh.right).toBeGreaterThanOrEqual(20);
expect(layout.refresh.top).toBeCloseTo(layout.lobby.top, 2);
expect(layout.refresh.width).toBeLessThanOrEqual(62);
expect(layout.lobby.width).toBeLessThanOrEqual(62);
await page.setViewportSize({ width: 500, height: 900 });
await expect(actions).toHaveCSS('display', 'grid');
await expect(realtime).toBeVisible();
await expect(refresh).toBeVisible();
await expect(lobby).toBeVisible();
layout = await measure();
expect(layout.columns.split(' ')).toHaveLength(3);
expect(layout.actions.left).toBeCloseTo(0, 2);
expect(layout.actions.right).toBeCloseTo(500, 2);
expect(layout.refresh.left).toBeCloseTo(layout.actions.left, 2);
expect(layout.lobby.right).toBeCloseTo(layout.actions.right, 2);
expect(layout.refresh.right).toBeLessThan(layout.realtime.left);
expect(layout.realtime.right).toBeLessThan(layout.lobby.left);
expect(layout.refresh.top).toBeCloseTo(layout.lobby.top, 2);
expect(layout.actions.top).toBeGreaterThanOrEqual(layout.title.bottom);
expect(layout.refresh.width).toBeLessThanOrEqual(62);
expect(layout.lobby.width).toBeLessThanOrEqual(62);
expect(
await page.evaluate(() => ({
document: document.documentElement.scrollWidth - document.documentElement.clientWidth,
body: document.body.scrollWidth - document.body.clientWidth,
}))
).toEqual({ document: 0, body: 0 });
await persistArtifact(page, `${basePath.slice(1)}-main-lobby-action-layout`);
});
test('mobile main Lumen button families keep the same state geometry without overflow', async ({ page }) => {
const state: NavigationFixture = {
officerLevel: 5,
+29 -4
View File
@@ -225,7 +225,7 @@ watch(
</h1>
<div class="game-shell__actions desktop-action-controls">
<button
class="game-shell__action toggle legacy-button legacy-button--navigation"
class="game-shell__action desktop-action-controls__realtime toggle legacy-button legacy-button--navigation"
:class="{ active: realtimeEnabled }"
type="button"
@click="dashboard.setRealtimeEnabled(!realtimeEnabled)"
@@ -233,7 +233,7 @@ watch(
실시간 동기화: {{ realtimeLabel }}
</button>
<button
class="game-shell__action legacy-button legacy-button--navigation"
class="game-shell__action desktop-action-controls__refresh legacy-button legacy-button--navigation"
type="button"
:aria-busy="refreshing"
@click="requestManualRefresh"
@@ -241,7 +241,7 @@ watch(
</button>
<button
class="game-shell__action legacy-button legacy-button--navigation"
class="game-shell__action desktop-action-controls__lobby legacy-button legacy-button--navigation"
type="button"
@click="moveLobby"
>
@@ -916,6 +916,10 @@ button {
font-weight: 400;
}
.desktop-action-controls__lobby {
margin-left: 12px;
}
.placeholder {
font-size: 0.85rem;
color: rgba(232, 221, 196, 0.7);
@@ -930,7 +934,12 @@ button {
}
.desktop-action-controls {
gap: 4px;
display: grid;
width: 100%;
grid-template-areas: 'refresh realtime lobby';
grid-template-columns: max-content 1fr max-content;
align-items: start;
gap: 0;
}
.desktop-action-controls .game-shell__action {
@@ -938,6 +947,22 @@ button {
padding-left: 4px;
}
.desktop-action-controls__refresh {
grid-area: refresh;
justify-self: start;
}
.desktop-action-controls__realtime {
grid-area: realtime;
justify-self: center;
}
.desktop-action-controls__lobby {
grid-area: lobby;
justify-self: end;
margin-left: 0;
}
.main-page {
width: 500px;
min-height: 3688px;