Skip to content

Commit

Permalink
feat(junior): Design modal for small devices
Browse files Browse the repository at this point in the history
Co-authored-by: <[email protected]>
Co-authored-by: <[email protected]>
  • Loading branch information
rouxxi committed Jan 9, 2025
1 parent ca47ccb commit 5f3d457
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 1 deletion.
135 changes: 135 additions & 0 deletions junior/app/components/device-warning-modal.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import trapFocus from '@1024pix/pix-ui/app/modifiers/trap-focus';
import PixButton from '@1024pix/pix-ui/components/pix-button';
import PixButtonLink from '@1024pix/pix-ui/components/pix-button-link';
import { action } from '@ember/object';
import { service } from '@ember/service';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { t } from 'ember-intl';

import { types } from '../services/device';
const { MOBILE, TABLET } = types;

export default class DeviceWarningModal extends Component {
@tracked showModal = false;
@tracked deviceType = '';
@tracked orientation = '';
@service device;
@service intl;
@service currentLearner;

shouldDisplayModal() {
const { type, orientation } = this.device.info;
this.deviceType = type;
this.orientation = orientation;

if (this.deviceType === MOBILE) {
return true;
}

const shouldDisplay = type === TABLET && orientation.startsWith('portrait');

if (!shouldDisplay && this.showModal) {
this.currentLearner.setHasSeenWarningModal();
} else if (this.currentLearner.hasSeenWarningModal) {
return false;
}

return shouldDisplay;
}

constructor() {
super(...arguments);
if (this.shouldDisplayModal()) {
this.showModal = true;
}

screen.orientation.addEventListener('change', () => {
this.showModal = this.shouldDisplayModal();
});
}

@action
onCloseModal() {
this.currentLearner.setHasSeenWarningModal();
this.showModal = false;
}

get title() {
if (this.deviceType === MOBILE) {
return this.intl.t('components.device-warning-modal.mobile.title');
}

return this.intl.t('components.device-warning-modal.tablet.title');
}

get contentText() {
if (this.deviceType === MOBILE) {
return this.intl.t('components.device-warning-modal.mobile.subtitle');
}

return this.intl.t('components.device-warning-modal.tablet.subtitle');
}

get isTablet() {
return this.deviceType === TABLET;
}

get isMobile() {
return this.deviceType === MOBILE;
}

get modalClassName() {
if (this.deviceType === TABLET) {
return 'device-warning-modal is-tablet';
}

if (this.deviceType === MOBILE) {
if (this.orientation.startsWith('landscape')) {
return 'device-warning-modal is-landscape is-mobile';
}
return 'device-warning-modal is-mobile';
}

return 'device-warning-modal';
}
<template>
<div
class="device-warning-modal-overlay {{unless this.showModal ' device-warning-modal-overlay--hidden'}}"
{{trapFocus this.showModal}}
>
<div class={{this.modalClassName}} role="dialog">
{{#if this.isTablet}}
<PixButton
class="close-button"
@iconBefore="close"
@triggerAction={{this.onCloseModal}}
@ariaLabel="Fermer"
@size="small"
@variant="secondary"
>
{{t "common.actions.close"}}
</PixButton>
{{/if}}

<section>
<img src="/images/logo-in-one-line.svg" alt="Pix Junior" class="logo" />
<h1>
{{this.title}}
</h1>
<h2>
{{#if this.isTablet}}
<img src="/images/icons/screen-rotation.svg" />
{{/if}}
{{this.contentText}}
</h2>
{{#if this.isMobile}}
<PixButtonLink class="button-link" @href="https://pix.fr/enseignement-primaire">
{{t "components.device-warning-modal.button.label"}}
</PixButtonLink>
{{/if}}
</section>
</div>
</div>
</template>
}
11 changes: 10 additions & 1 deletion junior/app/services/current-learner.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@ export default class CurrentLearnerService extends Service {
return JSON.parse(localStorage.getItem('learner'));
}

async setLearner(learner) {
setLearner(learner) {
localStorage.setItem('learner', JSON.stringify(learner));
}

setHasSeenWarningModal() {
localStorage.setItem('learner-has-seen-warning-modal', 'true');
}

get hasSeenWarningModal() {
return !!localStorage.getItem('learner-has-seen-warning-modal');
}

async remove() {
localStorage.removeItem('learner');
localStorage.removeItem('learner-has-seen-warning-modal');
}
}
41 changes: 41 additions & 0 deletions junior/app/services/device.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Service from '@ember/service';

const MOBILE_MAX_HEIGHT = 720;
const MOBILE_MAX_WIDTH = 540;
const TABLET_MAX_HEIGHT = 1366;
const TABLET_MAX_WIDTH = 1024;

export const types = {
DESKTOP: 'desktop',
MOBILE: 'mobile',
TABLET: 'tablet',
};

export default class DeviceService extends Service {
get info() {
return {
orientation: screen.orientation.type,
type: this.getType(screen.orientation.type),
};
}

getType(orientation) {
if (orientation.startsWith('landscape')) {
if (screen.width >= TABLET_MAX_HEIGHT) {
return types.DESKTOP;
}
if (screen.width >= MOBILE_MAX_HEIGHT && screen.height >= MOBILE_MAX_WIDTH) {
return types.TABLET;
}
return types.MOBILE;
} else {
if (screen.width >= TABLET_MAX_WIDTH) {
return types.DESKTOP;
}
if (screen.width >= MOBILE_MAX_WIDTH) {
return types.TABLET;
}
return types.MOBILE;
}
}
}
1 change: 1 addition & 0 deletions junior/app/styles/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
@import 'components/challenge/content/challenge-media';
@import 'components/challenge/challenge-layout';
@import 'components/delayed-element';
@import 'components/device-warning-modal';
@import 'components/mission-card/card';
@import 'components/bubble';
@import 'components/footer';
Expand Down
91 changes: 91 additions & 0 deletions junior/app/styles/components/device-warning-modal.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
.device-warning-modal-overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
background-color: var(--pix-neutral-0);

&--hidden {
visibility: hidden;
opacity: 0;
}
}

.device-warning-modal {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
text-align: initial;
background-image: url('/images/background-blob-with-robot.svg');
background-position-x: right;
background-position-y: bottom;
background-repeat: no-repeat;
background-size: 90%;
background-attachment: fixed;

.close-button {
align-self: self-end;
margin: var(--pix-spacing-8x) var(--pix-spacing-8x) 0 0;
}

section {
display: flex;
flex-direction: column;
gap: var(--pix-spacing-6x);
color: var(--pix-neutral-900);
margin: var(--pix-spacing-12x) var(--pix-spacing-9x);

h1 {
@extend %pix-title-l;
}

h2 {
@extend %pix-title-s;
display: flex;
flex-direction: row;
gap: var(--pix-spacing-6x);
font-weight: 600;
align-items: center;
}

.logo {
width: 182px;
height: 50px;
}

.button-link {
max-width: 200px;
}
}

&.is-mobile {
h1 {
--font-size-title: 1.2rem;
}

h2 {
--font-size-title: 1.2rem;
}

&.is-landscape {
background-size: 45%;

section {
max-width: 52%;
}
}
}

&.is-tablet section {
margin: var(--pix-spacing-6x) 80px;

.logo {
margin-bottom: var(--pix-spacing-3x);
width: 291px;
height: 80px;
}
}
}
1 change: 1 addition & 0 deletions junior/app/templates/application.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{{page-title (t "pages.pix-junior")}}
<div class="app">
<DeviceWarningModal />
<Banner::Communication />
<main>
{{outlet}}
Expand Down
5 changes: 5 additions & 0 deletions junior/public/images/icons/screen-rotation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions junior/translations/fr.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"common": {
"actions": {
"close": "Fermer"
}
},
"components": {
"challenge": {
"embed-simulator": {
Expand All @@ -11,6 +16,20 @@
"label": "Lire la consigne à haute voix",
"play": "J'écoute",
"stop": "Stop"
},
"device-warning-modal": {
"title": "Écran dans le mauvais sens",
"button": {
"label": "Découvrir Pix Junior"
},
"mobile": {
"title": "Cette résolution n’est pas prise en compte.",
"subtitle": "Merci d'utiliser Pix Junior sur une tablette ou un ordinateur."
},
"tablet": {
"title": "Oups, ta tablette n'est pas dans le bon sens...",
"subtitle": "Tourne ta tablette pour commencer à utiliser Pix Junior."
}
}
},
"navigation": {
Expand Down

0 comments on commit 5f3d457

Please sign in to comment.