refactor: tighten up css
created a bunch of utility classes and use those instead
This commit is contained in:
		@@ -2,13 +2,13 @@
 | 
			
		||||
 import { version } from '$app/environment';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="about d-flex col no-select">
 | 
			
		||||
    <h1 class="litechat">litechat<span class="plus">plus</span></h1>
 | 
			
		||||
<div class="about d-flex col no-select text-center">
 | 
			
		||||
    <h1 class="litechat mb-0 color-300">litechat<span class="plus color-cyan super">plus</span></h1>
 | 
			
		||||
    <p>A [<i>fedwave</i>] chat client.</p>
 | 
			
		||||
    <div class="d-flex build-info">
 | 
			
		||||
    <div class="d-flex build-info px-24 select-text color-400">
 | 
			
		||||
	<p class="version">Version: {version}</p>
 | 
			
		||||
	<div class="spacer" />
 | 
			
		||||
	<p class="commit">{__COMMIT__}</p>
 | 
			
		||||
	<p class="commit select-all">{__COMMIT__}</p>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@@ -16,29 +16,6 @@
 | 
			
		||||
 .about {
 | 
			
		||||
     height: var(--top-screen-cutout-height);
 | 
			
		||||
     width: var(--sidebar-width, 350px);
 | 
			
		||||
     text-align: center;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .litechat {
 | 
			
		||||
     color: var(--base-300);
 | 
			
		||||
 | 
			
		||||
     margin-bottom: 0px;
 | 
			
		||||
 | 
			
		||||
     & .plus {
 | 
			
		||||
	 vertical-align: super;
 | 
			
		||||
	 color: var(--cyan);
 | 
			
		||||
     }
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .build-info {
 | 
			
		||||
     padding-left: 24px;
 | 
			
		||||
     padding-right: 24px;
 | 
			
		||||
     & > * {
 | 
			
		||||
	 user-select: text;
 | 
			
		||||
     }
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .version {
 | 
			
		||||
     color: var(--base-400);
 | 
			
		||||
 }
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,9 @@
 | 
			
		||||
 export let size: string = 'var(--avatar-size)';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="avatar" style:--color="{color}" style:--size="{size}" on:click>
 | 
			
		||||
<button class="avatar pa-0 border-0" style:--color="{color}" style:--size="{size}" on:click>
 | 
			
		||||
    <img src="{avatar}" alt="{`${username}'s avatar`}">
 | 
			
		||||
</div>
 | 
			
		||||
</button>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
 .avatar, .avatar > img {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,15 +6,15 @@
 | 
			
		||||
 export let isHeader: boolean = true;
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="message" class:subseq="{!isHeader}">
 | 
			
		||||
<div class="message d-flex p-relative pl-8 pr-24" class:subseq="{!isHeader}">
 | 
			
		||||
    {#if isHeader}
 | 
			
		||||
	<div class="avatar" style="background-color: {message.color}">
 | 
			
		||||
	    <img alt="{message.username}'s avatar" src="{message.avatar || '/troll_haz2.png'}">
 | 
			
		||||
	<div class="avatar radius-pill overflow-hidden no-select" style="background-color: {message.color}">
 | 
			
		||||
	    <img class="w-100" alt="{message.username}'s avatar" src="{message.avatar || '/troll_haz2.png'}">
 | 
			
		||||
	</div>
 | 
			
		||||
    {/if}
 | 
			
		||||
    <div class="container">
 | 
			
		||||
	{#if isHeader}
 | 
			
		||||
	    <div class="top">
 | 
			
		||||
	    <div class="top d-flex grow-1">
 | 
			
		||||
		<div class="username">
 | 
			
		||||
		    {message.username}
 | 
			
		||||
		</div>
 | 
			
		||||
@@ -25,24 +25,25 @@
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="spacer" />
 | 
			
		||||
		{#if globalMode}
 | 
			
		||||
		    <a href="/{message.channel}" class="channel"
 | 
			
		||||
		    <a href="/{message.channel}" class="channel radius-4 px-2 text-end color-700 no-select"
 | 
			
		||||
		       class:local="{$room == message.channel.toLowerCase()}">
 | 
			
		||||
			{message.channel}
 | 
			
		||||
		    </a>
 | 
			
		||||
		{/if}
 | 
			
		||||
	    </div>
 | 
			
		||||
	{/if}
 | 
			
		||||
	<div class="text">
 | 
			
		||||
	<div class="text basis-0">
 | 
			
		||||
	    {@html message.message}
 | 
			
		||||
	</div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
 :root {
 | 
			
		||||
     --message-line-height: 22px;
 | 
			
		||||
     --avatar-size: 35px;
 | 
			
		||||
     --greentext-color: #789922;
 | 
			
		||||
     --message-group-spacing: 8px;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 * {
 | 
			
		||||
@@ -51,54 +52,26 @@
 | 
			
		||||
     font-family: IBM Plex Sans
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .message {
 | 
			
		||||
     position: relative;
 | 
			
		||||
     padding-left: 8px;
 | 
			
		||||
     padding-right: 24px;
 | 
			
		||||
 | 
			
		||||
     display: flex;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .message:last-child {
 | 
			
		||||
     margin-bottom: 12px;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .message:hover {
 | 
			
		||||
     background: var(--base-700);
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .avatar {
 | 
			
		||||
     border-radius: 9999px;
 | 
			
		||||
     overflow: hidden;
 | 
			
		||||
 | 
			
		||||
     min-height: var(--avatar-size);
 | 
			
		||||
     min-width: var(--avatar-size);
 | 
			
		||||
     max-height: var(--avatar-size);
 | 
			
		||||
     max-width: var(--avatar-size);
 | 
			
		||||
 | 
			
		||||
     user-select: none;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .avatar > img {
 | 
			
		||||
     width: 100%;
 | 
			
		||||
     height: auto
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .message:not(.subseq) {
 | 
			
		||||
     padding-top: 4px;
 | 
			
		||||
     margin-top: 8px;
 | 
			
		||||
     margin-top: var(--message-group-spacing);
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .subseq {
 | 
			
		||||
     margin-top: 0;
 | 
			
		||||
     padding-top: 0;
 | 
			
		||||
     padding-left: calc(16px + var(--avatar-size));
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .subseq > .container {
 | 
			
		||||
     margin-left: 0;
 | 
			
		||||
     padding-top: 2px;
 | 
			
		||||
     padding-bottom: 2px;
 | 
			
		||||
     padding-left: calc(16px + var(--avatar-size)) !important;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .container {
 | 
			
		||||
@@ -107,87 +80,72 @@
 | 
			
		||||
     justify-content: space-between;
 | 
			
		||||
     margin-left: 8px;
 | 
			
		||||
     width: 100%;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .top {
 | 
			
		||||
     display: flex;
 | 
			
		||||
     height: 18px;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .top .spacer {
 | 
			
		||||
     flex-grow: 1;
 | 
			
		||||
     .subseq > & {
 | 
			
		||||
	 margin-left: 0;
 | 
			
		||||
	 padding-top: 2px;
 | 
			
		||||
	 padding-bottom: 2px;
 | 
			
		||||
     }
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .username {
 | 
			
		||||
     font-weight: bold;
 | 
			
		||||
     font-optical-sizing: auto;
 | 
			
		||||
     height: 12px;
 | 
			
		||||
     font-family: IBM Plex Mono, Consolas, monospace;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .channel {
 | 
			
		||||
     --background: var(--base-600);
 | 
			
		||||
     border-radius: 4px;
 | 
			
		||||
     background-color: var(--background);
 | 
			
		||||
     padding-left: 2px;
 | 
			
		||||
     padding-right: 2px;
 | 
			
		||||
     background-color: var(--base-600);
 | 
			
		||||
 | 
			
		||||
     text-align: right;
 | 
			
		||||
     font-family: IBM Plex Mono, Consolas, monospace;
 | 
			
		||||
     text-transform: lowercase;
 | 
			
		||||
 | 
			
		||||
     color: var(--base-700);
 | 
			
		||||
 | 
			
		||||
     user-select: none;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .channel.local {
 | 
			
		||||
     --background: var(--cyan);
 | 
			
		||||
     background-color: var(--cyan);
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .text {
 | 
			
		||||
     flex-basis: 0;
 | 
			
		||||
 }
 | 
			
		||||
     & :global(.mention) {
 | 
			
		||||
	 font-weight: 800;
 | 
			
		||||
	 color: var(--yellow);
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
 .text :global(.mention) {
 | 
			
		||||
     font-weight: 800;
 | 
			
		||||
     color: var(--yellow);
 | 
			
		||||
 }
 | 
			
		||||
     & :global(p:empty), & :global(br:nth-last-child(1)), & :global(br) {
 | 
			
		||||
	 display: none;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
 .text :global(p:empty), .text :global(br:nth-last-child(1)), .text :global(br) {
 | 
			
		||||
     display: none;
 | 
			
		||||
 }
 | 
			
		||||
     & > :global(blockquote) {
 | 
			
		||||
	 margin: 0;
 | 
			
		||||
	 color: var(--greentext-color);
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
 .text > :global(blockquote) {
 | 
			
		||||
     margin: 0;
 | 
			
		||||
     color: var(--greentext-color);
 | 
			
		||||
 }
 | 
			
		||||
     & > :global(p), & > :global(blockquote) {
 | 
			
		||||
	 line-height: var(--message-line-height);
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
 .text > :global(p), .text > :global(blockquote) {
 | 
			
		||||
     line-height: var(--message-line-height);
 | 
			
		||||
 }
 | 
			
		||||
     & :global(h1) {
 | 
			
		||||
	 margin: 0;
 | 
			
		||||
	 margin-top: 8px;
 | 
			
		||||
	 margin-bottom: 8px;
 | 
			
		||||
	 font-size: 1.5em;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
 .text :global(h1) {
 | 
			
		||||
     margin: 0;
 | 
			
		||||
     margin-top: 8px;
 | 
			
		||||
     margin-bottom: 8px;
 | 
			
		||||
     font-size: 1.5em;
 | 
			
		||||
 }
 | 
			
		||||
     & :global(*) {
 | 
			
		||||
	 overflow-wrap: anywhere;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
 .text :global(*) {
 | 
			
		||||
     overflow-wrap: anywhere;
 | 
			
		||||
 }
 | 
			
		||||
     & :global(p) {
 | 
			
		||||
	 margin: 0;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
 .text :global(p) {
 | 
			
		||||
     margin: 0;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .text :global(img) {
 | 
			
		||||
     height: var(--message-line-height);
 | 
			
		||||
     vertical-align: bottom;
 | 
			
		||||
 }
 | 
			
		||||
 .text :global(h1 img) {
 | 
			
		||||
     height: calc(2 * var(--message-line-height));
 | 
			
		||||
     vertical-align: bottom;
 | 
			
		||||
     & :global(img) {
 | 
			
		||||
	 height: var(--message-line-height);
 | 
			
		||||
	 vertical-align: bottom;
 | 
			
		||||
     }
 | 
			
		||||
     & :global(h1 img) {
 | 
			
		||||
	 height: calc(2 * var(--message-line-height));
 | 
			
		||||
	 vertical-align: bottom;
 | 
			
		||||
     }
 | 
			
		||||
 }
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,90 +1,101 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
 import FAB from './ui/FAB.svelte';
 | 
			
		||||
 import MessageView from './MessageView.svelte';
 | 
			
		||||
 import Input from './Input.svelte';
 | 
			
		||||
  import FAB from './ui/FAB.svelte';
 | 
			
		||||
  import MessageView from './MessageView.svelte';
 | 
			
		||||
  import Input from './Input.svelte';
 | 
			
		||||
 | 
			
		||||
 import { Svrollbar } from 'svrollbar';
 | 
			
		||||
  import { Svrollbar } from 'svrollbar';
 | 
			
		||||
 | 
			
		||||
 import { chat_lock, chat, localMessages as messages, shouldTweet } from './chat';
 | 
			
		||||
 import { globalMode } from './settings';
 | 
			
		||||
 import { onMount, onDestroy, tick } from 'svelte';
 | 
			
		||||
 import type { Unsubscriber } from 'svelte/store';
 | 
			
		||||
  import { chat_lock, chat, localMessages as messages, shouldTweet } from './chat';
 | 
			
		||||
  import { globalMode } from './settings';
 | 
			
		||||
  import { onMount, onDestroy, tick } from 'svelte';
 | 
			
		||||
  import type { Unsubscriber } from 'svelte/store';
 | 
			
		||||
 | 
			
		||||
 import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
 | 
			
		||||
 import { faArrowDown } from '@fortawesome/free-solid-svg-icons';
 | 
			
		||||
  import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
 | 
			
		||||
  import { faArrowDown } from '@fortawesome/free-solid-svg-icons';
 | 
			
		||||
 | 
			
		||||
 let stickToBottom = true;
 | 
			
		||||
  let stickToBottom = true;
 | 
			
		||||
 | 
			
		||||
 let viewport: Element, contents: Element;
 | 
			
		||||
 let tweet: HTMLAudioElement;
 | 
			
		||||
  let viewport: Element, contents: Element;
 | 
			
		||||
  let tweet: HTMLAudioElement;
 | 
			
		||||
 | 
			
		||||
 shouldTweet.subscribe((should) => {
 | 
			
		||||
     if (should) {
 | 
			
		||||
	 if (tweet) {
 | 
			
		||||
             tweet.volume = 0.5;
 | 
			
		||||
             tweet?.play().catch(() => {});
 | 
			
		||||
	 }
 | 
			
		||||
	 shouldTweet.set(false);
 | 
			
		||||
     }
 | 
			
		||||
 });
 | 
			
		||||
  shouldTweet.subscribe((should) => {
 | 
			
		||||
    if (should) {
 | 
			
		||||
      if (tweet) {
 | 
			
		||||
        tweet.volume = 0.5;
 | 
			
		||||
        tweet?.play().catch(() => {});
 | 
			
		||||
      }
 | 
			
		||||
      shouldTweet.set(false);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 export async function scrollToBottom(smooth = true) {
 | 
			
		||||
     viewport &&
 | 
			
		||||
     viewport.scrollTo({
 | 
			
		||||
         top: viewport.scrollHeight,
 | 
			
		||||
         behavior: smooth ? 'smooth' : undefined
 | 
			
		||||
     });
 | 
			
		||||
 }
 | 
			
		||||
  export async function scrollToBottom(smooth = true) {
 | 
			
		||||
    viewport &&
 | 
			
		||||
      viewport.scrollTo({
 | 
			
		||||
        top: viewport.scrollHeight,
 | 
			
		||||
        behavior: smooth ? 'smooth' : undefined
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 let releaseLock: Unsubscriber;
 | 
			
		||||
 onMount(async () => {
 | 
			
		||||
     releaseLock = chat_lock.subscribe(() => {});
 | 
			
		||||
     await chat.hydrate();
 | 
			
		||||
     await tick();
 | 
			
		||||
     viewport && (viewport.scrollTop = viewport.scrollHeight);
 | 
			
		||||
 });
 | 
			
		||||
  let releaseLock: Unsubscriber;
 | 
			
		||||
  onMount(async () => {
 | 
			
		||||
    releaseLock = chat_lock.subscribe(() => {});
 | 
			
		||||
    await chat.hydrate();
 | 
			
		||||
    await tick();
 | 
			
		||||
    viewport && (viewport.scrollTop = viewport.scrollHeight);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 messages.subscribe(async () => {
 | 
			
		||||
     if (stickToBottom) {
 | 
			
		||||
	 // Wait for the message to be added to the DOM
 | 
			
		||||
	 await tick();
 | 
			
		||||
  messages.subscribe(async () => {
 | 
			
		||||
    if (stickToBottom) {
 | 
			
		||||
      // Wait for the message to be added to the DOM
 | 
			
		||||
      await tick();
 | 
			
		||||
 | 
			
		||||
	 // Scroll the list to the bottom with the new DOM
 | 
			
		||||
	 await scrollToBottom(false);
 | 
			
		||||
	 // vlist?.scrollToIndex(ms.length);
 | 
			
		||||
      // Scroll the list to the bottom with the new DOM
 | 
			
		||||
      await scrollToBottom(false);
 | 
			
		||||
      // vlist?.scrollToIndex(ms.length);
 | 
			
		||||
 | 
			
		||||
	 // Fake debounce to make sure we're still stuck at the bottom
 | 
			
		||||
	 await tick();
 | 
			
		||||
	 stickToBottom = true;
 | 
			
		||||
     }
 | 
			
		||||
 });
 | 
			
		||||
      // Fake debounce to make sure we're still stuck at the bottom
 | 
			
		||||
      await tick();
 | 
			
		||||
      stickToBottom = true;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 onDestroy(() => {
 | 
			
		||||
     releaseLock?.();
 | 
			
		||||
 });
 | 
			
		||||
  onDestroy(() => {
 | 
			
		||||
    releaseLock?.();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 function onScroll(e: Event) {
 | 
			
		||||
     if (!e.isTrusted) return;
 | 
			
		||||
     const scrollOffset = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;
 | 
			
		||||
 | 
			
		||||
     if (scrollOffset >= 80) {
 | 
			
		||||
	 stickToBottom = false;
 | 
			
		||||
     } else if (scrollOffset < 80) {
 | 
			
		||||
	 stickToBottom = true;
 | 
			
		||||
     }
 | 
			
		||||
 }
 | 
			
		||||
  function onScroll(e: Event) {
 | 
			
		||||
    if (!e.isTrusted) return;
 | 
			
		||||
    const scrollOffset = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;
 | 
			
		||||
 | 
			
		||||
    if (scrollOffset >= 80) {
 | 
			
		||||
      stickToBottom = false;
 | 
			
		||||
    } else if (scrollOffset < 80) {
 | 
			
		||||
      stickToBottom = true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="scroller">
 | 
			
		||||
    <audio src="/tweet.mp3" bind:this={tweet} />
 | 
			
		||||
    <Svrollbar {viewport} {contents}  margin={{ right: 6, bottom: 12, top: 12 }}
 | 
			
		||||
	       alwaysVisible
 | 
			
		||||
	       --svrollbar-track-width="8px" --svrollbar-thumb-width="4px" />
 | 
			
		||||
  <MessageView messages="{$messages}" showChannel="{$globalMode}"
 | 
			
		||||
	       bind:viewport bind:contents on:scroll={onScroll} />
 | 
			
		||||
<div class="scroller grow-1 basis-0 p-relative">
 | 
			
		||||
  <audio src="/tweet.mp3" bind:this={tweet} />
 | 
			
		||||
  <Svrollbar
 | 
			
		||||
    {viewport}
 | 
			
		||||
    {contents}
 | 
			
		||||
    margin={{ right: 6, bottom: 12, top: 12 }}
 | 
			
		||||
    alwaysVisible
 | 
			
		||||
    --svrollbar-track-width="8px"
 | 
			
		||||
    --svrollbar-thumb-width="4px"
 | 
			
		||||
  />
 | 
			
		||||
  <MessageView
 | 
			
		||||
    messages={$messages}
 | 
			
		||||
    showChannel={$globalMode}
 | 
			
		||||
    bind:viewport
 | 
			
		||||
    bind:contents
 | 
			
		||||
    on:scroll={onScroll}
 | 
			
		||||
  />
 | 
			
		||||
  {#if !stickToBottom}
 | 
			
		||||
      <FAB --background="{'var(--base-700)'}" on:click={() => scrollToBottom()}><FontAwesomeIcon icon="{faArrowDown}" /></FAB>
 | 
			
		||||
    <FAB --background={'var(--base-700)'} on:click={() => scrollToBottom()}
 | 
			
		||||
      ><FontAwesomeIcon icon={faArrowDown} /></FAB
 | 
			
		||||
    >
 | 
			
		||||
  {/if}
 | 
			
		||||
</div>
 | 
			
		||||
<Input />
 | 
			
		||||
@@ -92,9 +103,6 @@
 | 
			
		||||
<style>
 | 
			
		||||
  .scroller {
 | 
			
		||||
    min-height: 0;
 | 
			
		||||
    flex-grow: 1;
 | 
			
		||||
    flex-basis: 0;
 | 
			
		||||
    position: relative;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .scroller > :global(.viewport) {
 | 
			
		||||
@@ -106,16 +114,14 @@
 | 
			
		||||
    margin-bottom: 32px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 .scroller > :global(*) {
 | 
			
		||||
     /* hide scrollbar */
 | 
			
		||||
     -ms-overflow-style: none !important;
 | 
			
		||||
     scrollbar-width: none !important;
 | 
			
		||||
 }
 | 
			
		||||
  .scroller > :global(*) {
 | 
			
		||||
    -ms-overflow-style: none !important;
 | 
			
		||||
    scrollbar-width: none !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 .scroller > :global(*::-webkit-scrollbar) {
 | 
			
		||||
     /* hide scrollbar */
 | 
			
		||||
     display: none !important;
 | 
			
		||||
 }
 | 
			
		||||
  .scroller > :global(*::-webkit-scrollbar) {
 | 
			
		||||
    display: none !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .scroller :global(.v-thumb) {
 | 
			
		||||
    z-index: 101;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 export let flex = false;
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="header" class:flex="{flex}">
 | 
			
		||||
<div class="header p-relative" class:d-flex="{flex}">
 | 
			
		||||
    <slot />
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@@ -11,19 +11,12 @@
 | 
			
		||||
     --header-size: 48px;
 | 
			
		||||
     --header-color: var(--base-600);
 | 
			
		||||
     --header-z: 101;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .flex {
 | 
			
		||||
     display: flex;
 | 
			
		||||
     flex-direction: row;
 | 
			
		||||
     --header-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .header {
 | 
			
		||||
     position: relative;
 | 
			
		||||
     height: var(--header-size);
 | 
			
		||||
 | 
			
		||||
     /* box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; */
 | 
			
		||||
 | 
			
		||||
     box-shadow: none; /* var(--header-shadow) */
 | 
			
		||||
     background-color: var(--header-color);
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,19 +13,15 @@
 | 
			
		||||
 }
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="container">
 | 
			
		||||
    <textarea bind:value="{input}" on:keydown={keydown} class="input" />
 | 
			
		||||
<div class="container p-relative d-flex pa-16 pt-0">
 | 
			
		||||
    <textarea bind:value="{input}" on:keydown={keydown} class="input grow-1 radius-16 border-0 pa-8 bg-700 color-300" />
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
 .container {
 | 
			
		||||
     height: calc(2 * var(--message-line-height));
 | 
			
		||||
     display: flex;
 | 
			
		||||
     padding: 16px;
 | 
			
		||||
     padding-top: 0;
 | 
			
		||||
     margin-top: -12px;
 | 
			
		||||
     z-index: 100;
 | 
			
		||||
     position: relative
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .container::before, .container::after {
 | 
			
		||||
@@ -41,14 +37,8 @@
 | 
			
		||||
 .container::after  { right: 0; }
 | 
			
		||||
 | 
			
		||||
 .input {
 | 
			
		||||
     flex-grow: 1;
 | 
			
		||||
     resize: none;
 | 
			
		||||
     border-radius: 16px;
 | 
			
		||||
     border: none;
 | 
			
		||||
     z-index: 100;
 | 
			
		||||
     padding: 8px;
 | 
			
		||||
     background: var(--base-700);
 | 
			
		||||
     color: var(--base-300);
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .input:focus {
 | 
			
		||||
 
 | 
			
		||||
@@ -47,13 +47,13 @@
 | 
			
		||||
    <p class="no-select">Method:</p>
 | 
			
		||||
    <div class="signin-buttons grow-1 d-flex">
 | 
			
		||||
      <button
 | 
			
		||||
        class="grow-1"
 | 
			
		||||
        class="p-relative grow-1"
 | 
			
		||||
        disabled
 | 
			
		||||
        on:click={() => (selectedMethod = 'userpass')}
 | 
			
		||||
        class:selected={selectedMethod == 'userpass'}>Username</button
 | 
			
		||||
      >
 | 
			
		||||
      <button
 | 
			
		||||
        class="grow-1"
 | 
			
		||||
        class="p-relative grow-1"
 | 
			
		||||
        on:click={() => (selectedMethod = 'token')}
 | 
			
		||||
        class:selected={selectedMethod == 'token'}>Token</button
 | 
			
		||||
      >
 | 
			
		||||
@@ -67,6 +67,7 @@
 | 
			
		||||
      <textarea
 | 
			
		||||
        class:error
 | 
			
		||||
        spellcheck="false"
 | 
			
		||||
        class="w-100 bg-800 radius-4 pa-8"
 | 
			
		||||
        on:change={() => (error = false)}
 | 
			
		||||
        placeholder="Paste token here"
 | 
			
		||||
        bind:value={token}
 | 
			
		||||
@@ -90,7 +91,6 @@
 | 
			
		||||
  .selected {
 | 
			
		||||
    background-color: var(--base-600);
 | 
			
		||||
    color: var(--base-700);
 | 
			
		||||
    position: relative;
 | 
			
		||||
    margin-left: -32px;
 | 
			
		||||
    margin-right: -32px;
 | 
			
		||||
    border-radius: 24px;
 | 
			
		||||
@@ -129,13 +129,9 @@
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  textarea {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    max-width: 100%;
 | 
			
		||||
    height: 150px;
 | 
			
		||||
    background-color: var(--base-800);
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    padding: 8px;
 | 
			
		||||
    word-break: break-all;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -52,8 +52,8 @@
 | 
			
		||||
 }
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div transition:slide class="top screen" bind:clientHeight>
 | 
			
		||||
    <div class="about">
 | 
			
		||||
<div transition:slide class="top screen p-relative d-flex col" bind:clientHeight>
 | 
			
		||||
    <div class="about p-absolute">
 | 
			
		||||
	<About />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@@ -128,7 +128,9 @@
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
 @use "$lib/styles/utils";
 | 
			
		||||
 | 
			
		||||
 :global(body) {
 | 
			
		||||
     --top-screen-cutout-height: 20vh;
 | 
			
		||||
     --top-screen-background-color: var(--base-700);
 | 
			
		||||
@@ -139,21 +141,17 @@
 | 
			
		||||
     height: calc(100vh - var(--top-screen-cutout-height));
 | 
			
		||||
     max-height: calc(100vh - var(--top-screen-cutout-height));
 | 
			
		||||
     background-color: var(--top-screen-background-color);
 | 
			
		||||
 | 
			
		||||
     display: flex;
 | 
			
		||||
     flex-direction: column;
 | 
			
		||||
     position: relative;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 :global(.container.mobile) .about {
 | 
			
		||||
     display: none;
 | 
			
		||||
 }
 | 
			
		||||
 .about {
 | 
			
		||||
     position: absolute;
 | 
			
		||||
     z-index: 500;
 | 
			
		||||
     bottom: calc(-1 * var(--top-screen-cutout-height));
 | 
			
		||||
     opacity: var(--about-opacity);
 | 
			
		||||
     display: var(--about-display);
 | 
			
		||||
 | 
			
		||||
     :global(.container.mobile) & {
 | 
			
		||||
	 display: none;
 | 
			
		||||
     }
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 :global(.container.mobile) .settings {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,16 @@
 | 
			
		||||
.no-select {
 | 
			
		||||
    user-select: none;
 | 
			
		||||
}
 | 
			
		||||
.select-text {
 | 
			
		||||
    user-select: text;
 | 
			
		||||
}
 | 
			
		||||
.select-all {
 | 
			
		||||
    user-select: all;
 | 
			
		||||
}
 | 
			
		||||
.select-contain {
 | 
			
		||||
    user-select: contain;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.clickable {
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
@@ -89,3 +99,123 @@
 | 
			
		||||
    margin-top: 2px;
 | 
			
		||||
    margin-bottom: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin gen-directions($prefix, $prop, $i, $sz) {
 | 
			
		||||
    .#{$prefix}l-#{$i} {
 | 
			
		||||
	#{$prop}-left: #{$sz} !important;
 | 
			
		||||
    }
 | 
			
		||||
    .#{$prefix}r-#{$i} {
 | 
			
		||||
	#{$prop}-right: #{$sz} !important;
 | 
			
		||||
    }
 | 
			
		||||
    .#{$prefix}x-#{$i} {
 | 
			
		||||
	#{$prop}-left: #{$sz};
 | 
			
		||||
	#{$prop}-right: #{$sz};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .#{$prefix}t-#{$i} {
 | 
			
		||||
	#{$prop}-top: #{$sz} !important;
 | 
			
		||||
    }
 | 
			
		||||
    .#{$prefix}b-#{$i} {
 | 
			
		||||
	#{$prop}-bottom: #{$sz} !important;
 | 
			
		||||
    }
 | 
			
		||||
    .#{$prefix}y-#{$i} {
 | 
			
		||||
	#{$prop}-top: #{$sz};
 | 
			
		||||
	#{$prop}-bottom: #{$sz};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .#{$prefix}a-#{$i} {
 | 
			
		||||
	#{$prop}-left: #{$sz};
 | 
			
		||||
	#{$prop}-right: #{$sz};
 | 
			
		||||
	#{$prop}-top: #{$sz};
 | 
			
		||||
	#{$prop}-bottom: #{$sz};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin border-directions($i ,$sz) {
 | 
			
		||||
    .radius-tl-#{$i} {
 | 
			
		||||
	border-top-left-radius: #{$sz};
 | 
			
		||||
    }
 | 
			
		||||
    .radius-tr-#{$i} {
 | 
			
		||||
	border-top-right-radius: #{$sz};
 | 
			
		||||
    }
 | 
			
		||||
    .radius-t-#{$i} {
 | 
			
		||||
	@extend .radius-tl-#{$i};
 | 
			
		||||
	@extend .radius-tr-#{$i};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .radius-bl-#{$i} {
 | 
			
		||||
	border-bottom-left-radius: #{$sz};
 | 
			
		||||
    }
 | 
			
		||||
    .radius-br-#{$i} {
 | 
			
		||||
	border-bottom-right-radius: #{$sz};
 | 
			
		||||
    }
 | 
			
		||||
    .radius-b-#{$i} {
 | 
			
		||||
	@extend .radius-bl-#{$i};
 | 
			
		||||
	@extend .radius-br-#{$i};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .radius-l-#{$i} {
 | 
			
		||||
	@extend .radius-tl-#{$i};
 | 
			
		||||
	@extend .radius-bl-#{$i};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .radius-r-#{$i} {
 | 
			
		||||
	@extend .radius-tr-#{$i};
 | 
			
		||||
	@extend .radius-br-#{$i};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .radius-#{$i} {
 | 
			
		||||
	@extend .radius-l-#{$i};
 | 
			
		||||
	@extend .radius-r-#{$i};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$spacings: (0 0px, 1 1px, 2 2px, 4 4px, 6 6px, 8 8px, 12 12px, 16 16px, 18 18px, 24 24px, 32 32px, 36 36px, 48 48px);
 | 
			
		||||
@each $i, $sz in $spacings {
 | 
			
		||||
    @include gen-directions(p, padding, $i, $sz);
 | 
			
		||||
    @include gen-directions(m, margin, $i, $sz);
 | 
			
		||||
    @include border-directions($i, $sz);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@include border-directions(pill, 9999px);
 | 
			
		||||
.border-0 { border: 0; }
 | 
			
		||||
 | 
			
		||||
$colors: (100 base-100, 200 base-200, 300 base-300, 400 base-400, 500 base-500, 600 base-600, 700 base-700, 800 base-800, yellow yellow, orange orange, red red, magenta magenta, violet violet, blue blue, cyan cyan, green green);
 | 
			
		||||
@each $i, $name in $colors {
 | 
			
		||||
    .color-#{$i} {
 | 
			
		||||
	color: var(--#{$name}) !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .bg-#{$i} {
 | 
			
		||||
	background-color: var(--#{$name});
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@each $i in (start, end, center, justify, left, right) {
 | 
			
		||||
    .text-#{$i} {
 | 
			
		||||
	text-align: #{$i};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.super {
 | 
			
		||||
    vertical-align: super;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@each $i in (hidden, scroll) {
 | 
			
		||||
    .overflow-x-#{$i} {
 | 
			
		||||
	overflow-x: #{$i};
 | 
			
		||||
    }
 | 
			
		||||
    .overflow-y-#{$i} {
 | 
			
		||||
	overflow-y: #{$i};
 | 
			
		||||
    }
 | 
			
		||||
    .overflow-#{$i} {
 | 
			
		||||
	@extend .overflow-x-#{$i};
 | 
			
		||||
	@extend .overflow-y-#{$i};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@each $i in (relative, absolute, fixed, sticky) {
 | 
			
		||||
    .p-#{$i} {
 | 
			
		||||
	position: #{$i};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user