aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2025-07-06 23:37:26 +0800
committerGitHub <noreply@github.com>2025-07-06 23:37:26 +0800
commit9dafcc5c9e779fba1957400a76041ed091660710 (patch)
treee1f0b92eeaec44e68d5ef209096171ac55aae34b
parente0745eb14daad91e1c27c795cf8546be30749dd0 (diff)
downloadgitea-9dafcc5c9e779fba1957400a76041ed091660710.tar.gz
gitea-9dafcc5c9e779fba1957400a76041ed091660710.zip
Improve project & label color picker and image scroll (#34971)
Fix #34609 Fix #34967
-rw-r--r--templates/projects/view.tmpl2
-rw-r--r--templates/repo/issue/label_precolors.tmpl43
-rw-r--r--templates/repo/issue/labels/label_edit_modal.tmpl2
-rw-r--r--web_src/css/base.css13
-rw-r--r--web_src/css/features/colorpicker.css32
-rw-r--r--web_src/css/features/projects.css3
-rw-r--r--web_src/js/features/colorpicker.ts36
-rw-r--r--web_src/js/features/comp/LabelEdit.ts2
8 files changed, 76 insertions, 57 deletions
diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl
index 6aa776da02..692808a32d 100644
--- a/templates/projects/view.tmpl
+++ b/templates/projects/view.tmpl
@@ -134,7 +134,7 @@
</div>
<div class="field">
<label class="project-column-color-label" for="project-column-color-input">color</label>
- <div class="js-color-picker-input column">
+ <div class="color-picker-combo" data-global-init="initColorPicker">
<input maxlength="7" placeholder="#c320f6" id="project-column-color-input" name="color">
{{template "repo/issue/label_precolors"}}
</div>
diff --git a/templates/repo/issue/label_precolors.tmpl b/templates/repo/issue/label_precolors.tmpl
index 80007662c0..7be3f40350 100644
--- a/templates/repo/issue/label_precolors.tmpl
+++ b/templates/repo/issue/label_precolors.tmpl
@@ -1,22 +1,27 @@
<div class="precolors">
- <div class="tw-flex">
- <a class="color" style="background-color:#e11d21" data-color-hex="#e11d21"></a>
- <a class="color" style="background-color:#eb6420" data-color-hex="#eb6420"></a>
- <a class="color" style="background-color:#fbca04" data-color-hex="#fbca04"></a>
- <a class="color" style="background-color:#009800" data-color-hex="#009800"></a>
- <a class="color" style="background-color:#006b75" data-color-hex="#006b75"></a>
- <a class="color" style="background-color:#207de5" data-color-hex="#207de5"></a>
- <a class="color" style="background-color:#0052cc" data-color-hex="#0052cc"></a>
- <a class="color" style="background-color:#5319e7" data-color-hex="#5319e7"></a>
- </div>
- <div class="tw-flex">
- <a class="color" style="background-color:#f6c6c7" data-color-hex="#f6c6c7"></a>
- <a class="color" style="background-color:#fad8c7" data-color-hex="#fad8c7"></a>
- <a class="color" style="background-color:#fef2c0" data-color-hex="#fef2c0"></a>
- <a class="color" style="background-color:#bfe5bf" data-color-hex="#bfe5bf"></a>
- <a class="color" style="background-color:#bfdadc" data-color-hex="#bfdadc"></a>
- <a class="color" style="background-color:#c7def8" data-color-hex="#c7def8"></a>
- <a class="color" style="background-color:#bfd4f2" data-color-hex="#bfd4f2"></a>
- <a class="color" style="background-color:#d4c5f9" data-color-hex="#d4c5f9"></a>
+ <button type="button" class="ui button generate-random-color">
+ {{svg "octicon-sync"}}
+ </button>
+ <div>
+ <div class="tw-flex">
+ <a class="color" style="background-color:#e11d21" data-color-hex="#e11d21"></a>
+ <a class="color" style="background-color:#eb6420" data-color-hex="#eb6420"></a>
+ <a class="color" style="background-color:#fbca04" data-color-hex="#fbca04"></a>
+ <a class="color" style="background-color:#009800" data-color-hex="#009800"></a>
+ <a class="color" style="background-color:#006b75" data-color-hex="#006b75"></a>
+ <a class="color" style="background-color:#207de5" data-color-hex="#207de5"></a>
+ <a class="color" style="background-color:#0052cc" data-color-hex="#0052cc"></a>
+ <a class="color" style="background-color:#5319e7" data-color-hex="#5319e7"></a>
+ </div>
+ <div class="tw-flex">
+ <a class="color" style="background-color:#f6c6c7" data-color-hex="#f6c6c7"></a>
+ <a class="color" style="background-color:#fad8c7" data-color-hex="#fad8c7"></a>
+ <a class="color" style="background-color:#fef2c0" data-color-hex="#fef2c0"></a>
+ <a class="color" style="background-color:#bfe5bf" data-color-hex="#bfe5bf"></a>
+ <a class="color" style="background-color:#bfdadc" data-color-hex="#bfdadc"></a>
+ <a class="color" style="background-color:#c7def8" data-color-hex="#c7def8"></a>
+ <a class="color" style="background-color:#bfd4f2" data-color-hex="#bfd4f2"></a>
+ <a class="color" style="background-color:#d4c5f9" data-color-hex="#d4c5f9"></a>
+ </div>
</div>
</div>
diff --git a/templates/repo/issue/labels/label_edit_modal.tmpl b/templates/repo/issue/labels/label_edit_modal.tmpl
index 6837d66dce..ec57de2f3f 100644
--- a/templates/repo/issue/labels/label_edit_modal.tmpl
+++ b/templates/repo/issue/labels/label_edit_modal.tmpl
@@ -49,7 +49,7 @@
</div>
<div class="field">
<label for="color">{{ctx.Locale.Tr "repo.issues.label_color"}}</label>
- <div class="column js-color-picker-input">
+ <div class="color-picker-combo" data-global-init="initColorPicker">
<!-- the "#" is optional because backend NormalizeColor is able to handle it, API also accepts both formats, and it is easier for users to directly copy-paste a hex value -->
<input name="color" value="#70c24a" placeholder="#c320f6" required pattern="^#?([\dA-Fa-f]{3}|[\dA-Fa-f]{6})$" maxlength="7">
{{template "repo/issue/label_precolors"}}
diff --git a/web_src/css/base.css b/web_src/css/base.css
index 529ddd5386..2b7a47edf1 100644
--- a/web_src/css/base.css
+++ b/web_src/css/base.css
@@ -1031,19 +1031,6 @@ table th[data-sortt-desc] .svg {
min-height: 0;
}
-.precolors {
- display: flex;
- flex-direction: column;
- justify-content: center;
- margin-left: 1em;
-}
-
-.precolors .color {
- display: inline-block;
- width: 15px;
- height: 15px;
-}
-
.ui.dropdown:not(.button) {
line-height: var(--line-height-default); /* the dropdown doesn't have default line-height, use this to make the dropdown icon align with plain dropdown */
}
diff --git a/web_src/css/features/colorpicker.css b/web_src/css/features/colorpicker.css
index b7436783df..4c517e6348 100644
--- a/web_src/css/features/colorpicker.css
+++ b/web_src/css/features/colorpicker.css
@@ -1,15 +1,13 @@
-.js-color-picker-input {
+.color-picker-combo {
display: flex;
- position: relative;
+ position: relative; /* to position the preview square */
}
-.js-color-picker-input input {
- padding-top: 8px !important;
- padding-bottom: 8px !important;
+.color-picker-combo input {
padding-left: 32px !important;
}
-.js-color-picker-input .preview-square {
+.color-picker-combo .preview-square {
position: absolute;
aspect-ratio: 1;
height: 16px;
@@ -22,7 +20,7 @@
background-size: 8px 8px;
}
-.js-color-picker-input .preview-square::after {
+.color-picker-combo .preview-square::after {
content: "";
position: absolute;
width: 100%;
@@ -31,6 +29,26 @@
background-color: currentcolor;
}
+.color-picker-combo .precolors {
+ display: flex;
+ margin-left: 1em;
+ align-items: center;
+ gap: 0.125em;
+}
+
+.color-picker-combo .precolors .generate-random-color {
+ padding: 0;
+ width: 30px;
+ height: 30px;
+ min-height: 0;
+}
+
+.color-picker-combo .precolors .color {
+ display: inline-block;
+ width: 15px;
+ height: 15px;
+}
+
hex-color-picker {
width: 180px;
height: 120px;
diff --git a/web_src/css/features/projects.css b/web_src/css/features/projects.css
index 7fd5150970..25cb530f85 100644
--- a/web_src/css/features/projects.css
+++ b/web_src/css/features/projects.css
@@ -71,7 +71,7 @@
.card-attachment-images {
display: inline-block;
white-space: nowrap;
- overflow: scroll;
+ overflow: auto;
cursor: default;
scroll-snap-type: x mandatory;
text-align: center;
@@ -85,6 +85,7 @@
scroll-snap-align: center;
margin-right: 2px;
aspect-ratio: 1;
+ object-fit: contain;
}
.card-attachment-images img:only-child {
diff --git a/web_src/js/features/colorpicker.ts b/web_src/js/features/colorpicker.ts
index b99e2f8c45..66d1fcb72a 100644
--- a/web_src/js/features/colorpicker.ts
+++ b/web_src/js/features/colorpicker.ts
@@ -1,18 +1,19 @@
import {createTippy} from '../modules/tippy.ts';
import type {DOMEvent} from '../utils/dom.ts';
+import {registerGlobalInitFunc} from '../modules/observer.ts';
export async function initColorPickers() {
- const els = document.querySelectorAll<HTMLElement>('.js-color-picker-input');
- if (!els.length) return;
-
- await Promise.all([
- import(/* webpackChunkName: "colorpicker" */'vanilla-colorful/hex-color-picker.js'),
- import(/* webpackChunkName: "colorpicker" */'../../css/features/colorpicker.css'),
- ]);
-
- for (const el of els) {
+ let imported = false;
+ registerGlobalInitFunc('initColorPicker', async (el) => {
+ if (!imported) {
+ await Promise.all([
+ import(/* webpackChunkName: "colorpicker" */'vanilla-colorful/hex-color-picker.js'),
+ import(/* webpackChunkName: "colorpicker" */'../../css/features/colorpicker.css'),
+ ]);
+ imported = true;
+ }
initPicker(el);
- }
+ });
}
function updateSquare(el: HTMLElement, newValue: string): void {
@@ -55,13 +56,20 @@ function initPicker(el: HTMLElement): void {
},
});
- // init precolors
+ // init random color & precolors
+ const setSelectedColor = (color: string) => {
+ input.value = color;
+ input.dispatchEvent(new Event('input', {bubbles: true}));
+ updateSquare(square, color);
+ };
+ el.querySelector('.generate-random-color').addEventListener('click', () => {
+ const newValue = `#${Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, '0')}`;
+ setSelectedColor(newValue);
+ });
for (const colorEl of el.querySelectorAll<HTMLElement>('.precolors .color')) {
colorEl.addEventListener('click', (e: DOMEvent<MouseEvent, HTMLAnchorElement>) => {
const newValue = e.target.getAttribute('data-color-hex');
- input.value = newValue;
- input.dispatchEvent(new Event('input', {bubbles: true}));
- updateSquare(square, newValue);
+ setSelectedColor(newValue);
});
}
}
diff --git a/web_src/js/features/comp/LabelEdit.ts b/web_src/js/features/comp/LabelEdit.ts
index 423440129c..3e27eac1c5 100644
--- a/web_src/js/features/comp/LabelEdit.ts
+++ b/web_src/js/features/comp/LabelEdit.ts
@@ -24,7 +24,7 @@ export function initCompLabelEdit(pageSelector: string) {
const elIsArchivedField = elModal.querySelector('.label-is-archived-input-field');
const elIsArchivedInput = elModal.querySelector<HTMLInputElement>('.label-is-archived-input');
const elDescInput = elModal.querySelector<HTMLInputElement>('.label-desc-input');
- const elColorInput = elModal.querySelector<HTMLInputElement>('.js-color-picker-input input');
+ const elColorInput = elModal.querySelector<HTMLInputElement>('.color-picker-combo input');
const syncModalUi = () => {
const hasScope = nameHasScope(elNameInput.value);