diff --git a/src/webviews/apps/plus/home/components/branch-card.ts b/src/webviews/apps/plus/home/components/branch-card.ts index ce32e68c504ae..55f8ac3d29998 100644 --- a/src/webviews/apps/plus/home/components/branch-card.ts +++ b/src/webviews/apps/plus/home/components/branch-card.ts @@ -19,6 +19,7 @@ import '../../../shared/components/rich/issue-icon'; import '../../../shared/components/rich/pr-icon'; import '../../../shared/components/actions/action-item'; import '../../../shared/components/actions/action-nav'; +import '../../shared/components/branch-icon'; import './merge-target-status'; export const branchCardStyles = css` @@ -335,9 +336,7 @@ export abstract class GlBranchCardBase extends GlElement { >

- - - + ${this.renderBranchIcon()} ${this.branch.name}

@@ -355,6 +354,10 @@ export abstract class GlBranchCardBase extends GlElement { `; } + private renderBranchIcon() { + return html``; + } + protected renderPrItem() { if (!this.branch.pr) return nothing; diff --git a/src/webviews/apps/plus/shared/components/branch-icon.ts b/src/webviews/apps/plus/shared/components/branch-icon.ts new file mode 100644 index 0000000000000..264c9ec6d812a --- /dev/null +++ b/src/webviews/apps/plus/shared/components/branch-icon.ts @@ -0,0 +1,120 @@ +import { css, html, LitElement } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +type StatusType = 'synced' | 'diverged' | 'behind' | 'ahead' | 'changes' | undefined; + +@customElement('gl-branch-icon') +export class GlBranchIcon extends LitElement { + static override styles = css` + :host { + display: inline-flex; + width: 16px; + height: 16px; + + --gl-icon-color-foreground: var(--vscode-foreground, #c5c5c5); + + --gl-icon-color-status-synced: var(--gl-icon-color-foreground); + --gl-icon-color-status-diverged: var(--vscode-gitDecoration-modifiedResourceForeground, #ff5); + --gl-icon-color-status-behind: var(--vscode-gitDecoration-deletedResourceForeground, #f05); + --gl-icon-color-status-ahead: var(--vscode-gitDecoration-addedResourceForeground, #0f5); + --gl-icon-color-status-changes: var(--vscode-gitDecoration-untrackedResourceForeground, #1a79ff); + } + + :host-context(.vscode-dark), + :host-context(.vscode-high-contrast) { + --gl-icon-color-foreground: #c5c5c5; + } + + :host-context(.vscode-light), + :host-context(.vscode-high-contrast-light) { + --gl-icon-color-foreground: #424242; + } + + svg { + width: 100%; + height: 100%; + } + `; + + @property({ type: Object }) + branch!: { state?: { ahead: number; behind: number }; workingTreeState?: boolean; worktree?: boolean }; + + private get status() { + if (!this.branch.state) return undefined; + + let status: StatusType; + if (this.branch.state.behind > 0 && this.branch.state.ahead > 0) { + status = 'diverged'; + } else if (this.branch.state.behind > 0) { + status = 'behind'; + } else if (this.branch.state.ahead > 0) { + status = 'ahead'; + } else if (this.branch.workingTreeState) { + status = 'changes'; + } else { + status = 'synced'; + } + return status; + } + + override render() { + if (!this.branch.state) { + return html``; + } + + const statusColor = this.getStatusCssColor(); + + if (this.branch.worktree) { + return html` + + + + + + `; + } + + return html` + + + `; + } + + private getStatusCssColor(): string { + switch (this.status) { + case 'diverged': + return 'var(--gl-icon-color-status-diverged)'; + case 'behind': + return 'var(--gl-icon-color-status-behind)'; + case 'ahead': + return 'var(--gl-icon-color-status-ahead)'; + case 'changes': + return 'var(--gl-icon-color-status-changes)'; + case 'synced': + default: + return 'var(--gl-icon-color-status-synced)'; + } + } +}