Merge pull request #5333 from miqh/fix/color-input

fix(settings): add color input for cross-browser consistency (#3931)
This commit is contained in:
Johannes Millan 2025-10-22 19:24:58 +02:00 committed by GitHub
commit 7bb8cf08ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 58 additions and 11 deletions

View file

@ -0,0 +1,11 @@
<mat-form-field>
<mat-label>{{ to.label }}</mat-label>
<input
type="color"
class="color-input"
[formControl]="formControl"
[formlyAttributes]="field"
(focus)="onFocus($event)"
matInput
/>
</mat-form-field>

View file

@ -0,0 +1,3 @@
mat-form-field {
width: 100%;
}

View file

@ -0,0 +1,32 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { MatFormField, MatInput, MatLabel } from '@angular/material/input';
import { FieldType, FormlyModule } from '@ngx-formly/core';
import { IS_FIREFOX } from '../../../util/is-firefox';
import { IS_MOBILE } from '../../../util/is-mobile';
/**
* This component deliberately avoids Formly's field type abstractions for the
* Material UI components because the form field wrapper implementation uses
* a focus monitoring service that is counterproductive for certain native
* color input controls.
*/
@Component({
selector: 'color-input',
templateUrl: './color-input.component.html',
styleUrls: ['./color-input.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [FormlyModule, MatFormField, MatInput, MatLabel, ReactiveFormsModule],
})
export class ColorInputComponent extends FieldType {
onFocus(event: FocusEvent): void {
if (!IS_FIREFOX || IS_MOBILE) return;
// Desktop Firefox oddly fires another focus event when the native color
// input closes rather than a blur event, so determine whether a value
// change has occurred and force a blur to have it persisted
const input = event.target as HTMLInputElement;
if (input.value !== this.formControl.value) {
input.blur();
}
}
}

View file

@ -57,10 +57,9 @@ export const CREATE_PROJECT_BASIC_CONFIG_FORM_CONFIG: ConfigFormSection<Project>
},
{
key: 'theme.primary' as any,
type: 'input',
type: 'color',
templateOptions: {
label: T.F.PROJECT.FORM_THEME.L_THEME_COLOR,
type: 'color',
},
},
{

View file

@ -24,10 +24,9 @@ export const BASIC_TAG_CONFIG_FORM_CONFIG: ConfigFormSection<Tag> = {
},
{
key: 'color',
type: 'input',
type: 'color',
templateOptions: {
label: T.F.TAG.FORM_BASIC.L_COLOR,
type: 'color',
},
},
],

View file

@ -65,26 +65,23 @@ export const WORK_CONTEXT_THEME_CONFIG_FORM_CONFIG: ConfigFormSection<WorkContex
items: [
{
key: 'primary',
type: 'input',
type: 'color',
templateOptions: {
label: T.F.PROJECT.FORM_THEME.L_COLOR_PRIMARY,
type: 'color',
},
},
{
key: 'accent',
type: 'input',
type: 'color',
templateOptions: {
label: T.F.PROJECT.FORM_THEME.L_COLOR_ACCENT,
type: 'color',
},
},
{
key: 'warn',
type: 'input',
type: 'color',
templateOptions: {
label: T.F.PROJECT.FORM_THEME.L_COLOR_WARN,
type: 'color',
},
},
{

View file

@ -22,6 +22,7 @@ import { FormlyMatSliderModule } from '@ngx-formly/material/slider';
import { FormlyTagSelectionComponent } from './formly-tag-selection/formly-tag-selection.component';
import { FormlyBtnComponent } from './formly-button/formly-btn.component';
import { FormlyImageInputComponent } from './formly-image-input/formly-image-input.component';
import { ColorInputComponent } from '../features/config/color-input/color-input.component';
@NgModule({
imports: [
@ -64,6 +65,10 @@ import { FormlyImageInputComponent } from './formly-image-input/formly-image-inp
extends: 'input',
wrappers: ['form-field'],
},
{
name: 'color',
component: ColorInputComponent,
},
{
name: 'project-select',
component: SelectProjectComponent,

View file

@ -15,7 +15,8 @@ export const adjustToLiveFormlyForm = (
item.type === 'input' ||
item.type === 'textarea' ||
item.type === 'duration' ||
item.type === 'icon'
item.type === 'icon' ||
item.type === 'color'
) {
return {
...item,