Replace Playground with JSX Editor (#1500)
Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/1500 Inspired by the frequent usage of Expo snacks to run RN, to repro Yoga issues, this replaces the Playground port with a new ground up Playground UI. This UI right now is pretty simple, with a JSX editor which creates a Yoga tree, which is then rendered using the WebAssembly variant of Yoga. There are a lot of ways we can continue to improve this, but this merges the foundation. Subjectively, I find this more useful as a tool to play with Yoga behavior than the GUI. This also replaces some of the bits of the homepage, and adds a playground entrypoint (though it's pretty identical to the one I've been testing on the home page). Reviewed By: yungsters Differential Revision: D51963201 fbshipit-source-id: 1265cb1784151b685686e189d47ecd42cbacdf8f
This commit is contained in:
committed by
Facebook GitHub Bot
parent
0d03d8a06d
commit
77742af676
@@ -5,156 +5,30 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CSS files with the .module.css suffix will be treated as CSS modules
|
||||
* and scoped locally.
|
||||
*/
|
||||
|
||||
html[data-theme='light'] {
|
||||
--yg-color-playound-background: var(--ifm-color-gray-200);
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
--yg-color-playound-background: var(--ifm-color-background);
|
||||
}
|
||||
|
||||
.heroBanner {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.heroRow {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.blueprintColumn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 996px) {
|
||||
.blueprintColumn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.blueprint {
|
||||
--blueprint-gap: 5%;
|
||||
--fadein-duration: 500ms;
|
||||
box-shadow: var(--ifm-global-shadow-tl);
|
||||
background-color: var(--ifm-background-surface-color);
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
|
||||
.blueprintContainer {
|
||||
position: relative;
|
||||
width: var(--ifm-col-width);
|
||||
aspect-ratio: 1.0;
|
||||
background-color: var(--ifm-color-primary-lighter);
|
||||
box-shadow: var(--ifm-global-shadow-lw);
|
||||
}
|
||||
|
||||
.blueprintAvatar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: var(--blueprint-gap) 0 0 var(--blueprint-gap);
|
||||
width: calc(25% - (var(--blueprint-gap)));
|
||||
height: calc(25% - (var(--blueprint-gap)));
|
||||
animation: avatar-fadein var(--fadein-duration) ease;
|
||||
}
|
||||
|
||||
@keyframes avatar-fadein {
|
||||
0% {
|
||||
transform: scale(1.1);
|
||||
opacity: 0%;
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.0);
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.blueprintTitle {
|
||||
position: absolute;
|
||||
left: 25%;
|
||||
top: 0;
|
||||
right: 10%;
|
||||
margin: var(--blueprint-gap) var(--blueprint-gap) 0 var(--blueprint-gap);
|
||||
height: calc(10% - (var(--blueprint-gap)));
|
||||
animation: title-fadein var(--fadein-duration) ease;
|
||||
}
|
||||
|
||||
.blueprintSubtitle {
|
||||
position: absolute;
|
||||
left: 25%;
|
||||
top: 10%;
|
||||
right: 30%;
|
||||
margin: var(--blueprint-gap);
|
||||
height: calc(10% - (var(--blueprint-gap)));
|
||||
animation: title-fadein var(--fadein-duration) ease;
|
||||
}
|
||||
|
||||
@keyframes title-fadein {
|
||||
0% {
|
||||
transform: scale(1.1);
|
||||
opacity: 0%;
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: scale(1.1);
|
||||
opacity: 0%;
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: scale(1.0);
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.blueprintContent {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
margin: var(--blueprint-gap);
|
||||
width: calc(100% - (var(--blueprint-gap) * 2));
|
||||
height: calc(75% - (var(--blueprint-gap) * 2));
|
||||
animation: content-fadein var(--fadein-duration) ease;
|
||||
}
|
||||
|
||||
@keyframes content-fadein {
|
||||
0% {
|
||||
transform: scale(1.1);
|
||||
opacity: 0%;
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
opacity: 0%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1.0);
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.playgroundSection {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 600px;
|
||||
width: 100%;
|
||||
background-color: var(--yg-color-playound-background);
|
||||
}
|
||||
.heroLogo {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
@media (max-width: 996px) {
|
||||
.playgroundSection {
|
||||
.heroLogo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.playgroundSection :global(.prism-code) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.bg {
|
||||
background-color: var(--yg-color-playground-background);
|
||||
}
|
||||
|
@@ -5,83 +5,77 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {Suspense} from 'react';
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import Layout from '@theme/Layout';
|
||||
import BrowserOnly from '@docusaurus/BrowserOnly';
|
||||
|
||||
import styles from './index.module.css';
|
||||
|
||||
import YogaLogo from '../../static/img/logo.svg';
|
||||
import Playground from '../components/Playground';
|
||||
|
||||
function HeroSection() {
|
||||
return (
|
||||
<header className={clsx('hero', styles.heroBanner)}>
|
||||
<div className={clsx('row', 'container', styles.heroRow)}>
|
||||
<div className="col col--6">
|
||||
<h1 className="hero__title">Yoga Layout</h1>
|
||||
<h1 className="hero__title">Yoga</h1>
|
||||
<p className="hero__subtitle">
|
||||
A portable and perfomant layout engine targeting web standards
|
||||
A portable layout engine targeting web standards
|
||||
</p>
|
||||
|
||||
<Link className="button button--primary button--lg" to="/docs/intro">
|
||||
Learn more
|
||||
</Link>
|
||||
</div>
|
||||
<div className={clsx(['col col--6', styles.blueprintColumn])}>
|
||||
<div className={clsx([styles.blueprint, styles.blueprintContainer])}>
|
||||
<div className={styles.blueprintHeader}>
|
||||
<div
|
||||
className={clsx([styles.blueprint, styles.blueprintAvatar])}
|
||||
/>
|
||||
<div
|
||||
className={clsx([styles.blueprint, styles.blueprintTitle])}
|
||||
/>
|
||||
<div
|
||||
className={clsx([styles.blueprint, styles.blueprintSubtitle])}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={clsx([styles.blueprint, styles.blueprintContent])}
|
||||
/>
|
||||
</div>
|
||||
<div className="col col--2">
|
||||
<YogaLogo className={styles.heroLogo} />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
const LazyPlayground = React.lazy(
|
||||
() => import('../components/Playground/Playground'),
|
||||
);
|
||||
|
||||
// Docusaurus SSR does not correctly support top-level await
|
||||
// 1. https://github.com/facebook/docusaurus/issues/7238
|
||||
// 2. https://github.com/facebook/docusaurus/issues/9468
|
||||
function BrowserOnlyPlayground() {
|
||||
return (
|
||||
<BrowserOnly fallback={null}>
|
||||
{() => (
|
||||
<Suspense fallback={null}>
|
||||
<LazyPlayground className={styles.playground} />
|
||||
</Suspense>
|
||||
)}
|
||||
</BrowserOnly>
|
||||
);
|
||||
}
|
||||
const playgroundCode = `
|
||||
<Layout config={{useWebDefaults: false}}>
|
||||
<Node style={{ width: 250, height: 475, padding: 10 }}>
|
||||
<Node style={{ flex: 1, rowGap: 10}}>
|
||||
<Node style={{ height: 60 }} />
|
||||
<Node style={{ flex: 1, marginInline: 10 }} />
|
||||
<Node style={{ flex: 2, marginInline: 10 }} />
|
||||
<Node
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
bottom: 0,
|
||||
height: 64,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-around",
|
||||
}}
|
||||
>
|
||||
<Node style={{ height: 40, width: 40 }} />
|
||||
<Node style={{ height: 40, width: 40 }} />
|
||||
<Node style={{ height: 40, width: 40 }} />
|
||||
<Node style={{ height: 40, width: 40 }} />
|
||||
</Node>
|
||||
</Node>
|
||||
</Node>
|
||||
</Layout>
|
||||
`.trim();
|
||||
|
||||
function PlaygroundSection() {
|
||||
return (
|
||||
<main className={styles.playgroundSection}>
|
||||
<div className="container">
|
||||
<BrowserOnlyPlayground />
|
||||
</div>
|
||||
<Playground height="600px" code={playgroundCode} autoFocus={true} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home(): JSX.Element {
|
||||
return (
|
||||
<Layout title="Yoga Layout | A cross-platform layout engine">
|
||||
<Layout>
|
||||
<HeroSection />
|
||||
<PlaygroundSection />
|
||||
</Layout>
|
||||
|
23
website-next/src/pages/playground.module.css
Normal file
23
website-next/src/pages/playground.module.css
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
html[data-theme='light'] {
|
||||
--yg-color-playound-background: var(--ifm-color-gray-200);
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
--yg-color-playound-background: var(--ifm-color-background);
|
||||
}
|
||||
|
||||
.playgroundContainer {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.bg {
|
||||
background-color: var(--yg-color-playound-background);
|
||||
}
|
27
website-next/src/pages/playground.tsx
Normal file
27
website-next/src/pages/playground.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import {useLocation} from '@docusaurus/router';
|
||||
|
||||
import Playground from '../components/Playground';
|
||||
|
||||
import styles from './playground.module.css';
|
||||
|
||||
export default function PlaygroundPage(): JSX.Element {
|
||||
const params = new URLSearchParams(useLocation().search);
|
||||
const codeParam = params.get('code');
|
||||
const code = codeParam ? atob(codeParam) : undefined;
|
||||
|
||||
return (
|
||||
// @ts-ignore missing prop for `wrapperClassName`
|
||||
<Layout wrapperClassName={styles.bg} title="Playground">
|
||||
<Playground height="max(80vh, 600px)" code={code} autoFocus={true} />
|
||||
</Layout>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user