diff --git a/.DS_Store b/.DS_Store
deleted file mode 100644
index b16eb9ec68..0000000000
Binary files a/.DS_Store and /dev/null differ
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000000..d1ba2bc046
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,32 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: bug
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. iOS]
+ - Browser [e.g. chrome, safari]
+ - Version [e.g. 22]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/packages/builder/package.json b/packages/builder/package.json
index 3aae8af2d6..78e539bf60 100644
--- a/packages/builder/package.json
+++ b/packages/builder/package.json
@@ -63,7 +63,7 @@
}
},
"dependencies": {
- "@budibase/bbui": "^1.47.0",
+ "@budibase/bbui": "^1.50.1",
"@budibase/client": "^0.3.1",
"@budibase/colorpicker": "^1.0.1",
"@budibase/svelte-ag-grid": "^0.0.16",
diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js
index 101f875e96..6317640955 100644
--- a/packages/builder/src/builderStore/index.js
+++ b/packages/builder/src/builderStore/index.js
@@ -1,11 +1,13 @@
import { getStore } from "./store"
import { getBackendUiStore } from "./store/backend"
import { getAutomationStore } from "./store/automation/"
+import { getThemeStore } from "./store/theme"
import analytics from "analytics"
export const store = getStore()
export const backendUiStore = getBackendUiStore()
export const automationStore = getAutomationStore()
+export const themeStore = getThemeStore()
export const initialise = async () => {
try {
diff --git a/packages/builder/src/builderStore/store/localStorage.js b/packages/builder/src/builderStore/store/localStorage.js
new file mode 100644
index 0000000000..aaf10460b6
--- /dev/null
+++ b/packages/builder/src/builderStore/store/localStorage.js
@@ -0,0 +1,43 @@
+import { get, writable } from "svelte/store"
+
+export const localStorageStore = (localStorageKey, initialValue) => {
+ const store = writable(initialValue, () => {
+ // Hydrate from local storage when we get a new subscriber
+ hydrate()
+
+ // Listen for local storage changes and keep store in sync
+ const storageListener = ({ key }) => key === localStorageKey && hydrate()
+ window.addEventListener("storage", storageListener)
+ return () => window.removeEventListener("storage", storageListener)
+ })
+
+ // New store setter which updates the store and localstorage
+ const set = value => {
+ store.set(value)
+ localStorage.setItem(localStorageKey, JSON.stringify(value))
+ }
+
+ // New store updater which updates the store and localstorage
+ const update = updaterFn => set(updaterFn(get(store)))
+
+ // Hydrates the store from localstorage
+ const hydrate = () => {
+ const localValue = localStorage.getItem(localStorageKey)
+ if (localValue == null) {
+ set(initialValue)
+ } else {
+ try {
+ store.set(JSON.parse(localValue))
+ } catch {
+ set(initialValue)
+ }
+ }
+ }
+
+ // Patch the default svelte store functions with our overrides
+ return {
+ ...store,
+ set,
+ update,
+ }
+}
diff --git a/packages/builder/src/builderStore/store/theme.js b/packages/builder/src/builderStore/store/theme.js
new file mode 100644
index 0000000000..df94a4c3d5
--- /dev/null
+++ b/packages/builder/src/builderStore/store/theme.js
@@ -0,0 +1,38 @@
+import { localStorageStore } from "./localStorage"
+
+export const getThemeStore = () => {
+ const themeElement = document.documentElement
+ const initialValue = {
+ darkMode: false,
+ hue: 208,
+ saturation: 9,
+ lightness: 16,
+ }
+
+ const store = localStorageStore("bb-theme", initialValue)
+
+ // Sets a CSS variable on the root document element
+ function setCSSVariable(prop, value) {
+ themeElement.style.setProperty(prop, value)
+ }
+
+ // Resets the custom theme to the default dark theme.
+ // The reset option is only available when dark theme is on, which is why it
+ // sets dark mode to true here
+ store.reset = () => {
+ store.set({
+ ...initialValue,
+ darkMode: true,
+ })
+ }
+
+ // Update theme when store changes
+ store.subscribe(theme => {
+ themeElement.classList[theme.darkMode ? "add" : "remove"]("dark")
+ setCSSVariable("--theme-hue", Math.round(theme.hue))
+ setCSSVariable("--theme-saturation", `${Math.round(theme.saturation)}%`)
+ setCSSVariable("--theme-brightness", `${Math.round(theme.lightness)}%`)
+ })
+
+ return store
+}
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/Arrow.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/Arrow.svelte
index 4dab01d6f1..0e0c6bb83a 100644
--- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/Arrow.svelte
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/Arrow.svelte
@@ -4,8 +4,10 @@
viewBox="0 0 9 75"
fill="none"
xmlns="http://www.w3.org/2000/svg">
-