【2024年3月更新】 Nuxt3+Firebase Webアプリ開発手順② レイアウトの設定
更新情報
2024/3/22 記事更新
最新の書き方に合わせました
2023/12/22 Daisyuiを導入
モーダル作成はDaisyuiに任せたほうが良さそう
2023/10/15 TailwindCSS導入方法を更新
nuxtjs/tailwindcssを導入しました
2023/7/20 flowbiteを削りました
いい感じのデザインを素早く作るためにflowbiteは強力なツールでしたが、どうしても記述量が多く見づらくなってしまう欠点がありました。
また、モーダル作成はHTMLエレメントであるdialogを操作したほうがやりやすいので、無理してまでflowbiteを導入するメリットは少なくなり、最近はflowbiteを使うこと自体が減ったためです。
2023/3/10 flowbite、heroiconsを導入しました
- Tailwind単独でも開発はできますが、いい感じのデザインを素早く作るにはflowbiteは強力な助けとなります。
- flowbiteには独自のプログラムやcssが組み込まれており、スタイルをよりシンプルに書くことができます。
例えばモーダル作成はTailwind単独で作ろうとするとかなり大変ですが、flowbiteを使うと特殊な属性を設定するだけで済みます。 - Heroiconsはライブラリをインストールせずともsvgをコピペするだけでも使えますが、結構記述量が多くなります。
2022/11/25 nuxt.config.tsの書き方
nuxt3の正式版リリースに伴い、nuxt.config.tsの書き方を現状に合わせました
全体像
- Nuxt3アプリ作成〜firebaseデプロイ
- レイアウトの設定
- firestoreを使ったデータの読み取り、書き込み、更新
- ログイン機能の実装
スタイル関係のライブラリ
tailwindcss
tailwindcss公式の通りにインストールしても良いのですが、assets/css/tailwind.cssを設定するなど少し面倒です。
nuxtjs/tailwindjsをインストールすると、以下の2ステップで導入できますので格段に楽です
// インストール
$ npm i @nuxtjs/tailwindcss
nuxt.config.tsのmodulesに以下のように追記します
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
modules: [
'@nuxtjs/tailwindcss'
],
})
Daisyui
必須ではないのですが、以下の理由でスタイル用のライブラリを導入しています。
- TailwindCssだけではどうしてもclassの書き方が長くなり、HTMLの見通しが悪くなってしまう。
- 手軽にいい感じのサイトが作るには、予めいい感じにデザインされたUIコンポーネントを配置したほうが良い
古くはvuetify、flowbiteなどいろいろ試しましたが、2023年くらいからDaisyuiに落ち着いています。
導入方法はこちら
$ npm i -D daisyui@latest
なお、nuxtjs/tailwindcssを使う場合はtailwind.config.jsファイルの作成が必要ではないのですが、Daisyuiを導入する際にはtailwind.config.jsを用意して設定を書く必要があります
// tailwind.config.jsを作成
$ npx tailwindcss init
export default {
・・・
plugins: [require("daisyui")],
daisyui: {
themes: ["night","business"], // ここに使用するテーマを列挙
},
}
テーマは、nuxt.config.tsに記述します
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
・・・
app: {
head: {
htmlAttrs: {
lang: 'ja',
"data-theme":"business" // 他に"light","cupcake"など
},
},
},
})
Heroicons
どんなサイトでもアイコンは導入するので、ほぼほぼ必須みたいなものです。
(たまに痒いところに手が届かないことがあるので、もっと良いsvgアイコンライブラリがあれば導入したいところ)
※こっちが公式みたいですが、svgまたはjsxでしかコピーできません。名前でコピーしたほうが便利なので、上記のdevサイトを使っています。
$ npm install @heroicons/vue
vueやNuxtにおいては直接名前を入れて使うこともできますし、
<component :is="~~~">
の形で指定しても使えます
<script setup lang="ts">
import { CheckCircleIcon, HomeIcon, WrenchScrewdriverIcon} from "@heroicons/vue/24/outline";
const pages = [
{
title:'ホーム',
icon:'HomeIcon'
},{
title:'設定',
icon:'WrenchScrewdriverIcon'
}
]
</script>
<template>
普通の使い方
<CheckCircleIcon class="w-6" />
componentに指定することもできる
<li v-for="page of pages">
<div>{{ page.title }}</div>
<component :is="page.icon" class="w-6" />
</li>
</template>
ページレイアウト
TailwindCss、DaisyUi、Heroiconsを全て導入した前提でページレイアウトを作成します。
app.vue
クリックで表示
<template>
<div class="drawer sm:drawer-open">
<input id="my-drawer-3" type="checkbox" class="drawer-toggle" />
<div class="drawer-content flex flex-col">
<!-- Navbar -->
<div class="w-full navbar bg-base-300">
<div class="flex-none ">
<label for="my-drawer-3" aria-label="open sidebar" class="btn btn-square btn-ghost sm:hidden">
<Bars3Icon class="w-8 "></Bars3Icon>
</label>
</div>
<div class="flex-1 px-2 mx-2 font-bold text-3xl">タイトル</div>
<div class="dropdown dropdown-hover dropdown-bottom dropdown-end mr-10">
<div tabindex="0" role="button" class="avatar">
<div class="w-12 rounded-full">
<img :src="currentUser.photoURL" />
</div>
</div>
<ul tabindex="0" class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52">
<li class="menu-title">{{ currentUser.name }}</li>
<li><a>ユーザー情報</a></li>
<li><a>ログアウト</a></li>
</ul>
</div>
</div>
<!-- Page content here -->
<NuxtPage></NuxtPage>
</div>
<div class="drawer-side border-r border-r-gray-400">
<label for="my-drawer-3" aria-label="close sidebar" class="drawer-overlay"></label>
<ul class="menu py-4 px-0 space-y-2 w-14 min-h-full bg-base-200">
<!-- Sidebar content here -->
<li v-for=" p in pages ">
<a @click="navigateTo(p.to)">
<component :is="p.icon" class="w-6" ></component>
</a>
</li>
</ul>
</div>
</div>
全体レイアウトはDaisyuiのDrawerで設定
- drawerとは、ハンバーガーメニューアイコンを押した時に左側からヌッとでてくるサイドバーのこと
- ページ全体のレイアウトを決める要素なので、app.vueに導入するのがおすすめ
- デフォルトではdrawerは非表示。
.drawer-open
を入れることで開いた状態になる
ナビバーはDaisyuiのNavbar
各ページへのリンクメニュー
const pages = [
{
title:'ページ1',
icon:BellAlertIcon,
to:'/page1'
},{
title:'プロフィール',
icon:UserCircleIcon,
to:'/profile'
}
]
<template>
・・・
<div class="drawer-side border-r border-r-gray-400">
<label for="my-drawer-3" aria-label="close sidebar" class="drawer-overlay"></label>
<ul class="menu py-4 px-0 space-y-2 w-14 min-h-full bg-base-200">
<!-- Sidebar content here -->
<li v-for=" p in pages ">
<a @click="navigateTo(p.to)">
<component :is="p.icon" class="w-6" ></component>
</a>
</li>
</ul>
</div>
・・・
</template>
tailwindの便利な設定
theme設定
themeについて以下のように設定すると、'primary'という名前で色指定ができるようになります
module.exports = {
content: [
・・・
],
darkMode: 'class', // or 'media' or 'class'
theme: {
extend: {
colors:{
primary: '#0284c7' // extend下にcolorsを置くことで、追加ができる。(theme直下だと上書きしてしまう)
}
},
},
variants: {
extend: {},
},
plugins: [
require('flowbite/plugin')
],
};
全コンポーネントで共通して使うスタイルの設定
@layerを使うと、スタイル設定ができる。
@applyを使うと、tailwindの書き方でスタイルを設定できる。
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
h1 {
@apply font-extrabold text-2xl
}
}
nuxt/tailwindcssを導入している場合、assets/css/tailwind.cssを作成しなくても良いので、わざわざ作成するのも気が引ける。
なので、app/vueに全体適用のstyleとして設定しています
<div>
<AppBar></AppBar>
<Drawer></Drawer>
<NuxtPage></NuxtPage>
</div>
</template>
<style>
h1{
@apply text-3xl
}
</style>
参考
Discussion