Add office location map dialogs

This commit is contained in:
2026-09-21 15:53:21 +09:00
parent 39fefc5834
commit a4e3a9f995
6 changed files with 190 additions and 19 deletions

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" fill="#ffffff"><path d="m256-240-56-56 384-384H240v-80h480v480h-80v-344L256-240Z"/></svg>

After

Width:  |  Height:  |  Size: 178 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="000"><path d="M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#ffffff"><path d="M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z"/></svg>

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 179 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" fill="#ffffff"><path d="M536.5-503.5Q560-527 560-560t-23.5-56.5Q513-640 480-640t-56.5 23.5Q400-593 400-560t23.5 56.5Q447-480 480-480t56.5-23.5ZM480-186q122-112 181-203.5T720-552q0-109-69.5-178.5T480-800q-101 0-170.5 69.5T240-552q0 71 59 162.5T480-186Zm0 106Q319-217 239.5-334.5T160-552q0-150 96.5-239T480-880q127 0 223.5 89T800-552q0 100-79.5 217.5T480-80Zm0-480Z"/></svg>

After

Width:  |  Height:  |  Size: 461 B

View File

@@ -44,15 +44,39 @@
<section class="contact-layout">
<div class="office-list">
<article>
<span>Head Office</span>
<h2>대구 본사</h2>
<p>대구광역시 북구 경대로17길 47, 8층 803호<br />(복현동, IT융합산업빌딩)</p>
<article class="office-location">
<div>
<span>Head Office</span>
<h2>대구 본사</h2>
<p>대구광역시 북구 경대로17길 47, 8층 803호<br />(복현동, IT융합산업빌딩)</p>
</div>
<button
type="button"
class="office-map-button"
data-map-title="대구 본사"
data-map-address="대구광역시 북구 경대로17길 47 IT융합산업빌딩"
aria-label="대구 본사 지도 보기"
title="지도 보기"
>
<img src="assets/icons/location_on.svg" alt="" />
</button>
</article>
<article>
<span>Seoul Office</span>
<h2>서울 사무소</h2>
<p>서울특별시 강남구 논현로 416<br />운기빌딩 6층</p>
<article class="office-location">
<div>
<span>Seoul Office</span>
<h2>서울 사무소</h2>
<p>서울특별시 강남구 논현로 416<br />운기빌딩 6층</p>
</div>
<button
type="button"
class="office-map-button"
data-map-title="서울 사무소"
data-map-address="서울특별시 강남구 논현로 416 운기빌딩"
aria-label="서울 사무소 지도 보기"
title="지도 보기"
>
<img src="assets/icons/location_on.svg" alt="" />
</button>
</article>
<article>
<span>Office Hour</span>

View File

@@ -1579,6 +1579,39 @@ code {
border: 1px solid var(--line);
}
.office-location {
display: grid;
grid-template-columns: minmax(0, 1fr) 40px;
gap: 18px;
align-items: center;
}
.office-map-button {
display: grid;
place-items: center;
width: 40px;
height: 40px;
padding: 0;
color: var(--text);
border: 1px solid var(--line-strong);
border-radius: 4px;
background: rgba(255, 255, 255, .05);
cursor: pointer;
transition: border-color .2s var(--ease), background .2s var(--ease), transform .2s var(--ease);
}
.office-map-button img {
width: 20px;
height: 20px;
}
.office-map-button:hover,
.office-map-button:focus-visible {
border-color: var(--accent);
background: rgba(158, 233, 255, .12);
transform: translateX(2px);
}
.office-list h2 {
margin-bottom: 10px;
}
@@ -1948,6 +1981,50 @@ html.has-site-dialog,
font-size: 12px;
}
.location-dialog {
width: min(960px, calc(100% - 32px));
}
.location-map-content {
padding: 0;
overflow: hidden;
}
.location-map-frame {
display: block;
width: 100%;
height: min(58dvh, 560px);
min-height: 360px;
border: 0;
background: #0b1013;
}
.location-map-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
padding: 16px 24px;
border-top: 1px solid var(--line);
}
.location-map-meta p {
margin: 0;
}
.location-map-meta a {
display: inline-flex;
flex: 0 0 auto;
align-items: center;
gap: 6px;
font-weight: 750;
}
.location-map-meta img {
width: 18px;
height: 18px;
}
.sitemap-groups {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -1977,6 +2054,22 @@ html.has-site-dialog,
.site-dialog-content {
padding: 16px;
}
.location-map-content {
padding: 0;
}
.location-map-frame {
height: 52dvh;
min-height: 280px;
}
.location-map-meta {
align-items: flex-start;
flex-direction: column;
gap: 10px;
padding: 14px 16px;
}
}
.contact-body button:disabled {

View File

@@ -276,6 +276,20 @@
</nav>`,
},
};
function prepareDialog(dialog) {
dialog.querySelector(".dialog-close")?.addEventListener("click", () => dialog.close());
dialog.addEventListener("click", (event) => {
const rect = dialog.getBoundingClientRect();
const clickedOutside = event.target === dialog && (
event.clientX < rect.left || event.clientX > rect.right ||
event.clientY < rect.top || event.clientY > rect.bottom
);
if (clickedOutside) dialog.close();
});
dialog.addEventListener("close", () => document.documentElement.classList.remove("has-site-dialog"));
}
Object.entries(modalContent).forEach(([key, content]) => {
const dialog = document.createElement("dialog");
dialog.className = "site-dialog";
@@ -288,19 +302,10 @@
</header>
<div class="site-dialog-content">${content.body}</div>`;
document.body.appendChild(dialog);
dialog.querySelector(".dialog-close").addEventListener("click", () => dialog.close());
dialog.addEventListener("click", (event) => {
const rect = dialog.getBoundingClientRect();
const clickedOutside = event.target === dialog && (
event.clientX < rect.left || event.clientX > rect.right ||
event.clientY < rect.top || event.clientY > rect.bottom
);
if (clickedOutside) dialog.close();
});
prepareDialog(dialog);
dialog.querySelectorAll(".sitemap-groups a").forEach((link) => {
link.addEventListener("click", () => dialog.close());
});
dialog.addEventListener("close", () => document.documentElement.classList.remove("has-site-dialog"));
document.querySelectorAll(`[data-site-modal="${key}"]`).forEach((trigger) => {
trigger.setAttribute("aria-haspopup", "dialog");
trigger.setAttribute("aria-controls", dialog.id);
@@ -312,6 +317,53 @@
});
});
const mapTriggers = document.querySelectorAll("[data-map-address]");
if (mapTriggers.length) {
const dialog = document.createElement("dialog");
dialog.className = "site-dialog location-dialog";
dialog.id = "office-map-dialog";
dialog.setAttribute("aria-labelledby", "office-map-title");
dialog.innerHTML = `
<header class="site-dialog-header">
<h2 id="office-map-title">오시는 길</h2>
<button type="button" class="dialog-close" aria-label="닫기" title="닫기">&#215;</button>
</header>
<div class="site-dialog-content location-map-content">
<iframe class="location-map-frame" title="회사 위치 지도" loading="lazy" referrerpolicy="no-referrer-when-downgrade" allowfullscreen></iframe>
<div class="location-map-meta">
<p data-location-address></p>
<a data-location-link href="https://www.google.com/maps" target="_blank" rel="noopener noreferrer">
Google 지도에서 크게 보기
<img src="assets/icons/arrow_outward.svg" alt="" />
</a>
</div>
</div>`;
document.body.appendChild(dialog);
prepareDialog(dialog);
const title = dialog.querySelector("#office-map-title");
const frame = dialog.querySelector(".location-map-frame");
const addressLabel = dialog.querySelector("[data-location-address]");
const mapLink = dialog.querySelector("[data-location-link]");
mapTriggers.forEach((trigger) => {
trigger.setAttribute("aria-haspopup", "dialog");
trigger.setAttribute("aria-controls", dialog.id);
trigger.addEventListener("click", () => {
const office = trigger.dataset.mapTitle;
const address = trigger.dataset.mapAddress;
const query = encodeURIComponent(address);
title.textContent = `${office} 오시는 길`;
frame.title = `${office} 위치 지도`;
frame.src = `https://maps.google.com/maps?q=${query}&z=16&output=embed`;
addressLabel.textContent = address;
mapLink.href = `https://www.google.com/maps/search/?api=1&query=${query}`;
dialog.showModal();
document.documentElement.classList.add("has-site-dialog");
});
});
dialog.addEventListener("close", () => frame.removeAttribute("src"));
}
// 문의하기: PocketBase에 문의와 첨부파일을 저장.
const form = document.querySelector("[data-contact-form]");
if (form) {