Redesign deck options inputs (#2082)

* Create _input-mixins.scss

* Use button-mixins on more elements

* Replace <select> tag with custom Select component

* Fix RevertButton causing cursor: pointer when hidden

* Increase SaveButton chevron width

* Hide floating component box-shadow when inactive

* Rework SpinBox and move it into components

* Run eslint and prettier

* Remove leftover options prop

* Pass disabled array to EnumSelector again

* Update MapperRow.svelte

* Darken QHeaderView border color

Slipping this in without an extra PR.

* Adjust disabled color, border and cursor

* Remove redundant icon definition from stylesheets

* Fix deck options initial config

* Fix z-index issues in change notetype screen

It might be best to handle z-index locally in each user component instead of hard-coded component values.

* Give web SpinBox a horizontal design

* Give QRadioButton the same treatment as QCheckBox in #2079

* Fix unused CSS selector warning with base button-mixin

* Remove redundant import

* Fix deck options save button

* Delete input-mixins and remove unused down-arrow

* Run eslint on change-notetype

* Run eslint on components
This commit is contained in:
Matthias Metelka 2022-09-27 04:16:45 +02:00 committed by GitHub
parent 6a7f2d8a79
commit 23e6b2123e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 596 additions and 505 deletions

View file

@ -353,6 +353,7 @@ class AnkiApp(QApplication):
(
QPushButton,
QCheckBox,
QRadioButton,
# classes with PyQt5 compatibility proxy
without_qt5_compat_wrapper(QToolButton),
without_qt5_compat_wrapper(QTabBar),

View file

@ -16,42 +16,42 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<item row="3" column="0" alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="radioAhead">
<property name="text">
<string>custom_study_review_ahead</string>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="2" column="0" alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="radioForgot">
<property name="text">
<string>custom_study_review_forgotten_cards</string>
</property>
</widget>
</item>
<item row="0" column="0">
<item row="0" column="0" alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="radioNew">
<property name="text">
<string>custom_study_increase_todays_new_card_limit</string>
</property>
</widget>
</item>
<item row="1" column="0">
<item row="1" column="0" alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="radioRev">
<property name="text">
<string>custom_study_increase_todays_review_card_limit</string>
</property>
</widget>
</item>
<item row="5" column="0">
<item row="5" column="0" alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="radioCram">
<property name="text">
<string>custom_study_study_by_card_state_or_tag</string>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="4" column="0" alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="radioPreview">
<property name="text">
<string>custom_study_preview_new_cards</string>

View file

@ -155,7 +155,7 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="2" column="1" alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="sortField">
<property name="text">
<string>fields_sort_by_this_field_in_the</string>

View file

@ -34,7 +34,7 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="preview_front">
<property name="text">
<string notr="true">FRONT</string>
@ -44,7 +44,7 @@
</property>
</widget>
</item>
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="preview_back">
<property name="text">
<string notr="true">BACK</string>

View file

@ -74,7 +74,7 @@
<string/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="groups">
<property name="text">
<string notr="true">deck</string>
@ -84,7 +84,7 @@
</property>
</widget>
</item>
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="all">
<property name="text">
<string notr="true">collection</string>
@ -100,7 +100,7 @@
<string/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="month">
<property name="text">
<string notr="true">1 month</string>
@ -110,14 +110,14 @@
</property>
</widget>
</item>
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="year">
<property name="text">
<string notr="true">1 year</string>
</property>
</widget>
</item>
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="life">
<property name="text">
<string notr="true">deck life</string>

View file

@ -52,7 +52,7 @@
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="front_button">
<property name="toolTip">
<string notr="true"/>
@ -65,7 +65,7 @@
</property>
</widget>
</item>
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="back_button">
<property name="toolTip">
<string notr="true"/>
@ -75,7 +75,7 @@
</property>
</widget>
</item>
<item>
<item alignment="Qt::AlignLeft">
<widget class="QRadioButton" name="style_button">
<property name="toolTip">
<string notr="true"/>

View file

@ -233,7 +233,7 @@ QHeaderView {{
background: {tm.var(colors.CANVAS)};
}}
QHeaderView::section {{
border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
border: 1px solid {tm.var(colors.BORDER)};
background: {
button_gradient(
tm.var(colors.BUTTON_GRADIENT_START),
@ -261,19 +261,19 @@ QHeaderView::section:hover {{
};
}}
QHeaderView::section:first {{
border-left: 1px solid {tm.var(colors.BORDER_SUBTLE)};
border-left: 1px solid {tm.var(colors.BORDER)};
border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
}}
QHeaderView::section:!first {{
border-left: none;
}}
QHeaderView::section:last {{
border-right: 1px solid {tm.var(colors.BORDER_SUBTLE)};
border-right: 1px solid {tm.var(colors.BORDER)};
border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
}}
QHeaderView::section:only-one {{
border-left: 1px solid {tm.var(colors.BORDER_SUBTLE)};
border-right: 1px solid {tm.var(colors.BORDER_SUBTLE)};
border-left: 1px solid {tm.var(colors.BORDER)};
border-right: 1px solid {tm.var(colors.BORDER)};
border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
}}
@ -368,24 +368,34 @@ QSpinBox::down-arrow:off {{
def checkbox_styles(tm: ThemeManager) -> str:
return f"""
QCheckBox {{
QCheckBox,
QRadioButton {{
spacing: 8px;
margin: 2px 0;
}}
QCheckBox::indicator {{
QCheckBox::indicator,
QRadioButton::indicator {{
border: 1px solid {tm.var(colors.BUTTON_BORDER)};
border-radius: {tm.var(props.BORDER_RADIUS)};
background: {tm.var(colors.CANVAS_INSET)};
width: 16px;
height: 16px;
}}
QCheckBox::indicator {{
border-radius: {tm.var(props.BORDER_RADIUS)};
}}
QRadioButton::indicator {{
border-radius: 8px;
}}
QCheckBox::indicator:hover,
QCheckBox::indicator:checked:hover {{
QCheckBox::indicator:checked:hover,
QRadioButton::indicator:hover,
QRadioButton::indicator:checked:hover {{
border: 2px solid {tm.var(colors.BORDER_STRONG)};
width: 14px;
height: 14px;
}}
QCheckBox::indicator:checked {{
QCheckBox::indicator:checked,
QRadioButton::indicator:checked {{
image: url({tm.themed_icon("mdi:check")});
}}
QCheckBox::indicator:indeterminate {{

View file

@ -11,7 +11,7 @@
rgba(black, $intensity);
}
@mixin btn-border-radius {
@mixin border-radius {
border-top-left-radius: var(--border-left-radius);
border-bottom-left-radius: var(--border-left-radius);
@ -19,75 +19,100 @@
border-bottom-right-radius: var(--border-right-radius);
}
@mixin base(
$selector: button,
$with-primary: false,
$with-hover: true,
$with-active: true,
$with-disabled: true
) {
#{$selector} {
-webkit-appearance: none;
border: 1px solid var(--button-border);
color: var(--fg);
@mixin background($primary: false) {
@if $primary {
background: linear-gradient(
180deg,
var(--button-primary-gradient-start) 0%,
var(--button-primary-gradient-end) 100%
);
&:hover {
background: linear-gradient(
180deg,
var(--button-primary-hover-gradient-start) 0%,
var(--button-primary-hover-gradient-end) 100%
);
border-color: var(--button-hover-border);
}
} @else {
background: linear-gradient(
180deg,
var(--button-gradient-start) 0%,
var(--button-gradient-end) 100%
);
@if ($with-hover) {
&:hover {
background: linear-gradient(
180deg,
var(--button-hover-gradient-start) 0%,
var(--button-hover-gradient-end) 100%
);
border-color: var(--button-hover-border);
}
}
@if ($with-primary) {
&.btn-primary {
color: white;
background: linear-gradient(
180deg,
var(--button-primary-gradient-start) 0%,
var(--button-primary-gradient-end) 100%
);
&:hover {
background: linear-gradient(
180deg,
var(--button-primary-hover-gradient-start) 0%,
var(--button-primary-hover-gradient-end) 100%
);
}
}
}
@if ($with-active) {
&:active {
@include impressed-shadow(0.35);
box-shadow: none;
border-color: var(--button-border);
}
}
@if ($with-disabled) {
&[disabled] {
color: var(--fg-disabled);
background-color: var(--button-gradient-end) !important;
box-shadow: none !important;
border-color: var(--button-gradient-end) !important;
}
&:hover {
background: linear-gradient(
180deg,
var(--button-hover-gradient-start) 0%,
var(--button-hover-gradient-end) 100%
);
border-color: var(--button-hover-border);
}
}
}
$focus-color: vars.color(shadow-focus);
@mixin base(
$primary: false,
$border: true,
$with-hover: true,
$with-active: true,
$active-class: "",
$with-disabled: true
) {
-webkit-appearance: none;
cursor: pointer;
@if $border {
border: 1px solid var(--button-border);
} @else {
border: none;
}
@include background($primary);
@function down-arrow($color) {
@return url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='transparent' stroke='#{$color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
@if ($primary) {
color: white;
} @else {
color: var(--fg);
}
@if ($with-active) {
&:active {
@include impressed-shadow(0.35);
border-color: var(--button-border);
}
@if ($active-class != "") {
&.#{$active-class} {
@include impressed-shadow(0.35);
border-color: var(--button-border);
}
}
}
@if ($with-disabled) {
&[disabled],
&[disabled]:hover {
cursor: not-allowed;
color: var(--fg-disabled);
box-shadow: none !important;
background-color: var(--button-gradient-end);
}
}
}
$focus-color: var(--shadow-focus);
@mixin select($with-disabled: true) {
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
pointer-events: all;
cursor: pointer;
@include base($with-disabled: $with-disabled);
border-radius: var(--border-radius);
&.rtl {
direction: rtl;
}
}

View file

@ -34,8 +34,8 @@ $vars: (
dark: palette(lightgray, 3),
),
disabled: (
light: palette(darkgray, 2),
dark: palette(lightgray, 8),
light: palette(lightgray, 9),
dark: palette(darkgray, 0),
),
faint: (
light: palette(lightgray, 7),

View file

@ -1,5 +1,6 @@
@use "vars";
@use "scrollbar";
@use "button-mixins" as button;
$body-color: var(--fg);
$body-bg: var(--canvas);
@ -79,6 +80,11 @@ samp {
background-position: left 0.75rem center;
}
}
.form-select:focus {
outline: none;
border: 1px solid var(--border-focus);
box-shadow: none !important;
}
.night-mode .form-select:disabled {
background-color: var(--fg-disabled);
@ -88,3 +94,20 @@ samp {
transition: none !important;
animation: none !important;
}
select {
@include button.background;
@include button.border-radius;
cursor: pointer;
outline: none;
&:focus,
&.focus {
border: 1px solid var(--border-focus);
}
option {
background: var(--canvas-elevated);
color: var(--fg);
}
}

View file

@ -1,4 +1,5 @@
@use "vars";
@use "button-mixins" as button;
:root {
--focus-color: #{vars.palette-of(shadow-focus)};
@ -21,30 +22,7 @@
}
button {
-webkit-appearance: none;
color: vars.color(fg);
cursor: pointer;
background: linear-gradient(
180deg,
vars.color(button-gradient-start) 0%,
vars.color(button-gradient-end) 100%
);
border: 1px solid vars.color(button-border);
border-radius: vars.prop(border-radius);
@include button.base;
border-radius: var(--border-radius);
padding: 3px 10px 3px;
&:focus {
outline: none;
box-shadow: 0 0 0 1px var(--focus-color);
}
}
button:hover {
background: linear-gradient(
180deg,
vars.color(button-hover-gradient-start) 0%,
vars.color(button-hover-gradient-end) 100%
);
}

View file

@ -8,6 +8,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import Col from "../components/Col.svelte";
import Container from "../components/Container.svelte";
import Row from "../components/Row.svelte";
import StickyContainer from "../components/StickyContainer.svelte";
import * as tr from "../lib/ftl";
import { ChangeNotetypeState, MapContext } from "./lib";
import Mapper from "./Mapper.svelte";
@ -20,20 +21,27 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<div bind:offsetHeight={offset}>
<NotetypeSelector {state} />
<StickyContainer
--gutter-block="0.1rem"
--gutter-inline="0.25rem"
--sticky-borders="0 0 1px"
--z-index="4"
>
<NotetypeSelector {state} />
</StickyContainer>
</div>
<div id="scrollArea" style="--offset: {offset}px; --gutter-inline: 0.25rem;">
<Row class="gx-0" --cols={2}>
<Col --col-size={1} breakpoint="md">
<Container>
<StickyHeader {state} ctx={MapContext.Field} />
<StickyHeader {state} ctx={MapContext.Field} --z-index="2" />
<Mapper {state} ctx={MapContext.Field} />
</Container>
</Col>
<Col --col-size={1} breakpoint="md">
<Container>
<StickyHeader {state} ctx={MapContext.Template} />
<StickyHeader {state} ctx={MapContext.Template} --z-index="2" />
{#if $info.templates}
<Mapper {state} ctx={MapContext.Template} />
{:else}

View file

@ -5,6 +5,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import Col from "../components/Col.svelte";
import Row from "../components/Row.svelte";
import Select from "../components/Select.svelte";
import SelectOption from "../components/SelectOption.svelte";
import type { ChangeNotetypeState, MapContext } from "./lib";
export let state: ChangeNotetypeState;
@ -13,24 +15,20 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const info = state.info;
function onChange(evt: Event) {
const oldIdx = parseInt((evt.target as HTMLSelectElement).value, 10);
state.setOldIndex(ctx, newIndex, oldIdx);
}
let oldIndex = $info.getOldIndex(ctx, newIndex);
const options = $info.getOldNamesIncludingNothing(ctx);
$: state.setOldIndex(ctx, newIndex, oldIndex);
</script>
<Row --cols={2}>
<Col --col-size={1}>
<!-- svelte-ignore a11y-no-onchange -->
<select
value={$info.getOldIndex(ctx, newIndex)}
class="form-select"
on:change={onChange}
>
{#each $info.getOldNamesIncludingNothing(ctx) as name, idx}
<option value={idx}>{name}</option>
<Select current={options[oldIndex]}>
{#each options as name, idx}
<SelectOption on:select={() => (oldIndex = idx)}>{name}</SelectOption>
{/each}
</select>
</Select>
</Col>
<Col --col-size={1}>
{$info.getNewName(ctx, newIndex)}

View file

@ -7,9 +7,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import ButtonGroup from "../components/ButtonGroup.svelte";
import ButtonToolbar from "../components/ButtonToolbar.svelte";
import LabelButton from "../components/LabelButton.svelte";
import SelectButton from "../components/SelectButton.svelte";
import Select from "../components/Select.svelte";
import SelectOption from "../components/SelectOption.svelte";
import StickyContainer from "../components/StickyContainer.svelte";
import { arrowLeftIcon, arrowRightIcon } from "./icons";
import type { ChangeNotetypeState } from "./lib";
import SaveButton from "./SaveButton.svelte";
@ -17,40 +16,30 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export let state: ChangeNotetypeState;
const notetypes = state.notetypes;
const info = state.info;
let value: number = 0;
async function blur(event: Event): Promise<void> {
await state.setTargetNotetypeIndex(
parseInt((event.target! as HTMLSelectElement).value),
);
}
$: state.setTargetNotetypeIndex(value);
$: options = Array.from($notetypes, (notetype) => notetype.name);
</script>
<StickyContainer
--gutter-block="0.1rem"
--gutter-inline="0.25rem"
--sticky-borders="0 0 1px"
>
<ButtonToolbar class="justify-content-between" size={2.3} wrap={false}>
<LabelButton disabled={true}>
{$info.oldNotetypeName}
</LabelButton>
<Badge iconSize={70}>
{#if window.getComputedStyle(document.body).direction == "rtl"}
{@html arrowLeftIcon}
{:else}
{@html arrowRightIcon}
{/if}
</Badge>
<ButtonGroup class="flex-grow-1">
<SelectButton class="flex-grow-1" on:change={blur}>
{#each $notetypes as entry}
<SelectOption value={String(entry.idx)} selected={entry.current}>
{entry.name}
</SelectOption>
{/each}
</SelectButton>
</ButtonGroup>
<ButtonToolbar class="justify-content-between" size={2.3} wrap={false}>
<LabelButton disabled={true}>
{$info.oldNotetypeName}
</LabelButton>
<Badge iconSize={70}>
{#if window.getComputedStyle(document.body).direction == "rtl"}
{@html arrowLeftIcon}
{:else}
{@html arrowRightIcon}
{/if}
</Badge>
<ButtonGroup class="flex-grow-1">
<Select class="flex-grow-1" current={options[value]}>
{#each options as option, idx}
<SelectOption on:select={() => (value = idx)}>{option}</SelectOption>
{/each}
</Select>
</ButtonGroup>
<SaveButton {state} />
</ButtonToolbar>
</StickyContainer>
<SaveButton {state} />
</ButtonToolbar>

View file

@ -24,7 +24,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<ButtonGroup>
<LabelButton
theme="primary"
primary
tooltip={getPlatformString(keyCombination)}
on:click={save}
--border-left-radius="5px"

View file

@ -27,8 +27,3 @@ html {
padding: 0.5em 0.5em 1em 0.5em;
height: 100vh;
}
// override the default down arrow colour in <select> elements
.night-mode select {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23FFFFFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
}

View file

@ -11,6 +11,7 @@ _ts_deps = [
"@npm//@floating-ui/dom",
"@npm//bootstrap",
"@npm//svelte",
"@npm//@mdi",
]
compile_svelte(

View file

@ -3,17 +3,16 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import { pageTheme } from "../sveltelib/theme";
export let id: string | undefined = undefined;
let className = "";
export { className as class };
let buttonRef: HTMLButtonElement;
export let buttonRef: HTMLButtonElement | undefined = undefined;
export let tooltip: string | undefined = undefined;
export let active = false;
export let disabled = false;
$: if (buttonRef && active) {
/* buttonRef.scrollIntoView({ behavior: "smooth", block: "start" }); */
@ -33,8 +32,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
tabindex={tabbable ? 0 : -1}
class="dropdown-item {className}"
class:active
class:btn-day={!$pageTheme.isDark}
class:btn-night={$pageTheme.isDark}
class:disabled
title={tooltip}
on:mouseenter
on:focus
@ -46,11 +44,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</button>
<style lang="scss">
@use "sass/button-mixins" as button;
button {
display: flex;
justify-content: start;
width: 100%;
font-size: var(--dropdown-font-size, calc(0.8 * var(--base-font-size)));
@ -58,19 +55,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
box-shadow: none !important;
border: none;
border-radius: 0;
color: var(--fg);
&:active,
&.active {
background-color: button.$focus-color;
color: white;
&:hover {
background: var(--highlight-bg);
color: var(--highlight-fg);
}
}
.btn-day {
color: black;
}
.btn-night {
color: white;
}
</style>

View file

@ -3,7 +3,6 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import { pageTheme } from "../sveltelib/theme";
import IconConstrain from "./IconConstrain.svelte";
export let id: string | undefined = undefined;
@ -11,6 +10,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export { className as class };
export let tooltip: string | undefined = undefined;
export let primary = false;
export let active = false;
export let disabled = false;
export let tabbable = false;
@ -22,10 +22,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<button
{id}
class="icon-button btn {className}"
class="icon-button {className}"
class:active
class:btn-day={!$pageTheme.isDark}
class:btn-night={$pageTheme.isDark}
class:primary
title={tooltip}
{disabled}
tabindex={tabbable ? 0 : -1}
@ -41,12 +40,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
@use "sass/button-mixins" as button;
.icon-button {
@include button.base($active-class: active);
&.primary {
@include button.base($primary: true);
}
@include button.border-radius;
padding: 0;
font-size: var(--base-font-size);
height: var(--buttons-size);
@include button.btn-border-radius;
min-width: calc(var(--buttons-size) * 0.75);
}
@include button.base(".icon-button");
</style>

View file

@ -22,7 +22,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
vertical-align: var(--icon-align, middle);
/* constrain icon */
width: calc((var(--buttons-size, 22px) - 2px) * var(--width-multiplier));
min-width: calc((var(--buttons-size, 22px) - 2px) * var(--width-multiplier));
height: calc(var(--buttons-size, 22px) - 2px);
& > :global(svg),

View file

@ -5,16 +5,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import { createEventDispatcher, onMount } from "svelte";
import { pageTheme } from "../sveltelib/theme";
export let id: string | undefined = undefined;
let className: string = "";
export { className as class };
export let theme = "anki";
function extendClassName(className: string, theme: string): string {
return `btn ${theme !== "anki" ? `btn-${theme}` : ""}${className}`;
}
export let primary = false;
export let tooltip: string | undefined = undefined;
export let active = false;
@ -30,10 +24,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<button
bind:this={buttonRef}
{id}
class="label-button {extendClassName(className, theme)}"
class="label-button {className}"
class:active
class:btn-day={theme === "anki" && !$pageTheme.isDark}
class:btn-night={theme === "anki" && $pageTheme.isDark}
class:primary
title={tooltip}
{disabled}
tabindex={tabbable ? 0 : -1}
@ -47,6 +40,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
@use "sass/button-mixins" as button;
button {
@include button.base($active-class: active);
&.primary {
@include button.base($primary: true);
}
@include button.border-radius;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@ -54,9 +53,5 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
font-size: var(--base-font-size);
width: auto;
height: var(--buttons-size);
@include button.btn-border-radius;
}
@include button.base($with-primary: true);
</style>

View file

@ -2,19 +2,29 @@
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script>
<script lang="ts">
import { slide } from "svelte/transition";
import { pageTheme } from "../sveltelib/theme";
export let scrollable = false;
</script>
<div class="popover" class:dark={$pageTheme.isDark} on:mousedown|preventDefault>
<div
class="popover"
class:scrollable
class:dark={$pageTheme.isDark}
transition:slide={{ duration: 200 }}
>
<slot />
</div>
<style lang="scss">
@use "sass/vars";
.popover {
border-radius: 5px;
background-color: var(--canvas-elevated);
min-width: 1rem;
min-width: var(--popover-width, 1rem);
max-width: 95vw;
/* Needs this much space for FloatingArrow to be positioned */
@ -24,17 +34,21 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
color: var(--fg);
/* outer border */
border: 1px solid #b6b6b6;
border: 1px solid vars.palette(lightgray, 6);
&.dark {
border-color: #060606;
border-color: vars.palette(darkgray, 9);
}
/* inner border */
box-shadow: inset 0 0 0 1px #eeeeee;
box-shadow: inset 0 0 0 1px vars.palette(lightgray, 3);
&.dark {
box-shadow: inset 0 0 0 1px #565656;
box-shadow: inset 0 0 0 1px vars.palette(darkgray, 2);
}
&.scrollable {
max-height: 80vh;
overflow: hidden auto;
}
}
</style>

View file

@ -0,0 +1,86 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import IconConstrain from "./IconConstrain.svelte";
import { chevronDown } from "./icons";
import Popover from "./Popover.svelte";
import WithFloating from "./WithFloating.svelte";
export let id: string | undefined = undefined;
let className = "";
export { className as class };
export let disabled = false;
export let current: string = "";
export let tooltip: string | undefined = undefined;
const rtl: boolean = window.getComputedStyle(document.body).direction == "rtl";
export let element: HTMLElement | undefined = undefined;
let hover = false;
let showFloating = false;
let clientWidth: number;
</script>
<WithFloating
show={showFloating}
placement="bottom"
offset={0}
hideArrow
inline
closeOnInsideClick
on:close={() => (showFloating = false)}
let:asReference
>
<div
{id}
class="{className} select-container"
class:rtl
class:hover
{disabled}
title={tooltip}
tabindex="-1"
on:mouseenter={() => (hover = true)}
on:mouseleave={() => (hover = false)}
on:click={() => (showFloating = !showFloating)}
bind:this={element}
use:asReference
bind:clientWidth
>
{current}
<div class="chevron">
<IconConstrain iconSize={80}>
{@html chevronDown}
</IconConstrain>
</div>
</div>
<Popover slot="floating" scrollable --popover-width="{clientWidth}px">
<slot />
</Popover>
</WithFloating>
<style lang="scss">
@use "sass/button-mixins" as button;
.select-container {
@include button.select($with-disabled: false);
padding: 0.2rem 2rem 0.2rem 0.75rem;
line-height: 1.5;
height: var(--buttons-size, 100%);
position: relative;
}
.chevron {
position: absolute;
inset: 0 0 0 auto;
border-left: 1px solid var(--button-border);
}
:global([dir="rtl"]) {
.chevron {
inset: 0 auto 0 0;
border-left: none;
border-right: 1px solid var(--button-border);
}
}
</style>

View file

@ -1,82 +0,0 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import { createEventDispatcher, onMount } from "svelte";
import { pageTheme } from "../sveltelib/theme";
const rtl: boolean = window.getComputedStyle(document.body).direction == "rtl";
export let id: string | undefined = undefined;
let className = "";
export { className as class };
export let tooltip: string | undefined = undefined;
export let disabled = false;
let buttonRef: HTMLSelectElement;
const dispatch = createEventDispatcher();
onMount(() => dispatch("mount", { button: buttonRef }));
</script>
<!-- svelte-ignore a11y-no-onchange -->
<select
tabindex="-1"
bind:this={buttonRef}
{id}
{disabled}
class="{className} form-select"
class:btn-day={!$pageTheme.isDark}
class:btn-night={$pageTheme.isDark}
class:rtl
title={tooltip}
on:change
>
<slot />
</select>
<div class="arrow" class:dark={$pageTheme.isDark} class:rtl />
<style lang="scss">
@use "sass/button-mixins" as button;
@include button.base($selector: "select", $with-hover: false);
select {
height: var(--buttons-size);
/* Long option name can create overflow */
text-overflow: ellipsis;
/* Prevents text getting cropped on Windows */
padding: {
top: 0;
bottom: 0;
}
&.rtl {
direction: rtl;
/* Reversed Bootstrap values */
padding-left: 2.25rem;
padding-right: 0.75rem;
}
&.btn-day {
/* Hide default arrow for consistency */
background: var(--canvas-elevated);
}
}
.arrow {
top: 0;
right: 10px;
&.rtl {
left: 10px;
}
width: 15px;
height: 100%;
position: absolute;
pointer-events: none;
background: button.down-arrow(black) no-repeat right;
&.dark {
background-image: button.down-arrow(white);
}
}
</style>

View file

@ -3,16 +3,22 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
export let value: string | undefined = undefined;
export let selected = false;
import { createEventDispatcher } from "svelte";
import DropdownItem from "./DropdownItem.svelte";
export let disabled = false;
const dispatch = createEventDispatcher();
let element: HTMLButtonElement;
function onSelect(): void {
if (!disabled) {
dispatch("select");
}
}
</script>
<option class="select-option" {value} {selected}>
<DropdownItem {disabled} on:click={onSelect} bind:buttonRef={element}>
<slot />
</option>
<style lang="scss">
.select-option {
background-color: var(--canvas-elevated);
}
</style>
</DropdownItem>

View file

@ -0,0 +1,135 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import IconConstrain from "./IconConstrain.svelte";
import { chevronLeft, chevronRight } from "./icons";
export let value = 1;
export let step = 1;
export let min = 1;
export let max = 9999;
const rtl: boolean = window.getComputedStyle(document.body).direction == "rtl";
let input: HTMLInputElement;
let focused = false;
function decimalPlaces(value: number) {
if (Math.floor(value) === value) return 0;
return value.toString().split(".")[1].length || 0;
}
let stringValue: string;
$: stringValue = value.toFixed(decimalPlaces(step));
function update(this: HTMLInputElement): void {
value = Math.min(max, Math.max(min, parseFloat(this.value)));
if (value > max) {
value = max;
} else if (value < min) {
value = min;
}
}
function handleWheel(event: WheelEvent) {
if (focused) {
value += event.deltaY < 0 ? step : -step;
event.preventDefault();
}
}
</script>
<div class="spin-box" on:wheel={handleWheel}>
<button
class="left"
disabled={rtl ? value == max : value == min}
on:click={() => {
input.focus();
if (rtl && value < max) {
value += step;
} else if (value > min) {
value -= step;
}
}}
>
<IconConstrain>
{@html chevronLeft}
</IconConstrain>
</button>
<input
type="number"
pattern="[0-9]*"
inputmode="numeric"
{min}
{max}
{step}
value={stringValue}
bind:this={input}
on:blur={update}
on:focusin={() => (focused = true)}
on:focusout={() => (focused = false)}
/>
<button
class="right"
disabled={rtl ? value == min : value == max}
on:click={() => {
input.focus();
if (rtl && value > min) {
value -= step;
} else if (value < max) {
value += step;
}
}}
>
<IconConstrain>
{@html chevronRight}
</IconConstrain>
</button>
</div>
<style lang="scss">
@use "sass/button-mixins" as button;
.spin-box {
width: 100%;
border: 1px solid var(--border);
border-radius: var(--border-radius);
overflow: hidden;
position: relative;
input {
width: 100%;
padding: 0.2rem 1.5rem 0.2rem 0.75rem;
border: none;
outline: none;
text-align: center;
&::-webkit-inner-spin-button {
display: none;
}
}
&:hover,
&:focus-within {
button {
opacity: 1;
}
}
}
button {
opacity: 0;
position: absolute;
@include button.base($border: false);
&.left {
inset: 0 auto 0 0;
border-right: 1px solid var(--border);
}
&.right {
position: absolute;
inset: 0 0 0 auto;
border-left: 1px solid var(--border);
}
}
</style>

View file

@ -27,7 +27,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
bottom: 0;
left: 0;
right: 0;
z-index: 50;
z-index: var(--z-index, 50);
background: var(--sticky-bg, var(--canvas));
border-style: solid;

View file

@ -61,6 +61,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export let closeOnInsideClick = false;
export let keepOnKeyup = false;
export let hideArrow = false;
export let reference: ReferenceElement | undefined = undefined;
let floating: FloatingElement;
@ -170,13 +171,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{/if}
{/if}
<div bind:this={floating} class="floating" use:portal={portalTarget}>
<div bind:this={floating} class="floating" class:show use:portal={portalTarget}>
{#if show}
<slot name="floating" />
{/if}
<div bind:this={arrow} class="floating-arrow" hidden={!show}>
<FloatingArrow />
{#if !hideArrow}
<FloatingArrow />
{/if}
</div>
</div>
@ -188,7 +191,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
border-radius: 5px;
z-index: 890;
@include elevation.elevation(8);
&.show {
@include elevation.elevation(8);
}
&-arrow {
position: absolute;

View file

@ -140,7 +140,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{/if}
{/if}
<div bind:this={floating} class="overlay">
<div bind:this={floating} class="overlay" class:show>
{#if show}
<slot name="overlay" />
{/if}
@ -154,6 +154,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
border-radius: 5px;
z-index: 40;
@include elevation.elevation(5);
&.show {
@include elevation.elevation(5);
}
}
</style>

8
ts/components/icons.ts Normal file
View file

@ -0,0 +1,8 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/// <reference types="../lib/image-import" />
export { default as chevronDown } from "@mdi/svg/svg/chevron-down.svg";
export { default as chevronLeft } from "@mdi/svg/svg/chevron-left.svg";
export { default as chevronRight } from "@mdi/svg/svg/chevron-right.svg";

View file

@ -9,7 +9,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import ButtonGroup from "../components/ButtonGroup.svelte";
import ButtonToolbar from "../components/ButtonToolbar.svelte";
import { modalsKey } from "../components/context-keys";
import SelectButton from "../components/SelectButton.svelte";
import Select from "../components/Select.svelte";
import SelectOption from "../components/SelectOption.svelte";
import StickyContainer from "../components/StickyContainer.svelte";
import * as tr from "../lib/ftl";
@ -23,16 +23,19 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const dispatch = createEventDispatcher();
const dispatchPresetChange = () => dispatch("presetchange");
$: {
state.setCurrentIndex(value);
dispatchPresetChange();
}
$: options = Array.from($configList, (entry) => configLabel(entry));
$: value = $configList.find((entry) => entry.current)?.idx || 0;
function configLabel(entry: ConfigListEntry): string {
const count = tr.deckConfigUsedByDecks({ decks: entry.useCount });
return `${entry.name} (${count})`;
}
function blur(event: Event): void {
state.setCurrentIndex(parseInt((event.target! as HTMLSelectElement).value));
dispatchPresetChange();
}
function onAddConfig(text: string): void {
const trimmed = text.trim();
if (trimmed.length) {
@ -93,18 +96,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<StickyContainer --gutter-block="0.5rem" --sticky-borders="0 0 1px" breakpoint="sm">
<ButtonToolbar class="justify-content-between" size={2.3} wrap={false}>
<ButtonGroup class="flex-grow-1">
<SelectButton
class="flex-grow-1"
on:change={blur}
--border-left-radius="5px"
--border-right-radius="5px"
>
{#each $configList as entry}
<SelectOption value={String(entry.idx)} selected={entry.current}>
{configLabel(entry)}
<Select class="flex-grow-1" current={options[value]}>
{#each options as option, idx}
<SelectOption on:select={() => (value = idx)}
>{option}
</SelectOption>
{/each}
</SelectButton>
</Select>
</ButtonGroup>
<SaveButton

View file

@ -3,39 +3,18 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import { pageTheme } from "../sveltelib/theme";
import Select from "../components/Select.svelte";
import SelectOption from "../components/SelectOption.svelte";
export let choices: string[];
export let value: number = 0;
export let options: string[] = [];
export let disabled: number[] = [];
export let value = 0;
</script>
<select
bind:value
class:nightMode={$pageTheme.isDark}
class:visible-down-arrow={$pageTheme.isDark}
class="enum-selector form-select"
>
{#each choices as choice, idx}
<option value={idx} disabled={disabled.includes(idx)}>{choice}</option>
<Select current={options[value]}>
{#each options as option, idx}
<SelectOption disabled={disabled.includes(idx)} on:select={() => (value = idx)}
>{option}</SelectOption
>
{/each}
</select>
<style lang="scss">
@use "sass/night-mode" as nightmode;
@use "sass/button-mixins" as button;
.nightMode {
@include nightmode.input;
}
.enum-selector {
/* overwrite Bootstrap */
padding: 0.2rem 0.75rem;
}
.visible-down-arrow {
/* override the default down arrow */
background-image: button.down-arrow(white);
}
</style>
</Select>

View file

@ -23,7 +23,7 @@
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
</Col>
<Col --col-size={5} {breakpoint}>
<EnumSelector bind:value {choices} {disabled} />
<EnumSelector bind:value options={choices} {disabled} />
<RevertButton bind:value {defaultValue} />
</Col>
</Row>

View file

@ -95,5 +95,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
.hide :global(.badge) {
opacity: 0;
cursor: initial;
}
</style>

View file

@ -5,11 +5,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import { createEventDispatcher, tick } from "svelte";
import ButtonGroup from "../components/ButtonGroup.svelte";
import DropdownDivider from "../components/DropdownDivider.svelte";
import DropdownItem from "../components/DropdownItem.svelte";
import LabelButton from "../components/IconButton.svelte";
import IconButton from "../components/IconButton.svelte";
import LabelButton from "../components/LabelButton.svelte";
import Popover from "../components/Popover.svelte";
import Shortcut from "../components/Shortcut.svelte";
import WithFloating from "../components/WithFloating.svelte";
@ -64,48 +63,52 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let showFloating = false;
</script>
<ButtonGroup>
<LabelButton
theme="primary"
on:click={() => save(false)}
tooltip={getPlatformString(saveKeyCombination)}
--border-left-radius="5px">{tr.deckConfigSaveButton()}</LabelButton
>
<Shortcut keyCombination={saveKeyCombination} on:action={() => save(false)} />
<LabelButton
primary
on:click={() => save(false)}
tooltip={getPlatformString(saveKeyCombination)}
--border-left-radius="var(--border-radius)"
>
<div class="save">{tr.deckConfigSaveButton()}</div>
</LabelButton>
<Shortcut keyCombination={saveKeyCombination} on:action={() => save(false)} />
<WithFloating
show={showFloating}
closeOnInsideClick
inline
on:close={() => (showFloating = false)}
<WithFloating
show={showFloating}
closeOnInsideClick
inline
on:close={() => (showFloating = false)}
>
<IconButton
class="chevron"
slot="reference"
on:click={() => (showFloating = !showFloating)}
--border-right-radius="var(--border-radius)"
iconSize={80}
>
<IconButton
slot="reference"
widthMultiplier={0.5}
iconSize={120}
--border-right-radius="5px"
on:click={() => (showFloating = !showFloating)}
{@html chevronDown}
</IconButton>
<Popover slot="floating">
<DropdownItem on:click={() => dispatch("add")}
>{tr.deckConfigAddGroup()}</DropdownItem
>
{@html chevronDown}
</IconButton>
<DropdownItem on:click={() => dispatch("clone")}
>{tr.deckConfigCloneGroup()}</DropdownItem
>
<DropdownItem on:click={() => dispatch("rename")}>
{tr.deckConfigRenameGroup()}
</DropdownItem>
<DropdownItem on:click={removeConfig}>{tr.deckConfigRemoveGroup()}</DropdownItem
>
<DropdownDivider />
<DropdownItem on:click={() => save(true)}>
{tr.deckConfigSaveToAllSubdecks()}
</DropdownItem>
</Popover>
</WithFloating>
<Popover slot="floating">
<DropdownItem on:click={() => dispatch("add")}
>{tr.deckConfigAddGroup()}</DropdownItem
>
<DropdownItem on:click={() => dispatch("clone")}
>{tr.deckConfigCloneGroup()}</DropdownItem
>
<DropdownItem on:click={() => dispatch("rename")}>
{tr.deckConfigRenameGroup()}
</DropdownItem>
<DropdownItem on:click={removeConfig}
>{tr.deckConfigRemoveGroup()}</DropdownItem
>
<DropdownDivider />
<DropdownItem on:click={() => save(true)}>
{tr.deckConfigSaveToAllSubdecks()}
</DropdownItem>
</Popover>
</WithFloating>
</ButtonGroup>
<style lang="scss">
.save {
margin: 0.2rem 0.75rem;
}
</style>

View file

@ -1,44 +0,0 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import { pageTheme } from "../sveltelib/theme";
export let value: number;
export let min = 1;
export let max = 9999;
function checkMinMax() {
if (value > max) {
value = max;
} else if (value < min) {
value = min;
}
}
</script>
<input
type="number"
pattern="[0-9]*"
inputmode="numeric"
{min}
{max}
bind:value
class="spin-box form-control"
class:nightMode={$pageTheme.isDark}
on:blur={checkMinMax}
/>
<style lang="scss">
@use "sass/night-mode" as nightmode;
.spin-box {
/* overwrite Bootstrap */
padding: 0.2rem 0.75rem;
}
.nightMode {
@include nightmode.input;
}
</style>

View file

@ -1,37 +0,0 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import { pageTheme } from "../sveltelib/theme";
export let value: number;
export let min = 1;
export let max = 9999;
let stringValue: string;
$: stringValue = value.toFixed(2);
function update(this: HTMLInputElement): void {
value = Math.min(max, Math.max(min, parseFloat(this.value)));
}
</script>
<input
type="number"
class="form-control"
class:nightMode={$pageTheme.isDark}
{min}
{max}
step="0.01"
value={stringValue}
on:blur={update}
/>
<style lang="scss">
@use "sass/night-mode" as nightmode;
.nightMode {
@include nightmode.input;
}
</style>

View file

@ -5,8 +5,8 @@
<script lang="ts">
import Col from "../components/Col.svelte";
import Row from "../components/Row.svelte";
import SpinBox from "../components/SpinBox.svelte";
import RevertButton from "./RevertButton.svelte";
import SpinBoxFloat from "./SpinBoxFloat.svelte";
import TooltipLabel from "./TooltipLabel.svelte";
export let value: any;
@ -21,7 +21,7 @@
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
</Col>
<Col --col-size={5} breakpoint="sm">
<SpinBoxFloat bind:value {min} {max} />
<SpinBox bind:value {min} {max} step={0.01} />
<RevertButton bind:value {defaultValue} />
</Col>
</Row>

View file

@ -5,8 +5,8 @@
<script lang="ts">
import Col from "../components/Col.svelte";
import Row from "../components/Row.svelte";
import SpinBox from "../components/SpinBox.svelte";
import RevertButton from "./RevertButton.svelte";
import SpinBox from "./SpinBox.svelte";
import TooltipLabel from "./TooltipLabel.svelte";
export let value: any;

View file

@ -8,14 +8,15 @@ $size: var(--buttons-size);
$padding: 2px;
.linkb {
@include button.base;
@include button.border-radius;
width: $size;
height: $size;
padding: $padding;
font-size: calc($size * 0.6);
}
@include button.base($selector: ".linkb");
img.topbut {
max-width: calc($size - 2 * $padding);
max-height: calc($size - 2 * $padding);

View file

@ -7,4 +7,6 @@ input[type="checkbox"] {
cursor: pointer;
}
@include button.base;
button {
@include button.base;
}

View file

@ -27,7 +27,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
><Col --col-size={4}>{basename(path)}</Col><Col --col-justify="end">
<ButtonGroup size={2}>
<LabelButton
theme="primary"
primary
tooltip={getPlatformString(keyCombination)}
on:click={onImport}
--border-left-radius="5px"

View file

@ -22,7 +22,6 @@ body {
padding-bottom: 5em;
}
// override the default down arrow colour in <select> elements
.night-mode select {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23FFFFFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
html {
overflow-x: hidden;
}

View file

@ -48,6 +48,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
flex-grow: 1;
border-radius: 0;
}
@include button.base($with-disabled: false);
button {
@include button.base($with-disabled: false, $active-class: active);
}
</style>

View file

@ -58,6 +58,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}
.tag {
@include button.base($with-active: false, $with-disabled: false);
font-size: var(--base-font-size);
padding: 0;
@ -81,6 +83,4 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--border-color: var(--border-focus);
}
}
@include button.base($with-active: false, $with-disabled: false);
</style>