-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9765 from scratchfoundation/integration-branch-ux…
…-12.2024 Integration branch ux 12.2024
- Loading branch information
Showing
31 changed files
with
1,496 additions
and
45 deletions.
There are no files selected for viewing
This file contains 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 |
---|---|---|
@@ -0,0 +1,162 @@ | ||
@import "../../css/colors.css"; | ||
|
||
.debug-modal-overlay { | ||
position: fixed; | ||
top: 0; | ||
left: 0; | ||
right: 0; | ||
bottom: 0; | ||
background-color: 'transparent'; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
z-index: 510; | ||
} | ||
|
||
.debug-modal-container { | ||
background: white; | ||
border-radius: 8px; | ||
width: 1000px; | ||
max-height: 90%; | ||
display: flex; | ||
flex-direction: column; | ||
position: relative; | ||
overflow-x: visible; | ||
box-shadow: 0 4px 4px 0 $ui-black-transparent-10; | ||
outline: none; | ||
|
||
.modal-header { | ||
display: flex; | ||
border-radius: 8px 8px 0 0; | ||
justify-content: space-between; | ||
align-items: center; | ||
padding: 8px; | ||
padding-left: 12px; | ||
padding-right: 12px; | ||
background-color: $ui-green-2; | ||
} | ||
|
||
.header-title { | ||
display: flex; | ||
gap: 8px; | ||
align-items: center; | ||
font-size: 1rem; | ||
line-height: 1.25rem; | ||
font-weight: 700; | ||
color: white; | ||
} | ||
.debug-icon { | ||
height: 22px; | ||
width: 22px; | ||
} | ||
|
||
.hidden { | ||
display: none; | ||
} | ||
|
||
.close-button { | ||
display: flex; | ||
background: none; | ||
border: none; | ||
cursor: pointer; | ||
width: 32px; | ||
height: 32px; | ||
} | ||
|
||
.modal-content { | ||
display: flex; | ||
width: 100%; | ||
flex-grow: 1; | ||
overflow-y: scroll; | ||
} | ||
|
||
.modal-content::-webkit-scrollbar-track { | ||
background: transparent; | ||
} | ||
|
||
.modal-content::-webkit-scrollbar { | ||
width: 8px; | ||
} | ||
|
||
.previousIcon { | ||
position: absolute; | ||
cursor: pointer; | ||
top: 50%; | ||
} | ||
|
||
.nextIcon { | ||
position: absolute; | ||
cursor: pointer; | ||
right: -24px; | ||
top: 50%; | ||
} | ||
|
||
.topic-list { | ||
width: 30%; | ||
border-right: 1px solid $ui-green;; | ||
} | ||
|
||
.topic-item { | ||
display: flex; | ||
gap: 8px; | ||
align-items: center; | ||
padding: 8px; | ||
padding-left: 12px; | ||
font-size: 1rem; | ||
line-height: 1.5rem; | ||
color: $ui-green;; | ||
cursor: pointer; | ||
} | ||
|
||
.topic-item.active { | ||
background-color: #D1FAEE; | ||
font-weight: bold; | ||
} | ||
|
||
.info-container { | ||
flex-direction: column; | ||
width: 70%; | ||
display: flex; | ||
padding: 20px; | ||
color: $text-primary; | ||
} | ||
|
||
.text-container { | ||
flex: 1; | ||
margin-left: 70px; | ||
} | ||
|
||
.title-text { | ||
font-size: 24px; | ||
line-height: 32px; | ||
font-weight: 700; | ||
} | ||
|
||
.description { | ||
font-size: 16px; | ||
line-height: 28px; | ||
} | ||
|
||
.imageContainer { | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
padding: 10px; | ||
margin-top: 10px; | ||
} | ||
|
||
.topicImage { | ||
max-width: 100%; | ||
max-height: 100%; | ||
object-fit: contain; /* Ensures image scales proportionally */ | ||
} | ||
|
||
.navigation-buttons { | ||
margin-top: 20px; | ||
} | ||
|
||
button { | ||
margin: 5px; | ||
} | ||
} | ||
|
This file contains 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 |
---|---|---|
@@ -0,0 +1,174 @@ | ||
import React, {useState, useCallback, useEffect} from 'react'; | ||
import {defineMessages, FormattedMessage} from 'react-intl'; | ||
import PropTypes from 'prop-types'; | ||
import ReactModal from 'react-modal'; | ||
import classNames from 'classnames'; | ||
import {sections} from './sections/sections'; | ||
import GA4 from '../../lib/analytics'; | ||
|
||
import styles from './debug-modal.css'; | ||
import debugIcon from './icons/icon--debug.svg'; | ||
import debugIconInverted from './icons/icon--debug-inverted.svg'; | ||
import closeIcon from './icons/icon--close.svg'; | ||
import prevIcon from './icons/icon--prev.svg'; | ||
import nextIcon from './icons/icon--next.svg'; | ||
|
||
const messages = defineMessages({ | ||
title: { | ||
id: 'gui.debugModal.title', | ||
defaultMessage: 'Debugging | Getting Unstuck', | ||
description: 'title for the debugging modal' | ||
} | ||
}); | ||
|
||
const logTopicChange = topicIndex => { | ||
GA4.event({ | ||
category: 'change_topic_debug_modal', | ||
label: sections[topicIndex].id | ||
}); | ||
}; | ||
|
||
const DebugModal = ({isOpen, onClose = () => {}}) => { | ||
const [selectedTopicIndex, setSelectedTopicIndex] = useState(0); | ||
|
||
// Preload images | ||
useEffect(() => { | ||
sections.forEach(section => { | ||
new Image().src = section.image; | ||
}); | ||
}, []); | ||
|
||
const handleNext = useCallback(() => { | ||
if (selectedTopicIndex < sections.length - 1) { | ||
setSelectedTopicIndex(selectedTopicIndex + 1); | ||
logTopicChange(selectedTopicIndex + 1); | ||
} | ||
}, [selectedTopicIndex, setSelectedTopicIndex]); | ||
|
||
const handlePrevious = useCallback(() => { | ||
if (selectedTopicIndex > 0) { | ||
setSelectedTopicIndex(selectedTopicIndex - 1); | ||
logTopicChange(selectedTopicIndex - 1); | ||
} | ||
}, [selectedTopicIndex, setSelectedTopicIndex]); | ||
|
||
const handleTopicSelect = useCallback(index => { | ||
setSelectedTopicIndex(index); | ||
logTopicChange(index); | ||
}, [setSelectedTopicIndex]); | ||
|
||
const handleClose = useCallback(() => { | ||
GA4.event({ | ||
category: 'close_debug_modal' | ||
}); | ||
onClose(); | ||
}, [onClose]); | ||
|
||
useEffect(() => { | ||
if (isOpen) { | ||
GA4.event({ | ||
category: 'open_debug_modal', | ||
label: sections[selectedTopicIndex].id | ||
}); | ||
} | ||
}, [isOpen]); | ||
|
||
if (!isOpen) return null; | ||
|
||
return ( | ||
<ReactModal | ||
isOpen={isOpen} | ||
onRequestClose={handleClose} | ||
className={styles.debugModalContainer} | ||
overlayClassName={styles.debugModalOverlay} | ||
> | ||
<div className={styles.modalHeader}> | ||
<div className={styles.headerTitle}> | ||
<img | ||
className={styles.debugIcon} | ||
src={debugIcon} | ||
/> | ||
<FormattedMessage | ||
{...messages.title} | ||
/> | ||
</div> | ||
<button | ||
className={styles.closeButton} | ||
onClick={handleClose} | ||
> | ||
<img | ||
className={styles.closeIcon} | ||
src={closeIcon} | ||
/> | ||
</button> | ||
</div> | ||
<div className={styles.modalContent} > | ||
<div className={styles.topicList}> | ||
{sections.map((section, index) => ( | ||
<div | ||
key={index} | ||
className={classNames(styles.topicItem, { | ||
[styles.active]: selectedTopicIndex === index | ||
})} | ||
// eslint-disable-next-line react/jsx-no-bind | ||
onClick={() => handleTopicSelect(index)} | ||
> | ||
<div className={styles.debugIcon}> | ||
<img | ||
className={classNames({ | ||
[styles.hidden]: selectedTopicIndex !== index | ||
})} | ||
src={debugIconInverted} | ||
/> | ||
</div> | ||
<FormattedMessage | ||
{...(section.sectionTitle ?? section.title)} | ||
/> | ||
</div> | ||
))} | ||
</div> | ||
<div className={styles.infoContainer}> | ||
<div className={styles.textContainer}> | ||
<div className={styles.titleText}> | ||
<FormattedMessage | ||
{...sections[selectedTopicIndex].title} | ||
/> | ||
</div> | ||
<div className={styles.description}>{sections[selectedTopicIndex].description}</div> | ||
</div> | ||
<div className={styles.imageContainer}> | ||
<img | ||
src={sections[selectedTopicIndex].image} | ||
className={styles.topicImage} | ||
/> | ||
</div> | ||
<div className={styles.navigationButtons}> | ||
<img | ||
src={prevIcon} | ||
alt="Previous" | ||
onClick={handlePrevious} | ||
className={classNames(styles.previousIcon, { | ||
[styles.hidden]: selectedTopicIndex === 0 | ||
})} | ||
/> | ||
<img | ||
src={nextIcon} | ||
alt="Next" | ||
onClick={handleNext} | ||
className={classNames(styles.nextIcon, { | ||
[styles.hidden]: selectedTopicIndex === sections.length - 1 | ||
})} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</ReactModal> | ||
); | ||
}; | ||
|
||
DebugModal.propTypes = { | ||
isOpen: PropTypes.bool, | ||
onClose: PropTypes.func | ||
}; | ||
|
||
export default DebugModal; |
14 changes: 14 additions & 0 deletions
14
src/components/debug-modal/icons/icon--add-sound-checkpoints.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.