Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 8
fix: add allowClickOutside prop to Modal for improved interaction#735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
acdc4b7
fix: add allowClickOutside prop to Modal for improved interaction
Bekiboo 6a95887
fix: enhance DisclaimerModal with tooltip and animation effects
Bekiboo 7e2cd81
fix: update ProtectedLayout to include disclaimer modal with enhanced…
Bekiboo fd12631
fix: enhance disclaimer modal with pulsing animation and tooltip for …
Bekiboo ea5e8b7
fix: improve disclaimer handling with localStorage check and user hint
Bekiboo 43162b4
fix: update Modal to use onClickOutside prop for improved interaction…
Bekiboo 728d138
fix: implement safe localStorage access methods for disclaimer handli…
Bekiboo 1adc81f
fix: improve disclaimer handling with enhanced localStorage access an…
Bekiboo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
154 changes: 108 additions & 46 deletions
154 platforms/blabsy/src/components/layout/common-layout.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,77 +2,139 @@ import { useRequireAuth } from '@lib/hooks/useRequireAuth'; | ||
| import { Aside } from '@components/aside/aside'; | ||
| import { Suggestions } from '@components/aside/suggestions'; | ||
| import { Placeholder } from '@components/common/placeholder'; | ||
| import { type ReactNode, useState } from 'react'; | ||
| import { type ReactNode, useState, useEffect, useRef } from 'react'; | ||
| import { Modal } from '@components/modal/modal'; | ||
| import { Button } from '@components/ui/button'; | ||
| import { useAuth } from '@lib/context/auth-context'; | ||
| export type LayoutProps = { | ||
| children: ReactNode; | ||
| }; | ||
| const DISCLAIMER_KEY = 'blabsy-disclaimer-accepted'; | ||
| // Safe localStorage access for restricted environments | ||
| const safeGetItem = (key: string): string | null => { | ||
| try { | ||
| return localStorage.getItem(key); | ||
| } catch { | ||
| return null; | ||
| } | ||
| }; | ||
| const safeSetItem = (key: string, value: string): void => { | ||
| try { | ||
| localStorage.setItem(key, value); | ||
| } catch { | ||
| // Silently fail in restricted environments | ||
| } | ||
| }; | ||
| export function ProtectedLayout({ children }: LayoutProps): JSX.Element { | ||
| const user = useRequireAuth(); | ||
| const { signOut } = useAuth(); | ||
| const [disclaimerAccepted, setDisclaimerAccepted] = useState(false); | ||
| const [disclaimerChecked, setDisclaimerChecked] = useState(false); | ||
| const [showHint, setShowHint] = useState(false); | ||
| const [isPulsing, setIsPulsing] = useState(false); | ||
| useEffect(() => { | ||
| let accepted = false; | ||
| try { | ||
| accepted = localStorage.getItem(DISCLAIMER_KEY) === 'true'; | ||
| } catch { | ||
| // Storage may be unavailable; fall back to session-only acceptance. | ||
| } | ||
| setDisclaimerAccepted(accepted); | ||
| setDisclaimerChecked(true); | ||
| }, []); | ||
| const pulseTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null); | ||
| const handleOutsideClick = () => { | ||
| setIsPulsing(true); | ||
| setShowHint(true); | ||
| if (pulseTimeoutRef.current) clearTimeout(pulseTimeoutRef.current); | ||
| pulseTimeoutRef.current = setTimeout(() => setIsPulsing(false), 400); | ||
| }; | ||
| if (!user) return <Placeholder />; | ||
| if (!disclaimerChecked) return <></>; | ||
| if (disclaimerAccepted) return <>{children}</>; | ||
| return ( | ||
| <> | ||
| {children} | ||
| {!disclaimerAccepted ? ( | ||
| <Modal | ||
| open={!disclaimerAccepted} | ||
| closeModal={() => signOut()} | ||
| className='max-w-lg mx-auto mt-24' | ||
| modalClassName='bg-black backdrop-blur-md p-6 rounded-lg flex flex-col gap-2' | ||
| <Modal | ||
| open={true} | ||
| closeModal={handleOutsideClick} | ||
| className='max-w-lg mx-auto mt-24' | ||
| modalClassName={`bg-black backdrop-blur-md p-6 rounded-lg flex flex-col gap-2 ${isPulsing ? 'animate-pulse-scale' : ''}`} | ||
| > | ||
| <style>{` | ||
| @keyframes pulse-scale { | ||
| 0% { transform: scale(1); } | ||
| 25% { transform: scale(1.01); } | ||
| 50% { transform: scale(0.99); } | ||
| 75% { transform: scale(1.005); } | ||
| 100% { transform: scale(1); } | ||
| } | ||
| .animate-pulse-scale { | ||
| animation: pulse-scale 0.4s ease-in-out; | ||
| } | ||
| `}</style> | ||
| <h1 className='text-xl text-center font-bold'> | ||
| Disclaimer from MetaState Foundation | ||
| </h1> | ||
| <p className='font-bold'>⚠️ Please note:</p> | ||
| <p> | ||
| Blabsy is a <b>functional prototype</b>, intended to | ||
| showcase <b>interoperability</b> and core concepts of | ||
| the W3DS ecosystem. | ||
| </p> | ||
| <p> | ||
| <b>It is not a production-grade platform</b> and may | ||
| lack full reliability, performance, and security | ||
| guarantees. | ||
| </p> | ||
| <p> | ||
| We <b>strongly recommend</b> that you avoid sharing{' '} | ||
| <b>sensitive or private content</b>, and kindly ask for | ||
| your understanding regarding any bugs, incomplete | ||
| features, or unexpected behaviours. | ||
| </p> | ||
| <p> | ||
| The app is still in development, so we kindly ask for | ||
| your understanding regarding any potential issues. If | ||
| you experience issues or have feedback, feel free to | ||
| contact us at: | ||
| </p> | ||
| <a | ||
| href='mailto:info@metastate.foundation' | ||
| className='focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-400' | ||
| > | ||
| <h1 className='text-xl text-center font-bold'> | ||
| Disclaimer from MetaState Foundation | ||
| </h1> | ||
| <p className='font-bold'>⚠️ Please note:</p> | ||
| <p> | ||
| Blabsy is a <b>functional prototype</b>, intended to | ||
| showcase <b>interoperability</b> and core concepts of | ||
| the W3DS ecosystem. | ||
| </p> | ||
| <p> | ||
| <b>It is not a production-grade platform</b> and may | ||
| lack full reliability, performance, and security | ||
| guarantees. | ||
| </p> | ||
| <p> | ||
| We <b>strongly recommend</b> that you avoid sharing{' '} | ||
| <b>sensitive or private content</b>, and kindly ask for | ||
| your understanding regarding any bugs, incomplete | ||
| features, or unexpected behaviours. | ||
| </p> | ||
| <p> | ||
| The app is still in development, so we kindly ask for | ||
| your understanding regarding any potential issues. If | ||
| you experience issues or have feedback, feel free to | ||
| contact us at: | ||
| </p> | ||
| <a | ||
| href='mailto:info@metastate.foundation' | ||
| className='outline-none' | ||
| > | ||
| info@metastate.foundation | ||
| </a> | ||
| info@metastate.foundation | ||
| </a> | ||
| <div className='relative mt-4'> | ||
| {showHint && ( | ||
| <div className='mb-2 text-xs text-center text-yellow-400 bg-yellow-900/30 px-3 py-2 rounded'> | ||
| 💡 You must accept the disclaimer to continue. This will only appear once. | ||
| </div> | ||
| )} | ||
Bekiboo marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| <Button | ||
| type='button' | ||
| className='mt-4 bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600' | ||
| className='w-full bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600' | ||
| onClick={() => { | ||
| try { | ||
| localStorage.setItem(DISCLAIMER_KEY, 'true'); | ||
| } catch { | ||
| // Ignore storage failures; allow access for this session. | ||
| } | ||
| setDisclaimerAccepted(true); | ||
| }} | ||
| > | ||
| I Understand | ||
| </Button> | ||
| </Modal> | ||
| ) : ( | ||
| <></> | ||
| )} | ||
| </div> | ||
| </Modal> | ||
| </> | ||
| ); | ||
| } | ||
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.