Files
MindSift/frontend/src/features/workspace/MobileOutlineBar.tsx
T
sandrodachandClaude Opus 5.5 c6a2cfb85c
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m33s
feat(workspace): bar above the phone keyboard to indent, outdent and move bullets
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 11:09:39 +01:00

55 lines
2.2 KiB
TypeScript

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
);
};