Browse Source

Extracted generic FocusedElement hook

master
Dejvino 11 months ago
parent
commit
6dff62d61c
2 changed files with 45 additions and 37 deletions
  1. +42
    -0
      src/app/FocusedElement.tsx
  2. +3
    -37
      src/app/components/TagCloud.tsx

+ 42
- 0
src/app/FocusedElement.tsx View File

@@ -0,0 +1,42 @@
import { useState, useRef, useEffect } from "react";

const focusUrlParamName = 'focus'
const focusChangedEventName = "focus-changed"
const focusedElementClassName = 'focused-element'

function triggerElementFocused(elementKey: string) {
const url = new URL(window.location.href);
url.searchParams.set(focusUrlParamName, elementKey);
const focusChangeEvent = new Event(focusChangedEventName);
history.pushState({}, "", url);
window.dispatchEvent(focusChangeEvent)
}

export function useFocusedElement(elementKey: string) {
const [isFocusedElement, setFocusedElement] = useState(false);
const focusedClass = isFocusedElement ? focusedElementClassName : ''
const elementRef = useRef<HTMLSpanElement>(null)

function focusElement() {
triggerElementFocused(elementKey)
}
useEffect(() => {
function getFocusedState() {
const params = new URLSearchParams(window.location.search)
const focusedElement = params.get(focusUrlParamName)
const focused: boolean = focusedElement && focusedElement == elementKey || false
setFocusedElement(focused)
}

getFocusedState()
addEventListener(focusChangedEventName, getFocusedState)
return () => {
removeEventListener(focusChangedEventName, getFocusedState)
}
}, [elementKey, setFocusedElement])

isFocusedElement && elementRef.current?.scrollIntoView()

return {isFocusedElement, focusedClass, elementRef, focusElement}
}

+ 3
- 37
src/app/components/TagCloud.tsx View File

@@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import Container from 'react-bootstrap/Container';
import { useFocusedElement } from '../FocusedElement';

export type Props = {
title: string,
@@ -8,47 +9,12 @@ export type Props = {
style?: 'primary' | 'light'
}

const focusChangedEventName = "focus-changed"

function useFocusedElement(elementKey: string) {
const [isFocusedElement, setFocusedElement] = useState(false);
const focusedClass = isFocusedElement ? 'focused-element' : ''
const elementRef = useRef<HTMLSpanElement>(null)

useEffect(() => {
function getFocusedState() {
const params = new URLSearchParams(window.location.search)
const focusedElement = params.get('focus')
const focused: boolean = focusedElement && focusedElement == elementKey || false
setFocusedElement(focused)
}

getFocusedState()
addEventListener(focusChangedEventName, getFocusedState)
return () => {
removeEventListener(focusChangedEventName, getFocusedState)
}
}, [elementKey, setFocusedElement])

isFocusedElement && elementRef.current?.scrollIntoView()

return {isFocusedElement, focusedClass, elementRef}
}

function setFocusedElement(elementKey: string) {
const url = new URL(window.location.href);
url.searchParams.set('focus', elementKey);
const focusChangeEvent = new Event(focusChangedEventName);
history.pushState({}, "", url);
window.dispatchEvent(focusChangeEvent)
}

function Tag(props: {text: string}) {
const tagKey = 'tag_' + props.text;
const {focusedClass, elementRef} = useFocusedElement(tagKey)
const {elementRef, focusedClass, focusElement} = useFocusedElement(tagKey)
return (
<span ref={elementRef}
onClick={() => setFocusedElement(tagKey)}
onClick={focusElement}
className={`badge text-bg-light ${focusedClass}`}>{props.text}</span>
)
}


Loading…
Cancel
Save