Added scrollbar to lanes and removed unused CSS vars

This commit is contained in:
Pavel Laptev 2024-03-09 23:23:34 +01:00 committed by GitButler
parent 06f0490bf3
commit bf27c3c474
4 changed files with 228 additions and 178 deletions

View File

@ -5,6 +5,7 @@
import CommitDialog from './CommitDialog.svelte';
import DropzoneOverlay from './DropzoneOverlay.svelte';
import PullRequestCard from './PullRequestCard.svelte';
import ScrollableContainer from './ScrollableContainer.svelte';
import UpstreamCommits from './UpstreamCommits.svelte';
import { ButlerAIProvider } from '$lib/backend/aiProviders';
import { Summarizer } from '$lib/backend/summarizer';
@ -44,6 +45,7 @@
RemoteBranchData,
RemoteCommit
} from '$lib/vbranches/types';
export let branch: Branch;
export let isUnapplied = false;
export let project: Project;
@ -63,6 +65,7 @@
const aiGenEnabled = projectAiGenEnabled(project.id);
const aiGenAutoBranchNamingEnabled = projectAiGenAutoBranchNamingEnabled(project.id);
let scrollViewport: HTMLElement;
let rsViewport: HTMLElement;
const userSettings = getContext<SettingsStore>(SETTINGS_CONTEXT);
@ -187,177 +190,201 @@
/>
</div>
{:else}
<div class="resizer-wrapper">
<div class="resizer-wrapper" bind:this={scrollViewport}>
<div
class="branch-card"
class="branch-card hide-native-scrollbar"
data-tauri-drag-region
class:target-branch={branch.active && branch.selectedForChanges}
>
<div
bind:this={rsViewport}
style:width={`${laneWidth || $defaultBranchWidthRem}rem`}
class="branch-card__contents"
<ScrollableContainer
wide
padding={{
top: `var(--space-12)`,
bottom: `var(--space-12)`
}}
>
<BranchHeader
{isUnapplied}
{branchController}
{branch}
{base}
bind:isLaneCollapsed
projectId={project.id}
on:action={(e) => {
if (e.detail == 'generate-branch-name') {
generateBranchName();
}
}}
/>
<PullRequestCard
projectId={project.id}
{branch}
{branchService}
{githubService}
{isUnapplied}
isLaneCollapsed={$isLaneCollapsed}
/>
{#if user?.role == 'admin' && unknownCommits && unknownCommits.length > 0 && !branch.conflicted}
<UpstreamCommits
upstream={upstreamData}
branchId={branch.id}
{project}
{branchController}
{branchCount}
projectId={project.id}
{selectedFiles}
{base}
/>
{/if}
<!-- DROPZONES -->
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
<DropzoneOverlay class="lane-dz-marker" label="Move here" />
<div
class="branch-card__dropzone-wrapper"
use:dropzone={{
hover: 'move-commit-dz-hover',
active: 'move-commit-dz-active',
accepts: acceptMoveCommit,
onDrop: onCommitDrop,
disabled: isUnapplied
}}
use:dropzone={{
hover: 'cherrypick-dz-hover',
active: 'cherrypick-dz-active',
accepts: acceptCherrypick,
onDrop: onCherrypicked,
disabled: isUnapplied
}}
use:dropzone={{
hover: 'lane-dz-hover',
active: 'lane-dz-active',
accepts: acceptBranchDrop,
onDrop: onBranchDrop,
disabled: isUnapplied
}}
bind:this={rsViewport}
style:width={`${laneWidth || $defaultBranchWidthRem}rem`}
class="branch-card__contents"
>
<BranchHeader
{isUnapplied}
{branchController}
{branch}
{base}
bind:isLaneCollapsed
projectId={project.id}
on:action={(e) => {
if (e.detail == 'generate-branch-name') {
generateBranchName();
}
}}
/>
<PullRequestCard
projectId={project.id}
{branch}
{branchService}
{githubService}
{isUnapplied}
isLaneCollapsed={$isLaneCollapsed}
/>
{#if user?.role == 'admin' && unknownCommits && unknownCommits.length > 0 && !branch.conflicted}
<UpstreamCommits
upstream={upstreamData}
branchId={branch.id}
{project}
{branchController}
{branchCount}
projectId={project.id}
{selectedFiles}
{base}
/>
{/if}
<!-- DROPZONES -->
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
<DropzoneOverlay class="lane-dz-marker" label="Move here" />
<DropzoneOverlay class="move-commit-dz-marker" label="Move here" />
{#if branch.files?.length > 0}
<div class="card">
{#if branch.active && branch.conflicted}
<div class="mb-2 bg-red-500 p-2 font-bold text-white">
{#if branch.files.some((f) => f.conflicted)}
This virtual branch conflicts with upstream changes. Please resolve all
conflicts and commit before you can continue.
{:else}
Please commit your resolved conflicts to continue.
{/if}
</div>
{/if}
<BranchFiles
branchId={branch.id}
files={branch.files}
{isUnapplied}
{branchController}
{project}
{selectedOwnership}
{selectedFiles}
showCheckboxes={$commitBoxOpen}
allowMultiple={true}
readonly={false}
/>
{#if branch.active}
<CommitDialog
projectId={project.id}
<div
class="branch-card__dropzone-wrapper"
use:dropzone={{
hover: 'move-commit-dz-hover',
active: 'move-commit-dz-active',
accepts: acceptMoveCommit,
onDrop: onCommitDrop,
disabled: isUnapplied
}}
use:dropzone={{
hover: 'cherrypick-dz-hover',
active: 'cherrypick-dz-active',
accepts: acceptCherrypick,
onDrop: onCherrypicked,
disabled: isUnapplied
}}
use:dropzone={{
hover: 'lane-dz-hover',
active: 'lane-dz-active',
accepts: acceptBranchDrop,
onDrop: onBranchDrop,
disabled: isUnapplied
}}
>
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
<DropzoneOverlay class="lane-dz-marker" label="Move here" />
<DropzoneOverlay class="move-commit-dz-marker" label="Move here" />
{#if branch.files?.length > 0}
<div class="card">
{#if branch.active && branch.conflicted}
<div class="mb-2 bg-red-500 p-2 font-bold text-white">
{#if branch.files.some((f) => f.conflicted)}
This virtual branch conflicts with upstream changes. Please resolve all
conflicts and commit before you can continue.
{:else}
Please commit your resolved conflicts to continue.
{/if}
</div>
{/if}
<BranchFiles
branchId={branch.id}
files={branch.files}
{isUnapplied}
{branchController}
{branch}
{cloud}
{project}
{selectedOwnership}
{user}
bind:expanded={commitBoxOpen}
on:action={(e) => {
if (e.detail == 'generate-branch-name') {
generateBranchName();
}
}}
{selectedFiles}
showCheckboxes={$commitBoxOpen}
allowMultiple={true}
readonly={false}
/>
{/if}
</div>
{:else if branch.commits.length == 0}
<div class="new-branch card" data-dnd-ignore>
<div class="new-branch__content">
<div class="new-branch__image">
<ImgThemed
imgSet={{
light: '/images/lane-new-light.webp',
dark: '/images/lane-new-dark.webp'
{#if branch.active}
<CommitDialog
projectId={project.id}
{branchController}
{branch}
{cloud}
{selectedOwnership}
{user}
bind:expanded={commitBoxOpen}
on:action={(e) => {
if (e.detail == 'generate-branch-name') {
generateBranchName();
}
}}
/>
</div>
<h2 class="new-branch__title text-base-body-15 text-semibold">
This is a new branch.
</h2>
<p class="new-branch__caption text-base-body-13">
You can drag and drop files or parts of files here.
</p>
{/if}
</div>
</div>
{:else}
<!-- attention: these markers have custom css at the bottom of thise file -->
<div class="no-changes card" data-dnd-ignore>
<div class="new-branch__content">
<div class="new-branch__image">
<ImgThemed
imgSet={{
light: '/images/lane-no-changes-light.webp',
dark: '/images/lane-no-changes-dark.webp'
}}
/>
{:else if branch.commits.length == 0}
<div class="new-branch card" data-dnd-ignore>
<div class="new-branch__content">
<div class="new-branch__image">
<ImgThemed
imgSet={{
light: '/images/lane-new-light.webp',
dark: '/images/lane-new-dark.webp'
}}
/>
</div>
<h2 class="new-branch__title text-base-body-15 text-semibold">
This is a new branch.
</h2>
<p class="new-branch__caption text-base-body-13">
You can drag and drop files or parts of files here.
</p>
</div>
<h2 class="new-branch__caption text-base-body-13">
No uncommitted changes<br />on this branch
</h2>
</div>
</div>
{/if}
</div>
{:else}
<!-- attention: these markers have custom css at the bottom of thise file -->
<div class="no-changes card" data-dnd-ignore>
<div class="new-branch__content">
<div class="new-branch__image">
<ImgThemed
imgSet={{
light: '/images/lane-no-changes-light.webp',
dark: '/images/lane-no-changes-dark.webp'
}}
/>
</div>
<h2 class="new-branch__caption text-base-body-13">
No uncommitted changes<br />on this branch
</h2>
</div>
</div>
{/if}
</div>
<BranchCommits
{base}
{branch}
{project}
{githubService}
{branchController}
{branchService}
{branchCount}
{isUnapplied}
{selectedFiles}
<BranchCommits
{base}
{branch}
{project}
{githubService}
{branchController}
{branchService}
{branchCount}
{isUnapplied}
{selectedFiles}
/>
</div>
</ScrollableContainer>
<div class="divider-line">
<Resizer
viewport={rsViewport}
direction="right"
minWidth={320}
sticky
defaultLineColor={$selectedFiles.length > 0
? 'transparent'
: 'var(--clr-theme-container-outline-light)'}
on:width={(e) => {
laneWidth = e.detail / (16 * $userSettings.zoom);
lscache.set(laneWidthKey + branch.id, laneWidth, 7 * 1440); // 7 day ttl
$defaultBranchWidthRem = laneWidth;
}}
/>
</div>
</div>
<div class="divider-line">
<!-- <div class="divider-line">
<Resizer
viewport={rsViewport}
direction="right"
@ -372,7 +399,7 @@
$defaultBranchWidthRem = laneWidth;
}}
/>
</div>
</div> -->
</div>
{/if}
@ -388,19 +415,14 @@
user-select: none;
overflow-x: hidden;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 0px;
background: transparent; /* Chrome/Safari/Webkit */
}
}
.divider-line {
z-index: 30;
position: absolute;
top: 0;
right: 0;
height: 100%;
transform: translateX(var(--selected-resize-shift));
}
.branch-card__dropzone-wrapper {

View File

@ -138,9 +138,6 @@
user-select: none; /* here because of user-select draggable interference in board */
position: relative;
--target-branch-background: var(--clr-theme-container-pale);
--selected-resize-shift: 0;
--selected-target-branch-right-padding: 0;
--selected-opacity: 1;
background-color: var(--target-branch-background);
}
@ -152,12 +149,6 @@
);
}
.file-selected {
--selected-resize-shift: calc((var(--space-6) + 0.0625rem) * -1);
--selected-target-branch-right-padding: calc(var(--space-4) * -1);
--selected-opacity: 0;
}
.file-preview {
display: flex;
position: relative;
@ -167,6 +158,5 @@
align-items: self-start;
padding: var(--space-12) var(--space-12) var(--space-12) 0;
margin-left: var(--selected-target-branch-right-padding);
}
</style>

View File

@ -1,5 +1,5 @@
<script lang="ts">
import Scrollbar from '$lib/components/Scrollbar.svelte';
import Scrollbar, { type ScrollbarPadding } from '$lib/components/Scrollbar.svelte';
import { onDestroy, onMount, createEventDispatcher } from 'svelte';
export let viewport: HTMLDivElement | undefined = undefined;
@ -13,6 +13,10 @@
export let initiallyVisible = false;
export let showBorderWhenScrolled = false;
export let padding: ScrollbarPadding = {};
export let shift = '0';
export let thickness = '0.563rem';
let observer: ResizeObserver;
const dispatch = createEventDispatcher<{ dragging: boolean }>();
@ -53,6 +57,9 @@
{viewport}
{contents}
{initiallyVisible}
{padding}
{shift}
{thickness}
on:dragging={(e) => dispatch('dragging', e.detail)}
/>
</div>

View File

@ -1,3 +1,7 @@
<script lang="ts" context="module">
export type ScrollbarPadding = { top?: string; right?: string; bottom?: string; left?: string };
</script>
<script lang="ts">
import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/settings/userSettings';
import { onDestroy, createEventDispatcher } from 'svelte';
@ -10,6 +14,8 @@
export let hideAfter = 1000;
export let initiallyVisible = false;
export let thickness = '0.563rem';
export let padding: ScrollbarPadding = {};
export let shift = '0';
export let horz = false;
@ -35,6 +41,11 @@
$: teardownTrack = setupTrack(track);
$: teardownContents = setupContents(contents);
$: paddingTop = padding.top ?? '0px';
$: paddingBottom = padding.bottom ?? '0px';
$: paddingRight = padding.right ?? '0px';
$: paddingLeft = padding.left ?? '0px';
$: wholeHeight = viewport?.scrollHeight ?? 0;
$: wholeWidth = viewport?.scrollWidth ?? 0;
$: scrollTop = viewport?.scrollTop ?? 0;
@ -71,7 +82,7 @@
wholeHeight = viewport?.scrollHeight ?? 0;
wholeWidth = viewport?.scrollWidth ?? 0;
trackHeight = viewport?.clientHeight ?? 0;
trackWidth = viewport?.clientWidth ?? 0;
trackWidth = viewport?.clientWidth;
}
});
@ -261,27 +272,41 @@
class:vert
class:show-scrollbar={visible}
class:thumb-dragging={isDragging}
style:right={vert ? 0 : undefined}
style:top={vert ? 0 : undefined}
style:bottom={horz ? 0 : undefined}
style:left={horz ? 0 : undefined}
style:width={vert ? thickness : `80%`}
style:height={vert ? `80%` : thickness}
style:width={vert ? thickness : `100%`}
style:height={vert ? `100%` : thickness}
style:z-index={zIndex}
style="
--scrollbar-shift-vertical: {vert ? '0' : shift};
--scrollbar-shift-horizontal: {horz ? '0' : shift};
"
>
<div
bind:this={thumb}
class="scrollbar-thumb"
style:left={vert ? undefined : `${thumbLeft}px`}
style:top={vert ? `${thumbTop}px` : undefined}
style:width={vert ? '100%' : `${thumbWidth}px`}
style:height={vert ? `${thumbHeight}px` : '100%'}
style="
--thumb-width: {vert
? '100%'
: `calc(${thumbWidth.toFixed(0)}px - (${paddingRight} + ${paddingLeft}))`};
--thumb-height: {vert
? `calc(${thumbHeight.toFixed(0)}px - (${paddingBottom} + ${paddingTop}))`
: '100%'};
--thumb-top: {vert ? `calc(${thumbTop.toFixed(0)}px + ${paddingTop})` : 'auto'};
--thumb-left: {vert ? 'auto' : `calc(${thumbLeft.toFixed(0)}px + ${paddingLeft})`};
"
/>
</div>
<style>
.scrollbar-track {
/* scrollbar variables */
--scrollbar-shift-vertical: 0;
--scrollbar-shift-horizontal: 0;
/* variable props */
bottom: var(--scrollbar-shift-vertical);
right: var(--scrollbar-shift-horizontal);
/* other props */
position: absolute;
/* background-color: aqua; */
transition:
opacity 0.2s,
width 0.1s,
@ -289,6 +314,12 @@
}
.scrollbar-thumb {
/* variable props */
width: var(--thumb-width);
height: var(--thumb-height);
top: var(--thumb-top);
left: var(--thumb-left);
/* other props */
position: absolute;
z-index: 30;
background-color: var(--clr-theme-scale-ntrl-0);