Skip to content

Commit

Permalink
New: Added xlarge breakpoint, added isScreenSizeMin (#372)
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverfoster authored May 12, 2023
1 parent 30bf5b9 commit 16b2738
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 31 deletions.
41 changes: 30 additions & 11 deletions js/device.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,12 @@ class Device extends Backbone.Controller {
}

/**
* Compares the calculated screen width to the breakpoints defined in config.json.
*
* @returns {string} 'large', 'medium' or 'small'
* Returns an object of screen size names and em values
* @returns {Object}
*/
checkScreenSize() {
get screenSizes() {
const screenSizes = { ...Adapt.config.get('screenSize') };
let screenSizesList = Object.entries(screenSizes);
const screenSizesList = Object.entries(screenSizes);
const screensizeEmThreshold = 300;
const baseFontSize = 16;
for (const [name, value] of screenSizesList) {
Expand All @@ -69,11 +68,28 @@ class Device extends Backbone.Controller {
? value / baseFontSize
: value;
}
// Reread list after modifications
screenSizesList = Object.entries(screenSizes);
return screenSizes;
}

/**
* Returns a boolean if the current screen size is equal to or above the named
* screen size.
* @param {string} name
* @returns {boolean}
*/
isScreenSizeMin(name) {
return Boolean(window.matchMedia(`(min-width: ${this.screenSizes[name]}em)`)?.matches);
}

/**
* Returns the calculated screen width name.
* @returns {string} 'large', 'medium' or 'small'
*/
checkScreenSize() {
const screenSizesList = Object.entries(this.screenSizes);
screenSizesList.sort((a, b) => a[1] - b[1]);
const fontSize = parseFloat($('html').css('font-size'));
const screenSizeEmWidth = (window.innerWidth / fontSize);
screenSizesList.sort((a, b) => a[1] - b[1]);
const smallestScreenSize = screenSizesList[0][0];
// Find the best sized screen size
const screenSize = screenSizesList.reduce((screenSize, [name, value]) => {
Expand Down Expand Up @@ -154,9 +170,12 @@ class Device extends Backbone.Controller {
const newScreenSize = this.checkScreenSize();
if (newScreenSize !== this.screenSize) {
this.screenSize = newScreenSize;
this.$html.toggleClass('size-small', this.screenSize === 'small');
this.$html.toggleClass('size-medium', this.screenSize === 'medium');
this.$html.toggleClass('size-large', this.screenSize === 'large');
const screenSizes = this.screenSizes;
for (const name in screenSizes) {
if (name === this.screenSize) continue;
this.$html.removeClass(`size-${name}`);
}
this.$html.toggleClass(`size-${this.screenSize}`, true);
Adapt.trigger('device:changed', this.screenSize);
}

Expand Down
7 changes: 3 additions & 4 deletions less/_defaults/_variables.less
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,16 @@
// --------------------------------------------------
// html = 16px

// 20rem = 320px
// 32.5rem = 520px
// 47.5rem = 760px
// 56.25rem = 900px
// 45rem = 720px
// 60rem = 960px
// 80rem = 1280px
// 90rem = 1440px
// 120rem = 1920px

@device-width-small: unit(@adapt-device-small, rem);
@device-width-medium: unit(@adapt-device-medium, rem);
@device-width-large: unit(@adapt-device-large, rem);
@device-width-xlarge: unit(@adapt-device-xlarge, rem);

@max-width: 90rem;

Expand Down
21 changes: 15 additions & 6 deletions schema/config.model.schema
Original file line number Diff line number Diff line change
Expand Up @@ -195,29 +195,38 @@
"small": {
"type": "number",
"required": true,
"default": 520,
"default": 0,
"title": "Small",
"inputType": "Number",
"validators": ["required", "number"],
"help": "Pixel width for the small breakpoint, e.g. cellphones"
"help": "Pixel width for the start of the small breakpoint, e.g. cellphones"
},
"medium": {
"type": "number",
"required": true,
"default": 760,
"default": 720,
"title": "Medium",
"inputType": "Number",
"validators": ["required", "number"],
"help": "Pixel width for the medium breakpoint, e.g. tablet devices"
"help": "Pixel width for the start of the medium breakpoint, e.g. tablet devices"
},
"large": {
"type": "number",
"required": true,
"default": 900,
"default": 960,
"title": "Large",
"inputType": "Number",
"validators": ["required", "number"],
"help": "Pixel width for the large breakpoint, e.g. laptop/desktop computers"
"help": "Pixel width for the start of the large breakpoint, e.g. laptop/desktop computers"
},
"xlarge": {
"type": "number",
"required": true,
"default": 1280,
"title": "Large",
"inputType": "Number",
"validators": ["required", "number"],
"help": "Pixel width for the start of the extra large breakpoint, e.g. hd laptop/desktop computers"
}
}
},
Expand Down
18 changes: 12 additions & 6 deletions schema/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -179,20 +179,26 @@
"small": {
"type": "number",
"title": "Small",
"description": "Pixel width for the small breakpoint, e.g. cellphones",
"default": 520
"description": "Pixel width for the start of the small breakpoint, e.g. cellphones",
"default": 0
},
"medium": {
"type": "number",
"title": "Medium",
"description": "Pixel width for the medium breakpoint, e.g. tablet devices",
"default": 760
"description": "Pixel width for the start of the medium breakpoint, e.g. tablet devices",
"default": 720
},
"large": {
"type": "number",
"title": "Large",
"description": "Pixel width for the large breakpoint, e.g. laptop/desktop computers",
"default": 900
"description": "Pixel width for the start of the large breakpoint, e.g. laptop/desktop computers",
"default": 960
},
"xlarge": {
"type": "number",
"title": "Large",
"description": "Pixel width for the start of the extra large breakpoint, e.g. hd laptop/desktop computers",
"default": 1280
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion templates/header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function Header(props) {
_extension && _extension.toLowerCase()
].filter(Boolean)
} = props;
const sizedInstruction = (mobileInstruction && device.screenSize !== 'large') ?
const sizedInstruction = (mobileInstruction && !device.isScreenSizeMin('medium')) ?
mobileInstruction :
instruction;
const _globals = Adapt.course.get('_globals');
Expand Down
6 changes: 3 additions & 3 deletions templates/image.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import { html, classes, prefixClasses } from 'core/js/reactHelpers';
* @param {Array} [props.attributionClassNamePrefixes]
*/
export default function Image(props) {
const hasMediumSetting = (Object.prototype.hasOwnProperty.call(props, '_medium') || Object.prototype.hasOwnProperty.call(props, 'medium'));
const screenSize = hasMediumSetting
const hasMatchingSetting = (Object.hasOwn(props, `_${device.screenSize}`) || Object.hasOwn(props, device.screenSize));
const screenSize = hasMatchingSetting
? device.screenSize
: (device.screenSize === 'large' ? 'large' : 'small');
: (device.isScreenSizeMin('medium') ? 'large' : 'small');
const src = (
props[`_${screenSize}`] ||
props[`${screenSize}`] ||
Expand Down

0 comments on commit 16b2738

Please sign in to comment.