@setoelkahfi / svara / commits / 3e224d7

added tab list

mellbacon committed Apr 29, 2023 at 18:34 UTC 3e224d7b493dd165b4b85e1378c702131fd257f4
7 files changed +223 -4
package.json
+1
@@ -14,6 +14,7 @@
14 "dependencies": {
15 "@tauri-apps/api": "^1.2.0",
16 "sass": "^1.62.0",
17 + "sortablejs": "^1.15.0",
18 "svelte-splitpanes": "^0.7.13"
19 },
20 "devDependencies": {
src/config/themes/dark-theme.json
+9 -1
@@ -33,7 +33,15 @@
33 "foreground": "#ffffff"
34 },
35 "editor": {
36 - "tabContainerBackground": "#2D2D2D"
36 + "tabContainerBackground": "#2D2D2D",
37 + "tabBackground": "#1c1c1c",
38 + "tabForeground": "#ffffff",
39 + "tabBorderColor": "#414040",
40 + "tabActiveBorderColor": "#171717",
41 + "tabActiveBackground": "#171717",
42 + "tabActiveForeground": "#ffffff",
43 + "tabHoverBackground": "2b2b2b",
44 + "tabHoverForeground": "#ffffff"
45 }
46 }
47 }
src/lib/EditorTabList.svelte
+25 -3
@@ -1,17 +1,39 @@
1 <script lang="ts">
2 + import { onMount } from "svelte";
3 + import Tab from "./Tab.svelte";
4 + import { tabs, hidden } from "./scripts/Tab";
5 + import Sortable from 'sortablejs';
6 +
7 let tabcontainer = null;
8 +
9 + onMount(() => {
10 + Sortable.create(tabcontainer, {
11 + draggable: ".tab",
12 + animation: 150,
13 + forceFallback: true,
14 + easing: "cubic-bezier(1, 0, 0, 1)",
15 + sort: true
16 + })
17 + })
18 </script>
4 -<div id="editor-tabs">
5 - <div bind:this={tabcontainer} id="editor-tablist"></div>
19 +<div id="editor-tabs" class:hidden={$hidden}>
20 + <div bind:this={tabcontainer} id="editor-tablist">
21 + {#each $tabs as tab}
22 + <Tab id={tab.id} label={tab.label} path={tab.path} active={tab.active} />
23 + {/each}
24 + </div>
25 </div>
26
27 <style lang="scss">
28 + .hidden {
29 + visibility: hidden;
30 + }
31 #editor-tabs {
32 width: -webkit-fill-available;
33 display: flex;
34 justify-content: space-between;
35 position: absolute;
14 - z-index: 2;
36 + left: 0.5px; /*temp fix to show over the sidebar border*/
37 #editor-tablist {
38 position: relative;
39 display: flex;
src/lib/Tab.svelte new
+83
@@ -0,0 +1,83 @@
1 +<script lang="ts">
2 + import { setActive } from "./scripts/Tab";
3 + export let id = 0;
4 + export let label = "Untitled-1";
5 + export let path = "";
6 + export let active = false;
7 + let tab;
8 +</script>
9 +<div bind:this={tab} title={path} id={`editorTab-${id}`} class="tab" class:active={active}>
10 + <!-- svelte-ignore a11y-click-events-have-key-events -->
11 + <div class="tab-content" on:mousedown = {
12 + (e) => {
13 + if (e.button === 0) setActive(id);
14 + }
15 + }>
16 + <span class="tab-label">{label}</span>
17 + </div>
18 + <!-- svelte-ignore a11y-click-events-have-key-events -->
19 + <div class="close-tab">
20 + <span title="Close tab"></span>
21 + </div>
22 +</div>
23 +
24 +<style lang="scss">
25 + .tab {
26 + height: 100%;
27 + min-width: min-content;
28 + flex-grow: 0.05;
29 + display: flex;
30 + overflow: hidden;
31 + justify-content: space-between;
32 + align-items: center;
33 + font-size: 14px;
34 + cursor: pointer;
35 + padding: 0 10px;
36 + }
37 + .tab-content::-webkit-scrollbar {
38 + height: 4px;
39 + }
40 + .tab-content::-webkit-scrollbar {
41 + background-color: #1b5fdd;
42 + }
43 + .tab-content {
44 + display: flex;
45 + justify-content: center;
46 + align-items: center;
47 + overflow-x: overlay;
48 + overflow-y: hidden;
49 + height: 100%;
50 + padding-left: 2px;
51 + :nth-child(2) {
52 + display: block;
53 + width: 6px;
54 + height: 6px;
55 + background-color: white;
56 + border-radius: 50%;
57 + left: -11px;
58 + top: 0.5px;
59 + position: relative;
60 + }
61 + }
62 + .tab-label {
63 + text-overflow: ellipsis;
64 + white-space: nowrap;
65 + padding-right: 20px;
66 + }
67 + .close-tab span::before {
68 + content: "\2715";
69 + font-size: 11px;
70 + display: flex;
71 + }
72 + .close-tab span:hover {
73 + color: gray;
74 + }
75 + .close-tab {
76 + width: 2rem;
77 + margin-left: -1rem;
78 + display: flex;
79 + justify-content: center;
80 + position: relative;
81 + left: 10px;
82 + }
83 +</style>
\ No newline at end of file
src/lib/scripts/Tab.ts new
+74
@@ -0,0 +1,74 @@
1 +import { writable } from "svelte/store";
2 +
3 +export let hidden = writable(true);
4 +export let tablist: Tab[] = [];
5 +export let tabs = writable([]);
6 +
7 +let id = 0;
8 +let activeid = id;
9 +class Tab {
10 + id: number;
11 + label: string;
12 + active: boolean;
13 + path: string;
14 + content;
15 + isfile: boolean;
16 + saved = true;
17 + constructor(id: number, label = "", content = null, path = "") {
18 + this.id = id;
19 + this.label = label === "" ? `Untitled-${id}` : label;
20 + this.path = path === "" ? this.label : path;
21 + this.content = content;
22 + }
23 + updateView(id) {
24 + this.content.$set({ hidden: !(this.id === id) });
25 + }
26 + refreshView(tab) {
27 + if (tab.isfile) {
28 + tab.content.updateTheme();
29 + }
30 + }
31 +}
32 +
33 +export function addTab(path: string = "", label: string = "") {
34 + // dont add tabs that are already open
35 + if (tabOpen(path)) {
36 + return;
37 + }
38 +
39 + let tab = new Tab(id, label, null, path);
40 + tablist = [...tablist, tab];
41 +
42 + refreshTabs();
43 +}
44 +
45 +export function setActive(id: number) {
46 + for (let tab of tablist) {
47 + if (tab.id === id) {
48 + activeid = id;
49 + tab.active = true;
50 + }
51 + else {
52 + tab.active = false;
53 + }
54 + }
55 + tabs.set(tablist);
56 +}
57 +
58 +function refreshTabs() {
59 + if (tablist.length > 0) {
60 + hidden.set(false);
61 + }
62 + tabs.set(tablist);
63 + setActive(id);
64 + id++;
65 +}
66 +function tabOpen(path: string) {
67 + for (const tab of tablist) {
68 + if (tab.path === path) {
69 + setActive(tab.id);
70 + return true;
71 + }
72 + }
73 + return false;
74 +}
\ No newline at end of file
src/theme.scss
+26
@@ -25,6 +25,17 @@ $tab-container-height: 2rem;
25 --sidebar-tabActiveForeground: #ffffff;
26 --sidebar-tabActiveBorder: red;
27
28 + --editor-tabContainerBackground: #2D2D2D;
29 +
30 + --editor-tabBackground: #1c1c1c;
31 + --editor-tabForeground: #ffffff;
32 + --editor-tabBorderColor: #bdd4ff;
33 + --editor-tabActiveBorderColor: #1b5fdd;
34 + --editor-tabActiveBackground: #1c1c1c;
35 + --editor-tabActiveForeground: #ffffff;
36 + --editor-tabHoverBackground: #2b2b2b;
37 + --editor-tabHoverForeground: #ffffff;
38 +
39 --statusbar-background: transparent;
40 --statusbar-foreground: #ffffff;
41 }
@@ -86,6 +97,21 @@ html {
97 background-color: var(--header-background);
98 height: $tab-container-height;
99 box-shadow: inset 0px -1px 0 0 var(--window-borderColor);
100 +
101 + .tab {
102 + background-color: var(--editor-tabBackground);
103 + color: var(--editor-tabForeground);
104 + box-shadow: inset 0px -1px 0 0 var(--editor-tabBorderColor);
105 + &:not(.active):hover {
106 + background-color: var(--editor-tabHoverBackground);
107 + color: var(--editor-tabHoverForeground);
108 + }
109 + &.active {
110 + background-color: var(--editor-tabActiveBackground);
111 + box-shadow: inset 0px -2px 0 0 var(--editor-tabActiveBorderColor) !important;
112 + color: var(--editor-tabActiveForeground);
113 + }
114 + }
115 }
116
117 #statusbar {
yarn.lock
+5
@@ -718,6 +718,11 @@ sorcery@^0.11.0:
718 minimist "^1.2.0"
719 sander "^0.5.0"
720
721 +sortablejs@^1.15.0:
722 + version "1.15.0"
723 + resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.0.tgz#53230b8aa3502bb77a29e2005808ffdb4a5f7e2a"
724 + integrity sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==
725 +
726 "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
727 version "1.0.2"
728 resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"