diff --git a/src/components/repo.tsx b/src/components/repo.tsx index 276893a..f9d5f90 100644 --- a/src/components/repo.tsx +++ b/src/components/repo.tsx @@ -39,6 +39,7 @@ export const RepoTabLink: Component<{ icon: JSX.Element; label: string; meta?: string; + reserveMeta?: boolean; }> = (props) => (
{props.icon} {props.label} - - - {props.meta} + + + {props.meta ?? '0'} @@ -67,43 +74,120 @@ const prFileTreeSkeletonRows = Array.from({ length: 8 }); const prDiffFileSkeletons = Array.from({ length: 2 }); const prDiffCodeLines = Array.from({ length: 8 }); -export const RepoTreeSkeleton: Component = () => ( -
-
- -
- - - -
-
- - {(_, index) => ( -
-
- - -
- +export const RepoLanguageBarSkeleton: Component = () => ( + +); + +const TreeRowsSkeleton: Component = () => ( +
+ + {(_, index) => ( +
+
+ + +
+ +
+ )} +
+
+); + +const RepoOverviewSidebarSkeleton: Component = () => ( +
+
+ + + +
+
+ + {(_, index) => ( +
+ +
+ + +
- )} - -
+
+ )} +
-
-
- +
+
+ + +
-
- - - - +
+ +
); +export const RepoTreeSkeleton: Component<{ nested?: boolean }> = (props) => ( + <> +
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+
+ + + + +
+ +
+
+
+ +
+
+ +
+ + + +
+
+
+
+ + +
+
+
+ + + + +
+
+
+ +); + export const RepoBlobSkeleton: Component = () => (
@@ -156,6 +240,66 @@ export const RepoListSkeleton: Component<{ kind: 'issues' | 'pulls' }> = (props)
); +export const RepoListPageSkeleton: Component<{ + kind: 'issues' | 'pulls'; + showCreate?: boolean; +}> = (props) => ( + <> +
+
+
+ + + + + +
+ + + + +
+
+
+ +
+ +); + +export const RepoFormSkeleton: Component<{ titleWidth?: string }> = (props) => ( +
+
+ + + + +
+
+); + +export const PullComposeSkeleton: Component = () => ( +
+
+ + {(_, index) => ( +
+
+ + +
+
+ + +
+
+ )} +
+
+
+); + const IssueThreadSkeleton: Component = () => (
@@ -382,39 +526,43 @@ export const RepoThreadSkeleton: Component<{ kind: 'issue' | 'pull' }> = (props) ); -export const RepoFrameSkeleton: Component<{ active: 'code' | 'issues' | 'pulls' }> = (props) => ( +const defaultRepoFrameSkeletonContent = (active: 'code' | 'issues' | 'pulls') => + active === 'code' ? : ; + +export const RepoFrameSkeleton: Component<{ + active: 'code' | 'issues' | 'pulls'; + children?: JSX.Element; +}> = (props) => ( <> -
-
-
-
+
+
+
+
-
- - -
-
- - +
+
+ + +
-
- }> - - -
+ {props.children ?? defaultRepoFrameSkeletonContent(props.active)}
); diff --git a/src/index.css b/src/index.css index 79d35e9..5933558 100644 --- a/src/index.css +++ b/src/index.css @@ -861,6 +861,17 @@ pre { list-style: none; } +.untangled-language-bar-loading { + cursor: default; + pointer-events: none; +} + +.untangled-language-bar-skeleton { + width: 100%; + height: 100%; + border-radius: 0.25rem 0.25rem 0 0; +} + .untangled-language-bar::-webkit-details-marker { display: none; } @@ -1399,6 +1410,7 @@ details[open] > .untangled-language-bar { .untangled-repo-action-main { gap: 0.5rem; + min-width: 4.75rem; padding: 0 0.75rem; flex: 1 1 auto; justify-content: center; @@ -1426,6 +1438,8 @@ details[open] > .untangled-language-bar { .untangled-repo-action-count { border-left: 1px solid rgb(209 213 219); background: rgb(249 250 251); + justify-content: center; + min-width: 2.5rem; padding: 0 0.75rem; position: relative; text-decoration: none; @@ -1440,6 +1454,16 @@ details[open] > .untangled-language-bar { min-width: 80px; } +.untangled-repo-tab-meta { + display: inline-flex; + justify-content: center; + min-width: 1.25rem; +} + +.untangled-repo-tab-meta-placeholder { + visibility: hidden; +} + .group:hover .untangled-repo-tab-idle { background: rgb(243 244 246 / 0.25); } diff --git a/src/pages/repo/code.tsx b/src/pages/repo/code.tsx index a1274b9..6fb2634 100644 --- a/src/pages/repo/code.tsx +++ b/src/pages/repo/code.tsx @@ -5,7 +5,7 @@ import { createQuery, keepPreviousData, useQueryClient } from '@tanstack/solid-q import { For, Match, Show, Switch, createEffect, createMemo, createSignal, type Component } from 'solid-js'; import { buildBlobDataUrl, decodeBlobText, getRepoBlob, getRepoBranches, getRepoDefaultBranch, getRepoLanguages, getRepoLog, getRepoTags, getRepoTree } from '../../lib/api/repos'; import { Avatar, ErrorState, PlaceholderAvatar, buttonStyles, cardStyles } from '../../components/common'; -import { CloneDropdown, CodeView, FileRow, MarkdownBlock, OverviewFileRow, ReadmeCard, RepoTreeSkeleton } from '../../components/repo'; +import { CloneDropdown, CodeView, FileRow, MarkdownBlock, OverviewFileRow, ReadmeCard, RepoBlobSkeleton, RepoLanguageBarSkeleton, RepoTreeSkeleton } from '../../components/repo'; import { RepoFrame, useRepoQuery } from './shared'; import { blobHref, commitHref, commitsHref, countLines, decodeRoutePath, formatBytes, formatLanguagePercent, formatRelativeTime, getErrorMessage, getParentPath, imageLike, isDirectory, joinPath, languageColor, markdownLike, safeDecode, sortedTreeEntries, svgLike, treeHref, videoLike } from '../../lib/repo-utils'; import { LOADING_DELAY_MS, hasNamedRef, normalizeLanguages, resolveDefaultBranchName, resolveRouteRefAndPath, shouldAnimateNavigation, useDelayedLoading } from './code-helpers'; @@ -117,8 +117,9 @@ const TreeLatestCommitPanel: Component<{ const RepoLanguageBar: Component<{ languages: Array<{ name: string; percentage: number; color?: string }>; + loading?: boolean; }> = (props) => ( - 0}> + 0} fallback={}>
@@ -228,10 +229,10 @@ const RepoCodePageLegacy: Component = () => { }); return ( - + }> - +
@@ -513,6 +514,7 @@ export const RepoCodePage: Component = () => { const overviewReady = createMemo(() => Boolean(repoQuery.data && treeQuery.data && branchesQuery.data && tagsQuery.data && logQuery.data), ); + const languagesLoading = createMemo(() => !languagesQuery.data && (languagesQuery.isLoading || languagesQuery.isFetching)); const showOverviewSkeleton = useDelayedLoading(() => !overviewReady() && !overviewError()); createEffect(() => { @@ -553,10 +555,10 @@ export const RepoCodePage: Component = () => { }; return ( - + }> - +
@@ -584,7 +586,7 @@ export const RepoCodePage: Component = () => { return ( <>
- +
@@ -860,7 +862,7 @@ export const BlobPage: Component = () => { }); return ( - + }> diff --git a/src/pages/repo/commits.tsx b/src/pages/repo/commits.tsx index d36d850..23a1599 100644 --- a/src/pages/repo/commits.tsx +++ b/src/pages/repo/commits.tsx @@ -503,7 +503,15 @@ export const CommitsPage: Component = () => { }); return ( - + +

commits

+ +
+ } + >

commits

@@ -715,7 +723,7 @@ export const CommitPage: Component = () => { const patch = createMemo(() => renderUnifiedDiff(commitQuery.data?.diff)); return ( - + }> diff --git a/src/pages/repo/issues.tsx b/src/pages/repo/issues.tsx index 14c99c6..77a5fa2 100644 --- a/src/pages/repo/issues.tsx +++ b/src/pages/repo/issues.tsx @@ -10,7 +10,7 @@ import { parseAtUri } from '../../lib/api/records'; import type { RepoContext } from '../../lib/api/repos'; import { useAuth } from '../../lib/auth'; import { Avatar, ErrorState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, inputStyles, textareaStyles } from '../../components/common'; -import { AtUriPanel, MarkdownBlock, RepoListSkeleton, RepoThreadSkeleton } from '../../components/repo'; +import { AtUriPanel, MarkdownBlock, RepoFormSkeleton, RepoListPageSkeleton, RepoListSkeleton, RepoThreadSkeleton } from '../../components/repo'; import { RepoFrame, issueQueryKey, issuesQueryKey, useRepoQuery } from './shared'; import { REPO_LIST_PAGE_LIMIT, formatRelativeTime, getErrorMessage, issueHref, parseIntegerSearchParam, uniqueCommenters } from '../../lib/repo-utils'; import { buildIssueCommentThreads, buildIssueFilterQuery, parseIssueFilter } from './issues-helpers'; @@ -83,7 +83,7 @@ export const IssuesPage: Component = () => { const paginated = createMemo(() => issuesQuery.data?.items ?? []); return ( - + }>
@@ -239,7 +239,7 @@ export const NewIssuePage: Component = () => { }; return ( - + }>

new issue

@@ -422,7 +422,7 @@ export const IssuePage: Component = () => { }; return ( - + }> diff --git a/src/pages/repo/pulls.tsx b/src/pages/repo/pulls.tsx index cae8e42..41e4545 100644 --- a/src/pages/repo/pulls.tsx +++ b/src/pages/repo/pulls.tsx @@ -24,7 +24,7 @@ import { parseAtUri } from '../../lib/api/records'; import { compareBranches, getRepoBranches, type RepoContext } from '../../lib/api/repos'; import { useAuth } from '../../lib/auth'; import { Avatar, ErrorState, LoadingState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, textareaStyles } from '../../components/common'; -import { AtUriPanel, BranchPill, CommentCard, DiffView, MarkdownBlock, PullDiffSkeleton, PullDiffView, RepoListSkeleton, RepoThreadSkeleton } from '../../components/repo'; +import { AtUriPanel, BranchPill, CommentCard, DiffView, MarkdownBlock, PullComposeSkeleton, PullDiffSkeleton, PullDiffView, RepoListPageSkeleton, RepoListSkeleton, RepoThreadSkeleton } from '../../components/repo'; import { RepoFrame, pullQueryKey, pullsQueryKey, useRepoQuery } from './shared'; import { REPO_LIST_PAGE_LIMIT, formatRelativeTime, getErrorMessage, parseIntegerSearchParam, pullHref, uniqueCommenters } from '../../lib/repo-utils'; import { buildPullFilterQuery, parsePastedPatchPrefill, parsePullFilter, type PullSourceMode } from './pulls-helpers'; @@ -97,7 +97,7 @@ export const PullsPage: Component = () => { const paginated = createMemo(() => pullsQuery.data?.items ?? []); return ( - + }>
@@ -359,7 +359,7 @@ export const NewPullPage: Component = () => { }; return ( - + }>
@@ -973,7 +973,7 @@ export const PullPage: Component = () => { }); return ( - + }> diff --git a/src/pages/repo/shared.tsx b/src/pages/repo/shared.tsx index dff224e..75cec0a 100644 --- a/src/pages/repo/shared.tsx +++ b/src/pages/repo/shared.tsx @@ -55,6 +55,7 @@ export const RepoFrame: Component<{ active: 'code' | 'issues' | 'pulls'; children: JSX.Element; fullWidth?: boolean; + loadingFallback?: JSX.Element; }> = (props) => { const auth = useAuth(); const live = useLiveEvents(); @@ -197,7 +198,7 @@ export const RepoFrame: Component<{
- + {props.loadingFallback}
@@ -358,6 +359,7 @@ export const RepoFrame: Component<{ icon={} label="issues" meta={issueCountQuery.data === undefined ? undefined : String(issueCountQuery.data)} + reserveMeta /> } label="pulls" meta={pullCountQuery.data === undefined ? undefined : String(pullCountQuery.data)} + reserveMeta />