web: add content warning to compose
This commit is contained in:
parent
70b55da9bd
commit
6a626dd381
6 changed files with 121 additions and 16 deletions
|
@ -8,6 +8,11 @@
|
|||
<title>nyanoblog</title>
|
||||
</head>
|
||||
<body>
|
||||
<script id="nyano-config" type="application/json">
|
||||
{
|
||||
"maxNoteChars": 500
|
||||
}
|
||||
</script>
|
||||
<nyano-blog unresolved></nyano-blog>
|
||||
<link rel="stylesheet" type="text/css" href="font/source-sans/source-sans-3.css">
|
||||
<link rel="stylesheet" type="text/css" href="/theme.css">
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
--border-radius-large: 16px;
|
||||
|
||||
--font-family: "Source Sans 3", sans-serif;
|
||||
|
||||
--anim-duration-short: 60ms;
|
||||
}
|
||||
|
||||
html, body {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {LitElement, html, css} from "lit";
|
||||
import {customElement, property} from "lit/decorators.js";
|
||||
import {customElement, property, state} from "lit/decorators.js";
|
||||
|
||||
import withSharedStyles from "../theme";
|
||||
|
||||
@customElement("nyano-button")
|
||||
|
@ -7,7 +8,7 @@ export default class NyanoButton extends LitElement {
|
|||
@property({type: Boolean, attribute: true})
|
||||
public disabled = false;
|
||||
|
||||
@property({type: Boolean})
|
||||
@state()
|
||||
private pressed = false;
|
||||
|
||||
protected render() {
|
||||
|
@ -31,17 +32,17 @@ export default class NyanoButton extends LitElement {
|
|||
}
|
||||
|
||||
button {
|
||||
font: bold 1.1rem var(--font-family);
|
||||
font: bold 1rem var(--font-family);
|
||||
text-transform: uppercase;
|
||||
background-color: var(--accent-color);
|
||||
color: var(--accent-text-color);
|
||||
padding: var(--border-radius) calc(var(--border-radius) * 2);
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow:
|
||||
0 0 10px 2px inset rgba(0, 0, 0, 0.4),
|
||||
0 0 3px 0 inset rgba(0, 0, 0, 0.4);
|
||||
rgba(0, 0, 0, 0.5) 0 -2px 10px 2px inset,
|
||||
rgba(0, 0, 0, 0.4) 0 0 4px 0 inset;
|
||||
border: none;
|
||||
transition-duration: 100ms;
|
||||
transition-duration: 50ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
transition-property: background-color, color, filter, transform;
|
||||
transform-origin: center;
|
||||
|
|
62
src/web/components/input-field.ts
Normal file
62
src/web/components/input-field.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import {LitElement, html, css} from "lit";
|
||||
import {customElement, property, query} from "lit/decorators.js";
|
||||
|
||||
import withSharedStyles from "../theme";
|
||||
|
||||
@customElement("input-field")
|
||||
export default class InputField extends LitElement {
|
||||
@query("#input")
|
||||
private input: HTMLInputElement;
|
||||
|
||||
@property({type: String})
|
||||
public value = "";
|
||||
|
||||
@property({type: String, attribute: true})
|
||||
public placeholder = "";
|
||||
|
||||
@property({type: Number, attribute: true})
|
||||
public maxlength: number | undefined = undefined;
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<input
|
||||
id="input"
|
||||
.value="${this.value}"
|
||||
placeholder="${this.placeholder}"
|
||||
maxlength="${this.maxlength}"
|
||||
@input=${() => this.value = this.input.value}
|
||||
>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return withSharedStyles(css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
display: block;
|
||||
font-size: 1rem;
|
||||
font-family: var(--font-family);
|
||||
color: var(--text-color);
|
||||
padding: 8px;
|
||||
background-color: var(--background-lighter-color);
|
||||
border: none;
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: inset 0 1px 1px 0 rgba(255, 255, 255, 0.15);
|
||||
transition: box-shadow ease-in-out var(--anim-duration-short);
|
||||
}
|
||||
|
||||
input:focus-visible {
|
||||
outline: 0;
|
||||
box-shadow:
|
||||
inset 0 1px 1px 0 var(--accent-highlight-color),
|
||||
0 0 2px 0 var(--accent-highlight-color);
|
||||
}
|
||||
`);
|
||||
}
|
||||
}
|
9
src/web/config.ts
Normal file
9
src/web/config.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
export interface Config {
|
||||
maxNoteChars: number,
|
||||
}
|
||||
|
||||
const config: Config = JSON.parse(document.getElementById("nyano-config").innerText);
|
||||
export default config;
|
||||
|
||||
/** Maximum number of Unicode code points per note, including CW */
|
||||
export const maxNoteChars = config.maxNoteChars;
|
|
@ -1,12 +1,21 @@
|
|||
import {LitElement, html, css} from "lit";
|
||||
import {customElement, query, state} from "lit/decorators.js";
|
||||
|
||||
import { maxNoteChars } from "../config";
|
||||
import withSharedStyles from "../theme";
|
||||
|
||||
import "../components/button";
|
||||
import "../components/input-field";
|
||||
import InputField from "../components/input-field";
|
||||
|
||||
@customElement("compose-form")
|
||||
export default class ComposeForm extends LitElement {
|
||||
@query("#summary")
|
||||
private summaryInput: InputField;
|
||||
|
||||
@state()
|
||||
private summary = "";
|
||||
|
||||
@query("#content")
|
||||
private contentInput: HTMLTextAreaElement;
|
||||
|
||||
|
@ -15,18 +24,30 @@ export default class ComposeForm extends LitElement {
|
|||
|
||||
protected render() {
|
||||
return html`
|
||||
<textarea id="content" placeholder="Say something nice" @input=${this.onInput}></textarea>
|
||||
<input-field
|
||||
id="summary"
|
||||
placeholder="Content warning (optional)"
|
||||
maxlength="${maxNoteChars - this.content.length}"
|
||||
@input=${() => this.summary = this.summaryInput.value}
|
||||
></input-field>
|
||||
<textarea
|
||||
id="content"
|
||||
placeholder="Say something nice"
|
||||
@input=${() => this.content = this.contentInput.value}
|
||||
maxlength="${maxNoteChars - this.summary.length}"
|
||||
></textarea>
|
||||
<div id="bar">
|
||||
<div id="actions">${this.content.length}</div>
|
||||
<div id="actions">
|
||||
|
||||
</div>
|
||||
<div id="length">
|
||||
${maxNoteChars - this.summary.length - this.content.length}
|
||||
</div>
|
||||
<nyano-button ?disabled=${this.content.length === 0}>Meow!</nyano-button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private onInput() {
|
||||
this.content = this.contentInput.value;
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return withSharedStyles(css`
|
||||
textarea {
|
||||
|
@ -39,17 +60,17 @@ export default class ComposeForm extends LitElement {
|
|||
background-color: var(--background-lighter-color);
|
||||
color: var(--text-color);
|
||||
border: none;
|
||||
box-shadow: 0 1px 1px 0 inset rgba(255, 255, 255, 0.15);
|
||||
box-shadow: inset 0 1px 1px 0 rgba(255, 255, 255, 0.15);
|
||||
border-radius: var(--border-radius);
|
||||
resize: none;
|
||||
transition: box-shadow ease-in-out 100ms;
|
||||
transition: box-shadow ease-in-out var(--anim-duration-short);
|
||||
}
|
||||
|
||||
textarea:focus-visible {
|
||||
outline: 0;
|
||||
box-shadow:
|
||||
0 1px 1px 0 inset rgba(255, 255, 255, 0.15),
|
||||
0 0 4px 0 var(--accent-highlight-color);
|
||||
inset 0 1px 1px 0 var(--accent-highlight-color),
|
||||
0 0 2px 0 var(--accent-highlight-color);
|
||||
}
|
||||
|
||||
#bar {
|
||||
|
@ -62,6 +83,11 @@ export default class ComposeForm extends LitElement {
|
|||
flex: 1;
|
||||
}
|
||||
|
||||
#length {
|
||||
padding: 8px 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
nyano-button {
|
||||
margin: 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue