@@ -42,8 +42,20 @@ class Navbar extends NavTag
4242 * Brand link destination.
4343 */
4444 public string $ mainpage = '# ' ;
45+
46+ /**
47+ * Render the collapsible menu as an Offcanvas drawer instead of a
48+ * Bootstrap collapse. Enable in a subclass before finalize().
49+ */
50+ public bool $ offcanvas = false ;
51+
52+ /**
53+ * Offcanvas drawer placement when $offcanvas is enabled.
54+ */
55+ public string $ offcanvasPlacement = 'end ' ;
4556 private string $ navBarName = 'nav ' ;
4657 private \Ease \Html \DivTag $ containerFluid ;
58+ private ButtonTag $ toggler ;
4759
4860 /**
4961 * App Menu.
@@ -70,7 +82,8 @@ public function __construct($brand = null, $name = 'navbar', $properties = [])
7082 $ this ->leftContent = new UlTag (null , ['class ' => 'navbar-nav flex-nowrap mb-2 mb-lg-0 ' , 'style ' => '--bs-scroll-height: 100px; ' ]);
7183 $ this ->rightContent = new UlTag (null , ['class ' => 'navbar-nav ms-auto flex-nowrap mb-2 mb-lg-0 ' ]);
7284
73- $ this ->containerFluid = $ this ->addItem (new \Ease \Html \DivTag ([new ATag ($ this ->mainpage , $ brand , ['class ' => 'navbar-brand ' ]), $ this ->navBarToggler ()], ['class ' => 'container-fluid ' ]));
85+ $ this ->toggler = $ this ->navBarToggler ();
86+ $ this ->containerFluid = $ this ->addItem (new \Ease \Html \DivTag ([new ATag ($ this ->mainpage , $ brand , ['class ' => 'navbar-brand ' ]), $ this ->toggler ], ['class ' => 'container-fluid ' ]));
7487 }
7588
7689 /**
@@ -136,12 +149,49 @@ public function navBarCollapse()
136149 return new \Ease \Html \DivTag ($ this ->leftContent , ['class ' => 'collapse navbar-collapse ' , 'id ' => $ this ->navBarName ]);
137150 }
138151
152+ /**
153+ * Wrap the menu in an Offcanvas drawer (responsive offcanvas-in-navbar).
154+ *
155+ * @see https://getbootstrap.com/docs/5.3/components/navbar/#offcanvas
156+ *
157+ * @return \Ease\Html\DivTag Offcanvas drawer
158+ */
159+ public function navBarOffcanvas ()
160+ {
161+ $ ocId = 'offcanvas ' .$ this ->navBarName ;
162+
163+ $ header = new \Ease \Html \DivTag ([
164+ new \Ease \Html \H5Tag (_ ('Menu ' ), ['class ' => 'offcanvas-title ' , 'id ' => $ ocId .'Label ' ]),
165+ new ButtonTag ('' , ['class ' => 'btn-close ' , 'data-bs-dismiss ' => 'offcanvas ' , 'aria-label ' => _ ('Close ' )]),
166+ ], ['class ' => 'offcanvas-header ' ]);
167+
168+ $ body = new \Ease \Html \DivTag ($ this ->leftContent , ['class ' => 'offcanvas-body ' ]);
169+
170+ return new \Ease \Html \DivTag ([$ header , $ body ], [
171+ 'class ' => 'offcanvas offcanvas- ' .$ this ->offcanvasPlacement ,
172+ 'tabindex ' => '-1 ' ,
173+ 'id ' => $ ocId ,
174+ 'aria-labelledby ' => $ ocId .'Label ' ,
175+ ]);
176+ }
177+
139178 /**
140179 * Finalize NavBar.
141180 */
142181 public function finalize (): void
143182 {
144- $ this ->containerFluid ->addItem ($ this ->navbarCollapse ());
183+ if ($ this ->offcanvas ) {
184+ $ ocId = 'offcanvas ' .$ this ->navBarName ;
185+ $ this ->toggler ->setTagProperties ([
186+ 'data-bs-toggle ' => 'offcanvas ' ,
187+ 'data-bs-target ' => '# ' .$ ocId ,
188+ 'aria-controls ' => $ ocId ,
189+ ]);
190+ $ this ->containerFluid ->addItem ($ this ->navBarOffcanvas ());
191+ } else {
192+ $ this ->containerFluid ->addItem ($ this ->navbarCollapse ());
193+ }
194+
145195 parent ::finalize ();
146196 }
147197
0 commit comments