Improve "language stats" UI (#26968)

Before:

* The layout is quite complex 
* The UI flickers when switch the stats (https://try.gitea.io/)

After:

* Simplify the code
* The UI doesn't flicker
This commit is contained in:
wxiaoguang 2023-09-10 18:27:23 +08:00 committed by GitHub
parent a20e0affba
commit dd6e8ab57b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 147 deletions

View file

@ -1,48 +1,44 @@
{{if and (not .HideRepoInfo) (not .IsBlame)}} {{if and (not .HideRepoInfo) (not .IsBlame)}}
<div class="ui segments repository-summary{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo) .LanguageStats}} repository-summary-language-stats{{end}} gt-mt-2 gt-mb-0"> <div class="ui segments repository-summary gt-mt-2 gt-mb-0">
<div class="ui segment sub-menu repository-menu"> <div class="ui segment sub-menu repository-menu">
<div class="ui two horizontal center list"> {{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo)}}
{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo)}} <a class="item muted {{if .PageIsCommits}}active{{end}}" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}">
<div class="item{{if .PageIsCommits}} active{{end}}"> {{svg "octicon-history"}} <b>{{.locale.PrettyNumber .CommitsCount}}</b> {{.locale.TrN .CommitsCount "repo.commit" "repo.commits"}}
<a class="flex-text-inline" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}">{{svg "octicon-history"}} <b>{{.locale.PrettyNumber .CommitsCount}}</b> {{.locale.TrN .CommitsCount "repo.commit" "repo.commits"}}</a> </a>
</div> <a class="item muted {{if .PageIsBranches}}active{{end}}" href="{{.RepoLink}}/branches">
<div class="item{{if .PageIsBranches}} active{{end}}"> {{svg "octicon-git-branch"}} <b>{{.locale.PrettyNumber .BranchesCount}}</b> {{.locale.TrN .BranchesCount "repo.branch" "repo.branches"}}
<a class="flex-text-inline" href="{{.RepoLink}}/branches">{{svg "octicon-git-branch"}} <b>{{.locale.PrettyNumber .BranchesCount}}</b> {{.locale.TrN .BranchesCount "repo.branch" "repo.branches"}}</a> </a>
</div> {{if $.Permission.CanRead $.UnitTypeCode}}
{{if $.Permission.CanRead $.UnitTypeCode}} <a class="item muted {{if .PageIsTagList}}active{{end}}" href="{{.RepoLink}}/tags">
<div class="item{{if .PageIsTagList}} active{{end}}"> {{svg "octicon-tag"}} <b>{{.locale.PrettyNumber .NumTags}}</b> {{.locale.TrN .NumTags "repo.tag" "repo.tags"}}
<a class="flex-text-inline" href="{{.RepoLink}}/tags">{{svg "octicon-tag"}} <b>{{.locale.PrettyNumber .NumTags}}</b> {{.locale.TrN .NumTags "repo.tag" "repo.tags"}}</a> </a>
</div>
{{end}}
<div class="item" {{if not (eq .Repository.Size 0)}}data-tooltip-content="{{.Repository.SizeDetailsString}}"{{end}}>
{{$fileSizeFormatted := FileSize .Repository.Size}}{{/* the formatted string is always "{val} {unit}" */}}
{{$fileSizeFields := StringUtils.Split $fileSizeFormatted " "}}
<span class="flex-text-inline">{{svg "octicon-database"}} <b>{{.locale.PrettyNumber (index $fileSizeFields 0)}}</b> {{index $fileSizeFields 1}}</span>
</div>
{{end}} {{end}}
</div> <span class="item not-mobile" {{if not (eq .Repository.Size 0)}}data-tooltip-content="{{.Repository.SizeDetailsString}}"{{end}}>
{{$fileSizeFormatted := FileSize .Repository.Size}}{{/* the formatted string is always "{val} {unit}" */}}
{{$fileSizeFields := StringUtils.Split $fileSizeFormatted " "}}
{{svg "octicon-database"}} <b>{{.locale.PrettyNumber (index $fileSizeFields 0)}}</b> {{index $fileSizeFields 1}}
</span>
{{end}}
</div> </div>
{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo) .LanguageStats}} {{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo) .LanguageStats}}
<div class="ui segment sub-menu language-stats-details gt-hidden"> <div class="ui segment sub-menu language-stats-details gt-hidden">
<div class="ui horizontal center list">
{{range .LanguageStats}}
<div class="item gt-df gt-ac gt-jc">
<i class="color-icon gt-mr-3" style="background-color: {{.Color}}"></i>
<span class="gt-font-semibold gt-mr-3">
{{if eq .Language "other"}}
{{$.locale.Tr "repo.language_other"}}
{{else}}
{{.Language}}
{{end}}
</span>
{{.Percentage}}%
</div>
{{end}}
</div>
</div>
<a class="ui segment language-stats">
{{range .LanguageStats}} {{range .LanguageStats}}
<div class="bar" style="width: {{.Percentage}}%; background-color: {{.Color}}" data-tooltip-placement="top" data-tooltip-content={{.Language}}>&nbsp;</div> <div class="item">
<i class="color-icon" style="background-color: {{.Color}}"></i>
<span class="gt-font-semibold">
{{if eq .Language "other"}}
{{$.locale.Tr "repo.language_other"}}
{{else}}
{{.Language}}
{{end}}
</span>
{{.Percentage}}%
</div>
{{end}}
</div>
<a class="ui segment language-stats show-panel toggle" data-panel=".repository-summary > .sub-menu">
{{range .LanguageStats}}
<div class="bar" style="width: {{.Percentage}}%; background-color: {{.Color}}" data-tooltip-placement="top" data-tooltip-content={{.Language}}></div>
{{end}} {{end}}
</a> </a>
{{end}} {{end}}

View file

@ -1,9 +1,6 @@
.repository .data-table .line-num, .repository .data-table .line-num,
.repository .diff-file-box .file-body.file-code .lines-num, .repository .diff-file-box .file-body.file-code .lines-num,
.repository .diff-file-box .code-diff tbody tr .lines-type-marker, .repository .diff-file-box .code-diff tbody tr .lines-type-marker {
.repository .repository-summary .segment.language-stats {
-webkit-touch-callout: none;
-webkit-user-select: none;
user-select: none; user-select: none;
} }
@ -1943,47 +1940,6 @@
border-bottom: 1px solid var(--color-warning-border); border-bottom: 1px solid var(--color-warning-border);
} }
.repository .ui.segment.sub-menu {
padding: 7px;
line-height: 0;
}
.repository .ui.segment.sub-menu .list {
width: 100%;
display: flex;
align-items: stretch;
}
.repository .ui.segment.sub-menu .list .item {
width: 100%;
color: var(--color-text);
display: flex;
align-items: center;
justify-content: center;
}
.repository .ui.segment.sub-menu .list .item:first-of-type {
border-radius: var(--border-radius) 0 0 var(--border-radius);
padding-left: 0.25rem;
}
.repository .ui.segment.sub-menu .list .item:last-of-type {
border-radius: 0 var(--border-radius) var(--border-radius) 0;
padding-right: 0.25rem;
}
.repository .ui.segment.sub-menu .list .item a {
color: var(--color-text);
}
.repository .ui.segment.sub-menu .list .item a:hover {
color: var(--color-primary-light-2);
}
.repository .ui.segment.sub-menu .list .item.active {
background: var(--color-secondary);
}
.repository .segment.reactions.dropdown .menu, .repository .segment.reactions.dropdown .menu,
.repository .select-reaction.dropdown .menu { .repository .select-reaction.dropdown .menu {
right: 0 !important; right: 0 !important;
@ -2081,49 +2037,39 @@
} }
.repository .repository-summary { .repository .repository-summary {
box-shadow: none !important; box-shadow: none;
} }
.repository .repository-summary .segment.language-stats-details, .repository .repository-summary .segment.sub-menu {
.repository .repository-summary .segment.repository-summary { border: none;
border-top: none; display: flex;
background: none; align-items: center;
padding: 0 0.5em; /* make the UI look better for narrow (mobile) view */
overflow: hidden;
} }
.repository .repository-summary .segment.language-stats-details .item { .repository .repository-summary .sub-menu .item {
white-space: nowrap; flex: 1;
height: 30px;
line-height: var(--line-height-default);
display: flex;
align-items: center;
justify-content: center;
gap: 0.25em;
padding: 0 0.25em;
}
.repository .repository-summary .sub-menu .item.active {
background: var(--color-secondary);
} }
.repository .repository-summary .segment.language-stats { .repository .repository-summary .segment.language-stats {
padding: 0;
height: 11px;
display: flex; display: flex;
white-space: nowrap;
width: 100%;
border-radius: 0;
}
@media (max-width: 767.98px) {
.repository .repository-summary .segment.language-stats {
display: none;
}
}
.repository .repository-summary .segment.language-stats .bar {
white-space: nowrap;
border: 0;
padding: 0; padding: 0;
margin: 0; height: 10px;
height: 100%; white-space: nowrap;
} border-radius: 0 0 3px 3px !important;
overflow: hidden;
.repository .repository-menu {
padding: 0 !important;
}
.repository .repository-menu .item {
padding-top: 9px !important;
padding-bottom: 9px !important;
} }
#cite-repo-modal #citation-panel { #cite-repo-modal #citation-panel {
@ -2924,18 +2870,6 @@ tbody.commit-list {
height: 100%; height: 100%;
} }
/* prevent page shaking on language bar click */
.repository-summary-language-stats {
height: 48px;
overflow: hidden;
}
@media (max-width: 767.98px) {
.repository-summary-language-stats {
height: auto;
}
}
.ui.form .right .ui.button { .ui.form .right .ui.button {
margin-left: 0.25em; margin-left: 0.25em;
margin-right: 0; margin-right: 0;

View file

@ -388,9 +388,9 @@ export function initGlobalButtons() {
e.preventDefault(); e.preventDefault();
}); });
$('.show-panel.button').on('click', function (e) { $('.show-panel').on('click', function (e) {
// a '.show-panel.button' can show a panel, by `data-panel="selector"` // a '.show-panel' element can show a panel, by `data-panel="selector"`
// if the button is a "toggle" button, it toggles the panel // if it has "toggle" class, it toggles the panel
e.preventDefault(); e.preventDefault();
const sel = $(this).attr('data-panel'); const sel = $(this).attr('data-panel');
if (this.classList.contains('toggle')) { if (this.classList.contains('toggle')) {
@ -400,8 +400,8 @@ export function initGlobalButtons() {
} }
}); });
$('.hide-panel.button').on('click', function (e) { $('.hide-panel').on('click', function (e) {
// a `.hide-panel.button` can hide a panel, by `data-panel="selector"` or `data-panel-closest="selector"` // a `.hide-panel` element can hide a panel, by `data-panel="selector"` or `data-panel-closest="selector"`
e.preventDefault(); e.preventDefault();
let sel = $(this).attr('data-panel'); let sel = $(this).attr('data-panel');
if (sel) { if (sel) {

View file

@ -1,5 +1,5 @@
import $ from 'jquery'; import $ from 'jquery';
import {hideElem, showElem, toggleElem} from '../utils/dom.js'; import {hideElem, showElem} from '../utils/dom.js';
const {csrfToken} = window.config; const {csrfToken} = window.config;
@ -91,13 +91,3 @@ export function initRepoCommonFilterSearchDropdown(selector) {
message: {noResults: $dropdown.attr('data-no-results')}, message: {noResults: $dropdown.attr('data-no-results')},
}); });
} }
export function initRepoCommonLanguageStats() {
// Language stats
if ($('.language-stats').length > 0) {
$('.language-stats').on('click', (e) => {
e.preventDefault();
toggleElem($('.language-stats-details, .repository-menu'));
});
}
}

View file

@ -11,7 +11,6 @@ import {htmlEscape} from 'escape-goat';
import {initRepoBranchTagSelector} from '../components/RepoBranchTagSelector.vue'; import {initRepoBranchTagSelector} from '../components/RepoBranchTagSelector.vue';
import { import {
initRepoCloneLink, initRepoCommonBranchOrTagDropdown, initRepoCommonFilterSearchDropdown, initRepoCloneLink, initRepoCommonBranchOrTagDropdown, initRepoCommonFilterSearchDropdown,
initRepoCommonLanguageStats,
} from './repo-common.js'; } from './repo-common.js';
import {initCitationFileCopyContent} from './citation.js'; import {initCitationFileCopyContent} from './citation.js';
import {initCompLabelEdit} from './comp/LabelEdit.js'; import {initCompLabelEdit} from './comp/LabelEdit.js';
@ -525,7 +524,6 @@ export function initRepository() {
initRepoCloneLink(); initRepoCloneLink();
initCitationFileCopyContent(); initCitationFileCopyContent();
initRepoCommonLanguageStats();
initRepoSettingBranches(); initRepoSettingBranches();
// Issues // Issues