Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 30 additions & 25 deletions components/inputs/input-select-styles.js
Comment thread
dlockhart marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,24 +1,46 @@
import './input-styles.js';
import { css, unsafeCSS } from 'lit';
import { getFocusRingStyles, getFocusVisibleStyles } from '../../helpers/focus.js';
import { _isValidCssSelector } from '../../helpers/internal/css.js';
import { getFocusPseudoClass } from '../../helpers/focus.js';
import { registerSemanticVariableForSvgImageUrl } from '../colors/colors.js';

const focusClass = unsafeCSS(getFocusPseudoClass());

registerSemanticVariableForSvgImageUrl(
'--d2l-input-select-chevron-image',
`<svg width="11" height="7" viewBox="0 0 11 7" xmlns="http://www.w3.org/2000/svg">
<path d="M1 2l4.5 4M10 2L5.5 6" stroke="var(--d2l-theme-icon-color-standard)" stroke-width="2" fill="none" fill-rule="evenodd" stroke-linecap="round"/>
</svg>`
);

function _getSelectFocusStyles(selector) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm personally finding the addition of this helper really confusing to follow the before & after, vs. just calling into getFocusVisibleStyles directly from _generateSelectStyles right inline.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo i think should be pretty straight forward. what I did was only to group styles and selectors into this function, and then use the returned object there. I decided to created this helper function to encapsulate the logic that replaces the getPseudoClass from above

const notDisabledSelector = (focusSelector) => `
${selector}:not([disabled]):hover,
${selector}:not([disabled]):${focusSelector}`;
const ariaInvalidSelector = (focusSelector) => `
${selector}[aria-invalid="true"],
${selector}[aria-invalid="true"]:${focusSelector},
${selector}[aria-invalid="true"]:hover`;

return {
notDisabled: getFocusRingStyles(notDisabledSelector, {
extraStyles: css`
box-shadow: inset var(--d2l-theme-shadow-inset-offset-x) var(--d2l-theme-shadow-inset-offset-y) var(--d2l-theme-shadow-inset-blur-radius) 2px var(--d2l-theme-shadow-inset-color);

--d2l-focus-ring-offset: -2px;`,
preferContrastMediaQueryExtraStyles: css`box-shadow: none;`
}),
ariaInvalid: getFocusVisibleStyles(ariaInvalidSelector, (selector) => css`${selector} {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule is being used both inside and outside the media query, so just added it once

outline-color: var(--d2l-theme-status-color-error);
}`)
};
}

/**
* A private helper method that should not be used by general consumers
*/
export function _generateSelectStyles(selector) {
if (!_isValidCssSelector(selector)) return '';
const finalSelector = unsafeCSS(selector);
const selectFocusStyles = _getSelectFocusStyles(finalSelector);

return css`
${finalSelector} {
Expand Down Expand Up @@ -51,23 +73,16 @@ export function _generateSelectStyles(selector) {
vertical-align: middle;
}

${finalSelector}:not([disabled]):hover,
${finalSelector}:not([disabled]):${focusClass} {
box-shadow: inset var(--d2l-theme-shadow-inset-offset-x) var(--d2l-theme-shadow-inset-offset-y) var(--d2l-theme-shadow-inset-blur-radius) 2px var(--d2l-theme-shadow-inset-color);
outline: 2px solid var(--d2l-theme-border-color-focus);
outline-offset: -2px;
}
${selectFocusStyles.notDisabled}

${finalSelector}[aria-invalid="true"] {
background-image: var(--d2l-input-select-chevron-image), var(--d2l-input-invalid-image);
background-position: center var(--d2l-inline-end, right) 17px, center var(--d2l-inline-end, right) calc(1px + 11px + 17px);
background-repeat: no-repeat, no-repeat;
background-size: 11px 7px, 0.8rem 0.8rem;
}
${finalSelector}[aria-invalid="true"],
${finalSelector}[aria-invalid="true"]:${focusClass},
${finalSelector}[aria-invalid="true"]:hover {
outline-color: var(--d2l-theme-status-color-error);
}
${selectFocusStyles.ariaInvalid}

${finalSelector}:disabled {
opacity: var(--d2l-theme-opacity-disabled-control);
}
Expand All @@ -87,12 +102,6 @@ export function _generateSelectStyles(selector) {
padding-inline: 0.6rem 16px;
}

${finalSelector}:not([disabled]):${focusClass},
${finalSelector}:not([disabled]):hover {
box-shadow: none;
outline: 2px solid Highlight;
}

${finalSelector}:disabled {
outline: 1px solid GrayText;
}
Expand All @@ -104,11 +113,7 @@ export function _generateSelectStyles(selector) {
background-size: 0.8rem 0.8rem;
}

${finalSelector}[aria-invalid="true"],
${finalSelector}[aria-invalid="true"]:${focusClass},
${finalSelector}[aria-invalid="true"]:hover {
outline-color: var(--d2l-theme-status-color-error);
}
${selectFocusStyles.ariaInvalid}
}
`;
};
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified components/inputs/test/golden/input-select/chromium/sass-rtl.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 10 additions & 3 deletions components/inputs/test/input-select.vdiff.js

@EdwinACL831 EdwinACL831 Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added back the code in the vdiffs just to make sure they are still looking as expected. Here is the report. this will be reverted once we are happy (get some thumbs up) with the changes and their results

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, give me a bit longer to review this before reverting.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../demo/input-select-test.js';
import { expect, fixture, focusElem, html } from '@brightspace-ui/testing';
import { loadSass, unloadSass } from '../../../test/load-sass.js';
import { _generateSelectStyles } from '../input-select-styles.js';

const defaultFixture = html`<d2l-test-input-select></d2l-test-input-select>`;
const overflowFixture = html`<d2l-test-input-select overflow></d2l-test-input-select>`;
Expand All @@ -12,8 +12,15 @@ const sassInvalidFixture = html`<select class="d2l-test-input-select" aria-inval

describe('d2l-input-select', () => {

before(loadSass);
after(unloadSass);
before(() => {
const style = document.createElement('style');
style.id = 'generated-css';
style.textContent = _generateSelectStyles('.d2l-test-input-select').cssText;
document.head.appendChild(style);
});
after(() => {
document.getElementById('generated-css').remove();
});

[
{ name: 'default', template: defaultFixture, allColorModes: true },
Expand Down
6 changes: 5 additions & 1 deletion helpers/focus.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,13 @@ export function getFocusableDescendants(node, options) {
return focusables;
}

/**
* @deprecated Use getFocusVisibleStyles instead.
*/
export function getFocusPseudoClass() {
return isFocusVisibleSupported() ? 'focus-visible' : 'focus';
}
export function getFocusRingStyles(selector, { extraStyles = null } = {}) {
export function getFocusRingStyles(selector, { extraStyles = null, preferContrastMediaQueryExtraStyles = null } = {}) {
const stylesDelegate = selector => css`
${selector} {
${extraStyles ?? css``}
Expand All @@ -84,6 +87,7 @@ export function getFocusRingStyles(selector, { extraStyles = null } = {}) {
}
@media (prefers-contrast: more) {
${selector} {
${preferContrastMediaQueryExtraStyles ?? css``}
outline-color: Highlight;
}
}
Expand Down
5 changes: 5 additions & 0 deletions test/node-imports-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ describe('node imports', () => {
assert.ok(t._generateHeading4Styles);
});

it('should import input select styles in a node environment', async() => {
const t = await import('../components/inputs/input-select-styles.js');
assert.ok(t._generateSelectStyles);
});

});