Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions packages/sui-studio/src/components/theme-mode/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,31 @@ import PropTypes from 'prop-types'
import {forwardRef} from 'react'
import {DarkModeSwitch} from 'react-toggle-dark-mode'

const ThemeMode = forwardRef(({className, onChange, mode, ...props}, ref) => {
const COLORS = ['white', 'black']

const ThemeMode = forwardRef(({className, onChange, mode, size = 24, design, ...props}, ref) => {
const colors = design === 'inverted' ? {light: COLORS[0], dark: COLORS[1]} : {light: COLORS[1], dark: COLORS[0]}
return (
<button className="theme-mode" aria-label={`set ${mode === 'light' ? 'dark' : 'light'} mode`} ref={ref}>
<DarkModeSwitch onChange={onChange} checked={mode === 'dark'} size={24} />
<DarkModeSwitch
className={className}
onChange={onChange}
checked={mode === 'dark'}
size={size}
sunColor={colors.light}
moonColor={colors.dark}
{...props}
/>
</button>
)
})

ThemeMode.propTypes = {
className: PropTypes.string,
onChange: PropTypes.func,
mode: PropTypes.oneOf(['light', 'dark'])
mode: PropTypes.oneOf(['light', 'dark']),
size: PropTypes.number,
design: PropTypes.oneOf(['inverted'])
}

export default ThemeMode
51 changes: 23 additions & 28 deletions packages/sui-studio/workbench/src/app.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,13 @@
/* eslint-disable no-console, no-undef, import/no-webpack-loader-syntax */
import ReactDOM from 'react-dom'
import {render, browserHistory} from 'react-dom'
import {Router, Route, Redirect} from '@s-ui/react-router'

import {isFunction} from '../../src/components/demo/utilities.js'
import {importGlobals} from '../../src/components/globals.js'
import Raw from './components/Raw/index.js'
import Root from './components/Root/index.js'
import Workbench from './components/Workbench/index.js'

import './styles.scss'

const queryStringToJSON = queryString => {
if (queryString.indexOf('?') > -1) {
queryString = queryString.split('?')[1]
}
const pairs = queryString.split('&')
const result = {}
pairs.forEach(function (pair) {
pair = pair.split('=')
result[pair[0]] = decodeURIComponent(pair[1] || '')
})
return result
}

const params = queryStringToJSON(window.location.href)

const importAll = requireContext => requireContext.keys().map(requireContext)

;(async () => {
Expand Down Expand Up @@ -72,18 +57,28 @@ const importAll = requireContext => requireContext.keys().map(requireContext)
return acc
}, {})

const {raw} = params
const ComponentToRender = raw ? Raw : Root

await importGlobals()

ReactDOM.render(
<ComponentToRender
componentID={__COMPONENT_ID__}
contexts={contexts}
demo={DemoComponent}
themes={{...themes, default: demoStyles?.default || defaultStyle}}
{...params}
render(
<Router
history={browserHistory}
routes={
<Route>
<Route
path="/"
component={(...props) => (
<Workbench
componentID={__COMPONENT_ID__}
contexts={contexts}
demo={DemoComponent}
themes={{...themes, default: demoStyles?.default || defaultStyle}}
{...props}
/>
)}
/>
<Redirect from="**" to="/" />
</Route>
}
/>,
document.getElementById('app')
)
Expand Down
20 changes: 16 additions & 4 deletions packages/sui-studio/workbench/src/components/Header/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import {useState} from 'react'
import React, {useState} from 'react'

import PropTypes from 'prop-types'

export default function Header({children, componentID, iframeSrc}) {
import ThemeMode from '../../../../src/components/theme-mode/index.js'

export default function Header({children, componentID, iframeSrc, themeMode, setThemeMode}) {
const [show, setShow] = useState(true)

if (!show) return null

return (
<header className="Header">
<div className="Header-actions">
<span className="Header-link">
<ThemeMode
mode={themeMode}
onChange={checked => setThemeMode(checked ? 'dark' : 'light')}
size={16}
design="inverted"
/>
</span>
<a
className="Header-link"
href={iframeSrc}
Expand All @@ -18,7 +28,7 @@ export default function Header({children, componentID, iframeSrc}) {
title="Open Iframe in a new window"
>
<svg height="21" viewBox="0 0 21 21" width="21">
<g fill="none" stroke="#2a2e3b" transform="translate(3 4)">
<g fill="none" stroke="currentColor" transform="translate(3 4)">
<path
d="m4.17157288 4.87867966v-1.41421357c0-1.56209716 1.26632995-2.82842712 2.82842712-2.82842712s2.82842712 1.26632996 2.82842712 2.82842712v1.41421357m0 2.82842712v2.82842712c0 1.5620972-1.26632995 2.8284271-2.82842712 2.8284271s-2.82842712-1.2663299-2.82842712-2.8284271v-2.82842712"
transform="matrix(.70710678 .70710678 -.70710678 .70710678 7 -2.899495)"
Expand All @@ -37,7 +47,7 @@ export default function Header({children, componentID, iframeSrc}) {
title="Close box"
>
<svg height="16" viewBox="0 0 21 21" width="16">
<g fill="none" stroke="#2a2e3b" transform="translate(2 2)">
<g fill="none" stroke="currentColor" transform="translate(2 2)">
<circle cx="8.5" cy="8.5" r="8" />
<g transform="matrix(0 1 -1 0 17 0)">
<path d="m5.5 11.5 6-6" />
Expand All @@ -56,6 +66,8 @@ export default function Header({children, componentID, iframeSrc}) {

Header.propTypes = {
children: PropTypes.array,
themeMode: PropTypes.string,
setThemeMode: PropTypes.func,
componentID: PropTypes.string,
iframeSrc: PropTypes.string
}
13 changes: 10 additions & 3 deletions packages/sui-studio/workbench/src/components/Header/index.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
@import '../../../../src/components/preview/style';

.Header {
align-items: center;
background: rgba(0, 132, 255, 0.8);
background: color-mix(
in srgb,
color-mix(in srgb, var(--studio-c-on-surface) 60%, var(--studio-c-primary)),
transparent 10%
);
border-radius: 8px;
bottom: 16px;
color: #fff;
color: var(--studio-c-surface, #000);
display: flex;
flex-direction: column;
justify-content: center;
Expand All @@ -20,10 +26,11 @@
display: flex;
justify-content: center;
padding: 8px 0 0 0;
color: var(--studio-c-surface, #000);
}

&-link {
color: #fff;
color: inherit;
font-size: 12px;
padding-left: 8px;
text-decoration: none;
Expand Down
13 changes: 10 additions & 3 deletions packages/sui-studio/workbench/src/components/Raw/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/* eslint import/no-webpack-loader-syntax:0 */
import React, {useEffect, useState} from 'react'
import React, {useEffect, useRef, useState} from 'react'

import Component, * as named from 'component'
import PropTypes from 'prop-types'

import SUIContext from '@s-ui/react-context'
import {useRouter} from '@s-ui/react-router'

import {cleanDisplayName, createContextByType, removeDefaultContext} from '../../../../src/components/demo/utilities.js'
import Preview from '../../../../src/components/preview/index.js'
Expand All @@ -23,11 +24,17 @@ export default function Raw({
demo: DemoComponent,
themes
}) {
const {
location: {
query: {mode: themeMode = 'light'}
}
} = useRouter()
const rawRef = useRef()
const [playground, setPlayground] = useState(null)

const context = Object.keys(contexts).length && createContextByType(contexts, actualContext)

// check if is a normal component or it's wrapped with a React.memo method
// check if is a normal component, or it's wrapped with a React.memo method
const ComponentToRender = Component.type ? Component.type : Component

useEffect(() => {
Expand All @@ -36,7 +43,7 @@ export default function Raw({
}, [componentID])

return (
<div className="Raw">
<div className="Raw" ref={rawRef} data-theme-mode={themeMode}>
<Style id="sui-studio-raw-theme">{themes[actualStyle]}</Style>

<div className="Raw-center">
Expand Down
8 changes: 3 additions & 5 deletions packages/sui-studio/workbench/src/components/Raw/index.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
@import '../../../../src/styles/settings';

body {
background-color: $bgc-main;
}

.Raw {
padding: 16px;
background-color: var(--studio-c-surface);
color: var(--studio-c-on-surface);
padding: 0;
}
12 changes: 7 additions & 5 deletions packages/sui-studio/workbench/src/components/Root/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ const updateOnChange = (setState, sessionKey) => nextValue => {
setState(nextValue)
}

export default function Root({componentID, contexts = {}, themes}) {
export default function Root({componentID, contexts = {}, themes, themeMode, setThemeMode}) {
const [actualContext, setActualContext] = useState(() => getFromStorage('actualContext', 'default'))
const [actualStyle, setActualStyle] = useState(() => getFromStorage('actualStyle', 'default'))
const [showTests, setShowTests] = useState(() => getFromStorage('showTests', 'show'))

const iframeSrc = `/?raw=true&actualStyle=${actualStyle}&actualContext=${actualContext}`
const iframeSrc = `/?raw=true&actualStyle=${actualStyle}&actualContext=${actualContext}&mode=${themeMode}`

return (
<div className="Root">
<Header componentID={componentID} iframeSrc={iframeSrc}>
<div className="Root" data-theme-mode={themeMode}>
<Header componentID={componentID} iframeSrc={iframeSrc} themeMode={themeMode} setThemeMode={setThemeMode}>
<Select
label="contexts"
options={contexts}
Expand Down Expand Up @@ -67,5 +67,7 @@ export default function Root({componentID, contexts = {}, themes}) {
Root.propTypes = {
componentID: PropTypes.string,
contexts: PropTypes.object,
themes: PropTypes.object
themes: PropTypes.object,
themeMode: PropTypes.string,
setThemeMode: PropTypes.func
}
13 changes: 12 additions & 1 deletion packages/sui-studio/workbench/src/components/Root/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,23 @@
}

&-test {
background: #fafafa;
background: var(--studio-c-on-surface);
color: var(--studio-c-surface);
height: 100vh;
position: fixed;
right: 0;
top: 0;
z-index: 1;
#mocha,
#mocha-stats {
color: inherit;
a {
color: color-mix(in srgb, var(--studio-c-surface) 70%, var(--studio-c-primary));
}
em {
color: inherit;
}
}
}

&-testSwitch {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {useState} from 'react'

import usePrefersColorScheme from 'use-prefers-color-scheme'

import Raw from '../Raw/index.js'
import Root from '../Root/index.js'
import queryStringToJSON from './queryStringToJSON.js'

const Workbench = ({...rest}) => {
const colorScheme = usePrefersColorScheme()
const [theme, setTheme] = useState(colorScheme)

const params = queryStringToJSON(window.location.href)

const {raw} = params

const [Component, props] = raw
? [Raw, {themeMode: theme, ...rest}]
: [Root, {themeMode: theme, setThemeMode: setTheme, ...rest}]

return <Component {...props} />
}

Workbench.displayName = 'Workbench'

Workbench.propTypes = {}

export default Workbench
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Workbench from './Workbench.js'

export default Workbench
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default queryString => {
if (queryString.indexOf('?') > -1) {
queryString = queryString.split('?')[1]
}
const pairs = queryString.split('&')
const result = {}
pairs.forEach(function (pair) {
pair = pair.split('=')
result[pair[0]] = decodeURIComponent(pair[1] || '')
})
return result
}
4 changes: 2 additions & 2 deletions packages/sui-studio/workbench/src/styles.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
@import '../../src/styles/custom-properties';
@import '../../src/styles/settings';
@import '../../src/styles/default';
@import '../../src/components/theme-mode/style';

@import './components/Header/index';
@import './components/Root/index';
@import './components/Select/index';
@import './components/Suite/index';

@import '../../src/components/preview/style';