Skip to content

Commit

Permalink
Merge pull request #9765 from scratchfoundation/integration-branch-ux…
Browse files Browse the repository at this point in the history
…-12.2024

Integration branch ux 12.2024
  • Loading branch information
KManolov3 authored Dec 4, 2024
2 parents 18eaaa0 + dcf17db commit 68f5adc
Show file tree
Hide file tree
Showing 31 changed files with 1,496 additions and 45 deletions.
162 changes: 162 additions & 0 deletions src/components/debug-modal/debug-modal.css
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;
}
}

174 changes: 174 additions & 0 deletions src/components/debug-modal/debug-modal.jsx
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 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.
Loading

0 comments on commit 68f5adc

Please sign in to comment.