Merge pull request #667 from tidalcycles/toggle-sidebar

togglable panel position
This commit is contained in:
Felix Roos 2023-08-18 23:56:20 +02:00 committed by GitHub
commit 9287b8ea42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 45 deletions

View File

@ -18,3 +18,4 @@ vite.config.js
**/*.json **/*.json
**/dev-dist **/dev-dist
**/dist **/dist
/src-tauri/target/**/*

View File

@ -16,7 +16,7 @@ const TAURI = window.__TAURI__;
export function Footer({ context }) { export function Footer({ context }) {
const footerContent = useRef(); const footerContent = useRef();
const [log, setLog] = useState([]); const [log, setLog] = useState([]);
const { activeFooter, isZen } = useSettings(); const { activeFooter, isZen, panelPosition } = useSettings();
useLayoutEffect(() => { useLayoutEffect(() => {
if (footerContent.current && activeFooter === 'console') { if (footerContent.current && activeFooter === 'console') {
@ -71,8 +71,15 @@ export function Footer({ context }) {
if (isZen) { if (isZen) {
return null; return null;
} }
const isActive = activeFooter !== '';
let positions = {
right: cx('max-w-full flex-grow-0 flex-none overflow-hidden', isActive ? 'w-[600px] h-full' : 'absolute right-0'),
bottom: cx('relative', isActive ? 'h-[360px] min-h-[360px]' : ''),
};
return ( return (
<footer className="bg-lineHighlight z-[20]"> <nav className={cx('bg-lineHighlight z-[1000] flex flex-col', positions[panelPosition])}>
<div className="flex justify-between px-2"> <div className="flex justify-between px-2">
<div className={cx('flex select-none max-w-full overflow-auto', activeFooter && 'pb-2')}> <div className={cx('flex select-none max-w-full overflow-auto', activeFooter && 'pb-2')}>
<FooterTab name="intro" label="welcome" /> <FooterTab name="intro" label="welcome" />
@ -83,22 +90,24 @@ export function Footer({ context }) {
{TAURI && <FooterTab name="files" />} {TAURI && <FooterTab name="files" />}
</div> </div>
{activeFooter !== '' && ( {activeFooter !== '' && (
<button onClick={() => setActiveFooter('')} className="text-foreground" aria-label="Close Panel"> <button onClick={() => setActiveFooter('')} className="text-foreground px-2" aria-label="Close Panel">
<XMarkIcon className="w-5 h-5" /> <XMarkIcon className="w-5 h-5" />
</button> </button>
)} )}
</div> </div>
{activeFooter !== '' && ( {activeFooter !== '' && (
<div className="text-white flex-none h-[360px] overflow-auto max-w-full relative" ref={footerContent}> <div className="relative overflow-hidden">
{activeFooter === 'intro' && <WelcomeTab />} <div className="text-white overflow-auto h-full max-w-full" ref={footerContent}>
{activeFooter === 'console' && <ConsoleTab log={log} />} {activeFooter === 'intro' && <WelcomeTab />}
{activeFooter === 'sounds' && <SoundsTab />} {activeFooter === 'console' && <ConsoleTab log={log} />}
{activeFooter === 'reference' && <Reference />} {activeFooter === 'sounds' && <SoundsTab />}
{activeFooter === 'settings' && <SettingsTab scheduler={context.scheduler} />} {activeFooter === 'reference' && <Reference />}
{activeFooter === 'files' && <FilesTab />} {activeFooter === 'settings' && <SettingsTab scheduler={context.scheduler} />}
{activeFooter === 'files' && <FilesTab />}
</div>
</div> </div>
)} )}
</footer> </nav>
); );
} }
@ -377,6 +386,7 @@ function SettingsTab({ scheduler }) {
isLineWrappingEnabled, isLineWrappingEnabled,
fontSize, fontSize,
fontFamily, fontFamily,
panelPosition,
} = useSettings(); } = useSettings();
return ( return (
@ -420,14 +430,21 @@ function SettingsTab({ scheduler }) {
/> />
</FormItem> </FormItem>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-4 gap-4"> <FormItem label="Keybindings">
<FormItem label="Keybindings"> <ButtonGroup
<ButtonGroup value={keybindings}
value={keybindings} onChange={(keybindings) => settingsMap.setKey('keybindings', keybindings)}
onChange={(keybindings) => settingsMap.setKey('keybindings', keybindings)} items={{ codemirror: 'Codemirror', vim: 'Vim', emacs: 'Emacs' }}
items={{ codemirror: 'Codemirror', vim: 'Vim', emacs: 'Emacs' }} ></ButtonGroup>
></ButtonGroup> </FormItem>
</FormItem> <FormItem label="Panel Position">
<ButtonGroup
value={panelPosition}
onChange={(value) => settingsMap.setKey('panelPosition', value)}
items={{ bottom: 'Bottom', right: 'Right' }}
></ButtonGroup>
</FormItem>
<FormItem label="Code Settings">
<Checkbox <Checkbox
label="Display line numbers" label="Display line numbers"
onChange={(cbEvent) => settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)} onChange={(cbEvent) => settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)}
@ -443,7 +460,8 @@ function SettingsTab({ scheduler }) {
onChange={(cbEvent) => settingsMap.setKey('isLineWrappingEnabled', cbEvent.target.checked)} onChange={(cbEvent) => settingsMap.setKey('isLineWrappingEnabled', cbEvent.target.checked)}
value={isLineWrappingEnabled} value={isLineWrappingEnabled}
/> />
</div> </FormItem>
<FormItem label="Zen Mode">Try clicking the logo in the top left!</FormItem>
<FormItem label="Reset Settings"> <FormItem label="Reset Settings">
<button <button
className="bg-background p-2 max-w-[300px] rounded-md hover:opacity-50" className="bg-background p-2 max-w-[300px] rounded-md hover:opacity-50"

View File

@ -30,8 +30,9 @@ export function Header({ context }) {
<header <header
id="header" id="header"
className={cx( className={cx(
'py-1 flex-none w-full text-black justify-between z-[100] text-lg select-none sticky top-0', 'flex-none text-black z-[100] text-lg select-none',
!isZen && !isEmbedded && 'bg-lineHighlight', !isZen && !isEmbedded && 'bg-lineHighlight',
isZen ? 'h-12 w-8 fixed top-0 left-0' : 'sticky top-0 w-full py-1 justify-between',
isEmbedded ? 'flex' : 'md:flex', isEmbedded ? 'flex' : 'md:flex',
)} )}
> >

View File

@ -5,7 +5,7 @@ const visibleFunctions = jsdocJson.docs
export function Reference() { export function Reference() {
return ( return (
<div className="flex h-full w-full pt-2 text-foreground"> <div className="flex h-full w-full pt-2 text-foreground overflow-hidden">
<div className="w-42 flex-none h-full overflow-y-auto overflow-x-hidden pr-4"> <div className="w-42 flex-none h-full overflow-y-auto overflow-x-hidden pr-4">
{visibleFunctions.map((entry, i) => ( {visibleFunctions.map((entry, i) => (
<a key={i} className="cursor-pointer block hover:bg-lineHighlight py-1 px-4" href={`#doc-${i}`}> <a key={i} className="cursor-pointer block hover:bg-lineHighlight py-1 px-4" href={`#doc-${i}`}>
@ -14,7 +14,7 @@ export function Reference() {
))} ))}
</div> </div>
<div className="break-normal w-full h-full overflow-auto pl-4 flex relative"> <div className="break-normal w-full h-full overflow-auto pl-4 flex relative">
<div className="prose dark:prose-invert"> <div className="prose dark:prose-invert max-w-full pr-4">
<h2>API Reference</h2> <h2>API Reference</h2>
<p> <p>
This is the long list functions you can use! Remember that you don't need to remember all of those and that This is the long list functions you can use! Remember that you don't need to remember all of those and that

View File

@ -122,6 +122,7 @@ export function Repl({ embedded = false }) {
isLineNumbersDisplayed, isLineNumbersDisplayed,
isAutoCompletionEnabled, isAutoCompletionEnabled,
isLineWrappingEnabled, isLineWrappingEnabled,
panelPosition,
} = useSettings(); } = useSettings();
const { code, setCode, scheduler, evaluate, activateCode, isDirty, activeCode, pattern, started, stop, error } = const { code, setCode, scheduler, evaluate, activateCode, isDirty, activeCode, pattern, started, stop, error } =
@ -289,30 +290,12 @@ export function Repl({ embedded = false }) {
<ReplContext.Provider value={context}> <ReplContext.Provider value={context}>
<div <div
className={cx( className={cx(
'h-full flex flex-col', 'h-full flex flex-col relative',
// 'bg-gradient-to-t from-green-900 to-slate-900', // // overflow-hidden
)} )}
> >
<Loader active={pending} /> <Loader active={pending} />
<Header context={context} /> <Header context={context} />
<section className="grow flex text-gray-100 relative overflow-auto cursor-text pb-0" id="code">
<CodeMirror
theme={currentTheme}
value={code}
keybindings={keybindings}
isLineNumbersDisplayed={isLineNumbersDisplayed}
isAutoCompletionEnabled={isAutoCompletionEnabled}
isLineWrappingEnabled={isLineWrappingEnabled}
fontSize={fontSize}
fontFamily={fontFamily}
onChange={handleChangeCode}
onViewChanged={handleViewChanged}
onSelectionChange={handleSelectionChange}
/>
</section>
{error && (
<div className="text-red-500 p-4 bg-lineHighlight animate-pulse">{error.message || 'Unknown Error :-/'}</div>
)}
{isEmbedded && !started && ( {isEmbedded && !started && (
<button <button
onClick={() => handleTogglePlay()} onClick={() => handleTogglePlay()}
@ -322,7 +305,28 @@ export function Repl({ embedded = false }) {
<span>play</span> <span>play</span>
</button> </button>
)} )}
{!isEmbedded && <Footer context={context} />} <div className="grow flex relative overflow-hidden">
<section className="text-gray-100 cursor-text pb-0 overflow-auto grow" id="code">
<CodeMirror
theme={currentTheme}
value={code}
keybindings={keybindings}
isLineNumbersDisplayed={isLineNumbersDisplayed}
isAutoCompletionEnabled={isAutoCompletionEnabled}
isLineWrappingEnabled={isLineWrappingEnabled}
fontSize={fontSize}
fontFamily={fontFamily}
onChange={handleChangeCode}
onViewChanged={handleViewChanged}
onSelectionChange={handleSelectionChange}
/>
</section>
{panelPosition === 'right' && !isEmbedded && <Footer context={context} />}
</div>
{error && (
<div className="text-red-500 p-4 bg-lineHighlight animate-pulse">{error.message || 'Unknown Error :-/'}</div>
)}
{panelPosition === 'bottom' && !isEmbedded && <Footer context={context} />}
</div> </div>
</ReplContext.Provider> </ReplContext.Provider>
); );

View File

@ -14,6 +14,7 @@ export const defaultSettings = {
latestCode: '', latestCode: '',
isZen: false, isZen: false,
soundsFilter: 'all', soundsFilter: 'all',
panelPosition: 'bottom',
}; };
export const settingsMap = persistentMap('strudel-settings', defaultSettings); export const settingsMap = persistentMap('strudel-settings', defaultSettings);
@ -27,6 +28,7 @@ export function useSettings() {
isAutoCompletionEnabled: [true, 'true'].includes(state.isAutoCompletionEnabled) ? true : false, isAutoCompletionEnabled: [true, 'true'].includes(state.isAutoCompletionEnabled) ? true : false,
isLineWrappingEnabled: [true, 'true'].includes(state.isLineWrappingEnabled) ? true : false, isLineWrappingEnabled: [true, 'true'].includes(state.isLineWrappingEnabled) ? true : false,
fontSize: Number(state.fontSize), fontSize: Number(state.fontSize),
panelPosition: state.activeFooter !== '' ? state.panelPosition : 'bottom',
}; };
} }