mirror of https://github.com/Budibase/budibase.git
13 changed files with 391 additions and 326 deletions
@ -0,0 +1,34 @@ |
|||||
|
<script> |
||||
|
import NavigationPanel from "components/design/navigation/NavigationPanel.svelte" |
||||
|
import { Banner, Layout } from "@budibase/bbui" |
||||
|
import NavItem from "components/common/NavItem.svelte" |
||||
|
import { store } from "builderStore" |
||||
|
import LayoutDropdownMenu from "./LayoutDropdownMenu.svelte" |
||||
|
</script> |
||||
|
|
||||
|
<NavigationPanel title="Layouts"> |
||||
|
<Layout paddingX="L" paddingY="XL" gap="S"> |
||||
|
<Banner |
||||
|
type="warning" |
||||
|
showCloseButton={false} |
||||
|
extraButtonText="View details" |
||||
|
extraButtonAction={() => {}} |
||||
|
> |
||||
|
Custom layouts are being deprecated. They will be removed from June 1st. |
||||
|
</Banner> |
||||
|
</Layout> |
||||
|
{#each $store.layouts as layout (layout._id)} |
||||
|
<NavItem |
||||
|
icon="Experience" |
||||
|
indentLevel={0} |
||||
|
selected={$store.selectedLayoutId === layout._id} |
||||
|
text={layout.name} |
||||
|
on:click={() => ($store.selectedLayoutId = layout._id)} |
||||
|
> |
||||
|
<LayoutDropdownMenu {layout} /> |
||||
|
</NavItem> |
||||
|
{/each} |
||||
|
</NavigationPanel> |
||||
|
|
||||
|
<!-- --> |
||||
|
<!-- color={RoleUtils.getRoleColour(screen.routing.roleId)}--> |
||||
@ -0,0 +1,5 @@ |
|||||
|
<script> |
||||
|
import SettingsPanel from "components/design/settings/SettingsPanel.svelte" |
||||
|
</script> |
||||
|
|
||||
|
< |
||||
@ -0,0 +1,20 @@ |
|||||
|
<script> |
||||
|
import { syncURLToState } from "helpers/urlStateSync" |
||||
|
import { store } from "builderStore" |
||||
|
import * as routify from "@roxi/routify" |
||||
|
import { onDestroy } from "svelte" |
||||
|
|
||||
|
// Keep URL and state in sync for selected component ID |
||||
|
const stopSyncing = syncURLToState({ |
||||
|
urlParam: "layoutId", |
||||
|
stateKey: "selectedLayoutId", |
||||
|
validate: id => $store.layouts?.some(layout => layout._id === id), |
||||
|
fallbackUrl: "../", |
||||
|
store, |
||||
|
routify, |
||||
|
}) |
||||
|
|
||||
|
onDestroy(stopSyncing) |
||||
|
</script> |
||||
|
|
||||
|
<slot /> |
||||
@ -0,0 +1,5 @@ |
|||||
|
<script> |
||||
|
import LayoutNavigationPanel from "./_components/LayoutNavigationPanel.svelte" |
||||
|
</script> |
||||
|
|
||||
|
<LayoutNavigationPanel /> |
||||
@ -1,5 +1,13 @@ |
|||||
<script> |
<script> |
||||
import NavigationPanel from "components/design/navigation/NavigationPanel.svelte" |
import { store } from "builderStore" |
||||
|
import { onMount } from "svelte" |
||||
|
import { redirect } from "@roxi/routify" |
||||
|
|
||||
|
onMount(() => { |
||||
|
if ($store.layouts?.length) { |
||||
|
$redirect(`./${$store.layouts[0]._id}`) |
||||
|
} |
||||
|
}) |
||||
</script> |
</script> |
||||
|
|
||||
<NavigationPanel title="Layouts" /> |
You don't have any layouts |
||||
|
|||||
@ -0,0 +1,118 @@ |
|||||
|
<script> |
||||
|
import NavigationPanel from "components/design/navigation/NavigationPanel.svelte" |
||||
|
import { |
||||
|
Body, |
||||
|
Layout, |
||||
|
Label, |
||||
|
ActionGroup, |
||||
|
ActionButton, |
||||
|
Checkbox, |
||||
|
Select, |
||||
|
ColorPicker, |
||||
|
Input, |
||||
|
notifications, |
||||
|
} from "@budibase/bbui" |
||||
|
import NavigationLinksEditor from "./NavigationLinksEditor.svelte" |
||||
|
import { store } from "builderStore" |
||||
|
import { DefaultAppTheme } from "constants" |
||||
|
|
||||
|
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> |
||||
|
|
||||
|
<NavigationPanel title="Navigation"> |
||||
|
<Layout paddingX="L" paddingY="XL" gap="S"> |
||||
|
<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> |
||||
|
<NavigationLinksEditor /> |
||||
|
<Layout noPadding gap="XS"> |
||||
|
<Label>Position</Label> |
||||
|
<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> |
||||
|
</Layout> |
||||
|
{#if $store.navigation.navigation === "Top"} |
||||
|
<Checkbox |
||||
|
text="Sticky header" |
||||
|
value={$store.navigation.sticky} |
||||
|
on:change={e => update("sticky", e.detail)} |
||||
|
/> |
||||
|
<Select |
||||
|
label="Width" |
||||
|
options={["Max", "Large", "Medium", "Small"]} |
||||
|
plaveholder={null} |
||||
|
value={$store.navigation.navWidth} |
||||
|
on:change={e => update("navWidth", e.detail)} |
||||
|
/> |
||||
|
{/if} |
||||
|
<Layout noPadding gap="XS"> |
||||
|
<Checkbox |
||||
|
text="Logo" |
||||
|
value={!$store.navigation.hideLogo} |
||||
|
on:change={e => update("hideLogo", !e.detail)} |
||||
|
/> |
||||
|
{#if !$store.navigation.hideLogo} |
||||
|
<Input |
||||
|
value={$store.navigation.logoUrl} |
||||
|
on:change={e => update("logoUrl", e.detail)} |
||||
|
placeholder="Add logo URL" |
||||
|
updateOnChange={false} |
||||
|
/> |
||||
|
{/if} |
||||
|
</Layout> |
||||
|
<Layout noPadding gap="XS"> |
||||
|
<Checkbox |
||||
|
text="Title" |
||||
|
value={!$store.navigation.hideTitle} |
||||
|
on:change={e => update("hideTitle", !e.detail)} |
||||
|
/> |
||||
|
{#if !$store.navigation.hideTitle} |
||||
|
<Input |
||||
|
value={$store.navigation.title} |
||||
|
on:change={e => update("title", e.detail)} |
||||
|
placeholder="Add title" |
||||
|
updateOnChange={false} |
||||
|
/> |
||||
|
{/if} |
||||
|
</Layout> |
||||
|
<Layout noPadding gap="XS"> |
||||
|
<Label>Background color</Label> |
||||
|
<ColorPicker |
||||
|
spectrumTheme={$store.theme} |
||||
|
value={$store.navigation.navBackground || DefaultAppTheme.navBackground} |
||||
|
on:change={e => update("navBackground", e.detail)} |
||||
|
/> |
||||
|
</Layout> |
||||
|
<Layout noPadding gap="XS"> |
||||
|
<Label>Text color</Label> |
||||
|
<ColorPicker |
||||
|
spectrumTheme={$store.theme} |
||||
|
value={$store.navigation.navTextColor || DefaultAppTheme.navTextColor} |
||||
|
on:change={e => update("navTextColor", e.detail)} |
||||
|
/> |
||||
|
</Layout> |
||||
|
</Layout> |
||||
|
</NavigationPanel> |
||||
@ -1,118 +1,5 @@ |
|||||
<script> |
<script> |
||||
import NavigationPanel from "components/design/navigation/NavigationPanel.svelte" |
import NavigationSettingsPanel from "./_components/NavigationSettingsPanel.svelte" |
||||
import { |
|
||||
Body, |
|
||||
Layout, |
|
||||
Label, |
|
||||
ActionGroup, |
|
||||
ActionButton, |
|
||||
Checkbox, |
|
||||
Select, |
|
||||
ColorPicker, |
|
||||
Input, |
|
||||
notifications, |
|
||||
} from "@budibase/bbui" |
|
||||
import NavigationLinksEditor from "./_components/NavigationLinksEditor.svelte" |
|
||||
import { store } from "builderStore" |
|
||||
import { DefaultAppTheme } from "constants" |
|
||||
|
|
||||
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> |
</script> |
||||
|
|
||||
<NavigationPanel title="Navigation"> |
<NavigationSettingsPanel /> |
||||
<Layout paddingX="L" paddingY="XL" gap="S"> |
|
||||
<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> |
|
||||
<NavigationLinksEditor /> |
|
||||
<Layout noPadding gap="XS"> |
|
||||
<Label>Position</Label> |
|
||||
<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> |
|
||||
</Layout> |
|
||||
{#if $store.navigation.navigation === "Top"} |
|
||||
<Checkbox |
|
||||
text="Sticky header" |
|
||||
value={$store.navigation.sticky} |
|
||||
on:change={e => update("sticky", e.detail)} |
|
||||
/> |
|
||||
<Select |
|
||||
label="Width" |
|
||||
options={["Max", "Large", "Medium", "Small"]} |
|
||||
plaveholder={null} |
|
||||
value={$store.navigation.navWidth} |
|
||||
on:change={e => update("navWidth", e.detail)} |
|
||||
/> |
|
||||
{/if} |
|
||||
<Layout noPadding gap="XS"> |
|
||||
<Checkbox |
|
||||
text="Logo" |
|
||||
value={!$store.navigation.hideLogo} |
|
||||
on:change={e => update("hideLogo", !e.detail)} |
|
||||
/> |
|
||||
{#if !$store.navigation.hideLogo} |
|
||||
<Input |
|
||||
value={$store.navigation.logoUrl} |
|
||||
on:change={e => update("logoUrl", e.detail)} |
|
||||
placeholder="Add logo URL" |
|
||||
updateOnChange={false} |
|
||||
/> |
|
||||
{/if} |
|
||||
</Layout> |
|
||||
<Layout noPadding gap="XS"> |
|
||||
<Checkbox |
|
||||
text="Title" |
|
||||
value={!$store.navigation.hideTitle} |
|
||||
on:change={e => update("hideTitle", !e.detail)} |
|
||||
/> |
|
||||
{#if !$store.navigation.hideTitle} |
|
||||
<Input |
|
||||
value={$store.navigation.title} |
|
||||
on:change={e => update("title", e.detail)} |
|
||||
placeholder="Add title" |
|
||||
updateOnChange={false} |
|
||||
/> |
|
||||
{/if} |
|
||||
</Layout> |
|
||||
<Layout noPadding gap="XS"> |
|
||||
<Label>Background color</Label> |
|
||||
<ColorPicker |
|
||||
spectrumTheme={$store.theme} |
|
||||
value={$store.navigation.navBackground || DefaultAppTheme.navBackground} |
|
||||
on:change={e => update("navBackground", e.detail)} |
|
||||
/> |
|
||||
</Layout> |
|
||||
<Layout noPadding gap="XS"> |
|
||||
<Label>Text color</Label> |
|
||||
<ColorPicker |
|
||||
spectrumTheme={$store.theme} |
|
||||
value={$store.navigation.navTextColor || DefaultAppTheme.navTextColor} |
|
||||
on:change={e => update("navTextColor", e.detail)} |
|
||||
/> |
|
||||
</Layout> |
|
||||
</Layout> |
|
||||
</NavigationPanel> |
|
||||
|
|||||
@ -0,0 +1,120 @@ |
|||||
|
<script> |
||||
|
import NavigationPanel from "components/design/navigation/NavigationPanel.svelte" |
||||
|
import { |
||||
|
Body, |
||||
|
Layout, |
||||
|
Label, |
||||
|
ColorPicker, |
||||
|
Button, |
||||
|
notifications, |
||||
|
} from "@budibase/bbui" |
||||
|
import { store } from "builderStore" |
||||
|
import { get } from "svelte/store" |
||||
|
import { DefaultAppTheme } from "constants" |
||||
|
import AppThemeSelect from "./AppThemeSelect.svelte" |
||||
|
|
||||
|
const ButtonBorderRadiusOptions = [ |
||||
|
{ |
||||
|
label: "Square", |
||||
|
value: "0", |
||||
|
}, |
||||
|
{ |
||||
|
label: "Soft edge", |
||||
|
value: "4px", |
||||
|
}, |
||||
|
{ |
||||
|
label: "Curved", |
||||
|
value: "8px", |
||||
|
}, |
||||
|
{ |
||||
|
label: "Round", |
||||
|
value: "16px", |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
$: customTheme = $store.customTheme || {} |
||||
|
|
||||
|
const update = async (property, value) => { |
||||
|
try { |
||||
|
store.actions.customTheme.save({ |
||||
|
...get(store).customTheme, |
||||
|
[property]: value, |
||||
|
}) |
||||
|
} catch (error) { |
||||
|
notifications.error("Error updating custom theme") |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<NavigationPanel title="Theme"> |
||||
|
<Layout paddingX="L" paddingY="XL" gap="S"> |
||||
|
<Body size="S"> |
||||
|
Your theme is set across all the screens within your app |
||||
|
</Body> |
||||
|
<Layout noPadding gap="XS"> |
||||
|
<Label>Theme</Label> |
||||
|
<AppThemeSelect /> |
||||
|
</Layout> |
||||
|
<Layout noPadding gap="XS"> |
||||
|
<Label>Buttons</Label> |
||||
|
<div class="buttons"> |
||||
|
{#each ButtonBorderRadiusOptions as option} |
||||
|
<div |
||||
|
class:active={customTheme.buttonBorderRadius === option.value} |
||||
|
style={`--radius: ${option.value}`} |
||||
|
> |
||||
|
<Button |
||||
|
secondary |
||||
|
on:click={() => update("buttonBorderRadius", option.value)} |
||||
|
> |
||||
|
{option.label} |
||||
|
</Button> |
||||
|
</div> |
||||
|
{/each} |
||||
|
</div> |
||||
|
</Layout> |
||||
|
<Layout noPadding gap="XS"> |
||||
|
<Label>Accent color</Label> |
||||
|
<ColorPicker |
||||
|
spectrumTheme={$store.theme} |
||||
|
value={customTheme.primaryColor || DefaultAppTheme.primaryColor} |
||||
|
on:change={e => update("primaryColor", e.detail)} |
||||
|
/> |
||||
|
</Layout> |
||||
|
<Layout noPadding gap="XS"> |
||||
|
<Label>Accent color (hover)</Label> |
||||
|
<ColorPicker |
||||
|
spectrumTheme={$store.theme} |
||||
|
value={customTheme.primaryColorHover || |
||||
|
DefaultAppTheme.primaryColorHover} |
||||
|
on:change={e => update("primaryColorHover", e.detail)} |
||||
|
/> |
||||
|
</Layout> |
||||
|
</Layout> |
||||
|
</NavigationPanel> |
||||
|
|
||||
|
<style> |
||||
|
.buttons { |
||||
|
display: grid; |
||||
|
grid-template-columns: 100px 100px; |
||||
|
gap: var(--spacing-m); |
||||
|
} |
||||
|
.buttons > div { |
||||
|
display: contents; |
||||
|
} |
||||
|
.buttons > div :global(.spectrum-Button) { |
||||
|
border-radius: var(--radius) !important; |
||||
|
border-width: 1px; |
||||
|
border-color: var(--spectrum-global-color-gray-400); |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
.buttons > div:hover :global(.spectrum-Button) { |
||||
|
background: var(--spectrum-global-color-gray-700); |
||||
|
border-color: var(--spectrum-global-color-gray-700); |
||||
|
} |
||||
|
.buttons > div.active :global(.spectrum-Button) { |
||||
|
background: var(--spectrum-global-color-gray-200); |
||||
|
color: var(--spectrum-global-color-gray-800); |
||||
|
border-color: var(--spectrum-global-color-gray-600); |
||||
|
} |
||||
|
</style> |
||||
@ -1,120 +1,5 @@ |
|||||
<script> |
<script> |
||||
import NavigationPanel from "components/design/navigation/NavigationPanel.svelte" |
import ThemeSettingsPanel from "./_components/ThemeSettingsPanel.svelte" |
||||
import { |
|
||||
Body, |
|
||||
Layout, |
|
||||
Label, |
|
||||
ColorPicker, |
|
||||
Button, |
|
||||
notifications, |
|
||||
} from "@budibase/bbui" |
|
||||
import { store } from "builderStore" |
|
||||
import { get } from "svelte/store" |
|
||||
import { DefaultAppTheme } from "constants" |
|
||||
import AppThemeSelect from "./_components/AppThemeSelect.svelte" |
|
||||
|
|
||||
const ButtonBorderRadiusOptions = [ |
|
||||
{ |
|
||||
label: "Square", |
|
||||
value: "0", |
|
||||
}, |
|
||||
{ |
|
||||
label: "Soft edge", |
|
||||
value: "4px", |
|
||||
}, |
|
||||
{ |
|
||||
label: "Curved", |
|
||||
value: "8px", |
|
||||
}, |
|
||||
{ |
|
||||
label: "Round", |
|
||||
value: "16px", |
|
||||
}, |
|
||||
] |
|
||||
|
|
||||
$: customTheme = $store.customTheme || {} |
|
||||
|
|
||||
const update = async (property, value) => { |
|
||||
try { |
|
||||
store.actions.customTheme.save({ |
|
||||
...get(store).customTheme, |
|
||||
[property]: value, |
|
||||
}) |
|
||||
} catch (error) { |
|
||||
notifications.error("Error updating custom theme") |
|
||||
} |
|
||||
} |
|
||||
</script> |
</script> |
||||
|
|
||||
<NavigationPanel title="Theme"> |
<ThemeSettingsPanel /> |
||||
<Layout paddingX="L" paddingY="XL" gap="S"> |
|
||||
<Body size="S"> |
|
||||
Your theme is set across all the screens within your app |
|
||||
</Body> |
|
||||
<Layout noPadding gap="XS"> |
|
||||
<Label>Theme</Label> |
|
||||
<AppThemeSelect /> |
|
||||
</Layout> |
|
||||
<Layout noPadding gap="XS"> |
|
||||
<Label>Buttons</Label> |
|
||||
<div class="buttons"> |
|
||||
{#each ButtonBorderRadiusOptions as option} |
|
||||
<div |
|
||||
class:active={customTheme.buttonBorderRadius === option.value} |
|
||||
style={`--radius: ${option.value}`} |
|
||||
> |
|
||||
<Button |
|
||||
secondary |
|
||||
on:click={() => update("buttonBorderRadius", option.value)} |
|
||||
> |
|
||||
{option.label} |
|
||||
</Button> |
|
||||
</div> |
|
||||
{/each} |
|
||||
</div> |
|
||||
</Layout> |
|
||||
<Layout noPadding gap="XS"> |
|
||||
<Label>Accent color</Label> |
|
||||
<ColorPicker |
|
||||
spectrumTheme={$store.theme} |
|
||||
value={customTheme.primaryColor || DefaultAppTheme.primaryColor} |
|
||||
on:change={e => update("primaryColor", e.detail)} |
|
||||
/> |
|
||||
</Layout> |
|
||||
<Layout noPadding gap="XS"> |
|
||||
<Label>Accent color (hover)</Label> |
|
||||
<ColorPicker |
|
||||
spectrumTheme={$store.theme} |
|
||||
value={customTheme.primaryColorHover || |
|
||||
DefaultAppTheme.primaryColorHover} |
|
||||
on:change={e => update("primaryColorHover", e.detail)} |
|
||||
/> |
|
||||
</Layout> |
|
||||
</Layout> |
|
||||
</NavigationPanel> |
|
||||
|
|
||||
<style> |
|
||||
.buttons { |
|
||||
display: grid; |
|
||||
grid-template-columns: 100px 100px; |
|
||||
gap: var(--spacing-m); |
|
||||
} |
|
||||
.buttons > div { |
|
||||
display: contents; |
|
||||
} |
|
||||
.buttons > div :global(.spectrum-Button) { |
|
||||
border-radius: var(--radius) !important; |
|
||||
border-width: 1px; |
|
||||
border-color: var(--spectrum-global-color-gray-400); |
|
||||
font-weight: 600; |
|
||||
} |
|
||||
.buttons > div:hover :global(.spectrum-Button) { |
|
||||
background: var(--spectrum-global-color-gray-700); |
|
||||
border-color: var(--spectrum-global-color-gray-700); |
|
||||
} |
|
||||
.buttons > div.active :global(.spectrum-Button) { |
|
||||
background: var(--spectrum-global-color-gray-200); |
|
||||
color: var(--spectrum-global-color-gray-800); |
|
||||
border-color: var(--spectrum-global-color-gray-600); |
|
||||
} |
|
||||
</style> |
|
||||
|
|||||
Loading…
Reference in new issue