독립 페이지 하단 버튼 크기를 통일

This commit is contained in:
2026-08-31 14:55:52 +00:00
parent 7080ae5504
commit bf13dabc01
12 changed files with 126 additions and 35 deletions
+3
View File
@@ -270,6 +270,8 @@ test('resource auction preserves the legacy desktop structure, geometry, and int
return { return {
container: { x: containerRect.x, width: containerRect.width }, container: { x: containerRect.x, width: containerRect.width },
topBar: box('.top-back-bar'), topBar: box('.top-back-bar'),
topClose: box('.top-back-bar .close-button'),
bottomClose: box('.bottom-bar .close-button'),
row: { width: rowRect.width, height: rowRect.height }, row: { width: rowRect.width, height: rowRect.height },
cells, cells,
button: { button: {
@@ -282,6 +284,7 @@ test('resource auction preserves the legacy desktop structure, geometry, and int
}); });
expect(geometry.container).toEqual({ x: 0, width: 1000 }); expect(geometry.container).toEqual({ x: 0, width: 1000 });
expect(geometry.topBar).toMatchObject({ x: 0, width: 1000, height: 32 }); expect(geometry.topBar).toMatchObject({ x: 0, width: 1000, height: 32 });
expect(geometry.bottomClose).toMatchObject({ width: geometry.topClose.width, height: geometry.topClose.height });
expect(geometry.row).toEqual({ width: 1000, height: 22 }); expect(geometry.row).toEqual({ width: 1000, height: 22 });
expect(geometry.cells[0]).toBeCloseTo(66.66, 1); expect(geometry.cells[0]).toBeCloseTo(66.66, 1);
expect(geometry.cells[1]).toBeCloseTo(133.34, 1); expect(geometry.cells[1]).toBeCloseTo(133.34, 1);
+8 -2
View File
@@ -294,6 +294,7 @@ test('matches the ref meeting-room geometry, typography, textures, and controls'
return { return {
container: rect('#container'), container: rect('#container'),
topBar: rect('.top-back-bar'), topBar: rect('.top-back-bar'),
topButton: rect('.top-back-bar .back-button'),
titleLabel: rect('.form-label'), titleLabel: rect('.form-label'),
submitArticle: rect('#submitArticle'), submitArticle: rect('#submitArticle'),
articleAuthor: rect('.article-header .author-name'), articleAuthor: rect('.article-header .author-name'),
@@ -319,7 +320,7 @@ test('matches the ref meeting-room geometry, typography, textures, and controls'
}; };
}); });
expect(geometry.container).toMatchObject({ width: 1000, height: 397.3125 }); expect(geometry.container).toMatchObject({ width: 1000, height: 393.8125 });
expect(geometry.topBar.height).toBe(32); expect(geometry.topBar.height).toBe(32);
expect(geometry.titleLabel.width).toBeCloseTo(83.33, 1); expect(geometry.titleLabel.width).toBeCloseTo(83.33, 1);
expect(geometry.titleLabel).toMatchObject({ y: 64.1875, height: 22.1875 }); expect(geometry.titleLabel).toMatchObject({ y: 64.1875, height: 22.1875 });
@@ -333,7 +334,12 @@ test('matches the ref meeting-room geometry, typography, textures, and controls'
expect(geometry.commentAuthor.width).toBe(120); expect(geometry.commentAuthor.width).toBe(120);
expect(geometry.commentAuthor).toMatchObject({ y: 271.25, height: 20.1875 }); expect(geometry.commentAuthor).toMatchObject({ y: 271.25, height: 20.1875 });
expect(geometry.submitComment).toMatchObject({ y: 292.4375, height: 29.375 }); expect(geometry.submitComment).toMatchObject({ y: 292.4375, height: 29.375 });
expect(geometry.bottomButton).toMatchObject({ x: 0, y: 361.8125, width: 71, height: 35.5 }); expect(geometry.bottomButton).toMatchObject({
x: 0,
y: 361.8125,
width: geometry.topButton.width,
height: geometry.topButton.height,
});
expect(geometry.font.family).toContain('Pretendard'); expect(geometry.font.family).toContain('Pretendard');
expect(geometry.font).toMatchObject({ size: '14px', lineHeight: '18.2px' }); expect(geometry.font).toMatchObject({ size: '14px', lineHeight: '18.2px' });
expect(geometry.whiteSpace).toBe('pre'); expect(geometry.whiteSpace).toBe('pre');
@@ -3062,3 +3062,25 @@ test('keeps the shared main and chief shell geometry and interaction states', as
})); }));
expect(chiefMobile).toEqual({ width: 500, padding: '0px', headerWidth: 500 }); expect(chiefMobile).toEqual({ width: 500, padding: '0px', headerWidth: 500 });
}); });
test('keeps the chief footer return button the same size as the top return button', async ({ page }) => {
await install(page);
const measure = () =>
page.locator('.chief-page').evaluate((element) => {
const top = element.querySelector<HTMLElement>('.chief-top .chief-nav')!.getBoundingClientRect();
const bottom = element.querySelector<HTMLElement>('.chief-footer .chief-nav')!.getBoundingClientRect();
return {
top: { width: top.width, height: top.height },
bottom: { width: bottom.width, height: bottom.height },
};
});
await page.setViewportSize({ width: 1200, height: 900 });
await page.goto('/che/chief-center');
const desktop = await measure();
expect(desktop.bottom).toEqual(desktop.top);
await page.setViewportSize({ width: 500, height: 900 });
const mobile = await measure();
expect(mobile.bottom).toEqual(mobile.top);
});
+9 -2
View File
@@ -1111,6 +1111,13 @@ test('current-city hides values and general rows for a wandering user', async ({
await expect(page.locator('.generals')).toHaveCount(0); await expect(page.locator('.generals')).toHaveCount(0);
}); });
test('current-city keeps only the top and footer return buttons', async ({ page }) => {
await install(page, 'admin');
await go(page, 'current-city');
await expect(page.locator('.city-page .back-link')).toHaveCount(2);
await expect(page.locator('.city-page .back-row')).toHaveCount(0);
});
test('current-city exposes own general details to a member and admin fixture', async ({ page }) => { test('current-city exposes own general details to a member and admin fixture', async ({ page }) => {
await install(page, 'admin'); await install(page, 'admin');
await page.setViewportSize({ width: 1200, height: 900 }); await page.setViewportSize({ width: 1200, height: 900 });
@@ -1138,8 +1145,8 @@ test('current-city exposes own general details to a member and admin fixture', a
}; };
}); });
expect(legacyGeometry.selector).toMatchObject({ width: 400, height: 19 }); expect(legacyGeometry.selector).toMatchObject({ width: 400, height: 19 });
expect(legacyGeometry.stats).toEqual({ x: 100, y: 165.375, width: 1000, height: 106.9375 }); expect(legacyGeometry.stats).toEqual({ x: 100, y: 130.875, width: 1000, height: 106.9375 });
expect(legacyGeometry.generals).toMatchObject({ x: 88, y: 290.3125, width: 1024 }); expect(legacyGeometry.generals).toMatchObject({ x: 100, y: 255.8125, width: 1000 });
expect(legacyGeometry.titleAlign).toBe('start'); expect(legacyGeometry.titleAlign).toBe('start');
expect(legacyGeometry.icon).toMatchObject({ width: 64, height: 64, naturalWidth: 64, naturalHeight: 64 }); expect(legacyGeometry.icon).toMatchObject({ width: 64, height: 64, naturalWidth: 64, naturalHeight: 64 });
if (artifactRoot) { if (artifactRoot) {
+24
View File
@@ -2454,3 +2454,27 @@ test('감찰부 keeps the selector interaction and shows the permission error pa
await page.reload(); await page.reload();
await expect(page.getByRole('alert')).toContainText('권한이 부족합니다.'); await expect(page.getByRole('alert')).toContainText('권한이 부족합니다.');
}); });
test('감찰부 하단 창 닫기 버튼은 상단 버튼과 같은 크기를 유지한다', async ({ page }) => {
const head: FixtureState = { permission: 'head', myset: 3, settingMutations: [], accessPages: [] };
await install(page, head);
const measure = () =>
page.locator('.battle-page').evaluate((element) => {
const top = element.querySelector<HTMLElement>('.battle-top .battle-nav')!.getBoundingClientRect();
const bottom = element.querySelector<HTMLElement>('.battle-footer .battle-nav')!.getBoundingClientRect();
return {
top: { width: top.width, height: top.height },
bottom: { width: bottom.width, height: bottom.height },
};
});
await page.setViewportSize({ width: 1000, height: 900 });
await page.goto('battle-center');
await expect(page.getByRole('heading', { name: '감찰부' })).toBeVisible();
const desktop = await measure();
expect(desktop.bottom).toEqual(desktop.top);
await page.setViewportSize({ width: 500, height: 900 });
const mobile = await measure();
expect(mobile.bottom).toEqual(mobile.top);
});
@@ -1237,6 +1237,32 @@ test('keeps the active survey title after voting without reopening the new-surve
await expect(page.locator('.survey-notice')).toHaveCount(0); await expect(page.locator('.survey-notice')).toHaveCount(0);
}); });
test('keeps the survey footer close button the same size as the top close button', async ({ page }) => {
const state: NavigationFixture = {
officerLevel: 0,
permission: 0,
nationLevel: 0,
stage: 0,
npcMode: 1,
generalMeCalls: 0,
operations: [],
};
await installFixture(page, state);
await page.goto(`${basePath}/survey`);
for (const width of [1000, 500]) {
await page.setViewportSize({ width, height: 900 });
const geometry = await page.locator('.pageVote').evaluate((element) => {
const top = element.querySelector<HTMLElement>('.back_bar .back_btn')!.getBoundingClientRect();
const bottom = element.querySelector<HTMLElement>('.bottom_bar .back_btn')!.getBoundingClientRect();
return {
top: { width: top.width, height: top.height },
bottom: { width: bottom.width, height: bottom.height },
};
});
expect(geometry.bottom).toEqual(geometry.top);
}
});
test('notifies only for a new incoming private message and marks it read from the notice', async ({ test('notifies only for a new incoming private message and marks it read from the notice', async ({
page, page,
}, testInfo) => { }, testInfo) => {
+9 -1
View File
@@ -494,7 +494,11 @@ onMounted(() => {
</section> </section>
<footer class="bottom-bar bg0"> <footer class="bottom-bar bg0">
<button class="legacy-button legacy-button--navigation close-button" type="button" @click="closeWindow"> <button
class="legacy-button legacy-button--navigation legacy-button--fixed-height close-button"
type="button"
@click="closeWindow"
>
닫기 닫기
</button> </button>
</footer> </footer>
@@ -762,6 +766,10 @@ input:focus-visible {
.bottom-bar { .bottom-bar {
padding-top: 20px; padding-top: 20px;
} }
.bottom-bar .close-button {
--legacy-button-height: 32px;
width: 88px;
}
@media (max-width: 991px) { @media (max-width: 991px) {
.legacy-auction-page { .legacy-auction-page {
max-width: none; max-width: none;
@@ -317,7 +317,11 @@ onMounted(() => {
</section> </section>
<footer class="battle-footer legacy-bg0"> <footer class="battle-footer legacy-bg0">
<RouterLink v-slot="{ navigate }" custom to="/"> <RouterLink v-slot="{ navigate }" custom to="/">
<button class="legacy-button legacy-button--navigation battle-nav" type="button" @click="navigate"> <button
class="legacy-button legacy-button--navigation legacy-button--fixed-height battle-nav"
type="button"
@click="navigate"
>
닫기 닫기
</button> </button>
</RouterLink> </RouterLink>
@@ -443,7 +447,7 @@ onMounted(() => {
padding-top: 20px; padding-top: 20px;
} }
.battle-footer .battle-nav { .battle-footer .battle-nav {
width: 60px; width: 88px;
} }
@media (max-width: 991px) { @media (max-width: 991px) {
.battle-page { .battle-page {
@@ -452,5 +456,8 @@ onMounted(() => {
.battle-top { .battle-top {
grid-template-columns: 89px 89px 1fr 0 0; grid-template-columns: 89px 89px 1fr 0 0;
} }
.battle-footer .battle-nav {
width: 87px;
}
} }
</style> </style>
+1 -6
View File
@@ -496,12 +496,7 @@ onMounted(() => {
} }
.bottom-bar .back-button { .bottom-bar .back-button {
--legacy-button-height: 35.5px; width: 88px;
display: inline-block;
width: 71px;
margin: 0;
padding-right: 6px;
padding-left: 6px;
white-space: nowrap; white-space: nowrap;
} }
@@ -461,7 +461,11 @@ const repeatTurns = async (amount: number) => {
</template> </template>
</div> </div>
<footer class="chief-footer legacy-bg0"> <footer class="chief-footer legacy-bg0">
<button class="legacy-button legacy-button--navigation chief-nav" type="button" @click="router.push('/')"> <button
class="legacy-button legacy-button--navigation legacy-button--fixed-height chief-nav"
type="button"
@click="router.push('/')"
>
돌아가기 돌아가기
</button> </button>
</footer> </footer>
@@ -679,7 +683,7 @@ const repeatTurns = async (amount: number) => {
padding-top: 20px; padding-top: 20px;
} }
.chief-footer .chief-nav { .chief-footer .chief-nav {
width: 70px; width: 88px;
} }
@media (max-width: 1024px) { @media (max-width: 1024px) {
@@ -690,6 +694,9 @@ const repeatTurns = async (amount: number) => {
.chief-top { .chief-top {
grid-template-columns: 89px 89px 1fr 0 0; grid-template-columns: 89px 89px 1fr 0 0;
} }
.chief-footer .chief-nav {
width: 87px;
}
} }
/* Ref PageChiefCenter의 24 + 4×238 + 24 행렬과 500px 축소 overview 계약입니다. */ /* Ref PageChiefCenter의 24 + 4×238 + 24 행렬과 500px 축소 overview 계약입니다. */
@@ -130,21 +130,6 @@ const commandBrief = (command: ReservedCommand): string =>
</table> </table>
<p v-if="error" class="error" role="alert">{{ error }}</p> <p v-if="error" class="error" role="alert">{{ error }}</p>
<template v-if="data && city"> <template v-if="data && city">
<table class="legacy-table legacy-bg0 back-row">
<tbody>
<tr>
<td>
<button
class="legacy-button legacy-button--navigation back-link"
type="button"
@click="router.push('/')"
>
돌아가기
</button>
</td>
</tr>
</tbody>
</table>
<table class="legacy-table legacy-bg2 stats"> <table class="legacy-table legacy-bg2 stats">
<colgroup> <colgroup>
<col class="label-col" /> <col class="label-col" />
@@ -388,9 +373,6 @@ const commandBrief = (command: ReservedCommand): string =>
.selector p { .selector p {
margin: 1em 0; margin: 1em 0;
} }
.back-row {
margin-top: 16px;
}
.stats { .stats {
margin-top: 0; margin-top: 0;
table-layout: fixed; table-layout: fixed;
+6 -2
View File
@@ -406,7 +406,11 @@ onMounted(() => {
</div> </div>
<footer class="bottom_bar bg0"> <footer class="bottom_bar bg0">
<button class="legacy-button legacy-button--navigation back_btn" type="button" @click="router.push('/')"> <button
class="legacy-button legacy-button--navigation legacy-button--fixed-height back_btn"
type="button"
@click="router.push('/')"
>
닫기 닫기
</button> </button>
</footer> </footer>
@@ -594,7 +598,7 @@ onMounted(() => {
.bottom_bar .back_btn { .bottom_bar .back_btn {
display: inline-block; display: inline-block;
width: auto; width: 88px;
} }
.vote-notice { .vote-notice {