Tailwind CSSのナビゲーション

### live-server
$ npm install live-server
$ npx live-server public –host=0.0.0.0
// ポートが8080になるので注意

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<div>
			<header>
				<div>
					<h1>HR</h1>
						<button>
							<svg class="h-6 w-6 fill-current" viewBox="0 0 24 24">
								<path d="M24 6h-24v-4h24v4zm0 4h-24v4h24v-4zm0 8h-24v4h24v-4z"/>
							</svg>
						</button>
				</div>
			</header>
		</div>
	</div>
	<script>
		cost app = new Vue({
			el: "#app",
			data: {

			}
		});
	</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
	<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<div class="bg-gray-500">
			<header class="container mx-auto text-white">
					<div class="flex justify-between items-center fixed w-full left-0 h-16 bg-gray-500 px-2 md:static">
						<h1 class="text-4xl font-semibold md:text-xl">HR</h1>
						<div>
							<button @click="isOpen = !isOpen" class="focus:outline-none">
								<svg class="h-6 w-6 fill-current" viewBox="0 0 24 24">
									<path v-show="!isOpen" d="M24 6h-24v-4h24v4zm0 4h-24v4h24v-4zm0 8h-24v4h24v-4z"/>
									<path v-show="isOpen" d="M24 20.188l-8.315-8.209 8.2-8.282-3.697-3.697-8.212 8.318-8.31-8.203-3.666 3.666 8.321 8.24-8.206 8.313 3.666 3.666 8.237-8.318 8.285 8.203z"/>
								</svg>
							</button>
						</div>
					</div>
					<div :class="isOpen ? 'block' : 'hidden'" class="fixed left-0 w-full mt-16 bg-gray-500 h-full overflow-y-scroll md:overflow-visible md:block md:static md:mt-0">
					<ul class="md:flex md:justify-end md:items-center pb-24 md:pb-0">
						<li class="border-b md:border-none"><a href="#" class="block px-8 py-2 my-4 hover:bg-gray-600 rounded">HRとは</a></li>
						<li class="border-b md:border-none"><a href="#" class="block px-8 py-2 my-4 hover:bg-gray-600 rounded">機能一覧</a></li>
						<li class="border-b md:border-none"><a href="#" class="block px-8 py-2 my-4 hover:bg-gray-600 rounded">料金プラン</a></li>
						<li class="border-b md:border-none"><a href="#" class="block px-8 py-2 my-4 hover:bg-gray-600 rounded">お知らせ</a></li>
						<li class="my-4"><a href="#" class="block px-8 py-2 my-4 bg-orange-500 hover:bg-gray-400 rounded-full">お問い合わせ</a></li>
					</ul>
					</div>
			</header>
		</div>
		<div class="container mx-auto mt-16 md:mt-0">
			<p>コンテンツ領域</p>
		</div>
	</div>
	<script>
		const app = new Vue({
			el: "#app",
			data: {
				isOpen: false,
			}
		});
	</script>
</body>
</html>

なるほど、ハンバーガーは難しいね

Tailwind CSSとは

Bootstrapでは事前に準備されているボタン、メニュー、パンくずリストなどのコンポーネントは準備されておらず、utility classを使って独自のコンポーネントを作成し、デザインを行っていく。
その為、bootstrapよりオリジナリティの高いサイトを構築できる。

<button class="bg-indigo-700 font-semibold text-white py-2 px-4 rounded">ボタン</button>

– 文字の大きさは9種類、色の数はかなりの数のutility classが準備されている。

### cdnを利用する場合

<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">

### npmを使用する場合
$ npm init -y
$ npm install tailwindcss
/css/style.css を作成

@tailwind base;

@tailwind components;

@tailwind utilities;

/public/css フォルダを作成
$ npx tailwind build ./css/style.css -o ./public/css/style.css

package.jsonにbuildコマンドを追加

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tailwind build css/style.css -o public/css/style.css"
  },

/public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link rel="stylesheet" href="css/style.css">
</head>
<body>
	<h1>Hello Tailwind</h1>
</body>
</html>

<h1 class="text-4xl text-green-700 text-center font-semibold">Hello Tailwind</h1>

文字の大きさにはtext-xs, txt-sm, text-base … など10の値がある
文字の太さはfont-hairline, font-thin, font-light … など9つの値がある
色はtext-{色}-{色の濃さ}で設定を行う text-green-100, text-green-200 ..など濃さは9個設定できる

<button class="bg-indigo-700 font-semibold text-white py-2 px-4 rounded">ボタン</button>

css/sytle.css

@tailwind base;
@tailwind components;
.btn {
	@apply font-semibold text-white py-2 px-4 rounded;
}
@tailwind utilities;

$ npm run build

<div class="text-center mt-10">
	<button class="bg-indigo-700 font-semibold text-white py-2 px-4 rounded">ボタン</button>
	<button class="bg-red-700 btn hover:bg-red-500">ボタン</button>
</div>

### 設定ファイルの追加
$ npx tailwind init
tailwind.config.js

module.exports = {
  future: {
    // removeDeprecatedGapUtilities: true,
    // purgeLayersByDefault: true,
  },
  purge: [],
  theme: {
    extend: {
      colors: {
        cyan: '#9cdbff',
      }
    },
  },
  variants: {},
  plugins: [],
}

$ npm run build

<button class="bg-cyan btn hover:bg-red-500 focus:outline-none focus:shadow-outline">ボタン</button>

なるほど、良く出来ている

wip TDD、tailwindcss, @errorの書き方

wip: work in progress

refactoring

public function test_an_author_can_be_created(){

        $this->post('/authors', $this->data());
        $author = Author::all();

        $this->assertCount(1, $author);
        $this->assertInstanceOf(Carbon::class, $author->first()->dob);
        $this->assertEquals('1988/14/05', $author->first()->dob->format('Y/d/m'));
    }

    private function data(){
        return [
            'name' => 'Author Name',
            'dob' => '05/14/1988'
        ];
    }

$ phpunit –filter test_an_author_can_be_created

public function test_a_name_is_required(){
        $response = $this->post('/authors', array_merge($this->data(), ['name' => '']));

        $response->assertSessionHasErrors('name');

    }

    public function test_a_dob_is_required(){
        $response = $this->post('/authors', array_merge($this->data(), ['dob' => '']));
        $response->assertSessionHasErrors('dob');

    }

controller

public function store(){
    	$data = $this->validateData();

    	Author::create($data);
    }

    protected function validateData(){
    	return request()->vadidate([
    		'name' => 'required',
    		'dob'=> '',
    	]);
    }

### tailwindcss
$ php artisan help preset
$ php artisan preset none
$ php artisan preset vue

$ npm install

https://tailwindcss.com/
$ npm install tailwindcss –save-dev

app.scss

@tailwind base;

@tailwind components;

@tailwind utilities;

$ npx tailwind init

webpack.mix.js

const tailwindcss = require('tailwindcss');
mix.js('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css')
   .options({
    processCssUrls: false,
    postCss: [ tailwindcss('./.config.js') ],
  });

$ npm install webpack

$ npm run dev

authors/create.blade.php

@extends('layouts.app')

@section('content')
	<dvi class="bg-gray-300 h-screen">
		asdfg
	</dvi>
@endsection

web.php

Route::get('/authors/create', 'AuthorsController@create');

create.blade.php
test

@extends('layouts.app')

@section('content')
	<div class="w-2/3 bg-gray-200 mx-auto">
		asdfg
	</div>
@stop

### @errorの
styling

<div class="w-2/3 bg-gray-200 mx-auto p-6 shadow">
		<form action="/authors" method="post" class="flex flex-col items-center">
			@csrf
		<h1>Add New Author</h1>
		<div class="pt-4">
			<input type="text" name="name" placeholder="Full Name" class="rounded px-4 py-2 w-64">
			@if{{$errors->has('dob')}}
				<p class="text-red-600">{{$errors->first('name')}}</p>
			@endif
		</div>
		<div class="pt-4">
			<input type="text" name="dob" placeholder="Date of Birth" class="rounded px-4 py-2 w-64">
			@if{{$errors->has('dob')}}
				<p class="text-red-600">{{$errors->first('dob')}}</p>
			@endif
		</div>
		<div class="pt-4">
			<button class="bg-blue-400 text-white rounded py-2 px-4">Add New Author</button>
		</div>
		</form>
	</div>
@error('name') <p class="text-red-600">{{$message}}</p> @enderror

tailwindはモダンな感じがする
しかし、6系になってフロント周りを中心に随分仕様が変わってます。