Skip to content

Commit

Permalink
Merge pull request #7276 from craftcms/hotfix/login-page-a11y
Browse files Browse the repository at this point in the history
Login page accessibility improvements

Resolves #7268
Resolves #7287
Resolves #7288
  • Loading branch information
brandonkelly committed Dec 24, 2020
2 parents 816f0c0 + 2cbf337 commit f93cf84
Show file tree
Hide file tree
Showing 19 changed files with 277 additions and 284 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

### Changed
- Improved the error message that is output when running the `clear-caches/cp-resources` command, if the `@webroot` alias isn’t explicitly set. ([#7286](https://github.com/craftcms/cms/issues/7286))
- Improved the accessibility of the Login page. ([#7268](https://github.com/craftcms/cms/issues/7268), [#7287](https://github.com/craftcms/cms/issues/7287), [#7288](https://github.com/craftcms/cms/issues/7288))
- Added `aria-label` or `aria-hidden` attributes to control panel icons, where appropriate. ([#7302](https://github.com/craftcms/cms/pull/7302))

### Fixed
Expand Down
116 changes: 66 additions & 50 deletions src/templates/login.html
Expand Up @@ -3,12 +3,9 @@
{% set title = "Login"|t('app') %}
{% set bodyClass = 'login' %}
{% do view.registerAssetBundle("craft\\web\\assets\\login\\LoginAsset") %}
{% do view.registerTranslations('app', [
"Reset Password",
"Check your email for instructions to reset your password.",
]) %}

{% set username = craft.app.config.general.rememberUsernameDuration ? craft.app.user.getRememberedUsername(): '' %}
{% set showRememberMe = craft.app.config.general.rememberedUserSessionDuration %}

{% if craft.app.config.general.useEmailAsUsername %}
{% set usernameLabel = 'Email'|t('app') %}
Expand All @@ -23,67 +20,86 @@
{% set formAttributes = {
id: 'login-form',
method: 'post',
class: showRememberMe ? 'remember-me' : '',
'accept-charset': 'UTF-8',
} %}

{% if hasLogo %}
{% set logo = craft.rebrand.logo %}
{% set formAttributes = formAttributes|merge({
class: 'has-logo',
style: {
'background-image': "url(#{logo.url|e('css')})",
'background-size': "#{logo.width}px #{logo.height}px",
'padding-top': "#{logo.height + 30}px",
},
}) %}
{% endif %}

{% set formHtml %}
<main>
<form {{ attr(formAttributes) }}>
{% if not hasLogo %}
<h1>{{ systemName }}</h1>
{% endif %}
<div id="login-fields">
{{ forms.textField({
id: 'loginName',
name: 'username',
placeholder: usernameLabel,
value: username,
autocomplete: 'username',
type: usernameType,
inputAttributes: {
aria: {
label: usernameLabel,
<div id="login">

<h1>
{% if hasLogo %}
{{ tag('img', {
id: 'login-logo',
src: logo.url,
alt: systemName,
width: logo.width,
height: logo.height,
}) }}
{% else %}
{{ systemName }}
{% endif %}
</h1>

<form {{ attr(formAttributes) }}>

<div id="login-form-top">
{{ forms.textField({
id: 'loginName',
name: 'username',
placeholder: usernameLabel,
value: username,
autocomplete: 'username',
type: usernameType,
inputAttributes: {
aria: {
label: usernameLabel,
required: 'true',
},
},
},
}) }}
{{ forms.passwordField({
id: 'password',
name: 'password',
placeholder: 'Password'|t('app'),
autocomplete: 'current-password',
inputAttributes: {
aria: {
label: 'Password'|t('app'),
}) }}
{{ forms.passwordField({
id: 'password',
name: 'password',
placeholder: 'Password'|t('app'),
autocomplete: 'current-password',
inputAttributes: {
aria: {
label: 'Password'|t('app'),
required: 'true',
},
},
},
}) }}
</div>
<div id="password-fields">
{% if craft.app.config.general.rememberedUserSessionDuration %}
{{ forms.checkboxField({ id: 'rememberMe', label: 'Keep me logged in'|t('app') }) }}
{% endif %}
<a id="forgot-password">{{ 'Forgot your password?'|t('app') }}</a>
</div>
<div class="buttons">
<button id="submit" class="btn submit disabled" type="submit">{{ 'Login'|t('app') }}</button>
<div id="spinner" class="spinner hidden"></div>
}) }}
</div>

<div id="login-form-bottom">
{% if showRememberMe %}
{{ forms.checkboxField({ id: 'rememberMe', label: 'Keep me logged in'|t('app') }) }}
{% endif %}
<button id="forgot-password" type="button">{{ 'Forgot your password?'|t('app') }}</button>
<button id="remember-password" type="button">{{ 'Remember your password?'|t('app') }}</button>
</div>

<div class="buttons">
<button id="submit" class="btn submit" type="submit">{{ 'Login'|t('app') }}</button>
<div id="spinner" class="spinner hidden"></div>
</div>
</form>

<div id="login-errors" role="alert">
</div>

<a id="poweredby" href="http://craftcms.com/" title="{{ 'Powered by Craft CMS'|t('app') }}" aria-label="{{ 'Powered by Craft CMS'|t('app') }}">
{{ svg('@app/web/assets/cp/dist/images/craftcms.svg') }}
</a>
</form>

</div>

</main>
{% endset %}

Expand Down
2 changes: 2 additions & 0 deletions src/translations/en/app.php
Expand Up @@ -691,6 +691,7 @@
'Interlacing' => 'Interlacing',
'Internal Server Error' => 'Internal Server Error',
'Invalid email or password.' => 'Invalid email or password.',
'Invalid email.' => 'Invalid email.',
'Invalid password.' => 'Invalid password.',
'Invalid transform handle: {handle}' => 'Invalid transform handle: {handle}',
'Invalid username or email.' => 'Invalid username or email.',
Expand Down Expand Up @@ -1041,6 +1042,7 @@
'Release all jobs' => 'Release all jobs',
'Release job' => 'Release job',
'Release' => 'Release',
'Remember your password?' => 'Remember your password?',
'Remove files and folders' => 'Remove files and folders',
'Remove files uploaded by other users' => 'Remove files uploaded by other users',
'Remove it' => 'Remove it',
Expand Down
14 changes: 12 additions & 2 deletions src/validators/UserPasswordValidator.php
Expand Up @@ -19,6 +19,16 @@
*/
class UserPasswordValidator extends StringValidator
{
/**
* @since 3.5.18
*/
const MIN_PASSWORD_LENGTH = 6;

/**
* @since 3.5.18
*/
const MAX_PASSWORD_LENGTH = 160;

/**
* @var bool Whether the password must be different from the existing password.
*/
Expand All @@ -41,12 +51,12 @@ public function __construct(array $config = [])
{
// Default min
if (!isset($config['min'])) {
$config['min'] = 6;
$config['min'] = self::MIN_PASSWORD_LENGTH;
}

// Default max
if (!isset($config['max'])) {
$config['max'] = 160;
$config['max'] = self::MAX_PASSWORD_LENGTH;
}

parent::__construct($config);
Expand Down
6 changes: 6 additions & 0 deletions src/web/assets/cp/dist/css/craft.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/web/assets/cp/dist/css/craft.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/web/assets/cp/dist/images/craftcms.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/web/assets/cp/dist/js/Craft.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/web/assets/cp/dist/js/Craft.min.js.map

Large diffs are not rendered by default.

0 comments on commit f93cf84

Please sign in to comment.