Ottawa, Ontario
Account created on 19 July 2005, about 20 years ago
#

Recent comments

🇨🇦Canada mgifford Ottawa, Ontario

Another approach is to add an underline to the button.

@media screen and (min-width: 48em) {
  .is-horizontal .tabs--primary .tabs__link.is-active {
    border-bottom: 3px solid color-mix(in srgb, currentColor 40%, black);
    padding-bottom: 0.25rem;
  }
}
🇨🇦Canada mgifford Ottawa, Ontario

As discussed in the A11y Practice Area Meeting.

🇨🇦Canada mgifford Ottawa, Ontario

As discussed in the A11y Practice Area Meeting.

🇨🇦Canada mgifford Ottawa, Ontario

Thanks Liam. I'll see if I can get someone to renew it.

🇨🇦Canada mgifford Ottawa, Ontario

Can we get the API page link and the project description updated?

The link here didn't work for me.

https://api.drupal.org/api/drupal/core%21includes%21theme.inc/function/t...

A screnshot would be nice too.

🇨🇦Canada mgifford Ottawa, Ontario

I think this is a bug and that there is code to be reviewed.

🇨🇦Canada mgifford Ottawa, Ontario

I think this would do the trick - https://git.drupalcode.org/issue/drupal-3083583/-/compare/11.x...11.x

but I'm not even sure where all of these forms are showing up to test.

🇨🇦Canada mgifford Ottawa, Ontario

So we need it for the Menu settings for node editing:
/node/2/edit?destination=/admin/content

I am not seeing a way to include the title here:
/admin/structure/types/manage/page/fields

This may not be the only place it exist, but I wanted to see some changes on this. We may need to refer back to this to remove other elements of the title text.

🇨🇦Canada mgifford Ottawa, Ontario

Yes. That sounds right to me. Using the same color would make it easier to identify. Thanks.

🇨🇦Canada mgifford Ottawa, Ontario

I think this would be better:

.ckeditor5-toolbar-item {
  border: 1px solid #8A8A8A;
}

.ckeditor5-toolbar-disabled .ckeditor5-toolbar-item {
  border: 1px solid #8A8A8A;
}

🇨🇦Canada mgifford Ottawa, Ontario

I tried to update the patch here https://git.drupalcode.org/issue/drupal-867830/-/compare/11.x...867830-u...

The numbering may not matter, but because @lauriii is wonderful, the numbers aren't what I thought they were.

I think these are complementary issues, but definitely related.

🇨🇦Canada mgifford Ottawa, Ontario

@vsujeetkumar it has been 2 years, so this will need to be re-rolled.

What comments are still unaddressed?

@pasqualle suggested an approach that @ricksta recommended. I think the summary there is new variable "status_marker" and mark the old ones deprecated.

We would need a new variable name I think.

🇨🇦Canada mgifford Ottawa, Ontario

@kthull failing an automated test isn't the end of the world. There are often false positives. Of course it is easier if the automated tests pass.

Interesting to consider though if role=status would be sufficient substitution. Worth looking into a bit more. Thanks!

🇨🇦Canada mgifford Ottawa, Ontario

Thanks @siddharthjain_7998 & @jurgenhaas

I'll try to figure this out in the future.

🇨🇦Canada mgifford Ottawa, Ontario

Sadly, I need more information. This is a 3 line change (one little search/replace). npm build locally doesn't work for me Unknown command: "build".

It is a pretty trivial patch, but I still don't know how to contribute it.

diff --git a/styles/theme/variables.scss b/styles/theme/variables.scss
index 8e37e68b..ede2f940 100644
--- a/styles/theme/variables.scss
+++ b/styles/theme/variables.scss
@@ -12,7 +12,7 @@
   --gin-color-disabled-bg: #eaeaea;
   --gin-color-disabled-border: #c2c2c2;
 
-  --gin-color-warning: #d8b234;
+  --gin-color-warning: #9d6e04;
   --gin-color-warning-light: #efcf64;
   --gin-bg-warning: #{mix(black, #efcf64, 70%)};
   --gin-bg-warning-light: rgba(226, 151, 0, .08);
@@ -35,7 +35,7 @@
   --gin-status-bg: #eee;
   --gin-status-success-text: #1d6844;
   --gin-status-success-bg: #26a76930;
-  --gin-status-warning-text: #{mix(black, #d8b234, 40%)};
+  --gin-status-warning-text: #{mix(black, #9d6e04, 40%)};
   --gin-status-warning-bg: rgba(226, 151, 0, .15);
   --gin-status-danger-text: #cc3d3d;
   --gin-status-danger-bg: rgba(222, 117, 96, .15);
@@ -292,7 +292,7 @@
   --gin-status-bg: rgba(255, 255, 255, 0.12);
   --gin-status-success-text: #8bd3b1;
   --gin-status-success-bg: #26a76940;
-  --gin-status-warning-text: #{mix(white, #d8b234, 40%)};
+  --gin-status-warning-text: #{mix(white, #9d6e04, 40%)};
   --gin-status-warning-bg: rgba(226, 151, 0, .15);
   --gin-status-danger-text: #{mix(white, #cc3d3d, 50%)};
   --gin-status-danger-bg: rgba(222, 117, 96, .15);
🇨🇦Canada mgifford Ottawa, Ontario

There are a few code changes in the MR, but the most important one for this is this code --gin-border-color: #d4d4d8;
changing to --gin-border-color: #838585;

Just to compare the greys https://coolors.co/contrast-checker/838585-d4d4d8

The big thing here is that are these going to work in dark mode, and with forced-colors.

🇨🇦Canada mgifford Ottawa, Ontario

This is still a good idea.

As a start we could include it in the CKEditor Toolbar configuration admin/config/content/formats

🇨🇦Canada mgifford Ottawa, Ontario

Nobody is working on CKEditor 4 now I believe.

🇨🇦Canada mgifford Ottawa, Ontario

Very cool @itmaybejj

So we can close this when Editoria11y becomes part of Core?

🇨🇦Canada mgifford Ottawa, Ontario

@sandip that's interesting with the sticky header, but given that the sticky isn't visible, this is still a bug.

🇨🇦Canada mgifford Ottawa, Ontario

Is it better to loose the semantics by dropping the H2 or to retain the heading order? I'm not sure.

🇨🇦Canada mgifford Ottawa, Ontario

What else is needed to move this to RTBC?

🇨🇦Canada mgifford Ottawa, Ontario

mgifford created an issue.

🇨🇦Canada mgifford Ottawa, Ontario

I'm just playing around with options here, but:

tr.views-form__bulk-operations-row.selected {
  font-weight: 600;
  font-size: 1.1rem;

  background: linear-gradient(to right,
    rgba(var(--gin-color-primary-rgb), 0.15) 0%,
    #fff 10%,
    #fff 90%,
    rgba(var(--gin-color-primary-rgb), 0.15) 100%
  );
                              
  /* 12px solid outline in the accent color */
  outline: 12px solid rgba(var(--gin-color-primary-light-rgb), 0.5);  
  outline-offset: -12px;
}

/* Underline and darken links inside selected row */
tr.views-form__bulk-operations-row.selected a {
  text-decoration: underline;
  color: #111;
}

/* Ensure no other styles override the selected state */
tr.views-form__bulk-operations-row a:hover {
  text-decoration: underline;
  color: #111;
}

Now I don't pretend to be a designer, but I think we can find an alternative which can highlight the sticky bar (and the hover for that matter) while also meeting WCAG and looking sharp.

🇨🇦Canada mgifford Ottawa, Ontario

Using accessibility Insights I was able to duplicate and provide a screenshot of this.

I start in the Title field to make it easier.

The first round through the table goes fine, but when you get to Updated, it gets screwed up. You can see in the numbers that it looks like it goes 1, 2, 3, 4, 10, 6, 7 , 8, 9 (although the last numbers are hard to see).

After "Updated" what I see is that it goes to an empty focus item.

Then it jumps back to the beginning of the header menu and continues on. It just does that once, but it is an extra redundant (and buggy) step.

🇨🇦Canada mgifford Ottawa, Ontario

Now I'm not sure, but I just tried this and wasn't able to replicate it.

In your video it is easy to see the duplication.

I couldn't see it when I explored it locally:

I think this will required more steps for testing.

🇨🇦Canada mgifford Ottawa, Ontario

I like your suggestion around use of mask-image or mask @kentr.

🇨🇦Canada mgifford Ottawa, Ontario

Just looking at more info around strategies for this.

In terms of how we are addressing this:

https://tetralogical.com/blog/2022/12/20/foundations-target-size/

the Target Size (Minimum) criterion is perhaps misleading. It won't guarantee that there are no small targets. It defines an ideal minimum size, but also allows an exception for smaller targets with sufficient spacing. The intent of the criterion is not to make sure targets are large enough to be comfortably activated, but to avoid having targets that are too small clustered closely together, which would otherwise increase the likelihood of a person accidentally activating an adjacent target.

Some exceptions to the rule:

https://dubbot.com/dubblog/2024/staying-on-target.html

It is also important to take into consideration the exceptions to WCAG 2.5.8, which are:

  • If smaller targets (less than 24 x 24 CSS pixels) are arranged so that, when a 24 CSS pixel diameter circle is centered on each target's bounding box, the circles don't overlap with other targets or their circles.
  • Equivalent: The function can be achieved through a different control on the same page that meets this criterion. For instance, in the following screenshot, the targets in the upper right corner are 15px with no minimum spacing, while the ones further down the page are 24px with no minimum spacing. Therefore, the criterion has been met.
  • Inline: The target is in a sentence, or its size is otherwise constrained by the line height. For example, contextual links may be constrained by the vertical spacing between lines of text or the leading.
    • User-agent control: The size of the target is determined by the user agent and is not modified by the author. For example:
    • the options list of
      dropdowns
    • date picker for the HTML date input
    • color picker for the HTML color input
  • Essential: A particular presentation of the target is essential or is legally required for the information being conveyed. For example, the target must be a certain size or shape.

Some other good guidance from Eric Bailey https://www.smashingmagazine.com/2024/07/getting-bottom-minimum-wcag-con... and Adrian Roselli

🇨🇦Canada mgifford Ottawa, Ontario

I suspect that some JS like this will be needed:

(function () {
  const MIN_CONTRAST = 4.5;
  const BACKGROUNDS = [
    { hex: '#ffffff', name: 'white' },
    { hex: '#2A2A2D', name: 'dark grey' }
  ];

  const fields = [
    {
      inputId: 'edit-accent-color',
      warningId: 'accent-warning',
    },
    {
      inputId: 'edit-focus-color',
      warningId: 'focus-warning',
    },
  ];

  function hexToRgb(hex) {
    const val = hex.replace('#', '');
    return {
      r: parseInt(val.slice(0, 2), 16) / 255,
      g: parseInt(val.slice(2, 4), 16) / 255,
      b: parseInt(val.slice(4, 6), 16) / 255,
    };
  }

  function luminance({ r, g, b }) {
    const adjust = (c) =>
      c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
    return (
      0.2126 * adjust(r) + 0.7152 * adjust(g) + 0.0722 * adjust(b)
    );
  }

  function contrastRatio(l1, l2) {
    const [a, b] = [l1, l2].sort((x, y) => y - x);
    return (a + 0.05) / (b + 0.05);
  }

  function updateWarning(field) {
    const input = document.getElementById(field.inputId);
    const existing = document.getElementById(field.warningId);
    if (existing) existing.remove();

    const val = input.value;
    if (!/^#[0-9a-fA-F]{6}$/.test(val)) return;

    const fgLum = luminance(hexToRgb(val));
    const fails = BACKGROUNDS.filter((bg) => {
      const bgLum = luminance(hexToRgb(bg.hex));
      return contrastRatio(fgLum, bgLum) < MIN_CONTRAST;
    });

    if (fails.length) {
      const msg = document.createElement('div');
      msg.id = field.warningId;
      msg.style.color = 'red';
      msg.style.marginTop = '0.25rem';
      msg.textContent =
        '⚠️ Low contrast against: ' +
        fails.map((f) => f.name).join(', ') +
        ` (min ${MIN_CONTRAST}:1)`;
      input.parentNode.appendChild(msg);
    }
  }

  document.addEventListener('DOMContentLoaded', () => {
    fields.forEach((field) => {
      const input = document.getElementById(field.inputId);
      if (input) {
        input.addEventListener('input', () => updateWarning(field));
        updateWarning(field); // initial check
      }
    });
  });
})();
🇨🇦Canada mgifford Ottawa, Ontario

Some more observations on the colors in Gin.

There are 11 Accent colors, 4 different Focus colors, plus Dark/Light modes. That's a lot of combinations. Probably too many combinations to be able to provide good guidance.

Drupal Core should be providing a good example. We have as a community committed to striving to meet WCAG 2.2 AA standards. This is especially true of Core and Drupal CMS.

Light Mode:

Dark Mode (Looks good):

I believe adding a space in the focus outline should make addressing this easier. We can state a white or dark inner circle before the focus outline color.

The WCAG Success Criterion 1.4.1 (Use of Color) in question.

The least 3:1 I think would just need to be the background.

LIght Mode

  • Gin Focus color (Default) - #71B3FC / #FFFFFF - Failed (Could we not just use #5996EC)
  • Green - #78C9BE / #FFFFFF - Failed (Could we not just use #58A19D)
  • Claro Green - #85CBA8 / #FFFFFF - Failed (Could we not just use #739E8C)<
  • Orange - #F4B39E / #FFFFFF - Failed (Could we not just use #709F87)
  • Neutral - #A3A3A3 / #FFFFFF - Failed (Could we not just use #989494)
  • Same as Accent color - See above
  • Custom - N/A - we are restricting this to good defaults

Dark Mode

WebAim also has this interesting Link Contrast Checker.

🇨🇦Canada mgifford Ottawa, Ontario

Can we spend some time optimizing them before bringing them into Core?

https://www.svgviewer.dev/
https://optimize.svgomg.net/

For instance, 948 bytes:

<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M11 0L14 3V16H2V0H11Z" fill="#fff"/>
  <path d="M11 0L14 3V16H2V0H11ZM3 15H13V4H10V1H3V15ZM11 3H12.5L11 1.5V3Z" fill="#7f7f7f"/>
  <path d="M4 2H9V3H4V2Z" fill="#dadada"/>
  <path d="M4 3H9V4H4V3Z" fill="#e0e0e0"/>
  <path d="M4 4H9V5H4V4Z" fill="#ebebeb"/>
  <path d="M4 5H12V6H4V5Z" fill="#eee"/>
  <path d="M4 6H12V7H4V6Z" fill="#f5f5f5"/>
  <path d="M4 7H12V8H4V7Z" fill="#f8f8f8"/>
  <path d="M4 8H12V9H4V8Z" fill="#fcfcfc"/>
  <path d="M4 3H9V4H4V3Z" fill="#9e9e9e"/>
  <path d="M6 8H4V7H6V8ZM12 8H7V7H12V8Z" fill="#9e9e9e" fill-opacity="0.65"/>
  <path d="M8 6H4V5H8V6ZM12 6H9V5H12V6Z" fill="#9e9e9e" fill-opacity="0.8"/>
  <path d="M8 10H4V9H8V10ZM12 10H9V9H12V10Z" fill="#9e9e9e" fill-opacity="0.45"/>
  <path d="M6 12H4V11H6V12ZM10 12H7V11H10V12ZM12 12H11V11H12V12Z" fill="#9e9e9e" fill-opacity="0.3"/>
</svg>

Than 803 bytes:
<svg xmlns="http://www.w3.org/2000/svg" fill="none" aria-hidden="true" viewBox="0 0 16 16"><path fill="#fff" d="m11 0 3 3v13H2V0z"/><path fill="#7f7f7f" d="m11 0 3 3v13H2V0zM3 15h10V4h-3V1H3zm8-12h1.5L11 1.5z"/><path fill="#dadada" d="M4 2h5v1H4z"/><path fill="#e0e0e0" d="M4 3h5v1H4z"/><path fill="#ebebeb" d="M4 4h5v1H4z"/><path fill="#eee" d="M4 5h8v1H4z"/><path fill="#f5f5f5" d="M4 6h8v1H4z"/><path fill="#f8f8f8" d="M4 7h8v1H4z"/><path fill="#fcfcfc" d="M4 8h8v1H4z"/><path fill="#9e9e9e" d="M4 3h5v1H4z"/><path fill="#9e9e9e" fill-opacity=".7" d="M6 8H4V7h2zm6 0H7V7h5z"/><path fill="#9e9e9e" fill-opacity=".8" d="M8 6H4V5h4zm4 0H9V5h3z"/><path fill="#9e9e9e" fill-opacity=".5" d="M8 10H4V9h4zm4 0H9V9h3z"/><path fill="#9e9e9e" fill-opacity=".3" d="M6 12H4v-1h2zm4 0H7v-1h3zm2 0h-1v-1h1z"/></svg>

These are little, but they add up, with every page load.

It could get smaller still if we simplifed how it looks.

🇨🇦Canada mgifford Ottawa, Ontario

Going to Chi's comment in #5

"Claro is using content property for drawing the separators. The possible fix would be to use background-image instead like Olivero does."

I think we need to go from:

.breadcrumb__item + .breadcrumb__item::before {
  display: inline-block;
  padding: 0 0.75rem;
  content: url(...); /* SVG image as content */
}

To something like:

.breadcrumb__item + .breadcrumb__item {
  position: relative;
  padding-left: 1rem; /* or adjust as needed */
}

.breadcrumb__item + .breadcrumb__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 0.5rem;
  height: 0.5rem;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' height='8' width='5'%3e%3cpath fill='currentColor' d='M1.207.647L.5 1.354 3.146 4 .5 6.647l.707.707L4.561 4z'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-size: contain;
}

Using a background-image avoids the problem because backgrounds are considered purely decorative by user agents and not exposed to screen readers.

While messing with this code, why not optimize the carrot (less than arrow, whatever):

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5 8"><path fill="currentColor" d="m1.2.6-.7.8L3.1 4 .5 6.6l.7.8L4.6 4z"/></svg>

This is probably better:

.breadcrumb__item + .breadcrumb__item {
  position: relative;
  padding-left: 1rem; 
}

.breadcrumb__item + .breadcrumb__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 0.5rem;
  height: 0.5rem;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 8'%3e%3cpath fill='currentColor' d='m1.2.6-.7.8L3.1 4 .5 6.6l.7.8L4.6 4z'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-size: contain;
}
🇨🇦Canada mgifford Ottawa, Ontario

I made some small changes to the issue summary.

The latest MR adds the ARIA search role to the existing form.

It would be better though to switch core/modules/search/src/Form/SearchBlockForm.php & core/modules/search/src/Form/SearchPageForm.php to just use <search> though. HTML (including search) is always better, if possible, than using ARIA.

🇨🇦Canada mgifford Ottawa, Ontario

I think this color contrast looks good #000000 / #EEEEEE .

If you wanted the edge of the button to have contrast so that it sits above the FFF you could argue for:
#8A8A8A / #FFFFFF

As a background for the button. But I don't think that is what is generally needed for.

Mind you that does seem to be what is suggested here:
https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html#symbo...

I gotta say the grey buttons are ugly.

I'm also not convinced this is a Gin issue, as it is common in any CKEditor config here admin/config/content/formats/manage/content_format

🇨🇦Canada mgifford Ottawa, Ontario

I can move this to the navigation module.

Is there a duplicate issue for this, or are you suggesting there should be another issue opened up?

🇨🇦Canada mgifford Ottawa, Ontario

Ya, I think I filed this in the wrong place. I can move it, but what is the issue.

🇨🇦Canada mgifford Ottawa, Ontario

Just wanted to say that the images at the top came from the Basic Target Size Highlighter from:
https://accessibility-tools.github.io/target-size-highlighter/

There are reasons to use either the basic or Advanced Bookmarklet for this.

To see the outline more clearly in a Chrome Inspector, we can add:

a,
button,
input,
[role="button"],
[role="link"] {
  outline: 2px dashed red !important;
}

To ensure all buttons/links/icons have a minimum clickable size, can't we do something like:

a, button, input, .icon-button, .dropbutton__toggle {
  position: relative;
  min-width: 24px;
  min-height: 24px;
}

a {
  padding: 10px 15px;
  display: inline-block;
}

I like this idea for mobile devices (but that is a AAA SC at this point):

@media (hover: none) and (pointer: coarse) {
  button {
    min-width: 48px;
    min-height: 48px;
    margin: 10px;
  }
}

More on some of these from:
https://allyship.dev/blog/click-target-size

Nice to see Craft CMS aiming for AAA and 44px:

🇨🇦Canada mgifford Ottawa, Ontario

Moving this to Drupal Core as this affects most of Drupal. Gin's moving into Core, but the base problem isn't Gin.

🇨🇦Canada mgifford Ottawa, Ontario

I think that this builds better with the custom colors, but also allows for greater visibility:

.dropbutton-wrapper.open .dropbutton__items,
.dropbutton__items {
  background: var(--gin-bg-layer3, #fff);
  border-radius: var(--gin-border-l, 6px);
  padding: 0.5em;
  min-width: 120px;
  z-index: 9999;
  box-shadow:
    0 4px 8px rgba(var(--gin-color-primary-rgb, 0, 0, 0), 0.4),
    0 8px 20px rgba(0, 0, 0, 0.15) !important;
}

This certainly allows us to customize it more.

🇨🇦Canada mgifford Ottawa, Ontario

There are 11 Accent colors, 4 different Focus colors, plus Dark/Light modes. That's a lot of combinations. Probably too many combinations to be able to provide good guidance.

Drupal Core should be providing a good example. We have as a community committed to striving to meet WCAG 2.2 AA standards. This is especially true of Core and Drupal CMS.

#0750E6 / #FFF
#2E6DD0 / #FFF
#4300BF / #FFF
#5B00FF / #FFF
#0F857F / #FFF - Fail (could we not just use #088488)
#00875F / #FFF
#D12E70 / #FFF
#D8002E / #FFF
#DA6303 / #FFF - Fail (Could we not just use #B56026)
#111111 / #FFF

🇨🇦Canada mgifford Ottawa, Ontario

With the image provided, I've updated the Steps to reproduce above.

There are some possible improvements from:

@media (prefers-contrast: more), (forced-colors: active) {

  /* Save button (primary) */
  #edit-submit.form-submit,
  input[type="submit"].button--primary {
    forced-color-adjust: none;
    background-color: ButtonFace !important;
    color: ButtonText !important;
    border: 2px solid ButtonText !important;
    font-weight: bold;
    box-shadow: 0 0 0 2px ButtonText !important;
  }

  #edit-submit.form-submit:hover,
  #edit-submit.form-submit:focus-visible {
    background-color: Highlight !important;
    color: HighlightText !important;
    border-color: HighlightText !important;
    outline: 2px solid Highlight !important;
    outline-offset: 2px;
  }

  /* Preview button (secondary) */
  #gin-sticky-edit-preview.form-submit {
    forced-color-adjust: none;
    background-color: Canvas !important;
    color: ButtonText !important;
    border: 2px dashed ButtonText !important;
    font-weight: normal;
    box-shadow: 0 0 0 1px ButtonText !important;
  }

  #gin-sticky-edit-preview.form-submit:hover,
  #gin-sticky-edit-preview.form-submit:focus-visible {
    background-color: Highlight !important;
    color: HighlightText !important;
    border-color: HighlightText !important;
    outline: 2px solid Highlight !important;
    outline-offset: 2px;
  }

  /* Hide Sidebar Panel button */
  .meta-sidebar__trigger.trigger {
    forced-color-adjust: none;
    background-color: ButtonFace !important;
    color: ButtonText !important;
    border: 1px solid ButtonText !important;
    border-radius: 50%;
    width: 2.25rem;
    height: 2.25rem;
  }

  .meta-sidebar__trigger.trigger:hover,
  .meta-sidebar__trigger.trigger:focus-visible {
    background-color: Highlight !important;
    color: HighlightText !important;
    outline: 2px solid Highlight !important;
    outline-offset: 2px;
  }

  .meta-sidebar__trigger.trigger svg {
    fill: ButtonText !important;
  }
}

But I got a different looking input with forced colors enabled.

🇨🇦Canada mgifford Ottawa, Ontario

I think the menu module is the right place to do this.

I don't know if this should be just for folks who have configured their browsers correctly, but we can start with them:

@media (prefers-contrast: more), (forced-colors: active) {

  .admin-toolbar__expand-button {
    forced-color-adjust: none;
    background-color: ButtonFace !important;
    color: ButtonText !important;
    border: 4px solid ButtonText !important;
    box-shadow: none !important;
  }

  .admin-toolbar__expand-button:hover,
  .admin-toolbar__expand-button:focus-visible {
    background-color: Highlight !important;
    color: HighlightText !important;
    border-color: HighlightText !important;
    outline: 4px solid Highlight !important;
    outline-offset: 2px;
  }

  /* Make SVG chevron icon visible */
  .admin-toolbar__expand-button-chevron {
    fill: ButtonText !important;
    stroke: none !important;
  }
}

It would be interesting to see how that button features in user research. Certainly unsure how it would do with users who are using screen magnifiers.

🇨🇦Canada mgifford Ottawa, Ontario

This isn't a Gin issue specifically.

🇨🇦Canada mgifford Ottawa, Ontario

Sadly we can't use color-contrast() yet
https://caniuse.com/?search=color-contrast

Eventually, I think we might be able to do something like:

.button--primary {
  background-color: var(--accent);
  color: color-contrast(var(--accent) vs ButtonText, Black, White);
}

We really need to fix the accent colors. People can make choices with bad color contrast, but Drupal should not be presenting bad defaults to admins. We can't assume they are testing for color contrast (if we aren't).

.button--primary:hover,
input[type="submit"].button--primary:hover {
  background-color: #003078;
  border-color: #003078;
}

.button--secondary:hover {
  background-color: #f3f2f1;
  color: #003078;
  border-color: #003078;
}

@media (prefers-contrast: more) {
  /* Save Button (more prominent) */
  #edit-submit.form-submit,
  [data-drupal-selector="gin-sticky-edit-submit"] {
    background-color: #000 !important;
    color: #fff !important;
    border: 2px solid #000 !important;
    font-weight: bold;
  }

  /* Preview Button (less prominent) */
  [data-drupal-selector="gin-sticky-edit-preview"] {
    background-color: #fff !important;
    color: #000 !important;
    border: 2px solid #000 !important;
  }

  /* Shared focus style */
  #edit-submit.form-submit:focus-visible,
  [data-drupal-selector="gin-sticky-edit-preview"]:focus-visible {
    outline: 3px solid #000 !important;
    outline-offset: 2px;
    background-color: #ffbf47 !important; 
    color: #000 !important;
  }
}

@media (forced-colors: active) {
  /* Save Button (more prominent) */
  #edit-submit.form-submit,
  [data-drupal-selector="gin-sticky-edit-submit"] {
    forced-color-adjust: none;
    background-color: ButtonText !important;
    color: ButtonFace !important;
    border: 2px solid ButtonText !important;
    font-weight: bold;
  }

  /* Preview Button (less prominent) */
  [data-drupal-selector="gin-sticky-edit-preview"] {
    forced-color-adjust: none;
    background-color: Canvas !important;
    color: ButtonText !important;
    border: 2px solid ButtonText !important;
  }

  /* Focus visibility */
  #edit-submit.form-submit:focus-visible,
  [data-drupal-selector="gin-sticky-edit-preview"]:focus-visible {
    outline: 2px solid Highlight !important;
    outline-offset: 2px;
    background-color: Highlight !important;
    color: HighlightText !important;
  }
}
🇨🇦Canada mgifford Ottawa, Ontario

So I think this would help a lot:

.page-wrapper *:focus,.ui-dialog *:focus,.dropbutton .dropbutton__item > *:focus,.dropbutton .dropbutton__item > *:focus:hover,.dropbutton__items > .dropbutton__item:first-of-type > *:focus,.dropbutton__items > .dropbutton__item:first-of-type ~ .dropbutton__item > *:focus,.dropbutton__items > .dropbutton__item:first-of-type ~ .dropbutton__item > *:focus:hover,.form-boolean:focus:active,.form-boolean:focus:hover,.cke.cke_chrome.cke_focus,.horizontal-tabs ul.horizontal-tabs-list li.horizontal-tab-button a:focus,.form-element:focus,.form-element:hover:focus,.form-element.error:hover:focus,.form-actions .action-link:focus,.paragraphs-tabs-wrapper .field-multiple-table .draggable.drag,.layout-paragraphs-field .layout-paragraphs-actions input.layout-paragraphs-edit:focus,.layout-paragraphs-field .layout-paragraphs-actions input.layout-paragraphs-remove:focus,.ck .ck.ck-button:active,.ck .ck.ck-button:focus,.ck .ck.ck-button:active:focus,.toolbar-box .toolbar-handle:focus,.field-option:has(.field-option-radio:checked),.field-option:focus-within,.subfield-option:has(.field-option-radio:checked),.subfield-option:focus-within,#edit-submit.form-submit:focus,.toolbar-dropdown__menu .toolbar-dropdown__link:focus {
    outline: none;
    box-shadow: 0 0 0 2px var(--color-background, #fff), 0 0 0 5px var(--gin-color-focus);
}

I don't know why it isn't there on hover as well. I do think this would assist mouse users.

We need to do more to enhance the forced colors mode here, especially as the radio button doesn't look like a radio button, but rather three different buttons:

@media (forced-colors: active) {
  *:focus {
    outline: 6px solid Highlight !important;
    outline-offset: 2px;
    box-shadow: none !important;
  }
}

I am also a fan of how the UK government does their focus styling. As an example of how that could be done.

:root {
  --gin-color-focus-text: #0b0c0c;         /* GOV.UK black */
  --gin-color-focus-background: #ffdd00;   /* GOV.UK yellow */
}

/* -----------------------------------
   GDS-inspired global focus styling
----------------------------------- */

*:focus-visible {
  outline: 3px solid rgba(0, 0, 0, 0); /* suppress default outline */
  color: var(--gin-color-focus-text);
  background-color: var(--gin-color-focus-background);
  box-shadow:
    0 -2px var(--gin-color-focus-background),
    0 4px var(--gin-color-focus-text);
  text-decoration: none;
  z-index: 10;
}

/* -----------------------------------
   Gin-specific Form Focus Styles
----------------------------------- */

/* Light/Dark/Auto radio selection */
[data-drupal-selector="edit-enable-darkmode"] .form-radios input:checked + .form-item__label {
  color: var(--gin-color-button-text);
  background-color: var(--gin-color-primary);
  box-shadow:
    0 -2px var(--gin-color-focus-background),
    0 4px var(--gin-color-focus-text);
}

/* Classic toolbar and layout density radios */
[data-drupal-selector="edit-classic-toolbar"] .form-radios .form-item input:checked:focus,
[data-drupal-selector="edit-layout-density"] .form-radios .form-item input:checked:focus {
  box-shadow:
    0 -2px var(--gin-color-focus-background),
    0 4px var(--gin-color-focus-text);
  background-color: var(--gin-color-focus-background);
  color: var(--gin-color-focus-text);
}

/* Checkboxes not inside known exception wrappers */
:not(.form-checkboxes):not(td):not(.tabledrag-cell-content__item):not(.media-library-item__click-to-select-checkbox):not(.field-content):not(.ajax-new-content):not(.tablesaw-cell-content) 
> .form-type--checkbox input:focus {
  box-shadow:
    0 -2px var(--gin-color-focus-background),
    0 4px var(--gin-color-focus-text);
  background-color: var(--gin-color-focus-background);
  color: var(--gin-color-focus-text);
}

/* Optional: input[type="radio"] and input[type="checkbox"] globally */
input[type="radio"]:focus-visible,
input[type="checkbox"]:focus-visible {
  box-shadow:
    0 -2px var(--gin-color-focus-background),
    0 4px var(--gin-color-focus-text);
  background-color: var(--gin-color-focus-background);
  color: var(--gin-color-focus-text);
}

/* -----------------------------------
   Forced Colors Mode (High Contrast)
----------------------------------- */
@media (forced-colors: active) {
  *:focus-visible {
    outline: 2px solid Highlight !important;
    outline-offset: 2px;
    box-shadow: none !important;
    background-color: Highlight !important;
    color: HighlightText !important;
  }

  input[type="radio"]:checked + label,
  input[type="checkbox"]:checked + label {
    background-color: Highlight !important;
    color: HighlightText !important;
    font-weight: bold !important;
    border: 2px solid HighlightText !important;
    padding: 0.2em 0.5em !important;
  }
}
🇨🇦Canada mgifford Ottawa, Ontario

Do we have a list of the currently supported chips?

I made some suggested CSS changes:

@media (forced-colors: active) {
  .gin-status,
  .gin-new-flag,
  .gin-experimental-flag {
    forced-color-adjust: none;
    background-color: ButtonFace !important;
    color: ButtonText !important;
    border: 3px solid ButtonText !important;
  }
}

@media (prefers-contrast: more) {
  .gin-status,
  .gin-new-flag,
  .gin-experimental-flag {
    background-color: ButtonFace !important;
    color: ButtonText !important;
    border: 5px solid ButtonText !important;
    font-weight: bold;
  }
}

However, I'm just seeing the one chip now.

🇨🇦Canada mgifford Ottawa, Ontario

This occurs in the media system, but not sure it is restricted to it.

🇨🇦Canada mgifford Ottawa, Ontario

This CSS is an issue in both Gin & Claro, so this isn't a Gin specific issue. The CSS works reasonably well in both.

🇨🇦Canada mgifford Ottawa, Ontario

Ok, lets minimize the SVG and have it use the ButtonFace so it is more easily customizable

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="ButtonFace" d="M14.6 3 13 1.4a1 1 0 0 0-1.4 0l-1.3 1.4 3 3 1.2-1.3a1 1 0 0 0 0-1.4M5.2 13.6l-3-3 7-7 3 3zm-4.3 1c0 .3 0 .5.3.4l2-.7-1.6-1.6z"/></svg>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path stroke="ButtonFace" stroke-width="3" d="m2.3 2.3 11.4 11.4m-11.4 0L13.7 2.3"/></svg>

I think there will be better ways to do this, but just looking at the issue of the forced colors mode

@media (forced-colors: active) {
  /* Contextual trigger (pen icon) */
  .contextual .trigger {
    forced-color-adjust: none !important;
    background-color: ButtonFace !important;
    color: ButtonText !important;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='ButtonFace' d='M14.6 3 13 1.4a1 1 0 0 0-1.4 0l-1.3 1.4 3 3 1.2-1.3a1 1 0 0 0 0-1.4M5.2 13.6l-3-3 7-7 3 3zm-4.3 1c0 .3 0 .5.3.4l2-.7-1.6-1.6z'/%3e%3c/svg%3e") !important;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 16px 16px;
    border: 1px solid ButtonText !important;
    width: 26px;
    height: 26px;
    opacity: 1 !important;
  }

  .contextual .trigger:hover,
  .contextual .trigger:focus-visible {
    background-color: Highlight !important;
    color: HighlightText !important;
    outline: 2px solid Highlight !important;
  }

  /* Remove button (X icon) */
  .media-library-item__remove {
    forced-color-adjust: none !important;
    background-color: ButtonFace !important;
    color: ButtonText !important;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath stroke='ButtonFace' stroke-width='3' d='m2.3 2.3 11.4 11.4m-11.4 0L13.7 2.3'/%3e%3c/svg%3e") !important;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 0.75rem;
    border: 1px solid ButtonText !important;
    opacity: 1 !important;
  }

  .media-library-item__remove:hover,
  .media-library-item__remove:focus-visible {
    background-color: Highlight !important;
    color: HighlightText !important;
    outline: 2px solid Highlight !important;
  }

  /* Edit button (pen icon) */
  .media-library-item__edit {
    forced-color-adjust: none !important;
    background-color: ButtonFace !important;
    color: ButtonText !important;
    border: 1px solid ButtonText !important;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='ButtonFace' d='M14.6 3 13 1.4a1 1 0 0 0-1.4 0l-1.3 1.4 3 3 1.2-1.3a1 1 0 0 0 0-1.4M5.2 13.6l-3-3 7-7 3 3zm-4.3 1c0 .3 0 .5.3.4l2-.7-1.6-1.6z'/%3e%3c/svg%3e") !important;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 0.75rem;
    opacity: 1 !important;
  }

  .media-library-item__edit:hover,
  .media-library-item__edit:focus-visible {
    background-color: Highlight !important;
    color: HighlightText !important;
    outline: 2px solid Highlight !important;
  }
}

There is some JS which is is hiding edit pen when the mouse isn't hovering over the form:

<form class="views-exposed-form" aria-label="Filter the contents of the Media view" data-drupal-selector="views-exposed-form-media-library-page" action="/admin/content/media-grid" method="get" id="views-exposed-form-media-library-page" accept-charset="UTF-8" data-once="exposed-form">

It converts this:

<button class="trigger focusable visually-hidden" type="button" aria-pressed="false">Open  configuration options</button>

to this:
<button class="trigger focusable" type="button" aria-pressed="false">Open configuration options</button>

But it doesn't trigger for keyboard users (focus).

It should always be visible, especially in a high contrast mode.

🇨🇦Canada mgifford Ottawa, Ontario

Interesting. It works as expected in the Add Field Page.

But not in the Add Field Dialog.

🇨🇦Canada mgifford Ottawa, Ontario

@kentr I'd say that we make this change globally. If it were only in core themes it would be confusing. I'd agree that this should be fixed in core, and as such the Gin maintainers were right in having it marked it Won't Fix.

Would be nice to fix this bug before it turns 13.

🇨🇦Canada mgifford Ottawa, Ontario

We're now at 1.2 and there is a draft of 1.3
https://www.w3.org/WAI/standards-guidelines/aria/

Should we update this or start a new issue?

🇨🇦Canada mgifford Ottawa, Ontario

Might be a good fit first for Drupal CMS? Think we could be starting to ask more questions there? It is perhaps more useful to start asking questions and gathering information from those new to the community, than those already entrenched into D.o.

Both could be useful. I'm not arguing against involvement in Core. I see lots of ways that we could use Drupal itself to start promoting involvment in the Drupal community.

🇨🇦Canada mgifford Ottawa, Ontario

@scott_euser here is some reason comparisons between the two:

All three articles agree that AVIF’s superior compression leads to smaller image file sizes, which can reduce bandwidth usage and potentially lower energy consumption during data transmission. However, AVIF’s increased decoding time may require more processing power on the client side, possibly offsetting some energy savings.

🇨🇦Canada mgifford Ottawa, Ontario

With Drupal CMS the impact would be even bigger with all the contrib files. I do think this is worth exploring more. Would there ever be a need to produce a developer version (with the extra code), or is that just what you would find in Git?

And agreed @borisson_ it is about setting up good defaults for when everyone works to download Drupal (or Drupal CMS).

🇨🇦Canada mgifford Ottawa, Ontario

Are there advantages here with the latest version of PHPUnit? I don't actually know but there have been improvements since the last comment https://phpunit.de/announcements/phpunit-12.html

  • I believe we need to be searching for tests extending BrowserTestBase that perform setup through UI interactions.()
  • Then looking replacing browser interactions with direct API calls using services like entity_display.repository or entity storage handlers.()
  • Provide clear documentation within the test code to explain the rationale for using API calls over browser interactions.()
  • Measure test execution time before and after refactoring to quantify improvements.

Does that seem right?

🇨🇦Canada mgifford Ottawa, Ontario

So if we enabled File Hash and ensured that the duplicate file prevention was enabled, then this would be closed.

That seems more useful than the Audit Files module approach.

Think this should module should be considered for Drupal CMS?

🇨🇦Canada mgifford Ottawa, Ontario

Should we mark this as a duplicate and focus in on #3432765?

🇨🇦Canada mgifford Ottawa, Ontario

My understanding is that the Lighthouse test are the same as Deque's axe-core. Google uses axe-core.

🇨🇦Canada mgifford Ottawa, Ontario

Just adding @dunx to the metadata of this issue.

🇨🇦Canada mgifford Ottawa, Ontario

Bringing this up as there seem to be some outstanding issues.

We should be much closer to making this conversion the default though.

🇨🇦Canada mgifford Ottawa, Ontario

It has been over a year since someone looked at it. If @chi's perception of this is right, there are thousands more in savings that have been lost (let alone the environmental impact of running millions of processes on servers as part of this).

@joachim’s 2023 suggestion was to split the problem into separate issues for each test type. I tried to summarize would this would look like using ChatGPT to highlight what this would look like, along with justification and next steps. I'm mostly doing this to nudge this ahead.

Do these new issues sound like good places to begin? Has there been other work to do this already?

1. Kernel Tests: Optimize setUp() Execution

Goal: Avoid redundant setUp() execution for each method in Kernel tests.

Justification:
• Kernel tests do not boot the full stack and have fewer side effects.
• A shared setUp() could save significant time across large test classes.

Suggested New Issue:

“Optimize PHPUnit Kernel test execution by avoiding repeated setUp() calls per method.”

Action Items:
• Benchmark time saved when sharing setUp() across methods.
• Propose an attribute or annotation to allow opting in/out per class.
• Ensure tearDown cleanup logic remains reliable.

2. Browser Tests (Functional + FunctionalJavascript): Improve Test Efficiency

Goal: Investigate safe ways to cache installed sites between test methods in browser-based test classes.

Justification:
• Browser tests are the slowest due to full Drupal installs and HTTP interactions.
• Current design reinstalls Drupal for every method—even within the same class.

Suggested New Issue:

“Enable shared Drupal site installations across Browser test methods to reduce test run time.”

Action Items:
• Explore integration with #2900208 for site install caching.
• Identify classes that could safely share a site environment.
• Flag test classes with dependencies on state or side effects to avoid breaking isolation.

3. JavaScript Tests: Evaluate Efficiency Gains from Shared setUp()

Goal: Identify whether JS tests (Nightwatch or others) could benefit from setup sharing, or if they already do.

Justification:
• JS test infrastructure is separate (Node/Nightwatch/WebDriver), but setup redundancy may still exist.
• Even if not using PHPUnit, parallels in redundant test bootstrapping may exist.

Suggested New Issue:

“Audit and optimize Nightwatch JS tests for redundant setup executions across test methods.”

Action Items:
• Confirm whether test fixtures or browser states are rebuilt between methods.
• Identify opportunities for fixture reuse or browser session persistence.

Cross-Issue Meta Task: Central Coordination and Tracking

Create a meta issue to link all three above:

“Optimize test performance by limiting redundant setUp() execution across test types.”

Justification for Splitting

Joachim’s 2023 comment was correct: different test types have different performance bottlenecks, state requirements, and risk profiles. Attempting to solve them all in one issue creates blockers and lack of clarity. Splitting enables:
• Focused benchmarking
• Different contributors to work in parallel
• Faster consensus and review
• Targeted test infrastructure changes

🇨🇦Canada mgifford Ottawa, Ontario

Looking back at this issue now.

ImageAPI Optimize looks quite flexible, it will work for D10 & 11 but does require another 3rd party system. It would be interesting to see if that could be incorporated into Drupal CMS but unsure if it would be a good candidate for Core. Image optimization should be easy, but building in a 3rd party into Core would be a problem (not matter which one).

Imagemagick could also do the trick, and has more installs.

Some MIT projects that might be worth looking at:

🇨🇦Canada mgifford Ottawa, Ontario

There is going to be some overlap with https://www.drupal.org/project/gin/issues/3506350 🐛 Several icons and images are invisible in Forced Colors mode Active

Target is the Gin settings page admin/appearance/settings/gin

For the first item, this patch should be useful as this does provide an alternative for forced-colors:

@media (forced-colors: active) {
  input[type="radio"] {
    appearance: auto !important;
    forced-color-adjust: auto !important;
  }

  /* Reset default label styling for all options */
  input[type="radio"] + label {
    all: unset;
    display: inline-block;
    padding: 0.2em 0.5em;
  }

  /* Style the selected option */
  input[type="radio"]:checked + label {
    background-color: ButtonFace !important;
    color: ButtonText !important;
    font-weight: bold !important;
    text-decoration: underline !important;
    border: 2px solid HighlightText !important;
  }

  input[type="radio"]:focus-visible + label {
    outline: 2px solid Highlight !important;
    outline-offset: 2px;
  }
}
🇨🇦Canada mgifford Ottawa, Ontario

Removing forced-colors to avoid confusion with "high contrast" as they are treated the same here.

Production build 0.71.5 2024