diff --git a/packages/app/src/components/edgeless-toolbar/index.tsx b/packages/app/src/components/edgeless-toolbar/index.tsx index 49762dde84..61eed107c5 100644 --- a/packages/app/src/components/edgeless-toolbar/index.tsx +++ b/packages/app/src/components/edgeless-toolbar/index.tsx @@ -1,3 +1,4 @@ +import { useState, useEffect } from 'react'; import { StyledEdgelessToolbar, StyledToolbarWrapper, @@ -19,59 +20,101 @@ import { useEditor } from '@/components/editor-provider'; const toolbarList1 = [ { + flavor: 'select', icon: , toolTip: 'Select', - onClick: () => {}, disable: false, }, { + flavor: 'text', icon: , toolTip: 'Text(coming soon)', - onClick: () => {}, disable: true, }, { + flavor: 'shape', icon: , toolTip: 'Shape(coming soon)', - onClick: () => {}, disable: true, }, { + flavor: 'sticky', icon: , - toolTip: 'Sticker(coming soon)', - onClick: () => {}, + toolTip: 'Sticky(coming soon)', disable: true, }, { + flavor: 'pen', icon: , toolTip: 'Pen(coming soon)', - onClick: () => {}, disable: true, }, { + flavor: 'connector', icon: , toolTip: 'Connector(coming soon)', - onClick: () => {}, disable: true, }, ]; const toolbarList2 = [ { + flavor: 'undo', icon: , - toolTip: 'Undo(coming soon)', - onClick: () => {}, - disable: true, + toolTip: 'Undo', + disable: false, }, { + flavor: 'redo', icon: , - toolTip: 'Redo(coming soon)', - onClick: () => {}, - disable: true, + toolTip: 'Redo', + disable: false, }, ]; + +const UndoRedo = () => { + const [canUndo, setCanUndo] = useState(false); + const [canRedo, setCanRedo] = useState(false); + const { editor } = useEditor(); + useEffect(() => { + if (!editor) return; + const { store } = editor; + + store.signals.historyUpdated.on(() => { + setCanUndo(store.canUndo); + setCanRedo(store.canRedo); + }); + }, [editor]); + + return ( + + + { + editor?.store?.undo(); + }} + > + + + + + { + editor?.store?.redo(); + }} + > + + + + + ); +}; + export const EdgelessToolbar = () => { const { mode } = useEditor(); + return ( { > - {toolbarList1.map(({ icon, toolTip, onClick, disable }, index) => { + {toolbarList1.map(({ icon, toolTip, flavor, disable }, index) => { return ( - - {icon} - - - ); - })} - - - {toolbarList2.map(({ icon, toolTip, onClick, disable }, index) => { - return ( - - + { + console.log('flavor', flavor); + }} + > {icon} ); })} + ); diff --git a/packages/app/src/components/edgeless-toolbar/style.ts b/packages/app/src/components/edgeless-toolbar/style.ts index e57a370beb..2cab9efc6f 100644 --- a/packages/app/src/components/edgeless-toolbar/style.ts +++ b/packages/app/src/components/edgeless-toolbar/style.ts @@ -20,22 +20,22 @@ export const StyledToolbarWrapper = styled.div(({ theme }) => ({ marginBottom: '12px', })); -export const StyledToolbarItem = styled.div<{ disable: boolean }>( - ({ theme, disable }) => ({ +export const StyledToolbarItem = styled.div<{ + disable?: boolean; +}>(({ theme, disable = false }) => ({ + width: '36px', + height: '36px', + ...displayFlex('center', 'center'), + color: disable ? '#C0C0C0' : theme.colors.iconColor, + cursor: 'pointer', + svg: { width: '36px', height: '36px', - ...displayFlex('center', 'center'), - color: disable ? '#C0C0C0' : theme.colors.iconColor, - cursor: 'pointer', - svg: { - width: '36px', - height: '36px', - }, - ':hover': disable - ? {} - : { - color: theme.colors.primaryColor, - background: theme.colors.hoverBackground, - }, - }) -); + }, + ':hover': disable + ? {} + : { + color: theme.colors.primaryColor, + background: theme.colors.hoverBackground, + }, +})); diff --git a/packages/app/src/components/editor-mode-switch/style.ts b/packages/app/src/components/editor-mode-switch/style.ts index ac7050e94e..5c7620092f 100644 --- a/packages/app/src/components/editor-mode-switch/style.ts +++ b/packages/app/src/components/editor-mode-switch/style.ts @@ -3,7 +3,7 @@ import { displayFlex, keyframes, styled } from '@/styles'; import spring, { toString } from 'css-spring'; import type { ItemStatus } from './type'; -const ANIMATE_DURATION = 400; +const ANIMATE_DURATION = 500; export const StyledAnimateRadioContainer = styled('div')<{ shrink: boolean }>( ({ shrink, theme }) => { diff --git a/packages/app/src/components/editor-provider.tsx b/packages/app/src/components/editor-provider.tsx index 030b912d11..52f04ceb3d 100644 --- a/packages/app/src/components/editor-provider.tsx +++ b/packages/app/src/components/editor-provider.tsx @@ -9,6 +9,7 @@ type EditorContextValue = { setEditor: (editor: EditorContainer) => void; setMode: (mode: EditorContainer['mode']) => void; }; + type EditorContextProps = PropsWithChildren<{}>; export const EditorContext = createContext({ diff --git a/packages/app/src/components/editor.tsx b/packages/app/src/components/editor.tsx index 45c2556aa0..1dfce1378c 100644 --- a/packages/app/src/components/editor.tsx +++ b/packages/app/src/components/editor.tsx @@ -6,26 +6,29 @@ import '@blocksuite/editor'; import '@blocksuite/blocks/style'; import { useEditor } from '@/components/editor-provider'; import pkg from '../../package.json'; - +import exampleMarkdown from './example-markdown'; export const Editor = () => { const editorRef = useRef(); const { setEditor } = useEditor(); useEffect(() => { setEditor(editorRef.current!); const { store } = editorRef.current as EditorContainer; - - const version = pkg.dependencies['@blocksuite/editor'].substring(1); const pageId = store.addBlock({ flavour: 'page', - title: `BlockSuite live demo ${version}`, + title: 'Welcome to the AFFiNE Alpha', }); const groupId = store.addBlock({ flavour: 'group' }, pageId); - - const text = new Text(store, 'Legend from here...'); - store.addBlock({ flavour: 'paragraph', text }, groupId); + // const text = new Text(store, 'Legend from here...'); + // store.addBlock({ flavour: 'paragraph', text }, groupId); + editorRef.current!.clipboard.importMarkdown(exampleMarkdown, `${groupId}`); store.resetHistory(); }, [setEditor]); + useEffect(() => { + const version = pkg.dependencies['@blocksuite/editor'].substring(1); + console.log(`BlockSuite live demo ${version}`); + }, []); + return ( Error!}> diff --git a/packages/app/src/components/example-markdown.ts b/packages/app/src/components/example-markdown.ts new file mode 100644 index 0000000000..663c6965e7 --- /dev/null +++ b/packages/app/src/components/example-markdown.ts @@ -0,0 +1,62 @@ +const exampleMarkdown = `The [AFFiNE Alpha](https://pathfinder.affine.systems/) is here! 👏 + +**What's different in AFFiNE Alpha?** + +1. A much ~smoother editing~ experience, with much ~greater stability~; +2. More complete ~Markdown~ support and improved ~keyboard shortcuts~; +3. New features such as ~dark mode~ + * **Switch between view styles using the** ☀ **and** 🌙. +4. ~Clean and modern UI/UX~ design. + +**Looking for Markdown syntax or keyboard shortcuts?** + +* Find the (?) in the bottom right, then the ️, to view a full list. of \`Keyboard Shortcuts\` + +**Have an enjoyable editing experience !!!** **😃** + +Have some feedback or just want to get in touch? Use the (?), then 🎧 to get in touch and join our communities. + +**Still in development** + +There also somethings you should consider about this AFFiNE Alpha including some ~limitations~: + +* Single page editing - currently editing multiple docs/pages is not supported; +* Changes are not automatically stored, to save changes you should export your data. Options can be found by going to the top right and finding the \`⋮\` icon. +* Without an import/open feature you are still able to access your data by copying it back in. + +**Keyboard Shortcuts:** + +1. Undo: \`⌘ + Z\` or \`Ctrl+Z\` +2. Redo: \`⌘ + ⇧ + Z\` or \`Ctrl+Shift+Z\` +3. Bold: \`⌘ + B\` or \`Ctrl+B\` +4. Italic: \`⌘ + I\` or \`Ctrl+I\` +5. Underline: \`⌘ + U\` or \`Ctrl+U\` +6. Strikethrough: \`⌘ + ⇧ + S\` or \`Ctrl+Shift+S\` +7. Inline code: \`⌘ + E\` or \`Ctrl+E\` +8. Link: \`⌘ + K\` or \`Ctrl+K\` +9. Body text: \`⌘ + ⌥ + 0\` or \`Ctrl+Shift+0\` +10. Heading 1: \`⌘ + ⌥ + 1\` or \`Ctrl+Shift+1\` +11. Heading 2: \`⌘ + ⌥ + 2\` or \`Ctrl+Shift+2\` +12. Heading 3: \`⌘ + ⌥ + 3\` or \`Ctrl+Shift+3\` +13. Heading 4: \`⌘ + ⌥ + 4\` or \`Ctrl+Shift+4\` +14. Heading 5: \`⌘ + ⌥ + 5\` or \`Ctrl+Shift+5\` +15. Heading 6: \`⌘ + ⌥ + 6\` or \`Ctrl+Shift+6\` +16. Increase indent: \`Tab\` +17. Reduce indent: \`⇧ + Tab\` or \`Shift+Tab\` + +_Markdown Syntax:_ + +1. Bold: \`**text**\` +2. Italic: \`*text*\` +3. Underline: \`~text~\` +4. Strikethrough: \`~~text~~\` +5. Inline code: \`\` \`code\` \`\` +6. Heading 1: \`# text\` +7. Heading 2: \`## text\` +8. Heading 3: \`### text\` +9. Heading 4: \`#### text\` +10. Heading 5: \`##### text\` +11. Heading 6: \`###### text\` +`; + +export default exampleMarkdown; diff --git a/packages/app/src/components/loading/styled.ts b/packages/app/src/components/loading/styled.ts index 43c7254d22..f8b9e959d4 100644 --- a/packages/app/src/components/loading/styled.ts +++ b/packages/app/src/components/loading/styled.ts @@ -1,5 +1,6 @@ import { styled } from '@/styles'; +// Inspired by https://codepen.io/graphilla/pen/rNvBMYY const loadingItemSize = '40px'; export const StyledLoading = styled.div` position: relative; diff --git a/packages/app/src/components/shortcuts-modal/config.ts b/packages/app/src/components/shortcuts-modal/config.ts index 948a8a54f3..26b9ea6555 100644 --- a/packages/app/src/components/shortcuts-modal/config.ts +++ b/packages/app/src/components/shortcuts-modal/config.ts @@ -19,17 +19,17 @@ export const macKeyboardShortcuts = { }; export const macMarkdownShortcuts = { - Bold: '**Text** Space', - Italic: '*Text* Space', - Underline: '~Text~ Space', - Strikethrough: '~~Text~~ Space', - 'Inline code': '`Code` Space', - 'Heading 1': '# Space', - 'Heading 2': '## Space', - 'Heading 3': '### Space', - 'Heading 4': '#### Space', - 'Heading 5': '##### Space', - 'Heading 6': '###### Space', + Bold: '**Text** ', + Italic: '*Text* ', + Underline: '~Text~ ', + Strikethrough: '~~Text~~ ', + 'Inline code': '`Code` ', + 'Heading 1': '# ', + 'Heading 2': '## ', + 'Heading 3': '### ', + 'Heading 4': '#### ', + 'Heading 5': '##### ', + 'Heading 6': '###### ', }; export const windowsKeyboardShortcuts = { @@ -52,15 +52,15 @@ export const windowsKeyboardShortcuts = { 'Reduce indent': 'Shift + Tab', }; export const winMarkdownShortcuts = { - Bold: '**Text** Space', - Italic: '*Text* Space', - Underline: '~Text~ Space', - Strikethrough: '~~Text~~ Space', - 'Inline code': '`Code` Space', - 'Heading 1': '# Space', - 'Heading 2': '## Space', - 'Heading 3': '### Space', - 'Heading 4': '#### Space', - 'Heading 5': '##### Space', - 'Heading 6': '###### Space', + Bold: '**Text** ', + Italic: '*Text* ', + Underline: '~Text~ ', + Strikethrough: '~~Text~~ ', + 'Inline code': '`Code` ', + 'Heading 1': '# ', + 'Heading 2': '## ', + 'Heading 3': '### ', + 'Heading 4': '#### ', + 'Heading 5': '##### ', + 'Heading 6': '###### ', }; diff --git a/packages/app/src/components/shortcuts-modal/style.ts b/packages/app/src/components/shortcuts-modal/style.ts index e9a34cf679..c9bf33e301 100644 --- a/packages/app/src/components/shortcuts-modal/style.ts +++ b/packages/app/src/components/shortcuts-modal/style.ts @@ -1,8 +1,9 @@ import { displayFlex, styled } from '@/styles'; export const StyledShortcutsModal = styled.div(({ theme }) => ({ - width: '268px', - height: '66vh', + width: '288px', + height: '74vh', + paddingBottom: '28px', backgroundColor: theme.colors.popoverBackground, boxShadow: theme.shadow.popover, color: theme.colors.popoverColor, @@ -17,8 +18,9 @@ export const StyledShortcutsModal = styled.div(({ theme }) => ({ })); export const StyledTitle = styled.div(({ theme }) => ({ color: theme.colors.textColor, - fontWeight: '600', + fontWeight: '500', fontSize: theme.font.sm, + height: '44px', ...displayFlex('center', 'center'), svg: { width: '20px', @@ -27,17 +29,17 @@ export const StyledTitle = styled.div(({ theme }) => ({ }, })); export const StyledSubTitle = styled.div(({ theme }) => ({ - color: theme.colors.textColor, + color: theme.colors.popoverColor, fontWeight: '500', - fontSize: '12px', - height: '36px', + fontSize: theme.font.sm, + height: '34px', lineHeight: '36px', marginTop: '28px', padding: '0 16px', })); export const StyledModalHeader = styled.div(({ theme }) => ({ ...displayFlex('space-between', 'center'), - height: '36px', + paddingTop: '8px 4px 0 4px', width: '100%', padding: '8px 16px 0 16px', position: 'sticky', @@ -49,9 +51,9 @@ export const StyledModalHeader = styled.div(({ theme }) => ({ })); export const StyledListItem = styled.div(({ theme }) => ({ - height: '32px', + height: '34px', ...displayFlex('space-between', 'center'), - fontSize: theme.font.xs, + fontSize: theme.font.sm, padding: '0 16px', })); diff --git a/packages/app/src/styles/theme.ts b/packages/app/src/styles/theme.ts index c24b835891..e07b9a33d4 100644 --- a/packages/app/src/styles/theme.ts +++ b/packages/app/src/styles/theme.ts @@ -14,6 +14,7 @@ export const lightTheme: AffineTheme = { codeBackground: '#f2f5f9', textColor: '#3A4C5C', + edgelessTextColor: '#3A4C5C', iconColor: '#9096A5', linkColor: '#6880FF', linkColor2: '#6880FF', @@ -59,6 +60,7 @@ export const darkTheme: AffineTheme = { codeBackground: '#505662', textColor: '#fff', + edgelessTextColor: '#3A4C5C', iconColor: '#9096A5', linkColor: '#7D91FF', linkColor2: '#6880FF', @@ -91,6 +93,7 @@ export const globalThemeVariables: ( '--affine-code-background': theme.colors.codeBackground, '--affine-text-color': theme.colors.textColor, + '--affine-edgeless-text-color': theme.colors.edgelessTextColor, '--affine-link-color': theme.colors.linkColor, // In dark mode, normal text`s (not bold) color '--affine-link-color2': theme.colors.linkColor2, diff --git a/packages/app/src/styles/types.ts b/packages/app/src/styles/types.ts index b95dd38fcd..c8f33a0fd2 100644 --- a/packages/app/src/styles/types.ts +++ b/packages/app/src/styles/types.ts @@ -20,7 +20,10 @@ export interface AffineTheme { hoverBackground: string; codeBackground: string; + // Use for the page`s text textColor: string; + // Use for the editor`s text, because in edgeless mode text is different form other + edgelessTextColor: string; linkColor: string; // In dark mode, normal text`s (not bold) color linkColor2: string; @@ -64,6 +67,7 @@ export interface AffineThemeCSSVariables { '--affine-code-background': AffineTheme['colors']['codeBackground']; '--affine-text-color': AffineTheme['colors']['textColor']; + '--affine-edgeless-text-color': AffineTheme['colors']['edgelessTextColor']; '--affine-link-color': AffineTheme['colors']['linkColor']; // In dark mode, normal text`s (not bold) color '--affine-link-color2': AffineTheme['colors']['linkColor2'];