mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-22 17:11:43 +03:00
Tooltip-refactoring-+-new-component (#4804)
* tooltip component + custom svelte transitions * update some tooltips * replace old toogle * replace old tooltip hook * remove old tooltip hook * lint fixes * design tokens update
This commit is contained in:
parent
98c3f5d310
commit
c820a33e41
@ -47,7 +47,7 @@
|
|||||||
icon="pr-small"
|
icon="pr-small"
|
||||||
style="success"
|
style="success"
|
||||||
kind="solid"
|
kind="solid"
|
||||||
help="These changes have been integrated upstream, update your workspace to make this lane disappear."
|
tooltip="Changes have been integrated upstream, update your workspace to make this lane disappear."
|
||||||
reversedDirection>Integrated</Button
|
reversedDirection>Integrated</Button
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
@ -56,7 +56,7 @@
|
|||||||
size="tag"
|
size="tag"
|
||||||
icon="virtual-branch-small"
|
icon="virtual-branch-small"
|
||||||
style="neutral"
|
style="neutral"
|
||||||
help="These changes are in your working directory."
|
tooltip="Changes are in your working directory"
|
||||||
reversedDirection>Virtual</Button
|
reversedDirection>Virtual</Button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
@ -68,7 +68,7 @@
|
|||||||
style="neutral"
|
style="neutral"
|
||||||
shrinkable
|
shrinkable
|
||||||
disabled
|
disabled
|
||||||
help="Branch name that will be used when pushing. You can change it from the lane menu."
|
tooltip={'Branch name that will be used when pushing.\nChange it from the lane menu'}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</Button>
|
</Button>
|
||||||
@ -81,7 +81,7 @@
|
|||||||
style="neutral"
|
style="neutral"
|
||||||
kind="solid"
|
kind="solid"
|
||||||
icon="remote-branch-small"
|
icon="remote-branch-small"
|
||||||
help="At least some of your changes have been pushed"
|
tooltip="Some changes have been pushed"
|
||||||
reversedDirection>Remote</Button
|
reversedDirection>Remote</Button
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
|
@ -132,7 +132,7 @@
|
|||||||
<div class="draggable" data-drag-handle>
|
<div class="draggable" data-drag-handle>
|
||||||
<Icon name="draggable" />
|
<Icon name="draggable" />
|
||||||
</div>
|
</div>
|
||||||
<Button style="ghost" outline icon="unfold-lane" help="Expand lane" onclick={expandLane} />
|
<Button style="ghost" outline icon="unfold-lane" tooltip="Expand lane" onclick={expandLane} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="collapsed-lane__info-wrap" bind:clientHeight={headerInfoHeight}>
|
<div class="collapsed-lane__info-wrap" bind:clientHeight={headerInfoHeight}>
|
||||||
@ -147,7 +147,7 @@
|
|||||||
clickable={false}
|
clickable={false}
|
||||||
style="warning"
|
style="warning"
|
||||||
kind="soft"
|
kind="soft"
|
||||||
help="Uncommitted changes"
|
tooltip="Uncommitted changes"
|
||||||
>
|
>
|
||||||
{uncommittedChanges}
|
{uncommittedChanges}
|
||||||
{uncommittedChanges === 1 ? 'change' : 'changes'}
|
{uncommittedChanges === 1 ? 'change' : 'changes'}
|
||||||
@ -198,7 +198,7 @@
|
|||||||
clickable={false}
|
clickable={false}
|
||||||
icon="locked-small"
|
icon="locked-small"
|
||||||
style="warning"
|
style="warning"
|
||||||
help="Applying this branch will add merge conflict markers that you will have to resolve"
|
tooltip="Applying this branch will add merge conflict markers that you will have to resolve"
|
||||||
>
|
>
|
||||||
Conflict
|
Conflict
|
||||||
</Button>
|
</Button>
|
||||||
@ -214,7 +214,7 @@
|
|||||||
<Button
|
<Button
|
||||||
style="pop"
|
style="pop"
|
||||||
kind="soft"
|
kind="soft"
|
||||||
help="New changes will land here"
|
tooltip="New changes will land here"
|
||||||
icon="target"
|
icon="target"
|
||||||
clickable={false}
|
clickable={false}
|
||||||
>
|
>
|
||||||
@ -224,7 +224,7 @@
|
|||||||
<Button
|
<Button
|
||||||
style="ghost"
|
style="ghost"
|
||||||
outline
|
outline
|
||||||
help="When selected, new changes will land here"
|
tooltip="When selected, new changes land here"
|
||||||
icon="target"
|
icon="target"
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
isTargetBranchAnimated = true;
|
isTargetBranchAnimated = true;
|
||||||
@ -242,7 +242,7 @@
|
|||||||
<PullRequestButton
|
<PullRequestButton
|
||||||
click={async ({ draft }) => await createPr({ draft })}
|
click={async ({ draft }) => await createPr({ draft })}
|
||||||
disabled={branch.commits.length === 0 || !$gitHost}
|
disabled={branch.commits.length === 0 || !$gitHost}
|
||||||
help={!$gitHost ? 'You can enable git host integration in the settings' : ''}
|
tooltip={!$gitHost ? 'You can enable git host integration in the settings' : ''}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
import { VirtualBranch } from '$lib/vbranches/types';
|
import { VirtualBranch } from '$lib/vbranches/types';
|
||||||
import Button from '@gitbutler/ui/Button.svelte';
|
import Button from '@gitbutler/ui/Button.svelte';
|
||||||
import Modal from '@gitbutler/ui/Modal.svelte';
|
import Modal from '@gitbutler/ui/Modal.svelte';
|
||||||
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
contextMenuEl?: ContextMenu;
|
contextMenuEl?: ContextMenu;
|
||||||
@ -138,13 +139,9 @@
|
|||||||
|
|
||||||
<ContextMenuSection>
|
<ContextMenuSection>
|
||||||
<ContextMenuItem label="Allow rebasing" on:click={toggleAllowRebasing}>
|
<ContextMenuItem label="Allow rebasing" on:click={toggleAllowRebasing}>
|
||||||
<Toggle
|
<Tooltip slot="control" text={'Allows changing commits after push\n(force push needed)'}>
|
||||||
small
|
<Toggle small bind:checked={allowRebasing} on:click={toggleAllowRebasing} />
|
||||||
slot="control"
|
</Tooltip>
|
||||||
bind:checked={allowRebasing}
|
|
||||||
on:click={toggleAllowRebasing}
|
|
||||||
help="Allows changing commits after push (force push needed)"
|
|
||||||
/>
|
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
</ContextMenuSection>
|
</ContextMenuSection>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
import Button from '@gitbutler/ui/Button.svelte';
|
import Button from '@gitbutler/ui/Button.svelte';
|
||||||
import Icon from '@gitbutler/ui/Icon.svelte';
|
import Icon from '@gitbutler/ui/Icon.svelte';
|
||||||
import Modal from '@gitbutler/ui/Modal.svelte';
|
import Modal from '@gitbutler/ui/Modal.svelte';
|
||||||
import { tooltip } from '@gitbutler/ui/utils/tooltip';
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import type { PullRequest } from '$lib/gitHost/interface/types';
|
import type { PullRequest } from '$lib/gitHost/interface/types';
|
||||||
import type { Branch } from '$lib/vbranches/types';
|
import type { Branch } from '$lib/vbranches/types';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
@ -40,13 +40,18 @@
|
|||||||
<BranchLabel disabled name={branch.name} />
|
<BranchLabel disabled name={branch.name} />
|
||||||
<div class="header__remote-branch">
|
<div class="header__remote-branch">
|
||||||
{#if remoteBranch}
|
{#if remoteBranch}
|
||||||
<div
|
<Tooltip text="At least some of your changes have been pushed'">
|
||||||
class="status-tag text-11 text-semibold remote"
|
<Button
|
||||||
use:tooltip={'At least some of your changes have been pushed'}
|
size="tag"
|
||||||
|
icon="remote-branch-small"
|
||||||
|
style="neutral"
|
||||||
|
kind="solid"
|
||||||
|
clickable={false}
|
||||||
>
|
>
|
||||||
<Icon name="remote-branch-small" />
|
|
||||||
{localBranch ? 'local and remote' : 'remote'}
|
{localBranch ? 'local and remote' : 'remote'}
|
||||||
</div>
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
{#if gitHostBranch}
|
{#if gitHostBranch}
|
||||||
<Button
|
<Button
|
||||||
size="tag"
|
size="tag"
|
||||||
@ -93,7 +98,7 @@
|
|||||||
<Button
|
<Button
|
||||||
style="ghost"
|
style="ghost"
|
||||||
outline
|
outline
|
||||||
help="Restores these changes into your working directory"
|
tooltip="Restores these changes into your working directory"
|
||||||
icon="plus-small"
|
icon="plus-small"
|
||||||
loading={isApplying}
|
loading={isApplying}
|
||||||
disabled={$mode?.type !== 'OpenWorkspace'}
|
disabled={$mode?.type !== 'OpenWorkspace'}
|
||||||
@ -120,7 +125,7 @@
|
|||||||
<Button
|
<Button
|
||||||
style="ghost"
|
style="ghost"
|
||||||
outline
|
outline
|
||||||
help="Deletes the local branch. If this branch is also present on a remote, it will not be deleted there."
|
tooltip="Deletes the local branch. If this branch is also present on a remote, it will not be deleted there."
|
||||||
icon="bin-small"
|
icon="bin-small"
|
||||||
loading={isDeleting}
|
loading={isDeleting}
|
||||||
disabled={!localBranch}
|
disabled={!localBranch}
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
import Button from '@gitbutler/ui/Button.svelte';
|
import Button from '@gitbutler/ui/Button.svelte';
|
||||||
import Icon from '@gitbutler/ui/Icon.svelte';
|
import Icon from '@gitbutler/ui/Icon.svelte';
|
||||||
import Modal from '@gitbutler/ui/Modal.svelte';
|
import Modal from '@gitbutler/ui/Modal.svelte';
|
||||||
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import { getTimeAgo } from '@gitbutler/ui/utils/timeAgo';
|
import { getTimeAgo } from '@gitbutler/ui/utils/timeAgo';
|
||||||
import { tooltip } from '@gitbutler/ui/utils/tooltip';
|
|
||||||
import { type Snippet } from 'svelte';
|
import { type Snippet } from 'svelte';
|
||||||
|
|
||||||
export let branch: VirtualBranch | undefined = undefined;
|
export let branch: VirtualBranch | undefined = undefined;
|
||||||
@ -299,24 +299,25 @@
|
|||||||
|
|
||||||
<div class="text-11 commit__subtitle">
|
<div class="text-11 commit__subtitle">
|
||||||
{#if commit.isSigned}
|
{#if commit.isSigned}
|
||||||
<div class="commit__signed" use:tooltip={{ text: 'Signed', delay: 500 }}>
|
<Tooltip text="Signed">
|
||||||
|
<div class="commit__signed">
|
||||||
<Icon name="success-outline-small" />
|
<Icon name="success-outline-small" />
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<span class="commit__subtitle-divider">•</span>
|
<span class="commit__subtitle-divider">•</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if conflicted}
|
{#if conflicted}
|
||||||
<div
|
<Tooltip
|
||||||
class="commit__conflicted"
|
text={"Conflicted commits must be resolved before they can be ammended or squashed.\nPlease resolve conflicts using the 'Resolve conflicts' button"}
|
||||||
use:tooltip={{
|
|
||||||
text: 'Conflicted commits must be resolved before they can be ammended or squashed.\n\nPlease resolve conflicts using the "Resolve conflicts" button'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
|
<div class="commit__conflicted">
|
||||||
<Icon name="warning-small" />
|
<Icon name="warning-small" />
|
||||||
|
|
||||||
Conflicted
|
Conflicted
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<span class="commit__subtitle-divider">•</span>
|
<span class="commit__subtitle-divider">•</span>
|
||||||
{/if}
|
{/if}
|
||||||
@ -593,6 +594,7 @@
|
|||||||
|
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-underline-offset: 2px;
|
text-underline-offset: 2px;
|
||||||
|
transition: color var(--transition-fast);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--clr-text-1);
|
color: var(--clr-text-1);
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
import { persistedCommitMessage, projectRunCommitHooks } from '$lib/config/config';
|
import { persistedCommitMessage, projectRunCommitHooks } from '$lib/config/config';
|
||||||
import { getContext, getContextStore } from '$lib/utils/context';
|
import { getContext, getContextStore } from '$lib/utils/context';
|
||||||
import { intersectionObserver } from '$lib/utils/intersectionObserver';
|
import { intersectionObserver } from '$lib/utils/intersectionObserver';
|
||||||
import { slideFade } from '$lib/utils/svelteTransitions';
|
|
||||||
import { BranchController } from '$lib/vbranches/branchController';
|
import { BranchController } from '$lib/vbranches/branchController';
|
||||||
import { Ownership } from '$lib/vbranches/ownership';
|
import { Ownership } from '$lib/vbranches/ownership';
|
||||||
import { VirtualBranch } from '$lib/vbranches/types';
|
import { VirtualBranch } from '$lib/vbranches/types';
|
||||||
import Button from '@gitbutler/ui/Button.svelte';
|
import Button from '@gitbutler/ui/Button.svelte';
|
||||||
|
import { slideFade } from '@gitbutler/ui/utils/transitions';
|
||||||
import type { Writable } from 'svelte/store';
|
import type { Writable } from 'svelte/store';
|
||||||
|
|
||||||
export let projectId: string;
|
export let projectId: string;
|
||||||
|
@ -228,7 +228,7 @@
|
|||||||
wide
|
wide
|
||||||
loading={isPushingCommits}
|
loading={isPushingCommits}
|
||||||
disabled={localCommitsConflicted}
|
disabled={localCommitsConflicted}
|
||||||
help={localCommitsConflicted
|
tooltip={localCommitsConflicted
|
||||||
? 'In order to push, please resolve any conflicted commits.'
|
? 'In order to push, please resolve any conflicted commits.'
|
||||||
: undefined}
|
: undefined}
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
import { VirtualBranch, LocalFile } from '$lib/vbranches/types';
|
import { VirtualBranch, LocalFile } from '$lib/vbranches/types';
|
||||||
import Checkbox from '@gitbutler/ui/Checkbox.svelte';
|
import Checkbox from '@gitbutler/ui/Checkbox.svelte';
|
||||||
import Icon from '@gitbutler/ui/Icon.svelte';
|
import Icon from '@gitbutler/ui/Icon.svelte';
|
||||||
import { tooltip } from '@gitbutler/ui/utils/tooltip';
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import { createEventDispatcher, onMount } from 'svelte';
|
import { createEventDispatcher, onMount } from 'svelte';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
|
|
||||||
@ -179,27 +179,21 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if title.length > 50}
|
{#if title.length > 50}
|
||||||
<div
|
<Tooltip text={'50 characters or less is best.\nUse description for more details'}>
|
||||||
transition:fly={{ y: 2, duration: 150 }}
|
<div transition:fly={{ y: 2, duration: 150 }} class="commit-box__textarea-tooltip">
|
||||||
class="commit-box__textarea-tooltip"
|
|
||||||
use:tooltip={{
|
|
||||||
text: '50 characters or less is best. Extra info can be added in the description.',
|
|
||||||
delay: 200
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon name="idea" />
|
<Icon name="idea" />
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div
|
<Tooltip
|
||||||
class="commit-box__texarea-actions"
|
text={!aiConfigurationValid
|
||||||
class:commit-box-actions_expanded={isExpanded}
|
? 'You must be logged in or have provided your own API key'
|
||||||
use:tooltip={!aiConfigurationValid
|
|
||||||
? 'You must be logged in or have provided your own API key to use this feature'
|
|
||||||
: !$aiGenEnabled
|
: !$aiGenEnabled
|
||||||
? 'You must have summary generation enabled to use this feature'
|
? 'You must have summary generation enabled'
|
||||||
: ''}
|
: undefined}
|
||||||
>
|
>
|
||||||
|
<div class="commit-box__texarea-actions" class:commit-box-actions_expanded={isExpanded}>
|
||||||
<DropDownButton
|
<DropDownButton
|
||||||
style="ghost"
|
style="ghost"
|
||||||
outline
|
outline
|
||||||
@ -230,6 +224,7 @@
|
|||||||
{/snippet}
|
{/snippet}
|
||||||
</DropDownButton>
|
</DropDownButton>
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
import Button from '@gitbutler/ui/Button.svelte';
|
import Button from '@gitbutler/ui/Button.svelte';
|
||||||
import Checkbox from '@gitbutler/ui/Checkbox.svelte';
|
import Checkbox from '@gitbutler/ui/Checkbox.svelte';
|
||||||
import Modal from '@gitbutler/ui/Modal.svelte';
|
import Modal from '@gitbutler/ui/Modal.svelte';
|
||||||
import { tooltip } from '@gitbutler/ui/utils/tooltip';
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import type { BaseBranch } from '$lib/baseBranch/baseBranch';
|
import type { BaseBranch } from '$lib/baseBranch/baseBranch';
|
||||||
|
|
||||||
export let base: BaseBranch;
|
export let base: BaseBranch;
|
||||||
@ -49,7 +49,7 @@
|
|||||||
<Button
|
<Button
|
||||||
style="pop"
|
style="pop"
|
||||||
kind="solid"
|
kind="solid"
|
||||||
help={`Merges the commits from ${base.branchName} into the base of all applied virtual branches`}
|
tooltip={`Merges the commits from ${base.branchName} into the base of all applied virtual branches`}
|
||||||
disabled={$mode?.type !== 'OpenWorkspace'}
|
disabled={$mode?.type !== 'OpenWorkspace'}
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
if ($mergeUpstreamWarningDismissed) {
|
if ($mergeUpstreamWarningDismissed) {
|
||||||
@ -77,12 +77,9 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h1
|
<Tooltip text="Current base for virtual branches.">
|
||||||
class="text-13 info-text text-bold"
|
<h1 class="text-13 info-text text-bold">Local</h1>
|
||||||
use:tooltip={'This is the current base for your virtual branches.'}
|
</Tooltip>
|
||||||
>
|
|
||||||
Local
|
|
||||||
</h1>
|
|
||||||
{#each base.recentCommits as commit, index}
|
{#each base.recentCommits as commit, index}
|
||||||
<CommitCard
|
<CommitCard
|
||||||
{commit}
|
{commit}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
icon="plus-small"
|
icon="plus-small"
|
||||||
size="tag"
|
size="tag"
|
||||||
width={26}
|
width={26}
|
||||||
help="Insert empty commit"
|
tooltip="Insert empty commit"
|
||||||
helpShowDelay={500}
|
helpShowDelay={500}
|
||||||
onclick={() => dispatch('click')}
|
onclick={() => dispatch('click')}
|
||||||
/>
|
/>
|
||||||
|
@ -138,7 +138,7 @@
|
|||||||
<Button
|
<Button
|
||||||
style="pop"
|
style="pop"
|
||||||
kind="solid"
|
kind="solid"
|
||||||
help="Does not create a commit. Can be toggled."
|
tooltip="Does not create a commit. Can be toggled."
|
||||||
onclick={async () => createRemoteModal?.show()}>Apply from fork</Button
|
onclick={async () => createRemoteModal?.show()}>Apply from fork</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
style="ghost"
|
style="ghost"
|
||||||
outline
|
outline
|
||||||
icon="update-small"
|
icon="update-small"
|
||||||
help="Last fetch from upstream"
|
tooltip="Last fetch from upstream"
|
||||||
{loading}
|
{loading}
|
||||||
onmousedown={async (e) => {
|
onmousedown={async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
size="tag"
|
size="tag"
|
||||||
style="error"
|
style="error"
|
||||||
kind="solid"
|
kind="solid"
|
||||||
help="Merge upstream commits into common base"
|
tooltip="Merge upstream into common base"
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
loading = true;
|
loading = true;
|
||||||
try {
|
try {
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
clickable={false}
|
clickable={false}
|
||||||
icon="locked-small"
|
icon="locked-small"
|
||||||
style="warning"
|
style="warning"
|
||||||
help="File changes cannot be moved because part of this file was already committed into this branch"
|
tooltip="File changes cannot be moved because part of this file was already committed into this branch"
|
||||||
>Locked</Button
|
>Locked</Button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
import { getLocalCommits, getLocalAndRemoteCommits } from '$lib/vbranches/contexts';
|
import { getLocalCommits, getLocalAndRemoteCommits } from '$lib/vbranches/contexts';
|
||||||
import { getLockText } from '$lib/vbranches/tooltip';
|
import { getLockText } from '$lib/vbranches/tooltip';
|
||||||
import Icon from '@gitbutler/ui/Icon.svelte';
|
import Icon from '@gitbutler/ui/Icon.svelte';
|
||||||
import { tooltip } from '@gitbutler/ui/utils/tooltip';
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import type { HunkSection, ContentSection } from '$lib/utils/fileSections';
|
import type { HunkSection, ContentSection } from '$lib/utils/fileSections';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -76,14 +76,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if section.hunk.lockedTo && section.hunk.lockedTo.length > 0 && commits}
|
{#if section.hunk.lockedTo && section.hunk.lockedTo.length > 0 && commits}
|
||||||
<div
|
<Tooltip text={getLockText(section.hunk.lockedTo, commits)}>
|
||||||
use:tooltip={{
|
|
||||||
text: getLockText(section.hunk.lockedTo, commits),
|
|
||||||
delay: 500
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon name="locked-small" color="warning" />
|
<Icon name="locked-small" color="warning" />
|
||||||
</div>
|
</Tooltip>
|
||||||
{/if}
|
{/if}
|
||||||
{#if section.hunk.poisoned}
|
{#if section.hunk.poisoned}
|
||||||
Can not manage this hunk because it depends on changes from multiple branches
|
Can not manage this hunk because it depends on changes from multiple branches
|
||||||
|
@ -172,7 +172,7 @@
|
|||||||
size="tag"
|
size="tag"
|
||||||
style="ghost"
|
style="ghost"
|
||||||
outline
|
outline
|
||||||
help="Restores GitButler and your files to the state before this operation. Revert actions can also be undone."
|
tooltip="Restores GitButler and your files to the state before this operation. Revert actions can also be undone."
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
dispatch('restoreClick');
|
dispatch('restoreClick');
|
||||||
}}
|
}}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { tooltip } from '@gitbutler/ui/utils/tooltip';
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import { type Snippet } from 'svelte';
|
import { type Snippet } from 'svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -21,8 +21,8 @@
|
|||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Tooltip text={isNavCollapsed ? tooltipLabel : ''} align="start">
|
||||||
<button
|
<button
|
||||||
use:tooltip={isNavCollapsed ? tooltipLabel : ''}
|
|
||||||
{onmousedown}
|
{onmousedown}
|
||||||
class="domain-button text-14 text-semibold"
|
class="domain-button text-14 text-semibold"
|
||||||
class:selected={isSelected}
|
class:selected={isSelected}
|
||||||
@ -31,6 +31,7 @@
|
|||||||
>
|
>
|
||||||
{@render children()}
|
{@render children()}
|
||||||
</button>
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
.domain-button {
|
.domain-button {
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
icon="mail"
|
icon="mail"
|
||||||
style="ghost"
|
style="ghost"
|
||||||
size="cta"
|
size="cta"
|
||||||
help="Share feedback"
|
tooltip="Share feedback"
|
||||||
|
tooltipAlign="start"
|
||||||
|
tooltipPosition={isNavCollapsed ? 'bottom' : 'top'}
|
||||||
onclick={() => events.emit('openSendIssueModal')}
|
onclick={() => events.emit('openSendIssueModal')}
|
||||||
wide={isNavCollapsed}
|
wide={isNavCollapsed}
|
||||||
/>
|
/>
|
||||||
@ -27,7 +29,9 @@
|
|||||||
icon="settings"
|
icon="settings"
|
||||||
style="ghost"
|
style="ghost"
|
||||||
size="cta"
|
size="cta"
|
||||||
help="Project settings"
|
tooltip="Project settings"
|
||||||
|
tooltipAlign={isNavCollapsed ? 'start' : 'center'}
|
||||||
|
tooltipPosition={isNavCollapsed ? 'bottom' : 'top'}
|
||||||
onclick={async () => await goto(`/${projectId}/settings`)}
|
onclick={async () => await goto(`/${projectId}/settings`)}
|
||||||
wide={isNavCollapsed}
|
wide={isNavCollapsed}
|
||||||
disabled={$mode?.type !== 'OpenWorkspace'}
|
disabled={$mode?.type !== 'OpenWorkspace'}
|
||||||
@ -36,7 +40,9 @@
|
|||||||
icon="timeline"
|
icon="timeline"
|
||||||
style="ghost"
|
style="ghost"
|
||||||
size="cta"
|
size="cta"
|
||||||
help="Project history"
|
tooltip="Project history"
|
||||||
|
tooltipAlign={isNavCollapsed ? 'start' : 'center'}
|
||||||
|
tooltipPosition={isNavCollapsed ? 'bottom' : 'top'}
|
||||||
onclick={() => events.emit('openHistory')}
|
onclick={() => events.emit('openHistory')}
|
||||||
wide={isNavCollapsed}
|
wide={isNavCollapsed}
|
||||||
/>
|
/>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import ProjectAvatar from '$lib/navigation/ProjectAvatar.svelte';
|
import ProjectAvatar from '$lib/navigation/ProjectAvatar.svelte';
|
||||||
import { getContext } from '$lib/utils/context';
|
import { getContext } from '$lib/utils/context';
|
||||||
import Icon from '@gitbutler/ui/Icon.svelte';
|
import Icon from '@gitbutler/ui/Icon.svelte';
|
||||||
import { tooltip } from '@gitbutler/ui/utils/tooltip';
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
|
|
||||||
export let isNavCollapsed: boolean;
|
export let isNavCollapsed: boolean;
|
||||||
|
|
||||||
@ -15,10 +15,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
|
<Tooltip text={isNavCollapsed ? project?.title : ''} align="start">
|
||||||
<button
|
<button
|
||||||
bind:this={buttonTrigger}
|
bind:this={buttonTrigger}
|
||||||
class="text-input button"
|
class="text-input button"
|
||||||
use:tooltip={isNavCollapsed ? project?.title : ''}
|
|
||||||
on:mousedown={(e) => {
|
on:mousedown={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
popup.toggle();
|
popup.toggle();
|
||||||
@ -32,6 +32,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
</Tooltip>
|
||||||
<ProjectsPopup bind:this={popup} target={buttonTrigger} {isNavCollapsed} />
|
<ProjectsPopup bind:this={popup} target={buttonTrigger} {isNavCollapsed} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
import { getContext } from '$lib/utils/context';
|
import { getContext } from '$lib/utils/context';
|
||||||
import Badge from '@gitbutler/ui/Badge.svelte';
|
import Badge from '@gitbutler/ui/Badge.svelte';
|
||||||
import Icon from '@gitbutler/ui/Icon.svelte';
|
import Icon from '@gitbutler/ui/Icon.svelte';
|
||||||
import { tooltip } from '@gitbutler/ui/utils/tooltip';
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
@ -38,12 +38,13 @@
|
|||||||
{#if !isNavCollapsed}
|
{#if !isNavCollapsed}
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="button-head">
|
<div class="button-head">
|
||||||
<span
|
<Tooltip text="The branch your Workspace branches are based on and merge into.">
|
||||||
use:tooltip={'The branch that your Workspace virtual branches are based on and will be merged into.'}
|
<span class="text-14 text-semibold trunk-label">Target</span>
|
||||||
class="text-14 text-semibold trunk-label">Target</span
|
</Tooltip>
|
||||||
>
|
|
||||||
{#if ($base?.behind || 0) > 0}
|
{#if ($base?.behind || 0) > 0}
|
||||||
<Badge label={$base?.behind || 0} help="Unmerged upstream commits" />
|
<Tooltip text="Unmerged upstream commits">
|
||||||
|
<Badge label={$base?.behind || 0} />
|
||||||
|
</Tooltip>
|
||||||
{/if}
|
{/if}
|
||||||
<SyncButton />
|
<SyncButton />
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
export let loading = false;
|
export let loading = false;
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
export let wide = false;
|
export let wide = false;
|
||||||
export let help = '';
|
export let tooltip = '';
|
||||||
|
|
||||||
function persistedAction(projectId: string): Persisted<MergeMethod> {
|
function persistedAction(projectId: string): Persisted<MergeMethod> {
|
||||||
const key = 'projectMergeMethod';
|
const key = 'projectMergeMethod';
|
||||||
@ -35,7 +35,7 @@
|
|||||||
{loading}
|
{loading}
|
||||||
bind:this={dropDown}
|
bind:this={dropDown}
|
||||||
{wide}
|
{wide}
|
||||||
{help}
|
{tooltip}
|
||||||
{disabled}
|
{disabled}
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
dispatch('click', { method: $action });
|
dispatch('click', { method: $action });
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
type Props = {
|
type Props = {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
help: string;
|
tooltip: string;
|
||||||
click: (opts: { draft: boolean }) => void;
|
click: (opts: { draft: boolean }) => void;
|
||||||
};
|
};
|
||||||
const { loading, disabled, help, click }: Props = $props();
|
const { loading, disabled, tooltip, click }: Props = $props();
|
||||||
|
|
||||||
const preferredAction = persisted<Action>(Action.Create, 'projectDefaultPrAction');
|
const preferredAction = persisted<Action>(Action.Create, 'projectDefaultPrAction');
|
||||||
let dropDown: DropDownButton;
|
let dropDown: DropDownButton;
|
||||||
@ -38,7 +38,7 @@
|
|||||||
<DropDownButton
|
<DropDownButton
|
||||||
style="ghost"
|
style="ghost"
|
||||||
outline
|
outline
|
||||||
{help}
|
{tooltip}
|
||||||
{disabled}
|
{disabled}
|
||||||
{loading}
|
{loading}
|
||||||
bind:this={dropDown}
|
bind:this={dropDown}
|
||||||
|
@ -169,7 +169,7 @@
|
|||||||
style="ghost"
|
style="ghost"
|
||||||
outline
|
outline
|
||||||
loading={$mrLoading || $checksLoading}
|
loading={$mrLoading || $checksLoading}
|
||||||
help={$timeAgo ? 'Updated ' + $timeAgo : ''}
|
tooltip={$timeAgo ? 'Updated ' + $timeAgo : ''}
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
$checksMonitor?.update();
|
$checksMonitor?.update();
|
||||||
$prMonitor?.refresh();
|
$prMonitor?.refresh();
|
||||||
@ -231,7 +231,7 @@
|
|||||||
!$pr.mergeable ||
|
!$pr.mergeable ||
|
||||||
['dirty', 'unknown', 'blocked', 'behind'].includes($pr.mergeableState)}
|
['dirty', 'unknown', 'blocked', 'behind'].includes($pr.mergeableState)}
|
||||||
loading={isMerging}
|
loading={isMerging}
|
||||||
help="Merge pull request and refresh"
|
tooltip="Merge pull request and refresh"
|
||||||
on:click={async (e) => {
|
on:click={async (e) => {
|
||||||
if (!$pr) return;
|
if (!$pr) return;
|
||||||
isMerging = true;
|
isMerging = true;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import ContextMenu from '$lib/components/contextmenu/ContextMenu.svelte';
|
import ContextMenu from '$lib/components/contextmenu/ContextMenu.svelte';
|
||||||
import Button from '@gitbutler/ui/Button.svelte';
|
import Button from '@gitbutler/ui/Button.svelte';
|
||||||
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import type iconsJson from '@gitbutler/ui/data/icons.json';
|
import type iconsJson from '@gitbutler/ui/data/icons.json';
|
||||||
import type { ComponentColor, ComponentStyleKind } from '@gitbutler/ui/utils/colorTypes';
|
import type { ComponentColor, ComponentStyleKind } from '@gitbutler/ui/utils/colorTypes';
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
@ -13,7 +14,7 @@
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
wide?: boolean;
|
wide?: boolean;
|
||||||
help?: string;
|
tooltip?: string;
|
||||||
menuPosition?: 'top' | 'bottom';
|
menuPosition?: 'top' | 'bottom';
|
||||||
children: Snippet;
|
children: Snippet;
|
||||||
contextMenuSlot: Snippet;
|
contextMenuSlot: Snippet;
|
||||||
@ -28,7 +29,7 @@
|
|||||||
disabled = false,
|
disabled = false,
|
||||||
loading = false,
|
loading = false,
|
||||||
wide = false,
|
wide = false,
|
||||||
help = '',
|
tooltip,
|
||||||
menuPosition = 'bottom',
|
menuPosition = 'bottom',
|
||||||
children,
|
children,
|
||||||
contextMenuSlot,
|
contextMenuSlot,
|
||||||
@ -50,17 +51,17 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Tooltip text={tooltip}>
|
||||||
<div class="dropdown-wrapper" class:wide>
|
<div class="dropdown-wrapper" class:wide>
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<Button
|
<Button
|
||||||
{style}
|
{style}
|
||||||
{icon}
|
{icon}
|
||||||
{kind}
|
{kind}
|
||||||
{help}
|
|
||||||
{outline}
|
{outline}
|
||||||
reversedDirection
|
reversedDirection
|
||||||
disabled={disabled || loading}
|
disabled={disabled || loading}
|
||||||
isDropdownChild
|
dropdownChild
|
||||||
{onclick}
|
{onclick}
|
||||||
>
|
>
|
||||||
{@render children()}
|
{@render children()}
|
||||||
@ -69,12 +70,11 @@
|
|||||||
bind:el={iconEl}
|
bind:el={iconEl}
|
||||||
{style}
|
{style}
|
||||||
{kind}
|
{kind}
|
||||||
{help}
|
|
||||||
{outline}
|
{outline}
|
||||||
icon={visible ? 'chevron-up' : 'chevron-down'}
|
icon={visible ? 'chevron-up' : 'chevron-down'}
|
||||||
{loading}
|
{loading}
|
||||||
disabled={disabled || loading}
|
disabled={disabled || loading}
|
||||||
isDropdownChild
|
dropdownChild
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
visible = !visible;
|
visible = !visible;
|
||||||
contextMenu?.toggle();
|
contextMenu?.toggle();
|
||||||
@ -92,6 +92,7 @@
|
|||||||
{@render contextMenuSlot()}
|
{@render contextMenuSlot()}
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
.dropdown-wrapper {
|
.dropdown-wrapper {
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { tooltip } from '@gitbutler/ui/utils/tooltip';
|
|
||||||
|
|
||||||
export let small = false;
|
export let small = false;
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
export let checked = false;
|
export let checked = false;
|
||||||
export let value = '';
|
export let value = '';
|
||||||
export let help = '';
|
|
||||||
export let id = '';
|
export let id = '';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -18,7 +15,6 @@
|
|||||||
{value}
|
{value}
|
||||||
{id}
|
{id}
|
||||||
{disabled}
|
{disabled}
|
||||||
use:tooltip={help}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
import { pxToRem } from '@gitbutler/ui/utils/pxToRem';
|
|
||||||
import { sineInOut } from 'svelte/easing';
|
|
||||||
import { slide, type SlideParams, type TransitionConfig } from 'svelte/transition';
|
|
||||||
|
|
||||||
export function slideFade(node: Element, options: SlideParams): TransitionConfig {
|
|
||||||
const slideTrans: TransitionConfig = slide(node, options);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...slideTrans,
|
|
||||||
css: (t, u) =>
|
|
||||||
`${slideTrans.css ? slideTrans.css(t, u) : ''}
|
|
||||||
opacity:${t};`
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// extend SlideParams with opacity
|
|
||||||
type SlideFadeParams = SlideParams & {
|
|
||||||
opacity?: number;
|
|
||||||
minHeight?: number;
|
|
||||||
animateTopPadding?: boolean;
|
|
||||||
animateBottomPadding?: boolean;
|
|
||||||
animateLeftPadding?: boolean;
|
|
||||||
animateRightPadding?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function slideFadeExt(node: Element, options: SlideFadeParams): TransitionConfig {
|
|
||||||
const slideTrans: TransitionConfig = slide(node, options);
|
|
||||||
|
|
||||||
const currentHeight = node.clientHeight;
|
|
||||||
const minHeight = options.minHeight || 0;
|
|
||||||
|
|
||||||
const currentPadding = {
|
|
||||||
top: pxToRem(+getComputedStyle(node).paddingTop),
|
|
||||||
bottom: pxToRem(+getComputedStyle(node).paddingBottom),
|
|
||||||
left: pxToRem(+getComputedStyle(node).paddingLeft),
|
|
||||||
right: pxToRem(+getComputedStyle(node).paddingRight)
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
...slideTrans,
|
|
||||||
easing: sineInOut,
|
|
||||||
css: (t) =>
|
|
||||||
`height: ${minHeight + (currentHeight - minHeight) * Math.min(Math.max(t, 0), 1)}px;
|
|
||||||
opacity:${t};
|
|
||||||
padding-top: ${options.animateTopPadding ? 0 : currentPadding.top};
|
|
||||||
padding-bottom: ${options.animateBottomPadding ? 0 : currentPadding.bottom};
|
|
||||||
padding-left: ${options.animateLeftPadding ? 0 : currentPadding.left};
|
|
||||||
padding-right: ${options.animateRightPadding ? 0 : currentPadding.right};
|
|
||||||
`
|
|
||||||
};
|
|
||||||
}
|
|
@ -17,7 +17,7 @@
|
|||||||
"package:svelte": "svelte-kit sync && svelte-package",
|
"package:svelte": "svelte-kit sync && svelte-package",
|
||||||
"package:styles": "postcss ./src/styles/main.css -o ./dist/styles/main.css && pnpm run copy-fonts",
|
"package:styles": "postcss ./src/styles/main.css -o ./dist/styles/main.css && pnpm run copy-fonts",
|
||||||
"copy-fonts": "postcss ./src/styles/fonts.css -o ./dist/styles/fonts.css && cpy './src/styles/fonts/**/*.woff2' './dist/styles/fonts' --parents",
|
"copy-fonts": "postcss ./src/styles/fonts.css -o ./dist/styles/fonts.css && cpy './src/styles/fonts/**/*.woff2' './dist/styles/fonts' --parents",
|
||||||
"design-tokens:build": "npx tz build && prettier --write ./src/lib/design-tokens.json ./src/styles/core/design-tokens.css",
|
"design-tokens:build": "npx tz build && prettier --write ./src/lib/data/design-tokens.json ./src/styles/core/design-tokens.css",
|
||||||
"prepublishOnly": "pnpm run package",
|
"prepublishOnly": "pnpm run package",
|
||||||
"prepare": "svelte-kit sync",
|
"prepare": "svelte-kit sync",
|
||||||
"storybook": "storybook dev --no-open -p 6006",
|
"storybook": "storybook dev --no-open -p 6006",
|
||||||
|
@ -3,18 +3,16 @@
|
|||||||
|
|
||||||
export interface BadgeProps {
|
export interface BadgeProps {
|
||||||
label: string | number;
|
label: string | number;
|
||||||
help?: string;
|
|
||||||
style?: ComponentColor;
|
style?: ComponentColor;
|
||||||
kind?: ComponentStyleKind;
|
kind?: ComponentStyleKind;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { tooltip } from '$lib/utils/tooltip';
|
const { label, style = 'neutral', kind = 'solid' }: BadgeProps = $props();
|
||||||
let { label, help, style = 'neutral', kind = 'solid' }: BadgeProps = $props();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="badge {style} {kind} text-10 text-semibold" use:tooltip={help}>
|
<div class="badge {style} {kind} text-10 text-semibold">
|
||||||
{label}
|
{label}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
import type { ComponentColor, ComponentStyleKind } from '$lib/utils/colorTypes';
|
|
||||||
|
|
||||||
export interface ButtonProps {
|
export interface ButtonProps {
|
||||||
el?: HTMLElement;
|
el?: HTMLElement;
|
||||||
// Interaction props
|
// Interaction props
|
||||||
@ -18,7 +16,7 @@
|
|||||||
wide?: boolean;
|
wide?: boolean;
|
||||||
grow?: boolean;
|
grow?: boolean;
|
||||||
align?: 'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline' | 'auto';
|
align?: 'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline' | 'auto';
|
||||||
isDropdownChild?: boolean;
|
dropdownChild?: boolean;
|
||||||
// Style props
|
// Style props
|
||||||
style?: ComponentColor;
|
style?: ComponentColor;
|
||||||
kind?: ComponentStyleKind;
|
kind?: ComponentStyleKind;
|
||||||
@ -27,7 +25,9 @@
|
|||||||
solidBackground?: boolean;
|
solidBackground?: boolean;
|
||||||
// Additional elements
|
// Additional elements
|
||||||
icon?: keyof typeof iconsJson | undefined;
|
icon?: keyof typeof iconsJson | undefined;
|
||||||
help?: string;
|
tooltip?: string;
|
||||||
|
tooltipPosition?: TooltipPosition;
|
||||||
|
tooltipAlign?: TooltipAlign;
|
||||||
helpShowDelay?: number;
|
helpShowDelay?: number;
|
||||||
testId?: string;
|
testId?: string;
|
||||||
// Events
|
// Events
|
||||||
@ -41,10 +41,11 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import Tooltip, { type TooltipAlign, type TooltipPosition } from './Tooltip.svelte';
|
||||||
import Icon from '$lib/Icon.svelte';
|
import Icon from '$lib/Icon.svelte';
|
||||||
import { pxToRem } from '$lib/utils/pxToRem';
|
import { pxToRem } from '$lib/utils/pxToRem';
|
||||||
import { tooltip } from '$lib/utils/tooltip';
|
|
||||||
import type iconsJson from '$lib/data/icons.json';
|
import type iconsJson from '$lib/data/icons.json';
|
||||||
|
import type { ComponentColor, ComponentStyleKind } from '$lib/utils/colorTypes';
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
@ -62,7 +63,7 @@
|
|||||||
wide = false,
|
wide = false,
|
||||||
grow = false,
|
grow = false,
|
||||||
align = 'auto',
|
align = 'auto',
|
||||||
isDropdownChild = false,
|
dropdownChild = false,
|
||||||
style = 'neutral',
|
style = 'neutral',
|
||||||
kind = 'soft',
|
kind = 'soft',
|
||||||
outline = false,
|
outline = false,
|
||||||
@ -70,8 +71,9 @@
|
|||||||
solidBackground = false,
|
solidBackground = false,
|
||||||
testId,
|
testId,
|
||||||
icon,
|
icon,
|
||||||
help = '',
|
tooltip,
|
||||||
helpShowDelay = 1200,
|
tooltipPosition,
|
||||||
|
tooltipAlign,
|
||||||
onclick,
|
onclick,
|
||||||
onmousedown,
|
onmousedown,
|
||||||
oncontextmenu,
|
oncontextmenu,
|
||||||
@ -89,6 +91,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Tooltip text={tooltip} align={tooltipAlign} position={tooltipPosition}>
|
||||||
<button
|
<button
|
||||||
bind:this={el}
|
bind:this={el}
|
||||||
class="btn focus-state {style} {kind} {size}-size"
|
class="btn focus-state {style} {kind} {size}-size"
|
||||||
@ -99,15 +102,11 @@
|
|||||||
class:shrinkable
|
class:shrinkable
|
||||||
class:wide
|
class:wide
|
||||||
class:grow
|
class:grow
|
||||||
|
class:is-dropdown={dropdownChild}
|
||||||
class:not-clickable={!clickable}
|
class:not-clickable={!clickable}
|
||||||
class:fixed-width={!children && !wide}
|
class:fixed-width={!children && !wide}
|
||||||
class:is-dropdown={isDropdownChild}
|
|
||||||
style:align-self={align}
|
style:align-self={align}
|
||||||
style:width={width ? pxToRem(width) : undefined}
|
style:width={width ? pxToRem(width) : undefined}
|
||||||
use:tooltip={{
|
|
||||||
text: help,
|
|
||||||
delay: helpShowDelay
|
|
||||||
}}
|
|
||||||
disabled={disabled || loading}
|
disabled={disabled || loading}
|
||||||
onclick={handleAction}
|
onclick={handleAction}
|
||||||
{onmousedown}
|
{onmousedown}
|
||||||
@ -138,6 +137,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
.btn {
|
.btn {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Icon from '$lib/Icon.svelte';
|
import Icon from '$lib/Icon.svelte';
|
||||||
import TimeAgo from '$lib/TimeAgo.svelte';
|
import TimeAgo from '$lib/TimeAgo.svelte';
|
||||||
import { tooltip } from '$lib/utils/tooltip';
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import { onMount, type Snippet } from 'svelte';
|
import { onMount, type Snippet } from 'svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -55,8 +55,6 @@
|
|||||||
observer.disconnect();
|
observer.disconnect();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const tooltipDelay = 500;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button class="branch" class:selected onmousedown={onMouseDown} bind:this={intersectionTarget}>
|
<button class="branch" class:selected onmousedown={onMouseDown} bind:this={intersectionTarget}>
|
||||||
@ -84,8 +82,8 @@
|
|||||||
|
|
||||||
<div class="row-group">
|
<div class="row-group">
|
||||||
{#if pullRequestDetails}
|
{#if pullRequestDetails}
|
||||||
|
<Tooltip text={pullRequestDetails.title}>
|
||||||
<div
|
<div
|
||||||
use:tooltip={{ text: pullRequestDetails.title, delay: tooltipDelay }}
|
|
||||||
class="branch-tag tag-pr"
|
class="branch-tag tag-pr"
|
||||||
class:tag-pr={!pullRequestDetails.draft}
|
class:tag-pr={!pullRequestDetails.draft}
|
||||||
class:tag-draft-pr={pullRequestDetails.draft}
|
class:tag-draft-pr={pullRequestDetails.draft}
|
||||||
@ -95,6 +93,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<Icon name="pr-small" />
|
<Icon name="pr-small" />
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
{/if}
|
{/if}
|
||||||
{#if applied}
|
{#if applied}
|
||||||
<div class="branch-tag tag-applied">
|
<div class="branch-tag tag-applied">
|
||||||
@ -106,15 +105,14 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{#if lastCommitDetails?.lastCommitAt}
|
{#if lastCommitDetails?.lastCommitAt}
|
||||||
<span
|
<Tooltip text={lastCommitDetails.lastCommitAt.toLocaleString('en-GB')}>
|
||||||
class="branch-time text-11 details truncate"
|
<span class="branch-time text-11 details truncate">
|
||||||
use:tooltip={lastCommitDetails.lastCommitAt.toLocaleString('en-GB')}
|
|
||||||
>
|
|
||||||
{#if lastCommitDetails}
|
{#if lastCommitDetails}
|
||||||
<TimeAgo date={lastCommitDetails.lastCommitAt} addSuffix />
|
<TimeAgo date={lastCommitDetails.lastCommitAt} addSuffix />
|
||||||
by {lastCommitDetails.authorName}
|
by {lastCommitDetails.authorName}
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
</Tooltip>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="branch-time text-11 details truncate">
|
<span class="branch-time text-11 details truncate">
|
||||||
{#if lastCommitDetails}
|
{#if lastCommitDetails}
|
||||||
@ -125,24 +123,15 @@
|
|||||||
|
|
||||||
<div class="stats">
|
<div class="stats">
|
||||||
{#if branchDetails}
|
{#if branchDetails}
|
||||||
<div
|
<Tooltip text="Code changes">
|
||||||
use:tooltip={{
|
<div class="code-changes">
|
||||||
text: 'Code changes',
|
|
||||||
delay: tooltipDelay
|
|
||||||
}}
|
|
||||||
class="code-changes"
|
|
||||||
>
|
|
||||||
<span class="text-10 text-semibold">+{branchDetails.linesAdded}</span>
|
<span class="text-10 text-semibold">+{branchDetails.linesAdded}</span>
|
||||||
<span class="text-10 text-semibold">-{branchDetails.linesRemoved}</span>
|
<span class="text-10 text-semibold">-{branchDetails.linesRemoved}</span>
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<div
|
<Tooltip text="Number of commits">
|
||||||
use:tooltip={{
|
<div class="branch-tag tag-commits">
|
||||||
text: 'Number of commits',
|
|
||||||
delay: tooltipDelay
|
|
||||||
}}
|
|
||||||
class="branch-tag tag-commits"
|
|
||||||
>
|
|
||||||
<svg
|
<svg
|
||||||
width="12"
|
width="12"
|
||||||
height="8"
|
height="8"
|
||||||
@ -157,6 +146,7 @@
|
|||||||
|
|
||||||
<span class="text-10 text-semibold">{branchDetails.commitCount}</span>
|
<span class="text-10 text-semibold">{branchDetails.commitCount}</span>
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
142
packages/ui/src/lib/Tooltip.svelte
Normal file
142
packages/ui/src/lib/Tooltip.svelte
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<script lang="ts" context="module">
|
||||||
|
export type TooltipPosition = 'top' | 'bottom';
|
||||||
|
export type TooltipAlign = 'start' | 'center' | 'end';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { portal } from '$lib/utils/portal';
|
||||||
|
import { flyScale } from '$lib/utils/transitions';
|
||||||
|
import { type Snippet } from 'svelte';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
text?: string;
|
||||||
|
delay?: number;
|
||||||
|
align?: TooltipAlign;
|
||||||
|
position?: TooltipPosition;
|
||||||
|
children: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { text, delay = 700, align = 'center', position = 'bottom', children }: Props = $props();
|
||||||
|
|
||||||
|
let targetEl: HTMLElement | undefined = $state();
|
||||||
|
let tooltipEl: HTMLElement | undefined = $state();
|
||||||
|
|
||||||
|
let show = $state(false);
|
||||||
|
let timeoutId: undefined | ReturnType<typeof setTimeout> = $state();
|
||||||
|
|
||||||
|
const isTextEmpty = $derived(!text || text === '');
|
||||||
|
|
||||||
|
function handleMouseEnter() {
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
show = true;
|
||||||
|
// console.log('showing tooltip');
|
||||||
|
}, delay); // 500ms delay before showing the tooltip
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMouseLeave() {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
show = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function adjustPosition() {
|
||||||
|
if (!targetEl || !tooltipEl) return;
|
||||||
|
|
||||||
|
const tooltipRect = tooltipEl.getBoundingClientRect();
|
||||||
|
// get first child of targetEl
|
||||||
|
const targetChild = targetEl.children[0];
|
||||||
|
const targetRect = targetChild.getBoundingClientRect();
|
||||||
|
|
||||||
|
let top = 0;
|
||||||
|
let left = 0;
|
||||||
|
let transformOriginTop = 'center';
|
||||||
|
let transformOriginLeft = 'center';
|
||||||
|
const gap = 4;
|
||||||
|
|
||||||
|
if (position === 'bottom') {
|
||||||
|
top = targetRect.bottom + window.scrollY + gap;
|
||||||
|
|
||||||
|
transformOriginTop = 'top';
|
||||||
|
} else if (position === 'top') {
|
||||||
|
top = targetRect.top - tooltipRect.height + window.scrollY - gap;
|
||||||
|
|
||||||
|
transformOriginTop = 'bottom';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (align === 'start') {
|
||||||
|
left = targetRect.left + window.scrollX;
|
||||||
|
transformOriginLeft = 'left';
|
||||||
|
} else if (align === 'end') {
|
||||||
|
left = targetRect.right - tooltipRect.width + window.scrollX;
|
||||||
|
transformOriginLeft = 'right';
|
||||||
|
} else if (align === 'center') {
|
||||||
|
left = targetRect.left + targetRect.width / 2 - tooltipRect.width / 2 + window.scrollX;
|
||||||
|
transformOriginLeft = 'center';
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltipEl.style.top = `${top}px`;
|
||||||
|
tooltipEl.style.left = `${left}px`;
|
||||||
|
tooltipEl.style.transformOrigin = `${transformOriginTop} ${transformOriginLeft}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (tooltipEl) {
|
||||||
|
adjustPosition();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if isTextEmpty}
|
||||||
|
{@render children()}
|
||||||
|
{:else}
|
||||||
|
<span
|
||||||
|
bind:this={targetEl}
|
||||||
|
class="tooltip-wrap"
|
||||||
|
role="tooltip"
|
||||||
|
onmouseenter={handleMouseEnter}
|
||||||
|
onmouseleave={handleMouseLeave}
|
||||||
|
>
|
||||||
|
{#if children}
|
||||||
|
{@render children()}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if show}
|
||||||
|
<div
|
||||||
|
bind:this={tooltipEl}
|
||||||
|
use:portal={'body'}
|
||||||
|
class="tooltip-container text-11 text-body"
|
||||||
|
transition:flyScale={{
|
||||||
|
position: position
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{text}</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style lang="postcss">
|
||||||
|
.tooltip-wrap {
|
||||||
|
position: relative;
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-container {
|
||||||
|
white-space: pre-line;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
position: fixed;
|
||||||
|
pointer-events: none;
|
||||||
|
background-color: var(--clr-tooltip-bg);
|
||||||
|
border: 1px solid var(--clr-tooltip-border);
|
||||||
|
border-radius: var(--radius-m);
|
||||||
|
color: var(--clr-core-ntrl-80);
|
||||||
|
display: inline-block;
|
||||||
|
width: fit-content;
|
||||||
|
max-width: 240px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
z-index: var(--z-blocker);
|
||||||
|
text-align: left;
|
||||||
|
box-shadow: var(--fx-shadow-s);
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import Tooltip from '$lib/Tooltip.svelte';
|
||||||
import { stringToColor } from '$lib/utils/stringToColor';
|
import { stringToColor } from '$lib/utils/stringToColor';
|
||||||
import { tooltip as tooltipComponent } from '$lib/utils/tooltip';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
srcUrl: string;
|
srcUrl: string;
|
||||||
@ -13,6 +13,7 @@
|
|||||||
const { srcUrl, tooltip, size = 'small' }: Props = $props();
|
const { srcUrl, tooltip, size = 'small' }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Tooltip text={tooltip}>
|
||||||
<div class="image-wrapper {size}" style:background-color={stringToColor(tooltip)}>
|
<div class="image-wrapper {size}" style:background-color={stringToColor(tooltip)}>
|
||||||
<img
|
<img
|
||||||
class="avatar"
|
class="avatar"
|
||||||
@ -21,12 +22,9 @@
|
|||||||
loading="lazy"
|
loading="lazy"
|
||||||
onload={() => (isLoaded = true)}
|
onload={() => (isLoaded = true)}
|
||||||
class:show={isLoaded}
|
class:show={isLoaded}
|
||||||
use:tooltipComponent={{
|
|
||||||
text: tooltip,
|
|
||||||
delay: 500
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
.image-wrapper {
|
.image-wrapper {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Avatar from './Avatar.svelte';
|
import Avatar from './Avatar.svelte';
|
||||||
import { tooltip } from '$lib/utils/tooltip';
|
import Tooltip from '$lib/Tooltip.svelte';
|
||||||
|
|
||||||
const { avatars, maxAvatars = 5 }: Props = $props();
|
const { avatars, maxAvatars = 5 }: Props = $props();
|
||||||
|
|
||||||
@ -43,15 +43,11 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{#if avatars.length > maxAvatars}
|
{#if avatars.length > maxAvatars}
|
||||||
<div
|
<Tooltip text={getTooltipText() || 'mr. unknown'}>
|
||||||
class="avatars-counter"
|
<div class="avatars-counter">
|
||||||
use:tooltip={{
|
|
||||||
text: getTooltipText() || 'mr. unknown',
|
|
||||||
delay: 500
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span class="text-11 text-semibold">+{avatars.length - maxAvatars}</span>
|
<span class="text-11 text-semibold">+{avatars.length - maxAvatars}</span>
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import Tooltip from '$lib/Tooltip.svelte';
|
||||||
import Avatar from '$lib/avatar/Avatar.svelte';
|
import Avatar from '$lib/avatar/Avatar.svelte';
|
||||||
import { tooltip } from '$lib/utils/tooltip';
|
|
||||||
import { isDefined } from '$lib/utils/typeguards';
|
import { isDefined } from '$lib/utils/typeguards';
|
||||||
import type { CommitNodeData, Color } from '$lib/commitLines/types';
|
import type { CommitNodeData, Color } from '$lib/commitLines/types';
|
||||||
|
|
||||||
@ -37,7 +37,9 @@
|
|||||||
<Avatar srcUrl={commitNode.commit?.author.gravatarUrl ?? ''} tooltip={hoverText} />
|
<Avatar srcUrl={commitNode.commit?.author.gravatarUrl ?? ''} tooltip={hoverText} />
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="small-node" use:tooltip={hoverText}></div>
|
<Tooltip text={hoverText}>
|
||||||
|
<div class="small-node"></div>
|
||||||
|
</Tooltip>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -795,7 +795,7 @@
|
|||||||
},
|
},
|
||||||
"30": {
|
"30": {
|
||||||
"$type": "color",
|
"$type": "color",
|
||||||
"$value": "#2a7e57",
|
"$value": "#287b55",
|
||||||
"$description": "",
|
"$description": "",
|
||||||
"$extensions": {
|
"$extensions": {
|
||||||
"mode": {},
|
"mode": {},
|
||||||
@ -811,7 +811,7 @@
|
|||||||
},
|
},
|
||||||
"40": {
|
"40": {
|
||||||
"$type": "color",
|
"$type": "color",
|
||||||
"$value": "#469b73",
|
"$value": "#3c9a6f",
|
||||||
"$description": "",
|
"$description": "",
|
||||||
"$extensions": {
|
"$extensions": {
|
||||||
"mode": {},
|
"mode": {},
|
||||||
@ -827,7 +827,7 @@
|
|||||||
},
|
},
|
||||||
"50": {
|
"50": {
|
||||||
"$type": "color",
|
"$type": "color",
|
||||||
"$value": "#4eb182",
|
"$value": "#4ab582",
|
||||||
"$description": "",
|
"$description": "",
|
||||||
"$extensions": {
|
"$extensions": {
|
||||||
"mode": {},
|
"mode": {},
|
||||||
@ -843,7 +843,7 @@
|
|||||||
},
|
},
|
||||||
"60": {
|
"60": {
|
||||||
"$type": "color",
|
"$type": "color",
|
||||||
"$value": "#a1ceb9",
|
"$value": "#92ddba",
|
||||||
"$description": "",
|
"$description": "",
|
||||||
"$extensions": {
|
"$extensions": {
|
||||||
"mode": {},
|
"mode": {},
|
||||||
@ -859,7 +859,7 @@
|
|||||||
},
|
},
|
||||||
"70": {
|
"70": {
|
||||||
"$type": "color",
|
"$type": "color",
|
||||||
"$value": "#cae8da",
|
"$value": "#bef4da",
|
||||||
"$description": "",
|
"$description": "",
|
||||||
"$extensions": {
|
"$extensions": {
|
||||||
"mode": {},
|
"mode": {},
|
||||||
@ -875,7 +875,7 @@
|
|||||||
},
|
},
|
||||||
"80": {
|
"80": {
|
||||||
"$type": "color",
|
"$type": "color",
|
||||||
"$value": "#d6f0e4",
|
"$value": "#d0f7e5",
|
||||||
"$description": "",
|
"$description": "",
|
||||||
"$extensions": {
|
"$extensions": {
|
||||||
"mode": {},
|
"mode": {},
|
||||||
@ -891,7 +891,7 @@
|
|||||||
},
|
},
|
||||||
"90": {
|
"90": {
|
||||||
"$type": "color",
|
"$type": "color",
|
||||||
"$value": "#e8f7f0",
|
"$value": "#e5faf0",
|
||||||
"$description": "",
|
"$description": "",
|
||||||
"$extensions": {
|
"$extensions": {
|
||||||
"mode": {},
|
"mode": {},
|
||||||
@ -3921,6 +3921,46 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"border": {
|
||||||
|
"$type": "color",
|
||||||
|
"$value": "{clr-core.ntrl.10}",
|
||||||
|
"$description": "",
|
||||||
|
"$extensions": {
|
||||||
|
"mode": {
|
||||||
|
"light": "{clr-core.ntrl.10}",
|
||||||
|
"dark": "{clr-core.ntrl.30}"
|
||||||
|
},
|
||||||
|
"figma": {
|
||||||
|
"variableId": "VariableID:4330:3683",
|
||||||
|
"collection": {
|
||||||
|
"id": "VariableCollectionId:8:1868",
|
||||||
|
"name": "clr",
|
||||||
|
"defaultModeId": "8:5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bg": {
|
||||||
|
"$type": "color",
|
||||||
|
"$value": "{clr-core.ntrl.10}",
|
||||||
|
"$description": "",
|
||||||
|
"$extensions": {
|
||||||
|
"mode": {
|
||||||
|
"light": "{clr-core.ntrl.10}",
|
||||||
|
"dark": "{clr-core.ntrl.10}"
|
||||||
|
},
|
||||||
|
"figma": {
|
||||||
|
"variableId": "VariableID:4330:3697",
|
||||||
|
"collection": {
|
||||||
|
"id": "VariableCollectionId:8:1868",
|
||||||
|
"name": "clr",
|
||||||
|
"defaultModeId": "8:5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"size": {
|
"size": {
|
||||||
@ -4097,7 +4137,7 @@
|
|||||||
"useDTCGKeys": true,
|
"useDTCGKeys": true,
|
||||||
"colorMode": "hex",
|
"colorMode": "hex",
|
||||||
"variableCollections": ["clr-core", "clr", "size", "radius"],
|
"variableCollections": ["clr-core", "clr", "size", "radius"],
|
||||||
"createdAt": "2024-08-10T21:58:58.533Z"
|
"createdAt": "2024-08-31T23:16:13.487Z"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
import Checkbox from '$lib/Checkbox.svelte';
|
import Checkbox from '$lib/Checkbox.svelte';
|
||||||
import Icon from '$lib/Icon.svelte';
|
import Icon from '$lib/Icon.svelte';
|
||||||
import FileIcon from '$lib/file/FileIcon.svelte';
|
import FileIcon from '$lib/file/FileIcon.svelte';
|
||||||
import { tooltip } from '$lib/utils/tooltip';
|
import Tooltip from '@gitbutler/ui/Tooltip.svelte';
|
||||||
import type { FileStatus } from './types';
|
import type { FileStatus } from './types';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -95,9 +95,11 @@
|
|||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
{#if locked}
|
{#if locked}
|
||||||
<div class="locked" use:tooltip={{ text: lockText ?? '', delay: 500 }}>
|
<Tooltip text={lockText}>
|
||||||
|
<div class="locked">
|
||||||
<Icon name="locked-small" color="warning" />
|
<Icon name="locked-small" color="warning" />
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if conflicted}
|
{#if conflicted}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { tooltip } from '$lib/utils/tooltip';
|
|
||||||
import { getContext, onMount } from 'svelte';
|
import { getContext, onMount } from 'svelte';
|
||||||
import type { SegmentContext } from './segmentTypes';
|
import type { SegmentContext } from './segmentTypes';
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
@ -8,11 +7,10 @@
|
|||||||
id: string;
|
id: string;
|
||||||
onselect?: (id: string) => void;
|
onselect?: (id: string) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
tooltipText?: string;
|
|
||||||
children: Snippet;
|
children: Snippet;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id, onselect, children, tooltipText, disabled = false }: SegmentProps = $props();
|
const { id, onselect, children, disabled = false }: SegmentProps = $props();
|
||||||
|
|
||||||
const context = getContext<SegmentContext>('SegmentControl');
|
const context = getContext<SegmentContext>('SegmentControl');
|
||||||
const index = context.setIndex();
|
const index = context.setIndex();
|
||||||
@ -63,10 +61,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
use:tooltip={{
|
|
||||||
text: tooltipText ? tooltipText : '',
|
|
||||||
delay: 1000
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<span class="text-12 label">
|
<span class="text-12 label">
|
||||||
{@render children()}
|
{@render children()}
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
export interface ToolTipOptions {
|
|
||||||
text: string;
|
|
||||||
noMaxWidth?: boolean;
|
|
||||||
delay?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultOptions: Partial<ToolTipOptions> = {
|
|
||||||
delay: 1200,
|
|
||||||
noMaxWidth: false
|
|
||||||
};
|
|
||||||
|
|
||||||
export function tooltip(node: HTMLElement, optsOrString: ToolTipOptions | string | undefined) {
|
|
||||||
// The tooltip element we are adding to the dom
|
|
||||||
let tooltip: HTMLDivElement | undefined;
|
|
||||||
|
|
||||||
// Note that we use this both for delaying show, as well as delaying hide
|
|
||||||
let timeoutId: any;
|
|
||||||
|
|
||||||
// Options
|
|
||||||
let { text, delay, noMaxWidth } = defaultOptions;
|
|
||||||
|
|
||||||
// Most use cases only involve passing a string, so we allow either opts of
|
|
||||||
// simple text.
|
|
||||||
function setOpts(opts: ToolTipOptions | string | undefined) {
|
|
||||||
if (typeof opts === 'string') {
|
|
||||||
text = opts;
|
|
||||||
} else if (opts) {
|
|
||||||
({ text, delay, noMaxWidth } = opts || {});
|
|
||||||
}
|
|
||||||
if (tooltip && text) tooltip.innerText = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
setOpts(optsOrString);
|
|
||||||
|
|
||||||
function onPointerEnter() {
|
|
||||||
// If tooltip is displayed we clear hide timeout
|
|
||||||
if (tooltip && timeoutId) clearTimeout(timeoutId);
|
|
||||||
// If no tooltip and no timeout id we set a show timeout
|
|
||||||
else if (!tooltip && !timeoutId) timeoutId = setTimeout(() => show(), delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onPointerLeave() {
|
|
||||||
// If tooltip shown when mouse out then we hide after delay
|
|
||||||
if (tooltip) hide();
|
|
||||||
// But if we mouse out before tooltip is shown, we cancel the show timer
|
|
||||||
else if (timeoutId) {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
timeoutId = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function show() {
|
|
||||||
if (!text || !node.isConnected) return;
|
|
||||||
tooltip = document.createElement('div') as HTMLDivElement;
|
|
||||||
// TODO: Can we co-locate tooltip.js & tooltip.postcss?
|
|
||||||
tooltip.classList.add('tooltip', 'text-11'); // see tooltip.postcss
|
|
||||||
if (noMaxWidth) tooltip.classList.add('no-max-width');
|
|
||||||
tooltip.innerText = text;
|
|
||||||
document.body.appendChild(tooltip);
|
|
||||||
adjustPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
function hide() {
|
|
||||||
if (tooltip) tooltip.remove();
|
|
||||||
tooltip = undefined;
|
|
||||||
timeoutId = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function adjustPosition() {
|
|
||||||
if (!tooltip) return;
|
|
||||||
|
|
||||||
// Dimensions and position of target element
|
|
||||||
const nodeRect = node.getBoundingClientRect();
|
|
||||||
const nodeHeight = nodeRect.height;
|
|
||||||
const nodeWidth = nodeRect.width;
|
|
||||||
const nodeLeft = nodeRect.left;
|
|
||||||
const nodeTop = nodeRect.top;
|
|
||||||
|
|
||||||
// Padding
|
|
||||||
const padding = 4;
|
|
||||||
|
|
||||||
// Window dimensions
|
|
||||||
const windowHeight = window.innerHeight;
|
|
||||||
const windowWidth = window.innerWidth;
|
|
||||||
|
|
||||||
const tooltipHeight = tooltip.offsetHeight;
|
|
||||||
const tooltipWidth = tooltip.offsetWidth;
|
|
||||||
|
|
||||||
const showBelow = windowHeight > nodeTop + nodeHeight + tooltipHeight + padding;
|
|
||||||
|
|
||||||
// Note that we don't check if width of tooltip is wider than the window.
|
|
||||||
|
|
||||||
if (showBelow) {
|
|
||||||
tooltip.style.top = `${nodeTop + nodeHeight + padding}px`;
|
|
||||||
} else {
|
|
||||||
tooltip.style.top = `${nodeTop - tooltipHeight - padding}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
let leftPos = nodeLeft - (tooltipWidth - nodeWidth) / 2;
|
|
||||||
if (leftPos < padding) leftPos = padding;
|
|
||||||
if (leftPos + tooltipWidth > windowWidth) leftPos = windowWidth - tooltipWidth - padding;
|
|
||||||
tooltip.style.left = `${leftPos}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
node.addEventListener('pointerenter', onPointerEnter);
|
|
||||||
node.addEventListener('pointerleave', onPointerLeave);
|
|
||||||
|
|
||||||
return {
|
|
||||||
update(opts: ToolTipOptions | string | undefined) {
|
|
||||||
setOpts(opts);
|
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
tooltip?.remove();
|
|
||||||
timeoutId && clearTimeout(timeoutId);
|
|
||||||
node.removeEventListener('pointerenter', onPointerEnter);
|
|
||||||
node.removeEventListener('pointerleave', onPointerLeave);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
52
packages/ui/src/lib/utils/transitions.ts
Normal file
52
packages/ui/src/lib/utils/transitions.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { pxToRem } from './pxToRem';
|
||||||
|
import { cubicOut } from 'svelte/easing';
|
||||||
|
import { slide, type SlideParams, type TransitionConfig } from 'svelte/transition';
|
||||||
|
|
||||||
|
export function slideFade(node: Element, options: SlideParams): TransitionConfig {
|
||||||
|
const slideTrans: TransitionConfig = slide(node, options);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...slideTrans,
|
||||||
|
css: (t, u) =>
|
||||||
|
`${slideTrans.css ? slideTrans.css(t, u) : ''}
|
||||||
|
opacity:${t};`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function flyScale(
|
||||||
|
_: Element,
|
||||||
|
params: {
|
||||||
|
y?: number;
|
||||||
|
x?: number;
|
||||||
|
start?: number;
|
||||||
|
duration?: number;
|
||||||
|
position?: 'top' | 'bottom';
|
||||||
|
} = {}
|
||||||
|
): TransitionConfig {
|
||||||
|
// Default values
|
||||||
|
const DEFAULT_Y = -6;
|
||||||
|
const DEFAULT_X = 0;
|
||||||
|
const DEFAULT_SCALE_START = 0.94;
|
||||||
|
const DEFAULT_DURATION = 200;
|
||||||
|
const DEFAULT_POSITION = 'top';
|
||||||
|
|
||||||
|
// Extracting and using default values
|
||||||
|
const y = params.y ?? DEFAULT_Y;
|
||||||
|
const x = params.x ?? DEFAULT_X;
|
||||||
|
const startScale = params.start ?? DEFAULT_SCALE_START;
|
||||||
|
const duration = params.duration ?? DEFAULT_DURATION;
|
||||||
|
const position = params.position ?? DEFAULT_POSITION;
|
||||||
|
|
||||||
|
return {
|
||||||
|
duration,
|
||||||
|
css: (t) => {
|
||||||
|
const translateY = y * (1 - t);
|
||||||
|
const translateX = x * (1 - t);
|
||||||
|
const scale = startScale + t * (1 - startScale);
|
||||||
|
|
||||||
|
return `transform: translate3d(${pxToRem(translateX)}, ${pxToRem(position === 'top' ? -translateY : translateY)}, 0) scale(${scale});
|
||||||
|
opacity: ${t};`;
|
||||||
|
},
|
||||||
|
easing: cubicOut
|
||||||
|
};
|
||||||
|
}
|
@ -13,7 +13,6 @@ export const BadgeStory: Story = {
|
|||||||
name: 'Badge',
|
name: 'Badge',
|
||||||
args: {
|
args: {
|
||||||
label: '127',
|
label: '127',
|
||||||
help: 'This is a badge',
|
|
||||||
style: 'neutral',
|
style: 'neutral',
|
||||||
kind: 'solid'
|
kind: 'solid'
|
||||||
},
|
},
|
||||||
|
@ -23,7 +23,6 @@ export const ButtonDefault: Story = {
|
|||||||
outline: false,
|
outline: false,
|
||||||
dashed: false,
|
dashed: false,
|
||||||
solidBackground: false,
|
solidBackground: false,
|
||||||
help: '',
|
|
||||||
helpShowDelay: 1200,
|
helpShowDelay: 1200,
|
||||||
id: 'button',
|
id: 'button',
|
||||||
tabindex: 0,
|
tabindex: 0,
|
||||||
@ -34,7 +33,7 @@ export const ButtonDefault: Story = {
|
|||||||
wide: false,
|
wide: false,
|
||||||
grow: false,
|
grow: false,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
isDropdownChild: false,
|
dropdownChild: false,
|
||||||
onclick: () => {
|
onclick: () => {
|
||||||
console.log('Button clicked');
|
console.log('Button clicked');
|
||||||
}
|
}
|
||||||
@ -60,9 +59,16 @@ export const ButtonClickable: Story = {
|
|||||||
name: 'Not clickable + tooltip',
|
name: 'Not clickable + tooltip',
|
||||||
args: {
|
args: {
|
||||||
clickable: false,
|
clickable: false,
|
||||||
help: 'This button is not clickable',
|
tooltip: 'This button is not clickable',
|
||||||
|
tooltipAlign: 'start',
|
||||||
onclick: () => {
|
onclick: () => {
|
||||||
console.log('Button clicked');
|
console.log('Button clicked');
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
tooltipAlign: {
|
||||||
|
control: 'select',
|
||||||
|
options: ['start', 'center', 'end']
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,8 @@ const meta = {
|
|||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<typeof meta>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const ModalStory: Story = {
|
export const DefaultStory: Story = {
|
||||||
|
name: 'Modal',
|
||||||
args: {
|
args: {
|
||||||
width: 'small',
|
width: 'small',
|
||||||
title: 'This is a fantastic modal :D'
|
title: 'This is a fantastic modal :D'
|
||||||
|
30
packages/ui/src/stories/tooltip/DemoTooltip.svelte
Normal file
30
packages/ui/src/stories/tooltip/DemoTooltip.svelte
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Tooltip from '$lib/Tooltip.svelte';
|
||||||
|
|
||||||
|
const props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
<p class="text-13 text">
|
||||||
|
hello world! Here is a <Tooltip text={props.text}>
|
||||||
|
<span class="tooltip-text">tooltip</span>
|
||||||
|
</Tooltip> for you.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: var(--clr-text-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-text {
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-style: dotted;
|
||||||
|
}
|
||||||
|
</style>
|
30
packages/ui/src/stories/tooltip/Tooltip.stories.ts
Normal file
30
packages/ui/src/stories/tooltip/Tooltip.stories.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import DemoTooltip from './DemoTooltip.svelte';
|
||||||
|
import type { Meta, StoryObj } from '@storybook/svelte';
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: 'Overlays / Tooltip',
|
||||||
|
component: DemoTooltip
|
||||||
|
} satisfies Meta<DemoTooltip>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
|
export const DefaultStory: Story = {
|
||||||
|
name: 'Tooltip',
|
||||||
|
args: {
|
||||||
|
position: 'bottom',
|
||||||
|
align: 'center',
|
||||||
|
delay: 500,
|
||||||
|
text: 'This is a fantastic tooltip :D'
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
position: {
|
||||||
|
control: 'select',
|
||||||
|
options: ['top', 'bottom']
|
||||||
|
},
|
||||||
|
align: {
|
||||||
|
control: 'select',
|
||||||
|
options: ['start', 'center', 'end']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -1,33 +0,0 @@
|
|||||||
.tooltip {
|
|
||||||
pointer-events: none;
|
|
||||||
background-color: var(--clr-core-ntrl-10);
|
|
||||||
border-radius: var(--radius-s);
|
|
||||||
border: 1px solid var(--clr-core-ntrl-30);
|
|
||||||
color: var(--clr-core-ntrl-60);
|
|
||||||
display: inline-block;
|
|
||||||
padding: 6px 8px;
|
|
||||||
z-index: var(--z-blocker);
|
|
||||||
|
|
||||||
max-width: 180px;
|
|
||||||
position: absolute;
|
|
||||||
left: -9999px;
|
|
||||||
top: -9999px;
|
|
||||||
|
|
||||||
opacity: 0;
|
|
||||||
animation: showup-tooltip-animation 0.1s ease-out forwards;
|
|
||||||
|
|
||||||
&.no-max-width {
|
|
||||||
max-width: unset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes showup-tooltip-animation {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-0.2rem) scale(0.9);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0) scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -52,13 +52,13 @@
|
|||||||
--clr-core-succ-5: color(srgb 0.050980392156862744 0.14901960784313725 0.10196078431372549);
|
--clr-core-succ-5: color(srgb 0.050980392156862744 0.14901960784313725 0.10196078431372549);
|
||||||
--clr-core-succ-10: color(srgb 0.10980392156862745 0.25098039215686274 0.1843137254901961);
|
--clr-core-succ-10: color(srgb 0.10980392156862745 0.25098039215686274 0.1843137254901961);
|
||||||
--clr-core-succ-20: color(srgb 0.13333333333333333 0.3254901960784314 0.23529411764705882);
|
--clr-core-succ-20: color(srgb 0.13333333333333333 0.3254901960784314 0.23529411764705882);
|
||||||
--clr-core-succ-30: color(srgb 0.16470588235294117 0.49411764705882355 0.3411764705882353);
|
--clr-core-succ-30: color(srgb 0.1568627450980392 0.4823529411764706 0.3333333333333333);
|
||||||
--clr-core-succ-40: color(srgb 0.27450980392156865 0.6078431372549019 0.45098039215686275);
|
--clr-core-succ-40: color(srgb 0.23529411764705882 0.6039215686274509 0.43529411764705883);
|
||||||
--clr-core-succ-50: color(srgb 0.3058823529411765 0.6941176470588235 0.5098039215686274);
|
--clr-core-succ-50: color(srgb 0.2901960784313726 0.7098039215686275 0.5098039215686274);
|
||||||
--clr-core-succ-60: color(srgb 0.6313725490196078 0.807843137254902 0.7254901960784313);
|
--clr-core-succ-60: color(srgb 0.5725490196078431 0.8666666666666667 0.7294117647058823);
|
||||||
--clr-core-succ-70: color(srgb 0.792156862745098 0.9098039215686274 0.8549019607843137);
|
--clr-core-succ-70: color(srgb 0.7450980392156863 0.9568627450980393 0.8549019607843137);
|
||||||
--clr-core-succ-80: color(srgb 0.8392156862745098 0.9411764705882353 0.8941176470588236);
|
--clr-core-succ-80: color(srgb 0.8156862745098039 0.9686274509803922 0.8980392156862745);
|
||||||
--clr-core-succ-90: color(srgb 0.9098039215686274 0.9686274509803922 0.9411764705882353);
|
--clr-core-succ-90: color(srgb 0.8980392156862745 0.9803921568627451 0.9411764705882353);
|
||||||
--clr-core-succ-95: color(srgb 0.9647058823529412 0.9882352941176471 0.984313725490196);
|
--clr-core-succ-95: color(srgb 0.9647058823529412 0.9882352941176471 0.984313725490196);
|
||||||
--clr-core-purp-5: color(srgb 0.1568627450980392 0.11372549019607843 0.26666666666666666);
|
--clr-core-purp-5: color(srgb 0.1568627450980392 0.11372549019607843 0.26666666666666666);
|
||||||
--clr-core-purp-10: color(srgb 0.24705882352941178 0.17254901960784313 0.40784313725490196);
|
--clr-core-purp-10: color(srgb 0.24705882352941178 0.17254901960784313 0.40784313725490196);
|
||||||
@ -235,6 +235,8 @@
|
|||||||
srgb 0.5294117647058824 0.6588235294117647 0.6039215686274509
|
srgb 0.5294117647058824 0.6588235294117647 0.6039215686274509
|
||||||
);
|
);
|
||||||
--clr-diff-addition-line-bg: color(srgb 0.8784313725490196 0.984313725490196 0.9411764705882353);
|
--clr-diff-addition-line-bg: color(srgb 0.8784313725490196 0.984313725490196 0.9411764705882353);
|
||||||
|
--clr-tooltip-border: var(--clr-core-ntrl-10);
|
||||||
|
--clr-tooltip-bg: var(--clr-core-ntrl-10);
|
||||||
--size-icon: 1rem;
|
--size-icon: 1rem;
|
||||||
--size-tag: 1.375rem;
|
--size-tag: 1.375rem;
|
||||||
--size-button: 1.75rem;
|
--size-button: 1.75rem;
|
||||||
@ -419,6 +421,8 @@
|
|||||||
--clr-diff-addition-line-bg: color(
|
--clr-diff-addition-line-bg: color(
|
||||||
srgb 0.054901960784313725 0.1843137254901961 0.1450980392156863
|
srgb 0.054901960784313725 0.1843137254901961 0.1450980392156863
|
||||||
);
|
);
|
||||||
|
--clr-tooltip-border: var(--clr-core-ntrl-30);
|
||||||
|
--clr-tooltip-bg: var(--clr-core-ntrl-10);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-clr1 {
|
.bg-clr1 {
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
/* COMPONENTS */
|
/* COMPONENTS */
|
||||||
@import './components/diff.css';
|
@import './components/diff.css';
|
||||||
@import './components/tooltip.css';
|
|
||||||
@import './components/text-input.css';
|
@import './components/text-input.css';
|
||||||
@import './components/commit-lines.css';
|
@import './components/commit-lines.css';
|
||||||
@import './components/draggable.css';
|
@import './components/draggable.css';
|
||||||
|
@ -14,7 +14,7 @@ function clearFxPrefix(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
tokens: './src/lib/design-tokens.json',
|
tokens: './src/lib/data/design-tokens.json',
|
||||||
outDir: './src/styles/core',
|
outDir: './src/styles/core',
|
||||||
plugins: [
|
plugins: [
|
||||||
css({
|
css({
|
||||||
|
Loading…
Reference in New Issue
Block a user