New Nav component (#11266)

This commit is contained in:
Gerard Burns 2023-08-15 09:59:20 +01:00 committed by Gerard Burns
parent d32e9d58a0
commit e3cfdd537a
7 changed files with 351 additions and 34 deletions

View File

@ -0,0 +1,21 @@
<script>
import { getContext } from "svelte"
export let title
const createPaneStore = getContext("createPaneStore")
$: paneStore = createPaneStore(title)
</script>
{#if $paneStore}
<div class="pane">
<slot />
</div>
{/if}
<style>
.pane {
padding: 13px;
}
</style>

View File

@ -0,0 +1,112 @@
<script>
import { setContext } from "svelte"
import { writable, get } from "svelte/store"
import { Icon, Body, Button } from "@budibase/bbui"
export let icon
export let title
let panes = {}
let selectedPaneIdStore = writable(null)
const createPaneStore = pane => {
const id = crypto.randomUUID()
return {
subscribe: callback => {
panes[id] = pane
if (get(selectedPaneIdStore) === null) {
selectedPaneIdStore.set(id)
}
const unsubscribeSelectedPaneIdStore = selectedPaneIdStore.subscribe(
selectedPaneId => callback(selectedPaneId === id)
)
return () => {
delete panes[id]
panes = panes
unsubscribeSelectedPaneIdStore()
if (get(selectedPaneIdStore) === id) {
const ids = Object.keys(panes)
if (ids.length > 0) {
selectedPaneIdStore.set(ids[0])
} else {
selectedPaneIdStore.set(null)
}
}
}
},
}
}
setContext("createPaneStore", createPaneStore)
</script>
<div class="panel">
<div class="header">
<div class="icon">
<Icon name={icon} />
</div>
<Body>{title}</Body>
</div>
<div class="controls">
{#each Object.entries(panes) as [id, pane]}
<div class="button" class:active={$selectedPaneIdStore === id}>
<Button on:click={() => selectedPaneIdStore.set(id)}>{pane}</Button>
</div>
{/each}
</div>
<div class="divider" />
<slot />
</div>
<style>
.panel {
width: 310px;
background: var(--background);
}
.header {
display: flex;
padding: 16px 14px;
align-items: center;
}
.icon {
color: var(--grey-6);
margin-right: 8px;
}
.controls {
padding: 0 14px 16px;
display: flex;
}
.button:first-child {
margin-right: 8px;
}
.button :global(button) {
border-radius: 4px;
border: none;
background-color: var(--grey-1);
color: var(--ink);
}
.button :global(button):hover {
background-color: var(--grey-2);
}
.button.active :global(button) {
background-color: var(--grey-2);
}
.divider {
border-top: 1px solid var(--grey-3);
}
</style>

View File

@ -1,33 +0,0 @@
<script>
import Panel from "components/design/Panel.svelte"
import { Body, Layout, Banner } from "@budibase/bbui"
import { selectedScreen, store } from "builderStore"
import { get } from "svelte/store"
const removeCustomLayout = async () => {
return store.actions.screens.removeCustomLayout(get(selectedScreen))
}
</script>
<Panel borderLeft title="Navigation" icon="InfoOutline" wide>
<Layout paddingX="L" paddingY="XL" gap="S">
{#if $selectedScreen.layoutId}
<Banner
type="warning"
extraButtonText="Detach custom layout"
extraButtonAction={removeCustomLayout}
showCloseButton={false}
>
You can't preview your navigation settings using this screen as it uses
a custom layout, which is deprecated
</Banner>
{/if}
<Body size="S">
Your navigation is configured for all the screens within your app.
</Body>
<Body size="S">
You can hide and show your navigation for each screen in the screen
settings.
</Body>
</Layout>
</Panel>

View File

@ -0,0 +1,176 @@
<script>
import Pane from "components/design/Pane.svelte"
import {
ColorPicker,
Input,
Label,
ActionGroup,
ActionButton,
Checkbox,
notifications,
Icon,
Body,
Button,
Select,
} from "@budibase/bbui"
import { DefaultAppTheme } from "constants"
import { store } from "builderStore"
const update = async (key, value) => {
try {
let navigation = $store.navigation
navigation[key] = value
await store.actions.navigation.save(navigation)
} catch (error) {
notifications.error("Error updating navigation settings")
}
}
</script>
<Pane title="Customize">
<div class="info">
<div class="infoHeader">
<Icon name="InfoOutline" />
<Body size="S">CHANGES WILL APPLY TO ALL SCREENS</Body>
</div>
<Body>
Your navigation is configured for all the screens within your app.
</Body>
</div>
<div class="configureLinks">
<Button cta>Configure Links</Button>
</div>
<div class="controls">
<div class="label">
<Label size="M">Position</Label>
</div>
<ActionGroup quiet>
<ActionButton
selected={$store.navigation.navigation === "Top"}
quiet={$store.navigation.navigation !== "Top"}
icon="PaddingTop"
on:click={() => update("navigation", "Top")}
/>
<ActionButton
selected={$store.navigation.navigation === "Left"}
quiet={$store.navigation.navigation !== "Left"}
icon="PaddingLeft"
on:click={() => update("navigation", "Left")}
/>
</ActionGroup>
{#if $store.navigation.navigation === "Top"}
<div class="label">
<Label size="M">Sticky header</Label>
</div>
<Checkbox
value={$store.navigation.sticky}
on:change={e => update("sticky", e.detail)}
/>
<div class="label">
<Label size="M">Width</Label>
</div>
<Select
options={["Max", "Large", "Medium", "Small"]}
plaveholder={null}
value={$store.navigation.navWidth}
on:change={e => update("navWidth", e.detail)}
/>
{/if}
<div class="label">
<Label size="M">Show logo</Label>
</div>
<Checkbox
value={!$store.navigation.hideLogo}
on:change={e => update("hideLogo", !e.detail)}
/>
{#if !$store.navigation.hideLogo}
<div class="label">
<Label size="M">Logo URL</Label>
</div>
<Input
value={$store.navigation.logoUrl}
on:change={e => update("logoUrl", e.detail)}
updateOnChange={false}
/>
{/if}
<div class="label">
<Label size="M">Show title</Label>
</div>
<Checkbox
value={!$store.navigation.hideTitle}
on:change={e => update("hideTitle", !e.detail)}
/>
{#if !$store.navigation.hideTitle}
<div class="label">
<Label size="M">Title</Label>
</div>
<Input
value={$store.navigation.title}
on:change={e => update("title", e.detail)}
updateOnChange={false}
/>
{/if}
<div class="label">
<Label>Background</Label>
</div>
<ColorPicker
spectrumTheme={$store.theme}
value={$store.navigation.navBackground || DefaultAppTheme.navBackground}
on:change={e => update("navBackground", e.detail)}
/>
<div class="label">
<Label>Text</Label>
</div>
<ColorPicker
spectrumTheme={$store.theme}
value={$store.navigation.navTextColor || DefaultAppTheme.navTextColor}
on:change={e => update("navTextColor", e.detail)}
/>
</div>
</Pane>
<style>
.controls {
position: relative;
display: grid;
grid-template-columns: 90px 1fr;
align-items: start;
transition: background 130ms ease-out, border-color 130ms ease-out;
border-left: 4px solid transparent;
margin: 0 calc(-1 * var(--spacing-xl));
padding: 0 var(--spacing-xl) 0 calc(var(--spacing-xl) - 4px);
gap: 12px;
}
.label {
margin-top: 16px;
transform: translateY(-50%);
}
.info {
background-color: var(--background-alt);
padding: 12px;
margin-bottom: 12px;
}
.infoHeader {
display: flex;
margin-bottom: 5px;
border-radius: 4px;
}
.infoHeader :global(svg) {
margin-right: 5px;
color: var(--grey-6);
}
.infoHeader :global(p) {
color: var(--grey-6);
}
.configureLinks :global(button) {
margin-bottom: 20px;
width: 100%;
}
</style>

View File

@ -0,0 +1,31 @@
<script>
import Pane from "components/design/Pane.svelte"
import { get } from "svelte/store"
import { Toggle, Body } from "@budibase/bbui"
import { selectedScreen, store } from "builderStore"
const updateShowNavigation = async e => {
await store.actions.screens.updateSetting(
get(selectedScreen),
"showNavigation",
e.detail
)
}
</script>
<Pane title="Settings">
<div class="toggle">
<Toggle
on:change={updateShowNavigation}
value={$selectedScreen.showNavigation}
/>
<Body size="S">Show nav on this screen</Body>
</div>
</Pane>
<style>
.toggle {
display: flex;
align-items: center;
}
</style>

View File

@ -0,0 +1,10 @@
<script>
import RightPanel from "components/design/RightPanel.svelte"
import CustomizePane from "./CustomizePane.svelte"
import SettingsPane from "./SettingsPane.svelte"
</script>
<RightPanel title="Screen" icon="WebPage">
<SettingsPane />
<CustomizePane />
</RightPanel>

View File

@ -1,6 +1,6 @@
<script> <script>
import NavigationSettingsPanel from "./_components/NavigationSettingsPanel.svelte" import NavigationSettingsPanel from "./_components/NavigationSettingsPanel.svelte"
import NavigationInfoPanel from "./_components/NavigationInfoPanel.svelte" import NavigationInfoPanel from "./_components/NavigationInfoPanel/index.svelte"
</script> </script>
<NavigationSettingsPanel /> <NavigationSettingsPanel />