Skip to content

Commit

Permalink
Merge pull request #420 from jerempy/feature/useMediaQuery
Browse files Browse the repository at this point in the history
useMediaQuery
  • Loading branch information
dartpain authored Oct 4, 2023
2 parents cd4da2a + 4be0c1c commit 5cb3df6
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 67 deletions.
13 changes: 4 additions & 9 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,19 @@ import { Routes, Route } from 'react-router-dom';
import Navigation from './Navigation';
import Conversation from './conversation/Conversation';
import About from './About';
import { useState } from 'react';
import { ActiveState } from './models/misc';
import { inject } from '@vercel/analytics';
import { useMediaQuery } from './hooks';

inject();

export default function App() {
//TODO : below media query is disjoint from tailwind. Please wire it together.
const [navState, setNavState] = useState<ActiveState>(
window.matchMedia('(min-width: 768px)').matches ? 'ACTIVE' : 'INACTIVE',
);

const { isMobile } = useMediaQuery();
return (
<div className="min-h-full min-w-full">
<Navigation navState={navState} setNavState={setNavState} />
<Navigation />
<div
className={`transition-all duration-200 ${
navState === 'ACTIVE' ? 'ml-0 md:ml-72 lg:ml-60' : 'ml-0 md:ml-16'
!isMobile ? 'ml-0 md:ml-72 lg:ml-60' : 'ml-0 md:ml-16'
}`}
>
<Routes>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export default function Hero({ className = '' }: { className?: string }) {
</p>
<p className="mb-3 text-center leading-6 text-black-1000">
Enter a query related to the information in the documentation you
selected to receive and we will provide you with the most relevant
answers.
selected to receive
<br /> and we will provide you with the most relevant answers.
</p>
<p className="mb-3 text-center leading-6 text-black-1000">
Start by entering your query in the input field below and we will do the
Expand Down
60 changes: 28 additions & 32 deletions frontend/src/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,19 @@ import {
setConversation,
updateConversationId,
} from './conversation/conversationSlice';
import { useOutsideAlerter } from './hooks';
import { useMediaQuery, useOutsideAlerter } from './hooks';
import Upload from './upload/Upload';
import { Doc, getConversations } from './preferences/preferenceApi';
import SelectDocsModal from './preferences/SelectDocsModal';

export default function Navigation({
navState,
setNavState,
}: {
navState: ActiveState;
setNavState: React.Dispatch<React.SetStateAction<ActiveState>>;
}) {
export default function Navigation() {
const dispatch = useDispatch();
const docs = useSelector(selectSourceDocs);
const selectedDocs = useSelector(selectSelectedDocs);
const conversations = useSelector(selectConversations);
const conversationId = useSelector(selectConversationId);
const { isMobile } = useMediaQuery();
const [navOpen, setNavOpen] = useState(!isMobile);

const [isDocsListOpen, setIsDocsListOpen] = useState(false);

Expand All @@ -59,7 +55,8 @@ export default function Navigation({

const navRef = useRef(null);
const apiHost = import.meta.env.VITE_API_HOST || 'https://docsapi.arc53.com';
const embeddingsName = import.meta.env.VITE_EMBEDDINGS_NAME || 'openai_text-embedding-ada-002';
const embeddingsName =
import.meta.env.VITE_EMBEDDINGS_NAME || 'openai_text-embedding-ada-002';

useEffect(() => {
if (!conversations) {
Expand Down Expand Up @@ -123,51 +120,46 @@ export default function Navigation({
useOutsideAlerter(
navRef,
() => {
if (
window.matchMedia('(max-width: 768px)').matches &&
navState === 'ACTIVE' &&
apiKeyModalState === 'INACTIVE'
) {
setNavState('INACTIVE');
if (isMobile && navOpen && apiKeyModalState === 'INACTIVE') {
setNavOpen(false);
setIsDocsListOpen(false);
}
},
[navState, isDocsListOpen, apiKeyModalState],
[navOpen, isDocsListOpen, apiKeyModalState],
);

/*
Needed to fix bug where if mobile nav was closed and then window was resized to desktop, nav would still be closed but the button to open would be gone, as per #1 on issue #146
*/

useEffect(() => {
window.addEventListener('resize', () => {
if (window.matchMedia('(min-width: 768px)').matches) {
setNavState('ACTIVE');
} else {
setNavState('INACTIVE');
}
});
}, []);
if (isMobile) {
setNavOpen(false);
return;
}
setNavOpen(true);
}, [isMobile]);

return (
<>
<div
ref={navRef}
className={`${
navState === 'INACTIVE' && '-ml-96 md:-ml-[14rem]'
!navOpen && '-ml-96 md:-ml-[14rem]'
} duration-20 fixed z-20 flex h-full w-72 flex-col border-r-2 bg-gray-50 transition-all`}
>
<div className={'visible h-16 w-full border-b-2 md:hidden'}>
<button
className="float-right mr-5 mt-5 h-5 w-5"
onClick={() =>
setNavState(navState === 'ACTIVE' ? 'INACTIVE' : 'ACTIVE')
}
onClick={() => {
setNavOpen(!navOpen);
}}
>
<img
src={Arrow1}
alt="menu toggle"
className={`${
navState === 'INACTIVE' ? 'rotate-180' : 'rotate-0'
!navOpen ? 'rotate-180' : 'rotate-0'
} m-auto w-3 transition-all duration-200`}
/>
</button>
Expand All @@ -176,7 +168,11 @@ export default function Navigation({
to={'/'}
onClick={() => {
dispatch(setConversation([]));
dispatch(updateConversationId({ query: { conversationId: null } }));
dispatch(
updateConversationId({
query: { conversationId: null },
}),
);
}}
className={({ isActive }) =>
`${
Expand Down Expand Up @@ -327,7 +323,7 @@ export default function Navigation({
<img src={Link} alt="link" className="ml-2 w-5" />
<p className="my-auto text-eerie-black">Documentation</p>
</a>

<a
href="https://discord.gg/WHJdfbQDR4"
target="_blank"
Expand All @@ -352,7 +348,7 @@ export default function Navigation({
<div className="fixed h-16 w-full border-b-2 bg-gray-50 md:hidden">
<button
className="mt-5 ml-6 h-6 w-6 md:hidden"
onClick={() => setNavState('ACTIVE')}
onClick={() => setNavOpen(true)}
>
<img src={Hamburger} alt="menu toggle" className="w-7" />
</button>
Expand Down
19 changes: 0 additions & 19 deletions frontend/src/hooks.ts

This file was deleted.

45 changes: 45 additions & 0 deletions frontend/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useEffect, RefObject, useState } from 'react';

export function useOutsideAlerter<T extends HTMLElement>(
ref: RefObject<T>,
handler: () => void,
additionalDeps: unknown[],
) {
useEffect(() => {
function handleClickOutside(this: Document, event: MouseEvent) {
if (ref.current && !ref.current.contains(event.target as Node)) {
handler();
}
}
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [ref, ...additionalDeps]);
}

// Use isMobile for checking if the width is in the expected mobile range (less than 768px)
// use IsDesktop for effects you explicitly only want when width is wider than 960px.
export function useMediaQuery() {
const mobileQuery = '(max-width: 768px)';
const desktopQuery = '(min-width: 960px)';
const [isMobile, setIsMobile] = useState(false);
const [isDesktop, setIsDesktop] = useState(false);

useEffect(() => {
const mobileMedia = window.matchMedia(mobileQuery);
const desktopMedia = window.matchMedia(desktopQuery);
const updateMediaQueries = () => {
setIsMobile(mobileMedia.matches);
setIsDesktop(desktopMedia.matches);
};
updateMediaQueries();
const listener = () => updateMediaQueries();
window.addEventListener('resize', listener);
return () => {
window.removeEventListener('resize', listener);
};
}, [mobileQuery, desktopQuery]);

return { isMobile, isDesktop };
}
8 changes: 3 additions & 5 deletions frontend/src/preferences/APIKeyModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { ActiveState } from '../models/misc';
import { selectApiKey, setApiKey } from './preferenceSlice';
import { useOutsideAlerter } from './../hooks';
import { useMediaQuery, useOutsideAlerter } from './../hooks';
import Modal from '../Modal';

export default function APIKeyModal({
Expand All @@ -19,14 +19,12 @@ export default function APIKeyModal({
const [key, setKey] = useState(apiKey);
const [isError, setIsError] = useState(false);
const modalRef = useRef(null);
const { isMobile } = useMediaQuery();

useOutsideAlerter(
modalRef,
() => {
if (
window.matchMedia('(max-width: 768px)').matches &&
modalState === 'ACTIVE'
) {
if (isMobile && modalState === 'ACTIVE') {
setModalState('INACTIVE');
}
},
Expand Down

2 comments on commit 5cb3df6

@vercel
Copy link

@vercel vercel bot commented on 5cb3df6 Oct 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs-gpt – ./frontend

docs-gpt-brown.vercel.app
docs-gpt-arc53.vercel.app
docs-gpt-git-main-arc53.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 5cb3df6 Oct 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nextra-docsgpt – ./docs

nextra-docsgpt.vercel.app
nextra-docsgpt-git-main-arc53.vercel.app
docs.docsgpt.co.uk
nextra-docsgpt-arc53.vercel.app

Please sign in to comment.