Mercurial > libervia-templates
changeset 403:65c53ec5e777
Bulma: complete redesign:
This is a WIP full redesign of the whole web UI. Only chat is usable at the moment, many
things are broken.
The design uses the new Bulma v1+, has a look closer to industry standards, paves the way
for a dark theme, and should be easy to use.
It's a basis for coming features such as UI/UX for threads.
rel 457
line wrap: on
line diff
--- a/sat_templates/templates/bulma/base/base.html Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/base/base.html Fri Apr 11 21:32:05 2025 +0200 @@ -93,10 +93,14 @@ <div class="modal-background"></div> <div class="modal-content"> <div class="notification has-text-centered"> - <span class="icon is-large"> - <i class="icon-loading icon_animate_spin"></i> - </span> - {% trans %}page is loading, please wait…{% endtrans %} + <div class="is-flex is-align-items-center is-justify-content-center"> + <span class="icon is-large"> + <i class="fa-solid fa-spinner fa-spin fa-xl"></i> + </span> + <span class=""> + {% trans %}page is loading, please wait…{% endtrans %} + </span> + </div> </div> </div> </div> @@ -107,7 +111,7 @@ {% endblock main_menu %} {% endif %} {% block body_wrapper %} - <div id="body" class="container"> + <div id="body"> {% if breadcrumbs and not no_breadcrumps and breadcrumbs|length > 1 %} <nav class="breadcrumb is-medium" aria-label="breadcrumbs"> <ul>
--- a/sat_templates/templates/bulma/chat/chat.html Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/chat/chat.html Fri Apr 11 21:32:05 2025 +0200 @@ -1,76 +1,160 @@ -{% if not embedded %}{% extends 'base/base.html' %}{% endif %} +{% if not embedded %} + {% set loading_screen = true %} + {% extends 'base/base.html' %} +{% endif %} +{% from 'components/collapsible_card.html' import collapsible_card %} {% block title %}{{ target_jid }} - {{ super() }}{% endblock %} {% block body %} {{ icon_defs( - "lock-open", "lock-filled", "ok", "pencil", "dot-3", "share", "attach", - "paper-plane-empty", "doc", "download", "wrench", "eye", "smile", "plus-circled", - "quote-left", "trash-empty" + "share-nodes", "ellipsis","regular face-smile", "quote-left", "paperclip", "pencil", "regular trash-can" ) }} - {# TODO: this should be done in a more generic way in dialog module #} - <div id="modal" class="modal"> - <div class="modal-background"></div> - <div class="modal-content"> - <p class="image"> - <img id="modal-image" src="" alt=""> - </p> - </div> - <button class="modal-close is-large" aria-label="close"></button> - </div> + - <div id="chat-panel" class="is-flex is-flex-direction-column is-justify-content-space-between is-align-items-stretch pt-4"> <!-- calculate height depending on your navbar size --> - <!-- Header --> - <div id="header" class="box p-4 is-flex is-justify-content-space-between is-align-items-center is-flex-shrink-0"> - {% if subject is defined %} - <h2 id="room-subject" class="title is-5 has-text-weight-bold">{{- subject|urlize(nofollow=true,target='_blank') -}}</h2> - {% endif %} + <div class="columns is-gapless chat-container"> + <!-- Left Panel --> + <div class="column is-2-desktop is-3-tablet chat-sidebar has-background-dark" id="left_panel"> + <aside class="menu pl-4"> + <button class="button is-ghost has-text-grey-light mb-2 pl-1 is-align-items-center is-justify-content-start is-fullwidth" id="new_chat_btn" aria-label="Start new discussion"> + <span class="icon"> + <i class="fas fa-circle-plus"></i> + </span> + <span class="pt-1">Start New Chat</span> + </button> + <p class="menu-label has-text-grey-light"> + {% trans %}Rooms{% endtrans %} + </p> + <ul class="menu-list"> + {% for room_address, room_info in bookmarks.items() %} + <li> + <a {{ {'href': chat_url + "/" + room_address}|xmlattr}} class="chat-jid has-text-white"><span class="icon"><i class="fas fa-hashtag"></i></span> {{ room_info.get('name', room_address.split('@')[0]) }}</a> + </li> + {% endfor %} + </ul> + <p class="menu-label has-text-grey-light"> + Direct Messages + </p> + <div id="direct-messages"></div> + </aside> </div> - <!-- Messages --> - <div id="messages" class="box p-4 has-background-white mb-4 is-flex-grow-1 is-flex-direction-column-reverse is-overflow-auto"> - {% for msg in messages %} - {% set current_date = msg.timestamp|date_fmt('full', date_only=True) %} - {% if loop.changed(current_date) %} - <div class="separator"> - <hr class="has-background-light" /> - <span class="has-text-grey is-size-7">{{current_date}}</span> - <hr class="has-background-light" /> + <!-- Main Chat Area --> + <div class="column is-8-desktop is-6-tablet chat-main" id="main_panel"> + <div class="chat-header"> + <div class="level is-mobile"> + <div class="level-left"> + <div class="level-item"> + <button class="button is-small" id="left_panel-toggle" aria-label="Toggle left panel"> + <span class="icon"><i class="fas fa-bars"></i></span> + </button> + </div> + <div class="level-item"> + <h1 class="title is-5 mb-0">{{target_jid}}</h1> + </div> + </div> + <div class="level-right"> + <div class="level-item"> + <div class="field has-addons"> + <div class="control"> + <input class="input is-small" type="text" placeholder="Search"> + </div> + <div class="control"> + <button class="button is-info is-small"> + <span class="icon is-small"> + <i class="fas fa-search"></i> + </span> + </button> + </div> + </div> + </div> + <div class="level-item"> + <button class="button is-small"> + <span class="icon"><i class="fas fa-cog"></i></span> + </button> + </div> + <div class="level-item {{ "is-hidden" if chat_type != "group" }}"> + <button class="button is-small" id="right_panel-toggle"> + <span class="icon"><i class="fas fa-info-circle"></i></span> + </button> + </div> + </div> </div> - {% endif %} - {% include 'chat/message.html' %} - {% endfor %} + </div> + + <!-- Messages --> + <div id="messages"> + {% for msg in messages %} + {% set current_date = msg.timestamp|date_fmt('full', date_only=True) %} + {% if loop.changed(current_date) %} + <div class="separator"> + <hr class="has-background-light" /> + <span class="has-text-grey is-size-7">{{current_date}}</span> + <hr class="has-background-light" /> + </div> + {% endif %} + {% include 'chat/message.html' %} + {% endfor %} + </div> + + <!-- Attachments --> + <div id="attachments" class="box has-background-white is-flex is-flex-grow-0 is-flex-shrink-0 is-align-items-center is-overflow-auto is-contracted"> + {% for file in attachments %} + {% include 'chat/attachment_preview.html' %} + {% endfor %} + </div> + + <div id="message_input" class="chat-input"> + <div class="field has-addons"> + <div class="control"> + <button id="attach-button" class="button"> + <span class="icon is-small"> + {{ icon('paperclip') }} + </span> + </button> + <input id="file-input" type="file" multiple="true" style="display: none" /> + </div> + <div class="control is-expanded"> + <textarea id="message_input_area" class="textarea" name="message_input_area" type="text" rows="1" placeholder="{{_("Type your message…")}}"></textarea> + </div> + <div class="control"> + <button class="button is-primary"> + <span class="icon is-small"> + <i class="fas fa-paper-plane"></i> + </span> + <span class="is-hidden-mobile">Send</span> + </button> + </div> + </div> + </div> + </div> - <!-- Attachments --> - <div id="attachments" class="box has-background-white is-flex is-flex-grow-0 is-flex-shrink-0 is-align-items-center is-overflow-auto is-contracted"> - {% for file in attachments %} - {% include 'chat/attachment_preview.html' %} - {% endfor %} - </div> + + <!-- Right Panel --> + + <div class="column is-2-desktop is-3-tablet chat-details {{ 'is-hidden' if chat_type != 'group' }}" id="right_panel"> + <div class="box is-shadowless has-background-white-bis is-full-height"> + <h3 class="title is-5 has-text-centered mb-4">Room Details</h3> + + {% if subject is defined %} + {% call collapsible_card("Subject", icon="fas fa-quote-left") %} + {{subject}} + {% endcall %} + {% endif %} - <!-- Input --> - <div id="input-area" class="field has-addons py-4 is-flex-shrink-0"> - <p class="control is-expanded"> - <textarea id="message_input" class="textarea" name="message" type="text" rows="1" placeholder="{{_("enter your message")}}"></textarea> - </p> - <div class="control"> - <button class="button" id="attach_button"> - <span class="icon is-small"> - {{ icon('attach', cls='has-text-info') }} - </span> - </button> - <input id="file_input" type="file" multiple="true" style="display: none" /> + <div class="card"> + <div class="card-header has-background-info-light"> + <p class="card-header-title has-text-info-dark"> + <span class="icon"><i class="fas fa-users"></i></span> + <span>Members (<span id="occupants-count">0</span>)</span> + </p> + </div> + <div class="card-content py-3 px-4" id="group-occupants"> + </div> + </div> + </div> </div> - <div class="control"> - <button class="button" id="send_button"> - <span class="icon is-small"> - {{ icon('paper-plane-empty') }} - </span> - </button> - </div> - </div> - </div> {% endblock body %} {% block footer %}{% endblock footer %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat_templates/templates/bulma/chat/direct_messages.html Fri Apr 11 21:32:05 2025 +0200 @@ -0,0 +1,7 @@ + +<ul class="menu-list"> + {% for contact_jid, contact_data in roster.items() %} + {%- set name = identities[contact_jid].nicknames[0] | default(contact_jid) -%} + <li><a {{ {'href': chat_url + '/' + contact_jid}|xmlattr}} class="has-background-inherit has-text-white"><span class="icon"><i class="fas fa-circle has-text-success"></i></span>{{name}}</a></li> + {% endfor %} +</ul>
--- a/sat_templates/templates/bulma/chat/extra_menu.html Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/chat/extra_menu.html Fri Apr 11 21:32:05 2025 +0200 @@ -1,4 +1,4 @@ -<div class="extra-menu-popup"> +<div class="menu extra-menu-popup"> <ul class="menu-list"> <li class="action_quote"> <a href="#" class=""> @@ -15,7 +15,7 @@ {% if retract %} <li class="action_retract"> <a href="#" class=""> - {{ icon('trash-empty', cls='icon is-small has-text-danger') }} {% trans %}Retract{% endtrans %} + {{ icon('regular trash-can', cls='icon is-small has-text-danger') }} {% trans %}Retract{% endtrans %} </a> </li> {% endif %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat_templates/templates/bulma/chat/groups_search_item.html Fri Apr 11 21:32:05 2025 +0200 @@ -0,0 +1,28 @@ +{% import 'components/avatar.html' as avatar with context %} + + + +<div class="search-item box py-2 px-3 mb-2 is-unselectable is-clickable" {{ {'data-entity': item.entity}|xmlattr }}> + <div class="is-flex is-align-items-center"> + <div class="mr-2"> + {{ avatar.avatar(item.entity) }} + </div> + <div class="is-flex-grow-1"> + <p class="mb-0">{{item.name if item.name else item.entity}}</p> + <p class="has-text-grey is-size-7">{{item.entity}}</p> + </div> + <div> + {% if item.occupants %} + <span class="tag is-info is-light"> + <span class="icon-text"> + <span class="icon"> + <i class="fa-solid fa-user"></i> + </span> + <span>23</span> + </span> + </span> + {% endif %} + </div> + </div> +</div> +
--- a/sat_templates/templates/bulma/chat/message.html Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/chat/message.html Fri Apr 11 21:32:05 2025 +0200 @@ -8,74 +8,74 @@ <div id="{{msg.id}}" - class="media is-chat-message msg_{{msg.type}} {{'own_msg' if own_msg}} {{ 'is-retracted' if msg.extra.retracted }}" + class="media chat-message msg_{{msg.type}} {{'own_msg' if own_msg}} {{ 'is-retracted' if msg.extra.retracted }}" role="listitem" aria-label="{{ 'Retracted Message' if msg.extra.retracted else 'Chat Message' }}" {% if msg.extra.editions %}data-editions='{{msg.extra.editions|tojson}}'{% endif %} > {%- if msg.type != "info" %} {%- set author = identities[msg.from_].nicknames[0] | default(msg.from_) -%} - <figure class="media-left pt-1"> - {{ avatar.avatar(msg.from_, "is-32x32") }} + <figure class="media-left"> + {{ avatar.avatar(msg.from_) }} </figure> {% endif -%} <div class="media-content is-relative"> - <div class="content"> {%- if msg.type != "info" %} - <nav class="level is-mobile is-marginless is-size-7 is-not-selectable"> - <div class="level-left has-text-weight-bold"> - <div class="level-item"> - <span class="author" id="msg_author_{{msg.id}}">{{author}}</span> - </div> + + <div> + + <span class="author" id="msg_author_{{msg.id}}">{{author}}</span> + <span class="date" id="msg_date_{{msg.id}}">{{(msg.extra.updated or msg.timestamp)|date_fmt('short', tz_name=tz_name)}}</span> + <span id="status_icons_{{msg.id}}" class="status-icons level-item has-padding-left"> + {% if msg.extra.editions %} + {{ icon('pencil', cls='icon is-small message-editions') }} + {% endif %} + {% if msg.encrypted %} + {{ icon('lock-filled', cls='icon is-small has-text-success') }} + {% else %} + {{ icon('lock-open', cls='icon is-small has-text-danger') }} + {% endif %} + {% if msg.received %} + {{ icon('ok', cls='icon is-small has-text-link') }} + {% endif %} + {% if msg.edited %} + {{ icon('pencil', cls='icon is-small has-text-info') }} + {% endif %} + </span> + </div> + + {% endif -%} + <div class="message-core"> + <p class="message-body {{ "has-text-info" if msg.type=="info" or msg.extra.retracted }} m-0" id="message-body_{{msg.id}}"> + {%- if msg.extra.retracted %} + {% trans %}This message has been retracted.{% endtrans %} + {% else %} + {{- msg.html or (msg.text|e|urlize|safe) -}} + {% endif -%} + </p> + + <div class="url-previews is-hidden"> + <div class="icon-container"></div> + </div> + + <div + id="actions_{{msg.id}}" + class="level message-actions mb-0 mt-1 {{ "is-hidden" if msg.extra.retracted }}" + > + <div class="level-left"></div> + <div class="level-right"> + {# {{ icon('share-nodes', cls='icon is-small action-button', id='msg_share_' + msg.id) }} #} + {{ icon('regular face-smile', cls='icon is-small action-button reaction-button', id='msg_actions_' + msg.id) }} + {{ icon('ellipsis', cls='icon is-small action-button extra-button', id='msg_actions_' + msg.id) }} </div> - <div class="level-right is-italic"> - <div class="level-item"> - <span class="date" id="msg_date_{{msg.id}}">{{(msg.extra.updated or msg.timestamp)|date_fmt('short', tz_name=tz_name)}}</span> - <div id="status_icons_{{msg.id}}" class="status-icons level-item has-padding-left"> - {% if msg.extra.editions %} - {{ icon('pencil', cls='icon is-small message-editions') }} - {% endif %} - {% if msg.encrypted %} - {{ icon('lock-filled', cls='icon is-small has-text-success') }} - {% else %} - {{ icon('lock-open', cls='icon is-small has-text-danger') }} - {% endif %} - {% if msg.received %} - {{ icon('ok', cls='icon is-small has-text-link') }} - {% endif %} - {% if msg.edited %} - {{ icon('pencil', cls='icon is-small has-text-info') }} - {% endif %} - </div> - </div> - </div> - </nav> - {% endif -%} - <p class="msg_body has-whitespace-pre-wrap {{ "has-text-info" if msg.type=="info" or msg.extra.retracted }} m-0" id="msg_body_{{msg.id}}"> - {%- if msg.extra.retracted %} - {% trans %}This message has been retracted.{% endtrans %} - {% else %} - {{- msg.html or (msg.text|e|urlize|safe) -}} - {% endif -%} - </p> + </div> - <div class="url-previews is-hidden"> - <div class="icon-container"></div> - </div> - - <div - id="actions_{{msg.id}}" - class="level is-mobile actions mb-0 {{ "is-hidden" if msg.extra.retracted }}" - > - {#{{ icon('share', cls='icon is-small action-button', id='msg_share_{{msg.id}}') }} #} - {{ icon('smile', cls='icon is-small action-button reaction-button', id='msg_actions_{{msg.id}}') }} - {{ icon('dot-3', cls='icon is-small action-button extra-button', id='msg_actions_{{msg.id}}') }} - </div> - <div id="msg_reactions_{{msg.id}}" style="margin-top: 0.5em;"> - {% if msg.extra.reactions is defined %} - {% set reactions = msg.extra.get("reactions") %} - {% include 'chat/reactions.html' %} - {% endif %} + <div id="msg_reactions_{{msg.id}}"> + {% if msg.extra.reactions is defined %} + {% set reactions = msg.extra.get("reactions") %} + {% include 'chat/reactions.html' %} + {% endif %} + </div> </div> {% if msg.attachments %} <div class="message-attachments pt-2"> @@ -106,6 +106,5 @@ {%- endfor %} </div> {% endif %} - </div> </div> </div>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat_templates/templates/bulma/chat/new_chat_dialog.html Fri Apr 11 21:32:05 2025 +0200 @@ -0,0 +1,125 @@ +{% import 'components/avatar.html' as avatar with context %} + +<div class="modal-card jid-search-dialog"> + <header class="modal-card-head"> + <p class="modal-card-title">Start New Chat</p> + <button class="delete action_close"></button> + </header> + <section class="modal-card-body"> + + <div class="tabs is-boxed mt-4"> + <ul> + <li class="is-active" data-tab="direct"> + <a> + <span class="icon has-text-info"> + <i class="fa-solid fa-user"></i> + </span> + <span>Persons</span> + <span class="tag is-info is-light ml-2 direct-count">0</span> + </a> + </li> + <li data-tab="groups"> + <a> + <span class="icon has-text-success"> + <i class="fa-solid fa-users"></i> + </span> + <span>Group Chats</span> + </a> + </li> + </ul> + </div> + + <!-- Direct Messages Tab --> + <div class="direct-content pt-4"> + <div class="field"> + <label class="label">Direct contact search.</label> + <p class="help">Use names, JIDs, or keywords.</p> + <div class="control has-icons-left has-icons-right"> + <input class="input search-input" type="search" + placeholder="Search contacts…"> + <span class="icon is-small is-left"> + <i class="fa-solid fa-magnifying-glass"></i> + </span> + <span class="icon is-right action_clear_search"> + <a role="button" class="delete is-small" aria-label="Clear search"></a> + </span> + </div> + </div> + <div class="direct-items"> + </div> + </div> + + <!-- Group Chats Tab --> + <div class="groups-content is-hidden pt-4"> + <div class="field"> + <label class="label">Room search.</label> + <p class="help">Use names, JIDs, or keywords.</p> + <div class="control has-icons-left has-icons-right"> + <input class="input search-input" type="search" + placeholder="Search rooms…"> + <span class="icon is-small is-left"> + <i class="fa-solid fa-magnifying-glass"></i> + </span> + <span class="icon is-right action_clear_search"> + <a role="button" class="delete is-small" aria-label="Clear search"></a> + </span> + </div> + </div> + <div class="is-flex is-justify-content-space-between mb-4"> + <button class="button is-success is-light action_new_room"> + <span class="icon"> + <i class="fa-solid fa-plus"></i> + </span> + <span>Create New Room</span> + </button> + </div> + + <!-- New Room Form (initially hidden) --> + <div class="box is-hidden mb-4 panel_new_room"> + <div class="field"> + <label class="label">Room Name</label> + <div class="control has-icons-left"> + <input class="input input-room-name" type="text" placeholder="Enter room name"> + <span class="icon is-small is-left"> + <i class="fa-solid fa-hashtag"></i> + </span> + </div> + </div> + <div class="field"> + <label class="label">Room Type</label> + <div class="control"> + <div class="select is-fullwidth"> + <select> + <option>Public Room</option> + {# + FIXME: only public room is supported for now, need to + check config option to use. + <option>Private Room</option> + #} + </select> + </div> + </div> + </div> + <div class="field is-grouped"> + <div class="control"> + <button class="button is-success is-small action_create_room">Create Room</button> + </div> + </div> + <div class="notification is-danger error-message is-hidden mt-4"> + <button class="delete action_hide_error_message"></button> + <p></p> + </div> + </div> + + <!-- Search Result --> + <div class="groups-items"></div> + </div> + </section> + <footer class="modal-card-foot is-justify-content-flex-end"> + <button class="button action_close">Cancel</button> + <button class="button is-primary ml-2 action_ok" disabled>Start Chat</button> + </footer> +</div> + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat_templates/templates/bulma/chat/occupant_item.html Fri Apr 11 21:32:05 2025 +0200 @@ -0,0 +1,10 @@ +{% import 'components/avatar.html' as avatar with context %} + +<div class="is-flex is-align-items-center"> + <div class="mr-2"> + {{ avatar.avatar(item.entity) }} + </div> + <div class="is-flex-grow-1"> + <p class="mb-0">{{nick}}</p> + </div> +</div>
--- a/sat_templates/templates/bulma/chat/reactions.html Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/chat/reactions.html Fri Apr 11 21:32:05 2025 +0200 @@ -9,7 +9,7 @@ {% for emoji, jids in reactions.items() %} {% set own_reaction = local_jid in jids %} <div - class="reaction box is-shadowless is-inline-flex is-align-items-center my-1 ml-0 mr-2 px-2 py-1 is-size-6 has-background-light has-border is-not-selectable {{ 'own-reaction' if own_reaction }}" + class="reaction is-inline-flex is-align-items-center {{ 'own-reaction' if own_reaction }}" data-jids='{{jids|tojson}}' > <span class="emoji has-text-weight-semibold">{{ emoji }}</span>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat_templates/templates/bulma/chat/search_item.html Fri Apr 11 21:32:05 2025 +0200 @@ -0,0 +1,20 @@ +{% import 'components/avatar.html' as avatar with context %} + + + +<div class="search-item box py-2 px-3 mb-2 is-unselectable is-clickable" {{ {'data-entity': item.entity}|xmlattr }}> + <div class="is-flex is-align-items-center"> + <div class="mr-2"> + {{ avatar.avatar(item.entity) }} + </div> + <div class="is-flex-grow-1"> + <p class="mb-0">{{identities[item.entity].nicknames[0] if identities[item.entity].nicknames else item.entity}}</p> + <p class="has-text-grey is-size-7">{{item.entity}}</p> + </div> + {# + <div> + <span class="tag is-success is-light">Online</span> + </div> + #} + </div> +</div>
--- a/sat_templates/templates/bulma/components/avatar.html Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/components/avatar.html Fri Apr 11 21:32:05 2025 +0200 @@ -1,13 +1,13 @@ -{% macro avatar(jid, class="is-48x48") %} +{% macro avatar(jid, class="") %} {%- if identities is defined -%} {% set identity = identities.get(jid) %} {%- if identity and identity.avatar.filename %} - <div class="is-avatar image {{class}}"> + <div class="avatar image {{class}}"> <img src="/cache/common/{{identity.avatar.filename}}"> </div> {% else %} {% set nick = identity.nicknames[0] if identity.nicknames else jid %} - <span class="is-avatar image {{class}} is-flex has-items-centered has-text-weight-bold is-size-3 {{class}}">{{nick|first|upper}}</span> + <span class="avatar {{class}} is-flex is-align-items-center is-justify-content-center has-text-weight-bold is-family-code {{class}}">{{nick|initials}}</span> {%- endif -%} {%- endif -%} {% endmacro %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat_templates/templates/bulma/components/collapsible_card.html Fri Apr 11 21:32:05 2025 +0200 @@ -0,0 +1,24 @@ +{% macro collapsible_card(title, header_color='has-background-primary-light', icon=none) %} + <div class="card collapsible-card"> + <div class="card-header collapsible-header {{ header_color }}"> + <p class="card-header-title"> + {% if icon %} + <span class="icon is-small mr-2"> + <i class="fas fa-{{ icon }}"></i> + </span> + {% endif %} + {{ title }} + <span class="icon is-small ml-2 collapsible-icon"> + <i class="fas fa-chevron-down"></i> + </span> + </p> + </div> + <div class="collapsible-content"> + <div class="card-content"> + <div class="content"> + {{ caller() }} + </div> + </div> + </div> + </div> +{% endmacro %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat_templates/templates/bulma/dialogs/modal.html Fri Apr 11 21:32:05 2025 +0200 @@ -0,0 +1,8 @@ +<div class="modal is-active"> + <div class="modal-background"></div> + <div class="modal-content"> + </div> + {% if closable %} + <button class="modal-close is-large" aria-label="close"></button> + {% endif %} +</div>
--- a/sat_templates/templates/bulma/dialogs/notification.html Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/dialogs/notification.html Fri Apr 11 21:32:05 2025 +0200 @@ -1,5 +1,5 @@ <div class="main_notification columns is-centered"> - <div class="column is-narrow has-items-centered"> + <div class="column has-items-centered"> {% set level_map={ 'success': 'is-success', 'info': 'is-info',
--- a/sat_templates/templates/bulma/login/login.html Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/login/login.html Fri Apr 11 21:32:05 2025 +0200 @@ -5,7 +5,7 @@ {% block title %}{{C.APP_NAME}} login{% endblock %} {% block body %} -{{ icon_defs('group') }} +{{ icon_defs('users') }} <section class="section"> <div class="columns is-vcentered is-centered"> <div class="column is-narrow is-hidden-touch">
--- a/sat_templates/templates/bulma/static/chat.css Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/static/chat.css Fri Apr 11 21:32:05 2025 +0200 @@ -1,66 +1,220 @@ -#chat-panel { - height: calc(100vh - 3.25rem); +html, body, #body { + height: 100%; + overflow: hidden; +} + + +.chat-main { + /* Base colors */ + --color-background: #ffffff; + --color-text: #4a4a4a; + + /* Message colors */ + --message-background: #f5f5f5; + --message-hover-background: #e8e8e8; + + /* Reaction colors */ + --reaction-background: #ffffff; + --reaction-hover-background: #f5f5f5; + --reaction-border: #dbdbdb; + + /* User reaction colors */ + --reaction-user-background: #eef6fc; + --reaction-user-hover-background: #e3f1fc; + --reaction-user-border: #3273dc; + + /* Spacing */ + --reaction-padding: 0.25rem 0.5rem; + --reaction-gap: 0.5rem; + --reaction-margin-top: 0.5rem; + + /* Typography */ + --reaction-font-size: 0.875rem; + --reaction-counter-font-size: 0.75rem; +} + +[data-theme="dark"] .chat-main { + --color-background: #2c2c2c; + --color-text: #ffffff; + + --message-background: #363636; + --message-hover-background: #404040; + + --reaction-background: #2c2c2c; + --reaction-hover-background: #404040; + --reaction-border: #4a4a4a; + + --reaction-user-background: #1a3b5c; + --reaction-user-hover-background: #234875; + --reaction-user-border: #3273dc; +} + +.chat-container { + height: 100%; + overflow-y: auto; +} + +.chat-main { + height: 100%; + display: flex; + flex-direction: column; +} + +.chat-header { + border-bottom: 1px solid #dbdbdb; + padding: 0.5rem 1rem; +} + + +/* Sidebar toggle transitions */ +.chat-sidebar, .chat-details { + transition: transform 0.3s ease, max-width 0.3s ease, opacity 0.3s ease; + overflow-x: hidden; +} + +.chat-sidebar.is-collapsed { + transform: translateX(-100%); + max-width: 0; + padding: 0; + margin: 0; + opacity: 0; +} + +.chat-details.is-collapsed { + transform: translateX(100%); + max-width: 0; + padding: 0; + margin: 0; + opacity: 0; +} + +.chat-main.is-expanded-left { + margin-left: 0; } +.chat-main.is-expanded-right { + margin-right: 0; +} + +.columns.is-gapless.chat-container { + flex-wrap: nowrap; +} + +.author { + font-weight: bold; +} #messages { + flex-grow: 1; overflow-y: auto; + padding: 1rem; } +#left_panel a { + background-color: inherit; +} + +#left_panel a:hover { + background-color: #444; +} + +.chat-input { + border-top: 1px solid #dbdbdb; + padding: 1rem; +} + +.chat-input button { + height: 100%; +} + +.chat-message { + max-width: 95%; +} + +.message-core { + margin-bottom: 1rem; + padding: 0.75rem; + border-radius: 0.5rem; + overflow-wrap: anywhere; + background-color: #f5f5f5; + transition: background-color 0.2s, border-left 0.2s; +} +.message-core:hover, .message-core.has-popup-focus { + background-color: #e8e8e8; + border-left: 4px solid #3273dc; +} + +.message-actions { + display: none; +} + +.message-core:hover .message-actions, +.message-core.has-popup-focus .message-actions +{ + display: flex; +} + +.reactions-container { + gap: var(--reaction-gap); + margin-top: var(--reaction-margin-top); +} +.reaction { + padding: var(--reaction-padding); + border-radius: 1rem; + background-color: var(--reaction-background); + font-size: var(--reaction-font-size); + cursor: pointer; + transition: all 0.2s ease; + border: 1px solid var(--reaction-border); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.reaction:hover { + background-color: var(--reaction-hover-background); +} + +.reaction .counter { + margin-left: 0.25rem; + font-size: var(--reaction-counter-font-size); + color: var(--color-text); +} + +.reaction.own-reaction { + background-color: var(--reaction-user-background); + border-color: var(--reaction-user-border); +} + +.reaction.own-reaction:hover { + background-color: var(--reaction-user-hover-background); +} + + #attachments { overflow-x: auto; white-space: nowrap; } -#message_input { - resize: None; - max-height: 20rem; - min-height: 48px; -} - -/* Input "edit" mode */ -#message_input.mode_edit { - background-color: #d1ecf1; -} - -.is-chat-message { - transition: all 0.3s ease; -} - -.is-chat-message:hover, .is-chat-message.has-popup-focus { +.message-core:hover, .message-core.has-popup-focus { background-color: #f5f5f5; box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2); } -.media.is-chat-message.is-retracted { - padding: 0.5em; - border-left: 3px solid #ff3860; /* Reddish border for distinction */ - background-color: #f5f5f5; /* Light grey background */ - color: #636363; /* Slightly darker text for better readability */ +.message-body { + white-space: pre-wrap; + overflow-wrap: break-word; } .message-attachment { max-width: 20rem; } - .status-icons { - padding-bottom: 0.4rem; -} - -.actions { - position: absolute; - right: 5px; - bottom: 5px; - opacity: 0; -} - -.is-chat-message:hover .actions, .chat-message-highlight .actions { - opacity: 1; + display: inline; } .action-button { box-sizing: border-box; margin: 0 0.2rem; user-select: none; + cursor: pointer; z-index: 10; } @@ -70,34 +224,6 @@ transition: box-shadow 0.3s ease; } -.has-padding-left { - padding-left: 0.5em; -} - -#attach_button, #send_button { - height: 100%; -} - -/* URL previews */ - -.url-preview-iframe-container { - position: relative; - padding-bottom: 56.25%; - height: 0; - overflow: hidden; - max-width: 100%; - background: #000; -} - -.url-preview-iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; -} - /* Attachments */ #attachments { @@ -125,48 +251,3 @@ width: 9rem; height: 6rem; } - -.thumbnail-container { - width: 150px; - height: 80px; - overflow: hidden; - position: relative; -} -.icon { - width: 60px; - height: 60px; -} - -.thumbnail-image { - position: absolute; - left: 50%; - top: 50%; - height: 100%; - width: auto; - transform: translate(-50%, -50%); -} - -.attachment-name { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - max-width: 100%; - font-size: 0.8em; - letter-spacing: 0.02em; - text-align: center; - margin-top: auto; -} - -.thumbnail-image:empty { - left: 50%; - top: 50%; - width: 8rem; - height: auto; - transform: translate(-50%, -50%); -} - -.attachment-delete-button { - position: absolute; - top: -10px; - right: -10px; -}
--- a/sat_templates/templates/bulma/static/styles.css Sat Oct 26 22:53:26 2024 +0200 +++ b/sat_templates/templates/bulma/static/styles.css Fri Apr 11 21:32:05 2025 +0200 @@ -1,7 +1,26 @@ +:root { + --selected-item-bg: deepskyblue; +} + html, body { + height: 100vh; + overflow: hidden; +} + +body { + display: flex; + flex-direction: column; +} + +#body { + display: flex; + flex-direction: column; + overflow: auto; +} + +.is-full-height { height: 100%; - overflow: hidden; } .navbar-item { @@ -12,3 +31,47 @@ .menu-item { padding-top: 0.225em; } + +.avatar { + width: 40px; + height: 40px; + border-radius: 50%; + background-color: #3273dc; + color: #fff; +} + +.avatar.image { + background-color: #ccc; + padding: 3px; +} + +div.jid-search-dialog { + min-height: 80%; +} + +div.search-item.is-selected { + background-color: var(--selected-item-bg); +} + + +.collapsible-content { + overflow: hidden; + max-height: 0; + opacity: 1; + transition: + max-height 0.3s ease-out, + opacity 0.2s linear; +} + +.collapsible-header.collapsed .collapsible-icon { + transform: rotate(-90deg); +} + +/* Animation */ +.collapsible-header.collapsed + .collapsible-content { + opacity: 0; +} + +.collapsible-icon { + transition: transform 0.2s ease-out; +}