@@ -387,7 +390,7 @@ command_listener(async (e) => {
@@ -410,10 +413,9 @@ command_listener(async (e) => {
}
.logo {
- height: calc(var(--appbar-height) - 3rem);
+ height: calc(var(--appbar-height) - 2.5rem);
width: auto;
min-height: 100%;
- margin-right: var(--gap-md);
color: var(--color-contrast);
}
@@ -464,7 +466,14 @@ command_listener(async (e) => {
.container {
--appbar-height: 4.5rem;
+
--sidebar-width: 4.5rem;
+ --sidebar-open-width: 15rem;
+ --sidebar-padding: 0.75rem;
+
+ --sidebar-icon-size: 1.5rem;
+ --sidebar-button-size: calc(var(--sidebar-width) - calc(var(--sidebar-padding) * 2));
+ --sidebar-open-button-size: calc(var(--sidebar-open-width) - calc(var(--sidebar-padding) * 2));
height: 100vh;
display: flex;
@@ -552,12 +561,50 @@ command_listener(async (e) => {
.nav-container {
display: flex;
flex-direction: column;
+
+ padding-left: var(--sidebar-padding);
+ padding-right: var(--sidebar-padding);
+ padding-bottom: var(--sidebar-padding);
+
align-items: center;
justify-content: space-between;
+
height: 100%;
+
background-color: var(--color-raised-bg);
box-shadow: var(--shadow-inset-sm), var(--shadow-floating);
- padding: var(--gap-md);
+
+ transition: all ease-in-out 0.1s;
+
+ width: var(--sidebar-width);
+}
+
+.nav-container__open {
+ width: var(--sidebar-open-width);
+}
+
+.square-collapsed-space {
+ height: var(--appbar-height);
+ width: 100%;
+
+ user-select: none;
+ -webkit-user-select: none;
+
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+}
+
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ .square-collapsed-space {
+ height: auto;
+ padding-bottom: var(--gap-md);
+ }
+}
+
+.instances {
+ height: 100%;
+ flex-grow: 1;
}
.pages-list {
@@ -565,7 +612,9 @@ command_listener(async (e) => {
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
+
width: 100%;
+
gap: 0.35rem;
.page-item,
@@ -600,79 +649,35 @@ command_listener(async (e) => {
}
.collapsed-button {
- height: 3rem !important;
- width: 3rem !important;
- padding: 0.75rem;
+ justify-content: flex-start;
+
+ // width: var(--sidebar-icon-size);
+ height: var(--sidebar-button-size);
+ width: 100%;
+
+ padding: var(--sidebar-padding) !important;
border-radius: 99999px;
box-shadow: none;
+ white-space: nowrap;
+ overflow: hidden;
+
+ transition: all ease-in-out 0.1s;
+
+ .collapsed-button__icon,
svg {
- width: 1.5rem !important;
- height: 1.5rem !important;
- max-width: 1.5rem !important;
- max-height: 1.5rem !important;
- }
-}
+ width: var(--sidebar-icon-size);
+ height: var(--sidebar-icon-size);
-.instance-list {
- display: flex;
- flex-direction: column;
- justify-content: center;
- width: 70%;
- margin: 0.4rem;
-
- p:nth-child(1) {
- font-size: 0.6rem;
+ flex-shrink: 0;
}
- & > p {
- color: var(--color-base);
- margin: 0.8rem 0;
- font-size: 0.7rem;
- line-height: 0.8125rem;
- font-weight: 500;
- text-transform: uppercase;
+ .collapsed-button__label {
+ opacity: var(--sidebar-label-opacity);
+ transition: all ease-in-out 0.1s;
}
}
-.user-section {
- display: flex;
- justify-content: flex-start;
- align-items: center;
- width: 100%;
- height: 4.375rem;
-
- section {
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- text-align: left;
- margin-left: 0.5rem;
- }
-
- .username {
- margin-bottom: 0.3rem;
- font-weight: 400;
- line-height: 1.25rem;
- color: var(--color-contrast);
- }
-
- a {
- font-weight: 400;
- color: var(--color-secondary);
- }
-}
-
-.nav-section {
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- align-items: center;
- gap: 1rem;
-
- height: 100%;
-}
-
.video {
margin-top: 2.25rem;
width: 100vw;
diff --git a/theseus_gui/src/composables/click.js b/theseus_gui/src/composables/click.js
new file mode 100644
index 000000000..1f8fdb8ea
--- /dev/null
+++ b/theseus_gui/src/composables/click.js
@@ -0,0 +1,47 @@
+import { openExternal } from '@/helpers/external'
+import { onMounted } from 'vue'
+
+const disableMiddleClick = (e) => {
+ // disables middle click -> new tab
+ if (e.button === 1) {
+ e.preventDefault()
+ // instead do a left click
+ const event = new MouseEvent('click', {
+ view: window,
+ bubbles: true,
+ cancelable: true,
+ })
+ e.target.dispatchEvent(event)
+ }
+}
+
+const disableExternalNavigation = (e, window) => {
+ let target = e.target
+
+ while (target != null) {
+ if (target.matches('a')) {
+ if (
+ target.href &&
+ ['http://', 'https://', 'mailto:', 'tel:'].some((v) => target.href.startsWith(v)) &&
+ !target.classList.contains('router-link-active') &&
+ !target.href.startsWith('http://localhost') &&
+ !target.href.startsWith('https://tauri.localhost')
+ ) {
+ openExternal(window, target.href)
+ }
+ e.preventDefault()
+ break
+ }
+ target = target.parentElement
+ }
+}
+
+export const useDisableClicks = (document, window) => {
+ onMounted(() => {
+ document
+ .querySelector('body')
+ .addEventListener('click', (e) => disableExternalNavigation(e, window))
+
+ document.querySelector('body').addEventListener('auxclick', disableMiddleClick)
+ })
+}
diff --git a/theseus_gui/src/helpers/external.js b/theseus_gui/src/helpers/external.js
new file mode 100644
index 000000000..9acf01352
--- /dev/null
+++ b/theseus_gui/src/helpers/external.js
@@ -0,0 +1,9 @@
+export const openExternal = (window, url) => {
+ window.__TAURI_INVOKE__('tauri', {
+ __tauriModule: 'Shell',
+ message: {
+ cmd: 'open',
+ path: url,
+ },
+ })
+}
diff --git a/theseus_gui/src/pages/project/Index.vue b/theseus_gui/src/pages/project/Index.vue
index 3c8c4fa19..0f6d26168 100644
--- a/theseus_gui/src/pages/project/Index.vue
+++ b/theseus_gui/src/pages/project/Index.vue
@@ -325,7 +325,9 @@ async function fetchProjectData() {
installed.value =
instance.value?.path &&
(await check_installed(instance.value.path, data.value.id).catch(handleError))
+
breadcrumbs.setName('Project', data.value.title)
+
installedVersion.value = instance.value
? Object.values(instance.value.projects).find(
(p) => p?.metadata?.version?.project_id === data.value.id