Compare commits

...

6 Commits

15 changed files with 1093 additions and 14 deletions

View File

@ -83,6 +83,18 @@ def create_app():
app.config['MAX_CONTENT_LENGTH'] = 1000 * 1000 app.config['MAX_CONTENT_LENGTH'] = 1000 * 1000
os.makedirs(os.path.dirname(app.config["DB_PATH"]), exist_ok = True) os.makedirs(os.path.dirname(app.config["DB_PATH"]), exist_ok = True)
css_dir = 'data/static/css/'
allowed_themes = []
for f in os.listdir(css_dir):
if not os.path.isfile(os.path.join(css_dir, f)):
continue
theme_name = os.path.splitext(os.path.basename(f))[0]
allowed_themes.append(theme_name)
allowed_themes.sort(key=(lambda x: (x != 'style', x)))
app.config['allowed_themes'] = allowed_themes
with app.app_context(): with app.app_context():
from .schema import create as create_tables from .schema import create as create_tables
from .migrations import run_migrations from .migrations import run_migrations
@ -179,4 +191,11 @@ def create_app():
def cachebust(subject): def cachebust(subject):
return f"{subject}?v={str(int(time.time()))}" return f"{subject}?v={str(int(time.time()))}"
@app.template_filter('theme_name')
def get_theme_name(subject: str):
if subject == 'style':
return 'Default'
return f'{subject.removeprefix('theme-').capitalize()} (beta)'
return app return app

View File

@ -1,5 +1,5 @@
from .babycode_parser import Parser from .babycode_parser import Parser
from markupsafe import escape from markupsafe import Markup, escape
import re import re
BABYCODE_VERSION = 3 BABYCODE_VERSION = 3
@ -241,7 +241,7 @@ def babycode_to_html(s):
element['children'][i + 1] if i+1 < len(element['children']) else None element['children'][i + 1] if i+1 < len(element['children']) else None
) )
_nobr = element['name'] == "code" or element['name'] == "ul" or element['name'] == "ol" _nobr = element['name'] == "code" or element['name'] == "ul" or element['name'] == "ol"
c = c + fold(child, _nobr, _surrounding) c = c + Markup(fold(child, _nobr, _surrounding))
res = TAGS[element['name']](c, element['attr'], surrounding) res = TAGS[element['name']](c, element['attr'], surrounding)
return res return res
case "link": case "link":

View File

@ -178,7 +178,7 @@ class Topics(Model):
q = """ q = """
SELECT SELECT
threads.title, threads.slug, threads.created_at, threads.is_locked, threads.is_stickied, threads.id, threads.title, threads.slug, threads.created_at, threads.is_locked, threads.is_stickied,
users.username AS started_by, users.username AS started_by,
u.username AS latest_post_username, u.username AS latest_post_username,
ph.content AS latest_post_content, ph.content AS latest_post_content,
@ -251,6 +251,16 @@ class Avatars(Model):
class Subscriptions(Model): class Subscriptions(Model):
table = "subscriptions" table = "subscriptions"
def get_unread_count(self):
q = """SELECT COUNT(*) AS unread_count
FROM posts
LEFT JOIN subscriptions ON subscriptions.thread_id = posts.thread_id
WHERE subscriptions.user_id = ? AND posts.created_at > subscriptions.last_seen AND posts.thread_id = ?"""
res = db.fetch_one(q, self.user_id, self.thread_id)
if res:
return res['unread_count']
return None
class APIRateLimits(Model): class APIRateLimits(Model):
table = 'api_rate_limits' table = 'api_rate_limits'

View File

@ -54,12 +54,14 @@ def thread(slug):
other_topics = Topics.select() other_topics = Topics.select()
is_subscribed = False is_subscribed = False
unread_count = None
if is_logged_in(): if is_logged_in():
subscription = Subscriptions.find({ subscription = Subscriptions.find({
'thread_id': thread.id, 'thread_id': thread.id,
'user_id': get_active_user().id, 'user_id': get_active_user().id,
}) })
if subscription: if subscription:
unread_count = subscription.get_unread_count()
if int(posts[-1]['created_at']) > int(subscription.last_seen): if int(posts[-1]['created_at']) > int(subscription.last_seen):
subscription.update({ subscription.update({
'last_seen': int(posts[-1]['created_at']) 'last_seen': int(posts[-1]['created_at'])
@ -76,6 +78,7 @@ def thread(slug):
topics = other_topics, topics = other_topics,
is_subscribed = is_subscribed, is_subscribed = is_subscribed,
Reactions = Reactions, Reactions = Reactions,
unread_count = unread_count,
) )

View File

@ -1,8 +1,8 @@
from flask import ( from flask import (
Blueprint, render_template, request, redirect, url_for, flash, session Blueprint, render_template, request, redirect, url_for, flash, session
) )
from .users import login_required, mod_only from .users import login_required, mod_only, get_active_user, is_logged_in
from ..models import Users, Topics, Threads from ..models import Users, Topics, Threads, Subscriptions
from ..constants import InfoboxKind from ..constants import InfoboxKind
from slugify import slugify from slugify import slugify
import time import time
@ -62,9 +62,21 @@ def topic(slug):
page_count = max(math.ceil(threads_count / THREADS_PER_PAGE), 1) page_count = max(math.ceil(threads_count / THREADS_PER_PAGE), 1)
page = max(1, min(int(request.args.get('page', default=1)), page_count)) page = max(1, min(int(request.args.get('page', default=1)), page_count))
threads_list = target_topic.get_threads(THREADS_PER_PAGE, page, sort_by)
subscriptions = {}
if is_logged_in():
for thread in threads_list:
subscription = Subscriptions.find({
'user_id': get_active_user().id,
'thread_id': thread['id'],
})
if subscription:
subscriptions[thread['id']] = subscription.get_unread_count()
return render_template( return render_template(
"topics/topic.html", "topics/topic.html",
threads_list = target_topic.get_threads(THREADS_PER_PAGE, page, sort_by), threads_list = threads_list,
subscriptions = subscriptions,
topic = target_topic, topic = target_topic,
current_page = page, current_page = page,
page_count = page_count page_count = page_count

View File

@ -169,6 +169,9 @@ def get_prefers_theme():
if not 'theme' in session: if not 'theme' in session:
return 'style' return 'style'
if session['theme'] not in current_app.config['allowed_themes']:
return 'style'
return session['theme'] return session['theme']
@bp.get("/log_in") @bp.get("/log_in")
@ -294,8 +297,8 @@ def settings_form(username):
# we silently ignore the passed username # we silently ignore the passed username
# and grab the correct user from the session # and grab the correct user from the session
user = get_active_user() user = get_active_user()
theme = request.form.get('theme', default='default') theme = request.form.get('theme', default='style')
if theme == 'default': if theme == 'style':
if 'theme' in session: if 'theme' in session:
session.pop('theme') session.pop('theme')
else: else:

View File

@ -12,7 +12,7 @@
{% endif %} {% endif %}
<main> <main>
<nav class="darkbg"> <nav class="darkbg">
<h1 class="thread-title">{{ thread.title }}</h1> <h1 class="thread-title">{{ thread.title }}{% if unread_count is not none %} ({{ unread_count }} unread){% endif %}</h1>
<span>Posted in <a href="{{ url_for("topics.topic", slug=topic.slug) }}">{{ topic.name }}</a> <span>Posted in <a href="{{ url_for("topics.topic", slug=topic.slug) }}">{{ topic.name }}</a>
{% if thread.is_stickied %} {% if thread.is_stickied %}
&bullet; <i>stickied, so it's probably important</i> &bullet; <i>stickied, so it's probably important</i>

View File

@ -40,6 +40,9 @@
<div class="thread-info-container"> <div class="thread-info-container">
<span> <span>
<span class="thread-title"><a href="{{ url_for("threads.thread", slug=thread['slug']) }}">{{thread['title']}}</a></span> <span class="thread-title"><a href="{{ url_for("threads.thread", slug=thread['slug']) }}">{{thread['title']}}</a></span>
{% if thread['id'] in subscriptions %}
({{ subscriptions[thread['id']] }} unread)
{% endif %}
&bullet; &bullet;
Started by <a href="{{ url_for("users.page", username=thread['started_by']) }}">{{ thread['started_by'] }}</a> on {{ timestamp(thread['created_at'])}} Started by <a href="{{ url_for("users.page", username=thread['started_by']) }}">{{ thread['started_by'] }}</a> on {{ timestamp(thread['created_at'])}}
</span> </span>

View File

@ -17,8 +17,9 @@
<form method='post'> <form method='post'>
<label for='theme'>Theme (beta)</label> <label for='theme'>Theme (beta)</label>
<select autocomplete='off' id='theme' name='theme'> <select autocomplete='off' id='theme' name='theme'>
<option value='default' {{ 'selected' if get_prefers_theme() == 'style' }}>Default</option> {% for theme in config.allowed_themes %}
<option value='theme-otomotone' {{ 'selected' if get_prefers_theme() == 'theme-otomotone' }}>Otomotone (beta)</option> <option value="{{ theme }}" {{ 'selected' if get_prefers_theme() == theme }}>{{ theme | theme_name }}</option>
{% endfor %}
</select> </select>
<label for='topic_sort_by'>Sort threads by:</label> <label for='topic_sort_by'>Sort threads by:</label>
<select id='topic_sort_by' name='topic_sort_by'> <select id='topic_sort_by' name='topic_sort_by'>

View File

@ -478,7 +478,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus, select:focus
color: black; color: black;
} }
.infobox.critical { .infobox.critical {
background-color: rgb(237, 129, 129); background-color: #ed8181;
color: black; color: black;
} }
.infobox.warn { .infobox.warn {

View File

@ -271,7 +271,7 @@ blockquote {
margin: 10px; margin: 10px;
border-radius: 4px; border-radius: 4px;
border-left: 10px solid #ae6bae; border-left: 10px solid #ae6bae;
background-color: rgba(0, 0, 0, 0.1490196078); background-color: rgba(251, 175, 207, 0.0392156863);
} }
.user-info { .user-info {

View File

@ -0,0 +1,929 @@
@font-face {
font-family: "site-title";
src: url("/static/fonts/ChicagoFLF.woff2");
}
@font-face {
font-family: "Cadman";
src: url("/static/fonts/Cadman_Roman.woff2");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "Cadman";
src: url("/static/fonts/Cadman_Bold.woff2");
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: "Cadman";
src: url("/static/fonts/Cadman_Italic.woff2");
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: "Cadman";
src: url("/static/fonts/Cadman_BoldItalic.woff2");
font-weight: bold;
font-style: italic;
}
.reaction-button.active, .tab-button, .currentpage, .pagebutton, input[type=file]::file-selector-button, button.warn, input[type=submit].warn, .linkbutton.warn, button.critical, input[type=submit].critical, .linkbutton.critical, button, input[type=submit], .linkbutton {
cursor: default;
font-size: 0.9em;
font-family: "Cadman";
text-decoration: none;
border: 1px solid black;
border-radius: 16px;
padding: 8px 12px;
margin: 6px 0;
}
body {
font-family: "Cadman";
margin: 12px 50px;
background-color: #c85d45;
color: black;
}
a:link {
color: black;
}
a:visited {
color: black;
}
.big {
font-size: 1.8rem;
}
#topnav {
padding: 6px;
margin: 0;
display: flex;
justify-content: end;
background-color: #f27a5a;
justify-content: space-between;
align-items: baseline;
}
#bottomnav {
padding: 6px;
margin: 0;
display: flex;
justify-content: end;
background-color: #88486d;
}
.darkbg {
padding-bottom: 6px;
padding-left: 6px;
padding-right: 6px;
background-color: #88486d;
}
.user-actions {
display: flex;
column-gap: 8px;
}
.site-title {
font-family: "site-title";
font-size: 3rem;
margin: 0 12px;
text-decoration: none;
color: black !important;
}
.thread-title {
margin: 0;
font-size: 1.5rem;
font-weight: bold;
}
.post {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 1fr;
gap: 0;
grid-auto-flow: row;
grid-template-areas: "usercard post-content-container";
border: 2px outset rgb(155.8907865169, 93.2211235955, 76.5092134831);
}
.usercard {
grid-area: usercard;
padding: 12px 6px;
border: none;
background-color: #88486d;
border-right: none;
}
.usercard-inner {
display: flex;
flex-direction: column;
align-items: center;
top: 6px;
position: sticky;
}
.post-content-container {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: min-content 1fr min-content;
gap: 0;
grid-auto-flow: row;
grid-template-areas: "post-info" "post-content" "post-reactions";
grid-area: post-content-container;
min-height: 100%;
}
.post-info {
grid-area: post-info;
display: flex;
min-height: 35px;
justify-content: space-between;
padding: 3px 12px;
align-items: center;
border-top: 1px solid black;
border-bottom: 1px solid black;
background-color: #c85d45;
}
.post-content {
grid-area: post-content;
padding: 12px 12px 0 12px;
display: flex;
flex-direction: column;
overflow: hidden;
background-color: #f27a5a;
}
.post-reactions {
grid-area: post-reactions;
min-height: 50px;
display: flex;
padding: 6px 12px;
align-items: center;
flex-wrap: wrap;
gap: 6px;
background-color: #c85d45;
border-top: 2px dotted #f7bfdf;
}
.post-inner {
height: 100%;
padding-right: 25%;
}
.post-inner.wider {
padding-right: 12.5%;
}
.signature-container {
border-top: 2px dotted #f7bfdf;
padding: 6px 0;
}
pre code {
display: block;
background-color: rgb(41.7051685393, 28.2759550562, 24.6948314607);
font-size: 1rem;
color: white;
border-bottom-right-radius: 16px;
border-bottom-left-radius: 16px;
border-left: 6px solid rgb(231.56, 212.36, 207.24);
padding: 12px;
overflow: scroll;
tab-size: 4;
}
.copy-code-container {
position: sticky;
width: calc(100% - 4px);
display: flex;
justify-content: space-between;
align-items: last baseline;
font-family: "Cadman";
border-top-right-radius: 16px;
border-top-left-radius: 16px;
background-color: #f27a5a;
border-left: 2px solid black;
border-right: 2px solid black;
border-top: 2px solid black;
}
.copy-code-container::before {
content: "code block";
font-style: italic;
margin-left: 6px;
}
.copy-code {
margin-right: 6px;
}
.inline-code {
background-color: rgb(41.7051685393, 28.2759550562, 24.6948314607);
color: white;
padding: 3px 6px;
display: inline-block;
margin: 4px;
border-radius: 16px;
font-size: 1rem;
white-space: pre;
}
#delete-dialog, .lightbox-dialog {
padding: 0;
border-radius: 16px;
border: 2px solid black;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.25);
}
.delete-dialog-inner {
display: flex;
flex-direction: column;
align-items: center;
padding: 12px;
}
.lightbox-inner {
display: flex;
flex-direction: column;
padding: 12px;
min-width: 400px;
background-color: #f27a5a;
color: black;
gap: 6px;
}
.lightbox-image {
max-width: 70vw;
max-height: 70vh;
object-fit: scale-down;
}
.lightbox-nav {
display: flex;
justify-content: space-between;
align-items: center;
}
blockquote {
padding: 6px 12px;
margin: 6px;
border-radius: 16px;
border-left: 6px solid rgb(231.56, 212.36, 207.24);
background-color: rgba(0, 0, 0, 0.1333333333);
}
.user-info {
display: grid;
grid-template-columns: 300px 1fr;
grid-template-rows: 1fr;
gap: 0;
grid-template-areas: "user-page-usercard user-page-stats";
}
.user-page-usercard {
grid-area: user-page-usercard;
padding: 12px 6px;
border: none;
background-color: #88486d;
border-right: none;
}
.user-page-stats {
grid-area: user-page-stats;
padding: 12px 16px;
border: 1px solid black;
}
.user-stats-list {
list-style: none;
margin: 0 0 6px 0;
}
.user-page-posts {
border-left: 1px solid black;
border-right: 1px solid black;
border-bottom: 1px solid black;
background-color: #f27a5a;
}
.user-page-post-preview {
max-height: 200px;
mask-image: linear-gradient(180deg, #000 60%, transparent);
}
.avatar {
width: 90%;
height: 90%;
object-fit: contain;
margin-bottom: 6px;
}
.username-link {
overflow-wrap: anywhere;
}
.user-status {
text-align: center;
}
button, input[type=submit], .linkbutton {
display: inline-block;
background-color: #f27a5a;
color: black !important;
}
button:hover, input[type=submit]:hover, .linkbutton:hover {
background-color: rgb(244.6, 148.6, 123);
}
button:active, input[type=submit]:active, .linkbutton:active {
background-color: rgb(176.4525842697, 133.7379775281, 122.3474157303);
}
button:disabled, input[type=submit]:disabled, .linkbutton:disabled {
background-color: rgb(198.02, 189.62, 187.38);
}
button.reduced, input[type=submit].reduced, .linkbutton.reduced {
margin: 0;
padding: 6px;
}
button.critical, input[type=submit].critical, .linkbutton.critical {
background-color: #f73030;
color: white !important;
}
button.critical:hover, input[type=submit].critical:hover, .linkbutton.critical:hover {
background-color: rgb(248.6, 89.4, 89.4);
}
button.critical:active, input[type=submit].critical:active, .linkbutton.critical:active {
background-color: rgb(166.6956976744, 98.8043023256, 98.8043023256);
}
button.critical:disabled, input[type=submit].critical:disabled, .linkbutton.critical:disabled {
background-color: rgb(186.715, 172.785, 172.785);
}
button.critical.reduced, input[type=submit].critical.reduced, .linkbutton.critical.reduced {
margin: 0;
padding: 6px;
}
button.warn, input[type=submit].warn, .linkbutton.warn {
background-color: #fbfb8d;
color: black !important;
}
button.warn:hover, input[type=submit].warn:hover, .linkbutton.warn:hover {
background-color: rgb(251.8, 251.8, 163.8);
}
button.warn:active, input[type=submit].warn:active, .linkbutton.warn:active {
background-color: rgb(198.3813559322, 198.3813559322, 154.4186440678);
}
button.warn:disabled, input[type=submit].warn:disabled, .linkbutton.warn:disabled {
background-color: rgb(217.55, 217.55, 209.85);
}
button.warn.reduced, input[type=submit].warn.reduced, .linkbutton.warn.reduced {
margin: 0;
padding: 6px;
}
input[type=file]::file-selector-button {
background-color: #f27a5a;
color: black !important;
margin: 6px;
}
input[type=file]::file-selector-button:hover {
background-color: rgb(244.6, 148.6, 123);
}
input[type=file]::file-selector-button:active {
background-color: rgb(176.4525842697, 133.7379775281, 122.3474157303);
}
input[type=file]::file-selector-button:disabled {
background-color: rgb(198.02, 189.62, 187.38);
}
input[type=file]::file-selector-button.reduced {
margin: 0;
padding: 6px;
}
p {
margin: 8px 0;
}
.pagebutton {
background-color: #f27a5a;
color: black !important;
padding: 3px 3px;
margin: 0;
display: inline-block;
min-width: 36px;
text-align: center;
}
.pagebutton:hover {
background-color: rgb(244.6, 148.6, 123);
}
.pagebutton:active {
background-color: rgb(176.4525842697, 133.7379775281, 122.3474157303);
}
.pagebutton:disabled {
background-color: rgb(198.02, 189.62, 187.38);
}
.pagebutton.reduced {
margin: 0;
padding: 6px;
}
.currentpage {
border: none;
padding: 3px 3px;
margin: 0;
display: inline-block;
min-width: 36px;
text-align: center;
}
.modform {
display: inline;
}
.login-container > * {
width: 60%;
margin: auto;
}
.settings-container > * {
width: 60%;
margin: auto;
}
.avatar-form {
display: flex;
flex-direction: column;
align-items: center;
padding: 12px 0;
}
input[type=text], input[type=password], textarea, select {
border: 1px solid black;
border-radius: 16px;
padding: 8px;
width: 100%;
box-sizing: border-box;
resize: vertical;
color: black;
background-color: rgb(247.2, 175.2, 156);
}
input[type=text]:focus, input[type=password]:focus, textarea:focus, select:focus {
background-color: rgb(249.8, 201.8, 189);
}
.infobox {
border: 2px solid black;
background-color: #81a3e6;
padding: 12px 8px;
color: black;
}
.infobox.critical {
background-color: #f73030;
color: white;
}
.infobox.warn {
background-color: #fbfb8d;
color: black;
}
.infobox > span {
display: flex;
align-items: center;
}
.infobox-icon-container {
min-width: 60px;
padding-right: 8px;
}
.thread {
display: grid;
grid-template-columns: 96px 1.6fr 96px;
grid-template-rows: 1fr;
gap: 0;
grid-auto-flow: row;
min-height: 96px;
grid-template-areas: "thread-sticky-container thread-info-container thread-locked-container";
}
.thread-sticky-container {
grid-area: thread-sticky-container;
border: 1px solid black;
background-color: #f27a5a;
}
.thread-locked-container {
grid-area: thread-locked-container;
border: 1px solid black;
background-color: #f27a5a;
}
.contain-svg {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.contain-svg:not(.full) > svg, .contain-svg:not(.full) > img {
height: 50%;
width: 50%;
}
.contain-svg.full > svg, .contain-svg.full > img {
height: 100%;
width: 100%;
}
.post-img-container {
display: flex;
flex-wrap: wrap;
gap: 3px;
}
.post-image {
object-fit: contain;
max-width: 400px;
max-height: 400px;
min-width: 200px;
min-height: 200px;
flex: 1 1 0%;
width: auto;
height: auto;
}
.thread-info-container {
grid-area: thread-info-container;
background-color: #f27a5a;
padding: 3px 12px;
border-top: 1px solid black;
border-bottom: 1px solid black;
display: flex;
flex-direction: column;
overflow: hidden;
max-height: 110px;
mask-image: linear-gradient(180deg, #000 60%, transparent);
}
.thread-info-post-preview {
overflow: hidden;
text-overflow: ellipsis;
display: inline;
margin-right: 25%;
}
.babycode-guide-section {
background-color: #f27a5a;
padding: 3px 12px;
border: 1px solid black;
padding-right: 25%;
}
.babycode-guide-container {
display: grid;
grid-template-columns: 1.5fr 300px;
grid-template-rows: 1fr;
gap: 0;
grid-auto-flow: row;
grid-template-areas: "guide-topics guide-toc";
}
.guide-topics {
grid-area: guide-topics;
overflow: hidden;
}
.guide-toc {
grid-area: guide-toc;
position: sticky;
top: 100px;
align-self: start;
padding: 6px;
border-bottom-right-radius: 8px;
background-color: #f27a5a;
border-right: 1px solid black;
border-top: 1px solid black;
border-bottom: 1px solid black;
}
.emoji-table tr td {
text-align: center;
}
.emoji-table tr th {
padding-left: 50px;
padding-right: 50px;
}
.emoji-table {
margin: auto;
}
.emoji-table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
.colorful-table {
border-collapse: collapse;
width: 100%;
margin: 6px 0;
overflow: hidden;
}
.colorful-table tr th {
background-color: #b54444;
padding: 3px 0;
}
.colorful-table tr td {
background-color: #f27a5a;
padding: 3px 0;
text-align: center;
}
.colorful-table .small {
width: 250px;
}
.topic {
display: grid;
grid-template-columns: 1.5fr 96px;
grid-template-rows: 1fr;
gap: 0;
grid-auto-flow: row;
grid-template-areas: "topic-info-container topic-locked-container";
}
.topic-info-container {
grid-area: topic-info-container;
background-color: #f27a5a;
padding: 3px 12px;
border: 1px solid black;
display: flex;
flex-direction: column;
}
.topic-locked-container {
grid-area: topic-locked-container;
border: 1px solid black;
background-color: #f27a5a;
}
.draggable-topic {
cursor: pointer;
user-select: none;
background-color: #f27a5a;
padding: 12px;
margin: 8px 0;
border-top: 5px outset rgb(219.84, 191.04, 183.36);
border-bottom: 5px outset rgb(155.8907865169, 93.2211235955, 76.5092134831);
}
.draggable-topic.dragged {
background-color: #f27a5a;
}
.editing {
background-color: rgb(219.84, 191.04, 183.36);
}
.context-explain {
margin: 12px 0;
display: flex;
justify-content: space-evenly;
}
.post-edit-form {
display: flex;
flex-direction: column;
align-items: baseline;
height: 100%;
}
.babycode-editor {
height: 150px;
font-size: 1rem;
}
.babycode-editor-container {
width: 100%;
}
.babycode-preview-errors-container {
font-size: 0.8rem;
}
.tab-button {
background-color: #f27a5a;
color: black !important;
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
margin-bottom: 0;
}
.tab-button:hover {
background-color: rgb(244.6, 148.6, 123);
}
.tab-button:active {
background-color: rgb(176.4525842697, 133.7379775281, 122.3474157303);
}
.tab-button:disabled {
background-color: rgb(198.02, 189.62, 187.38);
}
.tab-button.reduced {
margin: 0;
padding: 6px;
}
.tab-button.active {
background-color: #b54444;
padding-top: 8px;
}
.tab-content {
display: none;
}
.tab-content.active {
min-height: 250px;
display: block;
background-color: rgb(156.1, 92.9, 92.9);
border: 1px solid black;
padding: 6px;
border-top-right-radius: 16px;
border-bottom-right-radius: 16px;
border-bottom-left-radius: 16px;
}
ul, ol {
margin: 6px 0 6px 16px;
padding: 0;
}
.new-concept-notification.hidden {
display: none;
}
.new-concept-notification {
position: fixed;
bottom: 80px;
right: 80px;
border: 1px solid black;
background-color: #81a3e6;
padding: 12px 8px;
border-radius: 16px;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.25);
}
.emoji {
max-width: 15px;
max-height: 15px;
}
.accordion {
border-top-right-radius: 16px;
border-top-left-radius: 16px;
box-sizing: border-box;
border: 1px solid black;
margin: 6px 3px;
overflow: hidden;
}
.accordion.hidden {
border-bottom: none;
}
.accordion-header {
display: flex;
align-items: center;
background-color: #c6655b;
padding: 0 6px;
gap: 6px;
border-bottom: 1px solid black;
}
.accordion-toggle {
padding: 0;
width: 36px;
height: 36px;
min-width: 36px;
min-height: 36px;
}
.accordion-title {
margin-right: auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.accordion-content {
padding: 0 8px;
}
.accordion-content.hidden {
display: none;
}
.post-accordion-content {
padding-top: 6px;
padding-bottom: 6px;
background-color: #c85d45;
}
.inbox-container {
padding: 6px;
}
.babycode-button-container {
display: flex;
gap: 3px;
flex-wrap: wrap;
}
.babycode-button {
padding: 3px 6px;
min-width: 36px;
}
.babycode-button > * {
font-size: 1rem;
}
.quote-popover {
position: absolute;
transform: translateX(-50%);
margin: 0;
border: none;
border-radius: 16px;
background-color: rgba(0, 0, 0, 0.5019607843);
padding: 3px 6px;
}
footer {
border-top: 1px solid black;
}
.reaction-button.active {
background-color: #b54444;
color: white !important;
}
.reaction-button.active:hover {
background-color: rgb(197.978313253, 103.221686747, 103.221686747);
}
.reaction-button.active:active {
background-color: rgb(127.305, 96.795, 96.795);
}
.reaction-button.active:disabled {
background-color: rgb(167.7956024096, 159.5043975904, 159.5043975904);
}
.reaction-button.active.reduced {
margin: 0;
padding: 6px;
}
.reaction-popover {
position: relative;
margin: 0;
border: none;
border-radius: 16px;
background-color: rgba(0, 0, 0, 0.5019607843);
padding: 3px 6px;
width: 250px;
}
.reaction-popover-inner {
display: flex;
flex-wrap: wrap;
overflow: scroll;
margin: auto;
justify-content: center;
}
.babycode-guide-list {
border-bottom: 1px dashed;
}
#topnav {
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
#bottomnav {
border-bottom-left-radius: 16px;
border-bottom-right-radius: 16px;
color: white;
}
textarea {
padding: 12px 16px;
}
footer {
margin-top: 10px;
border-radius: 16px;
border: none;
text-align: center;
}
.darkbg {
color: white;
}
.darkbg a {
color: white;
}

View File

@ -596,7 +596,7 @@ input[type="text"], input[type="password"], textarea, select {
} }
$infobox_info_color: #81a3e6 !default; $infobox_info_color: #81a3e6 !default;
$infobox_critical_color: rgb(237, 129, 129) !default; $infobox_critical_color: #ed8181 !default;
$infobox_warn_color: #fbfb8d !default; $infobox_warn_color: #fbfb8d !default;
$infobox_border: 2px solid black !default; $infobox_border: 2px solid black !default;
$infobox_padding: $BIG_PADDING $MEDIUM_BIG_PADDING !default; $infobox_padding: $BIG_PADDING $MEDIUM_BIG_PADDING !default;

View File

@ -40,6 +40,8 @@ $crit: #d53232;
$site_title_color: white, $site_title_color: white,
$topnav_color: #303030, $topnav_color: #303030,
$quote_background_color: #fbafcf0a,
$link_color: #e87fe1, $link_color: #e87fe1,
$link_color_visited: #ed4fb1, $link_color_visited: #ed4fb1,

97
sass/peachy.scss Normal file
View File

@ -0,0 +1,97 @@
// $accent: #dd5536;
$accent: #f27a5a;
$br: 16px;
@use 'default' with (
$ACCENT_COLOR: $accent,
$thread_locked_background: $accent,
$topic_locked_background: $accent,
// $DARK_1: #e36286,
$DARK_1: #88486d,
$MAIN_BG: #c85d45,
$usercard_border: none,
$usercard_border_right: none,
$thread_locked_border: 1px solid black,
$SETTINGS_WIDTH: 60%,
$PAGE_SIDE_MARGIN: 50px,
$link_color: black,
$link_color_visited: black,
$reaction_button_active_font_color: white,
// $DEFAULT_FONT_COLOR: white,
// $DEFAULT_FONT_COLOR_INVERSE: black,
$text_input_font_color: black,
$BUTTON_COLOR: $accent,
$BUTTON_COLOR_2: #b54444,
$BUTTON_COLOR_CRITICAL: #f73030,
$ACCORDION_COLOR: #c6655b,
$BUTTON_WARN_FONT_COLOR: black,
$BUTTON_CRITICAL_FONT_COLOR: white,
$SMALL_PADDING: 3px,
$MEDIUM_PADDING: 6px,
$MEDIUM_BIG_PADDING: 8px,
$BIG_PADDING: 12px,
$BIGGER_PADDING: 16px,
$DEFAULT_BORDER_RADIUS: $br,
$code_border_radius: $br,
$button_padding: 8px 12px,
$reduced_button_padding: 6px,
$post_reactions_border_top: 2px dotted #f7bfdf,
$post_info_min_height: 35px,
$post_reactions_padding: 6px 12px,
$post_reactions_gap: 6px,
$text_input_padding: 8px,
$infobox_info_color: #81a3e6,
$infobox_critical_color: #f73030,
$infobox_warn_color: #fbfb8d,
$infobox_info_font_color: black,
$infobox_critical_font_color: white,
$infobox_warn_font_color: black,
$pagebutton_min_width: 36px,
$quote_background_color: #0002,
);
#topnav {
border-top-left-radius: $br;
border-top-right-radius: $br;
}
#bottomnav {
border-bottom-left-radius: $br;
border-bottom-right-radius: $br;
color: white;
}
textarea {
padding: 12px 16px;
}
footer {
margin-top: 10px;
border-radius: $br;
border: none;
text-align: center;
}
.darkbg {
color: white;
& a {
color: white;
}
}