Introduce our own Container, Row, and Col components (#1495)

* Refactor out Placeholder from CardInfo.svelte

* Add breakpoint parameter for Container

- Use `Container` component inside `TitledContainer`

* Build Item into Row

- Use Row in DeckOptionsPage instead of just Item

* Reengineer Container/Row/Col CSS

* Inline Badges next to Labels when Lable spans multiple rows

* Adjust margins for mobile

* Implement Col component breakpoints

* Move card-info to use new Container and Row components

* Join StickyHeader and StickyFooter to StickyContainer

* Remove default middle vertical-alignment for Badges again

* Satisfy tests

* Restore inline gutters in change-notetype Mapper

* Add some comment to Col and Container

* Fix breaking behavior in DeckOptionsPage when multi-column

* Add back toolbar left padding to counter-act buttongroup right margins

* Make Label in SwitchRow take more of available space
This commit is contained in:
Henrik Giesel 2021-11-17 04:49:52 +01:00 committed by GitHub
parent 98b527eb99
commit ab6a68ec49
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 668 additions and 511 deletions

View file

@ -51,6 +51,14 @@ sass_library(
visibility = ["//visibility:public"],
)
sass_library(
name = "breakpoints_lib",
srcs = [
"breakpoints.scss",
],
visibility = ["//visibility:public"],
)
sass_library(
name = "button_mixins_lib",
srcs = [

View file

@ -1,3 +1,5 @@
/* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use "fusion-vars";
@import "bootstrap/scss/functions";

93
sass/breakpoints.scss Normal file
View file

@ -0,0 +1,93 @@
/* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use "sass:list";
@use "sass:map";
$bps: (
"xs",
"sm",
"md",
"lg",
"xl",
"xxl",
);
$breakpoints: (
list.nth($bps, 2): 576px,
list.nth($bps, 3): 768px,
list.nth($bps, 4): 992px,
list.nth($bps, 5): 1200px,
list.nth($bps, 6): 1400px,
);
@mixin with-breakpoint($bp) {
@if map.get($breakpoints, $bp) {
@media (min-width: map.get($breakpoints, $bp)) {
@content;
}
} @else {
@content;
}
};
@mixin with-breakpoints($prefix, $dict) {
@each $property, $values in $dict {
@each $bp, $value in $values {
@if map.get($breakpoints, $bp) {
@media (min-width: map.get($breakpoints, $bp)) {
.#{$prefix}-#{$bp} {
#{$property}: $value;
}
}
} @else {
.#{$prefix}-#{$bp} {
#{$property}: $value;
}
}
}
}
};
@function breakpoints-upto($upto) {
$result: ();
@each $bp in $bps {
$result: list.append($result, $bp);
@if $bp == $upto {
@return $result;
}
}
@return $result;
}
@function breakpoint-selector-upto($prefix, $upto) {
$result: ();
@each $bp in breakpoints-upto($upto) {
$result: list.append($result, ".#{$prefix}-#{$bp}", $separator: comma)
}
@return $result;
}
@mixin with-breakpoints-upto($prefix, $dict) {
@each $property, $values in $dict {
@each $bp, $value in $values {
$selector: breakpoint-selector-upto($prefix, $bp);
@if map.get($breakpoints, $bp) {
@media (min-width: map.get($breakpoints, $bp)) {
#{$selector} {
#{$property}: $value;
}
}
} @else {
#{$selector} {
#{$property}: $value;
}
}
}
}
};

View file

@ -3,53 +3,54 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import * as tr from "../lib/ftl";
import type { Stats } from "../lib/proto";
import { getCardStats } from "./lib";
import Container from "../components/Container.svelte";
import Row from "../components/Row.svelte";
import CardStats from "./CardStats.svelte";
import CardInfoPlaceholder from "./CardInfoPlaceholder.svelte";
import Revlog from "./Revlog.svelte";
export let cardId: number | null = null;
export let includeRevlog: boolean = true;
let stats: Stats.CardStatsResponse | null = null;
let revlog: Stats.CardStatsResponse.StatsRevlogEntry[] | null = null;
$: if (cardId === null) {
stats = null;
} else {
async function updateStats(cardId: number): Promise<void> {
const requestedCardId = cardId;
getCardStats(requestedCardId).then((s) => {
/* Skip if another update has been triggered in the meantime. */
if (requestedCardId === cardId) {
stats = s;
const cardStats = await getCardStats(requestedCardId);
/* Skip if another update has been triggered in the meantime. */
if (requestedCardId === cardId) {
stats = cardStats;
if (includeRevlog) {
revlog = stats.revlog as Stats.CardStatsResponse.StatsRevlogEntry[];
}
});
}
}
$: if (cardId) {
updateStats(cardId);
} else {
stats = null;
revlog = null;
}
</script>
{#if stats !== null}
<div class="container">
<div>
<Container breakpoint="md" --gutter-inline="0.25rem" --gutter-block="0.5rem">
{#if stats}
<Row>
<CardStats {stats} />
{#if includeRevlog}
<Revlog {stats} />
{/if}
</div>
</div>
{:else}
<div class="placeholder">{tr.cardStatsNoCard()}</div>
{/if}
</Row>
<style>
.container {
max-width: 40em;
}
.placeholder {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
{#if revlog}
<Row>
<Revlog {revlog} />
</Row>
{/if}
{:else}
<CardInfoPlaceholder />
{/if}
</Container>

View file

@ -0,0 +1,19 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import * as tr from "../lib/ftl";
</script>
<div class="card-info-placeholder">{tr.cardStatsNoCard()}</div>
<style lang="scss">
.card-info-placeholder {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>

View file

@ -94,10 +94,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
$: statsRows = rowsFromStats(stats);
</script>
<table class="stats-table">
{#each statsRows as row, _index}
<table class="stats-table align-start">
{#each statsRows as row}
<tr>
<th style="text-align:start">{row.label}</th>
<th class="align-start">{row.label}</th>
<td>{row.value}</td>
</tr>
{/each}
@ -108,6 +108,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
width: 100%;
border-spacing: 1em 0;
border-collapse: collapse;
}
.align-start {
text-align: start;
}
</style>

View file

@ -7,10 +7,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { Stats } from "../lib/proto";
import { Timestamp, timeSpan } from "../lib/time";
export let stats: Stats.CardStatsResponse;
type StatsRevlogEntry = Stats.CardStatsResponse.StatsRevlogEntry;
export let revlog: StatsRevlogEntry[];
function reviewKindClass(entry: StatsRevlogEntry): string {
switch (entry.reviewKind) {
case Stats.RevlogEntry.ReviewKind.LEARNING:
@ -59,6 +59,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
function revlogRowFromEntry(entry: StatsRevlogEntry): RevlogRow {
const timestamp = new Timestamp(entry.time);
return {
date: timestamp.dateString(),
time: timestamp.timeString(),
@ -72,37 +73,32 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
};
}
let revlogRows: RevlogRow[];
$: revlogRows = stats.revlog.map((entry) =>
revlogRowFromEntry(entry as StatsRevlogEntry),
);
$: revlogRows = revlog.map(revlogRowFromEntry);
</script>
{#if stats.revlog.length}
<div class="revlog-container">
<table class="revlog-table">
{#if revlog.length > 0}
<table class="revlog-table">
<tr>
<th class="left">{tr2.cardStatsReviewLogDate()}</th>
<th class="center hidden-xs">{tr2.cardStatsReviewLogType()}</th>
<th class="center">{tr2.cardStatsReviewLogRating()}</th>
<th class="right">{tr2.cardStatsInterval()}</th>
<th class="center hidden-xs">{tr2.cardStatsEase()}</th>
<th class="right">{tr2.cardStatsReviewLogTimeTaken()}</th>
</tr>
{#each revlogRows as row, _index}
<tr>
<th class="left">{tr2.cardStatsReviewLogDate()}</th>
<th class="center hidden-xs">{tr2.cardStatsReviewLogType()}</th>
<th class="center">{tr2.cardStatsReviewLogRating()}</th>
<th class="right">{tr2.cardStatsInterval()}</th>
<th class="center hidden-xs">{tr2.cardStatsEase()}</th>
<th class="right">{tr2.cardStatsReviewLogTimeTaken()}</th>
<td class="left"><b>{row.date}</b> @ {row.time}</td>
<td class="center hidden-xs {row.reviewKindClass}">
{row.reviewKind}
</td>
<td class="center {row.ratingClass}">{row.rating}</td>
<td class="right">{row.interval}</td>
<td class="center hidden-xs">{row.ease}</td>
<td class="right">{row.takenSecs}</td>
</tr>
{#each revlogRows as row, _index}
<tr>
<td class="left"><b>{row.date}</b> @ {row.time}</td>
<td class="center hidden-xs {row.reviewKindClass}">
{row.reviewKind}
</td>
<td class="center {row.ratingClass}">{row.rating}</td>
<td class="right">{row.interval}</td>
<td class="center hidden-xs">{row.ease}</td>
<td class="right">{row.takenSecs}</td>
</tr>
{/each}
</table>
</div>
{/each}
</table>
{/if}
<style>
@ -118,10 +114,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
text-align: center;
}
.revlog-container {
margin-top: 2em;
}
.revlog-table {
width: 100%;
border-spacing: 1em 0;

View file

@ -1,3 +1 @@
@import "sass/base";
@import "sass/bootstrap/scss/containers";

View file

@ -3,6 +3,9 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Container from "../components/Container.svelte";
import Row from "../components/Row.svelte";
import Col from "../components/Col.svelte";
import MapperRow from "./MapperRow.svelte";
import * as tr from "../lib/ftl";
import { ChangeNotetypeState, MapContext } from "./lib";
@ -13,26 +16,23 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let info = state.info;
let unused: string[];
let unusedMsg: string;
$: {
unused = $info.unusedItems(ctx);
unusedMsg =
ctx === MapContext.Field
? tr.changeNotetypeWillDiscardContent()
: tr.changeNotetypeWillDiscardCards();
}
$: unused = $info.unusedItems(ctx);
$: unusedMsg =
ctx === MapContext.Field
? tr.changeNotetypeWillDiscardContent()
: tr.changeNotetypeWillDiscardCards();
</script>
<div class="container m-1">
<div class="row">
<div class="col"><b>{tr.changeNotetypeCurrent()}</b></div>
<div class="col"><b>{tr.changeNotetypeNew()}</b></div>
</div>
<Container --gutter-inline="0.5rem" --gutter-block="0.1rem">
<Row --cols={2}>
<Col --col-size={1}><b>{tr.changeNotetypeCurrent()}</b></Col>
<Col --col-size={1}><b>{tr.changeNotetypeNew()}</b></Col>
</Row>
{#each $info.mapForContext(ctx) as _, newIndex}
<MapperRow {state} {ctx} {newIndex} />
{/each}
</div>
</Container>
{#if unused.length > 0}
<div class="alert alert-warning" in:slide out:slide>

View file

@ -3,6 +3,8 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Row from "../components/Row.svelte";
import Col from "../components/Col.svelte";
import type { ChangeNotetypeState, MapContext } from "./lib";
export let state: ChangeNotetypeState;
@ -17,8 +19,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}
</script>
<div class="row">
<div class="col">
<Row --cols={2}>
<Col --col-size={1}>
<!-- svelte-ignore a11y-no-onchange -->
<select
value={$info.getOldIndex(ctx, newIndex)}
@ -29,8 +31,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<option value={idx}>{name}</option>
{/each}
</select>
</div>
<div class="col align-self-center">
</Col>
<Col --col-size={1}>
{$info.getNewName(ctx, newIndex)}
</div>
</div>
</Col>
</Row>

View file

@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import type { ChangeNotetypeState } from "./lib";
import StickyHeader from "../components/StickyHeader.svelte";
import StickyContainer from "../components/StickyContainer.svelte";
import ButtonToolbar from "../components/ButtonToolbar.svelte";
import Item from "../components/Item.svelte";
import ButtonGroup from "../components/ButtonGroup.svelte";
@ -25,7 +25,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}
</script>
<StickyHeader>
<StickyContainer --gutter-block="0.1rem" --sticky-borders="0 0 1px">
<ButtonToolbar class="justify-content-between" size={2.3} wrap={false}>
<Item>
<ButtonGroup class="flex-grow-1">
@ -48,4 +48,4 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<SaveButton {state} />
</Item>
</ButtonToolbar>
</StickyHeader>
</StickyContainer>

View file

@ -39,6 +39,7 @@ svelte_check(
"//sass:base_lib",
"//sass:button_mixins_lib",
"//sass:scrollbar_lib",
"//sass:breakpoints_lib",
"//sass/bootstrap",
"@npm//@types/bootstrap",
"//ts/sveltelib:sveltelib_pkg",

View file

@ -111,7 +111,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<div
bind:this={buttonGroupRef}
{id}
class="btn-group {className}"
class="button-group btn-group {className}"
{style}
dir="ltr"
role="group"
@ -125,9 +125,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</div>
<style lang="scss">
div {
.button-group {
display: flex;
flex-direction: row;
flex-wrap: var(--buttons-wrap);
flex-flow: row var(--buttons-wrap);
}
</style>

View file

@ -119,7 +119,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
.button-toolbar {
flex-wrap: var(--buttons-wrap);
padding: 0.15rem 0;
padding-left: 0.15rem;
> :global(*) > :global(*) {
/* TODO replace with gap once available */

52
ts/components/Col.svelte Normal file
View file

@ -0,0 +1,52 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import type { Breakpoint } from "./types";
/* flex-basis: 100% if viewport < breakpoint otherwise
* as specified by --cols and --col-size */
export let breakpoint: Breakpoint = "xs";
</script>
<div
class="col"
class:col-xs={breakpoint === "xs"}
class:col-sm={breakpoint === "sm"}
class:col-md={breakpoint === "md"}
class:col-lg={breakpoint === "lg"}
class:col-xl={breakpoint === "xl"}
class:col-xxl={breakpoint === "xxl"}
>
<slot />
</div>
<style lang="scss">
@use "sass/breakpoints" as bp;
.col {
display: flex;
flex-flow: row nowrap;
align-items: var(--col-align, flex-start);
justify-content: var(--col-justify, flex-start);
padding: 0 var(--gutter-inline, 0);
flex: 1 0 100%;
}
$calc: calc(100% / var(--cols, 1) * var(--col-size, 1));
@include bp.with-breakpoints(
"col",
(
"flex-basis": (
"xs": $calc,
"sm": $calc,
"md": $calc,
"lg": $calc,
"xl": $calc,
"xxl": $calc
)
)
);
</style>

View file

@ -4,16 +4,62 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Section from "./Section.svelte";
import type { Breakpoint } from "./types";
export let id: string | undefined = undefined;
let className: string = "";
export { className as class };
/* width: 100% if viewport < breakpoint otherwise with gutters */
export let breakpoint: Breakpoint | "fluid" = "fluid";
export let api: Record<string, never> | undefined = undefined;
</script>
<div {id} class="container {className}">
<div
{id}
class="container {className}"
class:container-xs={breakpoint === "xs"}
class:container-sm={breakpoint === "sm"}
class:container-md={breakpoint === "md"}
class:container-lg={breakpoint === "lg"}
class:container-xl={breakpoint === "xl"}
class:container-xxl={breakpoint === "xxl"}
class:container-fluid={breakpoint === "fluid"}
>
<Section {api}>
<slot />
</Section>
</div>
<style lang="scss">
@use "sass/breakpoints";
.container {
display: flex;
flex-direction: var(--container-direction, column);
padding: var(--gutter-block, 0) var(--gutter-inline, 0);
margin: 0 auto;
&.container-fluid {
width: 100%;
height: 100%;
margin: 0;
}
}
@include breakpoints.with-breakpoints-upto(
"container",
(
"max-width": (
"xs": 360px,
"sm": 540px,
"md": 720px,
"lg": 960px,
"xl": 1140px,
"xxl": 1320px,
),
)
);
</style>

26
ts/components/Row.svelte Normal file
View file

@ -0,0 +1,26 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Item from "../components/Item.svelte";
export let id: string | undefined = undefined;
let className: string = "";
export { className as class };
</script>
<Item {id}>
<div class="row {className}">
<slot />
</div>
</Item>
<style lang="scss">
.row {
display: flex;
flex-flow: row wrap;
align-content: stretch;
padding: var(--gutter-block, 0) 0;
}
</style>

View file

@ -3,20 +3,29 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Container from "./Container.svelte";
import type { Breakpoint } from "./types";
export let id: string | undefined = undefined;
let className: string = "";
export { className as class };
export let height: number = 0;
export let breakpoint: Breakpoint | "fluid" = "fluid";
export let api: Record<string, never> | undefined = undefined;
</script>
<footer {id} bind:offsetHeight={height} class="sticky-footer {className}">
<slot />
</footer>
<div {id} bind:offsetHeight={height} class="sticky-container {className}">
<Container {breakpoint} {api}>
<slot />
</Container>
</div>
<style lang="scss">
.sticky-footer {
.sticky-container {
position: sticky;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 10;
@ -24,10 +33,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
background: var(--window-bg);
border-style: solid;
border-color: var(--medium-border);
border-width: 0;
padding: 0 3px;
bottom: 0;
border-top-width: 1px;
border-width: var(--sticky-borders, 0);
}
</style>

View file

@ -1,31 +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">
export let id: string | undefined = undefined;
let className: string = "";
export { className as class };
</script>
<header {id} class="sticky-header container-fluid {className}">
<slot />
</header>
<style lang="scss">
.sticky-header {
position: sticky;
left: 0;
right: 0;
z-index: 10;
background: var(--window-bg);
border-style: solid;
border-color: var(--medium-border);
border-width: 0;
padding: 0 3px;
top: 0;
border-bottom-width: 1px;
}
</style>

View file

@ -1,4 +1,5 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export type Size = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
export type Breakpoint = "xs" | "sm" | "md" | "lg" | "xl";
export type Breakpoint = "xs" | "sm" | "md" | "lg" | "xl" | "xxl";

View file

@ -5,7 +5,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import * as tr from "../lib/ftl";
import TitledContainer from "./TitledContainer.svelte";
import Item from "../components/Item.svelte";
import SpinBoxRow from "./SpinBoxRow.svelte";
import SpinBoxFloatRow from "./SpinBoxFloatRow.svelte";
import type { DeckOptionsState } from "./lib";
@ -20,80 +19,66 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<TitledContainer title={tr.deckConfigAdvancedTitle()} {api}>
<Item>
<SpinBoxRow
bind:value={$config.maximumReviewInterval}
defaultValue={defaults.maximumReviewInterval}
min={1}
max={365 * 100}
markdownTooltip={tr.deckConfigMaximumIntervalTooltip()}
>
{tr.schedulingMaximumInterval()}
</SpinBoxRow>
</Item>
<SpinBoxRow
bind:value={$config.maximumReviewInterval}
defaultValue={defaults.maximumReviewInterval}
min={1}
max={365 * 100}
markdownTooltip={tr.deckConfigMaximumIntervalTooltip()}
>
{tr.schedulingMaximumInterval()}
</SpinBoxRow>
<Item>
<SpinBoxFloatRow
bind:value={$config.initialEase}
defaultValue={defaults.initialEase}
min={1.31}
max={5}
markdownTooltip={tr.deckConfigStartingEaseTooltip()}
>
{tr.schedulingStartingEase()}
</SpinBoxFloatRow>
</Item>
<SpinBoxFloatRow
bind:value={$config.initialEase}
defaultValue={defaults.initialEase}
min={1.31}
max={5}
markdownTooltip={tr.deckConfigStartingEaseTooltip()}
>
{tr.schedulingStartingEase()}
</SpinBoxFloatRow>
<Item>
<SpinBoxFloatRow
bind:value={$config.easyMultiplier}
defaultValue={defaults.easyMultiplier}
min={1}
max={3}
markdownTooltip={tr.deckConfigEasyBonusTooltip()}
>
{tr.schedulingEasyBonus()}
</SpinBoxFloatRow>
</Item>
<SpinBoxFloatRow
bind:value={$config.easyMultiplier}
defaultValue={defaults.easyMultiplier}
min={1}
max={3}
markdownTooltip={tr.deckConfigEasyBonusTooltip()}
>
{tr.schedulingEasyBonus()}
</SpinBoxFloatRow>
<Item>
<SpinBoxFloatRow
bind:value={$config.intervalMultiplier}
defaultValue={defaults.intervalMultiplier}
min={0.5}
max={2}
markdownTooltip={tr.deckConfigIntervalModifierTooltip()}
>
{tr.schedulingIntervalModifier()}
</SpinBoxFloatRow>
</Item>
<SpinBoxFloatRow
bind:value={$config.intervalMultiplier}
defaultValue={defaults.intervalMultiplier}
min={0.5}
max={2}
markdownTooltip={tr.deckConfigIntervalModifierTooltip()}
>
{tr.schedulingIntervalModifier()}
</SpinBoxFloatRow>
<Item>
<SpinBoxFloatRow
bind:value={$config.hardMultiplier}
defaultValue={defaults.hardMultiplier}
min={0.5}
max={1.3}
markdownTooltip={tr.deckConfigHardIntervalTooltip()}
>
{tr.schedulingHardInterval()}
</SpinBoxFloatRow>
</Item>
<SpinBoxFloatRow
bind:value={$config.hardMultiplier}
defaultValue={defaults.hardMultiplier}
min={0.5}
max={1.3}
markdownTooltip={tr.deckConfigHardIntervalTooltip()}
>
{tr.schedulingHardInterval()}
</SpinBoxFloatRow>
<Item>
<SpinBoxFloatRow
bind:value={$config.lapseMultiplier}
defaultValue={defaults.lapseMultiplier}
max={1}
markdownTooltip={tr.deckConfigNewIntervalTooltip()}
>
{tr.schedulingNewInterval()}
</SpinBoxFloatRow>
</Item>
<SpinBoxFloatRow
bind:value={$config.lapseMultiplier}
defaultValue={defaults.lapseMultiplier}
max={1}
markdownTooltip={tr.deckConfigNewIntervalTooltip()}
>
{tr.schedulingNewInterval()}
</SpinBoxFloatRow>
{#if state.v3Scheduler}
<Item>
<CardStateCustomizer bind:value={$cardStateCustomizer} />
</Item>
<CardStateCustomizer bind:value={$cardStateCustomizer} />
{/if}
</TitledContainer>

View file

@ -5,7 +5,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import * as tr from "../lib/ftl";
import TitledContainer from "./TitledContainer.svelte";
import Item from "../components/Item.svelte";
import SwitchRow from "./SwitchRow.svelte";
import type { DeckOptionsState } from "./lib";
@ -17,22 +16,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<TitledContainer title={tr.deckConfigAudioTitle()} {api}>
<Item>
<SwitchRow
bind:value={$config.disableAutoplay}
defaultValue={defaults.disableAutoplay}
>
{tr.deckConfigDisableAutoplay()}
</SwitchRow>
</Item>
<SwitchRow
bind:value={$config.disableAutoplay}
defaultValue={defaults.disableAutoplay}
>
{tr.deckConfigDisableAutoplay()}
</SwitchRow>
<Item>
<SwitchRow
bind:value={$config.skipQuestionWhenReplayingAnswer}
defaultValue={defaults.skipQuestionWhenReplayingAnswer}
markdownTooltip={tr.deckConfigAlwaysIncludeQuestionAudioTooltip()}
>
{tr.deckConfigSkipQuestionWhenReplaying()}
</SwitchRow>
</Item>
<SwitchRow
bind:value={$config.skipQuestionWhenReplayingAnswer}
defaultValue={defaults.skipQuestionWhenReplayingAnswer}
markdownTooltip={tr.deckConfigAlwaysIncludeQuestionAudioTooltip()}
>
{tr.deckConfigSkipQuestionWhenReplaying()}
</SwitchRow>
</TitledContainer>

View file

@ -14,6 +14,7 @@ compile_sass(
deps = [
"//sass:base_lib",
"//sass:scrollbar_lib",
"//sass:breakpoints_lib",
"//sass/bootstrap",
],
)
@ -77,6 +78,7 @@ svelte_check(
]) + [
"//sass:button_mixins_lib",
"//sass:night_mode_lib",
"//sass:breakpoints_lib",
"//sass/bootstrap",
"@npm//@types/bootstrap",
"@npm//@types/lodash-es",

View file

@ -4,7 +4,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import TitledContainer from "./TitledContainer.svelte";
import Item from "../components/Item.svelte";
import SwitchRow from "./SwitchRow.svelte";
import * as tr from "../lib/ftl";
import type { DeckOptionsState } from "./lib";
@ -17,23 +16,19 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<TitledContainer title={tr.deckConfigBuryTitle()} {api}>
<Item>
<SwitchRow
bind:value={$config.buryNew}
defaultValue={defaults.buryNew}
markdownTooltip={tr.deckConfigBuryTooltip()}
>
{tr.deckConfigBuryNewSiblings()}
</SwitchRow>
</Item>
<SwitchRow
bind:value={$config.buryNew}
defaultValue={defaults.buryNew}
markdownTooltip={tr.deckConfigBuryTooltip()}
>
{tr.deckConfigBuryNewSiblings()}
</SwitchRow>
<Item>
<SwitchRow
bind:value={$config.buryReviews}
defaultValue={defaults.buryReviews}
markdownTooltip={tr.deckConfigBuryTooltip()}
>
{tr.deckConfigBuryReviewSiblings()}
</SwitchRow>
</Item>
<SwitchRow
bind:value={$config.buryReviews}
defaultValue={defaults.buryReviews}
markdownTooltip={tr.deckConfigBuryTooltip()}
>
{tr.deckConfigBuryReviewSiblings()}
</SwitchRow>
</TitledContainer>

View file

@ -4,10 +4,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import * as tr from "../lib/ftl";
import Row from "../components/Row.svelte";
import Col from "../components/Col.svelte";
import TooltipLabel from "./TooltipLabel.svelte";
import RevertButton from "./RevertButton.svelte";
import Row from "./Row.svelte";
import Col from "./Col.svelte";
export let value: string;
</script>

View file

@ -1,25 +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 Row from "./Row.svelte";
import Col from "./Col.svelte";
import TooltipLabel from "./TooltipLabel.svelte";
import CheckBox from "./CheckBox.svelte";
import RevertButton from "./RevertButton.svelte";
export let value: boolean;
export let defaultValue: boolean;
export let markdownTooltip: string | undefined = undefined;
</script>
<Row>
<Col>
<RevertButton bind:value {defaultValue} />
<CheckBox bind:value
>{#if markdownTooltip}<TooltipLabel {markdownTooltip}><slot /></TooltipLabel
>{:else}<slot />{/if}</CheckBox
>
</Col>
</Row>

View file

@ -1,22 +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 type { Breakpoint, Size } from "./col";
export let breakpoint: Breakpoint | undefined = undefined;
export let size: Size | undefined = undefined;
export let grow = true;
let colClass: string;
$: {
const breakpointComponent = breakpoint ? `-${breakpoint}` : "";
const sizeComponent = size ? `-${size}` : "";
colClass = "col" + breakpointComponent + sizeComponent;
}
</script>
<div class={`${colClass} d-flex align-items-center`} class:flex-grow-0={!grow}>
<slot />
</div>

View file

@ -10,12 +10,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type Modal from "bootstrap/js/dist/modal";
import TextInputModal from "./TextInputModal.svelte";
import StickyHeader from "../components/StickyHeader.svelte";
import StickyContainer from "../components/StickyContainer.svelte";
import ButtonToolbar from "../components/ButtonToolbar.svelte";
import Item from "../components/Item.svelte";
import ButtonGroup from "../components/ButtonGroup.svelte";
import ButtonGroupItem from "../components/ButtonGroupItem.svelte";
import Container from "../components/Container.svelte";
import SelectButton from "../components/SelectButton.svelte";
import SelectOption from "../components/SelectOption.svelte";
@ -88,34 +87,32 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
bind:modalKey
/>
<StickyHeader class="g-1">
<Container>
<ButtonToolbar class="justify-content-between" size={2.3} wrap={false}>
<Item>
<ButtonGroup class="flex-grow-1">
<ButtonGroupItem>
<SelectButton class="flex-grow-1" on:change={blur}>
{#each $configList as entry}
<SelectOption
value={String(entry.idx)}
selected={entry.current}
>
{configLabel(entry)}
</SelectOption>
{/each}
</SelectButton>
</ButtonGroupItem>
</ButtonGroup>
</Item>
<StickyContainer --gutter-block="0.1rem" --sticky-borders="0 0 1px" breakpoint="sm">
<ButtonToolbar class="justify-content-between" size={2.3} wrap={false}>
<Item>
<ButtonGroup class="flex-grow-1">
<ButtonGroupItem>
<SelectButton class="flex-grow-1" on:change={blur}>
{#each $configList as entry}
<SelectOption
value={String(entry.idx)}
selected={entry.current}
>
{configLabel(entry)}
</SelectOption>
{/each}
</SelectButton>
</ButtonGroupItem>
</ButtonGroup>
</Item>
<Item>
<SaveButton
{state}
on:add={promptToAdd}
on:clone={promptToClone}
on:rename={promptToRename}
/>
</Item>
</ButtonToolbar>
</Container>
</StickyHeader>
<Item>
<SaveButton
{state}
on:add={promptToAdd}
on:clone={promptToClone}
on:rename={promptToRename}
/>
</Item>
</ButtonToolbar>
</StickyContainer>

View file

@ -41,27 +41,27 @@
</script>
<TitledContainer title={tr.deckConfigDailyLimits()} {api}>
<Item>
<SpinBoxRow
bind:value={$config.newPerDay}
defaultValue={defaults.newPerDay}
markdownTooltip={tr.deckConfigNewLimitTooltip() + v3Extra}
>
{tr.schedulingNewCardsday()}
</SpinBoxRow>
<SpinBoxRow
bind:value={$config.newPerDay}
defaultValue={defaults.newPerDay}
markdownTooltip={tr.deckConfigNewLimitTooltip() + v3Extra}
>
{tr.schedulingNewCardsday()}
</SpinBoxRow>
<Item>
<Warning warning={newCardsGreaterThanParent} />
</Item>
<Item>
<SpinBoxRow
bind:value={$config.reviewsPerDay}
defaultValue={defaults.reviewsPerDay}
markdownTooltip={tr.deckConfigReviewLimitTooltip() + v3Extra}
>
{tr.schedulingMaximumReviewsday()}
</SpinBoxRow>
<SpinBoxRow
bind:value={$config.reviewsPerDay}
defaultValue={defaults.reviewsPerDay}
markdownTooltip={tr.deckConfigReviewLimitTooltip() + v3Extra}
>
{tr.schedulingMaximumReviewsday()}
</SpinBoxRow>
<Item>
<Warning warning={reviewsTooLow} />
</Item>
</TitledContainer>

View file

@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import ConfigSelector from "./ConfigSelector.svelte";
import Container from "../components/Container.svelte";
import Item from "../components/Item.svelte";
import Row from "../components/Row.svelte";
import DailyLimits from "./DailyLimits.svelte";
import DisplayOrder from "./DisplayOrder.svelte";
import NewOptions from "./NewOptions.svelte";
@ -57,57 +57,77 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<ConfigSelector {state} />
<div class="multi-column">
<Container api={options} class="g-1 mb-3 mt-3">
<Item>
<div class="deck-options-page">
<Container
breakpoint="sm"
--gutter-inline="0.25rem"
--gutter-block="0.5rem"
class="container-columns"
api={options}
>
<Row class="row-columns">
<DailyLimits {state} api={dailyLimits} />
</Item>
</Row>
<Item>
<Row class="row-columns">
<NewOptions {state} api={newOptions} />
</Item>
</Row>
<Item>
<Row class="row-columns">
<LapseOptions {state} api={lapseOptions} />
</Item>
</Row>
{#if state.v3Scheduler}
<Item>
<Row class="row-columns">
<DisplayOrder {state} api={displayOrder} />
</Item>
</Row>
{/if}
<Item>
<Row class="row-columns">
<TimerOptions {state} api={timerOptions} />
</Item>
</Row>
<Item>
<Row class="row-columns">
<BuryOptions {state} api={buryOptions} />
</Item>
</Row>
<Item>
<Row class="row-columns">
<AudioOptions {state} api={audioOptions} />
</Item>
</Row>
<Item>
<Row class="row-columns">
<Addons {state} api={addonOptions} />
</Item>
</Row>
<Item>
<Row class="row-columns">
<AdvancedOptions {state} api={advancedOptions} />
</Item>
</Row>
</Container>
</div>
<style lang="scss">
.multi-column :global(.container) {
column-count: 2;
column-gap: 5em;
}
@use "sass/breakpoints" as bp;
@media (max-width: 1000px) {
.multi-column :global(.container) {
column-count: 1;
.deck-options-page {
overflow-x: hidden;
@include bp.with-breakpoint("lg") {
:global(.container) {
display: block;
}
:global(.container-columns) {
column-count: 2;
column-gap: 5em;
:global(.container) {
break-inside: avoid;
}
}
:global(.row-columns) {
display: block;
}
}
}
</style>

View file

@ -16,7 +16,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
bind:value
class:nightMode
class:visible-down-arrow={nightMode}
class="form-select"
class="enum-selector form-select"
>
{#each choices as choice, idx}
<option value={idx}>{choice}</option>
@ -31,6 +31,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
@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);

View file

@ -3,10 +3,10 @@
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import type { Breakpoint } from "./col";
import type { Breakpoint } from "../components/types";
import Row from "./Row.svelte";
import Col from "./Col.svelte";
import Row from "../components/Row.svelte";
import Col from "../components/Col.svelte";
import TooltipLabel from "./TooltipLabel.svelte";
import EnumSelector from "./EnumSelector.svelte";
import RevertButton from "./RevertButton.svelte";
@ -18,11 +18,11 @@
export let markdownTooltip: string;
</script>
<Row>
<Col size={7}>
<Row --cols={12}>
<Col --col-size={7} {breakpoint}>
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
</Col>
<Col {breakpoint} size={5}>
<Col --col-size={5} {breakpoint}>
<EnumSelector bind:value {choices} />
<RevertButton bind:value {defaultValue} />
</Col>

View file

@ -18,3 +18,9 @@
</script>
<label bind:this={spanRef} for={forId}><slot /></label>
<style lang="scss">
label {
display: inline;
}
</style>

View file

@ -33,49 +33,43 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<TitledContainer title={tr.schedulingLapses()} {api}>
<Item>
<StepsInputRow
bind:value={$config.relearnSteps}
defaultValue={defaults.relearnSteps}
markdownTooltip={tr.deckConfigRelearningStepsTooltip()}
>
{tr.deckConfigRelearningSteps()}
</StepsInputRow>
</Item>
<StepsInputRow
bind:value={$config.relearnSteps}
defaultValue={defaults.relearnSteps}
markdownTooltip={tr.deckConfigRelearningStepsTooltip()}
>
{tr.deckConfigRelearningSteps()}
</StepsInputRow>
<SpinBoxRow
bind:value={$config.minimumLapseInterval}
defaultValue={defaults.minimumLapseInterval}
min={1}
markdownTooltip={tr.deckConfigMinimumIntervalTooltip()}
>
{tr.schedulingMinimumInterval()}
</SpinBoxRow>
<Item>
<SpinBoxRow
bind:value={$config.minimumLapseInterval}
defaultValue={defaults.minimumLapseInterval}
min={1}
markdownTooltip={tr.deckConfigMinimumIntervalTooltip()}
>
{tr.schedulingMinimumInterval()}
</SpinBoxRow>
<Warning warning={stepsExceedMinimumInterval} />
</Item>
<Item>
<SpinBoxRow
bind:value={$config.leechThreshold}
defaultValue={defaults.leechThreshold}
min={1}
markdownTooltip={tr.deckConfigLeechThresholdTooltip()}
>
{tr.schedulingLeechThreshold()}
</SpinBoxRow>
</Item>
<SpinBoxRow
bind:value={$config.leechThreshold}
defaultValue={defaults.leechThreshold}
min={1}
markdownTooltip={tr.deckConfigLeechThresholdTooltip()}
>
{tr.schedulingLeechThreshold()}
</SpinBoxRow>
<Item>
<EnumSelectorRow
bind:value={$config.leechAction}
defaultValue={defaults.leechAction}
choices={leechChoices}
breakpoint="sm"
markdownTooltip={tr.deckConfigLeechActionTooltip()}
>
{tr.schedulingLeechAction()}
</EnumSelectorRow>
</Item>
<EnumSelectorRow
bind:value={$config.leechAction}
defaultValue={defaults.leechAction}
choices={leechChoices}
breakpoint="sm"
markdownTooltip={tr.deckConfigLeechActionTooltip()}
>
{tr.schedulingLeechAction()}
</EnumSelectorRow>
</TitledContainer>

View file

@ -4,10 +4,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import TitledContainer from "./TitledContainer.svelte";
import Item from "../components/Item.svelte";
import StepsInputRow from "./StepsInputRow.svelte";
import SpinBoxRow from "./SpinBoxRow.svelte";
import EnumSelectorRow from "./EnumSelectorRow.svelte";
import Item from "../components/Item.svelte";
import Warning from "./Warning.svelte";
import type { DeckOptionsState } from "./lib";
@ -42,49 +42,45 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<TitledContainer title={tr.schedulingNewCards()} {api}>
<Item>
<StepsInputRow
bind:value={$config.learnSteps}
defaultValue={defaults.learnSteps}
markdownTooltip={tr.deckConfigLearningStepsTooltip()}
>
{tr.deckConfigLearningSteps()}
</StepsInputRow>
</Item>
<StepsInputRow
bind:value={$config.learnSteps}
defaultValue={defaults.learnSteps}
markdownTooltip={tr.deckConfigLearningStepsTooltip()}
>
{tr.deckConfigLearningSteps()}
</StepsInputRow>
<SpinBoxRow
bind:value={$config.graduatingIntervalGood}
defaultValue={defaults.graduatingIntervalGood}
markdownTooltip={tr.deckConfigGraduatingIntervalTooltip()}
>
{tr.schedulingGraduatingInterval()}
</SpinBoxRow>
<Item>
<SpinBoxRow
bind:value={$config.graduatingIntervalGood}
defaultValue={defaults.graduatingIntervalGood}
markdownTooltip={tr.deckConfigGraduatingIntervalTooltip()}
>
{tr.schedulingGraduatingInterval()}
</SpinBoxRow>
<Warning warning={stepsExceedGraduatingInterval} />
</Item>
<Item>
<SpinBoxRow
bind:value={$config.graduatingIntervalEasy}
defaultValue={defaults.graduatingIntervalEasy}
markdownTooltip={tr.deckConfigEasyIntervalTooltip()}
>
{tr.schedulingEasyInterval()}
</SpinBoxRow>
<SpinBoxRow
bind:value={$config.graduatingIntervalEasy}
defaultValue={defaults.graduatingIntervalEasy}
markdownTooltip={tr.deckConfigEasyIntervalTooltip()}
>
{tr.schedulingEasyInterval()}
</SpinBoxRow>
<Item>
<Warning warning={goodExceedsEasy} />
</Item>
<Item>
<EnumSelectorRow
bind:value={$config.newCardInsertOrder}
defaultValue={defaults.newCardInsertOrder}
choices={newInsertOrderChoices}
breakpoint={"md"}
markdownTooltip={tr.deckConfigNewInsertionOrderTooltip()}
>
{tr.deckConfigNewInsertionOrder()}
</EnumSelectorRow>
</Item>
<EnumSelectorRow
bind:value={$config.newCardInsertOrder}
defaultValue={defaults.newCardInsertOrder}
choices={newInsertOrderChoices}
breakpoint={"md"}
markdownTooltip={tr.deckConfigNewInsertionOrderTooltip()}
>
{tr.deckConfigNewInsertionOrder()}
</EnumSelectorRow>
</TitledContainer>

View file

@ -1,11 +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">
export let id: string | undefined = undefined;
</script>
<div {id} class="row gx-0 gy-2 mt-0">
<slot />
</div>

View file

@ -28,7 +28,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{min}
{max}
bind:value
class="form-control"
class="spin-box form-control"
class:nightMode
on:blur={checkMinMax}
/>
@ -36,6 +36,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<style lang="scss">
@use "sass/night-mode" as nightmode;
.spin-box {
/* overwrite Bootstrap */
padding: 0.2rem 0.75rem;
}
.nightMode {
@include nightmode.input;
}

View file

@ -3,8 +3,8 @@
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Row from "./Row.svelte";
import Col from "./Col.svelte";
import Row from "../components/Row.svelte";
import Col from "../components/Col.svelte";
import TooltipLabel from "./TooltipLabel.svelte";
import SpinBoxFloat from "./SpinBoxFloat.svelte";
import RevertButton from "./RevertButton.svelte";
@ -16,11 +16,11 @@
export let markdownTooltip: string;
</script>
<Row>
<Col size={7}>
<Row --cols={12}>
<Col --col-size={7} breakpoint="sm">
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
</Col>
<Col size={5}>
<Col --col-size={5} breakpoint="sm">
<SpinBoxFloat bind:value {min} {max} />
<RevertButton bind:value {defaultValue} />
</Col>

View file

@ -3,8 +3,8 @@
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Row from "./Row.svelte";
import Col from "./Col.svelte";
import Row from "../components/Row.svelte";
import Col from "../components/Col.svelte";
import TooltipLabel from "./TooltipLabel.svelte";
import SpinBox from "./SpinBox.svelte";
import RevertButton from "./RevertButton.svelte";
@ -16,11 +16,11 @@
export let markdownTooltip: string;
</script>
<Row>
<Col size={7}>
<Row --cols={12}>
<Col --col-size={7} breakpoint="sm">
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
</Col>
<Col size={5}>
<Col --col-size={5} breakpoint="sm">
<SpinBox bind:value {min} {max} />
<RevertButton bind:value {defaultValue} />
</Col>

View file

@ -3,8 +3,8 @@
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Row from "./Row.svelte";
import Col from "./Col.svelte";
import Row from "../components/Row.svelte";
import Col from "../components/Col.svelte";
import TooltipLabel from "./TooltipLabel.svelte";
import StepsInput from "./StepsInput.svelte";
import RevertButton from "./RevertButton.svelte";
@ -14,11 +14,11 @@
export let markdownTooltip: string;
</script>
<Row>
<Col size={7}>
<Row --cols={12}>
<Col --col-size={7} breakpoint="sm">
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
</Col>
<Col size={5}>
<Col --col-size={5} breakpoint="sm">
<StepsInput bind:value />
<RevertButton bind:value {defaultValue} />
</Col>

View file

@ -3,8 +3,8 @@
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Row from "./Row.svelte";
import Col from "./Col.svelte";
import Row from "../components/Row.svelte";
import Col from "../components/Col.svelte";
import Label from "./Label.svelte";
import TooltipLabel from "./TooltipLabel.svelte";
import Switch from "./Switch.svelte";
@ -17,13 +17,13 @@
const id = Math.random().toString(36).substring(2);
</script>
<Row>
<Col>
{#if markdownTooltip}<TooltipLabel for={id} {markdownTooltip}
<Row --cols={6}>
<Col --col-size={4}
>{#if markdownTooltip}<TooltipLabel for={id} {markdownTooltip}
><slot /></TooltipLabel
>{:else}<Label for={id}><slot /></Label>{/if}
</Col>
<Col grow={false}>
>{:else}<Label for={id}><slot /></Label>{/if}</Col
>
<Col --col-justify="flex-end">
<Switch {id} bind:value />
<RevertButton bind:value {defaultValue} />
</Col>

View file

@ -3,26 +3,20 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import Section from "../components/Section.svelte";
import Container from "../components/Container.svelte";
export let title: string;
export let api: Record<string, never> | undefined = undefined;
</script>
<div class="container-fluid mb-5">
<Container --gutter-block="2px" --container-margin="0" {api}>
<h1>{title}</h1>
<Section {api}>
<slot />
</Section>
</div>
<slot />
</Container>
<style lang="scss">
h1 {
border-bottom: 1px solid var(--medium-border);
}
.container-fluid {
break-inside: avoid;
}
</style>

View file

@ -29,6 +29,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
>
<Badge
class="opacity-50"
iconSize={85}
on:mount={(event) => createTooltip(event.detail.span)}
>
{@html infoCircle}

View file

@ -4,7 +4,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import { slide } from "svelte/transition";
import Row from "./Row.svelte";
import Row from "../components/Row.svelte";
import { withoutUnicodeIsolation } from "../lib/i18n/";
export let warning: string;

View file

@ -1,7 +1,5 @@
@import "sass/base";
@import "sass/bootstrap/scss/containers";
@import "sass/bootstrap/scss/grid";
@import "sass/bootstrap/scss/dropdown";
@import "sass/bootstrap/scss/buttons";
@import "sass/bootstrap/scss/button-group";

View file

@ -37,7 +37,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<script lang="ts">
import StickyHeader from "../components/StickyHeader.svelte";
import StickyContainer from "../components/StickyContainer.svelte";
import ButtonToolbar from "../components/ButtonToolbar.svelte";
import Item from "../components/Item.svelte";
@ -72,7 +72,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
} as EditorToolbarAPI);
</script>
<StickyHeader>
<StickyContainer --gutter-block="0.1rem" --sticky-borders="0 0 1px">
<ButtonToolbar {size} {wrap} api={toolbar}>
<Item id="notetype">
<NoteTypeButtons api={notetypeButtons} />
@ -94,4 +94,4 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<TemplateButtons api={templateButtons} />
</Item>
</ButtonToolbar>
</StickyHeader>
</StickyContainer>

View file

@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import { createEventDispatcher, tick } from "svelte";
import type { Writable } from "svelte/store";
import StickyFooter from "../components/StickyFooter.svelte";
import StickyContainer from "../components/StickyContainer.svelte";
import TagOptionsBadge from "./TagOptionsBadge.svelte";
import TagEditMode from "./TagEditMode.svelte";
import TagInput from "./TagInput.svelte";
@ -395,7 +395,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
$: shortenTags = shortenTags || assumedRows > 2;
</script>
<StickyFooter bind:height class="d-flex">
<StickyContainer
--gutter-block="0.1rem"
--sticky-borders="1px 0 0"
bind:height
class="d-flex"
>
{#if !wrap}
<TagOptionsBadge
showSelectionsOptions={tagTypes.some((tag) => tag.selected)}
@ -504,7 +509,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<Tag>SPACER</Tag>
</div>
</ButtonToolbar>
</StickyFooter>
</StickyContainer>
<style lang="scss">
.tag-spacer {

View file

@ -12,7 +12,7 @@
{ "path": "reviewer" },
{ "path": "lib" },
{ "path": "domlib" },
{ "path": "sveltelib" },
{ "path": "sveltelib" }
],
"compilerOptions": {
"declaration": true,