Под любой экран: адаптивная панель навигации с помощью React и Tailwind
Разработчик Франсиско Мендес опубликовал в блоге туториал по созданию панели навигации, которая адаптируется к различным размерам экрана. Описанный вариант выполнен с помощью React и Tailwind, а навигация будет проводиться по странице, на которой находится пользователь. Вот как это сделать.
По словам автора туториала, если сделать все правильно, в конце должна получиться такая адаптивная навигационная панель:
Наряду с Tailwind CSS будут использоваться другие инструменты, такие как classnames
и react-icons
:
npm install classnames react-icons
Затем создаем файл с названием навигационных элементов:
// @src/data/navigation.js export default ["Home", "Discover", "Store", "Inbox", "Profile"];
Потом, чтобы абстрагировать логику от выбранных элементов навигации, создаем хук, где главной страницей будет Home, а также будет функция, отвечающая за изменение направлений навигации.
// @src/hooks/useNavigation.js import { useState, useCallback } from "react"; const useNavigation = () => { const [route, setRoute] = useState("Home"); const selectAction = useCallback( (option) => { if (route === option) return; setRoute(option); }, [route] ); return { currentRoute: route, setCurrentRoute: selectAction }; }; export default useNavigation;
Работу с компонентами следуем начать с работы над панелью навигации. Ниже представлены стили компонента Navbar:
/* @src/components/Navbar/Navbar.module.css */ .navbar { @apply hidden md:flex flex-row items-center justify-between px-8 h-18 rounded-b-3xl bg-white; } .logo { @apply text-5xl text-gray-800 -mb-1; } .navItems { @apply flex flex-row self-end h-12; } .navItem { @apply w-22 text-gray-400 hover:text-gray-700 cursor-pointer font-medium tracking-wide text-sm flex items-start justify-center; } .selectedNavItem { @apply text-gray-700 border-b-3 border-gray-700 bg-gradient-to-b from-white to-gray-100; } .actions { @apply bg-white hover:bg-gray-50 border-2 border-gray-900 text-sm text-gray-900 py-3 px-5 rounded-lg font-medium tracking-wide leading-none; }
Компонент получит три пропса: элементы навигации, информацию по текущему маршруту и функцию для определения текущего маршрута. Затем надо будет сопоставить элементы массива, чтобы каждый из элементов навигации присутствовал в панели навигации, а также применить условный рендеринг с использованием classNames
, чтобы было можно соединить классы.
// @src/components/Navbar/index.jsx import React from "react"; import { CgMonday } from "react-icons/cg"; import classNames from "classnames"; import styles from "./Navbar.module.css"; const Navbar = ({ navigationData, currentRoute, setCurrentRoute }) => { return ( <nav className={styles.navbar}> <span className={styles.logo}> <CgMonday /> </span> <ul className={styles.navItems}> {navigationData.map((item, index) => ( <li className={classNames([ styles.navItem, currentRoute === item && styles.selectedNavItem, ])} key={index} onClick={() => setCurrentRoute(item)} > {item} </li> ))} </ul> <button className={styles.actions}>Logout</button> </nav> ); }; export default Navbar;
Для создания панели вкладок используются следующие стили:
/* @src/components/Tabbar/Tabbar.module.css */ .tabbar { @apply flex md:hidden flex-row items-center justify-around px-8 h-18 bg-white visible md:invisible fixed bottom-0 w-full rounded-t-3xl text-2xl; } .tabItem { @apply text-gray-400 hover:text-gray-700 cursor-pointer w-18 h-full flex items-center justify-center; } .tabItemActive { @apply bg-gradient-to-t from-white to-gray-100 border-t-3 border-gray-700 text-gray-700; } .icon { @apply -mb-1; }
Этот компонент будет получать точно такие же пропсы, как и Navbar, но на этот раз нужно выполнить условный рендеринг. При рендеринге элементов массива нужно отобразить иконку, соответствующую маршруту, поэтому создаем функцию с переключателем, которая будет отвечать за возврат иконки в зависимости от элемента.
// @src/components/Tabbar/index.jsx import React, { useCallback } from "react"; import classNames from "classnames"; import { AiFillHome, AiFillCompass } from "react-icons/ai"; import { BsFillBagFill, BsFillPersonFill } from "react-icons/bs"; import { CgInbox } from "react-icons/cg"; import styles from "./Tabbar.module.css"; const Tabbar = ({ navigationData, currentRoute, setCurrentRoute }) => { const getTabIcon = useCallback((item) => { switch (item) { case "Home": return <AiFillHome />; case "Discover": return <AiFillCompass />; case "Store": return <BsFillBagFill />; case "Inbox": return <CgInbox />; case "Profile": return <BsFillPersonFill />; } }, []); return ( <nav className={styles.tabbar}> {navigationData.map((item, index) => ( <span key={index} className={classNames([ styles.tabItem, currentRoute === item && styles.tabItemActive, ])} onClick={() => setCurrentRoute(item)} > <span className={styles.icon}>{getTabIcon(item)}</span> </span> ))} </nav> ); }; export default Tabbar;
Последним шагом нужно перейти к входному файлу App.jsx
. Стили будут следующие:
/* @src/App.module.css */ .container { @apply bg-gray-200 h-screen; } .devLogo { @apply flex items-center justify-center text-5xl text-gray-300 h-5/6; }
Теперь в App.jsx
импортируем навигационные данные, хук и каждый из компонентов, которые создадим ниже, каждому из них передаем указанные пропсы.
// @src/App.jsx import React from "react"; import { FaDev } from "react-icons/fa"; import styles from "./App.module.css"; import useNavigation from "./hooks/useNavigation"; import navigationData from "./data/navigation"; import Navbar from "./components/Navbar"; import Tabbar from "./components/Tabbar"; const App = () => { const { currentRoute, setCurrentRoute } = useNavigation(); return ( <div className={styles.container}> <Navbar navigationData={navigationData} currentRoute={currentRoute} setCurrentRoute={setCurrentRoute} /> <Tabbar navigationData={navigationData} currentRoute={currentRoute} setCurrentRoute={setCurrentRoute} /> <div className={styles.devLogo}> <FaDev /> </div> </div> ); }; export default App;
Вот и все!
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…