Menu
Implementation
- Steal a hamburger SVG from a Tailwind CSS tutorial
- Steal some Tailwind CSS code from the navigation component example as well as from the tutorial
- To control things when the pop-up menu is open or closed, using a MenuProvider—fun!
MenuProvider
- Defining
1import * as React from 'react'2import { useState } from 'react'3
4export const MenuContext = React.createContext()5
6export const MenuProvider = ({ children }) => {7 const [menuOpen, setMenuOpen] = useState(false)8
9 return (10 <MenuContext.Provider value={{ menuOpen, setMenuOpen }}>11 {children}12 </MenuContext.Provider>13 )14}
- Using
1import { useContext } from 'react'2import { MenuContext } from '../components'3
4export const Header = ({ siteTitle }) => {5 const { menuOpen, setMenuOpen } = useContext(MenuContext)6 // At this point, you can use menuOpen and setMenuOpen!7 //...8}
Using Props with twin.macro Styled-component
ContentWrapper - the styled component
- The
mt-40
is going to have to be constantly updated if new menu items are added. - Added
menuShift
because for the landing pages and posts, it looks nice going over the picture.
1// menuOpen is passed from the main component2// it can then be used to add more tailwind styles as needed3const ContentWrapper = styled.div(({ menuOpen, menuShift }) => [4 tw`p-4 mx-4 mt-6 bg-container rounded-lg shadow-lg`,5 menuOpen && menuShift && tw`mt-40`,6])
Content - the main component
1export const Content = ({ children }) => {2 const { menuOpen } = useContext(MenuContext)3 // Pass in a prop called menuOpen to the styled component4 // I tried <ContentWrapper menuOpen> but that didn't work5 return (6 <ContentWrapper menuOpen={menuOpen} menuShift={menuShift}>7 {children}8 </ContentWrapper>9 )10}
Scroll Bar Fun
When the scroll bar is not needed and then becomes needed, the menus and dark toggle fidget about. There was some CSS code in the html element from the original layout.css that I did not bring over which fixed this.
overflow-y: scroll;
Menu Design
Using the normal primary color (teal for light, orange for dark) did not look good for the menus. Created opposite colors for the theme. —primary is Sharks Teal, —opposite is Sharks Orange for light and vice versa for dark. This is how I had it in a mock-up and I think I like how it it looks. It does make me think the opposite color (secondary if you will) could be used more in the site.
Popup Menu
Originally, the idea was to have the theme toggle go away on a popup menu. However, I just realized now (as 2021 just started!) that this would make it impossible for mobile users to toggle the theme. I added the button as a flex container…a first for me. I thought to myself, why can't it be done? And it was done!
Button as Flex
I used spans for the text and icon but I probably could have used paragraphs, still, span sang to me for this. After all, these are just bits of the button.
1return (2 <div className='hover:bg-opposite'>3 <button4 type='button'5 onClick={() => {6 setTheme(theme === 'light' ? 'dark' : 'light')7 }}8 className='sm:inline sm:ml-2 flex justify-between items-center w-full pr-6'9 >10 <span className='block sm:hidden px-2 py-1 font-semibold rounded hover:bg-opposite'>11 {' '}12 Toggle Theme{' '}13 </span>14 <span className='block'>{`${theme === 'light' ? '🌙' : '🌞'}`}</span>15 </button>16 </div>17)
With this done, the button looks rather like any other menu item and reaches across the whole screen. A little padding on the right and the icon lines up pretty well with the menu button.
Final Tweaks
After getting the mobile dark mode toggle in the menu looking perfect, it looked poor for the desktop. That took some tweaking and remembering that top padding and margins both do nothing when an element is inline! (ugh!)
Attributions
Photo by Croissant (@getcroissant) on Unsplash