commit 3c2aff697ae9fdac7c48ea2894a9725d9919506a
parent 40a48a69c060164e1c0d784f7a9268e2d13e0447
Author: Sunny <kajimalu10@gmail.com>
Date: Mon, 10 Nov 2025 00:16:27 +0900
add menu
Diffstat:
| M | src/App.vue | | | 37 | ++++++++++++++++++++++++++++++++++++- |
| M | src/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 ===== */