From 206ec7fdabb58aa937108f375386b1ce948906e9 Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Fri, 10 Sep 2021 02:29:13 -0400 Subject: [PATCH 1/9] aupdated headless-ui, got started on naive implementation --- app/web/package.json | 2 +- .../src/components/IdeSideBar/IdeSideBar.tsx | 75 +++++++++++++++++-- app/web/src/components/Svg/Svg.tsx | 22 +++++- app/yarn.lock | 8 +- 4 files changed, 93 insertions(+), 14 deletions(-) diff --git a/app/web/package.json b/app/web/package.json index 77285a4..dc59ed2 100644 --- a/app/web/package.json +++ b/app/web/package.json @@ -13,7 +13,7 @@ ] }, "dependencies": { - "@headlessui/react": "^1.0.0", + "@headlessui/react": "^1.4.1", "@heroicons/react": "^1.0.4", "@material-ui/core": "^4.11.0", "@monaco-editor/react": "^4.0.11", diff --git a/app/web/src/components/IdeSideBar/IdeSideBar.tsx b/app/web/src/components/IdeSideBar/IdeSideBar.tsx index d76b2a9..b5941bf 100644 --- a/app/web/src/components/IdeSideBar/IdeSideBar.tsx +++ b/app/web/src/components/IdeSideBar/IdeSideBar.tsx @@ -1,5 +1,44 @@ import { Link, routes } from '@redwoodjs/router' -import Svg from 'src/components/Svg/Svg' +import { Tab } from '@headlessui/react' +import Svg, { SvgNames } from 'src/components/Svg/Svg' +import { ReactNode } from 'react' + +interface SidebarConfigType { + name: string, + icon: SvgNames, + disabled: boolean, + panel: ReactNode | null, +} + +const sidebarTopConfig : SidebarConfigType[] = [ + { + name: 'Files', + icon: 'files', + disabled: false, + panel: () => {

Some Files!

}, + }, + { + name: 'GitHub', + icon: 'github', + disabled: false, + panel: () => {

Le GitHub Integration™️

}, + }, + { + name: 'Visibility', + icon: 'eye', + disabled: true, + panel: null, + }, +] + +const sidebarBottomConfig : SidebarConfigType[] = [ + { + name: 'Settings', + icon: 'gear', + disabled: true, + panel: null, + }, +] const IdeSideBar = () => { return ( @@ -9,13 +48,33 @@ const IdeSideBar = () => { - + + +
+ { sidebarTopConfig.map(topItem => ( + + + + ))} +
+
+ { sidebarBottomConfig.map(bottomItem => ( + + + + ))} +
+
+ + { ([...sidebarTopConfig, ...sidebarBottomConfig]).map(item => item.panel && ( + { item.panel } + )) } + +
) } diff --git a/app/web/src/components/Svg/Svg.tsx b/app/web/src/components/Svg/Svg.tsx index e9974d9..84cdcc7 100644 --- a/app/web/src/components/Svg/Svg.tsx +++ b/app/web/src/components/Svg/Svg.tsx @@ -1,4 +1,4 @@ -type SvgNames = +export type SvgNames = | 'arrow-down' // | 'arrow' | 'arrow-left' @@ -8,12 +8,15 @@ type SvgNames = | 'dots-vertical' | 'drag-grid' | 'exclamation-circle' + | 'eye' | 'favicon' + | 'files' | 'flag' | 'floppy-disk' | 'fork' | 'fork-new' | 'gear' + | 'github' | 'lightbulb' | 'logout' | 'mac-cmd-key' @@ -159,6 +162,12 @@ const Svg = ({ /> ), + eye: ( + + + + + ), favicon: ( @@ -258,6 +267,12 @@ const Svg = ({ ), + files: ( + + + + + ), flag: ( ), + github: ( + + + + ), lightbulb: ( Date: Sat, 11 Sep 2021 04:34:13 -0400 Subject: [PATCH 2/9] got working toggle tabs! I don't like HeadlessUI's Tabs, they don't appear to support programmatic opening --- .../src/components/IdeHeader/IdeHeader.tsx | 15 ++- .../src/components/IdeSideBar/IdeSideBar.tsx | 104 ++++++++++++------ .../src/components/IdeWrapper/IdeWrapper.tsx | 18 +-- app/web/src/index.css | 23 ++++ 4 files changed, 110 insertions(+), 50 deletions(-) diff --git a/app/web/src/components/IdeHeader/IdeHeader.tsx b/app/web/src/components/IdeHeader/IdeHeader.tsx index 62822db..cee2c50 100644 --- a/app/web/src/components/IdeHeader/IdeHeader.tsx +++ b/app/web/src/components/IdeHeader/IdeHeader.tsx @@ -65,8 +65,13 @@ const IdeHeader = ({ return (
- {_projectId ? ( -
+
+
+ + + +
+ {_projectId && <> -
- ) : ( -
- )} + } +
{canEdit && !projectTitle && ( {

Some Files!

}, + panel:

Some Files!

, }, { name: 'GitHub', icon: 'github', disabled: false, - panel: () => {

Le GitHub Integration™️

}, + panel:

Le GitHub Integration™️

, }, { name: 'Visibility', @@ -40,42 +40,74 @@ const sidebarBottomConfig : SidebarConfigType[] = [ }, ] -const IdeSideBar = () => { +const combinedConfig = [ + ...sidebarTopConfig, + ...sidebarBottomConfig, +] + +function TabToggle({ item, className = "", active, onChange, onClick }) { return ( -
-
- - - -
- - -
- { sidebarTopConfig.map(topItem => ( - - - + + ) +} + +const IdeSideBar = () => { + const [selectedTab, setSelectedTab] = useState("") + const [lastOpen, setLastOpen] = useState("") + + function onTabClick(name) { + return function() { + if (selectedTab === name) { + setLastOpen(selectedTab) + setSelectedTab("") + } else if (selectedTab === "" && lastOpen === name) { + setSelectedTab(name) + } + } + } + + return ( +
+
+
+ { sidebarTopConfig.map((topItem, i) => ( + setSelectedTab(topItem.name) } + onClick={ onTabClick(topItem.name) } + /> ))} -
-
- { sidebarBottomConfig.map(bottomItem => ( - - - +
+
+ { sidebarBottomConfig.map((bottomItem, i) => ( + setSelectedTab(bottomItem.name) } + onClick={ onTabClick(bottomItem.name) } + /> ))} -
- - - { ([...sidebarTopConfig, ...sidebarBottomConfig]).map(item => item.panel && ( - { item.panel } - )) } - - -
+
+ + { combinedConfig.find(item => item.name === selectedTab)?.panel && ( +
+ { combinedConfig.find(item => item.name === selectedTab).panel } +
+ ) } + ) } diff --git a/app/web/src/components/IdeWrapper/IdeWrapper.tsx b/app/web/src/components/IdeWrapper/IdeWrapper.tsx index aceab38..e7f2af7 100644 --- a/app/web/src/components/IdeWrapper/IdeWrapper.tsx +++ b/app/web/src/components/IdeWrapper/IdeWrapper.tsx @@ -24,15 +24,17 @@ const IdeWrapper = ({ cadPackage }: Props) => { useIdeInit(cadPackage, project?.code || state?.code) return ( -
-
- -
-
- +
+
+ +
+
+ +
) diff --git a/app/web/src/index.css b/app/web/src/index.css index 0b8ef1d..0e17ea0 100644 --- a/app/web/src/index.css +++ b/app/web/src/index.css @@ -17,6 +17,29 @@ body { font-family: 'Fira Sans', ui-sans-serif, system-ui, -apple-system, system-ui, "Segoe UI", "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } + + /* https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/ */ + .visually-hidden { + clip: rect(0 0 0 0); + clip-path: inset(50%); + height: 1px; + overflow: hidden; + position: absolute; + white-space: nowrap; + width: 1px; + } +} + +@layer components { + .tabToggle { + @apply text-ch-gray-300 p-3 mb-3 flex justify-center; + } + .tabToggle.active { + @apply bg-ch-pink-800 text-ch-pink-300 bg-opacity-30; + } + .tabToggle.disabled { + @apply text-ch-gray-550 cursor-not-allowed; + } } From 0d7e9585058ed573c6a17e9511cd7df28cf887cd Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Sat, 11 Sep 2021 05:02:15 -0400 Subject: [PATCH 3/9] got tsome dummy text in the Files and GitHub menus, improved styling --- .../src/components/IdeSideBar/IdeSideBar.tsx | 60 +++---------------- app/web/src/index.css | 4 ++ 2 files changed, 13 insertions(+), 51 deletions(-) diff --git a/app/web/src/components/IdeSideBar/IdeSideBar.tsx b/app/web/src/components/IdeSideBar/IdeSideBar.tsx index 394d980..15e61d8 100644 --- a/app/web/src/components/IdeSideBar/IdeSideBar.tsx +++ b/app/web/src/components/IdeSideBar/IdeSideBar.tsx @@ -1,49 +1,6 @@ -import { ReactNode, useState } from 'react' -import { Link, routes } from '@redwoodjs/router' -import { Tab } from '@headlessui/react' -import Svg, { SvgNames } from 'src/components/Svg/Svg' - -interface SidebarConfigType { - name: string, - icon: SvgNames, - disabled: boolean, - panel: ReactNode | null, -} - -const sidebarTopConfig : SidebarConfigType[] = [ - { - name: 'Files', - icon: 'files', - disabled: false, - panel:

Some Files!

, - }, - { - name: 'GitHub', - icon: 'github', - disabled: false, - panel:

Le GitHub Integration™️

, - }, - { - name: 'Visibility', - icon: 'eye', - disabled: true, - panel: null, - }, -] - -const sidebarBottomConfig : SidebarConfigType[] = [ - { - name: 'Settings', - icon: 'gear', - disabled: true, - panel: null, - }, -] - -const combinedConfig = [ - ...sidebarTopConfig, - ...sidebarBottomConfig, -] +import { useState } from 'react' +import Svg from 'src/components/Svg/Svg' +import { sidebarTopConfig, sidebarBottomConfig, sidebarCombinedConfig } from './sidebarConfig' function TabToggle({ item, className = "", active, onChange, onClick }) { return ( @@ -79,8 +36,8 @@ const IdeSideBar = () => { } return ( -
-
+
+
{ sidebarTopConfig.map((topItem, i) => ( { ))}
- { combinedConfig.find(item => item.name === selectedTab)?.panel && ( -
- { combinedConfig.find(item => item.name === selectedTab).panel } + { sidebarCombinedConfig.find(item => item.name === selectedTab)?.panel && ( +
+

{ selectedTab }

+ { sidebarCombinedConfig.find(item => item.name === selectedTab).panel }
) }
diff --git a/app/web/src/index.css b/app/web/src/index.css index 0e17ea0..8a5dee5 100644 --- a/app/web/src/index.css +++ b/app/web/src/index.css @@ -40,6 +40,10 @@ .tabToggle.disabled { @apply text-ch-gray-550 cursor-not-allowed; } + + .sidebarContainer { + @apply p-2; + } } From e47ad59003d5ac240a3665e9d70d80a768b097b4 Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Sat, 11 Sep 2021 05:43:29 -0400 Subject: [PATCH 4/9] Added Settings tray with initial sections as details elements --- app/web/src/components/IdeSideBar/IdeSideBar.tsx | 5 +++-- app/web/src/index.css | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/web/src/components/IdeSideBar/IdeSideBar.tsx b/app/web/src/components/IdeSideBar/IdeSideBar.tsx index 15e61d8..64a0d90 100644 --- a/app/web/src/components/IdeSideBar/IdeSideBar.tsx +++ b/app/web/src/components/IdeSideBar/IdeSideBar.tsx @@ -5,7 +5,6 @@ import { sidebarTopConfig, sidebarBottomConfig, sidebarCombinedConfig } from './ function TabToggle({ item, className = "", active, onChange, onClick }) { return (
@@ -55,13 +55,14 @@ const IdeSideBar = () => { active={ selectedTab === bottomItem.name } onChange={ () => setSelectedTab(bottomItem.name) } onClick={ onTabClick(bottomItem.name) } + key={ 'tab-' + (sidebarTopConfig.length+i) } /> ))}
{ sidebarCombinedConfig.find(item => item.name === selectedTab)?.panel && (
-

{ selectedTab }

+

{ selectedTab }

{ sidebarCombinedConfig.find(item => item.name === selectedTab).panel }
) } diff --git a/app/web/src/index.css b/app/web/src/index.css index 8a5dee5..0e17ea0 100644 --- a/app/web/src/index.css +++ b/app/web/src/index.css @@ -40,10 +40,6 @@ .tabToggle.disabled { @apply text-ch-gray-550 cursor-not-allowed; } - - .sidebarContainer { - @apply p-2; - } } From 39f9a02c0a1b2c3615e945870c9669959c1ae70a Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Sat, 11 Sep 2021 05:57:00 -0400 Subject: [PATCH 5/9] Broke out into a config file --- app/web/src/components/IdeSideBar/IdeSideBar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/web/src/components/IdeSideBar/IdeSideBar.tsx b/app/web/src/components/IdeSideBar/IdeSideBar.tsx index 64a0d90..b92ab3c 100644 --- a/app/web/src/components/IdeSideBar/IdeSideBar.tsx +++ b/app/web/src/components/IdeSideBar/IdeSideBar.tsx @@ -61,8 +61,8 @@ const IdeSideBar = () => {
{ sidebarCombinedConfig.find(item => item.name === selectedTab)?.panel && ( -
-

{ selectedTab }

+
+

{ selectedTab }

{ sidebarCombinedConfig.find(item => item.name === selectedTab).panel }
) } From 011baad9d0cf2777556ed24af289e0129be497ac Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Sat, 11 Sep 2021 13:49:26 -0400 Subject: [PATCH 6/9] Broke out SettingsMenu as a standalone component --- .../components/IdeSideBar/sidebarConfig.tsx | 18 +++++------------- app/web/src/index.css | 2 +- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/app/web/src/components/IdeSideBar/sidebarConfig.tsx b/app/web/src/components/IdeSideBar/sidebarConfig.tsx index 2faed46..a4bfed4 100644 --- a/app/web/src/components/IdeSideBar/sidebarConfig.tsx +++ b/app/web/src/components/IdeSideBar/sidebarConfig.tsx @@ -1,11 +1,11 @@ -import { ReactFragment, ReactNode, useEffect, useReducer, useState } from 'react' +import React, { ReactNode } from 'react' import { SvgNames } from 'src/components/Svg/Svg' interface SidebarConfigType { name: string, icon: SvgNames, disabled: boolean, - panel: ReactFragment | null, + panel: ReactNode | null, } export const sidebarTopConfig : SidebarConfigType[] = [ @@ -67,14 +67,7 @@ export const sidebarBottomConfig : SidebarConfigType[] = [ name: 'Settings', icon: 'gear', disabled: false, - panel:
- { settingsConfig.map(item => ( -
- { item.title } - { item.content } -
- ))} -
, + panel: , }, ] @@ -84,12 +77,11 @@ export const sidebarCombinedConfig = [ ] function SettingsMenu() { - console.log('hello?', settingsConfig) return ( -
+
{ settingsConfig.map(item => (
- { item.title } + { item.title } { item.content }
))} diff --git a/app/web/src/index.css b/app/web/src/index.css index 0e17ea0..a536eac 100644 --- a/app/web/src/index.css +++ b/app/web/src/index.css @@ -32,7 +32,7 @@ @layer components { .tabToggle { - @apply text-ch-gray-300 p-3 mb-3 flex justify-center; + @apply text-ch-gray-300 p-3 mb-1 flex justify-center; } .tabToggle.active { @apply bg-ch-pink-800 text-ch-pink-300 bg-opacity-30; From 69c83d33b1bb6c2349787983edf37aa55db1f0ae Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Sun, 12 Sep 2021 19:54:31 +1000 Subject: [PATCH 7/9] State controlled tray mvp --- .../src/components/IdeSideBar/IdeSideBar.tsx | 28 ++- .../components/IdeSideBar/sidebarConfig.tsx | 26 ++- app/web/src/helpers/hooks/useIdeState.ts | 198 ++++++++++-------- 3 files changed, 138 insertions(+), 114 deletions(-) diff --git a/app/web/src/components/IdeSideBar/IdeSideBar.tsx b/app/web/src/components/IdeSideBar/IdeSideBar.tsx index b92ab3c..666b37c 100644 --- a/app/web/src/components/IdeSideBar/IdeSideBar.tsx +++ b/app/web/src/components/IdeSideBar/IdeSideBar.tsx @@ -1,6 +1,7 @@ import { useState } from 'react' import Svg from 'src/components/Svg/Svg' import { sidebarTopConfig, sidebarBottomConfig, sidebarCombinedConfig } from './sidebarConfig' +import { useIdeContext } from 'src/helpers/hooks/useIdeContext' function TabToggle({ item, className = "", active, onChange, onClick }) { return ( @@ -20,29 +21,24 @@ function TabToggle({ item, className = "", active, onChange, onClick }) { } const IdeSideBar = () => { - const [selectedTab, setSelectedTab] = useState("") - const [lastOpen, setLastOpen] = useState("") + const { state, thunkDispatch } = useIdeContext() function onTabClick(name) { return function() { - if (selectedTab === name) { - setLastOpen(selectedTab) - setSelectedTab("") - } else if (selectedTab === "" && lastOpen === name) { - setSelectedTab(name) - } + thunkDispatch({type: 'settingsButtonClicked', payload: [name]}) } } + const selectedTab = React.useMemo(() => sidebarCombinedConfig.find(item => item.name === state.sideTray[0]), [state.sideTray]) return ( -
+
{ sidebarTopConfig.map((topItem, i) => ( setSelectedTab(topItem.name) } + active={ state.sideTray[0] === topItem.name } + onChange={ () => onTabClick(topItem.name) } onClick={ onTabClick(topItem.name) } key={ 'tab-' + i } /> @@ -52,18 +48,18 @@ const IdeSideBar = () => { { sidebarBottomConfig.map((bottomItem, i) => ( setSelectedTab(bottomItem.name) } + active={ state.sideTray[0] === bottomItem.name } + onChange={ () => onTabClick(bottomItem.name) } onClick={ onTabClick(bottomItem.name) } key={ 'tab-' + (sidebarTopConfig.length+i) } /> ))}
- { sidebarCombinedConfig.find(item => item.name === selectedTab)?.panel && ( + { selectedTab?.panel && (
-

{ selectedTab }

- { sidebarCombinedConfig.find(item => item.name === selectedTab).panel } +

{ selectedTab.name }

+ { selectedTab.panel }
) }
diff --git a/app/web/src/components/IdeSideBar/sidebarConfig.tsx b/app/web/src/components/IdeSideBar/sidebarConfig.tsx index a4bfed4..9015091 100644 --- a/app/web/src/components/IdeSideBar/sidebarConfig.tsx +++ b/app/web/src/components/IdeSideBar/sidebarConfig.tsx @@ -1,5 +1,6 @@ import React, { ReactNode } from 'react' import { SvgNames } from 'src/components/Svg/Svg' +import { useIdeContext } from 'src/helpers/hooks/useIdeContext' interface SidebarConfigType { name: string, @@ -67,7 +68,7 @@ export const sidebarBottomConfig : SidebarConfigType[] = [ name: 'Settings', icon: 'gear', disabled: false, - panel: , + panel: , }, ] @@ -76,15 +77,26 @@ export const sidebarCombinedConfig = [ ...sidebarBottomConfig, ] -function SettingsMenu() { +function SettingsMenu({parentName}: {parentName: string}) { + const { state, thunkDispatch } = useIdeContext() return (
{ settingsConfig.map(item => ( -
- { item.title } - { item.content } -
+
  • + + { state.sideTray.slice(-1)[0] === item.name && item.content } +
  • + //
    + // thunkDispatch((dispatch) => dispatch({type: 'settingsButtonClicked', payload:[parentName, item.name]}))} + // >{ item.title }hi there + // { state.sideTray.slice(-1)[0] === item.name && item.content } + // {state.sideTray.slice(-1)[0]} + //
    ))}
    ) -} \ No newline at end of file +} diff --git a/app/web/src/helpers/hooks/useIdeState.ts b/app/web/src/helpers/hooks/useIdeState.ts index 8945841..3e23c3c 100644 --- a/app/web/src/helpers/hooks/useIdeState.ts +++ b/app/web/src/helpers/hooks/useIdeState.ts @@ -115,6 +115,7 @@ export interface State { viewerSize: { width: number; height: number } isLoading: boolean threeInstance: RootState + sideTray: string[] // could probably be an array of a union type } const code = '' @@ -146,103 +147,118 @@ export const initialState: State = { viewerSize: { width: 0, height: 0 }, isLoading: false, threeInstance: null, + sideTray: [], } -export const useIdeState = (): [State, (actionOrThunk: any) => any] => { - const reducer = (state: State, { type, payload }): State => { - switch (type) { - case 'initIde': +const reducer = (state: State, { type, payload }): State => { + console.log('reducing') + switch (type) { + case 'initIde': + return { + ...state, + code: + payload.code || + // localStorage.getItem(makeCodeStoreKey(payload.cadPackage)) || + initCodeMap[payload.cadPackage] || + '', + ideType: payload.cadPackage, + } + case 'updateCode': + return { ...state, code: payload } + case 'healthyRender': + const customizerParams: CadhubParams[] = payload?.customizerParams?.length + ? payload.customizerParams + : state.customizerParams + const currentParameters = {} + customizerParams.forEach((param) => { + currentParameters[param.name] = + typeof state?.currentParameters?.[param.name] !== 'undefined' + ? state?.currentParameters?.[param.name] + : param.initial + }) + return { + ...state, + objectData: { + ...state.objectData, + type: payload.objectData?.type, + data: payload.objectData?.data, + }, + customizerParams, + currentParameters, + consoleMessages: payload.message + ? [...state.consoleMessages, payload.message] + : payload.message, + isLoading: false, + } + case 'errorRender': + return { + ...state, + consoleMessages: payload.message + ? [...state.consoleMessages, payload.message] + : payload.message, + isLoading: false, + } + case 'setCurrentCustomizerParams': + if (!Object.keys(payload || {}).length) return state + return { + ...state, + currentParameters: payload, + } + case 'setLayout': + return { + ...state, + layout: payload.message, + } + case 'updateCamera': + return { + ...state, + camera: payload.camera, + } + case 'updateViewerSize': + return { + ...state, + viewerSize: payload.viewerSize, + } + case 'setLoading': + return { + ...state, + isLoading: true, + } + case 'resetLoading': + return { + ...state, + isLoading: false, + } + case 'resetLayout': + return { + ...state, + layout: initialLayout, + } + case 'setThreeInstance': + return { + ...state, + threeInstance: payload, + } + case 'settingsButtonClicked': + const isReClick = + state.sideTray.length && + state.sideTray.length === payload.length && + state.sideTray.every((original, index) => original === payload[index]) + if (isReClick) { return { ...state, - code: - payload.code || - // localStorage.getItem(makeCodeStoreKey(payload.cadPackage)) || - initCodeMap[payload.cadPackage] || - '', - ideType: payload.cadPackage, + sideTray: state.sideTray.slice(0, -1), } - case 'updateCode': - return { ...state, code: payload } - case 'healthyRender': - const customizerParams: CadhubParams[] = payload?.customizerParams - ?.length - ? payload.customizerParams - : state.customizerParams - const currentParameters = {} - customizerParams.forEach((param) => { - currentParameters[param.name] = - typeof state?.currentParameters?.[param.name] !== 'undefined' - ? state?.currentParameters?.[param.name] - : param.initial - }) - return { - ...state, - objectData: { - ...state.objectData, - type: payload.objectData?.type, - data: payload.objectData?.data, - }, - customizerParams, - currentParameters, - consoleMessages: payload.message - ? [...state.consoleMessages, payload.message] - : payload.message, - isLoading: false, - } - case 'errorRender': - return { - ...state, - consoleMessages: payload.message - ? [...state.consoleMessages, payload.message] - : payload.message, - isLoading: false, - } - case 'setCurrentCustomizerParams': - if (!Object.keys(payload || {}).length) return state - return { - ...state, - currentParameters: payload, - } - case 'setLayout': - return { - ...state, - layout: payload.message, - } - case 'updateCamera': - return { - ...state, - camera: payload.camera, - } - case 'updateViewerSize': - return { - ...state, - viewerSize: payload.viewerSize, - } - case 'setLoading': - return { - ...state, - isLoading: true, - } - case 'resetLoading': - return { - ...state, - isLoading: false, - } - case 'resetLayout': - return { - ...state, - layout: initialLayout, - } - case 'setThreeInstance': - return { - ...state, - threeInstance: payload, - } - default: - return state - } + } + return { + ...state, + sideTray: payload, + } + default: + return state } - +} +export const useIdeState = (): [State, (actionOrThunk: any) => any] => { const [state, dispatch] = useReducer(reducer, initialState) mutableState = state const getState = (): State => mutableState From 2ec3a0b20267e744e5bf71ed645d424e135d1b0b Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Sun, 12 Sep 2021 17:13:30 -0400 Subject: [PATCH 8/9] Sorted out using
    element, got ancestor clicks closing out to their level --- .../src/components/EditorMenu/EditorMenu.tsx | 11 +- .../components/IdeContainer/IdeContainer.tsx | 33 ++- .../src/components/IdeHeader/IdeHeader.tsx | 44 ++-- .../src/components/IdeSideBar/IdeSideBar.tsx | 86 ++++--- .../components/IdeSideBar/sidebarConfig.tsx | 222 +++++++++++------- .../src/components/IdeWrapper/IdeWrapper.tsx | 18 +- .../components/PanelToolbar/PanelToolbar.tsx | 12 +- app/web/src/components/Svg/Svg.tsx | 36 ++- app/web/src/helpers/hooks/useIdeState.ts | 16 ++ 9 files changed, 313 insertions(+), 165 deletions(-) diff --git a/app/web/src/components/EditorMenu/EditorMenu.tsx b/app/web/src/components/EditorMenu/EditorMenu.tsx index ffe2ef0..9ef9456 100644 --- a/app/web/src/components/EditorMenu/EditorMenu.tsx +++ b/app/web/src/components/EditorMenu/EditorMenu.tsx @@ -34,9 +34,16 @@ const EditorMenu = () => { ))}
    diff --git a/app/web/src/components/IdeContainer/IdeContainer.tsx b/app/web/src/components/IdeContainer/IdeContainer.tsx index 817528e..0286838 100644 --- a/app/web/src/components/IdeContainer/IdeContainer.tsx +++ b/app/web/src/components/IdeContainer/IdeContainer.tsx @@ -42,19 +42,40 @@ const ELEMENT_MAP = { } const TOOLBAR_MAP = { - Editor: ( + Editor: () => (
    ), - Viewer: ( + Viewer: (thunkDispatch) => (
    - + + thunkDispatch((dispatch) => + dispatch({ + type: 'settingsButtonClicked', + payload: ['Settings', 'viewer'], + }) + ) + } + />
    ), - Console: ( + Console: (thunkDispatch) => (
    - + + thunkDispatch((dispatch) => + dispatch({ + type: 'settingsButtonClicked', + payload: ['Settings', 'console'], + }) + ) + } + />
    ), } @@ -74,7 +95,7 @@ const IdeContainer = () => { return ( TOOLBAR_MAP[id]} + renderToolbar={() => TOOLBAR_MAP[id](thunkDispatch)} className={`${id.toLowerCase()} ${id.toLowerCase()}-tile`} > {id === 'Viewer' ? ( diff --git a/app/web/src/components/IdeHeader/IdeHeader.tsx b/app/web/src/components/IdeHeader/IdeHeader.tsx index cee2c50..f2199c5 100644 --- a/app/web/src/components/IdeHeader/IdeHeader.tsx +++ b/app/web/src/components/IdeHeader/IdeHeader.tsx @@ -71,28 +71,30 @@ const IdeHeader = ({
    - {_projectId && <> - - + + + + {_projectOwner} + + + - - {_projectOwner} - - - - } + + )}
    {canEdit && !projectTitle && ( diff --git a/app/web/src/components/IdeSideBar/IdeSideBar.tsx b/app/web/src/components/IdeSideBar/IdeSideBar.tsx index 666b37c..0a071f7 100644 --- a/app/web/src/components/IdeSideBar/IdeSideBar.tsx +++ b/app/web/src/components/IdeSideBar/IdeSideBar.tsx @@ -1,22 +1,30 @@ import { useState } from 'react' import Svg from 'src/components/Svg/Svg' -import { sidebarTopConfig, sidebarBottomConfig, sidebarCombinedConfig } from './sidebarConfig' +import { + sidebarTopConfig, + sidebarBottomConfig, + sidebarCombinedConfig, +} from './sidebarConfig' import { useIdeContext } from 'src/helpers/hooks/useIdeContext' -function TabToggle({ item, className = "", active, onChange, onClick }) { +function TabToggle({ item, className = '', active, onChange, onClick }) { return ( - + ) } @@ -24,44 +32,52 @@ const IdeSideBar = () => { const { state, thunkDispatch } = useIdeContext() function onTabClick(name) { - return function() { - thunkDispatch({type: 'settingsButtonClicked', payload: [name]}) + return function () { + thunkDispatch({ type: 'settingsButtonClicked', payload: [name] }) } } - const selectedTab = React.useMemo(() => sidebarCombinedConfig.find(item => item.name === state.sideTray[0]), [state.sideTray]) + const selectedTab = React.useMemo( + () => sidebarCombinedConfig.find((item) => item.name === state.sideTray[0]), + [state.sideTray] + ) return ( -
    +
    - { sidebarTopConfig.map((topItem, i) => ( + {sidebarTopConfig.map((topItem, i) => ( onTabClick(topItem.name) } - onClick={ onTabClick(topItem.name) } - key={ 'tab-' + i } + active={state.sideTray[0] === topItem.name} + onChange={() => onTabClick(topItem.name)} + onClick={onTabClick(topItem.name)} + key={'tab-' + i} /> ))}
    - { sidebarBottomConfig.map((bottomItem, i) => ( + {sidebarBottomConfig.map((bottomItem, i) => ( onTabClick(bottomItem.name) } - onClick={ onTabClick(bottomItem.name) } - key={ 'tab-' + (sidebarTopConfig.length+i) } - /> + item={bottomItem} + active={state.sideTray[0] === bottomItem.name} + onChange={() => onTabClick(bottomItem.name)} + onClick={onTabClick(bottomItem.name)} + key={'tab-' + (sidebarTopConfig.length + i)} + /> ))}
    - { selectedTab?.panel && ( -
    -

    { selectedTab.name }

    - { selectedTab.panel } + {selectedTab?.panel && ( +
    +

    + {selectedTab.name} +

    + {selectedTab.panel}
    - ) } + )}
    ) } diff --git a/app/web/src/components/IdeSideBar/sidebarConfig.tsx b/app/web/src/components/IdeSideBar/sidebarConfig.tsx index 9015091..1ac449b 100644 --- a/app/web/src/components/IdeSideBar/sidebarConfig.tsx +++ b/app/web/src/components/IdeSideBar/sidebarConfig.tsx @@ -3,100 +3,154 @@ import { SvgNames } from 'src/components/Svg/Svg' import { useIdeContext } from 'src/helpers/hooks/useIdeContext' interface SidebarConfigType { - name: string, - icon: SvgNames, - disabled: boolean, - panel: ReactNode | null, + name: string + icon: SvgNames + disabled: boolean + panel: ReactNode | null } -export const sidebarTopConfig : SidebarConfigType[] = [ - { - name: 'Files', - icon: 'files', - disabled: false, - panel:
    -

    Coming Soon

    -
    -

    - We're working on multi-file support in tandem with the GitHub integration. -

    -
    , - }, - { - name: 'GitHub', - icon: 'github', - disabled: false, - panel:
    -

    Coming Soon

    -
    -

    - This integration will allow you to sync a project with a GitHub repo and push changes back to it as a commit! -

    -
    , - }, - { - name: 'Visibility', - icon: 'eye', - disabled: true, - panel: null, - }, +export const sidebarTopConfig: SidebarConfigType[] = [ + { + name: 'Files', + icon: 'files', + disabled: false, + panel: ( +
    +

    + Coming Soon +

    +
    +

    + We're working on multi-file support in tandem with the GitHub + integration. +

    +
    + ), + }, + { + name: 'GitHub', + icon: 'github', + disabled: false, + panel: ( +
    +

    + Coming Soon +

    +
    +

    + This integration will allow you to sync a project with a GitHub repo + and push changes back to it as a commit! +

    +
    + ), + }, + { + name: 'Visibility', + icon: 'eye', + disabled: true, + panel: null, + }, ] +const DiscordLink = () => ( + + Discord + +) + const settingsConfig = [ - { - title: "Editor", - name: "editor", - open: false, - content:

    This text will go in a details element!

    , - }, - { - title: "Viewer", - name: "viewer", - open: false, - content:

    This text will go in a details element!

    - }, - { - title: "Console", - name: "console", - open: false, - content:

    This text will go in a details element!

    - }, + { + title: 'Editor', + name: 'editor', + open: false, + content: ( +
    +

    + Coming Soon +

    +
    +

    + We're building configuration settings for the Viewer pane now. Join us on if you want to lend a hand! +

    +
    + ), + }, + { + title: 'Viewer', + name: 'viewer', + open: false, + content: ( +
    +

    + Coming Soon +

    +
    +

    + We're building configuration settings for the Viewer pane now. Join us on if you want to lend a hand! +

    +
    + ), + }, + { + title: 'Console', + name: 'console', + open: false, + content: ( +
    +

    + Coming Soon +

    +
    +

    + We're building configuration settings for the Viewer pane now. Join us on if you want to lend a hand! +

    +
    + ), + }, ] -export const sidebarBottomConfig : SidebarConfigType[] = [ - { - name: 'Settings', - icon: 'gear', - disabled: false, - panel: , - }, +export const sidebarBottomConfig: SidebarConfigType[] = [ + { + name: 'Settings', + icon: 'gear', + disabled: false, + panel: , + }, ] export const sidebarCombinedConfig = [ - ...sidebarTopConfig, - ...sidebarBottomConfig, + ...sidebarTopConfig, + ...sidebarBottomConfig, ] -function SettingsMenu({parentName}: {parentName: string}) { - const { state, thunkDispatch } = useIdeContext() - return ( -
    - { settingsConfig.map(item => ( -
  • - - { state.sideTray.slice(-1)[0] === item.name && item.content } -
  • - //
    - // thunkDispatch((dispatch) => dispatch({type: 'settingsButtonClicked', payload:[parentName, item.name]}))} - // >{ item.title }hi there - // { state.sideTray.slice(-1)[0] === item.name && item.content } - // {state.sideTray.slice(-1)[0]} - //
    - ))} -
    - ) +function SettingsMenu({ parentName }: { parentName: string }) { + const { state, thunkDispatch } = useIdeContext() + return ( +
    + {settingsConfig.map((item) => ( +
    { + e.preventDefault() + thunkDispatch((dispatch) => + dispatch({ + type: 'settingsButtonClicked', + payload: [parentName, item.name], + }) + ) + }} + > + + {item.title} + + {item.content} +
    + ))} +
    + ) } diff --git a/app/web/src/components/IdeWrapper/IdeWrapper.tsx b/app/web/src/components/IdeWrapper/IdeWrapper.tsx index 1ab9ddf..7b52242 100644 --- a/app/web/src/components/IdeWrapper/IdeWrapper.tsx +++ b/app/web/src/components/IdeWrapper/IdeWrapper.tsx @@ -32,17 +32,17 @@ const IdeWrapper = ({ cadPackage }: Props) => { return (
    - +
    +
    + +
    +
    + +
    -
    - -
    -
    ) diff --git a/app/web/src/components/PanelToolbar/PanelToolbar.tsx b/app/web/src/components/PanelToolbar/PanelToolbar.tsx index c8f8826..67c67a0 100644 --- a/app/web/src/components/PanelToolbar/PanelToolbar.tsx +++ b/app/web/src/components/PanelToolbar/PanelToolbar.tsx @@ -1,4 +1,4 @@ -import { useContext } from 'react' +import { MouseEventHandler, useContext } from 'react' import { MosaicWindowContext } from 'react-mosaic-component' import Svg from 'src/components/Svg/Svg' import OpenscadStaticImageMessage from 'src/components/OpenscadStaticImageMessage/OpenscadStaticImageMessage' @@ -6,9 +6,11 @@ import OpenscadStaticImageMessage from 'src/components/OpenscadStaticImageMessag const PanelToolbar = ({ panelName, showTopGradient, + onClick, }: { panelName: 'Viewer' | 'Console' showTopGradient?: boolean + onClick?: MouseEventHandler }) => { const { mosaicWindowActions } = useContext(MosaicWindowContext) return ( @@ -19,9 +21,13 @@ const PanelToolbar = ({
    {panelName === 'Viewer' && } diff --git a/app/web/src/components/Svg/Svg.tsx b/app/web/src/components/Svg/Svg.tsx index 4048a5f..7e47e7c 100644 --- a/app/web/src/components/Svg/Svg.tsx +++ b/app/web/src/components/Svg/Svg.tsx @@ -181,8 +181,19 @@ const Svg = ({ ), eye: ( - - + + ), favicon: ( @@ -286,8 +297,18 @@ const Svg = ({ ), files: ( - - + + ), flag: ( @@ -373,7 +394,12 @@ const Svg = ({ ), github: ( - + ), lightbulb: ( diff --git a/app/web/src/helpers/hooks/useIdeState.ts b/app/web/src/helpers/hooks/useIdeState.ts index 3e23c3c..09e9cc2 100644 --- a/app/web/src/helpers/hooks/useIdeState.ts +++ b/app/web/src/helpers/hooks/useIdeState.ts @@ -244,11 +244,27 @@ const reducer = (state: State, { type, payload }): State => { state.sideTray.length && state.sideTray.length === payload.length && state.sideTray.every((original, index) => original === payload[index]) + + const payloadInOriginal = + payload.length && state.sideTray.indexOf(payload[0]) + const isAncestorClick = + state.sideTray.length && + state.sideTray.length > payload.length && + payloadInOriginal >= 0 && + payload.every( + (incoming, i) => incoming === state.sideTray[i + payloadInOriginal] + ) + if (isReClick) { return { ...state, sideTray: state.sideTray.slice(0, -1), } + } else if (isAncestorClick) { + return { + ...state, + sideTray: state.sideTray.slice(0, payload.length * -1 - 1), + } } return { ...state, From cd1cecd774b0e7582ff1696569252a32e81ed0e3 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Sat, 18 Sep 2021 16:19:31 +1000 Subject: [PATCH 9/9] Remove double icon --- app/web/src/components/IdeSideBar/IdeSideBar.tsx | 2 +- .../src/components/ProjectProfile/ProjectProfile.tsx | 6 ------ app/web/src/components/UserProfile/UserProfile.tsx | 6 ------ app/web/src/helpers/hooks/useIdeState.ts | 1 - app/web/src/index.css | 10 ---------- 5 files changed, 1 insertion(+), 24 deletions(-) diff --git a/app/web/src/components/IdeSideBar/IdeSideBar.tsx b/app/web/src/components/IdeSideBar/IdeSideBar.tsx index 0a071f7..1919b9b 100644 --- a/app/web/src/components/IdeSideBar/IdeSideBar.tsx +++ b/app/web/src/components/IdeSideBar/IdeSideBar.tsx @@ -21,7 +21,7 @@ function TabToggle({ item, className = '', active, onChange, onClick }) { value={item.name} onChange={onChange} onClick={onClick} - className="visually-hidden" + className="sr-only" /> diff --git a/app/web/src/components/ProjectProfile/ProjectProfile.tsx b/app/web/src/components/ProjectProfile/ProjectProfile.tsx index 3d4c83b..399021c 100644 --- a/app/web/src/components/ProjectProfile/ProjectProfile.tsx +++ b/app/web/src/components/ProjectProfile/ProjectProfile.tsx @@ -70,12 +70,6 @@ const ProjectProfile = ({ <>
    - - - {}} projectTitle={project?.title} diff --git a/app/web/src/components/UserProfile/UserProfile.tsx b/app/web/src/components/UserProfile/UserProfile.tsx index 7c300f7..9ea9e91 100644 --- a/app/web/src/components/UserProfile/UserProfile.tsx +++ b/app/web/src/components/UserProfile/UserProfile.tsx @@ -53,12 +53,6 @@ const UserProfile = ({ <>
    - - - {}} projectOwner={user?.userName} diff --git a/app/web/src/helpers/hooks/useIdeState.ts b/app/web/src/helpers/hooks/useIdeState.ts index 09e9cc2..0e64da2 100644 --- a/app/web/src/helpers/hooks/useIdeState.ts +++ b/app/web/src/helpers/hooks/useIdeState.ts @@ -151,7 +151,6 @@ export const initialState: State = { } const reducer = (state: State, { type, payload }): State => { - console.log('reducing') switch (type) { case 'initIde': return { diff --git a/app/web/src/index.css b/app/web/src/index.css index aa01fce..b3ce904 100644 --- a/app/web/src/index.css +++ b/app/web/src/index.css @@ -30,16 +30,6 @@ @apply bg-ch-pink-800 bg-opacity-30 hover:bg-opacity-60; } - /* https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/ */ - .visually-hidden { - clip: rect(0 0 0 0); - clip-path: inset(50%); - height: 1px; - overflow: hidden; - position: absolute; - white-space: nowrap; - width: 1px; - } } @layer components {