Как добавить интерактивный туториал на сайт используя React
Вступление или для чего вообще нужен интерактивный туториал
Привет, опять. В этой статье ты узнаешь как быстро и просто создать интерактивный туториал по вашему инструменту на Реакте. И первый вопрос который бы я задал, был бы такой: а нужен ли он вообще?
И действительно, если функционал инструмента максимально простой и интуитивно понятный, то заморачиваться над туториалом не стоит. В идеале, к этому и нужно стремиться чтобы пользователь без всякой лишней мысли приступал к использованию твоего инструмента.
Но как это бывает в реальной жизни, не все инструменты одно кнопочные и у многих большой и сложный функционал. Взять к примеру следующие веб-инструменты:
- Topvisor
- Google Analytics
Нельзя так просто взять и пользоваться ими. Сначала, ты должен научиться ими пользоваться. В моём случае получился не очень интуитивно понятный инструмент. По этому будем делать встроенный туториал на сайт.
Создание собственного ивента для запуска туториала
У нас уже есть кнопка для вызова цепочки подсказок
Нужно теперь её настроить так, чтобы эта цепочка работала. Сделаем мы это через создание собственного события.
В файле Header.js замени:
export default function Header() {
const header_buttons = document.getElementById('meta-header')
const btns = []
for ( const btn of header_buttons.children){
const ref = btn.firstElementChild.getAttribute('href')
if (btn.dataset.type == 'inner-link'){
btns.push()
}
else if (btn.dataset.type == 'tutorial' ){
btns.push()
}
export default function Header() {
const header_buttons = document.getElementById('meta-header')
const btns = []
for ( const btn of header_buttons.children){
const ref = btn.firstElementChild.getAttribute('href')
if (btn.dataset.type == 'inner-link'){
btns.push()
}
else if (btn.dataset.type == 'tutorial' ){
btns.push()
}
Мы добавили к кнопке айдишник + собственное событие на клик.
Создание нового компонента Tutorial.js
Теперь создадим новый компонент. В директории src/components создай файл Tutorial.js. После чего добавь туда следующий код:
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import Popover from '@mui/material/Popover';
export default function Hint({children, anchor}) {
const [anchorEl, setAnchorEl] = React.useState(null);
const [counter, setCounter] = React.useState(1);
const [message, setMessage] = React.useState('');
const clearAllHints = () => {
const hints = document.querySelectorAll('.tutorial_hint')
hints.forEach( (hint_target) => {
hint_target.style = ''
if (hint_target.classList.contains('to_be_hidden')){
hint_target.classList.add('hidden')
hint_target.classList.remove('to_be_hidden')
}
})
}
const displayNextHint = () => {
const hints = document.querySelectorAll('.tutorial_hint')
hints.forEach( (hint_target) => {
if (parseInt(hint_target.dataset.queue) == counter){
hint_target.style = 'background-color: orange'
if (hint_target.classList.contains('hidden')){
hint_target.classList.remove('hidden')
hint_target.classList.add('to_be_hidden')
}
var hint_msg = document.getElementById(`tutorial_hint_${hint_target.dataset.queue}`)
setMessage(hint_msg.innerText)
setAnchorEl(hint_target)
}
})
setCounter(counter + 1)
}
const handleClick = (event) => {
clearAllHints()
displayNextHint()
};
let tutorial_button = document.getElementById('onTutorial')
tutorial_button.addEventListener('onTutorial', handleClick, {once: true})
const handleClose = () => {
const hints = document.querySelectorAll('.tutorial_hint')
if (hints.length < counter){
setMessage('')
setCounter(1)
setAnchorEl(null);
clearAllHints()
}
else{
clearAllHints()
displayNextHint()
}
};
const open = Boolean(anchorEl);
const id = open ? 'simple-popover' : undefined;
return (
{message}
);
}
const popover = document.getElementById('popover-tutorial');
const root = createRoot(popover);
root.render( );
Суть данного кода сводиться к тому, чтобы искать помеченные элементы с классом tutorial_hint и отрендерить подсказку рядом с этим элементом. Функцию на которую стоит обратить внимание это displayNextHint. Найдя все помеченные элементы, она находит элемент с ней связанный и берёт от туда текст подсказки. После чего выделяет элемент подсказки и показывает саму подсказку.
Чтобы компонент смог отрендериться добавим ещё один элемент в app.html, прямо перед app_settings элементом.
И подключим новый компонент в index.js
Помечаем элементы для подсказок
Осталось только пометить необходимые элементы для подсказок.
export default function AppActions(){
const [isModal, setModal] = React.useState(false);
const req = {'setModal': setModal}
return (
Optional: Then you can save all of your configurations
{setModal(true); waitTillModalIsUp(SaveRequest, req)}} className='w-fit tutorial_hint' data-queue="4">
{setModal(false)}}
>
Step 3: And now you can gather all informatino from SERP results
{StartParsingRequest(req)}} className='w-fit tutorial_hint'>
)
}
export default function AppQueries(){
…
return (
{engine_list}
Step 2: Choose an required engine to parse. And then type your query
handleClick(ev,engine_list)} className='w-fit tutorial_hint' data-queue="2">
)
}
export default function AppSettings(){
...
return (
Step 1: Check at least one checkbox, to choose what to save
{/* Icon button is gonna be changed */}
{ isSettings ?
: }
)
}
export default function AppUtils(){
...
return (
Here you can find the most popular and ready-to-use presets
Here you will find your own presets
Here you will see the actual proccess of gathering information
It is a link to a results of parsing proccess
...
}
Выводы или то как это выглядит
По итогу всё это будет выглядеть как-то так:
Если ты пропустил всё что было выше и хочешь просто получить проект в текущем состоянии, то ты можешь скачать его здесь
В следующей статье мы создадим возможность пользователям, входить и регистрироваться на нашем сайте.
0
Использованные термины
- Реакт ⟶ Это библиотека JavaScript, разработанная Facebook для создания пользовательских интерфейсов, в частности, для одностраничных приложений. React позволяет разработчикам создавать компоненты, которые могут эффективно обновлять и рендерить при изменении данных.
- Вебсайт ⟶ Это совокупность связанных между собой веб-страниц, доступных через интернет и имеющих одно общее доменное имя. Каждый веб-сайт может содержать текстовую информацию, изображения, видео и другие мультимедийные элементы. Веб-сайты могут выполнять различные функции, включая предоставление информации, общение, онлайн-торговлю и множество других взаимодействий.
- HTML (Гипер текстовый язык разметки) ⟶ Это стандартный язык разметки, используемый для создания веб-страниц. Он описывает структуру и содержание документа с помощью различных элементов и тегов. HTML позволяет интегрировать текст, изображения, ссылки, формы и другие медиа-элементы.
- Javascript ⟶ Это высокоуровневый, интерпретируемый язык программирования, который используется в основном для разработки веб-приложений. Он был создан в 1995 году и изначально предназначался для добавления интерактивности и динамики на веб-страницы.
Релевантные вопросы
- Как отключить переходы глобально? Material UI использует тот же помощник темы для создания всех своих переходов. Поэтому вы можете отключить все переходы, переопределив помощника в своей теме.
- Когда следует использовать встроенный стиль, а когда CSS? Используйте встроенные стили для динамических свойств стилей. Альтернатива CSS обеспечивает больше преимуществ, таких как автоматическое добавление префиксов, улучшенная отладка, медиа-запросы, ключевые кадры.
- Как работает проп children? Некоторые компоненты не знают своих потомков заранее. Это особенно характерно для таких компонентов, как Sidebar или Dialog, которые представляют из себя как бы «коробку», в которую можно что-то положить. Для таких компонентов мы рекомендуем использовать специальный проп children, который передаст дочерние элементы сразу на вывод
- В чем разница между управляемыми и неуправляемыми компонентами? В управляемом компоненте с каждой мутацией состояния связана функция-обработчик. Благодаря этому валидация или изменение введённого значения становится простой задачей. Неуправляемые компоненты опираются на DOM в качестве источника данных и могут быть удобны при интеграции React с кодом, не связанным с React.
- Как отключить эффект ряби глобально? Эффект ряби исходит исключительно от компонента BaseButton. Вы можете отключить эффект ряби глобально, указав соответствующее значение в своей теме.