oshiphoto

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 3c2aff697ae9fdac7c48ea2894a9725d9919506a
parent 40a48a69c060164e1c0d784f7a9268e2d13e0447
Author: Sunny <kajimalu10@gmail.com>
Date:   Mon, 10 Nov 2025 00:16:27 +0900

add menu

Diffstat:
Msrc/App.vue | 37++++++++++++++++++++++++++++++++++++-
Msrc/style.css | 121++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 150 insertions(+), 8 deletions(-)

diff --git a/src/App.vue b/src/App.vue @@ -1,6 +1,14 @@ <template> <header> <h1>推しふぉと!</h1> + <button + @click="toggleMenu" + class="menu-button" + :class="{ 'is-open': isMenuOpen }" aria-label="メニュー開閉" + > + <span class="material-symbols-rounded icon-menu">menu</span> + <span class="material-symbols-rounded icon-close">close</span> + </button> </header> <main class="main-content"> @@ -97,7 +105,29 @@ </div> </div> </div> - </main> + </main> + + <Transition name="fade"> + <div + v-if="isMenuOpen" + class="sidebar-overlay" + @click="toggleMenu" + ></div> + </Transition> + + <Transition name="slide"> + <nav v-if="isMenuOpen" class="sidebar-menu"> + <h2>メニュー</h2> + <ul> + <li> + <a href="#">設定</a> + </li> + <li> + <a href="#">利用規約</a> + </li> + </ul> + </nav> + </Transition> </template> <script setup> @@ -113,6 +143,11 @@ const currentBgHtmlImage = ref(null); const editor = ref(null); const canvasWrapperRef = ref(null); const canvasHasImage = ref(false); +const isMenuOpen = ref(false); + +const toggleMenu = () => { + isMenuOpen.value = !isMenuOpen.value; +}; const handleResize = () => { // 必要な要素が揃っていない(背景がまだない等)場合は何もしない diff --git a/src/style.css b/src/style.css @@ -50,14 +50,9 @@ button { html, body, #app { - height: 100%; font-family: inherit; background-color: #f4f4f9; color: #333; -} - -/* App shell for PWA-style layout */ -#app { display: flex; flex-direction: column; height: 100vh; @@ -67,16 +62,128 @@ body, /* Header */ header { flex-shrink: 0; - padding: 6px; + padding: 8px 20px; background-color: #fff; border-bottom: 1px solid #ddd; - text-align: center; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); + display: flex; + justify-content: space-between; + align-items: center; + position: relative; + z-index: 1002; } header h1 { font-size: 1.2rem; font-weight: 600; + margin: 0; +} + +.menu-button { + background: none; + border: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + -webkit-tap-highlight-color: transparent; + position: relative; + overflow: hidden; + width: 26px; + height: 26px; +} + +.menu-button .material-symbols-rounded { + user-select: none; + color: #333; + font-size: 26px; + position: absolute; + top: 50%; + left: 50%; + transition: transform 0.2s ease-out, opacity 0.2s ease-out; + transform: translate(-50%, -50%) scale(1) rotate(0deg); +} + +.menu-button .icon-close { + opacity: 0; + transform: translate(-50%, -50%) scale(0.7) rotate(-90deg); +} +.menu-button .icon-menu { + opacity: 1; + transform: translate(-50%, -50%) scale(1) rotate(0deg); +} + +.menu-button.is-open .icon-close { + opacity: 1; + transform: translate(-50%, -50%) scale(1) rotate(0deg); +} +.menu-button.is-open .icon-menu { + opacity: 0; + transform: translate(-50%, -50%) scale(0.7) rotate(90deg); +} + +/* ===== Menu ===== */ +.sidebar-overlay { + position: fixed; + inset: 0; + background-color: rgba(0, 0, 0, 0.5); + z-index: 1000; +} + +.sidebar-menu { + position: fixed; + top: 0; + right: 0; + width: 200px; + max-width: 60%; + height: 100vh; + padding: 50px 15px 15px 15px; + background-color: #fff; + box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15); + z-index: 1001; + display: flex; + flex-direction: column; +} + +.sidebar-menu h2 { + font-size: 1.2rem; + font-weight: 600; + padding: 6px 6px 6px 6px; + margin: 0 0 6px 0; + border-bottom: 1px solid #999; +} +.sidebar-menu ul { + list-style: none; + padding: 0; + margin: 0; +} +.sidebar-menu li a { + display: block; + padding: 6px; + text-decoration: none; + color: #333; + border-bottom: 1px solid #f9f9f9; +} +.sidebar-menu li a:active { + background-color: #f0f0f0; +} + +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.25s ease; +} +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +.slide-enter-active, +.slide-leave-active { + transition: transform 0.25s ease-out; +} +.slide-enter-from, +.slide-leave-to { + transform: translateX(100%); } /* ===== Main content & columns ===== */