From cfba7fcdabeaa5d0bc886ea576f7ffdd26f14da9 Mon Sep 17 00:00:00 2001 From: Orta Therox Date: Sun, 12 Jan 2020 21:38:03 +0000 Subject: [PATCH] Support mobile phones on the dev pages --- .../lib/utils/isTouchDevice.ts | 26 ++++++++ .../src/components/SuppressWhenTouch.tsx | 36 +++++++++++ .../typescriptlang-org/src/pages/dev/dev.scss | 26 ++++++++ .../src/pages/dev/sandbox.tsx | 24 +++++--- .../src/pages/dev/twoslash.tsx | 59 +++++++++++-------- 5 files changed, 136 insertions(+), 35 deletions(-) create mode 100644 packages/typescriptlang-org/lib/utils/isTouchDevice.ts create mode 100644 packages/typescriptlang-org/src/components/SuppressWhenTouch.tsx diff --git a/packages/typescriptlang-org/lib/utils/isTouchDevice.ts b/packages/typescriptlang-org/lib/utils/isTouchDevice.ts new file mode 100644 index 000000000000..499cfc5131a9 --- /dev/null +++ b/packages/typescriptlang-org/lib/utils/isTouchDevice.ts @@ -0,0 +1,26 @@ +/** Based on https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent */ +export function isTouchDevice() { + return true + var hasTouchScreen = false + if ("maxTouchPoints" in navigator) { + hasTouchScreen = navigator.maxTouchPoints > 0 + } else if ("msMaxTouchPoints" in navigator) { + // @ts-ignore + hasTouchScreen = navigator.msMaxTouchPoints > 0 + } else { + var mQ = window.matchMedia && matchMedia("(pointer:coarse)") + if (mQ && mQ.media === "(pointer:coarse)") { + hasTouchScreen = !!mQ.matches + } else if ("orientation" in window) { + hasTouchScreen = true // deprecated, but good fallback + } else { + // Only as a last resort, fall back to user agent sniffing + // @ts-ignore + var UA = navigator.userAgent + hasTouchScreen = + /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) || + /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA) + } + } + return hasTouchScreen +} diff --git a/packages/typescriptlang-org/src/components/SuppressWhenTouch.tsx b/packages/typescriptlang-org/src/components/SuppressWhenTouch.tsx new file mode 100644 index 000000000000..f0abf2bde586 --- /dev/null +++ b/packages/typescriptlang-org/src/components/SuppressWhenTouch.tsx @@ -0,0 +1,36 @@ +import React, { useEffect } from "react" +import { isTouchDevice } from "../../lib/utils/isTouchDevice" + +/** + * A React component which will remove its children (at runtime!) + * from the hierarchy if we're on a touch device + */ +export const SuppressWhenTouch = ({ children, hideOnTouch }: any) => { + + useEffect(() => { + if (isTouchDevice()) { + // It's touch, so let's kill the content in the child and + // replace it with a message that this section isn't good for mobile + const suppressible = document.getElementById("touch-suppressible")! + while (suppressible.firstChild) { + suppressible.removeChild(suppressible.firstChild) + } + + if (hideOnTouch) return + + const h4 = document.createElement("h4") + h4.textContent = "Section best on a computer" + + const p = document.createElement("p") + p.textContent = "This part of the site does not run well on a touch-oriented browser. We recommend switching to a computer to carry on." + + suppressible.appendChild(h4) + suppressible.appendChild(p) + } + + }) + return ( +
+ {children} +
) +} diff --git a/packages/typescriptlang-org/src/pages/dev/dev.scss b/packages/typescriptlang-org/src/pages/dev/dev.scss index b0411e33e16c..51f468dae5af 100644 --- a/packages/typescriptlang-org/src/pages/dev/dev.scss +++ b/packages/typescriptlang-org/src/pages/dev/dev.scss @@ -1,3 +1,5 @@ +$width-for-single-column: 800px; + #dev { .content { display: flex; @@ -6,6 +8,8 @@ pre { background-color: #f9f9f9; color: black; + margin-right: 0; + overflow-x: scroll; .mtk5 { color: black; @@ -17,12 +21,34 @@ flex-direction: row; width: 100%; + @media (max-width: $width-for-single-column) { + flex-direction: column; + } + > p, > div { flex: 1; } } + .split-sixhundred { + width: calc(100% - 600px); + @media (max-width: $width-for-single-column) { + width: 100%; + } + } + .sixhundred { + width: 600px; + margin-left: 20px; + + @media (max-width: $width-for-single-column) { + width: 100%; + margin-left: 0px; + padding-left: 20px; + text-align: center; + } + } + .split-code { display: flex; diff --git a/packages/typescriptlang-org/src/pages/dev/sandbox.tsx b/packages/typescriptlang-org/src/pages/dev/sandbox.tsx index f29ce3b7d8c5..ad08db8400ef 100644 --- a/packages/typescriptlang-org/src/pages/dev/sandbox.tsx +++ b/packages/typescriptlang-org/src/pages/dev/sandbox.tsx @@ -4,11 +4,14 @@ import { withPrefix } from "gatsby" import "./dev.scss" import { DevNav } from "../../components/dev-nav" - - +import { isTouchDevice } from "../../../lib/utils/isTouchDevice" +import { SuppressWhenTouch } from "../../components/SuppressWhenTouch" const Index = (props: any) => { useEffect(() => { + // Don't even bother getting monaco + if (isTouchDevice()) { return } + const getLoaderScript = document.createElement('script'); getLoaderScript.src = withPrefix("/js/vs.loader.js"); getLoaderScript.async = true; @@ -69,7 +72,7 @@ export default async function () {
-
+

TypeScript Sandbox

A DOM library for interacting with TypeScript and JavaScript code, which powers the heart of the TypeScript playground

You can use the TypeScript sandbox for:

@@ -82,13 +85,16 @@ export default async function () {

This library builds on top of the Monaco Editor, providing a higher level API but offering access to all the lower-level APIs via a single sandbox object.

You can find the code for the TypeScript Sandbox inside the microsoft/TypeScript-Website mono-repo.

-
-
-
-

Downloading Sandbox...

+ + +
+
+
+

Downloading Sandbox...

+
+
-
-
+
diff --git a/packages/typescriptlang-org/src/pages/dev/twoslash.tsx b/packages/typescriptlang-org/src/pages/dev/twoslash.tsx index e86133662ee1..c31d59a7cb3a 100644 --- a/packages/typescriptlang-org/src/pages/dev/twoslash.tsx +++ b/packages/typescriptlang-org/src/pages/dev/twoslash.tsx @@ -8,6 +8,8 @@ import { renderToHTML } from "gatsby-remark-shiki/src/renderer" import "./dev.scss" import { DevNav } from "../../components/dev-nav" +import { isTouchDevice } from "../../../lib/utils/isTouchDevice" +import { SuppressWhenTouch } from "../../components/SuppressWhenTouch" /** Note: to run all the web infra in debug, run: localStorage.debug = '*' @@ -17,6 +19,9 @@ import { DevNav } from "../../components/dev-nav" const Index = (props: any) => { useEffect(() => { + // No monaco for touch + if (isTouchDevice()) { return } + const getLoaderScript = document.createElement('script'); getLoaderScript.src = withPrefix("/js/vs.loader.js"); getLoaderScript.async = true; @@ -176,38 +181,40 @@ const Index = (props: any) => {
-
-

Markup

-

{codeSamples[0].blurb}

-
-
-

Downloading Sandbox...

-
-
-
- {codeSamples.map(code => { - const setExample = (e) => { - if (e.target.classList.contains("disabled")) return - - document.getElementById("exampleBlurb")!.innerText = code.blurb - // @ts-ignore - window.sandbox.setText(code.code) + + +
+

Markup

+

{codeSamples[0].blurb}

+
+
+

Downloading Sandbox...

+
+
+
+ {codeSamples.map(code => { + const setExample = (e) => { + if (e.target.classList.contains("disabled")) return + + document.getElementById("exampleBlurb")!.innerText = code.blurb + // @ts-ignore + window.sandbox.setText(code.code) + } + return
{code.name}
} - return
{code.name}
- } - )} + )} +
-
-
-

Results

+
+

Results

-
-
-
+
+
+
+
-

Usage

Twoslash will be available on NPM soon, for now it's only being used in the TypeScript website.