[MM-61592]: Updated the Theme list section in the settings modal (#29596)

* [MA-13]: Updated the Theme list section in the settings modal

* [MA-13]: Fixed failing e2e test cases

* [MA-13]: Fixed accordion and removed aria-label from button

* [MA-13]: Fixed grouping of radio buttons

* [MA-13]: Updated the Theme list structure

* [MA-13]: Minor styling changes

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
ayush-chauhan233
2025-02-28 02:59:25 +05:30
коммит произвёл GitHub
родитель e1336b24bf
Коммит 0acadb7b93
6 изменённых файлов: 226 добавлений и 129 удалений

Просмотреть файл

@@ -35,10 +35,10 @@ describe('Settings > Display > Theme > Custom Theme Colors', () => {
cy.get('#customThemes').check().should('be.checked'); cy.get('#customThemes').check().should('be.checked');
// # Open Center Channel Styles section // # Open Center Channel Styles section
cy.get('#centerChannelStyles').click({force: true}).wait(TIMEOUTS.ONE_HUNDRED_MILLIS); cy.get('#centerChannelStylesAccordion').click({force: true}).wait(TIMEOUTS.ONE_HUNDRED_MILLIS);
// # Select custom code theme // # Select custom code theme
cy.get('#codeThemeSelect').should('be.visible').scrollIntoView().select(theme.name); cy.get('#codeThemeSelect').scrollIntoView().should('be.visible').select(theme.name);
// * Verify that the setting changes in the background? // * Verify that the setting changes in the background?
verifyLastPostStyle(theme); verifyLastPostStyle(theme);

Просмотреть файл

@@ -2,14 +2,21 @@
exports[`components/user_settings/display/CustomThemeChooser should match, init 1`] = ` exports[`components/user_settings/display/CustomThemeChooser should match, init 1`] = `
<div <div
aria-labelledby="customThemes"
className="appearance-section pt-2" className="appearance-section pt-2"
id="customThemesSection"
> >
<div <div
className="theme-elements row" className="theme-elements row"
> >
<div <h4
className="theme-elements__header" className="theme-elements__header"
id="sidebarStyles" >
<button
aria-controls="sidebarStylesSection"
aria-expanded={false}
className="theme-elements__header"
id="sidebarStylesAccordion"
onClick={[Function]} onClick={[Function]}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -20,15 +27,20 @@ exports[`components/user_settings/display/CustomThemeChooser should match, init
className="header__icon" className="header__icon"
> >
<i <i
aria-hidden={true}
className="fa fa-plus" className="fa fa-plus"
/> />
<i <i
aria-hidden={true}
className="fa fa-minus" className="fa fa-minus"
/> />
</div> </div>
</div> </button>
</h4>
<div <div
aria-labelledby="sidebarStylesAccordion"
className="theme-elements__body" className="theme-elements__body"
id="sidebarStylesSection"
> >
<div <div
className="col-sm-6 form-group element" className="col-sm-6 form-group element"
@@ -259,9 +271,14 @@ exports[`components/user_settings/display/CustomThemeChooser should match, init
<div <div
className="theme-elements row" className="theme-elements row"
> >
<div <h4
className="theme-elements__header" className="theme-elements__header"
id="centerChannelStyles" >
<button
aria-controls="centerChannelStylesSection"
aria-expanded={false}
className="theme-elements__header"
id="centerChannelStylesAccordion"
onClick={[Function]} onClick={[Function]}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -272,16 +289,20 @@ exports[`components/user_settings/display/CustomThemeChooser should match, init
className="header__icon" className="header__icon"
> >
<i <i
aria-hidden={true}
className="fa fa-plus" className="fa fa-plus"
/> />
<i <i
aria-hidden={true}
className="fa fa-minus" className="fa fa-minus"
/> />
</div> </div>
</div> </button>
</h4>
<div <div
aria-labelledby="centerChannelStylesAccordion"
className="theme-elements__body" className="theme-elements__body"
id="centerChannelStyles" id="centerChannelStylesSection"
> >
<div <div
className="col-sm-6 form-group element" className="col-sm-6 form-group element"
@@ -456,9 +477,14 @@ exports[`components/user_settings/display/CustomThemeChooser should match, init
<div <div
className="theme-elements row" className="theme-elements row"
> >
<div <h4
className="theme-elements__header" className="theme-elements__header"
id="linkAndButtonsStyles" >
<button
aria-controls="linkAndButtonsStylesSection"
aria-expanded={false}
className="theme-elements__header"
id="linkAndButtonsStylesAccordion"
onClick={[Function]} onClick={[Function]}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -469,15 +495,20 @@ exports[`components/user_settings/display/CustomThemeChooser should match, init
className="header__icon" className="header__icon"
> >
<i <i
aria-hidden={true}
className="fa fa-plus" className="fa fa-plus"
/> />
<i <i
aria-hidden={true}
className="fa fa-minus" className="fa fa-minus"
/> />
</div> </div>
</div> </button>
</h4>
<div <div
aria-labelledby="linkAndButtonsStylesAccordion"
className="theme-elements__body" className="theme-elements__body"
id="linkAndButtonsStylesSection"
> >
<div <div
className="col-sm-6 form-group element" className="col-sm-6 form-group element"

Просмотреть файл

@@ -128,9 +128,9 @@ type State = {
export class CustomThemeChooser extends React.PureComponent<Props, State> { export class CustomThemeChooser extends React.PureComponent<Props, State> {
textareaRef: RefObject<HTMLTextAreaElement>; textareaRef: RefObject<HTMLTextAreaElement>;
sidebarStylesHeaderRef: RefObject<HTMLDivElement>; sidebarStylesHeaderRef: RefObject<HTMLButtonElement>;
centerChannelStylesHeaderRef: RefObject<HTMLDivElement>; centerChannelStylesHeaderRef: RefObject<HTMLButtonElement>;
linkAndButtonStylesHeaderRef: RefObject<HTMLDivElement>; linkAndButtonStylesHeaderRef: RefObject<HTMLButtonElement>;
sidebarStylesRef: RefObject<HTMLDivElement>; sidebarStylesRef: RefObject<HTMLDivElement>;
centerChannelStylesRef: RefObject<HTMLDivElement>; centerChannelStylesRef: RefObject<HTMLDivElement>;
linkAndButtonStylesRef: RefObject<HTMLDivElement>; linkAndButtonStylesRef: RefObject<HTMLDivElement>;
@@ -160,7 +160,7 @@ export class CustomThemeChooser extends React.PureComponent<Props, State> {
[settingId]: color, [settingId]: color,
}; };
// For backwards compatability // For backwards compatibility
if (settingId === 'mentionBg') { if (settingId === 'mentionBg') {
newTheme.mentionBj = color; newTheme.mentionBj = color;
} }
@@ -220,24 +220,33 @@ export class CustomThemeChooser extends React.PureComponent<Props, State> {
this.textareaRef.current?.setSelectionRange(0, this.state.copyTheme.length); this.textareaRef.current?.setSelectionRange(0, this.state.copyTheme.length);
}; };
toggleSidebarStyles = (e: MouseEvent<HTMLDivElement>) => { toggleSidebarStyles = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault(); e.preventDefault();
this.sidebarStylesHeaderRef.current?.classList.toggle('open'); this.sidebarStylesHeaderRef.current?.classList.toggle('open');
const isAccordionOpen = this.sidebarStylesHeaderRef.current?.classList.contains('open');
this.sidebarStylesHeaderRef.current?.setAttribute('aria-expanded', `${isAccordionOpen}`);
this.toggleSection(this.sidebarStylesRef.current); this.toggleSection(this.sidebarStylesRef.current);
}; };
toggleCenterChannelStyles = (e: MouseEvent<HTMLDivElement>) => { toggleCenterChannelStyles = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault(); e.preventDefault();
this.centerChannelStylesHeaderRef.current?.classList.toggle('open'); this.centerChannelStylesHeaderRef.current?.classList.toggle('open');
const isAccordionOpen = this.centerChannelStylesHeaderRef.current?.classList.contains('open');
this.centerChannelStylesHeaderRef.current?.setAttribute('aria-expanded', `${isAccordionOpen}`);
this.toggleSection(this.centerChannelStylesRef.current); this.toggleSection(this.centerChannelStylesRef.current);
}; };
toggleLinkAndButtonStyles = (e: MouseEvent<HTMLDivElement>) => { toggleLinkAndButtonStyles = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault(); e.preventDefault();
this.linkAndButtonStylesHeaderRef.current?.classList.toggle('open'); this.linkAndButtonStylesHeaderRef.current?.classList.toggle('open');
const isAccordionOpen = this.linkAndButtonStylesHeaderRef.current?.classList.contains('open');
this.linkAndButtonStylesHeaderRef.current?.setAttribute('aria-expanded', `${isAccordionOpen}`);
this.toggleSection(this.linkAndButtonStylesRef.current); this.toggleSection(this.linkAndButtonStylesRef.current);
}; };
@@ -448,13 +457,20 @@ export class CustomThemeChooser extends React.PureComponent<Props, State> {
); );
return ( return (
<div className='appearance-section pt-2'>
<div className='theme-elements row'>
<div <div
id='customThemesSection'
className='appearance-section pt-2'
aria-labelledby='customThemes'
>
<div className='theme-elements row'>
<h4 className='theme-elements__header'>
<button
ref={this.sidebarStylesHeaderRef} ref={this.sidebarStylesHeaderRef}
id='sidebarStyles' id='sidebarStylesAccordion'
className='theme-elements__header'
onClick={this.toggleSidebarStyles} onClick={this.toggleSidebarStyles}
aria-expanded={false}
aria-controls='sidebarStylesSection'
className='theme-elements__header'
> >
<FormattedMessage <FormattedMessage
id='user.settings.custom_theme.sidebarTitle' id='user.settings.custom_theme.sidebarTitle'
@@ -463,27 +479,35 @@ export class CustomThemeChooser extends React.PureComponent<Props, State> {
<div className='header__icon'> <div className='header__icon'>
<i <i
className='fa fa-plus' className='fa fa-plus'
aria-hidden={true}
title={intl.formatMessage({id: 'generic_icons.expand', defaultMessage: 'Expand Icon'})} title={intl.formatMessage({id: 'generic_icons.expand', defaultMessage: 'Expand Icon'})}
/> />
<i <i
className='fa fa-minus' className='fa fa-minus'
aria-hidden={true}
title={intl.formatMessage({id: 'generic_icons.collapse', defaultMessage: 'Collapse Icon'})} title={intl.formatMessage({id: 'generic_icons.collapse', defaultMessage: 'Collapse Icon'})}
/> />
</div> </div>
</div> </button>
</h4>
<div <div
ref={this.sidebarStylesRef} ref={this.sidebarStylesRef}
id='sidebarStylesSection'
aria-labelledby='sidebarStylesAccordion'
className='theme-elements__body' className='theme-elements__body'
> >
{sidebarElements} {sidebarElements}
</div> </div>
</div> </div>
<div className='theme-elements row'> <div className='theme-elements row'>
<div <h4 className='theme-elements__header'>
<button
ref={this.centerChannelStylesHeaderRef} ref={this.centerChannelStylesHeaderRef}
id='centerChannelStyles' id='centerChannelStylesAccordion'
className='theme-elements__header'
onClick={this.toggleCenterChannelStyles} onClick={this.toggleCenterChannelStyles}
aria-expanded={false}
aria-controls='centerChannelStylesSection'
className='theme-elements__header'
> >
<FormattedMessage <FormattedMessage
id='user.settings.custom_theme.centerChannelTitle' id='user.settings.custom_theme.centerChannelTitle'
@@ -492,28 +516,35 @@ export class CustomThemeChooser extends React.PureComponent<Props, State> {
<div className='header__icon'> <div className='header__icon'>
<i <i
className='fa fa-plus' className='fa fa-plus'
aria-hidden={true}
title={intl.formatMessage({id: 'generic_icons.expand', defaultMessage: 'Expand Icon'})} title={intl.formatMessage({id: 'generic_icons.expand', defaultMessage: 'Expand Icon'})}
/> />
<i <i
className='fa fa-minus' className='fa fa-minus'
aria-hidden={true}
title={intl.formatMessage({id: 'generic_icons.collapse', defaultMessage: 'Collapse Icon'})} title={intl.formatMessage({id: 'generic_icons.collapse', defaultMessage: 'Collapse Icon'})}
/> />
</div> </div>
</div> </button>
</h4>
<div <div
ref={this.centerChannelStylesRef} ref={this.centerChannelStylesRef}
id='centerChannelStyles' id='centerChannelStylesSection'
className='theme-elements__body' className='theme-elements__body'
aria-labelledby='centerChannelStylesAccordion'
> >
{centerChannelElements} {centerChannelElements}
</div> </div>
</div> </div>
<div className='theme-elements row'> <div className='theme-elements row'>
<div <h4 className='theme-elements__header'>
<button
ref={this.linkAndButtonStylesHeaderRef} ref={this.linkAndButtonStylesHeaderRef}
id='linkAndButtonsStyles' id='linkAndButtonsStylesAccordion'
className='theme-elements__header'
onClick={this.toggleLinkAndButtonStyles} onClick={this.toggleLinkAndButtonStyles}
aria-expanded={false}
aria-controls='linkAndButtonsStylesSection'
className='theme-elements__header'
> >
<FormattedMessage <FormattedMessage
id='user.settings.custom_theme.linkButtonTitle' id='user.settings.custom_theme.linkButtonTitle'
@@ -522,17 +553,22 @@ export class CustomThemeChooser extends React.PureComponent<Props, State> {
<div className='header__icon'> <div className='header__icon'>
<i <i
className='fa fa-plus' className='fa fa-plus'
aria-hidden={true}
title={intl.formatMessage({id: 'generic_icons.expand', defaultMessage: 'Expand Icon'})} title={intl.formatMessage({id: 'generic_icons.expand', defaultMessage: 'Expand Icon'})}
/> />
<i <i
className='fa fa-minus' className='fa fa-minus'
aria-hidden={true}
title={intl.formatMessage({id: 'generic_icons.collapse', defaultMessage: 'Collapse Icon'})} title={intl.formatMessage({id: 'generic_icons.collapse', defaultMessage: 'Collapse Icon'})}
/> />
</div> </div>
</div> </button>
</h4>
<div <div
id='linkAndButtonsStylesSection'
ref={this.linkAndButtonStylesRef} ref={this.linkAndButtonStylesRef}
className='theme-elements__body' className='theme-elements__body'
aria-labelledby='linkAndButtonsStylesAccordion'
> >
{linkAndButtonElements} {linkAndButtonElements}
</div> </div>

Просмотреть файл

@@ -39,9 +39,9 @@ const PremadeThemeChooser = ({theme, updateTheme, allowedThemes = []}: Props) =>
className='col-xs-6 col-sm-3 premade-themes' className='col-xs-6 col-sm-3 premade-themes'
key={'premade-theme-key' + k} key={'premade-theme-key' + k}
> >
<div <button
id={`premadeTheme${premadeTheme.type?.replace(' ', '')}`} id={`premadeTheme${premadeTheme.type?.replace(' ', '')}`}
className={activeClass} className={`premadeThemeButton ${activeClass}`}
onClick={() => updateTheme(premadeTheme)} onClick={() => updateTheme(premadeTheme)}
> >
<label> <label>
@@ -61,14 +61,18 @@ const PremadeThemeChooser = ({theme, updateTheme, allowedThemes = []}: Props) =>
/> />
<div className='theme-label'>{toTitleCase(premadeTheme.type || '')}</div> <div className='theme-label'>{toTitleCase(premadeTheme.type || '')}</div>
</label> </label>
</div> </button>
</div>, </div>,
); );
} }
} }
return ( return (
<div className='row appearance-section'> <div
id='premadeThemesSection'
className='row appearance-section'
aria-labelledby='standardThemes'
>
<div className='clearfix'> <div className='clearfix'>
{premadeThemes} {premadeThemes}
</div> </div>

Просмотреть файл

@@ -195,6 +195,7 @@ export default class ThemeSetting extends React.PureComponent<Props, State> {
name='theme' name='theme'
checked={!displayCustom} checked={!displayCustom}
onChange={this.updateType.bind(this, 'premade')} onChange={this.updateType.bind(this, 'premade')}
aria-controls='premadeThemesSection'
/> />
<FormattedMessage <FormattedMessage
id='user.settings.display.theme.themeColors' id='user.settings.display.theme.themeColors'
@@ -206,8 +207,6 @@ export default class ThemeSetting extends React.PureComponent<Props, State> {
); );
} }
inputs.push(premade);
if (this.props.allowCustomThemes) { if (this.props.allowCustomThemes) {
inputs.push( inputs.push(
<div <div
@@ -221,6 +220,7 @@ export default class ThemeSetting extends React.PureComponent<Props, State> {
name='theme' name='theme'
checked={displayCustom} checked={displayCustom}
onChange={this.updateType.bind(this, 'custom')} onChange={this.updateType.bind(this, 'custom')}
aria-controls='customThemesSection'
/> />
<FormattedMessage <FormattedMessage
id='user.settings.display.theme.customTheme' id='user.settings.display.theme.customTheme'
@@ -230,7 +230,7 @@ export default class ThemeSetting extends React.PureComponent<Props, State> {
</div>, </div>,
); );
inputs.push(custom); inputs.push(premade, custom);
inputs.push( inputs.push(
<div key='otherThemes'> <div key='otherThemes'>
@@ -271,7 +271,19 @@ export default class ThemeSetting extends React.PureComponent<Props, State> {
themeUI = ( themeUI = (
<SettingItemMax <SettingItemMax
inputs={inputs} inputs={
<fieldset>
<legend className='hidden-label'>
<FormattedMessage
id='user.settings.display.theme.title'
defaultMessage='Theme'
/>
</legend>
<div>
{inputs}
</div>
</fieldset>
}
submitExtra={allTeamsCheckbox} submitExtra={allTeamsCheckbox}
submit={this.submitTheme} submit={this.submitTheme}
disableEnterSubmit={true} disableEnterSubmit={true}

Просмотреть файл

@@ -371,6 +371,11 @@
white-space: nowrap; white-space: nowrap;
} }
.premadeThemeButton{
border: none;
background: none;
}
label { label {
width: 100%; width: 100%;
} }
@@ -407,13 +412,22 @@
} }
.theme-elements__header { .theme-elements__header {
padding: 1px 0 10px;
border-bottom: 1px solid; border-bottom: 1px solid;
margin: 10px 20px 0 0; margin: 10px 20px 0 0;
cursor: pointer; cursor: pointer;
font-size: functions.em(13.5px); font-size: functions.em(13.5px);
font-weight: 600; font-weight: 600;
button {
display: flex;
width: 100%;
align-items: center;
justify-content: space-between;
padding: 10px 1px;
border: none;
background: none;
}
.fa-minus { .fa-minus {
display: none; display: none;
} }