diff --git a/src-web/components/MarkdownEditor.tsx b/src-web/components/MarkdownEditor.tsx index e2599613..aa1280a7 100644 --- a/src-web/components/MarkdownEditor.tsx +++ b/src-web/components/MarkdownEditor.tsx @@ -1,15 +1,12 @@ import classNames from 'classnames'; -import { atom, useAtom } from 'jotai'; -import { useRef } from 'react'; +import { useRef, useState } from 'react'; import type { Components } from 'react-markdown'; import Markdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; -import { useStateWithDeps } from '../hooks/useStateWithDeps'; -import { Button } from './core/Button'; import type { EditorProps } from './core/Editor/Editor'; import { Editor } from './core/Editor/Editor'; -import { HStack, VStack } from './core/Stacks'; import { Prose } from './Prose'; +import { SegmentedControl } from './core/SegmentedControl'; type ViewMode = 'edit' | 'preview'; @@ -19,27 +16,19 @@ interface Props extends Pick void; name: string; - defaultMode?: ViewMode; - doneButtonLabel?: string; } -const viewModeAtom = atom>({}); - export function MarkdownEditor({ className, defaultValue, onChange, name, - defaultMode = 'preview', - doneButtonLabel = 'Save', forceUpdateKey, ...editorProps }: Props) { - const [rawViewMode, setViewMode] = useAtom(viewModeAtom); - const [value, setValue] = useStateWithDeps(defaultValue, [forceUpdateKey]); + const [viewMode, setViewMode] = useState(defaultValue ? 'preview' : 'edit'); const containerRef = useRef(null); - const viewMode = rawViewMode[name] ?? defaultMode; const editor = ( @@ -61,7 +49,7 @@ export function MarkdownEditor({ ) : ( - {value} + {defaultValue} ); @@ -72,53 +60,31 @@ export function MarkdownEditor({
{contents}
- - {viewMode === 'preview' && ( - - )} - {viewMode === 'edit' && ( - - - - - )} - +
); } diff --git a/src-web/components/core/IconButton.tsx b/src-web/components/core/IconButton.tsx index 9c81c525..6db9ed4b 100644 --- a/src-web/components/core/IconButton.tsx +++ b/src-web/components/core/IconButton.tsx @@ -7,7 +7,7 @@ import { Button } from './Button'; import type { IconProps } from './Icon'; import { Icon } from './Icon'; -type Props = IconProps & +export type IconButtonProps = IconProps & ButtonProps & { showConfirm?: boolean; iconClassName?: string; @@ -16,7 +16,7 @@ type Props = IconProps & showBadge?: boolean; }; -export const IconButton = forwardRef(function IconButton( +export const IconButton = forwardRef(function IconButton( { showConfirm, icon, @@ -30,7 +30,7 @@ export const IconButton = forwardRef(function IconButt iconSize, showBadge, ...props - }: Props, + }: IconButtonProps, ref, ) { const [confirmed, setConfirmed] = useTimedBoolean(); diff --git a/src-web/components/core/SegmentedControl.tsx b/src-web/components/core/SegmentedControl.tsx new file mode 100644 index 00000000..3ed7bf41 --- /dev/null +++ b/src-web/components/core/SegmentedControl.tsx @@ -0,0 +1,56 @@ +import { useRef } from 'react'; +import { useStateWithDeps } from '../../hooks/useStateWithDeps'; +import type { IconProps } from './Icon'; +import type { IconButtonProps } from './IconButton'; +import { IconButton } from './IconButton'; +import { HStack } from './Stacks'; + +interface Props { + options: { value: T; label: string; icon: IconProps['icon']; event?: IconButtonProps['event'] }[]; + onChange: (value: T) => void; + value: T; + name: string; +} + +export function SegmentedControl({ value, onChange, options, name }: Props) { + const [selectedValue, setSelectedValue] = useStateWithDeps(value, [value]); + const containerRef = useRef(null); + return ( + { + const selectedIndex = options.findIndex((o) => o.value === selectedValue); + if (e.key === 'ArrowRight') { + const newIndex = Math.abs((selectedIndex + 1) % options.length); + setSelectedValue(options[newIndex]!.value); + const child = containerRef.current?.children[newIndex] as HTMLButtonElement; + child.focus(); + } else if (e.key === 'ArrowLeft') { + const newIndex = Math.abs((selectedIndex - 1) % options.length); + setSelectedValue(options[newIndex]!.value); + const child = containerRef.current?.children[newIndex] as HTMLButtonElement; + child.focus(); + } + }} + > + {options.map((o, i) => ( + onChange(o.value)} + /> + ))} + + ); +} diff --git a/src-web/hooks/useHotKey.ts b/src-web/hooks/useHotKey.ts index 24a535e2..12732f28 100644 --- a/src-web/hooks/useHotKey.ts +++ b/src-web/hooks/useHotKey.ts @@ -44,7 +44,7 @@ const hotkeys: Record = { 'settings.show': ['CmdCtrl+,'], 'sidebar.focus': ['CmdCtrl+b'], 'url_bar.focus': ['CmdCtrl+l'], - 'workspace_settings.show': ['CmdCtrl+Shift+,'], + 'workspace_settings.show': ['CmdCtrl+;'], }; const hotkeyLabels: Record = {