Отзывчивые навигационные панели являются одними из хлеба и масла фронтенд-разработки. Обычной практикой является панель навигации на рабочем столе и боковая панель на мобильных устройствах. Вероятно, это очень легко реализовать с помощью ваших любимых фреймворков CSS. Тем не менее, это оказывается либо довольно сложным, либо совершенно сложным при использовании фреймворка semantic-UI-react (который, за исключением этой маленькой причуды, является удивительным фреймворком). Эта статья представляет собой демонстрацию того, как создать адаптивную панель навигации с помощью React, Semantic-UI-React и React-Response, поскольку на момент написания практически не было готовых решений.
Запись выше — это образец панели навигации, которую мы будем создавать на протяжении всей статьи.
В конце этой статьи вы узнаете, как:
- сделать отзывчивую панель навигации с помощью
semantic-UI-react
CSS framework - используйте пакет
react-responsive
Что такое Semantic-UI-реакция?
Semantic UI — один из многих популярных фреймворков CSS, которые якобы ускоряют создание веб-сайтов, предоставляя нам уже готовые компоненты CSS. Он гордится тем, что является семантическим, что в основном достигается за счет использования продуманных и осмысленных имен классов. Теперь, после использования таких фреймворков, как bootstrap и tailwind, я должен признать, что четкие, продуманные имена классов стали весьма ценными!
Фреймворк semantic-UI-react является расширением CSS-фреймворка semantic-UI, оптимизированным для работы с реакцией и использования системы поддержки реакции (так же, как у нас есть bootstrap и react-bootstrap). И это работает как шарм, пока вам не нужно создать отзывчивую панель навигации.
Что такое React-Responsive?
React-responsive — это пакет, который позволяет нам динамически вводить и удалять контент, отображаемый React в данный момент на экране, в зависимости от размера области просмотра. Используя этот пакет, мы можем имитировать медиа-запросы CSS-экрана непосредственно в коде реакции. Это мой любимый инструмент для адаптивного дизайна в React. Не стесняйтесь использовать любой альтернативный пакет, который может воспроизвести ту же функциональность.
Настраивать
Для начала:
- запустить приложение React (в этой демонстрации используется
vite-react
) - очистите приложение, чтобы оно соответствовало файловой структуре на картинке ниже
- Установите пакеты semantic-UI-react, semantic-UI-CSS и пакеты, реагирующие на реакцию, с помощью NPM.
- Добавьте любое изображение логотипа по вашему выбору в общую папку
- Импортируйте
semantic.min.css
вmain.jsx
. Этот импорт должен быть вышеindex.css
, чтобы мы могли использоватьindex.css
для перезаписи некоторых встроенных стилей семантической реакции пользовательского интерфейса, если это необходимо. - Добавьте следующие строки кода в указанные компоненты
/*index.css*/ body { background-color: rgb(35, 35, 141) } //app.jsx import Navbar from "./components/navbar" function App() { return ( <div className="App"> <Navbar /> </div> ) } export default App //Main.jsx import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import 'semantic-ui-css/semantic.min.css' import './index.css' ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <App /> </React.StrictMode> )
Компонент NavbarLg
Мы будем использовать компонент меню для панели навигации на больших экранах. Для этого посетите semantic-UI-react docs и выберите предпочитаемый тип компонента меню. В этой демонстрации будет использоваться инвертированный тип меню.
- Документы написаны с использованием компонентов класса React, но это довольно простой код, поэтому я преобразую его в функциональный компонент.
- Мы также добавим ссылку для регистрации и входа в правый край панели навигации.
import { useState} from 'react' import { Menu, Segment } from 'semantic-ui-react' export default function NavbarLg() { const [activeItem,setactiveItem]=useState("home") const handleItemClick = (e, { name }) => setactiveItem(name) return ( <Segment inverted attached size='mini'> <Menu inverted secondary> <Menu.Item name='logo' active={activeItem === 'logo'} onClick={handleItemClick} > <img src="ghostblog.svg" alt="" /> </Menu.Item> <Menu.Item name='home' active={activeItem === 'home'} onClick={handleItemClick} /> <Menu.Item name='messages' active={activeItem === 'messages'} onClick={handleItemClick} /> <Menu.Item name='friends' active={activeItem === 'friends'} onClick={handleItemClick} /> <Menu.Item name='login' active={activeItem === 'login'} onClick={handleItemClick} position="right" /> <Menu.Item name='sign_in' active={activeItem === 'sign_in'} onClick={handleItemClick} /> {/* section */} </Menu> </Segment> ) } //navbar.jsx import NavbarLg from "./NavbarLg" export default function Navbar() { return ( <div> <NavbarLg/> </div> ) }
Компонент NavbarMb
Переходя к мобильной панели навигации, мы будем использовать боковую панель semantic-UI-react (см. https://react.semantic-ui.com/modules/sidebar/), но внесем в нее некоторые серьезные изменения.
Проблема заключается в том, как семантический пользовательский интерфейс добавил оверлей, который вынуждает весь остальной контент на странице находиться в компоненте sidebar.pusher
. Это неэффективно, учитывая, что мы не хотели бы вкладывать весь контент нашего приложения в этот компонент. Кроме того, элементы управления боковой панели нуждаются в доработке, так как значок гамбургера был бы гораздо предпочтительнее, чем галочка. Чтобы исправить все это, мы добавим три пользовательских компонента.
- Компонент тонированного наложения
- Значок гамбургера, чтобы открыть боковую панель
- Значок закрытия, чтобы закрыть боковую панель
Примечание: мы будем использовать встроенные значки семантического интерфейса.
Значок гамбургера будет переключаться в зависимости от состояния боковой панели, чтобы открыть или закрыть значок.
//NavbarMb.jsx import { useState } from 'react' import { Menu, Sidebar } from 'semantic-ui-react' function Overlay() { return ( <div style={{ backgroundColor: "rgba(0, 0, 0, 0.795)", position: "fixed", height: "110vh", width: "100%", }} /> ) } function HamIcon() { return (<i className="big bars icon inverted" />) } function CloseIcon() { return (<i className="big close red icon" />) } function NavbarMb({renderLinks}) { const [visible, setVisible] = useState(false) const [icon, setIcon] = useState(HamIcon) const [activeItem, setactiveItem] = useState("home") const handleItemClick = (e, { name }) => setactiveItem(name) const hideSidebar = () => { setIcon(HamIcon) setVisible(false) } const showSidebar = () => { setIcon(CloseIcon) setVisible(true) } const toggleSidebar = () => { visible ? hideSidebar() : showSidebar() } return ( <> {visible && <Overlay />} <Menu inverted size="tiny" borderless attached > <Menu.Item> <img src="ghostblog.svg" width="35px" height="35px" alt="" /> </Menu.Item> <Menu.Menu position='right'> <Menu.Item onClick={toggleSidebar}> {icon} </Menu.Item> </Menu.Menu> </Menu> <Sidebar as={Menu} animation='overlay' icon='labeled' inverted vertical visible={visible} width='thin' > <Menu.Item> <img src="ghostblog.svg" width="35px" height="35px" style={{ margin: "0 auto" }} alt="" /> </Menu.Item> <Menu.Item name='home' active={activeItem === 'home'} onClick={handleItemClick} /> <Menu.Item name='messages' active={activeItem === 'messages'} onClick={handleItemClick} /> <Menu.Item name='friends' active={activeItem === 'friends'} onClick={handleItemClick} /> <Menu.Item name='login' active={activeItem === 'login'} onClick={handleItemClick} position="right" /> <Menu.Item name='sign_in' active={activeItem === 'sign_in'} onClick={handleItemClick} /> </Sidebar> </> ) } export default NavbarMb //navbar.jsx import NavbarMb from "./NavbarMb" import NavbarLg from "./NavbarLg" export default function Navbar() { return ( <div> {/*<NavbarLg/>*/} <NavbarMb/> </div> ) }
Повтор сеанса с открытым исходным кодом
OpenReplay – это пакет для воспроизведения сеансов с открытым исходным кодом, который позволяет вам видеть, что пользователи делают в вашем веб-приложении, помогая вам быстрее устранять неполадки. OpenReplay размещается на собственном сервере для полного контроля над вашими данными.
Начните получать удовольствие от отладки — начните использовать OpenReplay бесплатно.
Делаем навигационную панель отзывчивой с помощью React-responsive
У нас есть навигационная панель для большого экрана и одна для мобильного экрана. Давайте поработаем с react-responsive, чтобы сделать панель навигации отзывчивой, переключаясь с navbar-large на navbar-mobile и наоборот в зависимости от размера экрана.
Мы сделаем это в компоненте навигационной панели, используя отзывчивый ответ.
- Импортируйте
NavbarLg
иNavbarMb
в компонентNavbar
- Следуя отзывчивым документам, объявите несколько точек останова как переменные, используя хук
useMediaQuery
. - Создайте объект размеров экрана из точек останова
- Отображение компонента
NavbarLg
илиNavbarMb
условно в зависимости от того, превышает ли размер экрана точку останова или нет
Примечание. Этот пакет (реагирующий на реакцию) довольно прост в использовании, и документация очень ясно описывает, как его использовать.
//navbar.jsx import { useMediaQuery } from 'react-responsive' import NavbarMb from "./NavbarMb" import NavbarLg from "./NavbarLg" export default function Navbar() { const none =useMediaQuery({ query: "(max-width:576px)" }) const sm = useMediaQuery({ query: "(min-width:576px)" }) const md = useMediaQuery({ query: "(min-width:768px)" }) const lg = useMediaQuery({ query: "(min-width:992px)" }) const xl = useMediaQuery({ query: "(min-width:1200px)" }) const xxl = useMediaQuery({ query: "(min-width:1400px)" }) const size = {none,sm,md,lg,xl,xxl} return ( <div> {size.sm ? <NavbarLg /> : <NavbarMb /> } </div> ) }
Вроде все закончили, но не совсем. Если вы посмотрите достаточно внимательно, вы заметите, что состояние не сохраняется после перехода с большой панели навигации на мобильную панель навигации. Это видно по выделенному nav-link
, который снова меняется на home
, когда мы переключаемся с большой панели навигации на мобильную панель навигации и наоборот.
Теперь представьте, что это многостраничное приложение React. Это, вероятно, приведет к путанице, поскольку, если кто-то на странице входа свернет свой экран, панель навигации вернется к выделению home
, даже если приложение останется на странице входа.
Чтобы исправить это,
- мы поднимем состояние
nav-links
до основного компонента Navbar и будем обрабатывать клики оттуда. - Затем
nav-links
можно передатьNavbarLg
илиNavbarMb
в качестве реквизита. Это сохранит состояние, посколькуnav-links
являются частью компонентаNavbar
, а компонентNavbar
всегда будет присутствовать в нашем пользовательском интерфейсе на больших и малых экранах.
//navbar.jsx import { useState} from 'react' import { useMediaQuery } from 'react-responsive' import { Menu } from 'semantic-ui-react' import NavbarMb from "./NavbarMb" import NavbarLg from "./NavbarLg" export default function Navbar() { const [activeItem,setactiveItem]=useState("home") const handleItemClick = (e, { name }) => setactiveItem(name) const renderLinks=()=>{ return <><Menu.Item name='logo' active={activeItem === 'logo'} onClick={handleItemClick} > <img src="ghostblog.svg" width="35px" height="35px" style={{ margin: "0 auto" }} alt="" /> </Menu.Item> <Menu.Item name='home' active={activeItem === 'home'} onClick={handleItemClick} /> <Menu.Item name='messages' active={activeItem === 'messages'} onClick={handleItemClick} /> <Menu.Item name='friends' active={activeItem === 'friends'} onClick={handleItemClick} /> <Menu.Item name='login' active={activeItem === 'login'} onClick={handleItemClick} position="right" /> <Menu.Item name='sign_in' active={activeItem === 'sign_in'} onClick={handleItemClick} /> </> } const none =useMediaQuery({ query: "(max-width:576px)" }) const sm = useMediaQuery({ query: "(min-width:576px)" }) const md = useMediaQuery({ query: "(min-width:768px)" }) const lg = useMediaQuery({ query: "(min-width:992px)" }) const xl = useMediaQuery({ query: "(min-width:1200px)" }) const xxl = useMediaQuery({ query: "(min-width:1400px)" }) const size = {none,sm,md,lg,xl,xxl} return ( <div> {size.sm ? <NavbarLg renderLinks={renderLinks}/> : <NavbarMb renderLinks={renderLinks}/> } </div> ) } //NavbarLg.jsx import { Menu, Segment } from 'semantic-ui-react' export default function NavbarLg({renderLinks}) { return ( <Segment inverted attached size='mini'> <Menu inverted secondary> {renderLinks()} </Menu> </Segment> ) } //Navbar.Mb import { useState } from 'react' import { Menu, Sidebar } from 'semantic-ui-react' function Overlay() { return ( <div style={{ backgroundColor: "rgba(0, 0, 0, 0.795)", position: "fixed", height: "110vh", width: "100%", }} /> ) } function HamIcon() { return (<i className="big bars icon inverted" />) } function CloseIcon() { return (<i className="big close red icon" />) } function NavbarMb({renderLinks}) { const [visible, setVisible] = useState(false) const [icon, setIcon] = useState(HamIcon) const hideSidebar = () => { setIcon(HamIcon) setVisible(false) } const showSidebar = () => { setIcon(CloseIcon) setVisible(true) } const toggleSidebar = () => { visible ? hideSidebar() : showSidebar() } return ( <> {visible && <Overlay />} <Menu inverted size="tiny" borderless attached > <Menu.Item> <img src="ghostblog.svg" width="35px" height="35px" alt="" /> </Menu.Item> <Menu.Menu position='right'> <Menu.Item onClick={toggleSidebar}> {icon} </Menu.Item> </Menu.Menu> </Menu> <Sidebar as={Menu} animation='overlay' icon='labeled' inverted vertical visible={visible} width='thin' > {renderLinks()} </Sidebar> </> ) } export default NavbarMb
Краткое содержание
Эта демонстрация длинная, но если вы когда-нибудь столкнетесь с трудностями при работе с адаптивной панелью навигации с помощью Semantic-UI или Semantic-UI-react, она должна вам помочь.
Кроме того, благодаря тому, что компоненты реакции легко повторно использовать, компонент навигационной панели можно повторно использовать в нескольких проектах. С помощью стиля semantic-UI-react мы можем вносить соответствующие изменения и изменения в дизайн, чтобы он подходил для любого конкретного проекта.
Ресурсы
Первоначально опубликовано на https://blog.openreplay.com.