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"