Skip to content

Commit

Permalink
[pa] touch support with new toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
a-type committed Oct 6, 2024
1 parent e64c4aa commit 65d50c3
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 70 deletions.
2 changes: 1 addition & 1 deletion apps/palette/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
"@a-type/react-space": "^0.2.10",
"@a-type/react-space": "^0.2.12",
"@a-type/ui": "1.1.16",
"@a-type/utils": "1.1.3",
"@biscuits/client": "workspace:*",
Expand Down
71 changes: 52 additions & 19 deletions apps/palette/web/src/components/projects/ProjectCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,15 @@ import {
useClaimGesture,
useCanvas,
} from '@a-type/react-space';
import { proxy, useSnapshot } from 'valtio';
import { Button } from '@a-type/ui/components/button';
import { Icon } from '@a-type/ui/components/icon';

export interface ProjectCanvasProps {
project: Project;
className?: string;
showBubbles: boolean;
}
export function ProjectCanvas({
project,
className,
showBubbles,
}: ProjectCanvasProps) {
export function ProjectCanvas({ project, className }: ProjectCanvasProps) {
const { image, colors } = hooks.useWatch(project);
const [_, setSelected] = useColorSelection();
const addColor = (init: ProjectColorsItemInit) => {
Expand All @@ -38,6 +36,7 @@ export function ProjectCanvas({
setSelected(newColor.get('id'));
};
const [picking, setPicking] = useState(false);
const { showBubbles } = useSnapshot(toolState);

const viewport = useCreateViewport({
panLimitMode: 'viewport',
Expand All @@ -49,17 +48,21 @@ export function ProjectCanvas({
});

return (
<div className={clsx('relative w-full sm:(w-auto h-full)', className)}>
<ViewportRoot viewport={viewport}>
<div className="relative">
<ColorPickerCanvas
image={image}
onColor={addColor}
onPickingChange={setPicking}
/>
{showBubbles && !picking && <Bubbles colors={colors} />}
</div>
<div
className={clsx(
'relative flex flex-col w-full sm:(w-auto h-full)',
className,
)}
>
<ViewportRoot viewport={viewport} style={{ height: 'auto', flex: '1' }}>
<ColorPickerCanvas
image={image}
onColor={addColor}
onPickingChange={setPicking}
/>
{showBubbles && !picking && <Bubbles colors={colors} />}
</ViewportRoot>
<CanvasTools />
</div>
);
}
Expand Down Expand Up @@ -171,12 +174,14 @@ function BubblePicker({
}) {
const previewRef = useRef<HTMLDivElement>(null);

const { tool } = useSnapshot(toolState);

useClaimGesture(
'tool',
'bubble',
(detail) => {
console.log('detail', detail);
return detail.isTouch || detail.isLeftMouse;
return (tool === 'bubble' && detail.isTouch) || detail.isLeftMouse;
},
{
onCanvas: true,
Expand Down Expand Up @@ -272,8 +277,8 @@ function Bubble({ color: colorVal }: { color: ProjectColorsItem }) {
<button
onClick={() => setSelected(id)}
className={clsx(
'absolute rounded-full pointer-events-auto -translate-1/2 border-solid border-1 border-black appearance-none min-h-0 min-w-0 p-0 m-0',
selected && 'border-2 border-black z-1',
'absolute rounded-full pointer-events-auto -translate-1/2 border-solid border-1 border-gray appearance-none min-h-0 min-w-0 p-0 m-0',
selected && 'border-2 z-1',
)}
style={{
backgroundColor: `rgb(${r}, ${g}, ${b})`,
Expand All @@ -285,3 +290,31 @@ function Bubble({ color: colorVal }: { color: ProjectColorsItem }) {
/>
);
}

function CanvasTools() {
const { tool, showBubbles } = useSnapshot(toolState);

return (
<div className="row w-full bg-white p-2 border-gray border-1 border-solid">
<Button
size="icon"
toggled={showBubbles}
onClick={() => (toolState.showBubbles = !showBubbles)}
>
<Icon name={showBubbles ? 'eye' : 'eyeClosed'} />
</Button>
<Button
size="icon"
toggled={tool === 'bubble'}
onClick={() => (toolState.tool = tool === 'bubble' ? null : 'bubble')}
>
<Icon name="waterDrop" />
</Button>
</div>
);
}

const toolState = proxy({
tool: null as 'bubble' | null,
showBubbles: true,
});
11 changes: 3 additions & 8 deletions apps/palette/web/src/components/projects/ProjectView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@ import { ProjectColorSpotlight } from './ProjectColorSpotlight.jsx';

export interface ProjectViewProps {
project: Project;
showBubbles: boolean;
}

export function ProjectView({ project, showBubbles }: ProjectViewProps) {
export function ProjectView({ project }: ProjectViewProps) {
return (
<div className="flex flex-col items-stretch md:flex-row w-full h-full overflow-hidden gap-1">
<ProjectCanvas
project={project}
className="[flex:3_0_auto]"
showBubbles={showBubbles}
/>
<ProjectPalette project={project} className="[flex:1]" />
<ProjectCanvas project={project} className="[flex:3_0_0]" />
<ProjectPalette project={project} className="[flex:1_0_50px]" />
<ProjectColorSpotlight project={project} className="[flex:1_0_100px]" />
</div>
);
Expand Down
63 changes: 26 additions & 37 deletions apps/palette/web/src/pages/ProjectPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,38 @@ import { Icon } from '@a-type/ui/components/icon';
import { PageContent } from '@a-type/ui/components/layouts';
import { H1 } from '@a-type/ui/components/typography';
import { Link, useParams } from '@verdant-web/react-router';
import { useState } from 'react';

export interface ProjectPageProps {}

export function ProjectPage({}: ProjectPageProps) {
const id = useParams().id;
const project = hooks.useProject(id);
const id = useParams().id;
const project = hooks.useProject(id);

const [showBubbles, setShowBubbles] = useState(true);
if (!project) {
return (
<PageContent className="gap-4">
<H1>Project missing</H1>
<p>Sorry, couldn't find this project. Maybe it was deleted?</p>
<Button asChild>
<Link to="/">Back to projects</Link>
</Button>
</PageContent>
);
}

if (!project) {
return (
<PageContent className="gap-4">
<H1>Project missing</H1>
<p>Sorry, couldn't find this project. Maybe it was deleted?</p>
<Button asChild>
<Link to="/">Back to projects</Link>
</Button>
</PageContent>
);
}

return (
<div className="flex flex-col p-0 m-0 w-full h-100vh">
<div className="row py-1">
<Button asChild color="ghost" size="small">
<Link to="/">
<Icon name="arrowLeft" />
Back to projects
</Link>
</Button>
<Button
toggled={showBubbles}
onClick={() => setShowBubbles((v) => !v)}
size="icon"
className="ml-auto mr-2"
>
<Icon name="waterDrop" />
</Button>
</div>
<ProjectView project={project} showBubbles={showBubbles} />
</div>
);
return (
<div className="flex flex-col p-0 m-0 w-full h-100vh">
<div className="row py-1">
<Button asChild color="ghost" size="small">
<Link to="/">
<Icon name="arrowLeft" />
Back to projects
</Link>
</Button>
</div>
<ProjectView project={project} />
</div>
);
}

export default ProjectPage;
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 65d50c3

Please sign in to comment.