Hide console option in view menu (#545)
* Update menuConfig.tsx
* Revert "Update menuConfig.tsx"
This reverts commit 7be28e2a76.
* second attempt
* Update mosaic tree to remove and add the console.
* Added Toggle UI component
* Remove console noise from Toggle component
Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
Co-authored-by: Frank Johnson <frankjohnson1993@gmail.com>
This commit was merged in pull request #545.
This commit is contained in:
@@ -98,6 +98,9 @@ module.exports = {
|
||||
minHeight: {
|
||||
md: '28rem',
|
||||
},
|
||||
outline: {
|
||||
gray: ['2px solid #3B3E4B', '8px'],
|
||||
},
|
||||
skew: {
|
||||
'-20': '-20deg',
|
||||
},
|
||||
|
||||
@@ -106,7 +106,7 @@ const IdeContainer = () => {
|
||||
}}
|
||||
value={state.layout}
|
||||
onChange={(newLayout) =>
|
||||
thunkDispatch({ type: 'setLayout', payload: { message: newLayout } })
|
||||
thunkDispatch({ type: 'setLayout', payload: newLayout })
|
||||
}
|
||||
onRelease={handleViewerSizeUpdate}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import React, { ReactNode } from 'react'
|
||||
import { ReactNode } from 'react'
|
||||
import { SvgNames } from 'src/components/Svg/Svg'
|
||||
import { useIdeContext } from 'src/helpers/hooks/useIdeContext'
|
||||
import { createRemoveUpdate, updateTree } from 'react-mosaic-component'
|
||||
import type { MosaicPath } from 'react-mosaic-component'
|
||||
import Toggle from 'src/components/Toggle'
|
||||
|
||||
interface SidebarConfigType {
|
||||
name: string
|
||||
@@ -9,6 +12,39 @@ interface SidebarConfigType {
|
||||
panel: ReactNode | null
|
||||
}
|
||||
|
||||
interface MosaicTree {
|
||||
first: string | MosaicTree
|
||||
second: string | MosaicTree
|
||||
}
|
||||
|
||||
const getPathById = (
|
||||
tree: MosaicTree,
|
||||
id: string,
|
||||
path: MosaicPath = []
|
||||
): MosaicPath => {
|
||||
if (tree.first === id || tree.second === id) {
|
||||
return [...path, tree.first === id ? 'first' : 'second']
|
||||
}
|
||||
if (typeof tree.first !== 'string' && typeof tree.second !== 'string') {
|
||||
throw new Error('id not found')
|
||||
}
|
||||
try {
|
||||
if (typeof tree.first !== 'string') {
|
||||
return getPathById(tree.first, id, [...path, 'first'])
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error('id not found')
|
||||
}
|
||||
try {
|
||||
if (typeof tree.second !== 'string') {
|
||||
return getPathById(tree.second, id, [...path, 'second'])
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error('id not found')
|
||||
}
|
||||
throw new Error('id not found')
|
||||
}
|
||||
|
||||
export const sidebarTopConfig: SidebarConfigType[] = [
|
||||
{
|
||||
name: 'Files',
|
||||
@@ -105,18 +141,60 @@ const settingsConfig: settingsConfig[] = [
|
||||
{
|
||||
title: 'Console',
|
||||
name: 'console',
|
||||
Content: () => (
|
||||
<div className="p-2">
|
||||
<p>
|
||||
<em>Coming Soon</em>
|
||||
</p>
|
||||
<hr className="my-2" />
|
||||
<p className="p-2">
|
||||
We're building configuration settings for the Viewer pane now. Join us
|
||||
on <DiscordLink /> if you want to lend a hand!
|
||||
</p>
|
||||
</div>
|
||||
),
|
||||
Content: () => {
|
||||
const { state, thunkDispatch } = useIdeContext()
|
||||
const consolePath = React.useMemo<MosaicPath | null>(() => {
|
||||
try {
|
||||
const path = getPathById(state.layout, 'Console')
|
||||
return path
|
||||
} catch (error) {
|
||||
return null
|
||||
}
|
||||
}, [state.layout])
|
||||
return (
|
||||
<div className="p-2">
|
||||
<li className="list-none select-none">
|
||||
<label
|
||||
className="grid items-center my-2 cursor-pointer"
|
||||
style={{ gridTemplateColumns: '1fr auto' }}
|
||||
>
|
||||
<span>Visible</span>
|
||||
<Toggle
|
||||
offLabel="Hide"
|
||||
onLabel="Show"
|
||||
onChange={(newValue) => {
|
||||
if (consolePath) {
|
||||
const newTree = updateTree(state.layout, [
|
||||
createRemoveUpdate(state.layout, consolePath),
|
||||
])
|
||||
thunkDispatch({ type: 'setLayout', payload: newTree })
|
||||
} else {
|
||||
// Split 'Viewer' panel to add console back in
|
||||
const viewerPath = getPathById(state.layout, 'Viewer')
|
||||
const newTree = { ...state.layout }
|
||||
let temp = newTree
|
||||
viewerPath.forEach((name) => {
|
||||
if (newTree[name] === 'Viewer') {
|
||||
newTree[name] = {
|
||||
direction: 'column',
|
||||
first: 'Viewer',
|
||||
second: 'Console',
|
||||
splitPercentage: 70,
|
||||
}
|
||||
return
|
||||
}
|
||||
temp = { ...newTree[name] }
|
||||
})
|
||||
thunkDispatch({ type: 'setLayout', payload: newTree })
|
||||
}
|
||||
}}
|
||||
checked={!!consolePath}
|
||||
/>
|
||||
</label>
|
||||
</li>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
33
app/web/src/components/Toggle/Toggle.tsx
Normal file
33
app/web/src/components/Toggle/Toggle.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
const Toggle = ({ offLabel = 'off', onLabel = 'on', checked, onChange }) => {
|
||||
return (
|
||||
<div className="flex items-center text-sm cursor-pointer font-light">
|
||||
<span className={`${!checked && 'text-ch-gray-500'}`}>{offLabel}</span>
|
||||
<div
|
||||
className={
|
||||
'mx-2 w-7 h-4 p-1 rounded-full border border-ch-gray-300 relative ' +
|
||||
(checked && 'border-ch-gray-500')
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="w-2.5 h-2.5 rounded-full bg-ch-pink-300 absolute transition-transform duration-75"
|
||||
style={{
|
||||
left: '50%',
|
||||
top: '50%',
|
||||
transform: checked
|
||||
? 'translate(-100%, -50%)'
|
||||
: 'translate(0%, -50%)',
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
<span className={`${checked && 'text-ch-gray-500'}`}>{onLabel}</span>
|
||||
<input
|
||||
className="sr-only"
|
||||
type="checkbox"
|
||||
onChange={onChange}
|
||||
checked={checked}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Toggle
|
||||
@@ -182,7 +182,7 @@ const reducer = (state: State, { type, payload }): State => {
|
||||
case 'setLayout':
|
||||
return {
|
||||
...state,
|
||||
layout: payload.message,
|
||||
layout: payload,
|
||||
}
|
||||
case 'updateCamera':
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user