관리자 팝오버 표면 공통화

This commit is contained in:
2026-07-23 17:41:39 +09:00
parent 60512ef07d
commit 7dc1ecef4d
11 changed files with 78 additions and 25 deletions

View File

@@ -648,14 +648,18 @@ watch(() => props.member, () => {
<circle cx="12" cy="12.001" r="4.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
</svg>
</button>
<div v-if="actionMenuOpen" class="admin-member-form__action-popover absolute right-0 top-12 z-20 grid w-52 overflow-hidden rounded-xl border border-line bg-white py-2 text-sm text-[#3f4650] shadow-[0_16px_44px_rgba(15,23,42,0.16)]">
<AdminPopoverSurface
v-if="actionMenuOpen"
root-class="admin-member-form__action-popover absolute right-0 top-12 z-20 grid w-52 rounded-xl border-line py-2 text-sm text-[#3f4650]"
clipped
>
<button class="admin-member-form__action-item px-4 py-2.5 text-left hover:bg-[#f3f5f7]" type="button" @click="openPasswordModal">
비밀번호 변경
</button>
<button class="admin-member-form__action-item px-4 py-2.5 text-left text-[#d21a26] hover:bg-[#fff1f2]" type="button" @click="openDeleteModal">
멤버 삭제
</button>
</div>
</AdminPopoverSurface>
</div>
<button v-else class="admin-member-form__action-icon flex h-11 w-11 items-center justify-center rounded-md border border-line bg-white text-[#3f4650]" type="button" aria-label="멤버 작업" disabled>
<svg class="h-5 w-5" viewBox="0 0 24 24" aria-hidden="true">

View File

@@ -843,9 +843,9 @@ defineExpose({
</svg>
</button>
</div>
<div
<AdminPopoverSurface
v-if="isPageSectionSuggestionsOpen && hasPageSectionSuggestions"
class="admin-page-form__section-suggestions absolute left-0 right-0 top-[calc(100%+0.25rem)] z-20 max-h-48 overflow-y-auto rounded border border-[#e3e6e8] bg-white py-1 shadow-lg"
root-class="admin-page-form__section-suggestions absolute left-0 right-0 top-[calc(100%+0.25rem)] z-20 max-h-48 overflow-y-auto rounded border-[#e3e6e8] py-1"
>
<button
v-for="(option, index) in pageSectionSuggestionOptions"
@@ -859,13 +859,14 @@ defineExpose({
<span class="truncate">{{ option.name }}</span>
<span v-if="option.isSelected" class="text-xs text-[#8e9cac]">선택됨</span>
</button>
</div>
<p
</AdminPopoverSurface>
<AdminPopoverSurface
v-else-if="isPageSectionSuggestionsOpen && pageSectionInput.trim()"
class="admin-page-form__section-empty absolute left-0 right-0 top-[calc(100%+0.25rem)] z-20 rounded border border-[#e3e6e8] bg-white px-3 py-2 text-xs text-[#7c8b9a] shadow-lg"
as="p"
root-class="admin-page-form__section-empty absolute left-0 right-0 top-[calc(100%+0.25rem)] z-20 rounded border-[#e3e6e8] px-3 py-2 text-xs text-[#7c8b9a]"
>
일치하는 섹션이 없습니다.
</p>
</AdminPopoverSurface>
</div>
<span class="admin-page-form__help text-xs text-[#7c8b9a]">
섹션은 네비게이션의 페이지 섹션에서 추가합니다.

View File

@@ -0,0 +1,41 @@
<script setup>
const props = defineProps({
/** 렌더링할 HTML 태그 */
as: {
type: String,
default: 'div'
},
/** 팝오버 접근성 role */
role: {
type: String,
default: ''
},
/** 팝오버에 추가할 화면별 클래스 */
rootClass: {
type: String,
default: ''
},
/** 팝오버에 적용할 인라인 스타일 */
surfaceStyle: {
type: Object,
default: () => ({})
},
/** 기본 overflow 숨김 사용 여부 */
clipped: {
type: Boolean,
default: false
}
})
</script>
<template>
<component
:is="props.as"
class="admin-popover-surface border bg-white shadow-[0_18px_50px_rgba(15,23,42,0.14)]"
:class="[clipped ? 'overflow-hidden' : '', rootClass]"
:style="surfaceStyle"
:role="role || undefined"
>
<slot />
</component>
</template>

View File

@@ -2281,9 +2281,9 @@ defineExpose({
<p class="mt-1 text-xs text-[#8e9cac]">
{{ selectedTags.length }} / {{ postTagLimit }}개 선택됨
</p>
<div
<AdminPopoverSurface
v-if="hasTagSuggestions"
class="admin-post-form__tag-suggestions absolute left-0 right-0 top-full z-40 mt-1 max-h-64 overflow-y-auto rounded-lg border border-[#d7dce0] bg-white py-1 text-sm shadow-[0_18px_50px_rgba(15,23,42,0.14)]"
root-class="admin-post-form__tag-suggestions absolute left-0 right-0 top-full z-40 mt-1 max-h-64 overflow-y-auto rounded-lg border-[#d7dce0] py-1 text-sm"
role="listbox"
>
<button
@@ -2300,7 +2300,7 @@ defineExpose({
<span class="admin-post-form__tag-suggestion-name min-w-0 truncate font-semibold text-[#15171a]">{{ tag.name }}</span>
<span class="admin-post-form__tag-suggestion-meta shrink-0 text-xs text-muted">{{ getTagSuggestionMeta(tag) }}</span>
</button>
</div>
</AdminPopoverSurface>
</div>
</div>

View File

@@ -150,15 +150,16 @@ onBeforeUnmount(() => {
</svg>
</button>
<Teleport to="body">
<div
<AdminPopoverSurface
v-if="isOpen"
class="admin-row-more-menu__popover fixed z-[80] overflow-hidden rounded-xl border border-[#e2e5e9] bg-white py-2 text-sm text-[#3f4650] shadow-[0_18px_50px_rgba(15,23,42,0.16)]"
:style="popoverStyle"
root-class="admin-row-more-menu__popover fixed z-[80] rounded-xl border-[#e2e5e9] py-2 text-sm text-[#3f4650]"
:surface-style="popoverStyle"
clipped
role="menu"
data-admin-row-menu
>
<slot />
</div>
</AdminPopoverSurface>
</Teleport>
</div>
</template>