update layout styles to support multiple panes

This commit is contained in:
marlon-erler
2024-07-22 13:29:08 +02:00
parent e8ab217be3
commit 343bd7ef01
5 changed files with 200 additions and 191 deletions
+24 -21
View File
@@ -205,31 +205,34 @@ body[showing-chat] #chat-page-wrapper {
#chat-page { #chat-page {
--ribbon-size: calc(var(--control-height) + 2 * var(--gap-between-tiles)); --ribbon-size: calc(var(--control-height) + 2 * var(--gap-between-tiles));
} }
#chat-page #ribbon, #chat-page > div,
#chat-page .toolbar, #chat-page > div > #ribbon,
#chat-page #main, #chat-page > div > #main,
#chat-page #main .content { #chat-page > div > #main > div,
#chat-page > div > #main > div > .pane,
#chat-page > div > #main > div > .pane > .toolbar,
#chat-page > div > #main > div > .pane > .content {
display: flex; display: flex;
} }
#chat-page > div { #chat-page > div {
padding: 0px; padding: 0px;
overflow: hidden; overflow: hidden;
display: flex;
} }
#chat-page #main { #chat-page > div > #main {
width: calc(100% - var(--ribbon-size)); width: calc(100% - var(--ribbon-size));
display: flex;
flex-direction: column;
} }
#chat-page #main > div, #chat-page #main > div,
#chat-page #main .content { #chat-page > div > #main > div > .pane,
#chat-page > div > #main > div > .pane > .content {
width: 100%; width: 100%;
height: 100%; height: 100%;
flex: 1; flex: 1;
display: flex; }
#chat-page > div > #main > div > .pane {
flex-direction: column; flex-direction: column;
} }
#chat-page #main .content { #chat-page > div > #main > div > .pane > .content {
flex-direction: column;
overflow: auto; overflow: auto;
padding: var(--content-padding); padding: var(--content-padding);
} }
@@ -238,41 +241,41 @@ body[showing-chat] #chat-page-wrapper {
#chat-page #main .content { #chat-page #main .content {
flex-direction: column; flex-direction: column;
} }
#chat-page #ribbon { #chat-page > div > #ribbon {
width: var(--ribbon-size); width: var(--ribbon-size);
border-right: 1px solid var(--border); border-right: 1px solid var(--border);
justify-content: space-between; justify-content: space-between;
padding-bottom: var(--safe-area-bottom); padding-bottom: var(--safe-area-bottom);
} }
#chat-page #ribbon > span { #chat-page > div > #ribbon > span {
height: 100%; height: 100%;
flex: 1; flex: 1;
overflow: auto; overflow: auto;
justify-content: flex-end; justify-content: flex-end;
} }
#chat-page #main .toolbar { #chat-page > div > #main > div > .pane > .toolbar {
height: var(--ribbon-size); height: var(--ribbon-size);
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
overflow-x: auto; overflow-x: auto;
padding-left: var(--content-padding); padding-left: var(--content-padding);
border-top: 1px solid var(--border); border-top: 1px solid var(--border);
} }
#chat-page #ribbon, #chat-page > div > #ribbon,
#chat-page .toolbar { #chat-page > div > #main > div > .pane > .toolbar {
align-items: center; align-items: center;
} }
#chat-page #ribbon > span, #chat-page #ribbon > span,
#chat-page .toolbar > span { #chat-page > div > #main > div > .pane > .toolbar > span {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: var(--gap-between-tiles); padding: var(--gap-between-tiles);
gap: var(--gap-between-tiles); gap: var(--gap-between-tiles);
} }
#chat-page #ribbon > span { #chat-page > div > #ribbon > span {
width: 100%; width: 100%;
} }
#chat-page #ribbon button, #chat-page > div > #ribbon button,
#chat-page .toolbar button { #chat-page > div > #main > div > .pane > .toolbar button {
padding: 0px; padding: 0px;
width: 100%; width: 100%;
max-width: var(--control-height); max-width: var(--control-height);
@@ -281,7 +284,7 @@ body[showing-chat] #chat-page-wrapper {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
#chat-page #ribbon > button { #chat-page > div > #ribbon > button {
margin-top: var(--gap-between-tiles); margin-top: var(--gap-between-tiles);
} }
+4 -4
View File
@@ -1604,7 +1604,7 @@
} }
chatViewModel.chatMessageViewModels.subscribeSilent(scrollDownIfApplicable); chatViewModel.chatMessageViewModels.subscribeSilent(scrollDownIfApplicable);
setTimeout(() => scrollDown(), 100); setTimeout(() => scrollDown(), 100);
return /* @__PURE__ */ createElement("div", { id: "message-page" }, /* @__PURE__ */ createElement("div", { class: "toolbar" }, /* @__PURE__ */ createElement("span", { "subscribe:innerText": chatViewModel.primaryChannel })), /* @__PURE__ */ createElement("div", { class: "content" }, messageContainer, /* @__PURE__ */ createElement("div", { id: "composer" }, /* @__PURE__ */ createElement("div", { class: "content-width-constraint" }, /* @__PURE__ */ createElement("div", { class: "input-width-constraint" }, /* @__PURE__ */ createElement( return /* @__PURE__ */ createElement("div", { id: "message-page" }, /* @__PURE__ */ createElement("div", { class: "pane" }, /* @__PURE__ */ createElement("div", { class: "toolbar" }, /* @__PURE__ */ createElement("span", { "subscribe:innerText": chatViewModel.primaryChannel })), /* @__PURE__ */ createElement("div", { class: "content" }, messageContainer, /* @__PURE__ */ createElement("div", { id: "composer" }, /* @__PURE__ */ createElement("div", { class: "content-width-constraint" }, /* @__PURE__ */ createElement("div", { class: "input-width-constraint" }, /* @__PURE__ */ createElement(
"input", "input",
{ {
"bind:value": chatViewModel.composingMessage, "bind:value": chatViewModel.composingMessage,
@@ -1620,7 +1620,7 @@
"toggle:disabled": chatViewModel.cannotSendMessage "toggle:disabled": chatViewModel.cannotSendMessage
}, },
/* @__PURE__ */ createElement("span", { class: "icon" }, "send") /* @__PURE__ */ createElement("span", { class: "icon" }, "send")
)))))); )))))));
} }
// src/View/Components/dangerousActionButton.tsx // src/View/Components/dangerousActionButton.tsx
@@ -1677,7 +1677,7 @@
chatViewModel.removeSecondaryChannel(secondaryChannel); chatViewModel.removeSecondaryChannel(secondaryChannel);
}); });
}; };
return /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("div", { class: "toolbar" }, /* @__PURE__ */ createElement("span", null, translations.chatPage.settings.settingsHeadline)), /* @__PURE__ */ createElement("div", { class: "content" }, /* @__PURE__ */ createElement("label", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "forum"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translations.chatPage.settings.primaryChannelLabel), /* @__PURE__ */ createElement( return /* @__PURE__ */ createElement("div", { id: "settings-page" }, /* @__PURE__ */ createElement("div", { class: "pane" }, /* @__PURE__ */ createElement("div", { class: "toolbar" }, /* @__PURE__ */ createElement("span", null, translations.chatPage.settings.settingsHeadline)), /* @__PURE__ */ createElement("div", { class: "content" }, /* @__PURE__ */ createElement("label", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "forum"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translations.chatPage.settings.primaryChannelLabel), /* @__PURE__ */ createElement(
"input", "input",
{ {
"bind:value": chatViewModel.primaryChannelInput, "bind:value": chatViewModel.primaryChannelInput,
@@ -1764,7 +1764,7 @@
translations.chatPage.settings.deleteChatButton, translations.chatPage.settings.deleteChatButton,
"chat_error", "chat_error",
chatViewModel.remove chatViewModel.remove
)))); )))));
} }
// src/View/ChatPages/taskPage.tsx // src/View/ChatPages/taskPage.tsx
+27 -25
View File
@@ -33,31 +33,33 @@ export function MessagePage(chatViewModel: ChatViewModel) {
return ( return (
<div id="message-page"> <div id="message-page">
<div class="toolbar"> <div class="pane">
<span subscribe:innerText={chatViewModel.primaryChannel}></span> <div class="toolbar">
</div> <span subscribe:innerText={chatViewModel.primaryChannel}></span>
<div class="content"> </div>
{messageContainer} <div class="content">
<div id="composer"> {messageContainer}
<div class="content-width-constraint"> <div id="composer">
<div class="input-width-constraint"> <div class="content-width-constraint">
<input <div class="input-width-constraint">
bind:value={chatViewModel.composingMessage} <input
on:enter={chatViewModel.sendMessage} bind:value={chatViewModel.composingMessage}
placeholder={ on:enter={chatViewModel.sendMessage}
translations.chatPage.message.composerInputPlaceholder placeholder={
} translations.chatPage.message.composerInputPlaceholder
></input> }
<button ></input>
class="primary" <button
aria-label={ class="primary"
translations.chatPage.message.sendMessageButtonAudioLabel aria-label={
} translations.chatPage.message.sendMessageButtonAudioLabel
on:click={chatViewModel.sendMessage} }
toggle:disabled={chatViewModel.cannotSendMessage} on:click={chatViewModel.sendMessage}
> toggle:disabled={chatViewModel.cannotSendMessage}
<span class="icon">send</span> >
</button> <span class="icon">send</span>
</button>
</div>
</div> </div>
</div> </div>
</div> </div>
+120 -117
View File
@@ -16,136 +16,139 @@ export function SettingsPage(chatViewModel: ChatViewModel) {
}; };
return ( return (
<div> <div id="settings-page">
<div class="toolbar"> <div class="pane">
<span>{translations.chatPage.settings.settingsHeadline}</span> <div class="toolbar">
</div> <span>{translations.chatPage.settings.settingsHeadline}</span>
<div class="content"> </div>
<label class="tile flex-no"> <div class="content">
<span class="icon">forum</span> <label class="tile flex-no">
<div> <span class="icon">forum</span>
<span>{translations.chatPage.settings.primaryChannelLabel}</span> <div>
<input <span>{translations.chatPage.settings.primaryChannelLabel}</span>
bind:value={chatViewModel.primaryChannelInput} <input
on:enter={chatViewModel.setPrimaryChannel} bind:value={chatViewModel.primaryChannelInput}
></input> on:enter={chatViewModel.setPrimaryChannel}
></input>
</div>
</label>
<div class="flex-row justify-end width-input">
<button
class="width-50"
aria-label={
translations.chatPage.settings.setPrimaryChannelButtonAudioLabel
}
on:click={chatViewModel.setPrimaryChannel}
toggle:disabled={chatViewModel.cannotSetPrimaryChannel}
>
{translations.general.setButton}
<span class="icon">check</span>
</button>
</div> </div>
</label>
<div class="flex-row justify-end width-input">
<button
class="width-50"
aria-label={
translations.chatPage.settings.setPrimaryChannelButtonAudioLabel
}
on:click={chatViewModel.setPrimaryChannel}
toggle:disabled={chatViewModel.cannotSetPrimaryChannel}
>
{translations.general.setButton}
<span class="icon">check</span>
</button>
</div>
<hr></hr> <hr></hr>
<div class="flex-row width-input margin-bottom"> <div class="flex-row width-input margin-bottom">
<input
aria-label={
translations.chatPage.settings.newSecondaryChannelAudioLabel
}
placeholder={
translations.chatPage.settings.newSecondaryChannelPlaceholder
}
bind:value={chatViewModel.newSecondaryChannelInput}
on:enter={chatViewModel.addSecondaryChannel}
></input>
<button
class="primary"
aria-label={
translations.chatPage.settings.addSecondaryChannelButtonAudioLabel
}
on:click={chatViewModel.addSecondaryChannel}
toggle:disabled={chatViewModel.cannotAddSecondaryChannel}
>
<span class="icon">add</span>
</button>
</div>
<div
class="flex-column gap width-input"
children:append={[
chatViewModel.secondaryChannels,
secondaryChannelConverter,
]}
></div>
<hr></hr>
<label class="tile flex-no">
<span class="icon">key</span>
<div>
<span>{translations.chatPage.settings.encryptionKeyLabel}</span>
<input <input
bind:value={chatViewModel.encryptionKeyInput} aria-label={
on:enter={chatViewModel.setEncryptionKey} translations.chatPage.settings.newSecondaryChannelAudioLabel
set:type={chatViewModel.encryptionKeyInputType} }
placeholder={
translations.chatPage.settings.newSecondaryChannelPlaceholder
}
bind:value={chatViewModel.newSecondaryChannelInput}
on:enter={chatViewModel.addSecondaryChannel}
></input> ></input>
<button
class="primary"
aria-label={
translations.chatPage.settings
.addSecondaryChannelButtonAudioLabel
}
on:click={chatViewModel.addSecondaryChannel}
toggle:disabled={chatViewModel.cannotAddSecondaryChannel}
>
<span class="icon">add</span>
</button>
</div> </div>
</label>
<div class="flex-row justify-end width-input">
<button
class="width-50"
aria-label={
translations.chatPage.settings.setEncryptionKeyButtonAudioLabel
}
on:click={chatViewModel.setEncryptionKey}
toggle:disabled={chatViewModel.cannotSetEncryptionKey}
>
{translations.general.setButton}
<span class="icon">check</span>
</button>
</div>
<label class="inline"> <div
<input class="flex-column gap width-input"
type="checkbox" children:append={[
bind:checked={chatViewModel.shouldShowEncryptionKey} chatViewModel.secondaryChannels,
></input> secondaryChannelConverter,
{translations.chatPage.settings.showEncryptionKey} ]}
</label> ></div>
<hr></hr> <hr></hr>
<div class="flex-row gap width-input"> <label class="tile flex-no">
{...Object.values(Color).map((color) => { <span class="icon">key</span>
const isSelected = React.createProxyState( <div>
[chatViewModel.color], <span>{translations.chatPage.settings.encryptionKeyLabel}</span>
() => chatViewModel.color.value == color <input
); bind:value={chatViewModel.encryptionKeyInput}
on:enter={chatViewModel.setEncryptionKey}
set:type={chatViewModel.encryptionKeyInputType}
></input>
</div>
</label>
<div class="flex-row justify-end width-input">
<button
class="width-50"
aria-label={
translations.chatPage.settings.setEncryptionKeyButtonAudioLabel
}
on:click={chatViewModel.setEncryptionKey}
toggle:disabled={chatViewModel.cannotSetEncryptionKey}
>
{translations.general.setButton}
<span class="icon">check</span>
</button>
</div>
function setColor() { <label class="inline">
chatViewModel.setColor(color); <input
} type="checkbox"
bind:checked={chatViewModel.shouldShowEncryptionKey}
></input>
{translations.chatPage.settings.showEncryptionKey}
</label>
return ( <hr></hr>
<button
color={color}
class="fill-color width-100 flex"
style="height: 2rem"
toggle:selected={isSelected}
on:click={setColor}
></button>
);
})}
</div>
<hr></hr> <div class="flex-row gap width-input">
{...Object.values(Color).map((color) => {
const isSelected = React.createProxyState(
[chatViewModel.color],
() => chatViewModel.color.value == color
);
<div class="width-input"> function setColor() {
{DangerousActionButton( chatViewModel.setColor(color);
translations.chatPage.settings.deleteChatButton, }
"chat_error",
chatViewModel.remove return (
)} <button
color={color}
class="fill-color width-100 flex"
style="height: 2rem"
toggle:selected={isSelected}
on:click={setColor}
></button>
);
})}
</div>
<hr></hr>
<div class="width-input">
{DangerousActionButton(
translations.chatPage.settings.deleteChatButton,
"chat_error",
chatViewModel.remove
)}
</div>
</div> </div>
</div> </div>
</div> </div>
+25 -24
View File
@@ -26,39 +26,40 @@ body[showing-chat] #chat-page-wrapper {
--ribbon-size: calc(var(--control-height) + 2 * var(--gap-between-tiles)); --ribbon-size: calc(var(--control-height) + 2 * var(--gap-between-tiles));
} }
#chat-page #ribbon, #chat-page > div,
#chat-page .toolbar, #chat-page > div > #ribbon,
#chat-page #main, #chat-page > div > #main,
#chat-page #main .content { #chat-page > div > #main > div,
#chat-page > div > #main > div > .pane,
#chat-page > div > #main > div > .pane > .toolbar,
#chat-page > div > #main > div > .pane > .content {
display: flex; display: flex;
} }
#chat-page > div { #chat-page > div {
padding: 0px; padding: 0px;
overflow: hidden; overflow: hidden;
display: flex;
} }
#chat-page #main { #chat-page > div > #main {
width: calc(100% - var(--ribbon-size)); width: calc(100% - var(--ribbon-size));
display: flex;
flex-direction: column;
} }
#chat-page #main > div, #chat-page #main > div,
#chat-page #main .content { #chat-page > div > #main > div > .pane,
#chat-page > div > #main > div > .pane > .content {
width: 100%; width: 100%;
height: 100%; height: 100%;
flex: 1; flex: 1;
}
display: flex; #chat-page > div > #main > div > .pane {
flex-direction: column; flex-direction: column;
} }
#chat-page #main .content { #chat-page > div > #main > div > .pane > .content {
flex-direction: column;
overflow: auto; overflow: auto;
padding: var(--content-padding); padding: var(--content-padding);
} }
@@ -69,7 +70,7 @@ body[showing-chat] #chat-page-wrapper {
} }
/* ribbon, toolbar */ /* ribbon, toolbar */
#chat-page #ribbon { #chat-page > div > #ribbon {
width: var(--ribbon-size); width: var(--ribbon-size);
border-right: 1px solid var(--border); border-right: 1px solid var(--border);
@@ -78,16 +79,16 @@ body[showing-chat] #chat-page-wrapper {
padding-bottom: var(--safe-area-bottom); padding-bottom: var(--safe-area-bottom);
} }
#chat-page #ribbon > span { #chat-page > div > #ribbon > span {
height: 100%; height: 100%;
flex: 1; flex: 1;
overflow: auto; overflow: auto;
justify-content: flex-end; justify-content: flex-end;
} }
#chat-page #main .toolbar { #chat-page > div > #main > div > .pane > .toolbar {
height: var(--ribbon-size); height: var(--ribbon-size);
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
@@ -97,13 +98,13 @@ body[showing-chat] #chat-page-wrapper {
border-top: 1px solid var(--border); border-top: 1px solid var(--border);
} }
#chat-page #ribbon, #chat-page > div > #ribbon,
#chat-page .toolbar { #chat-page > div > #main > div > .pane > .toolbar {
align-items: center; align-items: center;
} }
#chat-page #ribbon > span, #chat-page #ribbon > span,
#chat-page .toolbar > span { #chat-page > div > #main > div > .pane > .toolbar > span {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -111,12 +112,12 @@ body[showing-chat] #chat-page-wrapper {
gap: var(--gap-between-tiles); gap: var(--gap-between-tiles);
} }
#chat-page #ribbon > span { #chat-page > div > #ribbon > span {
width: 100%; width: 100%;
} }
#chat-page #ribbon button, #chat-page > div > #ribbon button,
#chat-page .toolbar button { #chat-page > div > #main > div > .pane > .toolbar button {
padding: 0px; padding: 0px;
width: 100%; width: 100%;
@@ -128,6 +129,6 @@ body[showing-chat] #chat-page-wrapper {
justify-content: center; justify-content: center;
} }
#chat-page #ribbon > button { #chat-page > div > #ribbon > button {
margin-top: var(--gap-between-tiles); margin-top: var(--gap-between-tiles);
} }