remove panel hover + optimize bottom panel
This commit is contained in:
parent
4f14ff00d5
commit
60b5024f63
5 changed files with 121 additions and 138 deletions
|
|
@ -13,115 +13,122 @@ export function Header({ context, embedded = false }) {
|
||||||
const { started, pending, isDirty, activeCode, handleTogglePlay, handleEvaluate, handleShuffle, handleShare } =
|
const { started, pending, isDirty, activeCode, handleTogglePlay, handleEvaluate, handleShuffle, handleShare } =
|
||||||
context;
|
context;
|
||||||
const isEmbedded = typeof window !== 'undefined' && (embedded || window.location !== window.parent.location);
|
const isEmbedded = typeof window !== 'undefined' && (embedded || window.location !== window.parent.location);
|
||||||
const { isZen, isButtonRowHidden, isCSSAnimationDisabled, fontFamily, isPanelOpen } = useSettings();
|
const { isZen, isButtonRowHidden, isCSSAnimationDisabled, fontFamily, isPanelOpen, panelPosition } = useSettings();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
id="header"
|
id="header"
|
||||||
className={cx(
|
className={cx(
|
||||||
'flex-none text-black z-[100] text-sm select-none min-h-10',
|
'flex-none text-black z-[100] text-sm select-none min-h-10',
|
||||||
!isZen && !isEmbedded && 'bg-lineHighlight',
|
!isZen && !isEmbedded && 'bg-lineHighlight',
|
||||||
isZen ? 'h-12 w-8 fixed top-0 left-0' : 'sticky top-0 w-full justify-between',
|
isZen ? 'h-12 w-8 fixed top-0 left-0' : 'sticky top-0 w-full justify-between',
|
||||||
isEmbedded ? 'flex' : 'sm:flex',
|
'flex items-center',
|
||||||
)}
|
)}
|
||||||
style={{ fontFamily }}
|
style={{ fontFamily }}
|
||||||
>
|
>
|
||||||
<div className="px-4 pt-1 flex space-x-2 md:pt-0 select-none">
|
<div className={cx(isEmbedded ? 'flex' : 'sm:flex', 'w-full sm:justify-between')}>
|
||||||
<h1
|
<div className="px-3 pt-1 flex space-x-2 sm:pt-0 select-none">
|
||||||
onClick={() => {
|
<h1
|
||||||
if (isEmbedded) window.open(window.location.href.replace('embed', ''));
|
|
||||||
}}
|
|
||||||
className={cx(
|
|
||||||
isEmbedded ? 'text-l cursor-pointer' : 'text-xl',
|
|
||||||
'text-foreground font-bold flex space-x-2 items-center',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={cx(
|
|
||||||
'mt-[1px]',
|
|
||||||
started && !isCSSAnimationDisabled && 'animate-spin',
|
|
||||||
'cursor-pointer text-blue-500',
|
|
||||||
isZen && 'fixed top-2 right-4',
|
|
||||||
)}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!isEmbedded) {
|
if (isEmbedded) window.open(window.location.href.replace('embed', ''));
|
||||||
setIsZen(!isZen);
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
|
||||||
<span className="block text-foreground rotate-90">
|
|
||||||
<StrudelIcon className="w-5 h-5 fill-foreground" />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{!isZen && (
|
|
||||||
<div className="space-x-2">
|
|
||||||
<span className="">strudel</span>
|
|
||||||
<span className="text-sm font-medium">REPL</span>
|
|
||||||
{!isEmbedded && isButtonRowHidden && (
|
|
||||||
<a href={`${baseNoTrailing}/learn`} className="text-sm opacity-25 font-medium">
|
|
||||||
DOCS
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
{!isZen && !isButtonRowHidden && (
|
|
||||||
<div className="flex max-w-full overflow-auto text-foreground px-2 h-10 justify-end">
|
|
||||||
<button
|
|
||||||
onClick={handleTogglePlay}
|
|
||||||
title={started ? 'stop' : 'play'}
|
|
||||||
className={cx('px-2 hover:opacity-50', !started && !isCSSAnimationDisabled && 'animate-pulse')}
|
|
||||||
>
|
|
||||||
{!pending ? (
|
|
||||||
<span className={cx('flex items-center space-x-2')}>
|
|
||||||
{started ? <StopCircleIcon className="w-5 h-5" /> : <PlayCircleIcon className="w-5 h-5" />}
|
|
||||||
{!isEmbedded && <span>{started ? 'stop' : 'play'}</span>}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<>loading...</>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={handleEvaluate}
|
|
||||||
title="update"
|
|
||||||
className={cx(
|
className={cx(
|
||||||
'flex items-center space-x-1 px-2',
|
isEmbedded ? 'text-l cursor-pointer' : 'text-xl',
|
||||||
!isDirty || !activeCode ? 'opacity-50' : 'hover:opacity-50',
|
'text-foreground font-bold flex space-x-2 items-center',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{!isEmbedded && <span>update</span>}
|
<div
|
||||||
</button>
|
className={cx(
|
||||||
{!isEmbedded && (
|
'mt-[1px]',
|
||||||
<button
|
started && !isCSSAnimationDisabled && 'animate-spin',
|
||||||
title="share"
|
'cursor-pointer text-blue-500',
|
||||||
className={cx('cursor-pointer hover:opacity-50 flex items-center space-x-1 px-2')}
|
isZen && 'fixed top-2 right-4',
|
||||||
onClick={handleShare}
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
if (!isEmbedded) {
|
||||||
|
setIsZen(!isZen);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<span>share</span>
|
<span className="block text-foreground rotate-90">
|
||||||
</button>
|
<StrudelIcon className="w-5 h-5 fill-foreground" />
|
||||||
)}
|
</span>
|
||||||
{!isEmbedded && (
|
</div>
|
||||||
<a
|
{!isZen && (
|
||||||
title="learn"
|
<div className="space-x-2">
|
||||||
href={`${baseNoTrailing}/workshop/getting-started/`}
|
<span className="">strudel</span>
|
||||||
className={cx('hover:opacity-50 flex items-center space-x-1', !isEmbedded ? 'p-2' : 'px-2')}
|
<span className="text-sm font-medium">REPL</span>
|
||||||
>
|
{!isEmbedded && isButtonRowHidden && (
|
||||||
<span>learn</span>
|
<a href={`${baseNoTrailing}/learn`} className="text-sm opacity-25 font-medium">
|
||||||
</a>
|
DOCS
|
||||||
)}
|
</a>
|
||||||
{!isEmbedded && (
|
)}
|
||||||
<button
|
</div>
|
||||||
title="share"
|
)}
|
||||||
className={cx('cursor-pointer hover:opacity-50 flex items-center space-x-1 pl-2 pr-1')}
|
</h1>
|
||||||
onClick={() => setIsPanelOpened(!isPanelOpen)}
|
|
||||||
>
|
|
||||||
<span>menu</span>
|
|
||||||
<Bars3Icon className="w-5 h-5" />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
{!isZen && !isButtonRowHidden && (
|
||||||
|
<div className="flex max-w-full overflow-auto text-foreground px-3 h-10">
|
||||||
|
<button
|
||||||
|
onClick={handleTogglePlay}
|
||||||
|
title={started ? 'stop' : 'play'}
|
||||||
|
className={cx('hover:opacity-50', !started && !isCSSAnimationDisabled && 'animate-pulse')}
|
||||||
|
>
|
||||||
|
{!pending ? (
|
||||||
|
<span className={cx('flex items-center space-x-2')}>
|
||||||
|
{started ? <StopCircleIcon className="w-5 h-5" /> : <PlayCircleIcon className="w-5 h-5" />}
|
||||||
|
{!isEmbedded && <span>{started ? 'stop' : 'play'}</span>}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<>loading...</>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleEvaluate}
|
||||||
|
title="update"
|
||||||
|
className={cx(
|
||||||
|
'flex items-center space-x-1 px-2',
|
||||||
|
!isDirty || !activeCode ? 'opacity-50' : 'hover:opacity-50',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{!isEmbedded && <span>update</span>}
|
||||||
|
</button>
|
||||||
|
{!isEmbedded && (
|
||||||
|
<button
|
||||||
|
title="share"
|
||||||
|
className={cx('cursor-pointer hover:opacity-50 flex items-center space-x-1 px-2')}
|
||||||
|
onClick={handleShare}
|
||||||
|
>
|
||||||
|
<span>share</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{!isEmbedded && (
|
||||||
|
<a
|
||||||
|
title="learn"
|
||||||
|
href={`${baseNoTrailing}/workshop/getting-started/`}
|
||||||
|
className={cx('hover:opacity-50 flex items-center space-x-1', !isEmbedded ? 'p-2' : 'px-2')}
|
||||||
|
>
|
||||||
|
<span>learn</span>
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{!isEmbedded && !isZen && panelPosition === 'right' && (
|
||||||
|
<button
|
||||||
|
title="share"
|
||||||
|
className={cx(
|
||||||
|
'cursor-pointer hover:opacity-50 flex items-center space-x-1 pr-3 text-foreground',
|
||||||
|
// isPanelOpen && 'opacity-0',
|
||||||
|
)}
|
||||||
|
onClick={() => setIsPanelOpened(!isPanelOpen)}
|
||||||
|
>
|
||||||
|
{/* <span>menu</span> */}
|
||||||
|
<Bars3Icon className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,27 +14,25 @@ import ExportTab from './ExportTab';
|
||||||
const TAURI = typeof window !== 'undefined' && window.__TAURI__;
|
const TAURI = typeof window !== 'undefined' && window.__TAURI__;
|
||||||
|
|
||||||
export function HorizontalPanel({ context }) {
|
export function HorizontalPanel({ context }) {
|
||||||
const settings = useSettings();
|
const { isPanelOpen, activeFooter: tab } = useSettings();
|
||||||
const { isPanelOpen, activeFooter: tab } = settings;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelNav
|
<PanelNav
|
||||||
settings={settings}
|
className={cx(
|
||||||
className={cx(isPanelOpen ? `min-h-[360px] max-h-[360px]` : 'min-h-12 max-h-12', 'overflow-hidden flex flex-col')}
|
isPanelOpen ? `min-h-[360px] max-h-[360px]` : 'min-h-10 max-h-10',
|
||||||
|
'overflow-hidden flex flex-col relative ',
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
|
<div className="flex justify-between min-h-10 max-h-10 grid-cols-2 items-center">
|
||||||
|
<Tabs setTab={setTab} tab={tab} />
|
||||||
|
</div>
|
||||||
|
<div className="absolute right-0 top-1">
|
||||||
|
<PanelActionButton />
|
||||||
|
</div>
|
||||||
{isPanelOpen && (
|
{isPanelOpen && (
|
||||||
<div className="flex h-full overflow-auto pr-10 ">
|
<div className="flex h-full overflow-auto pr-10 ">
|
||||||
<PanelContent context={context} tab={tab} />
|
<PanelContent context={context} tab={tab} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="absolute right-4 pt-4">
|
|
||||||
<PanelActionButton settings={settings} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex justify-between min-h-12 max-h-12 grid-cols-2 items-center">
|
|
||||||
<Tabs setTab={setTab} tab={tab} />
|
|
||||||
</div>
|
|
||||||
</PanelNav>
|
</PanelNav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -53,7 +51,7 @@ export function VerticalPanel({ context }) {
|
||||||
<div className={cx('flex flex-col h-full')}>
|
<div className={cx('flex flex-col h-full')}>
|
||||||
<div className="flex justify-between w-full ">
|
<div className="flex justify-between w-full ">
|
||||||
<Tabs setTab={setTab} tab={tab} />
|
<Tabs setTab={setTab} tab={tab} />
|
||||||
<PanelActionButton settings={settings} />
|
{/* <PanelActionButton settings={settings} /> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overflow-auto h-full">
|
<div className="overflow-auto h-full">
|
||||||
|
|
@ -77,8 +75,8 @@ if (TAURI) {
|
||||||
tabNames.files = 'files';
|
tabNames.files = 'files';
|
||||||
}
|
}
|
||||||
|
|
||||||
function PanelNav({ children, className, settings, ...props }) {
|
function PanelNav({ children, className, ...props }) {
|
||||||
const isHoverBehavior = settings.togglePanelTrigger === 'hover';
|
const settings = useSettings();
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -86,16 +84,6 @@ function PanelNav({ children, className, settings, ...props }) {
|
||||||
setIsPanelOpened(true);
|
setIsPanelOpened(true);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onMouseEnter={() => {
|
|
||||||
if (isHoverBehavior && !settings.isPanelOpen) {
|
|
||||||
setIsPanelOpened(true);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onMouseLeave={() => {
|
|
||||||
if (isHoverBehavior && !settings.isPanelPinned) {
|
|
||||||
setIsPanelOpened(false);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
aria-label="Menu Panel"
|
aria-label="Menu Panel"
|
||||||
className={cx('bg-lineHighlight group overflow-x-auto', className)}
|
className={cx('bg-lineHighlight group overflow-x-auto', className)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -142,27 +130,24 @@ function PanelTab({ label, isSelected, onClick }) {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
function Tabs({ setTab, tab, className }) {
|
function Tabs({ className }) {
|
||||||
|
const { isPanelOpen, activeFooter: tab } = useSettings();
|
||||||
return (
|
return (
|
||||||
<div className={cx('flex select-none max-w-full overflow-auto pb-2', className)}>
|
<div className={cx('flex select-none max-w-full overflow-auto pb-2', className)}>
|
||||||
{Object.keys(tabNames).map((key) => {
|
{Object.keys(tabNames).map((key) => {
|
||||||
const val = tabNames[key];
|
const val = tabNames[key];
|
||||||
return <PanelTab key={key} isSelected={tab === val} label={key} onClick={() => setTab(val)} />;
|
return <PanelTab key={key} isSelected={tab === val && isPanelOpen} label={key} onClick={() => setTab(val)} />;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PanelActionButton({ settings }) {
|
function PanelActionButton() {
|
||||||
const { togglePanelTrigger, isPanelPinned, isPanelOpen } = settings;
|
const settings = useSettings();
|
||||||
const isHoverBehavior = togglePanelTrigger === 'hover';
|
const { isPanelOpen } = settings;
|
||||||
if (!isPanelOpen) {
|
if (!isPanelOpen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isHoverBehavior) {
|
|
||||||
return <PinButton pinned={isPanelPinned} />;
|
|
||||||
}
|
|
||||||
return <CloseButton onClick={() => setIsPanelOpened(false)} />;
|
return <CloseButton onClick={() => setIsPanelOpened(false)} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,6 @@ export function SettingsTab({ started }) {
|
||||||
panelPosition,
|
panelPosition,
|
||||||
audioDeviceName,
|
audioDeviceName,
|
||||||
audioEngineTarget,
|
audioEngineTarget,
|
||||||
togglePanelTrigger,
|
|
||||||
maxPolyphony,
|
maxPolyphony,
|
||||||
multiChannelOrbits,
|
multiChannelOrbits,
|
||||||
isTabIndentationEnabled,
|
isTabIndentationEnabled,
|
||||||
|
|
@ -256,13 +255,6 @@ export function SettingsTab({ started }) {
|
||||||
items={{ bottom: 'Bottom', right: 'Right' }}
|
items={{ bottom: 'Bottom', right: 'Right' }}
|
||||||
></ButtonGroup>
|
></ButtonGroup>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="Open Panel on: ">
|
|
||||||
<ButtonGroup
|
|
||||||
value={togglePanelTrigger}
|
|
||||||
onChange={(value) => settingsMap.setKey('togglePanelTrigger', value)}
|
|
||||||
items={{ click: 'Click', hover: 'Hover' }}
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem label="More Settings">
|
<FormItem label="More Settings">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Enable bracket matching"
|
label="Enable bracket matching"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export function WelcomeTab({ context }) {
|
||||||
const { fontFamily } = useSettings();
|
const { fontFamily } = useSettings();
|
||||||
return (
|
return (
|
||||||
<div className="prose dark:prose-invert min-w-full pt-2 font-sans pb-8 px-4 " style={{ fontFamily }}>
|
<div className="prose dark:prose-invert min-w-full pt-2 font-sans pb-8 px-4 " style={{ fontFamily }}>
|
||||||
<h3>꩜ welcome</h3>
|
<h3>welcome</h3>
|
||||||
<p>
|
<p>
|
||||||
You have found <span className="underline">strudel</span>, a new live coding platform to write dynamic music
|
You have found <span className="underline">strudel</span>, a new live coding platform to write dynamic music
|
||||||
pieces in the browser! It is free and open-source and made for beginners and experts alike. To get started:
|
pieces in the browser! It is free and open-source and made for beginners and experts alike. To get started:
|
||||||
|
|
@ -30,7 +30,7 @@ export function WelcomeTab({ context }) {
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
to ask any questions, give feedback or just say hello.
|
to ask any questions, give feedback or just say hello.
|
||||||
</p>
|
</p>
|
||||||
<h3>꩜ about</h3>
|
<h3>about</h3>
|
||||||
<p>
|
<p>
|
||||||
strudel is a JavaScript version of{' '}
|
strudel is a JavaScript version of{' '}
|
||||||
<a href="https://tidalcycles.org/" target="_blank">
|
<a href="https://tidalcycles.org/" target="_blank">
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ export const defaultSettings = {
|
||||||
panelPosition: 'right',
|
panelPosition: 'right',
|
||||||
isPanelPinned: false,
|
isPanelPinned: false,
|
||||||
isPanelOpen: true,
|
isPanelOpen: true,
|
||||||
togglePanelTrigger: 'click', //click | hover
|
|
||||||
userPatterns: '{}',
|
userPatterns: '{}',
|
||||||
prebakeScript: '',
|
prebakeScript: '',
|
||||||
audioEngineTarget: audioEngineTargets.webaudio,
|
audioEngineTarget: audioEngineTargets.webaudio,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue