theme: 홈 피드·사이드바·유저 메뉴 동작 보정
Made-with: Cursor
This commit is contained in:
@@ -108,6 +108,36 @@ menu {
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.site-shell-wrap {
|
||||
height: calc(100vh - var(--topbar-height));
|
||||
}
|
||||
|
||||
.site-shell {
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.site-main {
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.sidebar--left,
|
||||
.sidebar--right {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar,
|
||||
.site-main {
|
||||
min-width: 0;
|
||||
@@ -731,6 +761,10 @@ body:not(.left-sidebar-collapsed) .topbar__sidebar-toggle-icon--close {
|
||||
padding-inline: 14px;
|
||||
}
|
||||
|
||||
[data-featured-track]::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
@@ -1450,7 +1484,7 @@ body:not(.left-sidebar-collapsed) .topbar__sidebar-toggle-icon--close {
|
||||
|
||||
.kg-content .kg-width-wide {
|
||||
position: relative;
|
||||
width: min(100vw - 48px, 820px);
|
||||
width: min(100vw - 48px, 680px);
|
||||
max-width: none;
|
||||
margin-left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -153,6 +153,28 @@
|
||||
|
||||
syncLeftSidebarState();
|
||||
|
||||
var siteMain = document.querySelector(".site-main");
|
||||
var sidebarNodes = document.querySelectorAll(".sidebar--left, .sidebar--right");
|
||||
|
||||
function shouldProxySidebarWheel() {
|
||||
return !tabletMedia.matches && !!siteMain;
|
||||
}
|
||||
|
||||
sidebarNodes.forEach(function (sidebar) {
|
||||
sidebar.addEventListener("wheel", function (event) {
|
||||
if (!shouldProxySidebarWheel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
siteMain.scrollBy({
|
||||
top: event.deltaY,
|
||||
left: 0,
|
||||
behavior: "auto"
|
||||
});
|
||||
}, { passive: false });
|
||||
});
|
||||
|
||||
var tabRoot = document.querySelector("[data-tabs]");
|
||||
if (tabRoot) {
|
||||
var triggers = tabRoot.querySelectorAll("[data-tab-trigger]");
|
||||
@@ -259,6 +281,96 @@
|
||||
}
|
||||
});
|
||||
|
||||
var userMenuToggle = document.querySelector("[data-user-menu-toggle]");
|
||||
var userMenu = document.querySelector("[data-user-menu]");
|
||||
var userThemeToggle = document.querySelector("[data-user-theme-toggle]");
|
||||
var userMenuStateToggle = document.querySelector("[data-user-menu-state-toggle]");
|
||||
var userThemeTrack = document.querySelector("[data-user-theme-track]");
|
||||
var userThemeThumb = document.querySelector("[data-user-theme-thumb]");
|
||||
var userMenuTrack = document.querySelector("[data-user-menu-track]");
|
||||
var userMenuThumb = document.querySelector("[data-user-menu-thumb]");
|
||||
|
||||
function syncUserMenuToggles() {
|
||||
var isDark = body.classList.contains("theme-dark");
|
||||
var menuOpen = tabletMedia.matches ? body.classList.contains("left-sidebar-open") : !body.classList.contains("left-sidebar-collapsed");
|
||||
|
||||
if (userThemeTrack) {
|
||||
userThemeTrack.classList.toggle("bg-accent", isDark);
|
||||
userThemeTrack.classList.toggle("bg-brd", !isDark);
|
||||
}
|
||||
if (userThemeThumb) {
|
||||
userThemeThumb.classList.toggle("translate-x-3.5", isDark);
|
||||
userThemeThumb.classList.toggle("translate-x-0", !isDark);
|
||||
}
|
||||
|
||||
if (userMenuTrack) {
|
||||
userMenuTrack.classList.toggle("bg-accent", menuOpen);
|
||||
userMenuTrack.classList.toggle("bg-brd", !menuOpen);
|
||||
}
|
||||
if (userMenuThumb) {
|
||||
userMenuThumb.classList.toggle("translate-x-3.5", menuOpen);
|
||||
userMenuThumb.classList.toggle("translate-x-0", !menuOpen);
|
||||
}
|
||||
}
|
||||
|
||||
function setUserMenu(open) {
|
||||
if (!userMenu) {
|
||||
return;
|
||||
}
|
||||
|
||||
userMenu.classList.toggle("translate-y-0", open);
|
||||
userMenu.classList.toggle("opacity-100", open);
|
||||
userMenu.classList.toggle("visible", open);
|
||||
userMenu.classList.toggle("scale-100", open);
|
||||
userMenu.classList.toggle("pointer-events-auto", open);
|
||||
userMenu.classList.toggle("-translate-y-4", !open);
|
||||
userMenu.classList.toggle("opacity-0", !open);
|
||||
userMenu.classList.toggle("invisible", !open);
|
||||
userMenu.classList.toggle("scale-95", !open);
|
||||
userMenu.classList.toggle("pointer-events-none", !open);
|
||||
}
|
||||
|
||||
if (userMenuToggle && userMenu) {
|
||||
userMenuToggle.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setUserMenu(userMenu.classList.contains("invisible"));
|
||||
syncUserMenuToggles();
|
||||
});
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
if (!event.target.closest("[data-user-menu]") && !event.target.closest("[data-user-menu-toggle]")) {
|
||||
setUserMenu(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (userThemeToggle) {
|
||||
userThemeToggle.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setTheme(body.classList.contains("theme-dark") ? "light" : "dark");
|
||||
syncUserMenuToggles();
|
||||
});
|
||||
}
|
||||
|
||||
if (userMenuStateToggle) {
|
||||
userMenuStateToggle.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var isOverlay = tabletMedia.matches;
|
||||
var isOpen = isOverlay ? body.classList.contains("left-sidebar-open") : !body.classList.contains("left-sidebar-collapsed");
|
||||
if (isOpen) {
|
||||
closeLeftSidebar();
|
||||
} else {
|
||||
openLeftSidebar();
|
||||
}
|
||||
syncUserMenuToggles();
|
||||
});
|
||||
}
|
||||
|
||||
syncUserMenuToggles();
|
||||
|
||||
function updateLoadMoreState(pagination, nextUrl, loading) {
|
||||
var trigger = pagination.querySelector("[data-load-more-trigger]");
|
||||
if (!trigger) {
|
||||
@@ -338,4 +450,41 @@
|
||||
document.querySelectorAll("[data-load-more-root]").forEach(function (rootNode) {
|
||||
initializeLoadMore(rootNode);
|
||||
});
|
||||
|
||||
document.querySelectorAll("[data-featured-slider]").forEach(function (sliderRoot) {
|
||||
var track = sliderRoot.querySelector("[data-featured-track]");
|
||||
var prev = sliderRoot.querySelector("[data-featured-prev]");
|
||||
var next = sliderRoot.querySelector("[data-featured-next]");
|
||||
|
||||
if (!track || !prev || !next) {
|
||||
return;
|
||||
}
|
||||
|
||||
function getStep() {
|
||||
var firstCard = track.querySelector(".featured-slider__item");
|
||||
if (!firstCard) {
|
||||
return 320;
|
||||
}
|
||||
var gap = 20;
|
||||
return firstCard.getBoundingClientRect().width + gap;
|
||||
}
|
||||
|
||||
function syncButtons() {
|
||||
var maxLeft = Math.max(0, track.scrollWidth - track.clientWidth - 2);
|
||||
prev.disabled = track.scrollLeft <= 1;
|
||||
next.disabled = track.scrollLeft >= maxLeft;
|
||||
}
|
||||
|
||||
prev.addEventListener("click", function () {
|
||||
track.scrollBy({ left: -getStep(), behavior: "smooth" });
|
||||
});
|
||||
|
||||
next.addEventListener("click", function () {
|
||||
track.scrollBy({ left: getStep(), behavior: "smooth" });
|
||||
});
|
||||
|
||||
track.addEventListener("scroll", syncButtons, { passive: true });
|
||||
window.addEventListener("resize", syncButtons);
|
||||
syncButtons();
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# 의사결정 이력
|
||||
|
||||
## 2026-04-16 v0.1.40
|
||||
홈 메인에서 4개 탭을 유지하면 원본 화면과 다르게 상단 컨트롤이 과해지고, 실제 요구사항인 Featured 강조 흐름이 약해진다. 그래서 탭형 전환 UI를 홈 진입 구조에서 제거하고, Featured가 있을 때만 수평 슬라이드로 노출한 뒤 Latest 리스트를 바로 이어 붙이는 구성으로 정리했다. 이 방식은 원본의 정보 우선순위(Featured -> Latest)를 그대로 따르면서 Ghost `featured:true` 데이터도 자연스럽게 재사용할 수 있다.
|
||||
|
||||
## 2026-04-16 v0.1.40
|
||||
최근 수정이 누적되면서 `update/spec/map/deploy/history` 문서의 버전 표기가 서로 어긋났고, 커밋 메시지도 기존 저장소 패턴과 달라져 추적성이 떨어졌다. 그래서 이번에는 기능 자체를 더 넓게 바꾸기보다, 이미 진행한 홈 히어로/탭 피드/태그 카드 보정 작업을 기준으로 문서 버전 체계를 `v0.1.40`으로 맞추고 기록 형식을 기존 흐름에 맞춰 정리했다. 이렇게 해야 다음 작업자가 문서와 커밋 히스토리만 보고도 현재 상태를 빠르게 파악할 수 있다.
|
||||
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
- [home.hbs](/Users/bicute/Desktop/UGREEN/GHOST%20THEME/home.hbs): 메인 홈
|
||||
- [index.hbs](/Users/bicute/Desktop/UGREEN/GHOST%20THEME/index.hbs): 기본 목록 진입
|
||||
- [partials/home/hero.hbs](/Users/bicute/Desktop/UGREEN/GHOST%20THEME/partials/home/hero.hbs): 홈 히어로 영역
|
||||
- [partials/home/tabbed-feed.hbs](/Users/bicute/Desktop/UGREEN/GHOST%20THEME/partials/home/tabbed-feed.hbs): Latest/Featured/Updated/Categories 탭과 카테고리 개요 행
|
||||
- [partials/lists/post-feed.hbs](/Users/bicute/Desktop/UGREEN/GHOST%20THEME/partials/lists/post-feed.hbs): 홈 Featured 슬라이드와 Latest 리스트 묶음
|
||||
- [partials/lists/post-items.hbs](/Users/bicute/Desktop/UGREEN/GHOST%20THEME/partials/lists/post-items.hbs): Tailwind 기반 리스트형 포스트 카드, 댓글 아이콘, 우측 공유 액션, 메타 정보, 태그 accent 배지
|
||||
- [partials/lists/post-feed.hbs](/Users/bicute/Desktop/UGREEN/GHOST%20THEME/partials/lists/post-feed.hbs): 목록 래퍼와 `Load More` 확장형 페이지네이션 연결
|
||||
|
||||
## 상세 및 아카이브
|
||||
- [post.hbs](/Users/bicute/Desktop/UGREEN/GHOST%20THEME/post.hbs): 포스트 상세
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
- 태그/작성자 디렉터리 목록은 현재 `limit="100"` 기준
|
||||
- `tags-index.hbs`, `authors-index.hbs`는 Ghost `routes.yaml` 커스텀 라우트로 `/tags/`, `/authors/`에 연결됨
|
||||
- 로컬 개발 환경의 실제 라우트 설정은 `.docker/ghost/content/settings/routes.yaml`을 기준으로 사용함
|
||||
- 홈 메인 피드는 히어로, 탭형 목록, 카테고리 개요를 원본 비주얼 밀도에 가깝게 재구성
|
||||
- 홈 메인 피드는 히어로, Featured 수평 슬라이드, Latest 리스트 구성을 사용함
|
||||
- 리스트형 `post-card`는 Tailwind 유틸리티 중심 마크업으로 구성되며, 썸네일은 `aspect-square sm:aspect-video` 비율을 사용
|
||||
- 각 카드 항목은 `border-b border-brd` 구분선을 유지하고, 콘텐츠 래퍼는 `min-w-0` 기준으로 줄바꿈 폭을 제어
|
||||
- 포스트 상세 헤더는 제목, 메타, 공유 버튼, 대표 이미지를 Tailwind 유틸리티 중심 마크업으로 구성하고 상단 단일 태그 라벨은 표시하지 않음
|
||||
|
||||
@@ -4,6 +4,26 @@
|
||||
- 문서 버전 표기를 `v0.1.40`으로 정합성 수정.
|
||||
- `docs/history.md` 의사결정 이력 최신 버전 항목 추가.
|
||||
- 홈 히어로/탭 피드/태그 카드 원본 기준 보정 작업 반영 및 형식 정리.
|
||||
- `partials/site/sidebar-left.hbs` Authors 섹션을 원본 구조 기준 아코디언/hover 인터랙션 형태로 수정.
|
||||
- `partials/site/sidebar-left.hbs` Authors 헤더 양식을 Categories와 동일한 `sidebar-card` 패턴으로 통일하고, 썸네일/등급 텍스트/hover 점 전환 동작을 보정.
|
||||
- `partials/site/sidebar-left.hbs` Authors 보조 텍스트를 `role` 우선 표시로 수정하고, 하단 네비게이션 닫힘 태그 오류(`</footer>`→`</nav>`)와 좌측 사이드바 하단 고정 레이아웃을 보정.
|
||||
- `partials/site/sidebar-left.hbs` Authors hover 점 아이콘이 배경에 묻히던 문제를 대비 색/위치/전환값으로 보정해 항상 보이도록 수정.
|
||||
- `partials/site/sidebar-left.hbs` Authors 보조 텍스트에서 `location` 노출을 제거하고 `role`만 표시하도록 수정.
|
||||
- `partials/site/sidebar-left.hbs` Authors hover 점 아이콘 색상을 Tailwind 유틸리티 대신 `--text` 기반 `color-mix` 인라인 값으로 고정해 테마 색상과 충돌 없이 표시되도록 수정.
|
||||
- `partials/site/sidebar-left.hbs` Authors hover 배경색을 `#f5f5f5`로 조정하고 hover 점 아이콘 대비를 더 진하게 보정.
|
||||
- `partials/site/sidebar-left.hbs` Authors hover 점 아이콘 색상을 브랜드 액센트(`--accent`) 고정으로 변경.
|
||||
- `partials/site/topbar.hbs` 우측 모바일 검색 버튼을 계정 버튼으로 교체하고, 로그인 시 멤버 아바타/비로그인 시 기본 유저 아이콘 노출로 수정.
|
||||
- `partials/site/topbar.hbs` 유저 아이콘 클릭 시 열리는 사용자 메뉴 모달(계정/회원 액션, 다크모드 토글, 메뉴 열림 토글) 추가.
|
||||
- `partials/site/topbar.hbs` 유저 메뉴가 아이콘 내부 SVG 클릭 시 즉시 닫히던 조건을 `closest()` 기반으로 수정하고, 데스크톱에서도 보이도록 유저 버튼 클래스를 분리.
|
||||
- `partials/site/topbar.hbs`, `assets/built/theme.js` 유저 메뉴 모달 토글을 Alpine 의존에서 공통 스크립트 기반으로 전환해 클릭/외부 클릭 열고닫기와 스위치 상태 동기화를 안정화.
|
||||
- `partials/site/topbar.hbs`, `assets/built/theme.js` 유저 메뉴 스위치 클릭 시 모달이 닫히지 않도록 이벤트 전파를 차단하고, 다크모드를 공통 `setTheme()` 직접 호출 방식으로 보정.
|
||||
- `assets/built/screen.css`, `assets/built/theme.js` 데스크톱에서 사이드바는 화면 고정/중앙 본문만 스크롤되도록 레이아웃을 조정하고, 사이드바 영역 휠 입력을 중앙 본문 스크롤로 전달하도록 수정.
|
||||
- `home.hbs`, `partials/lists/post-feed.hbs` 홈 피드 구조를 탭형에서 Featured 슬라이드 + Latest 리스트 구성으로 전환.
|
||||
- `assets/built/theme.js` Featured 슬라이드 좌/우 버튼 스크롤 제어 및 비활성 상태 동기화 로직 추가.
|
||||
- `docs/spec.md`, `docs/map.md`, `docs/history.md` 홈 피드 구조 변경 기준으로 문서 정합성 갱신.
|
||||
- `partials/lists/post-feed.hbs` Featured 카드에서 썸네일 미존재 시 텍스트를 검은색으로 보정하고, 썸네일 카드와 동일한 라디우스/테두리 형태로 통일.
|
||||
- `assets/built/screen.css` Featured 가로 슬라이드 스크롤바 비노출 처리 추가.
|
||||
- `partials/site/sidebar-right.hbs` 우측 사이드바를 세로 플렉스 구조로 보정해 하단 footer가 화면 하단에 고정되도록 수정.
|
||||
|
||||
## v0.1.39 - 2026-04-16
|
||||
- `tags-index.hbs` 태그 카드 목록 마크업을 원본(Thred) 구조 기준으로 변환 수정.
|
||||
|
||||
2
home.hbs
2
home.hbs
@@ -2,5 +2,5 @@
|
||||
|
||||
<main class="content-area">
|
||||
{{> "home/hero"}}
|
||||
{{> "home/tabbed-feed"}}
|
||||
{{> "lists/post-feed" posts=posts}}
|
||||
</main>
|
||||
|
||||
@@ -1,9 +1,63 @@
|
||||
<div class="post-feed" data-load-more-root>
|
||||
{{#if show_filter}}
|
||||
<div class="section-filter">
|
||||
<span>Latest posts</span>
|
||||
<section class="px-5 sm:px-6 py-4" data-home-featured>
|
||||
<div class="max-w-content mx-auto">
|
||||
{{#get "posts" filter="featured:true" limit="12" include="authors,tags"}}
|
||||
{{#if posts}}
|
||||
<section data-featured-slider>
|
||||
<div class="flex gap-2 items-end justify-between border-b border-brd pb-2">
|
||||
<h2 class="text-sm uppercase font-medium text-typ-tone">Featured</h2>
|
||||
<div class="flex justify-between gap-2">
|
||||
<button class="cursor-pointer hover:opacity-75 disabled:opacity-40" data-featured-prev type="button">
|
||||
<i class="icon icon-chevron-left size-4 stroke-2" role="presentation">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M15 6l-6 6l6 6"></path>
|
||||
</svg>
|
||||
</i>
|
||||
<span class="sr-only">Previous</span>
|
||||
</button>
|
||||
<button class="cursor-pointer hover:opacity-75 disabled:opacity-40" data-featured-next type="button">
|
||||
<span class="sr-only">Next</span>
|
||||
<i class="icon icon-chevron-right size-4 stroke-2" role="presentation">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M9 6l6 6l-6 6"></path>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-hidden mt-4">
|
||||
<div class="featured-slider flex gap-4 sm:gap-5 overflow-x-auto snap-x snap-mandatory scroll-smooth" data-featured-track style="scrollbar-width: none; -ms-overflow-style: none;">
|
||||
{{#foreach posts}}
|
||||
<a href="{{url}}" class="featured-slider__item relative bg-bgr-tone block group shrink-0 snap-start basis-[78%] sm:basis-[58%] lg:basis-[38%]">
|
||||
{{#if feature_image}}
|
||||
<figure class="relative block rounded-theme overflow-hidden contrast-125 brightness-75 group-hover:contrast-110 group-hover:brightness-90 transition-all" role="none">
|
||||
<img class="w-full aspect-video object-cover rounded-[inherit]" src="{{img_url feature_image size="m"}}" alt="{{title}}">
|
||||
</figure>
|
||||
<h2 class="text-white absolute bottom-0 left-0 w-full px-3 mb-2.5 text-sm font-medium leading-tight line-clamp-2 text-ellipsis">{{title}}</h2>
|
||||
{{else}}
|
||||
<figure class="relative rounded-theme overflow-hidden bg-bgr-tone aspect-video border border-brd p-3 flex items-end" role="none">
|
||||
<h2 class="text-typ w-full text-sm font-medium leading-tight line-clamp-2 text-ellipsis">{{title}}</h2>
|
||||
</figure>
|
||||
{{/if}}
|
||||
</a>
|
||||
{{/foreach}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{/if}}
|
||||
{{/get}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="px-5 sm:px-6 py-4" data-home-latest>
|
||||
<div class="max-w-content mx-auto">
|
||||
<div class="flex gap-2 items-end justify-between border-b border-brd pb-2">
|
||||
<h2 class="text-sm uppercase font-medium text-typ-tone">Latest</h2>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{> "lists/post-items" posts=posts}}
|
||||
{{pagination}}
|
||||
</div>
|
||||
<div class="flex flex-col gap-8 mb-8 mt-1" data-load-more-root>
|
||||
{{> "lists/post-items" posts=posts}}
|
||||
{{pagination}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
<h2 class="text-sm font-medium leading-tight flex flex-wrap gap-y-0.5 gap-x-1.5 items-end max-w-[90%]" data-post-card-title>
|
||||
<a href="{{url}}" class="hover:opacity-75 flex items-start gap-1.5">
|
||||
{{#if featured}}
|
||||
<span data-post-featured class="icon icon-bolt size-4 stroke-1 fill-current5">
|
||||
<img class="size-4 -mt-0.5" src="{{asset "icons/bolt.svg"}}" alt="">
|
||||
<span data-post-featured="" class="inline-flex text-brand -mr-0.5 [&_svg]:-mt-0.5">
|
||||
<i class="icon icon-bolt size-4 stroke-1 fill-current" role="presentation">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-bolt"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M13 3l0 7l6 0l-8 11l0 -7l-6 0l8 -11"></path></svg>
|
||||
</i>
|
||||
</span>
|
||||
{{/if}}
|
||||
<span>{{title}}</span>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<aside class="sidebar sidebar--left">
|
||||
<aside class="sidebar sidebar--left h-full flex flex-col">
|
||||
<nav class="menu-groups border-b border-brd pl-4 pr-3 sm:pl-5 xl:pl-0 py-3" data-nav="menu" data-primary-nav x-data="{ homePagesOpen: true, membersOpen: false }">
|
||||
<ul class="menu-groups__list flex flex-col gap-0.75 text-typ text-sm">
|
||||
<li class="menu-group menu-group--nav nav-toggle is-mainitem flex items-center flex-wrap w-full relative group" :class="{ 'is-open': homePagesOpen }" data-label="Home pages" data-slug="home-pages" data-length="10" aria-haspopup="true">
|
||||
@@ -78,27 +78,36 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="px-5 sm:px-6 py-4 sm:py-5 xl:pl-0 pr-3 sm:pr-3 flex flex-col gap-1.5 border-b border-brd">
|
||||
<div class="sidebar-card__header">
|
||||
<h2>Authors</h2>
|
||||
</div>
|
||||
<div class="author-list">
|
||||
<section class="sidebar-card sidebar-card--authors border-b border-brd px-5 sm:px-6 py-4 sm:py-5 xl:pl-0 pr-3 sm:pr-3 flex flex-col gap-1.5" x-data="{ authorsOpen: window.innerWidth >= 1024 }" x-init="window.addEventListener('resize', () => { authorsOpen = window.innerWidth >= 1024 })" data-sidebar-authors>
|
||||
<button class="sidebar-card__trigger flex items-center gap-1 justify-between cursor-pointer pr-2 hover:opacity-75" type="button" @click="authorsOpen = !authorsOpen" :aria-expanded="authorsOpen.toString()">
|
||||
<span class="sidebar-card__eyebrow uppercase font-medium text-xs">Authors</span>
|
||||
<span class="sidebar-card__chevron" aria-hidden="true">
|
||||
<img x-show="!authorsOpen" x-cloak class="sidebar-card__chevron-icon sidebar-card__chevron-icon--down" src="{{asset "icons/keyboard_arrow_down.svg"}}" alt="">
|
||||
<img x-show="authorsOpen" x-cloak class="sidebar-card__chevron-icon sidebar-card__chevron-icon--up" src="{{asset "icons/keyboard_arrow_up.svg"}}" alt="">
|
||||
</span>
|
||||
</button>
|
||||
<ul class="sidebar-card__content sidebar-card__content--authors flex flex-col gap-0.5 mt-1 text-typ-tone font-medium text-[0.8rem] -mb-1.5" x-cloak x-show="authorsOpen">
|
||||
{{#get "authors" limit="4" include="count.posts"}}
|
||||
{{#foreach authors}}
|
||||
<a class="author-list__item" href="{{url}}">
|
||||
{{#if profile_image}}
|
||||
<img class="avatar" src="{{img_url profile_image size="xxs"}}" alt="{{name}}">
|
||||
{{else}}
|
||||
<span class="avatar avatar--fallback">A</span>
|
||||
{{/if}}
|
||||
<span class="author-list__body">
|
||||
<strong>{{name}}</strong>
|
||||
<small>{{plural count.posts empty="No posts" singular="% post" plural="% posts"}}</small>
|
||||
</span>
|
||||
</a>
|
||||
{{#foreach authors}}
|
||||
<li>
|
||||
<a href="{{url}}" class="group relative flex items-center gap-1.5 leading-tight pl-0 pr-3 py-1 rounded-theme hover:text-typ hover:bg-[#f5f5f5] transition-[padding] min-h-8 md:min-h-10 hover:pl-7" aria-label="{{name}}">
|
||||
{{#if profile_image}}
|
||||
<figure class="size-6 md:size-7 rounded-full overflow-hidden transition-all group-hover:size-0">
|
||||
<img class="w-full h-full object-cover rounded-full" src="{{img_url profile_image size="s"}}" alt="">
|
||||
</figure>
|
||||
{{else}}
|
||||
<span class="size-6 md:size-7 rounded-full bg-bgr-tone flex items-center justify-center text-[11px] transition-all group-hover:size-0">A</span>
|
||||
{{/if}}
|
||||
<span class="absolute left-3.5 top-1/2 z-10 block size-2 rounded-full opacity-0 scale-75 -translate-y-1/2 -translate-x-1 transition-all duration-200 group-hover:opacity-100 group-hover:scale-100 group-hover:translate-x-0" style="background-color: var(--accent);"></span>
|
||||
<span class="flex-1 min-w-0 flex flex-col gap-0.5 group-hover:gap-0 overflow-hidden">
|
||||
<span class="line-clamp-1 text-ellipsis leading-none">{{name}}</span>
|
||||
<span class="text-xs text-typ-tone leading-none line-clamp-1 text-ellipsis opacity-75 group-hover:invisible group-hover:w-0 group-hover:h-0 group-hover:opacity-0 transition-all group-hover:translate-y-full">{{#if role}}{{role}}{{else}}Author{{/if}}</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{/foreach}}
|
||||
{{/get}}
|
||||
</div>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<span class="flex-1"></span>
|
||||
@@ -111,5 +120,5 @@
|
||||
<li><a href="{{@custom.footer_quaternary_url}}">{{@custom.footer_quaternary_link}}</a></li>
|
||||
</ul>
|
||||
<button class="flex items-center self-start gap-1 p-1 size-6 rounded-theme hover:bg-bgr-tone cursor-pointer text-xs font-medium" data-theme-toggle aria-label="Toggle theme">◐</button>
|
||||
</footer>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<aside class="sidebar sidebar--right">
|
||||
<aside class="sidebar sidebar--right h-full flex flex-col">
|
||||
{{#is "post"}}
|
||||
{{#post}}
|
||||
{{#primary_author}}
|
||||
@@ -102,7 +102,7 @@
|
||||
</section>
|
||||
{{/post}}
|
||||
{{/is}}
|
||||
<span class="md:flex-1"></span>
|
||||
<span class="flex-1"></span>
|
||||
<footer class="px-5 sm:px-6 xl:pr-1">
|
||||
<div class="py-3 flex flex-col items-start justify-start text-typ-tone text-xs">
|
||||
©{{date format="YYYY"}} {{@site.title}}. Published with Ghost.
|
||||
|
||||
@@ -16,10 +16,96 @@
|
||||
<span class="search-shortcut">/</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="topbar__actions flex h-full items-center justify-end gap-2 px-4">
|
||||
<button class="icon-button icon-button--search-mobile inline-flex items-center justify-center rounded-theme border border-brd bg-bgr hover:bg-bgr-tone" type="button" data-search-open aria-label="Open search">
|
||||
<img class="search-trigger__icon" src="{{asset "icons/search.svg"}}" alt="">
|
||||
<div class="topbar__actions relative flex h-full items-center justify-end gap-2 px-4">
|
||||
<button class="icon-button icon-button--user-menu inline-flex items-center justify-center rounded-theme border border-brd bg-bgr hover:bg-bgr-tone overflow-hidden" type="button" aria-label="Open user menu" data-user-menu-toggle>
|
||||
{{#if @member}}
|
||||
{{#if @member.avatar_image}}
|
||||
<img class="w-full h-full object-cover" src="{{@member.avatar_image}}" alt="{{@member.name}}">
|
||||
{{else}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" role="presentation" aria-hidden="true">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0"></path>
|
||||
<path d="M12 10m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0"></path>
|
||||
<path d="M6.168 18.849a4 4 0 0 1 3.832 -2.849h4a4 4 0 0 1 3.834 2.855"></path>
|
||||
</svg>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" role="presentation" aria-hidden="true">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0"></path>
|
||||
<path d="M12 10m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0"></path>
|
||||
<path d="M6.168 18.849a4 4 0 0 1 3.832 -2.849h4a4 4 0 0 1 3.834 2.855"></path>
|
||||
</svg>
|
||||
{{/if}}
|
||||
</button>
|
||||
<div class="z-50 p-3 pb-2 flex flex-col text-sm bg-bgr border border-brd rounded-theme absolute top-12 right-0 -translate-y-4 opacity-0 invisible pointer-events-none transition-[transform,opacity,visibility,scale] min-w-[200px] max-w-xs overflow-hidden font-medium scale-95 shadow-md" style="background-color: var(--bg);" data-user-menu>
|
||||
<div class="flex items-center gap-2 border-b border-brd pb-3 mb-2">
|
||||
<div class="size-8 md:size-10 rounded-full overflow-hidden bg-bgr-tone">
|
||||
{{#if @member}}
|
||||
{{#if @member.avatar_image}}
|
||||
<img class="size-8 md:size-10 object-cover" src="{{@member.avatar_image}}" alt="{{@member.name}}">
|
||||
{{else}}
|
||||
<span class="size-8 md:size-10 flex items-center justify-center uppercase font-normal text-base md:text-lg">@</span>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<span class="size-8 md:size-10 flex items-center justify-center uppercase font-normal text-base md:text-lg">@</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="flex gap-0.5 flex-col">
|
||||
<div class="line-clamp-1 text-ellipsis leading-[1.15] max-w-xs">{{#if @member}}{{@member.name}}{{else}}Anonymous{{/if}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if @member}}
|
||||
<a href="#/portal/account" class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-theme hover:bg-bgr-tone">
|
||||
<i class="icon icon-login size-5 stroke-2" role="presentation">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M9 6l6 0"></path>
|
||||
<path d="M12 3l0 6"></path>
|
||||
<path d="M5 12a7 7 0 0 0 14 0a7 7 0 0 0 -14 0"></path>
|
||||
</svg>
|
||||
</i>
|
||||
<span>Account</span>
|
||||
</a>
|
||||
{{else}}
|
||||
<a href="#/portal/signup" class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-theme hover:bg-bgr-tone">
|
||||
<i class="icon icon-signup size-5 stroke-2" role="presentation">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0"></path>
|
||||
<path d="M15 9l-6 6"></path>
|
||||
<path d="M15 15v-6h-6"></path>
|
||||
</svg>
|
||||
</i>
|
||||
<span>Sign up</span>
|
||||
</a>
|
||||
<a href="#/portal/signin" class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-theme hover:bg-bgr-tone">
|
||||
<i class="icon icon-login size-5 stroke-2" role="presentation">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M15 8v-2a2 2 0 0 0 -2 -2h-7a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2 -2v-2"></path>
|
||||
<path d="M21 12h-13l3 -3"></path>
|
||||
<path d="M11 15l-3 -3"></path>
|
||||
</svg>
|
||||
</i>
|
||||
<span>Sign in</span>
|
||||
</a>
|
||||
{{/if}}
|
||||
<div class="flex flex-col gap-0.5 items-center justify-between border-t border-brd mt-2 pt-2">
|
||||
<button class="group flex items-center justify-between gap-1.5 py-1 pl-0.5 rounded-theme w-full cursor-pointer text-typ-tone hover:text-typ" type="button" data-user-theme-toggle>
|
||||
<span class="uppercase text-xs">Dark mode</span>
|
||||
<span class="inline-flex h-[18px] w-8 shrink-0 rounded-full border-2 border-transparent bg-brd" data-user-theme-track>
|
||||
<span aria-hidden="true" class="pointer-events-none inline-block size-3.5 transform rounded-full bg-white shadow ring-0 transition" data-user-theme-thumb></span>
|
||||
</span>
|
||||
</button>
|
||||
<button class="group flex items-center justify-between gap-1.5 py-1 pl-0.5 rounded-theme w-full cursor-pointer text-typ-tone hover:text-typ" type="button" data-user-menu-state-toggle>
|
||||
<span class="uppercase text-xs">Menu open</span>
|
||||
<span class="inline-flex h-[18px] w-8 shrink-0 rounded-full border-2 border-transparent bg-brd" data-user-menu-track>
|
||||
<span aria-hidden="true" class="pointer-events-none inline-block size-3.5 transform rounded-full bg-white shadow ring-0 transition" data-user-menu-thumb></span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{#if @custom.show_admin_link}}
|
||||
<a class="button button--accent rounded-theme" href="/ghost/">Admin</a>
|
||||
<a class="icon-button icon-button--profile rounded-full border border-brd bg-bgr hover:bg-bgr-tone" href="/ghost/" aria-label="Ghost admin"><span></span></a>
|
||||
|
||||
Reference in New Issue
Block a user