Fine tune more downdrop settings, use SVG for labels, improve Repo Topic Edit form ()

Although it seems that some different purposes are mixed in this PR,
however, they are all related, and can be tested together, so I put them
together to save everyone's time.

Diff: `+79 −84`, everything becomes much better.

### Improve the dropdown settings.

Move all fomantic-init related code into our `fomantic.js`

Fine-tune some dropdown global settings, see the comments.

Also help to fix the first problem in  , cc: @yp05327 

The "language" menu has been simplified, and it works with small-height
window better.

### Use SVG instead of `<i class="delete icon">`

It's also done by `$.fn.dropdown.settings.templates.label` , cc:
@silverwind

### Remove incorrect `tabable` CSS class

It doesn't have CSS styles, and it was only in Vue. So it's totally
unnecessary, remove it by the way.

### Improve the Repo Topic Edit form

* Simplify the code
* Add a "Cancel" button
* Align elements

Before:

<details>

![image](https://user-images.githubusercontent.com/2114189/223325782-f09532de-0c38-4742-ba86-ed35cc9a858d.png)

</details>

After:

![image](https://user-images.githubusercontent.com/2114189/226796347-207feb0a-b3cd-4820-8a3e-01930bab1069.png)
This commit is contained in:
wxiaoguang 2023-03-26 19:31:26 +08:00 committed by GitHub
parent ac64c82974
commit 12fff36d05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 80 additions and 86 deletions

View file

@ -19,9 +19,8 @@
{{if .ShowFooterBranding}}
<a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea">{{svg "octicon-mark-github"}}<span class="sr-only">GitHub</span></a>
{{end}}
<div class="ui language bottom floating slide up dropdown link item">
{{svg "octicon-globe"}}
<span>{{.locale.LangName}}</span>
<div class="ui dropdown upward language">
<span>{{svg "octicon-globe"}} {{.locale.LangName}}</span>
<div class="menu language-menu">
{{range .AllLangs}}
<a lang="{{.Lang}}" data-url="{{AppSubUrl}}/?lang={{.Lang}}" class="item {{if eq $.locale.Lang .Lang}}active selected{{end}}">{{.Name}}</a>

View file

@ -28,34 +28,29 @@
</div>
{{end}}
</div>
<div class="gt-mt-3" id="repo-topics">
{{range .Topics}}<a class="ui repo-topic large label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a>{{end}}
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<a id="manage_topic" class="muted">{{.locale.Tr "repo.topic.manage_topics"}}</a>{{end}}
<div class="gt-df gt-ac gt-fw gt-mt-3" id="repo-topics">
{{range .Topics}}<a class="ui repo-topic large label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a>{{end}}
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<button id="manage_topic" class="ui button tiny tertiary gt-ml-2">{{.locale.Tr "repo.topic.manage_topics"}}</button>{{end}}
</div>
{{end}}
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}
<div class="ui repo-topic-edit grid form gt-hidden" id="topic_edit">
<div class="fourteen wide column">
<div class="field">
<div class="ui fluid multiple search selection dropdown">
<input type="hidden" name="topics" value="{{range $i, $v := .Topics}}{{.Name}}{{if lt (Add $i 1) (len $.Topics)}},{{end}}{{end}}">
{{range .Topics}}
<div class="ui small label topic transition visible" data-value="{{.Name}}" style="display: inline-block !important; cursor: default;">{{.Name}}{{svg "octicon-x" 16 "delete icon gt-ml-3 gt-mt-1"}}</div>
{{end}}
<div class="text"></div>
</div>
<div class="ui form gt-hidden gt-df gt-mt-4" id="topic_edit">
<div class="field gt-f1 gt-mr-3">
<div class="ui fluid multiple search selection dropdown" data-text-count-prompt="{{.locale.Tr "repo.topic.count_prompt"}}" data-text-format-prompt="{{.locale.Tr "repo.topic.format_prompt"}}">
<input type="hidden" name="topics" value="{{range $i, $v := .Topics}}{{.Name}}{{if lt (Add $i 1) (len $.Topics)}},{{end}}{{end}}">
{{range .Topics}}
{{/* keey the same layout as Fomantic UI generated labels */}}
<a class="ui label transition visible gt-cursor-default" data-value="{{.Name}}" style="display: inline-block !important;">{{.Name}}{{svg "octicon-x" 16 "delete icon"}}</a>
{{end}}
<div class="text"></div>
</div>
</div>
<div class="two wide column">
<a class="ui button primary" role="button" tabindex="0" id="save_topic"
data-link="{{.RepoLink}}/topics">{{.locale.Tr "repo.topic.done"}}</a>
<div>
<button class="ui basic button secondary" id="cancel_topic_edit">{{.locale.Tr "cancel"}}</button>
<button class="ui primary button" id="save_topic" data-link="{{.RepoLink}}/topics">{{.locale.Tr "save"}}</button>
</div>
</div>
{{end}}
<div class="gt-hidden" id="validate_prompt">
<span id="count_prompt">{{.locale.Tr "repo.topic.count_prompt"}}</span>
<span id="format_prompt">{{.locale.Tr "repo.topic.format_prompt"}}</span>
</div>
{{if .Repository.IsArchived}}
<div class="ui warning message">
{{.locale.Tr "repo.archive.title"}}

View file

@ -1854,15 +1854,15 @@ footer .container .links > *:first-child {
}
footer .ui.language .menu {
max-height: 500px;
height: 500px;
max-height: calc(100vh - 60px);
overflow-y: auto;
margin-bottom: 7px;
}
footer .ui.language .svg {
margin-right: 0.15em;
vertical-align: top;
margin-top: calc(2em - 16px);
margin-top: 1px;
}
footer .ui.left,
@ -2387,6 +2387,10 @@ a.ui.label:hover {
color: var(--color-text);
}
.ui.tertiary.button:focus {
color: var(--color-text-dark);
}
.ui.primary.label,
.ui.primary.labels .label {
background-color: var(--color-primary) !important;

View file

@ -23,6 +23,7 @@
.gt-pointer-events-none { pointer-events: none !important; }
.gt-relative { position: relative !important; }
.gt-overflow-x-scroll { overflow-x: scroll !important; }
.gt-cursor-default { cursor: default !important; }
.gt-mono {
font-family: var(--fonts-monospace) !important;

View file

@ -3062,21 +3062,10 @@ tbody.commit-list {
top: -2px;
}
#topic_edit {
margin-top: 5px;
}
#repo-topics {
margin-top: 5px;
display: flex;
align-items: center;
flex-wrap: wrap;
}
.repo-topic {
font-weight: normal !important;
#repo-topics .repo-topic {
font-weight: normal;
cursor: pointer;
margin: 2px !important;
margin: 2px;
}
#new-dependency-drop-list.ui.selection.dropdown {
@ -3092,18 +3081,6 @@ tbody.commit-list {
overflow: hidden;
}
#manage_topic {
font-size: 12px;
}
.label + #manage_topic {
margin-left: 5px;
}
.ui.small.label.topic {
margin-bottom: 4px;
}
.repo-header {
display: flex;
align-items: center;

View file

@ -1,6 +1,6 @@
<template>
<div>
<div v-if="!isOrganization" class="ui two item tabable menu">
<div v-if="!isOrganization" class="ui two item menu">
<a :class="{item: true, active: tab === 'repos'}" @click="changeTab('repos')">{{ textRepository }}</a>
<a :class="{item: true, active: tab === 'organizations'}" @click="changeTab('organizations')">{{ textOrganization }}</a>
</div>

View file

@ -83,7 +83,7 @@ export function initGlobalCommon() {
const $uiDropdowns = $('.ui.dropdown');
// do not init "custom" dropdowns, "custom" dropdowns are managed by their own code.
$uiDropdowns.filter(':not(.custom)').dropdown({fullTextSearch: 'exact'});
$uiDropdowns.filter(':not(.custom)').dropdown();
// The "jump" means this dropdown is mainly used for "menu" purpose,
// clicking an item will jump to somewhere else or trigger an action/function.
@ -111,14 +111,12 @@ export function initGlobalCommon() {
},
});
// special animations/popup-directions
$uiDropdowns.filter('.slide.up').dropdown({transition: 'slide up'});
$uiDropdowns.filter('.upward').dropdown({direction: 'upward'});
// special popup-directions
$uiDropdowns.filter('.upward').dropdown('setting', 'direction', 'upward');
$('.ui.checkbox').checkbox();
$('.tabular.menu .item').tab();
$('.tabable.menu .item').tab();
$('.toggle.button').on('click', function () {
toggleElem($($(this).data('target')));

View file

@ -6,27 +6,29 @@ const {appSubUrl, csrfToken} = window.config;
export function initRepoTopicBar() {
const mgrBtn = $('#manage_topic');
if (!mgrBtn.length) return;
const editDiv = $('#topic_edit');
const viewDiv = $('#repo-topics');
const saveBtn = $('#save_topic');
const topicDropdown = $('#topic_edit .dropdown');
const topicForm = $('#topic_edit.ui.form');
const topicPrompts = getPrompts();
const topicForm = editDiv; // the old logic, editDiv is topicForm
const topicDropdownSearch = topicDropdown.find('input.search');
const topicPrompts = {
countPrompt: topicDropdown.attr('data-text-count-prompt'),
formatPrompt: topicDropdown.attr('data-text-format-prompt'),
};
mgrBtn.on('click', () => {
hideElem(viewDiv);
showElem(editDiv);
topicDropdownSearch.focus();
});
function getPrompts() {
const hidePrompt = $('#validate_prompt');
const prompts = {
countPrompt: hidePrompt.children('#count_prompt').text(),
formatPrompt: hidePrompt.children('#format_prompt').text()
};
hidePrompt.remove();
return prompts;
}
$('#cancel_topic_edit').on('click', () => {
hideElem(editDiv);
showElem(viewDiv);
mgrBtn.focus();
});
saveBtn.on('click', () => {
const topics = $('input[name=topics]').val();
@ -39,13 +41,11 @@ export function initRepoTopicBar() {
viewDiv.children('.topic').remove();
if (topics.length) {
const topicArray = topics.split(',');
const last = viewDiv.children('a').last();
for (let i = 0; i < topicArray.length; i++) {
const link = $('<a class="ui repo-topic large label topic"></a>');
link.attr('href', `${appSubUrl}/explore/repos?q=${encodeURIComponent(topicArray[i])}&topic=1`);
link.text(topicArray[i]);
link.insertBefore(last);
link.insertBefore(mgrBtn); // insert all new topics before manage button
}
}
hideElem(editDiv);
@ -86,9 +86,6 @@ export function initRepoTopicBar() {
duration: 200,
variation: false,
},
className: {
label: 'ui small label'
},
apiSettings: {
url: `${appSubUrl}/explore/topics/search?q={query}`,
throttle: 500,
@ -101,7 +98,7 @@ export function initRepoTopicBar() {
const query = stripTags(this.urlData.query.trim());
let found_query = false;
const current_topics = [];
topicDropdown.find('div.label.visible.topic,a.label.visible').each((_, el) => {
topicDropdown.find('a.label.visible').each((_, el) => {
current_topics.push(el.getAttribute('data-value'));
});

View file

@ -88,21 +88,15 @@ import {initFormattingReplacements} from './features/formatting.js';
import {initCopyContent} from './features/copycontent.js';
import {initCaptcha} from './features/captcha.js';
import {initRepositoryActionView} from './components/RepoActionView.vue';
import {initAriaCheckboxPatch} from './modules/aria/checkbox.js';
import {initAriaDropdownPatch} from './modules/aria/dropdown.js';
import {initGlobalTooltips} from './modules/tippy.js';
import {initGiteaFomantic} from './modules/fomantic.js';
// Run time-critical code as soon as possible. This is safe to do because this
// script appears at the end of <body> and rendered HTML is accessible at that point.
// TODO: replace them with CustomElements
initFormattingReplacements();
// Silence fomantic's error logging when tabs are used without a target content element
$.fn.tab.settings.silent = true;
// Disable the behavior of fomantic to toggle the checkbox when you press enter on a checkbox element.
$.fn.checkbox.settings.enableEnterKey = false;
// Use the patches to improve accessibility, these patches are designed to be as independent as possible, make it easy to modify or remove in the future.
initAriaCheckboxPatch();
initAriaDropdownPatch();
// Init Gitea's Fomantic settings
initGiteaFomantic();
$(document).ready(() => {
initGlobalCommon();

View file

@ -0,0 +1,29 @@
import $ from 'jquery';
import {initAriaCheckboxPatch} from './aria/checkbox.js';
import {initAriaDropdownPatch} from './aria/dropdown.js';
import {svg} from '../svg.js';
export function initGiteaFomantic() {
// Silence fomantic's error logging when tabs are used without a target content element
$.fn.tab.settings.silent = true;
// Disable the behavior of fomantic to toggle the checkbox when you press enter on a checkbox element.
$.fn.checkbox.settings.enableEnterKey = false;
// Prevent Fomantic from guessing the popup direction.
// Otherwise, if the viewport height is small, Fomantic would show the popup upward,
// if the dropdown is at the beginning of the page, then the top part would be clipped by the window view, eg: Issue List "Sort" dropdown
$.fn.dropdown.settings.direction = 'downward';
// By default, use "exact match" for full text search
$.fn.dropdown.settings.fullTextSearch = 'exact';
// Do not use "cursor: pointer" for dropdown labels
$.fn.dropdown.settings.className.label += ' gt-cursor-default';
// Always use Gitea's SVG icons
$.fn.dropdown.settings.templates.label = function(_value, text, preserveHTML, className) {
const escape = $.fn.dropdown.settings.templates.escape;
return escape(text, preserveHTML) + svg('octicon-x', 16, `${className.delete} icon`);
};
// Use the patches to improve accessibility, these patches are designed to be as independent as possible, make it easy to modify or remove in the future.
initAriaCheckboxPatch();
initAriaDropdownPatch();
}