diff --git a/components/inputs/input-checkbox-styles.js b/components/inputs/input-checkbox-styles.js
new file mode 100644
index 00000000000..dd478b1593c
--- /dev/null
+++ b/components/inputs/input-checkbox-styles.js
@@ -0,0 +1,119 @@
+import { css, unsafeCSS } from 'lit';
+import { _isValidCssSelector } from '../../helpers/internal/css.js';
+import { registerSemanticVariableForSvgImageUrl } from '../colors/colors.js';
+
+registerSemanticVariableForSvgImageUrl(
+ '--d2l-input-checkbox-check-image',
+ ``
+);
+
+registerSemanticVariableForSvgImageUrl(
+ '--d2l-input-checkbox-indeterminate-image',
+ ``
+);
+
+export const cssSizes = {
+ inputBoxSize: 1.2,
+ checkboxMargin: 0.5,
+};
+
+/**
+ * A private helper method that should not be used by general consumers
+ */
+export const _generateInputCheckboxStyles = (selector) => {
+ if (!_isValidCssSelector(selector)) return;
+
+ const selectorCSS = unsafeCSS(selector);
+ return css`
+ ${selectorCSS} {
+ --d2l-input-checkbox-background-image: none;
+ --d2l-input-checkbox-background-color: var(--d2l-theme-background-color-interactive-faint-default);
+ --d2l-input-checkbox-background-image-disabled:
+ linear-gradient(
+ var(--d2l-theme-background-color-interactive-faint-disabled),
+ var(--d2l-theme-background-color-interactive-faint-disabled)
+ ),
+ var(--d2l-input-checkbox-background-image);
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ background-image: var(--d2l-input-checkbox-background-image);
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: ${cssSizes.inputBoxSize}rem ${cssSizes.inputBoxSize}rem;
+ border-radius: 0.3rem;
+ border-style: solid;
+ box-sizing: border-box;
+ display: inline-block;
+ height: ${cssSizes.inputBoxSize}rem;
+ margin: 0;
+ padding: 0;
+ vertical-align: middle;
+ width: ${cssSizes.inputBoxSize}rem;
+ }
+ ${selectorCSS}:checked {
+ --d2l-input-checkbox-background-image: var(--d2l-input-checkbox-check-image);
+ }
+ ${selectorCSS}:indeterminate {
+ --d2l-input-checkbox-background-image: var(--d2l-input-checkbox-indeterminate-image);
+ }
+ ${selectorCSS},
+ ${selectorCSS}:hover:disabled {
+ background-color: var(--d2l-input-checkbox-background-color);
+ border-color: var(--d2l-theme-border-color-emphasized);
+ border-width: 1px;
+ }
+ ${selectorCSS}:hover:disabled {
+ border-color: var(--d2l-theme-border-color-disabled);
+ }
+ ${selectorCSS}:hover,
+ ${selectorCSS}:focus,
+ ${selectorCSS}.d2l-input-checkbox-focus,
+ :host(.d2l-hovering) input[type="checkbox"]:not(:disabled).d2l-input-checkbox {
+ border-color: var(--d2l-input-checkbox-border-color-hover-focus, var(--d2l-theme-border-color-focus));
+ border-width: 2px;
+ outline: none;
+ }
+ ${selectorCSS}:disabled,
+ ${selectorCSS}:where([aria-disabled="true"]) {
+ background-image: var(--d2l-input-checkbox-background-image-disabled);
+ border-color: var(--d2l-theme-border-color-disabled);
+ }
+ @media (forced-colors: active) {
+ ${selectorCSS}:checked,
+ ${selectorCSS}:indeterminate {
+ background-image: none;
+ position: relative;
+ }
+ ${selectorCSS}:checked::after,
+ ${selectorCSS}:indeterminate::after {
+ background-color: FieldText;
+ content: "";
+ display: block;
+ height: ${cssSizes.inputBoxSize}rem;
+ left: 50%;
+ position: absolute;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ width: ${cssSizes.inputBoxSize}rem;
+ }
+
+ ${selectorCSS}:disabled,
+ ${selectorCSS}:where([aria-disabled="true"]) {
+ opacity: var(--d2l-theme-opacity-disabled-control);
+ }
+
+ ${selectorCSS}:checked::after {
+ mask-image: var(--d2l-input-checkbox-check-image);
+ }
+
+ ${selectorCSS}:indeterminate::after {
+ mask-image: var(--d2l-input-checkbox-indeterminate-image);
+ }
+ }
+ `;
+};
diff --git a/components/inputs/input-checkbox.js b/components/inputs/input-checkbox.js
index 287cd0ec191..960bc77155e 100644
--- a/components/inputs/input-checkbox.js
+++ b/components/inputs/input-checkbox.js
@@ -1,5 +1,6 @@
import '../expand-collapse/expand-collapse-content.js';
import '../tooltip/tooltip.js';
+import { _generateInputCheckboxStyles, cssSizes } from './input-checkbox-styles.js';
import { css, html, LitElement, nothing } from 'lit';
import { classMap } from 'lit/directives/class-map.js';
import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
@@ -8,116 +9,9 @@ import { getUniqueId } from '../../helpers/uniqueId.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { InputInlineHelpMixin } from './input-inline-help.js';
import { offscreenStyles } from '../offscreen/offscreen.js';
-import { registerSemanticVariableForSvgImageUrl } from '../colors/colors.js';
import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
-registerSemanticVariableForSvgImageUrl(
- '--d2l-input-checkbox-check-image',
- ``
-);
-
-registerSemanticVariableForSvgImageUrl(
- '--d2l-input-checkbox-indeterminate-image',
- ``
-);
-
-export const cssSizes = {
- inputBoxSize: 1.2,
- checkboxMargin: 0.5,
-};
-
-export const checkboxStyles = css`
- input[type="checkbox"].d2l-input-checkbox {
- --d2l-input-checkbox-background-image: none;
- --d2l-input-checkbox-background-color: var(--d2l-theme-background-color-interactive-faint-default);
- --d2l-input-checkbox-background-image-disabled:
- linear-gradient(
- var(--d2l-theme-background-color-interactive-faint-disabled),
- var(--d2l-theme-background-color-interactive-faint-disabled)
- ),
- var(--d2l-input-checkbox-background-image);
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background-image: var(--d2l-input-checkbox-background-image);
- background-position: center center;
- background-repeat: no-repeat;
- background-size: ${cssSizes.inputBoxSize}rem ${cssSizes.inputBoxSize}rem;
- border-radius: 0.3rem;
- border-style: solid;
- box-sizing: border-box;
- display: inline-block;
- height: ${cssSizes.inputBoxSize}rem;
- margin: 0;
- padding: 0;
- vertical-align: middle;
- width: ${cssSizes.inputBoxSize}rem;
- }
- input[type="checkbox"].d2l-input-checkbox:checked {
- --d2l-input-checkbox-background-image: var(--d2l-input-checkbox-check-image);
- }
- input[type="checkbox"].d2l-input-checkbox:indeterminate {
- --d2l-input-checkbox-background-image: var(--d2l-input-checkbox-indeterminate-image);
- }
- input[type="checkbox"].d2l-input-checkbox,
- input[type="checkbox"].d2l-input-checkbox:hover:disabled {
- background-color: var(--d2l-input-checkbox-background-color);
- border-color: var(--d2l-theme-border-color-emphasized);
- border-width: 1px;
- }
- input[type="checkbox"].d2l-input-checkbox:hover:disabled {
- border-color: var(--d2l-theme-border-color-disabled);
- }
- input[type="checkbox"].d2l-input-checkbox:hover,
- input[type="checkbox"].d2l-input-checkbox:focus,
- input[type="checkbox"].d2l-input-checkbox.d2l-input-checkbox-focus,
- :host(.d2l-hovering) input[type="checkbox"]:not(:disabled).d2l-input-checkbox {
- border-color: var(--d2l-input-checkbox-border-color-hover-focus, var(--d2l-theme-border-color-focus));
- border-width: 2px;
- outline: none;
- }
- input[type="checkbox"].d2l-input-checkbox:disabled,
- input[type="checkbox"].d2l-input-checkbox:where([aria-disabled="true"]) {
- background-image: var(--d2l-input-checkbox-background-image-disabled);
- border-color: var(--d2l-theme-border-color-disabled);
- }
- @media (forced-colors: active) {
- input[type="checkbox"].d2l-input-checkbox:checked,
- input[type="checkbox"].d2l-input-checkbox:indeterminate {
- background-image: none;
- position: relative;
- }
- input[type="checkbox"].d2l-input-checkbox:checked::after,
- input[type="checkbox"].d2l-input-checkbox:indeterminate::after {
- background-color: FieldText;
- content: "";
- display: block;
- height: ${cssSizes.inputBoxSize}rem;
- left: 50%;
- position: absolute;
- top: 50%;
- transform: translate(-50%, -50%);
- width: ${cssSizes.inputBoxSize}rem;
- }
-
- input[type="checkbox"].d2l-input-checkbox:disabled,
- input[type="checkbox"].d2l-input-checkbox:where([aria-disabled="true"]) {
- opacity: var(--d2l-theme-opacity-disabled-control);
- }
-
- input[type="checkbox"].d2l-input-checkbox:checked::after {
- mask-image: var(--d2l-input-checkbox-check-image);
- }
-
- input[type="checkbox"].d2l-input-checkbox:indeterminate::after {
- mask-image: var(--d2l-input-checkbox-indeterminate-image);
- }
- }
-`;
+export const checkboxStyles = _generateInputCheckboxStyles('input[type="checkbox"].d2l-input-checkbox');
/**
* A component that can be used to show a checkbox and optional visible label.
diff --git a/components/table/table-wrapper.js b/components/table/table-wrapper.js
index 780249f5348..48cfec4545d 100644
--- a/components/table/table-wrapper.js
+++ b/components/table/table-wrapper.js
@@ -2,7 +2,7 @@ import '../colors/colors.js';
import '../scroll-wrapper/scroll-wrapper.js';
import '../backdrop/backdrop-loading.js';
import { css, html, LitElement, nothing } from 'lit';
-import { cssSizes } from '../inputs/input-checkbox.js';
+import { cssSizes } from '../inputs/input-checkbox-styles.js';
import { getComposedParent } from '../../helpers/dom.js';
import { getFlag } from '../../helpers/flags.js';
import { ifDefined } from 'lit/directives/if-defined.js';
diff --git a/helpers/internal/css.js b/helpers/internal/css.js
index e7231ed9cba..623a793b01a 100644
--- a/helpers/internal/css.js
+++ b/helpers/internal/css.js
@@ -1,6 +1,6 @@
export function _isValidCssSelector(selector) {
const partIsValid = (part) => {
- const re = /([a-zA-Z0-9-_ >.#]+)(\[[a-zA-Z0-9-_]+\])?([a-zA-Z0-9-_ >.#]+)?/g;
+ const re = /([a-zA-Z0-9-_ >.#]+)(\[[a-zA-Z0-9-_="]+\])?([a-zA-Z0-9-_ >.#]+)?/g;
if (part === ':host') return true;
const match = part.match(re);
const isValid = !!match && match.length === 1 && match[0].length === part.length;
diff --git a/components/typography/test/styles.test.js b/helpers/test/css.test.js
similarity index 94%
rename from components/typography/test/styles.test.js
rename to helpers/test/css.test.js
index 6e7d94a78ff..ea867169229 100644
--- a/components/typography/test/styles.test.js
+++ b/helpers/test/css.test.js
@@ -1,4 +1,4 @@
-import { _isValidCssSelector } from '../../../helpers/internal/css.js';
+import { _isValidCssSelector } from '../internal/css.js';
import { expect } from '@brightspace-ui/testing';
describe('_isValidCssSelector', () => {
@@ -33,6 +33,7 @@ describe('_isValidCssSelector', () => {
expect(_isValidCssSelector('dl #id')).to.be.true;
expect(_isValidCssSelector('dl > dt')).to.be.true;
expect(_isValidCssSelector('dl > dt > dd')).to.be.true;
+ expect(_isValidCssSelector('input[type="checkbox"].d2l-input-checkbox')).to.be.true;
});
it('should support simple :host selector', () => {