mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
feat: optimize icons
This commit is contained in:
parent
c558eaf35c
commit
10668b6606
11 changed files with 109 additions and 142 deletions
|
|
@ -1,7 +1,22 @@
|
|||
import {
|
||||
DiffAddedIcon,
|
||||
DiffIgnoredIcon,
|
||||
DiffModifiedIcon,
|
||||
DiffRemovedIcon,
|
||||
DiffRenamedIcon
|
||||
} from '@primer/octicons-react'
|
||||
import * as React from 'react'
|
||||
import { resolveDiffGraphMeta } from 'utils/general'
|
||||
import { Icon } from '../Icon'
|
||||
|
||||
const iconMap = {
|
||||
added: DiffAddedIcon,
|
||||
ignored: DiffIgnoredIcon,
|
||||
modified: DiffModifiedIcon,
|
||||
removed: DiffRemovedIcon,
|
||||
renamed: DiffRenamedIcon,
|
||||
}
|
||||
|
||||
export function DiffStatGraph({
|
||||
diff: { status, changes, additions, deletions },
|
||||
}: {
|
||||
|
|
@ -19,18 +34,7 @@ export function DiffStatGraph({
|
|||
|
||||
return (
|
||||
<span className={'diff-stat-graph'}>
|
||||
<Icon
|
||||
className={status}
|
||||
type={
|
||||
{
|
||||
added: 'diffAdded',
|
||||
ignored: 'diffIgnored',
|
||||
modified: 'diffModified',
|
||||
removed: 'diffRemoved',
|
||||
renamed: 'diffRenamed',
|
||||
}[status]
|
||||
}
|
||||
/>
|
||||
<Icon className={status} IconComponent={iconMap[status]} />
|
||||
{children}
|
||||
</span>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -77,17 +77,18 @@ const NodeItemIcon = React.memo(function NodeItemIcon({
|
|||
() => (node.type === 'tree' ? getFolderIconURL(node, open) : getFileIconURL(node)),
|
||||
[node, open],
|
||||
)
|
||||
const iconType = React.useMemo(() => getIconType(node), [node])
|
||||
|
||||
if (icons === 'native') return <Icon type={getIconType(node)} />
|
||||
if (icons === 'native') return <Icon type={iconType} />
|
||||
return (
|
||||
<>
|
||||
<Icon
|
||||
className={'node-item-type-icon'}
|
||||
placeholder={node.type !== 'tree'}
|
||||
type={loading ? 'loading' : getIconType(node)}
|
||||
type={loading ? 'loading' : iconType}
|
||||
/>
|
||||
{node.type === 'commit' ? (
|
||||
<Icon type={getIconType(node)} />
|
||||
<Icon type={iconType} />
|
||||
) : (
|
||||
<img alt={node.name} className={cx('node-item-icon', { dim: icons === 'dim' })} src={src} />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { CommentIcon } from '@primer/octicons-react'
|
||||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import * as React from 'react'
|
||||
import { isNotFalsy } from 'utils/general'
|
||||
|
|
@ -42,7 +43,7 @@ export function useRenderFileCommentAmounts() {
|
|||
node.comments.active
|
||||
} active, ${node.comments.resolved} resolved`}
|
||||
>
|
||||
<Icon type={'comment'} /> {node.comments.active > 9 ? '9+' : node.comments.active}
|
||||
<Icon IconComponent={CommentIcon} /> {node.comments.active > 9 ? '9+' : node.comments.active}
|
||||
</span>
|
||||
) : null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { GearIcon } from '@primer/octicons-react'
|
||||
import { Link } from '@primer/react'
|
||||
import { Icon } from 'components/Icon'
|
||||
import { VERSION } from 'env'
|
||||
import * as React from 'react'
|
||||
import { wikiLinks } from './SettingsBar'
|
||||
import { RoundIconButton } from './RoundIconButton'
|
||||
import { wikiLinks } from './settings/SettingsBar'
|
||||
|
||||
type Props = {
|
||||
toggleShowSettings: () => void
|
||||
|
|
@ -21,9 +22,12 @@ export function Footer(props: Props) {
|
|||
>
|
||||
{VERSION}
|
||||
</Link>
|
||||
<button className={'settings-button'} onClick={toggleShowSettings}>
|
||||
<Icon type={'gear'} className={'show-settings-icon'} />
|
||||
</button>
|
||||
<RoundIconButton
|
||||
aria-label={'settings'}
|
||||
icon={GearIcon}
|
||||
iconColor="fg.muted"
|
||||
onClick={toggleShowSettings}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -61,14 +61,7 @@ const typeToIconComponentMap: {
|
|||
} = {
|
||||
search: 'Search',
|
||||
loading: 'Clock',
|
||||
hourglass: 'Hourglass',
|
||||
submodule: 'Submodule',
|
||||
grabber: 'Grabber',
|
||||
comment: 'Comment',
|
||||
x: 'X',
|
||||
pin: 'Pin',
|
||||
tab: 'Tab',
|
||||
gear: 'Gear',
|
||||
diff: 'Diff',
|
||||
diffAdded: 'DiffAdded',
|
||||
diffIgnored: 'DiffIgnored',
|
||||
|
|
@ -76,7 +69,6 @@ const typeToIconComponentMap: {
|
|||
diffRemoved: 'DiffRemoved',
|
||||
diffRenamed: 'DiffRenamed',
|
||||
folder: 'ChevronRight',
|
||||
'chevron-down': 'ChevronDown',
|
||||
'go-to': 'Reply',
|
||||
'.zip': 'FileZip',
|
||||
'.rar': 'FileZip',
|
||||
|
|
@ -99,7 +91,9 @@ const typeToIconComponentMap: {
|
|||
}
|
||||
|
||||
type Props = {
|
||||
type: string
|
||||
type?: keyof typeof typeToIconComponentMap
|
||||
name?: keyof typeof iconToComponentMap
|
||||
IconComponent?: React.ComponentType<IconProps>
|
||||
className?: string
|
||||
placeholder?: boolean
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void
|
||||
|
|
@ -107,19 +101,15 @@ type Props = {
|
|||
|
||||
export const Icon = React.memo(function Icon({
|
||||
type,
|
||||
className = undefined,
|
||||
placeholder,
|
||||
className = undefined,
|
||||
name = (type && typeToIconComponentMap[type]) || defaultIcon,
|
||||
IconComponent = iconToComponentMap[name],
|
||||
...otherProps
|
||||
}: Props) {
|
||||
let children: React.ReactNode = null
|
||||
if (!placeholder) {
|
||||
const name = typeToIconComponentMap[type] || defaultIcon
|
||||
const IconComponent = iconToComponentMap[name]
|
||||
children = <IconComponent className={cx('octicon', name)} {...otherProps} />
|
||||
}
|
||||
return (
|
||||
<div className={cx('octicon-wrapper', className)} {...otherProps}>
|
||||
{children}
|
||||
</div>
|
||||
<span className={cx('octicon-wrapper', className)} {...otherProps}>
|
||||
{placeholder ? null : <IconComponent className={cx('octicon', name)} {...otherProps} />}
|
||||
</span>
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Icon } from 'components/Icon'
|
||||
import { HourglassIcon } from '@primer/octicons-react'
|
||||
import * as React from 'react'
|
||||
|
||||
type Props = {
|
||||
|
|
@ -8,7 +8,7 @@ export function LoadingIndicator({ text }: Props) {
|
|||
return (
|
||||
<div className={'loading-indicator-container'}>
|
||||
<div className={'loading-indicator'}>
|
||||
<Icon className={'loading-indicator-icon'} type={'hourglass'} />
|
||||
<HourglassIcon className={'loading-indicator-icon'} />
|
||||
{text}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { GrabberIcon } from '@primer/octicons-react'
|
||||
import { Icon } from 'components/Icon'
|
||||
import * as React from 'react'
|
||||
import { ResizeState, useResizeHandler } from '../utils/hooks/useResizeHandler'
|
||||
|
|
@ -21,7 +22,7 @@ export function ResizeHandler({ onResize, onResetSize, onResizeStateChange, size
|
|||
onDoubleClick={onResetSize}
|
||||
style={style}
|
||||
>
|
||||
<Icon type={'grabber'} className={'grabber-icon'} size={20} />
|
||||
<Icon IconComponent={GrabberIcon} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { PinIcon, TabIcon } from '@primer/octicons-react'
|
||||
import { AccessDeniedDescription } from 'components/AccessDeniedDescription'
|
||||
import { FileExplorer } from 'components/FileExplorer'
|
||||
import { Footer } from 'components/Footer'
|
||||
import { MetaBar } from 'components/MetaBar'
|
||||
import { Portal } from 'components/Portal'
|
||||
import { Footer } from 'components/settings/Footer'
|
||||
import { SideBarBodyWrapper } from 'components/SideBarBodyWrapper'
|
||||
import { ToggleShowButton } from 'components/ToggleShowButton'
|
||||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
|
|
@ -19,8 +20,8 @@ import { RepoContext } from '../containers/RepoContext'
|
|||
import { SideBarStateContext } from '../containers/SideBarState'
|
||||
import { Theme } from '../containers/Theme'
|
||||
import { useToggleSideBarWithKeyboard } from '../utils/hooks/useToggleSideBarWithKeyboard'
|
||||
import { Icon } from './Icon'
|
||||
import { LoadingIndicator } from './LoadingIndicator'
|
||||
import { RoundIconButton } from './RoundIconButton'
|
||||
import { SettingsBarContent } from './settings/SettingsBar'
|
||||
|
||||
export function SideBar() {
|
||||
|
|
@ -151,27 +152,29 @@ export function SideBar() {
|
|||
<div className={'header'}>
|
||||
<div className={'close-side-bar-button-position'}>
|
||||
{sidebarToggleMode === 'persistent' && (
|
||||
<button
|
||||
title={'Collapse sidebar'}
|
||||
className={'close-side-bar-button'}
|
||||
<RoundIconButton
|
||||
icon={TabIcon}
|
||||
aria-label={'Collapse sidebar'}
|
||||
sx={{
|
||||
transform: 'rotateY(180deg)',
|
||||
}}
|
||||
onClick={toggleShowSideBar}
|
||||
>
|
||||
<Icon className={'action-icon'} type={'tab'} />
|
||||
</button>
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
title={'Toggle sidebar dock mode between float and persistent'}
|
||||
className={cx('close-side-bar-button', {
|
||||
active: sidebarToggleMode === 'persistent',
|
||||
})}
|
||||
<RoundIconButton
|
||||
icon={PinIcon}
|
||||
aria-label={'Toggle sidebar dock mode between float and persistent'}
|
||||
iconColor={sidebarToggleMode === 'persistent' ? 'fg.default' : undefined}
|
||||
sx={{
|
||||
transform: 'rotateY(180deg)',
|
||||
}}
|
||||
onClick={() =>
|
||||
configContext.onChange({
|
||||
sidebarToggleMode: sidebarToggleMode === 'float' ? 'persistent' : 'float',
|
||||
sidebarToggleMode:
|
||||
sidebarToggleMode === 'persistent' ? 'float' : 'persistent',
|
||||
})
|
||||
}
|
||||
>
|
||||
<Icon className={'action-icon'} type={'pin'} />
|
||||
</button>
|
||||
/>
|
||||
</div>
|
||||
{metaData && <MetaBar metaData={metaData} />}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { ChevronDownIcon } from '@primer/octicons-react'
|
||||
import { Box } from '@primer/react'
|
||||
import { Icon } from 'components/Icon'
|
||||
import { RoundIconButton } from 'components/RoundIconButton'
|
||||
import { platform } from 'platforms'
|
||||
import { GitHub } from 'platforms/GitHub'
|
||||
import * as React from 'react'
|
||||
|
|
@ -53,9 +54,13 @@ export function SettingsBarContent({ toggleShow }: { toggleShow: () => void }) {
|
|||
<div className={'gitako-settings-bar'}>
|
||||
<div className={'gitako-settings-bar-header'}>
|
||||
<h2 className={'gitako-settings-bar-title'}>Settings</h2>
|
||||
<button className={'settings-button'} onClick={toggleShow}>
|
||||
<Icon type={'chevron-down'} className={'hide-settings-icon'} />
|
||||
</button>
|
||||
<RoundIconButton
|
||||
aria-label="Close settings"
|
||||
onClick={toggleShow}
|
||||
size="medium"
|
||||
icon={ChevronDownIcon}
|
||||
color="fg.default"
|
||||
/>
|
||||
</div>
|
||||
<Box display="grid" gridGap={4} className={'gitako-settings-bar-content'}>
|
||||
<div className={'shadow-shelter'} />
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { InfoIcon, LinkExternalIcon } from '@primer/octicons-react'
|
||||
import { Box } from '@primer/react'
|
||||
import * as React from 'react'
|
||||
import { ConfigKeys } from 'utils/config/helper'
|
||||
import { SimpleConfigField } from '.'
|
||||
|
|
@ -12,14 +14,29 @@ export function FieldLabel<Key extends ConfigKeys>({
|
|||
{label}
|
||||
{(wikiLink || tooltip) && ' '}
|
||||
{wikiLink ? (
|
||||
<a href={wikiLink} title={tooltip} target="_blank" rel="noopener noreferrer">
|
||||
(?)
|
||||
<a
|
||||
className={'help'}
|
||||
href={wikiLink}
|
||||
title={tooltip}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<LinkExternalIcon size="small" />
|
||||
</a>
|
||||
) : (
|
||||
tooltip && (
|
||||
<span className={'help'} title={tooltip}>
|
||||
(?)
|
||||
</span>
|
||||
<Box
|
||||
as="span"
|
||||
sx={{
|
||||
'.octicon': {
|
||||
color: 'fg.subtle',
|
||||
},
|
||||
}}
|
||||
className={'help'}
|
||||
title={tooltip}
|
||||
>
|
||||
<InfoIcon size="small" />
|
||||
</Box>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -220,7 +220,12 @@ $minimal-z-index: max(
|
|||
padding-top: 0;
|
||||
|
||||
.#{$name}-side-bar {
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -409,14 +414,7 @@ $minimal-z-index: max(
|
|||
background: var(--color-bg-subtle);
|
||||
border-left: 1px solid var(--color-border-default);
|
||||
}
|
||||
|
||||
.octicon.Grabber {
|
||||
margin-left: -2px;
|
||||
width: 20px;
|
||||
font-size: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.#{$name}-side-bar-body {
|
||||
$button-size: 32px;
|
||||
position: relative;
|
||||
|
|
@ -426,20 +424,9 @@ $minimal-z-index: max(
|
|||
flex-direction: column;
|
||||
background: var(--color-bg-subtle);
|
||||
border-left: 1px solid var(--color-border-default);
|
||||
|
||||
.octicon {
|
||||
transition: transform 0.3s ease;
|
||||
color: var(--color-fg-subtle);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.octicon-color {
|
||||
color: var(--color-fg-subtle);
|
||||
}
|
||||
|
||||
.octicon-wrapper {
|
||||
display: inline-block;
|
||||
color: var(--color-fg-subtle);
|
||||
width: 16px;
|
||||
min-width: 16px; // prevent shrink when sidebar is narrow
|
||||
text-align: center;
|
||||
|
|
@ -478,41 +465,6 @@ $minimal-z-index: max(
|
|||
.close-side-bar-button-position {
|
||||
float: right;
|
||||
z-index: 1; // prevent being covered by following elements
|
||||
|
||||
.close-side-bar-button {
|
||||
@include icon-button;
|
||||
width: $button-size;
|
||||
height: $button-size;
|
||||
border-radius: $button-size;
|
||||
|
||||
// feedback to click should be instant
|
||||
&:not(:active) {
|
||||
transition: background linear 0.3s;
|
||||
}
|
||||
|
||||
&.active .octicon {
|
||||
color: var(--color-fg-default);
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
color: var(--color-fg-subtle);
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
.octicon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.Pin,
|
||||
.Tab {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.close-side-bar-button + .close-side-bar-button {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -536,11 +488,7 @@ $minimal-z-index: max(
|
|||
height: 20px;
|
||||
margin-right: 4px;
|
||||
|
||||
.octicon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
animation: pulse-rotate 1.8s infinite ease;
|
||||
}
|
||||
animation: pulse-rotate 1.8s infinite ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -755,6 +703,9 @@ $minimal-z-index: max(
|
|||
height: 10px;
|
||||
margin: 0 1px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.diff-stat-graph-no-change {
|
||||
background: var(--color-neutral-emphasis);
|
||||
}
|
||||
|
||||
|
|
@ -861,6 +812,9 @@ $minimal-z-index: max(
|
|||
.hint {
|
||||
color: var(--color-fg-subtle);
|
||||
}
|
||||
.help {
|
||||
cursor: help;
|
||||
}
|
||||
.access-token-input-control {
|
||||
display: flex;
|
||||
.access-token-input {
|
||||
|
|
@ -881,19 +835,6 @@ $minimal-z-index: max(
|
|||
color: var(--color-fg-muted);
|
||||
}
|
||||
}
|
||||
|
||||
.settings-button {
|
||||
@include icon-button();
|
||||
$size: 32px;
|
||||
width: $size;
|
||||
height: $size;
|
||||
border-radius: $size;
|
||||
user-select: none;
|
||||
|
||||
.octicon-wrapper {
|
||||
width: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue