mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-11 08:50:34 +08:00
Style patch tabs
This commit is contained in:
@@ -11,10 +11,12 @@
|
||||
styleHeight?: string;
|
||||
styleMinHeight?: string;
|
||||
styleWidth?: string;
|
||||
styleDisplay?: string;
|
||||
styleCursor?: "default" | "pointer" | "text";
|
||||
styleGap?: string;
|
||||
styleOverflow?: string;
|
||||
flatTop?: boolean;
|
||||
flatBottom?: boolean;
|
||||
styleBackgroundColor?: string;
|
||||
styleFlexDirection?: string;
|
||||
styleAlignItems?: string;
|
||||
@@ -31,10 +33,12 @@
|
||||
styleMinHeight,
|
||||
stylePosition,
|
||||
styleWidth,
|
||||
styleDisplay = "flex",
|
||||
styleCursor = "default",
|
||||
styleGap = "0.5rem",
|
||||
styleOverflow,
|
||||
flatTop = false,
|
||||
flatBottom = false,
|
||||
styleBackgroundColor = "var(--color-background-default)",
|
||||
styleFlexDirection = "row",
|
||||
styleAlignItems = "center",
|
||||
@@ -130,7 +134,6 @@
|
||||
}
|
||||
.p3-3 {
|
||||
grid-area: p3-3;
|
||||
display: flex;
|
||||
background-color: var(--local-background-color);
|
||||
}
|
||||
.p3-4 {
|
||||
@@ -196,6 +199,21 @@
|
||||
.flat-top > .p2-5 {
|
||||
background-color: var(--local-button-color-1);
|
||||
}
|
||||
|
||||
.flat-bottom > .p4-2,
|
||||
.flat-bottom > .p4-4 {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.flat-bottom > .p4-1,
|
||||
.flat-bottom > .p4-5,
|
||||
.flat-bottom > .p5-3,
|
||||
.flat-bottom > .p5-1,
|
||||
.flat-bottom > .p5-2,
|
||||
.flat-bottom > .p5-4,
|
||||
.flat-bottom > .p5-5 {
|
||||
background-color: var(--local-button-color-1);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
@@ -204,6 +222,7 @@
|
||||
style:cursor={styleCursor}
|
||||
class="container"
|
||||
class:flat-top={flatTop}
|
||||
class:flat-bottom={flatBottom}
|
||||
{onclick}
|
||||
role="button"
|
||||
tabindex={onclick !== undefined ? 0 : -1}
|
||||
@@ -226,6 +245,7 @@
|
||||
<div class="p3-2"></div>
|
||||
<div
|
||||
class="p3-3"
|
||||
style:display={styleDisplay}
|
||||
style:position={stylePosition}
|
||||
style:padding={stylePadding}
|
||||
style:gap={styleGap}
|
||||
|
||||
@@ -16,11 +16,15 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.diff:not(:last-of-type) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="diff-list">
|
||||
{#each diff.files as file}
|
||||
<div style:margin-bottom="1rem">
|
||||
<div class="diff">
|
||||
<FileDiff
|
||||
filePath={"path" in file ? file.path : file.newPath}
|
||||
oldFilePath={"oldPath" in file ? file.oldPath : undefined}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
<style>
|
||||
.header {
|
||||
display: flex;
|
||||
height: 3rem;
|
||||
align-items: center;
|
||||
padding: 0 0.5rem 0 1rem;
|
||||
height: 2.5rem;
|
||||
padding-left: 1rem;
|
||||
z-index: 2;
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
@@ -46,6 +46,7 @@
|
||||
.container {
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
z-index: 1;
|
||||
}
|
||||
.container::after {
|
||||
position: absolute;
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
interface Props {
|
||||
children: Snippet;
|
||||
onclick?: () => void;
|
||||
disabled?: boolean;
|
||||
active?: boolean;
|
||||
flatLeft?: boolean;
|
||||
flatRight?: boolean;
|
||||
}
|
||||
|
||||
const {
|
||||
children,
|
||||
onclick = undefined,
|
||||
disabled = false,
|
||||
active = false,
|
||||
flatLeft = false,
|
||||
flatRight = false,
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
white-space: nowrap;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.active {
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-foreground-emphasized);
|
||||
}
|
||||
|
||||
.wrapper.active::after {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
content: " ";
|
||||
background-color: var(--color-fill-secondary);
|
||||
height: 2px;
|
||||
bottom: -4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container.disabled {
|
||||
color: var(--color-foreground-disabled);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div
|
||||
class="container"
|
||||
style:cursor={!disabled ? "pointer" : "default"}
|
||||
class:disabled
|
||||
class:flat-right={flatRight}
|
||||
class:flat-left={flatLeft}
|
||||
onclick={!disabled ? onclick : undefined}
|
||||
role="button"
|
||||
tabindex="0">
|
||||
<div class="wrapper" class:active>
|
||||
{@render children()}
|
||||
</div>
|
||||
</div>
|
||||
+131
-101
@@ -27,7 +27,6 @@
|
||||
|
||||
import AssigneeInput from "@app/components/AssigneeInput.svelte";
|
||||
import Border from "@app/components/Border.svelte";
|
||||
import Button from "@app/components/Button.svelte";
|
||||
import Changeset from "@app/components/Changeset.svelte";
|
||||
import CommentComponent from "@app/components/Comment.svelte";
|
||||
import CopyableId from "@app/components/CopyableId.svelte";
|
||||
@@ -40,6 +39,7 @@
|
||||
import PatchTeaser from "@app/components/PatchTeaser.svelte";
|
||||
import PatchTimeline from "@app/components/PatchTimeline.svelte";
|
||||
import Sidebar from "@app/components/Sidebar.svelte";
|
||||
import Tab from "@app/components/Tab.svelte";
|
||||
import TextInput from "@app/components/TextInput.svelte";
|
||||
|
||||
interface Props {
|
||||
@@ -335,8 +335,9 @@
|
||||
}
|
||||
|
||||
.patch-body {
|
||||
margin: 1rem 0;
|
||||
margin-bottom: 1rem;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
/* We put the background and clip-path in a separate element to prevent
|
||||
popovers being clipped in the main element. */
|
||||
@@ -471,113 +472,142 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<Border variant="ghost" styleGap="0">
|
||||
<div class="metadata-section" style:min-width="8rem">
|
||||
<div class="metadata-section-title">Status</div>
|
||||
<PatchStateBadge state={patch.state} />
|
||||
</div>
|
||||
<div class="global-flex" style:gap="0.5rem">
|
||||
<Border stylePosition="relative" variant="ghost" flatBottom>
|
||||
<div
|
||||
class="global-flex"
|
||||
style:z-index="10"
|
||||
style:gap="1rem"
|
||||
style:padding="0 1rem">
|
||||
<Tab
|
||||
active={tab === "patch"}
|
||||
onclick={() => {
|
||||
tab = "patch";
|
||||
}}>
|
||||
{formatOid(patch.id)}
|
||||
<span
|
||||
class="global-counter"
|
||||
style:height="22px"
|
||||
style:color="var(--color-foreground-contrast)">
|
||||
Initial
|
||||
</span>
|
||||
</Tab>
|
||||
|
||||
<div class="metadata-divider"></div>
|
||||
|
||||
<div class="metadata-section" style:flex="1">
|
||||
<LabelInput
|
||||
allowedToEdit={!!roles.isDelegateOrAuthor(
|
||||
config.publicKey,
|
||||
repo.delegates.map(delegate => delegate.did),
|
||||
patch.author.did,
|
||||
)}
|
||||
labels={patch.labels}
|
||||
submitInProgress={labelSaveInProgress}
|
||||
save={saveLabels} />
|
||||
</div>
|
||||
|
||||
<div class="metadata-divider"></div>
|
||||
|
||||
<div class="metadata-section" style:flex="1">
|
||||
<AssigneeInput
|
||||
allowedToEdit={!!roles.isDelegateOrAuthor(
|
||||
config.publicKey,
|
||||
repo.delegates.map(delegate => delegate.did),
|
||||
patch.author.did,
|
||||
)}
|
||||
assignees={patch.assignees}
|
||||
submitInProgress={assigneesSaveInProgress}
|
||||
save={saveAssignees} />
|
||||
</div>
|
||||
</Border>
|
||||
|
||||
<div class="global-flex" style:gap="0" style:margin-top="1rem">
|
||||
<Button
|
||||
flatRight
|
||||
active={tab === "patch"}
|
||||
variant="ghost"
|
||||
onclick={() => {
|
||||
tab = "patch";
|
||||
}}>
|
||||
Patch
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
flatLeft
|
||||
variant="ghost"
|
||||
active={tab === "revisions"}
|
||||
onclick={() => {
|
||||
tab = "revisions";
|
||||
}}>
|
||||
Revision: {formatOid(revisions.slice(-1)[0].id)}
|
||||
<span class="global-counter" style:height="22px">latest</span>
|
||||
</Button>
|
||||
<Tab
|
||||
active={tab === "revisions"}
|
||||
onclick={() => {
|
||||
tab = "revisions";
|
||||
}}>
|
||||
{formatOid(revisions.slice(-1)[0].id)}
|
||||
<span
|
||||
class="global-counter"
|
||||
style:height="22px"
|
||||
style:color="var(--color-foreground-contrast)">
|
||||
Latest
|
||||
</span>
|
||||
</Tab>
|
||||
</div>
|
||||
</Border>
|
||||
</div>
|
||||
|
||||
{#if tab === "patch"}
|
||||
<div class="txt-small patch-body">
|
||||
<CommentComponent
|
||||
caption="opened"
|
||||
rid={repo.rid}
|
||||
id={patch.id}
|
||||
lastEdit={revisions[0].description.length > 1
|
||||
? revisions[0].description.at(-1)
|
||||
: undefined}
|
||||
author={revisions[0].author}
|
||||
reactions={revisions[0].reactions}
|
||||
timestamp={revisions[0].timestamp}
|
||||
body={revisions[0].description.slice(-1)[0].body}
|
||||
reactOnComment={partial(
|
||||
reactOnRevision,
|
||||
config.publicKey,
|
||||
revisions[0].id,
|
||||
)}
|
||||
editComment={roles.isDelegateOrAuthor(
|
||||
config.publicKey,
|
||||
repo.delegates.map(delegate => delegate.did),
|
||||
revisions[0].author.did,
|
||||
) && partial(editRevision, revisions[0].id)}>
|
||||
</CommentComponent>
|
||||
</div>
|
||||
<Border
|
||||
variant="ghost"
|
||||
flatTop
|
||||
styleWidth="100%"
|
||||
stylePadding="1rem"
|
||||
styleDisplay="block"
|
||||
styleFlexDirection="column"
|
||||
styleAlignItems="flex-start">
|
||||
<div class="txt-small patch-body">
|
||||
<CommentComponent
|
||||
caption="opened"
|
||||
rid={repo.rid}
|
||||
id={patch.id}
|
||||
lastEdit={revisions[0].description.length > 1
|
||||
? revisions[0].description.at(-1)
|
||||
: undefined}
|
||||
author={revisions[0].author}
|
||||
reactions={revisions[0].reactions}
|
||||
timestamp={revisions[0].timestamp}
|
||||
body={revisions[0].description.slice(-1)[0].body}
|
||||
reactOnComment={partial(
|
||||
reactOnRevision,
|
||||
config.publicKey,
|
||||
revisions[0].id,
|
||||
)}
|
||||
editComment={roles.isDelegateOrAuthor(
|
||||
config.publicKey,
|
||||
repo.delegates.map(delegate => delegate.did),
|
||||
revisions[0].author.did,
|
||||
) && partial(editRevision, revisions[0].id)}>
|
||||
</CommentComponent>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="txt-semibold global-flex"
|
||||
style:margin-bottom="1rem"
|
||||
style:cursor="pointer"
|
||||
onclick={() => (hideTimeline = !hideTimeline)}>
|
||||
<Icon
|
||||
name={hideTimeline ? "chevron-right" : "chevron-down"} />Timeline
|
||||
<Border variant="ghost" styleGap="0">
|
||||
<div class="metadata-section" style:min-width="8rem">
|
||||
<div class="metadata-section-title">Status</div>
|
||||
<PatchStateBadge state={patch.state} />
|
||||
</div>
|
||||
|
||||
<div class="metadata-divider"></div>
|
||||
|
||||
<div class="metadata-section" style:flex="1">
|
||||
<LabelInput
|
||||
allowedToEdit={!!roles.isDelegateOrAuthor(
|
||||
config.publicKey,
|
||||
repo.delegates.map(delegate => delegate.did),
|
||||
patch.author.did,
|
||||
)}
|
||||
labels={patch.labels}
|
||||
submitInProgress={labelSaveInProgress}
|
||||
save={saveLabels} />
|
||||
</div>
|
||||
|
||||
<div class="metadata-divider"></div>
|
||||
|
||||
<div class="metadata-section" style:flex="1">
|
||||
<AssigneeInput
|
||||
allowedToEdit={!!roles.isDelegateOrAuthor(
|
||||
config.publicKey,
|
||||
repo.delegates.map(delegate => delegate.did),
|
||||
patch.author.did,
|
||||
)}
|
||||
assignees={patch.assignees}
|
||||
submitInProgress={assigneesSaveInProgress}
|
||||
save={saveAssignees} />
|
||||
</div>
|
||||
</Border>
|
||||
|
||||
<div>
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="txt-semibold global-flex"
|
||||
style:margin="1rem 0"
|
||||
style:cursor="pointer"
|
||||
onclick={() => (hideTimeline = !hideTimeline)}>
|
||||
<Icon
|
||||
name={hideTimeline ? "chevron-right" : "chevron-down"} />Timeline
|
||||
</div>
|
||||
<div class:hide-timeline={hideTimeline}>
|
||||
<PatchTimeline {activity} patchId={patch.id} />
|
||||
</div>
|
||||
</div>
|
||||
<div class:hide-timeline={hideTimeline}>
|
||||
<PatchTimeline {activity} patchId={patch.id} />
|
||||
</div>
|
||||
</div>
|
||||
</Border>
|
||||
{:else}
|
||||
{@const revision = revisions.slice(-1)[0]}
|
||||
{#await loadHighlightedDiff(repo.rid, revision.base, revision.head) then diff}
|
||||
<div style:margin-top="1rem">
|
||||
<Border
|
||||
variant="ghost"
|
||||
flatTop
|
||||
styleDisplay="block"
|
||||
stylePadding="1rem"
|
||||
styleAlignItems="flex-start">
|
||||
{@const revision = revisions.slice(-1)[0]}
|
||||
{#await loadHighlightedDiff(repo.rid, revision.base, revision.head) then diff}
|
||||
<Changeset {diff} repoId={repo.rid} />
|
||||
</div>
|
||||
{/await}
|
||||
{/await}
|
||||
</Border>
|
||||
{/if}
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
Reference in New Issue
Block a user