Use ButtonGroupItem for all buttons in editor

This commit is contained in:
Henrik Giesel 2021-05-06 01:58:14 +02:00
parent bcb1b5d214
commit 0371405c23
8 changed files with 334 additions and 274 deletions

View File

@ -6,21 +6,23 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { onMount, createEventDispatcher, getContext } from "svelte";
import { nightModeKey } from "./contextKeys";
export let id: string;
export let className = "";
export let tooltip: string | undefined;
export let id: string | undefined = undefined;
let className = "";
export { className as class };
export let tooltip: string | undefined = undefined;
const nightMode = getContext(nightModeKey);
let buttonRef: HTMLButtonElement;
let inputRef: HTMLInputElement;
function delegateToInput() {
inputRef.click();
}
let buttonRef: HTMLButtonElement;
let inputRef: HTMLInputElement;
const dispatch = createEventDispatcher();
onMount(() => dispatch("mount", { button: buttonRef }));
onMount(() => dispatch("mount", { button: buttonRef, input: inputRef }));
</script>
<style lang="scss">
@ -30,13 +32,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
@import "ts/sass/bootstrap/variables";
button {
padding: 0;
width: calc(var(--toolbar-size) - 0px);
height: calc(var(--toolbar-size) - 0px);
padding: 4px;
overflow: hidden;
border-top-left-radius: var(--border-left-radius);
border-bottom-left-radius: var(--border-left-radius);
border-top-right-radius: var(--border-right-radius);
border-bottom-right-radius: var(--border-right-radius);
}
@include button.btn-day($with-disabled: false) using ($base) {

View File

@ -7,13 +7,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { getContext, onMount, createEventDispatcher } from "svelte";
import { disabledKey, nightModeKey, dropdownKey } from "./contextKeys";
export let id: string;
export let id: string | undefined = undefined;
let className = "";
export { className as class };
export let tooltip: string | undefined;
export let tooltip: string | undefined = undefined;
export let active = false;
export let disables = true;
export let tabbable = false;
let buttonRef: HTMLButtonElement;
@ -21,9 +22,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
$: _disabled = disables && $disabled;
const nightMode = getContext<boolean>(nightModeKey);
const dropdown = getContext(dropdownKey);
const dropdownProps = dropdown?.getDropdownTriggerProps() ?? {};
const dropdownProps = getContext(dropdownKey) ?? { dropdown: false };
const dispatch = createEventDispatcher();
onMount(() => dispatch("mount", { button: buttonRef }));
@ -34,6 +33,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
button {
padding: 0;
border-top-left-radius: var(--border-left-radius);
border-bottom-left-radius: var(--border-left-radius);
border-top-right-radius: var(--border-right-radius);
border-bottom-right-radius: var(--border-right-radius);
}
@include button.btn-day;
@ -66,13 +71,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{id}
class={`btn ${className}`}
class:active
class:dropdown-toggle={dropdownProps.dropdown}
class:btn-day={!nightMode}
class:btn-night={nightMode}
tabindex="-1"
title={tooltip}
disabled={_disabled}
class:dropdown-toggle={Boolean(dropdown)}
{...dropdownProps}
disabled={_disabled}
tabindex={tabbable ? 0 : -1}
on:click
on:mousedown|preventDefault>
<span class="p-1"><slot /></span>

View File

@ -5,28 +5,21 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="typescript">
import type { Readable } from "svelte/store";
import { onMount, createEventDispatcher, getContext } from "svelte";
import { disabledKey, nightModeKey } from "./contextKeys";
import { disabledKey, nightModeKey, dropdownKey } from "./contextKeys";
export let id: string | undefined = undefined;
let className: string = "";
export { className as class };
export let tooltip: string | undefined;
export let dropdownToggle = false;
export let disables = true;
export let tabbable = false;
$: dropdownProps = dropdownToggle
? {
"data-bs-toggle": "dropdown",
"aria-expanded": "false",
}
: {};
const disabled = getContext<Readable<boolean>>(disabledKey);
$: _disabled = disables && $disabled;
const nightMode = getContext<boolean>(nightModeKey);
const dropdownProps = getContext(dropdownKey) ?? {};
let buttonRef: HTMLButtonElement;
@ -58,7 +51,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
bind:this={buttonRef}
{id}
class={`btn ${className}`}
class:dropdown-toggle={dropdownToggle}
class:dropdown-toggle={dropdownProps.dropdown}
class:btn-day={!nightMode}
class:btn-night={nightMode}
title={tooltip}

View File

@ -9,10 +9,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { dropdownKey } from "./contextKeys";
setContext(dropdownKey, {
getDropdownTriggerProps: () => ({
"data-bs-toggle": "dropdown",
"aria-expanded": "false",
}),
dropdown: true,
"data-bs-toggle": "dropdown",
"aria-expanded": "false",
});
const menuId = Math.random().toString(36).substring(2);

View File

@ -5,9 +5,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="typescript">
import * as tr from "lib/i18n";
import ButtonGroup from "components/ButtonGroup.svelte";
import ButtonGroupItem from "components/ButtonGroupItem.svelte";
import IconButton from "components/IconButton.svelte";
import ColorPicker from "components/ColorPicker.svelte";
import ButtonGroup from "components/ButtonGroup.svelte";
import WithShortcut from "components/WithShortcut.svelte";
import { squareFillIcon } from "./icons";
@ -31,20 +32,24 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<ButtonGroup id="color">
<WithShortcut shortcut="F7" let:createShortcut let:shortcutLabel>
<IconButton
class="forecolor"
tooltip={`${tr.editingSetForegroundColor} (${shortcutLabel})`}
on:click={wrapWithForecolor}
on:mount={createShortcut}>
{@html squareFillIcon}
</IconButton>
</WithShortcut>
<ButtonGroupItem>
<WithShortcut shortcut="F7" let:createShortcut let:shortcutLabel>
<IconButton
class="forecolor"
tooltip={`${tr.editingSetForegroundColor} (${shortcutLabel})`}
on:click={wrapWithForecolor}
on:mount={createShortcut}>
{@html squareFillIcon}
</IconButton>
</WithShortcut>
</ButtonGroupItem>
<WithShortcut shortcut="F8" let:createShortcut let:shortcutLabel>
<ColorPicker
tooltip={`${tr.editingChangeColor()} (${shortcutLabel})`}
on:change={setWithCurrentColor}
on:mount={createShortcut} />
</WithShortcut>
<ButtonGroupItem>
<WithShortcut shortcut="F8" let:createShortcut let:shortcutLabel>
<ColorPicker
tooltip={`${tr.editingChangeColor()} (${shortcutLabel})`}
on:change={setWithCurrentColor}
on:mount={createShortcut} />
</WithShortcut>
</ButtonGroupItem>
</ButtonGroup>

View File

@ -6,8 +6,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { EditingArea } from "./editingArea";
import * as tr from "lib/i18n";
import IconButton from "components/IconButton.svelte";
import ButtonGroup from "components/ButtonGroup.svelte";
import ButtonGroupItem from "components/ButtonGroupItem.svelte";
import IconButton from "components/IconButton.svelte";
import ButtonDropdown from "components/ButtonDropdown.svelte";
import WithState from "components/WithState.svelte";
import WithDropdownMenu from "components/WithDropdownMenu.svelte";
@ -43,118 +44,138 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<ButtonGroup id="blockFormatting" {api}>
<WithState
key="insertUnorderedList"
update={() => document.queryCommandState('insertUnorderedList')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingUnorderedList()}
{active}
on:click={(event) => {
document.execCommand('insertUnorderedList');
updateState(event);
}}>
{@html ulIcon}
</IconButton>
</WithState>
<ButtonGroupItem>
<WithState
key="insertUnorderedList"
update={() => document.queryCommandState('insertUnorderedList')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingUnorderedList()}
{active}
on:click={(event) => {
document.execCommand('insertUnorderedList');
updateState(event);
}}>
{@html ulIcon}
</IconButton>
</WithState>
</ButtonGroupItem>
<WithState
key="insertOrderedList"
update={() => document.queryCommandState('insertOrderedList')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingOrderedList()}
{active}
on:click={(event) => {
document.execCommand('insertOrderedList');
updateState(event);
}}>
{@html olIcon}
</IconButton>
</WithState>
<ButtonGroupItem>
<WithState
key="insertOrderedList"
update={() => document.queryCommandState('insertOrderedList')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingOrderedList()}
{active}
on:click={(event) => {
document.execCommand('insertOrderedList');
updateState(event);
}}>
{@html olIcon}
</IconButton>
</WithState>
</ButtonGroupItem>
<WithDropdownMenu let:createDropdown let:menuId>
<IconButton on:mount={createDropdown}>
{@html listOptionsIcon}
</IconButton>
<ButtonGroupItem>
<IconButton on:mount={createDropdown}>
{@html listOptionsIcon}
</IconButton>
</ButtonGroupItem>
<ButtonDropdown id={menuId}>
<ButtonGroup id="justify" {api}>
<WithState
key="justifyLeft"
update={() => document.queryCommandState('justifyLeft')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingAlignLeft()}
{active}
on:click={(event) => {
document.execCommand('justifyLeft');
updateState(event);
}}>
{@html justifyLeftIcon}
</IconButton>
</WithState>
<ButtonGroupItem>
<WithState
key="justifyLeft"
update={() => document.queryCommandState('justifyLeft')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingAlignLeft()}
{active}
on:click={(event) => {
document.execCommand('justifyLeft');
updateState(event);
}}>
{@html justifyLeftIcon}
</IconButton>
</WithState>
</ButtonGroupItem>
<WithState
key="justifyCenter"
update={() => document.queryCommandState('justifyCenter')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingCenter()}
{active}
on:click={(event) => {
document.execCommand('justifyCenter');
updateState(event);
}}>
{@html justifyCenterIcon}
</IconButton>
</WithState>
<ButtonGroupItem>
<WithState
key="justifyCenter"
update={() => document.queryCommandState('justifyCenter')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingCenter()}
{active}
on:click={(event) => {
document.execCommand('justifyCenter');
updateState(event);
}}>
{@html justifyCenterIcon}
</IconButton>
</WithState>
</ButtonGroupItem>
<WithState
key="justifyRight"
update={() => document.queryCommandState('justifyRight')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingAlignRight()}
{active}
on:click={(event) => {
document.execCommand('justifyRight');
updateState(event);
}}>
{@html justifyRightIcon}
</IconButton>
</WithState>
<ButtonGroupItem>
<WithState
key="justifyRight"
update={() => document.queryCommandState('justifyRight')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingAlignRight()}
{active}
on:click={(event) => {
document.execCommand('justifyRight');
updateState(event);
}}>
{@html justifyRightIcon}
</IconButton>
</WithState>
</ButtonGroupItem>
<WithState
key="justifyFull"
update={() => document.queryCommandState('justifyFull')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingJustify()}
{active}
on:click={(event) => {
document.execCommand('justifyFull');
updateState(event);
}}>
{@html justifyFullIcon}
</IconButton>
</WithState>
<ButtonGroupItem>
<WithState
key="justifyFull"
update={() => document.queryCommandState('justifyFull')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingJustify()}
{active}
on:click={(event) => {
document.execCommand('justifyFull');
updateState(event);
}}>
{@html justifyFullIcon}
</IconButton>
</WithState>
</ButtonGroupItem>
</ButtonGroup>
<ButtonGroup id="indentation" {api}>
<IconButton on:click={outdentListItem} tooltip={tr.editingOutdent()}>
{@html outdentIcon}
</IconButton>
<ButtonGroupItem>
<IconButton
on:click={outdentListItem}
tooltip={tr.editingOutdent()}>
{@html outdentIcon}
</IconButton>
</ButtonGroupItem>
<IconButton on:click={indentListItem} tooltip={tr.editingIndent()}>
{@html indentIcon}
</IconButton>
<ButtonGroupItem>
<IconButton on:click={indentListItem} tooltip={tr.editingIndent()}>
{@html indentIcon}
</IconButton>
</ButtonGroupItem>
</ButtonGroup>
</ButtonDropdown>
</WithDropdownMenu>

View File

@ -6,6 +6,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import * as tr from "lib/i18n";
import ButtonGroup from "components/ButtonGroup.svelte";
import ButtonGroupItem from "components/ButtonGroupItem.svelte";
import IconButton from "components/IconButton.svelte";
import WithState from "components/WithState.svelte";
import WithShortcut from "components/WithShortcut.svelte";
@ -23,109 +24,124 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<ButtonGroup id="notetype" {api}>
<WithShortcut shortcut="Control+KeyB" let:createShortcut let:shortcutLabel>
<WithState
key="bold"
update={() => document.queryCommandState('bold')}
let:state={active}
let:updateState>
<ButtonGroupItem>
<WithShortcut shortcut="Control+KeyB" let:createShortcut let:shortcutLabel>
<WithState
key="bold"
update={() => document.queryCommandState('bold')}
let:state={active}
let:updateState>
<IconButton
tooltip={`${tr.editingBoldText()} (${shortcutLabel})`}
{active}
on:click={(event) => {
document.execCommand('bold');
updateState(event);
}}
on:mount={createShortcut}>
{@html boldIcon}
</IconButton>
</WithState>
</WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="Control+KeyI" let:createShortcut let:shortcutLabel>
<WithState
key="italic"
update={() => document.queryCommandState('italic')}
let:state={active}
let:updateState>
<IconButton
tooltip={`${tr.editingItalicText()} (${shortcutLabel})`}
{active}
on:click={(event) => {
document.execCommand('italic');
updateState(event);
}}
on:mount={createShortcut}>
{@html italicIcon}
</IconButton>
</WithState>
</WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="Control+KeyU" let:createShortcut let:shortcutLabel>
<WithState
key="underline"
update={() => document.queryCommandState('underline')}
let:state={active}
let:updateState>
<IconButton
tooltip={`${tr.editingUnderlineText()} (${shortcutLabel})`}
{active}
on:click={(event) => {
document.execCommand('underline');
updateState(event);
}}
on:mount={createShortcut}>
{@html underlineIcon}
</IconButton>
</WithState>
</WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut
shortcut="Control+Shift+Equal"
let:createShortcut
let:shortcutLabel>
<WithState
key="superscript"
update={() => document.queryCommandState('superscript')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingSuperscript()}
{active}
on:click={(event) => {
document.execCommand('superscript');
updateState(event);
}}
on:mount={createShortcut}>
{@html superscriptIcon}
</IconButton>
</WithState>
</WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="Control+Equal" let:createShortcut let:shortcutLabel>
<WithState
key="subscript"
update={() => document.queryCommandState('subscript')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingSubscript()}
{active}
on:click={(event) => {
document.execCommand('subscript');
updateState(event);
}}
on:mount={createShortcut}>
{@html subscriptIcon}
</IconButton>
</WithState>
</WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="Control+KeyR" let:createShortcut let:shortcutLabel>
<IconButton
tooltip={`${tr.editingBoldText()} (${shortcutLabel})`}
{active}
tooltip={tr.editingRemoveFormatting()}
on:click={(event) => {
document.execCommand('bold');
updateState(event);
document.execCommand('removeFormat');
}}
on:mount={createShortcut}>
{@html boldIcon}
{@html eraserIcon}
</IconButton>
</WithState>
</WithShortcut>
<WithShortcut shortcut="Control+KeyI" let:createShortcut let:shortcutLabel>
<WithState
key="italic"
update={() => document.queryCommandState('italic')}
let:state={active}
let:updateState>
<IconButton
tooltip={`${tr.editingItalicText()} (${shortcutLabel})`}
{active}
on:click={(event) => {
document.execCommand('italic');
updateState(event);
}}
on:mount={createShortcut}>
{@html italicIcon}
</IconButton>
</WithState>
</WithShortcut>
<WithShortcut shortcut="Control+KeyU" let:createShortcut let:shortcutLabel>
<WithState
key="underline"
update={() => document.queryCommandState('underline')}
let:state={active}
let:updateState>
<IconButton
tooltip={`${tr.editingUnderlineText()} (${shortcutLabel})`}
{active}
on:click={(event) => {
document.execCommand('underline');
updateState(event);
}}
on:mount={createShortcut}>
{@html underlineIcon}
</IconButton>
</WithState>
</WithShortcut>
<WithShortcut shortcut="Control+Shift+Equal" let:createShortcut let:shortcutLabel>
<WithState
key="superscript"
update={() => document.queryCommandState('superscript')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingSuperscript()}
{active}
on:click={(event) => {
document.execCommand('superscript');
updateState(event);
}}
on:mount={createShortcut}>
{@html superscriptIcon}
</IconButton>
</WithState>
</WithShortcut>
<WithShortcut shortcut="Control+Equal" let:createShortcut let:shortcutLabel>
<WithState
key="subscript"
update={() => document.queryCommandState('subscript')}
let:state={active}
let:updateState>
<IconButton
tooltip={tr.editingSubscript()}
{active}
on:click={(event) => {
document.execCommand('subscript');
updateState(event);
}}
on:mount={createShortcut}>
{@html subscriptIcon}
</IconButton>
</WithState>
</WithShortcut>
<WithShortcut shortcut="Control+KeyR" let:createShortcut let:shortcutLabel>
<IconButton
tooltip={tr.editingRemoveFormatting()}
on:click={(event) => {
document.execCommand('removeFormat');
}}
on:mount={createShortcut}>
{@html eraserIcon}
</IconButton>
</WithShortcut>
</WithShortcut>
</ButtonGroupItem>
</ButtonGroup>

View File

@ -6,8 +6,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import * as tr from "lib/i18n";
import { bridgeCommand } from "lib/bridgecommand";
import IconButton from "components/IconButton.svelte";
import ButtonGroup from "components/ButtonGroup.svelte";
import ButtonGroupItem from "components/ButtonGroupItem.svelte";
import IconButton from "components/IconButton.svelte";
import DropdownMenu from "components/DropdownMenu.svelte";
import DropdownItem from "components/DropdownItem.svelte";
import WithDropdownMenu from "components/WithDropdownMenu.svelte";
@ -32,28 +33,37 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<ButtonGroup id="template">
<WithShortcut shortcut="F3" let:createShortcut let:shortcutLabel>
<IconButton
tooltip={appendInParentheses(tr.editingAttachPicturesaudiovideo(), shortcutLabel)}
on:click={onAttachment}>
{@html paperclipIcon}
</IconButton>
</WithShortcut>
<ButtonGroupItem>
<WithShortcut shortcut="F3" let:createShortcut let:shortcutLabel>
<IconButton
tooltip={appendInParentheses(tr.editingAttachPicturesaudiovideo(), shortcutLabel)}
on:click={onAttachment}
on:mount={createShortcut}>
{@html paperclipIcon}
</IconButton>
</WithShortcut>
</ButtonGroupItem>
<WithShortcut shortcut="F5" let:createShortcut let:shortcutLabel>
<IconButton
tooltip={appendInParentheses(tr.editingRecordAudio(), shortcutLabel)}
on:click={onRecord}>
{@html micIcon}
</IconButton>
</WithShortcut>
<ButtonGroupItem>
<WithShortcut shortcut="F5" let:createShortcut let:shortcutLabel>
<IconButton
tooltip={appendInParentheses(tr.editingRecordAudio(), shortcutLabel)}
on:click={onRecord}>
{@html micIcon}
</IconButton>
</WithShortcut>
</ButtonGroupItem>
<ClozeButton />
<ButtonGroupItem>
<ClozeButton />
</ButtonGroupItem>
<WithDropdownMenu let:menuId let:createDropdown>
<IconButton on:mount={createDropdown}>
{@html functionIcon}
</IconButton>
<ButtonGroupItem>
<IconButton on:mount={createDropdown}>
{@html functionIcon}
</IconButton>
</ButtonGroupItem>
<DropdownMenu id={menuId}>
<WithShortcut
@ -112,12 +122,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</DropdownMenu>
</WithDropdownMenu>
<WithShortcut shortcut="Control+Shift+KeyX" let:createShortcut let:shortcutLabel>
<IconButton
tooltip={appendInParentheses(tr.editingHtmlEditor(), shortcutLabel)}
on:click={onHtmlEdit}
on:mount={createShortcut}>
{@html xmlIcon}
</IconButton>
</WithShortcut>
<ButtonGroupItem>
<WithShortcut
shortcut="Control+Shift+KeyX"
let:createShortcut
let:shortcutLabel>
<IconButton
tooltip={appendInParentheses(tr.editingHtmlEditor(), shortcutLabel)}
on:click={onHtmlEdit}
on:mount={createShortcut}>
{@html xmlIcon}
</IconButton>
</WithShortcut>
</ButtonGroupItem>
</ButtonGroup>