feat(workspace): bar above the phone keyboard to indent, outdent and move bullets
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m33s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m33s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
32b79b5d62
commit
c6a2cfb85c
9 files changed
+183
-7
No files matched your search
@@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { ArrowDown, ArrowUp, IndentDecrease, IndentIncrease } from 'lucide-react';
|
||||
import { useKeyboardInset } from '../../lib/useKeyboardInset';
|
||||
|
||||
// Phones and tablets have no Tab key: while a bullet is being edited, a slim bar sits right above the
|
||||
// on-screen keyboard with outdent / indent and move up / down (the bullet takes its children along).
|
||||
export const isTouchOnly =
|
||||
typeof window !== 'undefined' &&
|
||||
!!window.matchMedia?.('(hover: none) and (pointer: coarse)').matches &&
|
||||
!window.matchMedia?.('(any-pointer: fine)').matches;
|
||||
|
||||
interface MobileOutlineBarProps {
|
||||
onOutdent: () => void;
|
||||
onIndent: () => void;
|
||||
onMoveUp: () => void;
|
||||
onMoveDown: () => void;
|
||||
}
|
||||
|
||||
export const MobileOutlineBar: React.FC<MobileOutlineBarProps> = ({ onOutdent, onIndent, onMoveUp, onMoveDown }) => {
|
||||
// iOS keeps fixed elements behind the keyboard: lift the bar by the keyboard's height
|
||||
const { inset } = useKeyboardInset();
|
||||
|
||||
const button = (label: string, icon: React.ReactNode, action: () => void) => (
|
||||
<button
|
||||
type="button"
|
||||
aria-label={label}
|
||||
title={label}
|
||||
// Keep the focus (and the keyboard) in the bullet: no focus change on press, act on click
|
||||
onPointerDown={(e) => e.preventDefault()}
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
onClick={action}
|
||||
className="h-10 flex-1 max-w-[4.5rem] flex items-center justify-center rounded-btn border border-border bg-canvas text-main active:bg-panel-elevated touch-manipulation"
|
||||
>
|
||||
{icon}
|
||||
</button>
|
||||
);
|
||||
|
||||
return createPortal(
|
||||
<div
|
||||
className="fixed left-0 right-0 z-[70] flex items-center justify-center gap-2 px-3 py-1.5 bg-panel/95 backdrop-blur-md border-t border-border"
|
||||
style={{ bottom: inset }}
|
||||
role="toolbar"
|
||||
aria-label="Punkt bearbeiten"
|
||||
>
|
||||
{button('Ausrücken', <IndentDecrease className="w-5 h-5" />, onOutdent)}
|
||||
{button('Einrücken', <IndentIncrease className="w-5 h-5" />, onIndent)}
|
||||
<span className="w-px h-6 bg-border mx-1" aria-hidden />
|
||||
{button('Nach oben', <ArrowUp className="w-5 h-5" />, onMoveUp)}
|
||||
{button('Nach unten', <ArrowDown className="w-5 h-5" />, onMoveDown)}
|
||||
</div>,
|
||||
document.body
|
||||
);
|
||||
};
|
||||
Reference in new issue
Block a user