mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-07 02:22:52 +00:00
feat: settings wip
This commit is contained in:
89
src/lib/components/layout/Layout.svelte
Normal file
89
src/lib/components/layout/Layout.svelte
Normal file
@@ -0,0 +1,89 @@
|
||||
<script>
|
||||
import {serialPort} from "$lib/serial/connection"
|
||||
import LayoutCC1 from "$lib/components/layout/LayoutCC1.svelte"
|
||||
|
||||
$: device = $serialPort?.device ?? "ONE"
|
||||
let activeLayer = 0
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<select bind:value={device}>
|
||||
<option value="ONE">CC1</option>
|
||||
<option value="LITE">Lite</option>
|
||||
</select>
|
||||
|
||||
<fieldset>
|
||||
{#each [["Numeric Layer", "123", 1], ["Primary Layer", "abc", 0], ["Function Layer", "function", 2]] as [title, icon, value]}
|
||||
<button
|
||||
{title}
|
||||
class="icon"
|
||||
on:click={() => (activeLayer = value)}
|
||||
class:active={activeLayer === value}
|
||||
>
|
||||
{icon}
|
||||
</button>
|
||||
{/each}
|
||||
</fieldset>
|
||||
|
||||
{#if device === "ONE"}
|
||||
<LayoutCC1 bind:activeLayer />
|
||||
{:else}
|
||||
<p>Unsupported device ({$serialPort?.device})</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
fieldset {
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
margin-block-end: -36px;
|
||||
padding: 0;
|
||||
|
||||
border: none;
|
||||
}
|
||||
|
||||
button.icon {
|
||||
cursor: pointer;
|
||||
|
||||
z-index: 1;
|
||||
|
||||
font-size: 24px;
|
||||
color: var(--md-sys-color-on-surface-variant);
|
||||
|
||||
background: var(--md-sys-color-surface-variant);
|
||||
border: none;
|
||||
|
||||
transition: all 250ms ease;
|
||||
|
||||
&:nth-child(2) {
|
||||
z-index: 2;
|
||||
|
||||
aspect-ratio: 1;
|
||||
|
||||
font-size: 32px;
|
||||
|
||||
border-radius: 50%;
|
||||
outline: 8px solid var(--md-sys-color-background);
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
padding-inline-end: 16px;
|
||||
border-radius: 16px 0 0 16px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-inline-start: 16px;
|
||||
border-radius: 0 16px 16px 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: 900;
|
||||
color: var(--md-sys-color-on-tertiary);
|
||||
background: var(--md-sys-color-tertiary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,121 +1,52 @@
|
||||
<script>
|
||||
import RingInput from "$lib/components/layout/RingInput.svelte"
|
||||
|
||||
let activeLayer = 0
|
||||
export let activeLayer = 0
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<fieldset>
|
||||
{#each [["Numeric Layer", "123", 1], ["Primary Layer", "abc", 0], ["Function Layer", "function", 2]] as [title, icon, value]}
|
||||
<button
|
||||
{title}
|
||||
class="icon"
|
||||
on:click={() => (activeLayer = value)}
|
||||
class:active={activeLayer === value}
|
||||
>
|
||||
{icon}
|
||||
</button>
|
||||
{/each}
|
||||
</fieldset>
|
||||
|
||||
<div class="col layout" style="gap: 0">
|
||||
<div class="row" style="gap: 156px">
|
||||
<div class="row">
|
||||
<RingInput {activeLayer} keys={{d: 30, e: 31, n: 32, w: 33, s: 34}} type="tertiary" />
|
||||
<div class="col">
|
||||
<RingInput {activeLayer} keys={{d: 25, e: 26, n: 27, w: 28, s: 29}} />
|
||||
<RingInput {activeLayer} keys={{d: 40, e: 41, n: 42, w: 43, s: 44}} type="secondary" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<RingInput {activeLayer} keys={{d: 20, e: 21, n: 22, w: 23, s: 24}} />
|
||||
<RingInput {activeLayer} keys={{d: 35, e: 36, n: 37, w: 38, s: 39}} type="secondary" />
|
||||
</div>
|
||||
<RingInput {activeLayer} keys={{d: 15, e: 16, n: 17, w: 18, s: 19}} />
|
||||
<div class="col layout" style="gap: 0">
|
||||
<div class="row" style="gap: 156px">
|
||||
<div class="row">
|
||||
<RingInput {activeLayer} keys={{d: 30, e: 31, n: 32, w: 33, s: 34}} type="tertiary" />
|
||||
<div class="col">
|
||||
<RingInput {activeLayer} keys={{d: 25, e: 26, n: 27, w: 28, s: 29}} />
|
||||
<RingInput {activeLayer} keys={{d: 40, e: 41, n: 42, w: 43, s: 44}} type="secondary" />
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<RingInput {activeLayer} keys={{d: 60, w: 61, n: 62, e: 63, s: 64}} />
|
||||
<div class="col">
|
||||
<RingInput {activeLayer} keys={{d: 65, w: 66, n: 67, e: 68, s: 69}} />
|
||||
<RingInput {activeLayer} keys={{d: 80, w: 81, n: 82, e: 83, s: 84}} />
|
||||
</div>
|
||||
<div class="col">
|
||||
<RingInput {activeLayer} keys={{d: 70, w: 71, n: 72, e: 73, s: 74}} />
|
||||
<RingInput {activeLayer} keys={{d: 85, w: 86, n: 87, e: 88, s: 89}} />
|
||||
</div>
|
||||
<RingInput {activeLayer} keys={{d: 75, w: 76, n: 77, e: 78, s: 79}} />
|
||||
<div class="col">
|
||||
<RingInput {activeLayer} keys={{d: 20, e: 21, n: 22, w: 23, s: 24}} />
|
||||
<RingInput {activeLayer} keys={{d: 35, e: 36, n: 37, w: 38, s: 39}} type="secondary" />
|
||||
</div>
|
||||
<RingInput {activeLayer} keys={{d: 15, e: 16, n: 17, w: 18, s: 19}} />
|
||||
</div>
|
||||
<div class="row" style="gap: 48px; margin-top: -32px">
|
||||
<RingInput {activeLayer} keys={{d: 10, e: 11, n: 12, w: 13, s: 14}} />
|
||||
<RingInput {activeLayer} keys={{d: 55, w: 56, n: 57, e: 58, s: 59}} />
|
||||
</div>
|
||||
<div class="row" style="gap: 160px">
|
||||
<RingInput {activeLayer} keys={{d: 5, e: 6, n: 7, w: 8, s: 9}} />
|
||||
<RingInput {activeLayer} keys={{d: 50, w: 51, n: 52, e: 53, s: 54}} />
|
||||
</div>
|
||||
<div class="row" style="gap: 320px; margin-top: -12px">
|
||||
<RingInput {activeLayer} keys={{d: 0, e: 1, n: 2, w: 3, s: 4}} type="secondary" />
|
||||
<RingInput {activeLayer} keys={{d: 45, w: 46, n: 47, e: 48, s: 49}} type="secondary" />
|
||||
|
||||
<div class="row">
|
||||
<RingInput {activeLayer} keys={{d: 60, w: 61, n: 62, e: 63, s: 64}} />
|
||||
<div class="col">
|
||||
<RingInput {activeLayer} keys={{d: 65, w: 66, n: 67, e: 68, s: 69}} />
|
||||
<RingInput {activeLayer} keys={{d: 80, w: 81, n: 82, e: 83, s: 84}} />
|
||||
</div>
|
||||
<div class="col">
|
||||
<RingInput {activeLayer} keys={{d: 70, w: 71, n: 72, e: 73, s: 74}} />
|
||||
<RingInput {activeLayer} keys={{d: 85, w: 86, n: 87, e: 88, s: 89}} />
|
||||
</div>
|
||||
<RingInput {activeLayer} keys={{d: 75, w: 76, n: 77, e: 78, s: 79}} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="gap: 48px; margin-top: -32px">
|
||||
<RingInput {activeLayer} keys={{d: 10, e: 11, n: 12, w: 13, s: 14}} />
|
||||
<RingInput {activeLayer} keys={{d: 55, w: 56, n: 57, e: 58, s: 59}} />
|
||||
</div>
|
||||
<div class="row" style="gap: 160px">
|
||||
<RingInput {activeLayer} keys={{d: 5, e: 6, n: 7, w: 8, s: 9}} />
|
||||
<RingInput {activeLayer} keys={{d: 50, w: 51, n: 52, e: 53, s: 54}} />
|
||||
</div>
|
||||
<div class="row" style="gap: 320px; margin-top: -12px">
|
||||
<RingInput {activeLayer} keys={{d: 0, e: 1, n: 2, w: 3, s: 4}} type="secondary" />
|
||||
<RingInput {activeLayer} keys={{d: 45, w: 46, n: 47, e: 48, s: 49}} type="secondary" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
fieldset {
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
margin-block-end: -36px;
|
||||
padding: 0;
|
||||
|
||||
border: none;
|
||||
}
|
||||
|
||||
button.icon {
|
||||
cursor: pointer;
|
||||
|
||||
z-index: 1;
|
||||
|
||||
font-size: 24px;
|
||||
color: var(--md-sys-color-on-surface-variant);
|
||||
|
||||
background: var(--md-sys-color-surface-variant);
|
||||
border: none;
|
||||
|
||||
transition: all 250ms ease;
|
||||
|
||||
&:nth-child(2) {
|
||||
z-index: 2;
|
||||
|
||||
aspect-ratio: 1;
|
||||
|
||||
font-size: 32px;
|
||||
|
||||
border-radius: 50%;
|
||||
outline: 8px solid var(--md-sys-color-background);
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
padding-inline-end: 16px;
|
||||
border-radius: 16px 0 0 16px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-inline-start: 16px;
|
||||
border-radius: 0 16px 16px 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: 900;
|
||||
color: var(--md-sys-color-on-tertiary);
|
||||
background: var(--md-sys-color-tertiary);
|
||||
}
|
||||
}
|
||||
|
||||
.row,
|
||||
.col {
|
||||
display: flex;
|
||||
|
||||
@@ -2,6 +2,7 @@ import {LineBreakTransformer} from "$lib/serial/line-break-transformer"
|
||||
import {serialLog} from "$lib/serial/connection"
|
||||
import type {Chord} from "$lib/serial/chord"
|
||||
import {parseChordActions, parsePhrase, stringifyChordActions, stringifyPhrase} from "$lib/serial/chord"
|
||||
import {dev} from "$app/environment"
|
||||
|
||||
export const VENDOR_ID = 0x239a
|
||||
|
||||
@@ -24,8 +25,10 @@ export class CharaDevice {
|
||||
|
||||
private lock?: Promise<true>
|
||||
|
||||
version!: string
|
||||
deviceId!: string
|
||||
version!: [number, number, number]
|
||||
company!: "CHARACHORDER"
|
||||
device!: "ONE" | "LITE"
|
||||
chipset!: "M0" | "S2"
|
||||
|
||||
constructor(private readonly baudRate = 115200) {}
|
||||
|
||||
@@ -58,8 +61,12 @@ export class CharaDevice {
|
||||
})
|
||||
.getReader()
|
||||
|
||||
this.version = await this.send("VERSION").then(it => it[0])
|
||||
this.deviceId = await this.send("ID").then(it => it[0])
|
||||
const [version] = await this.send("VERSION")
|
||||
this.version = version.split(".").map(Number) as [number, number, number]
|
||||
const [company, device, chipset] = await this.send("ID")
|
||||
this.company = company as "CHARACHORDER"
|
||||
this.device = device as "ONE" | "LITE"
|
||||
this.chipset = chipset as "M0" | "S2"
|
||||
}
|
||||
|
||||
private async internalRead() {
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
export interface DeviceSettings {
|
||||
enableSerialLog: boolean
|
||||
enableSerialRaw: boolean
|
||||
enableSerialChord: boolean
|
||||
enableSerialKeyboard: boolean
|
||||
enableSerialMouse: boolean
|
||||
enableSerialDebug: boolean
|
||||
enableSerialHeader: boolean
|
||||
enableHidKeyboard: boolean
|
||||
pressThreshold: number
|
||||
releaseThreshold: number
|
||||
enableHidMouse: number
|
||||
scrollDelay: number
|
||||
enableSpurring: boolean
|
||||
spurKillerToggle: number
|
||||
spurKiller: number
|
||||
enableChording: boolean
|
||||
charKillerToggle: number
|
||||
charCounterKiller: number
|
||||
}
|
||||
|
||||
export const SETTING_IDS: Record<keyof DeviceSettings, number> = {
|
||||
enableSerialLog: 0x01,
|
||||
enableSerialRaw: 0x02,
|
||||
enableSerialChord: 0x03,
|
||||
enableSerialKeyboard: 0x04,
|
||||
enableSerialMouse: 0x05,
|
||||
enableSerialDebug: 0x06,
|
||||
enableSerialHeader: 0x07,
|
||||
enableHidKeyboard: 0x0a,
|
||||
pressThreshold: 0x0b,
|
||||
releaseThreshold: 0x0c,
|
||||
enableHidMouse: 0x14,
|
||||
scrollDelay: 0x15,
|
||||
enableSpurring: 0x1e,
|
||||
spurKillerToggle: 0x1f,
|
||||
spurKiller: 0x20,
|
||||
enableChording: 0x28,
|
||||
charKillerToggle: 0x29,
|
||||
charCounterKiller: 0x2a,
|
||||
}
|
||||
@@ -4,6 +4,7 @@ $height: 1.5em;
|
||||
|
||||
label:has(input[type="checkbox"]) {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
display: flex;
|
||||
gap: $padding;
|
||||
@@ -12,7 +13,7 @@ label:has(input[type="checkbox"]) {
|
||||
|
||||
font-size: 12px;
|
||||
|
||||
input {
|
||||
input[type="checkbox"] {
|
||||
$width: calc($height * (5 / 3));
|
||||
$diameter: calc($height - ((2 * $padding) + (2 * $border)));
|
||||
$radius: calc($diameter / 2);
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
.disclaimer {
|
||||
@@ -91,6 +93,7 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
width: max-content;
|
||||
height: 48px;
|
||||
padding-block: 8px;
|
||||
padding-inline: 16px;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {initSerial, serialPort} from "$lib/serial/connection"
|
||||
import {browser} from "$app/environment"
|
||||
import {slide, fade, fly} from "svelte/transition"
|
||||
import {slide, fade} from "svelte/transition"
|
||||
import {preference} from "$lib/preferences"
|
||||
import Terminal from "$lib/components/Terminal.svelte"
|
||||
|
||||
let terminal = false
|
||||
let powerDialog = false
|
||||
@@ -17,9 +16,11 @@
|
||||
|
||||
{#if $serialPort}
|
||||
<p transition:slide>
|
||||
{$serialPort.deviceId}
|
||||
{$serialPort.company}
|
||||
{$serialPort.device}
|
||||
{$serialPort.chipset}
|
||||
<br />
|
||||
Version {$serialPort.version}
|
||||
Version {$serialPort.version.map(it => it.toString()).join(".")}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import type {Chord} from "$lib/serial/chord"
|
||||
import tippy from "tippy.js"
|
||||
import {calculateChordCoverage} from "$lib/chords/coverage"
|
||||
import {SETTING_IDS} from "$lib/serial/settings"
|
||||
|
||||
$: searchIndex = $chords?.length > 0 ? buildIndex($chords) : undefined
|
||||
|
||||
@@ -45,11 +44,6 @@
|
||||
{/if}
|
||||
<button class="icon" on:click={sort}>sort</button>
|
||||
<button class="icon">filter_list</button>
|
||||
{#if $serialPort}
|
||||
{#await $serialPort.getSetting(SETTING_IDS.enableChording) then enableChording}
|
||||
<label><input type="checkbox" checked={enableChording !== 0} /> Enable Chording</label>
|
||||
{/await}
|
||||
{/if}
|
||||
|
||||
<section>
|
||||
<table>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import LayoutCC1 from "$lib/components/layout/LayoutCC1.svelte"
|
||||
import {share} from "$lib/share"
|
||||
import {layout} from "$lib/serial/connection"
|
||||
import tippy from "tippy.js"
|
||||
import {onMount} from "svelte"
|
||||
import {layoutAsUrlComponent, layoutFromUrlComponent} from "$lib/serialization/layout"
|
||||
import Layout from "$lib/components/layout/Layout.svelte"
|
||||
|
||||
onMount(async () => {
|
||||
const url = new URL(window.location.href)
|
||||
@@ -30,7 +30,7 @@
|
||||
<svelte:window use:share={shareLayout} />
|
||||
|
||||
<section>
|
||||
<LayoutCC1 />
|
||||
<Layout />
|
||||
</section>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -1,4 +1,193 @@
|
||||
<script>
|
||||
import {serialPort} from "$lib/serial/connection"
|
||||
</script>
|
||||
|
||||
<label><input type="checkbox" />Serial Log</label>
|
||||
{#if $serialPort}
|
||||
<form>
|
||||
<fieldset>
|
||||
<legend><label><input type="checkbox" />Spurring</label></legend>
|
||||
<p>
|
||||
"Chording only" mode which tells your device to output chords on a press rather than a press &
|
||||
release. It also enables you to jump from one chord to another without releasing everything and can be
|
||||
activated in GTM or by chording both mirror keys. It can provide significant speed gains with
|
||||
chording, but also takes away the flexibility of character entry.
|
||||
</p>
|
||||
<p>Spurring also helps new users learn how to chord by eliminating the need to focus on timing.</p>
|
||||
<p>Spurring is toggled by chording both of the 'mirror' keys together.</p>
|
||||
<label
|
||||
>Character Counter Timeout<span class="unit"
|
||||
><input type="number" step="0.1" min="0" max="25.5" />s</span
|
||||
></label
|
||||
>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend><label><input type="checkbox" />Arpeggiates</label></legend>
|
||||
<p>
|
||||
A quick, single key press and release used to indicate a suffix, prefix, or modifier to be associated
|
||||
with a chord.
|
||||
</p>
|
||||
<label>Tolerance<span class="unit"><input type="number" step="1" />ms</span></label>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend><label><input type="checkbox" />Character Entry</label></legend>
|
||||
<label>Swap Keymap 0 and 1<input type="checkbox" /></label>
|
||||
<label>Key Scan Rate<span class="unit"><input type="number" />Hz</span></label>
|
||||
<label>Key Debounce Press<span class="unit"><input type="number" />ms</span></label>
|
||||
<label>Key Debounce Release<span class="unit"><input type="number" />ms</span></label>
|
||||
<label>Output Character Delay<span class="unit"><input type="number" />µs</span></label>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend><label><input type="checkbox" />Mouse</label></legend>
|
||||
<label>Mouse Speed<input type="number" /><input type="number" /></label>
|
||||
<label>Scroll Speed<input type="number" /></label>
|
||||
<label title="Bounces mouse by 1px every 60s if enabled">Active Mouse<input type="checkbox" /></label>
|
||||
<label>Poll Rate<span class="unit"><input type="number" />Hz</span></label>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend><label><input type="checkbox" />Chording</label></legend>
|
||||
<label
|
||||
>Character Timeout <span class="unit"><input type="number" min="0" max="25.5" step="0.1" />s</span
|
||||
></label
|
||||
>
|
||||
<label
|
||||
>Detection Tolerance<span class="unit"><input type="number" min="1" max="50" step="1" />ms</span
|
||||
></label
|
||||
>
|
||||
<label
|
||||
>Release Tolerance<span class="unit"><input type="number" min="1" max="50" step="1" />ms</span></label
|
||||
>
|
||||
<label>Compound Chording<input type="checkbox" /></label>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend><label>Device</label></legend>
|
||||
<label>Boot message<input type="checkbox" /></label>
|
||||
<label>Realtime Feedback<input type="checkbox" /></label>
|
||||
<label>
|
||||
Operating System
|
||||
<select>
|
||||
<option value="0">Windows</option>
|
||||
<option value="1">MacOS</option>
|
||||
<option value="2">Linux</option>
|
||||
<option value="3">iOS</option>
|
||||
<option value="4">Android</option>
|
||||
<option value="255">Unknown</option>
|
||||
</select>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
{#if $serialPort.device === "LITE"}
|
||||
<fieldset>
|
||||
<legend><label><input type="checkbox" />RGB</label></legend>
|
||||
<label>Brightness<input type="range" min="0" max="50" step="1" /></label>
|
||||
<label>Color</label>
|
||||
<label>Reactive Keys<input type="checkbox" /></label>
|
||||
</fieldset>
|
||||
{/if}
|
||||
</form>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
form {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
gap: 16px;
|
||||
justify-content: center;
|
||||
|
||||
max-width: 30cm;
|
||||
margin-block: auto;
|
||||
}
|
||||
|
||||
legend,
|
||||
legend > label {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
|
||||
> input {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
fieldset {
|
||||
max-width: 400px;
|
||||
border: 1px solid var(--md-sys-color-outline);
|
||||
border-radius: 24px;
|
||||
|
||||
> label {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
margin-block: 4px;
|
||||
|
||||
font-size: 14px;
|
||||
|
||||
&:has(input[type="number"]) {
|
||||
cursor: text;
|
||||
|
||||
&:hover {
|
||||
filter: none;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.unit {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
width: 67px;
|
||||
padding-inline-end: auto;
|
||||
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
|
||||
background: var(--md-sys-color-secondary-container);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
display: flex;
|
||||
|
||||
width: 5ch;
|
||||
height: 100%;
|
||||
padding-block: 4px;
|
||||
|
||||
font-family: "Noto Sans Mono", monospace;
|
||||
color: var(--md-sys-color-on-secondary);
|
||||
text-align: end;
|
||||
|
||||
background: var(--md-sys-color-secondary);
|
||||
border: none;
|
||||
|
||||
&::-webkit-inner-spin-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "bleh";
|
||||
}
|
||||
|
||||
&:focus {
|
||||
filter: brightness(120%);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user