Skip to content

Commit

Permalink
✨ Customizable UI (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
trickypr authored Nov 20, 2023
1 parent 17133a8 commit 9490da8
Show file tree
Hide file tree
Showing 51 changed files with 1,461 additions and 161 deletions.
1 change: 1 addition & 0 deletions .config/webpack.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const sharedSettings = (contentFiles, dev) => {
extensions: ['.ts', '.mjs', '.js', '.svelte'],
alias: {
'@shared': resolve('src/content/shared'),
'@browser': resolve('src/content/browser'),
},
},

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"@catppuccin/palette": "^0.2.0",
"fnts": "^2.0.1",
"mitt": "^3.0.1",
"nanoid": "^5.0.3",
"remixicon": "^3.5.0",
"snarkdown": "^2.0.0"
},
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 12 additions & 64 deletions src/content/browser/Browser.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,81 +3,29 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<script lang="ts">
import Browser from './components/Browser.svelte'
import BrowserContextMenu from './components/contextMenus/BrowserContextMenu.svelte'
import { customizableUIDynamicPref } from '@shared/customizableUI'
import CustomizableUi from './components/customizableUI/CustomizableUI.svelte'
import { BrowserContextMenu, HamburgerMenu } from './components/menus'
import Keybindings from './components/keybindings/Keybindings.svelte'
import Tab from './components/tabs/Tab.svelte'
import Toolbar from './components/toolbar/Toolbar.svelte'
import { tabs, openTab, selectedTab } from './lib/globalApi'
import { tabs, selectedTab } from './lib/globalApi'
let component = customizableUIDynamicPref('browser.uiCustomization.state')
$: currentTab = $tabs.find((tab) => tab.getId() == $selectedTab)
// We don't care about the order that browers are rendered in the dom, but we
// want to allow tab reordering. This should stop unnessisary updates
$: sortedBrowers = [...$tabs].sort(
(tabA, tabB) => tabA.getId() - tabB.getId(),
)
</script>

<div class="content">
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="tabs" on:drop|preventDefault>
{#each $tabs as tab (tab.getId())}
<Tab {tab} bind:selectedTab={$selectedTab} />
{/each}
<button on:click={() => openTab()} class="tabs__button">
<i class="ri-add-line ri-lg" />
</button>
</div>

{#if currentTab}
<Toolbar tab={currentTab} />
{/if}

<div class="browsers">
{#each sortedBrowers as tab (tab.getId())}
<Browser
{tab}
selectedTab={$selectedTab}
on:constructed={(_) => {
if ($selectedTab == -1) selectedTab.set(tab.getId())
}}
/>
{/each}
</div>
</div>
{#if currentTab}
<CustomizableUi component={$component} root={$component} tab={currentTab} />
{/if}

<BrowserContextMenu />
<HamburgerMenu />
<Keybindings />

<style>
.content {
/* The root component must be specified to be full height */
:global(body > .component) {
height: 100%;
display: flex;
flex-direction: column;
}
.tabs {
display: flex;
gap: 0.25rem;
overflow-x: scroll;
}
.tabs__button {
border: none;
background: none;
margin: 0.25rem 0;
border-radius: 0.5rem;
width: 2.5rem;
height: 2.5rem;
}
.tabs__button:hover {
background: var(--surface);
}
.browsers {
flex-grow: 1;
}
</style>
1 change: 1 addition & 0 deletions src/content/browser/components/Browser.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
height: 100%;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.browser-container[hidden] {
Expand Down
25 changes: 25 additions & 0 deletions src/content/browser/components/customizableUI/Block.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<script lang="ts">
import type {
BlockComponent,
Component,
ComponentId,
} from '@shared/customizableUI'
import type { Tab } from '../tabs/tab'
import UiItemBase from './UIItemBase.svelte'
import CustomizableUi from './CustomizableUI.svelte'
export let component: ComponentId & BlockComponent
export let root: Component
export let tab: Tab
</script>

<UiItemBase {component} {root}>
{#each component.content as child}
<CustomizableUi component={child} {tab} {root} />
{/each}
</UiItemBase>
29 changes: 29 additions & 0 deletions src/content/browser/components/customizableUI/BrowserView.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<script lang="ts">
import type {
BrowserComponent,
Component,
ComponentId,
} from '@shared/customizableUI'
import UiItemBase from './UIItemBase.svelte'
import { selectedTab, tabs } from '../../lib/globalApi'
import Browser from '../Browser.svelte'
export let component: ComponentId & BrowserComponent
export let root: Component
// We don't care about the order that browers are rendered in the dom, but we
// want to allow tab reordering. This should stop unnessisary updates
$: sortedBrowers = [...$tabs].sort(
(tabA, tabB) => tabA.getId() - tabB.getId(),
)
</script>

<UiItemBase {component} {root}>
{#each sortedBrowers as tab (tab.getId())}
<Browser {tab} selectedTab={$selectedTab} />
{/each}
</UiItemBase>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<script lang="ts">
import type {
Component,
ComponentId,
ExportComponent,
} from '@shared/customizableUI'
import type { Tab } from '../tabs/tab'
import Block from './Block.svelte'
import IconButton from './IconButton.svelte'
import Spacer from './Spacer.svelte'
import BrowserView from './BrowserView.svelte'
import OmniboxContainer from './OmniboxContainer.svelte'
import Tabs from './Tabs.svelte'
export let component: ComponentId & ExportComponent
export let root: Component
export let tab: Tab
</script>

{#if component.type === 'block'}
<Block {component} {root} {tab} />
{:else if component.type === 'icon'}
<IconButton {component} {root} {tab} />
{:else if component.type === 'spacer'}
<Spacer {component} {root} />
{:else if component.type === 'browser'}
<BrowserView {component} {root} />
{:else if component.type === 'omnibox'}
<OmniboxContainer {component} {root} {tab} />
{:else if component.type === 'tabs'}
<Tabs {component} {root} />
{/if}
32 changes: 32 additions & 0 deletions src/content/browser/components/customizableUI/IconButton.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<script lang="ts">
import type {
ComponentId,
IconComponent,
Component,
} from '@shared/customizableUI'
import type { Tab } from '../tabs/tab'
import { ToolbarButton } from '@shared/components'
import UIItemBase from './UIItemBase.svelte'
export let component: ComponentId & IconComponent
export let root: Component
export let tab: Tab
let button: HTMLButtonElement | undefined
$: enabled = component.enabled(tab)
</script>

<UIItemBase {component} {root}>
<ToolbarButton
bind:button
disabled={!$enabled}
on:click={() => component.action(tab, button)}
>
<i class={`ri-${component.icon}`} />
</ToolbarButton>
</UIItemBase>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<script lang="ts">
import type {
Component,
ComponentId,
OmniboxComponent,
} from '@shared/customizableUI'
import type { Tab } from '../tabs/tab'
import UiItemBase from './UIItemBase.svelte'
import Omnibox from '../omnibox/Omnibox.svelte'
export let component: ComponentId & OmniboxComponent
export let root: Component
export let tab: Tab
</script>

<UiItemBase {component} {root}>
<Omnibox {tab} />
</UiItemBase>
17 changes: 17 additions & 0 deletions src/content/browser/components/customizableUI/Spacer.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<script lang="ts">
import type {
Component,
ComponentId,
SpacerComponent,
} from '@shared/customizableUI'
import UiItemBase from './UIItemBase.svelte'
export let component: ComponentId & SpacerComponent
export let root: Component
</script>

<UiItemBase {component} {root} />
32 changes: 32 additions & 0 deletions src/content/browser/components/customizableUI/Tabs.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<script lang="ts">
import type {
Component,
ComponentId,
TabsComponent,
} from '@shared/customizableUI'
import { tabs, selectedTab } from '@browser/lib/globalApi'
import Tab from '@browser/components/tabs/Tab.svelte'
import UiItemBase from './UIItemBase.svelte'
export let component: ComponentId & TabsComponent
export let root: Component
</script>

<UiItemBase {component} {root} class="tabs" on:drop={(e) => e.preventDefault()}>
{#each $tabs as tab}
<Tab {tab} bind:selectedTab={$selectedTab} />
{/each}
</UiItemBase>

<style>
:global(.component.tabs) {
display: flex;
gap: 0.25;
overflow: scroll;
}
</style>
34 changes: 34 additions & 0 deletions src/content/browser/components/customizableUI/UIItemBase.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<script lang="ts">
import {
getParentOrientation,
type Component,
getComponentStyle,
} from '@shared/customizableUI'
let clazz = ''
export { clazz as class }
export let component: Component
export let root: Component
$: parentOrientation = getParentOrientation(root, component)
$: style = getComponentStyle(component, parentOrientation, false)
</script>

<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class={`component ${clazz}`} {style} on:drop>
<slot />
</div>

<style>
.component {
border-style: solid;
border-width: 1px;
border-color: transparent;
cursor: pointer;
}
</style>
3 changes: 3 additions & 0 deletions src/content/browser/components/customizableUI/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<script lang="ts">
import { onMount } from 'svelte'
import { type Keybind, keybindFromString } from '../../lib/keybinds'
import { observable } from '../../lib/xul/observable'
import { observable } from '../../../shared/xul/observable'
export let pref: string
let keybind: Keybind = keybindFromString(
Expand Down
Loading

0 comments on commit 9490da8

Please sign in to comment.