WIP PWA for Grain
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add grain-textarea atom with character counter

+75
+75
src/components/atoms/grain-textarea.js
··· 1 + import { LitElement, html, css } from 'lit'; 2 + 3 + export class GrainTextarea extends LitElement { 4 + static properties = { 5 + placeholder: { type: String }, 6 + value: { type: String }, 7 + maxlength: { type: Number } 8 + }; 9 + 10 + static styles = css` 11 + :host { 12 + display: block; 13 + } 14 + textarea { 15 + width: 100%; 16 + padding: var(--space-sm); 17 + border: 1px solid var(--color-border); 18 + border-radius: 6px; 19 + background: var(--color-bg-primary); 20 + color: var(--color-text-primary); 21 + font-size: var(--font-size-sm); 22 + font-family: inherit; 23 + box-sizing: border-box; 24 + min-height: 100px; 25 + resize: vertical; 26 + } 27 + textarea::placeholder { 28 + color: var(--color-text-secondary); 29 + } 30 + textarea:focus { 31 + outline: none; 32 + border-color: var(--color-text-secondary); 33 + } 34 + .char-count { 35 + font-size: var(--font-size-xs); 36 + color: var(--color-text-secondary); 37 + text-align: right; 38 + margin-top: 4px; 39 + } 40 + `; 41 + 42 + constructor() { 43 + super(); 44 + this.placeholder = ''; 45 + this.value = ''; 46 + this.maxlength = null; 47 + } 48 + 49 + #handleInput(e) { 50 + this.value = this.maxlength 51 + ? e.target.value.slice(0, this.maxlength) 52 + : e.target.value; 53 + this.dispatchEvent(new CustomEvent('input', { 54 + detail: { value: this.value }, 55 + bubbles: true, 56 + composed: true 57 + })); 58 + } 59 + 60 + render() { 61 + return html` 62 + <textarea 63 + placeholder=${this.placeholder} 64 + .value=${this.value} 65 + @input=${this.#handleInput} 66 + maxlength=${this.maxlength || ''} 67 + ></textarea> 68 + ${this.maxlength ? html` 69 + <div class="char-count">${this.value.length}/${this.maxlength}</div> 70 + ` : ''} 71 + `; 72 + } 73 + } 74 + 75 + customElements.define('grain-textarea', GrainTextarea);