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 { onMount, createEventDispatcher, getContext } from "svelte";
import { nightModeKey } from "./contextKeys"; import { nightModeKey } from "./contextKeys";
export let id: string; export let id: string | undefined = undefined;
export let className = ""; let className = "";
export let tooltip: string | undefined; export { className as class };
export let tooltip: string | undefined = undefined;
const nightMode = getContext(nightModeKey); const nightMode = getContext(nightModeKey);
let buttonRef: HTMLButtonElement;
let inputRef: HTMLInputElement;
function delegateToInput() { function delegateToInput() {
inputRef.click(); inputRef.click();
} }
let buttonRef: HTMLButtonElement;
let inputRef: HTMLInputElement;
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
onMount(() => dispatch("mount", { button: buttonRef })); onMount(() => dispatch("mount", { button: buttonRef, input: inputRef }));
</script> </script>
<style lang="scss"> <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"; @import "ts/sass/bootstrap/variables";
button { button {
padding: 0;
width: calc(var(--toolbar-size) - 0px); width: calc(var(--toolbar-size) - 0px);
height: calc(var(--toolbar-size) - 0px); height: calc(var(--toolbar-size) - 0px);
padding: 4px; padding: 4px;
overflow: hidden; 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) { @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 { getContext, onMount, createEventDispatcher } from "svelte";
import { disabledKey, nightModeKey, dropdownKey } from "./contextKeys"; import { disabledKey, nightModeKey, dropdownKey } from "./contextKeys";
export let id: string; export let id: string | undefined = undefined;
let className = ""; let className = "";
export { className as class }; export { className as class };
export let tooltip: string | undefined; export let tooltip: string | undefined = undefined;
export let active = false; export let active = false;
export let disables = true; export let disables = true;
export let tabbable = false;
let buttonRef: HTMLButtonElement; let buttonRef: HTMLButtonElement;
@ -21,9 +22,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
$: _disabled = disables && $disabled; $: _disabled = disables && $disabled;
const nightMode = getContext<boolean>(nightModeKey); const nightMode = getContext<boolean>(nightModeKey);
const dropdownProps = getContext(dropdownKey) ?? { dropdown: false };
const dropdown = getContext(dropdownKey);
const dropdownProps = dropdown?.getDropdownTriggerProps() ?? {};
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
onMount(() => dispatch("mount", { button: buttonRef })); onMount(() => dispatch("mount", { button: buttonRef }));
@ -34,6 +33,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
button { button {
padding: 0; 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; @include button.btn-day;
@ -66,13 +71,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{id} {id}
class={`btn ${className}`} class={`btn ${className}`}
class:active class:active
class:dropdown-toggle={dropdownProps.dropdown}
class:btn-day={!nightMode} class:btn-day={!nightMode}
class:btn-night={nightMode} class:btn-night={nightMode}
tabindex="-1"
title={tooltip} title={tooltip}
disabled={_disabled}
class:dropdown-toggle={Boolean(dropdown)}
{...dropdownProps} {...dropdownProps}
disabled={_disabled}
tabindex={tabbable ? 0 : -1}
on:click on:click
on:mousedown|preventDefault> on:mousedown|preventDefault>
<span class="p-1"><slot /></span> <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"> <script lang="typescript">
import type { Readable } from "svelte/store"; import type { Readable } from "svelte/store";
import { onMount, createEventDispatcher, getContext } from "svelte"; import { onMount, createEventDispatcher, getContext } from "svelte";
import { disabledKey, nightModeKey } from "./contextKeys"; import { disabledKey, nightModeKey, dropdownKey } from "./contextKeys";
export let id: string | undefined = undefined; export let id: string | undefined = undefined;
let className: string = ""; let className: string = "";
export { className as class }; export { className as class };
export let tooltip: string | undefined; export let tooltip: string | undefined;
export let dropdownToggle = false;
export let disables = true; export let disables = true;
export let tabbable = false; export let tabbable = false;
$: dropdownProps = dropdownToggle
? {
"data-bs-toggle": "dropdown",
"aria-expanded": "false",
}
: {};
const disabled = getContext<Readable<boolean>>(disabledKey); const disabled = getContext<Readable<boolean>>(disabledKey);
$: _disabled = disables && $disabled; $: _disabled = disables && $disabled;
const nightMode = getContext<boolean>(nightModeKey); const nightMode = getContext<boolean>(nightModeKey);
const dropdownProps = getContext(dropdownKey) ?? {};
let buttonRef: HTMLButtonElement; let buttonRef: HTMLButtonElement;
@ -58,7 +51,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
bind:this={buttonRef} bind:this={buttonRef}
{id} {id}
class={`btn ${className}`} class={`btn ${className}`}
class:dropdown-toggle={dropdownToggle} class:dropdown-toggle={dropdownProps.dropdown}
class:btn-day={!nightMode} class:btn-day={!nightMode}
class:btn-night={nightMode} class:btn-night={nightMode}
title={tooltip} 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"; import { dropdownKey } from "./contextKeys";
setContext(dropdownKey, { setContext(dropdownKey, {
getDropdownTriggerProps: () => ({ dropdown: true,
"data-bs-toggle": "dropdown", "data-bs-toggle": "dropdown",
"aria-expanded": "false", "aria-expanded": "false",
}),
}); });
const menuId = Math.random().toString(36).substring(2); 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"> <script lang="typescript">
import * as tr from "lib/i18n"; 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 IconButton from "components/IconButton.svelte";
import ColorPicker from "components/ColorPicker.svelte"; import ColorPicker from "components/ColorPicker.svelte";
import ButtonGroup from "components/ButtonGroup.svelte";
import WithShortcut from "components/WithShortcut.svelte"; import WithShortcut from "components/WithShortcut.svelte";
import { squareFillIcon } from "./icons"; import { squareFillIcon } from "./icons";
@ -31,6 +32,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<ButtonGroup id="color"> <ButtonGroup id="color">
<ButtonGroupItem>
<WithShortcut shortcut="F7" let:createShortcut let:shortcutLabel> <WithShortcut shortcut="F7" let:createShortcut let:shortcutLabel>
<IconButton <IconButton
class="forecolor" class="forecolor"
@ -40,11 +42,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html squareFillIcon} {@html squareFillIcon}
</IconButton> </IconButton>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="F8" let:createShortcut let:shortcutLabel> <WithShortcut shortcut="F8" let:createShortcut let:shortcutLabel>
<ColorPicker <ColorPicker
tooltip={`${tr.editingChangeColor()} (${shortcutLabel})`} tooltip={`${tr.editingChangeColor()} (${shortcutLabel})`}
on:change={setWithCurrentColor} on:change={setWithCurrentColor}
on:mount={createShortcut} /> on:mount={createShortcut} />
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
</ButtonGroup> </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 type { EditingArea } from "./editingArea";
import * as tr from "lib/i18n"; import * as tr from "lib/i18n";
import IconButton from "components/IconButton.svelte";
import ButtonGroup from "components/ButtonGroup.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 ButtonDropdown from "components/ButtonDropdown.svelte";
import WithState from "components/WithState.svelte"; import WithState from "components/WithState.svelte";
import WithDropdownMenu from "components/WithDropdownMenu.svelte"; import WithDropdownMenu from "components/WithDropdownMenu.svelte";
@ -43,6 +44,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<ButtonGroup id="blockFormatting" {api}> <ButtonGroup id="blockFormatting" {api}>
<ButtonGroupItem>
<WithState <WithState
key="insertUnorderedList" key="insertUnorderedList"
update={() => document.queryCommandState('insertUnorderedList')} update={() => document.queryCommandState('insertUnorderedList')}
@ -58,7 +60,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html ulIcon} {@html ulIcon}
</IconButton> </IconButton>
</WithState> </WithState>
</ButtonGroupItem>
<ButtonGroupItem>
<WithState <WithState
key="insertOrderedList" key="insertOrderedList"
update={() => document.queryCommandState('insertOrderedList')} update={() => document.queryCommandState('insertOrderedList')}
@ -74,14 +78,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html olIcon} {@html olIcon}
</IconButton> </IconButton>
</WithState> </WithState>
</ButtonGroupItem>
<WithDropdownMenu let:createDropdown let:menuId> <WithDropdownMenu let:createDropdown let:menuId>
<ButtonGroupItem>
<IconButton on:mount={createDropdown}> <IconButton on:mount={createDropdown}>
{@html listOptionsIcon} {@html listOptionsIcon}
</IconButton> </IconButton>
</ButtonGroupItem>
<ButtonDropdown id={menuId}> <ButtonDropdown id={menuId}>
<ButtonGroup id="justify" {api}> <ButtonGroup id="justify" {api}>
<ButtonGroupItem>
<WithState <WithState
key="justifyLeft" key="justifyLeft"
update={() => document.queryCommandState('justifyLeft')} update={() => document.queryCommandState('justifyLeft')}
@ -97,7 +105,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html justifyLeftIcon} {@html justifyLeftIcon}
</IconButton> </IconButton>
</WithState> </WithState>
</ButtonGroupItem>
<ButtonGroupItem>
<WithState <WithState
key="justifyCenter" key="justifyCenter"
update={() => document.queryCommandState('justifyCenter')} update={() => document.queryCommandState('justifyCenter')}
@ -113,7 +123,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html justifyCenterIcon} {@html justifyCenterIcon}
</IconButton> </IconButton>
</WithState> </WithState>
</ButtonGroupItem>
<ButtonGroupItem>
<WithState <WithState
key="justifyRight" key="justifyRight"
update={() => document.queryCommandState('justifyRight')} update={() => document.queryCommandState('justifyRight')}
@ -129,7 +141,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html justifyRightIcon} {@html justifyRightIcon}
</IconButton> </IconButton>
</WithState> </WithState>
</ButtonGroupItem>
<ButtonGroupItem>
<WithState <WithState
key="justifyFull" key="justifyFull"
update={() => document.queryCommandState('justifyFull')} update={() => document.queryCommandState('justifyFull')}
@ -145,16 +159,23 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html justifyFullIcon} {@html justifyFullIcon}
</IconButton> </IconButton>
</WithState> </WithState>
</ButtonGroupItem>
</ButtonGroup> </ButtonGroup>
<ButtonGroup id="indentation" {api}> <ButtonGroup id="indentation" {api}>
<IconButton on:click={outdentListItem} tooltip={tr.editingOutdent()}> <ButtonGroupItem>
<IconButton
on:click={outdentListItem}
tooltip={tr.editingOutdent()}>
{@html outdentIcon} {@html outdentIcon}
</IconButton> </IconButton>
</ButtonGroupItem>
<ButtonGroupItem>
<IconButton on:click={indentListItem} tooltip={tr.editingIndent()}> <IconButton on:click={indentListItem} tooltip={tr.editingIndent()}>
{@html indentIcon} {@html indentIcon}
</IconButton> </IconButton>
</ButtonGroupItem>
</ButtonGroup> </ButtonGroup>
</ButtonDropdown> </ButtonDropdown>
</WithDropdownMenu> </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 * as tr from "lib/i18n";
import ButtonGroup from "components/ButtonGroup.svelte"; import ButtonGroup from "components/ButtonGroup.svelte";
import ButtonGroupItem from "components/ButtonGroupItem.svelte";
import IconButton from "components/IconButton.svelte"; import IconButton from "components/IconButton.svelte";
import WithState from "components/WithState.svelte"; import WithState from "components/WithState.svelte";
import WithShortcut from "components/WithShortcut.svelte"; import WithShortcut from "components/WithShortcut.svelte";
@ -23,6 +24,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<ButtonGroup id="notetype" {api}> <ButtonGroup id="notetype" {api}>
<ButtonGroupItem>
<WithShortcut shortcut="Control+KeyB" let:createShortcut let:shortcutLabel> <WithShortcut shortcut="Control+KeyB" let:createShortcut let:shortcutLabel>
<WithState <WithState
key="bold" key="bold"
@ -41,7 +43,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</IconButton> </IconButton>
</WithState> </WithState>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="Control+KeyI" let:createShortcut let:shortcutLabel> <WithShortcut shortcut="Control+KeyI" let:createShortcut let:shortcutLabel>
<WithState <WithState
key="italic" key="italic"
@ -60,7 +64,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</IconButton> </IconButton>
</WithState> </WithState>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="Control+KeyU" let:createShortcut let:shortcutLabel> <WithShortcut shortcut="Control+KeyU" let:createShortcut let:shortcutLabel>
<WithState <WithState
key="underline" key="underline"
@ -79,8 +85,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</IconButton> </IconButton>
</WithState> </WithState>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
<WithShortcut shortcut="Control+Shift+Equal" let:createShortcut let:shortcutLabel> <ButtonGroupItem>
<WithShortcut
shortcut="Control+Shift+Equal"
let:createShortcut
let:shortcutLabel>
<WithState <WithState
key="superscript" key="superscript"
update={() => document.queryCommandState('superscript')} update={() => document.queryCommandState('superscript')}
@ -98,7 +109,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</IconButton> </IconButton>
</WithState> </WithState>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="Control+Equal" let:createShortcut let:shortcutLabel> <WithShortcut shortcut="Control+Equal" let:createShortcut let:shortcutLabel>
<WithState <WithState
key="subscript" key="subscript"
@ -117,7 +130,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</IconButton> </IconButton>
</WithState> </WithState>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="Control+KeyR" let:createShortcut let:shortcutLabel> <WithShortcut shortcut="Control+KeyR" let:createShortcut let:shortcutLabel>
<IconButton <IconButton
tooltip={tr.editingRemoveFormatting()} tooltip={tr.editingRemoveFormatting()}
@ -128,4 +143,5 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html eraserIcon} {@html eraserIcon}
</IconButton> </IconButton>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
</ButtonGroup> </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 * as tr from "lib/i18n";
import { bridgeCommand } from "lib/bridgecommand"; import { bridgeCommand } from "lib/bridgecommand";
import IconButton from "components/IconButton.svelte";
import ButtonGroup from "components/ButtonGroup.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 DropdownMenu from "components/DropdownMenu.svelte";
import DropdownItem from "components/DropdownItem.svelte"; import DropdownItem from "components/DropdownItem.svelte";
import WithDropdownMenu from "components/WithDropdownMenu.svelte"; import WithDropdownMenu from "components/WithDropdownMenu.svelte";
@ -32,14 +33,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<ButtonGroup id="template"> <ButtonGroup id="template">
<ButtonGroupItem>
<WithShortcut shortcut="F3" let:createShortcut let:shortcutLabel> <WithShortcut shortcut="F3" let:createShortcut let:shortcutLabel>
<IconButton <IconButton
tooltip={appendInParentheses(tr.editingAttachPicturesaudiovideo(), shortcutLabel)} tooltip={appendInParentheses(tr.editingAttachPicturesaudiovideo(), shortcutLabel)}
on:click={onAttachment}> on:click={onAttachment}
on:mount={createShortcut}>
{@html paperclipIcon} {@html paperclipIcon}
</IconButton> </IconButton>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<WithShortcut shortcut="F5" let:createShortcut let:shortcutLabel> <WithShortcut shortcut="F5" let:createShortcut let:shortcutLabel>
<IconButton <IconButton
tooltip={appendInParentheses(tr.editingRecordAudio(), shortcutLabel)} tooltip={appendInParentheses(tr.editingRecordAudio(), shortcutLabel)}
@ -47,13 +52,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html micIcon} {@html micIcon}
</IconButton> </IconButton>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
<ButtonGroupItem>
<ClozeButton /> <ClozeButton />
</ButtonGroupItem>
<WithDropdownMenu let:menuId let:createDropdown> <WithDropdownMenu let:menuId let:createDropdown>
<ButtonGroupItem>
<IconButton on:mount={createDropdown}> <IconButton on:mount={createDropdown}>
{@html functionIcon} {@html functionIcon}
</IconButton> </IconButton>
</ButtonGroupItem>
<DropdownMenu id={menuId}> <DropdownMenu id={menuId}>
<WithShortcut <WithShortcut
@ -112,7 +122,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</DropdownMenu> </DropdownMenu>
</WithDropdownMenu> </WithDropdownMenu>
<WithShortcut shortcut="Control+Shift+KeyX" let:createShortcut let:shortcutLabel> <ButtonGroupItem>
<WithShortcut
shortcut="Control+Shift+KeyX"
let:createShortcut
let:shortcutLabel>
<IconButton <IconButton
tooltip={appendInParentheses(tr.editingHtmlEditor(), shortcutLabel)} tooltip={appendInParentheses(tr.editingHtmlEditor(), shortcutLabel)}
on:click={onHtmlEdit} on:click={onHtmlEdit}
@ -120,4 +134,5 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{@html xmlIcon} {@html xmlIcon}
</IconButton> </IconButton>
</WithShortcut> </WithShortcut>
</ButtonGroupItem>
</ButtonGroup> </ButtonGroup>