Chapter 12

tailwindcssで、Navigation階層化メニュー検討

knaka Tech-Blog
knaka Tech-Blog
2021.05.07に更新

概要:

tailwindcssで、ナビ部分のサブメニューや。ドロップダウンを探したのですが。
なかなか見当たらずに、簡単なサブメニュー部品を Reactで作成した内容となります

  • tailwindcss初期設定等は、前の記事を参考にしてます

環境

  • tailwindcss: 2.1.2
  • next.js : 10.1.3
  • react: 17.0.2
  • node 14

参考のデモページ

https://cms-kuc-jamstack-ex16.netlify.app/


通常のナビ、参考

  • メニューが少ない場合で、サブメニュー不要の場合の簡素版、公式とほぼ似た部品

https://gist.github.com/kuc-arc-f/ee1f52cd53c76a586e809b64974312de

02_navi.html
    <ul class="flex flex-wrap py-2 px-4">
      <li class="w-full sm:w-16">
        <a class="text-blue-500 hover:text-blue-800" href="#">Active</a>
      </li>
      <li class="w-full sm:w-16">
        <a class="text-blue-500 hover:text-blue-800" href="#">Link</a>
      </li>
      <li class="w-full sm:w-40">
        <a class="text-blue-500 hover:text-blue-800" href="#">メニュー2番目を実行</a>
      </li>
      <li class="w-full sm:w-16">
        <a class="text-blue-500 hover:text-blue-800" href="#">Link</a>
      </li>
      <li class="w-full sm:w-16">
        <a class="text-blue-500 hover:text-blue-800" href="#">Link</a>
      </li>
      <li class="w-full sm:w-16">
        <a class="text-blue-500 hover:text-blue-800" href="#">Link</a>
      </li>
      <li class="w-full sm:w-16">
        <a class="text-blue-500 hover:text-blue-800" href="#">Link</a>
      </li>
    </ul>


参考のコード

  • 作成したサブメニュー、next.js

https://github.com/kuc-arc-f/nextjs_3_15tailwind_nav

画面

  • 下矢印のリンクを押すと、サブメニューが表示


実装など

  • サブのデータを設定 , lib/LibNavigation.js

親IDを指定し、下層メニューの。各名称/ アクション先URL を取り出す

LibNavigation.js
  get_sub_items: function(parent_id){
    var ret = {}
    var arr = [
      {id: 1 , 
        subData: [
          {name: 'subAction-1' , action: '/action/1'},
          {name: 'subAction-2' , action: '/action/2'},
          {name: 'subAction-3' , action: '/action/3'},
        ] 
      } ,
      {id: 2 , 
        subData: [
          {name: 'subAction-11' , action: '/action/11'},
          {name: 'subAction-12' , action: '/action/12'},
          {name: 'subAction-13' , action: '/action/13'},
          {name: 'subAction-14' , action: '/action/14'},
        ] 
      } ,
    ]
    arr.forEach(function(item){
//console.log(item.id );
      if(item.id === parent_id){
        ret = item.subData
      }
    });    
    return ret
  }, 

  • 親nav, components/Navibar.jsx

React.Componentで、サブ呼出し、下層データのを渡す。サブ表示イベント処理

LibNavigation.js
export default class Navibar extends React.Component {
  constructor(props){
    super(props)
    this.state = {subDisplay: 0 , subData: [] }
  }
  clickHandler(display , parent_id){
    var sub_maenu = LibNavigation.get_sub_items(parent_id)
    this.setState({ subDisplay: display, subData: sub_maenu })
  }    
  render(){
    return (
    <div className="bg-white ">
      <div className="container mx-auto">
        <ul className="flex flex-wrap py-2 px-4">
          <li className="mr-6">
            <Link href="/">
              <a className="text-blue-500 hover:text-blue-800">Home</a>
            </Link>
          </li>
          <li className="w-full sm:w-16">
            <a className="text-blue-500 hover:text-blue-800" href="#"
            onClick={this.clickHandler.bind(this , 1, 1)} >
            Open <span className="text-xs"></span>
            </a>
          </li>        
          <li className="w-full sm:w-16">
            <Link href="/">
              <a className="text-blue-500 hover:text-blue-800">Link1</a>
            </Link>
          </li>
          <li className="mr-6">
            <Link href="/about">
              <a className="text-blue-500 hover:text-blue-800">About</a>
            </Link>
          </li>                  
        </ul>
        {this.state.subDisplay ==0 ? ""
        : (<NavibarSub subDisplay={this.state.subDisplay}
           subData={this.state.subData} />)
        }
      </div>
    </div>
    )
  }

  • サブnav

配列から、各サブのアクションURL、名称取り出し<Link>タグで移動

NavibarSub.jsx
export default function Page(props){
//console.log(props.subData)
  return (
    <ul className="flex flex-wrap p-2 bg-gray-700">
    {props.subData.map((item, index) => {
      return (
      <li key={index} className="w-full sm:w-28">
        <Link href={item.action}>
          <a className="text-white hover:text-blue-400">{item.name}
          </a>
        </Link>        
      </li>      
      )
    })}
    </ul>
    )
}


Update

  • update : 2021/05/07 , dark モード追加


  • 設定

_app.js :

navi_color.css の行を削除し、navi_color_dark.css をimport
すると、dark モード変更できます。

import '../styles/components/navi_color_dark.css'
//import '../styles/components/navi_color.css'

....