Skip to content

Commit 883ea48

Browse files
fix(ui): keep checked checkbox checkmark legible across themes (#9074)
1 parent 6d9d4bc commit 883ea48

2 files changed

Lines changed: 31 additions & 4 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@clerk/ui": patch
3+
---
4+
5+
Fix the checked checkbox appearing as a blank filled box in dark themes. The checkmark now uses the `colorPrimaryForeground` theme color, so it stays legible against the checkbox background across light, dark, and custom themes.

packages/ui/src/primitives/Input.tsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ import { common, createVariants, mqu } from '../styledSystem';
66
import { sanitizeInputProps, useFormField } from './hooks/useFormField';
77
import { useInput } from './hooks/useInput';
88

9+
/**
10+
* Checkmark shape for a checked checkbox, used as a CSS mask rather than a tinted
11+
* background-image. Only the shape's alpha matters here; the visible checkmark color
12+
* comes from `backgroundColor` on the masked element, which lets it reference the
13+
* `colorPrimaryForeground` theme token (a CSS variable / `light-dark()` value would
14+
* not resolve if it were baked into the SVG fill).
15+
*/
16+
const checkboxCheckmarkMask = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23000' fill-rule='evenodd' d='M7.712.233a.889.889 0 0 1 .055 1.256C6.742 2.61 6.249 3.291 5.508 4.615c-.279.5-.589 1.194-.835 1.784a36.761 36.761 0 0 0-.382.95l-.021.057-.006.014-.001.003a.89.89 0 0 1-1.504.27L.218 4.765A.889.889 0 1 1 1.56 3.6l1.591 1.834c.235-.548.524-1.181.806-1.685.807-1.445 1.38-2.239 2.499-3.46A.889.889 0 0 1 7.712.234Z' clip-rule='evenodd'/%3E%3C/svg%3E")`;
17+
918
const { applyVariants, filterProps } = createVariants((theme, props) => ({
1019
base: {
1120
boxSizing: 'border-box',
@@ -24,12 +33,25 @@ const { applyVariants, filterProps } = createVariants((theme, props) => ({
2433
appearance: 'none',
2534
height: theme.sizes.$4,
2635
padding: theme.space.$1,
27-
backgroundSize: `${theme.sizes.$2} ${theme.sizes.$2}`,
28-
backgroundPosition: 'center',
29-
backgroundRepeat: 'no-repeat',
3036
'&:checked': {
31-
backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 8 8'%3E%3Cpath fill='${theme.colors.$white}' fill-rule='evenodd' d='M7.712.233a.889.889 0 0 1 .055 1.256C6.742 2.61 6.249 3.291 5.508 4.615c-.279.5-.589 1.194-.835 1.784a36.761 36.761 0 0 0-.382.95l-.021.057-.006.014-.001.003a.89.89 0 0 1-1.504.27L.218 4.765A.889.889 0 1 1 1.56 3.6l1.591 1.834c.235-.548.524-1.181.806-1.685.807-1.445 1.38-2.239 2.499-3.46A.889.889 0 0 1 7.712.234Z' clip-rule='evenodd'/%3E%3C/svg%3E")`,
37+
position: 'relative',
3238
backgroundColor: theme.colors.$primary500,
39+
// Draw the checkmark on a masked overlay so its color tracks the
40+
// colorPrimaryForeground token and stays legible in every theme.
41+
'&::before': {
42+
content: '""',
43+
position: 'absolute',
44+
inset: 0,
45+
backgroundColor: theme.colors.$colorPrimaryForeground,
46+
maskImage: checkboxCheckmarkMask,
47+
WebkitMaskImage: checkboxCheckmarkMask,
48+
maskPosition: 'center',
49+
WebkitMaskPosition: 'center',
50+
maskRepeat: 'no-repeat',
51+
WebkitMaskRepeat: 'no-repeat',
52+
maskSize: `${theme.sizes.$2} ${theme.sizes.$2}`,
53+
WebkitMaskSize: `${theme.sizes.$2} ${theme.sizes.$2}`,
54+
},
3355
},
3456
}
3557
: {}),

0 commit comments

Comments
 (0)