@cerebruminc/cerebellum 17.3.6 → 17.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # react-component-lib-boilerplate
2
2
 
3
+ ## [17.3.7](https://github.com/cerebruminc/cerebellum/compare/v17.3.6...v17.3.7) (2026-06-23)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **upload-dropzone:** increase contrast in UploadDropzone ([ca12fb3](https://github.com/cerebruminc/cerebellum/commit/ca12fb3e092138e49580e00d901dd3dc8a29bd58))
9
+
3
10
  ## [17.3.6](https://github.com/cerebruminc/cerebellum/compare/v17.3.5...v17.3.6) (2026-06-22)
4
11
 
5
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cerebruminc/cerebellum",
3
- "version": "17.3.6",
3
+ "version": "17.3.7",
4
4
  "description": "Cerebrum's React Component Library",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -1,9 +1,11 @@
1
1
  import { fireEvent, render, screen } from "@testing-library/react";
2
2
  import React from "react";
3
3
  import { act } from "react-dom/test-utils";
4
+ import { contrast } from "../../helpers/accessibility";
4
5
  import { noop } from "../../helpers/utils";
5
- import { FileTypeEnum } from "../../sharedTypes/enums";
6
6
  import { withTheme } from "../../hocs/withTheme";
7
+ import { FileTypeEnum } from "../../sharedTypes/enums";
8
+ import { cerebellumTheme } from "../../theme";
7
9
  import { UploadDropzone } from "./UploadDropzone";
8
10
 
9
11
  const ThemedUploadDropzone = withTheme(UploadDropzone);
@@ -70,3 +72,40 @@ describe("UploadDropzone", () => {
70
72
  expect(await screen.findByText("ping.json - Invalid file type")).toBeInTheDocument();
71
73
  });
72
74
  });
75
+
76
+ describe("UploadDropzone color contrast (WCAG 2.1 AA)", () => {
77
+ const WCAG_AA_TEXT = 4.5;
78
+
79
+ // Source directly from the theme so these tests catch regressions in
80
+ // both the token values and the theme wiring (e.g. textColor, secondaryText).
81
+ const textColor = cerebellumTheme.uploadDropzone.textColor;
82
+
83
+ const colorFamilyPairs = [
84
+ {
85
+ family: "Purple",
86
+ accent: cerebellumTheme.colorFamilies.PURPLE.secondaryText!,
87
+ background: cerebellumTheme.colorFamilies.PURPLE.light,
88
+ },
89
+ {
90
+ family: "Blue",
91
+ accent: cerebellumTheme.colorFamilies.BLUE.secondaryText!,
92
+ background: cerebellumTheme.colorFamilies.BLUE.light,
93
+ },
94
+ {
95
+ family: "Red",
96
+ accent: cerebellumTheme.colorFamilies.RED.secondaryText!,
97
+ background: cerebellumTheme.colorFamilies.RED.light,
98
+ },
99
+ ];
100
+
101
+ test.each(colorFamilyPairs)("$family: body text (COOL_GREY_70) achieves >= 4.5:1 contrast against light background", ({ background }) => {
102
+ expect(contrast(textColor, background)).toBeGreaterThanOrEqual(WCAG_AA_TEXT);
103
+ });
104
+
105
+ test.each(colorFamilyPairs)(
106
+ "$family: accent color (secondaryText) achieves >= 4.5:1 contrast against light background",
107
+ ({ accent, background }) => {
108
+ expect(contrast(accent, background)).toBeGreaterThanOrEqual(WCAG_AA_TEXT);
109
+ }
110
+ );
111
+ });
@@ -1,9 +1,9 @@
1
1
  import React, { FC, useCallback, useEffect, useRef, useState } from "react";
2
2
  import { useTheme } from "styled-components";
3
3
 
4
+ import { colors } from "../../const/colors";
4
5
  import { CloseCircle, File, FileComplete, FileError as FileErrorIcon, UploadDocument } from "../Icons";
5
6
  import { TextLink } from "../TextLink";
6
- import { colors } from "../../const/colors";
7
7
  import {
8
8
  DropZoneContainer,
9
9
  DropzoneBox,
@@ -22,13 +22,13 @@ import {
22
22
  import { DropzoneColorFamilyEnum, FileError, UploadDropzoneType } from "./types";
23
23
 
24
24
  import { FileRejection, useDropzone } from "react-dropzone";
25
- import { Truncate } from "../Truncate";
26
25
  import { formatBytesToString } from "../../helpers/numbers";
27
26
  import useMeasure from "../../hooks/useMeasure";
28
27
  import { showLabel } from "../../sharedHelpers/showLabel";
29
28
  import { Asterisk, LabelBox, ValidationText } from "../../sharedStyle/Inputs";
30
29
  import { TextStyleEnum } from "../../sharedTypes/enums";
31
30
  import { ASTERISK_OFFSET_SPACE } from "../Input/helpers";
31
+ import { Truncate } from "../Truncate";
32
32
  import { TextVariantEnum, Typography } from "../Typography";
33
33
  import { createAcceptObject, defaultDescripion } from "./helpers";
34
34
 
@@ -57,6 +57,7 @@ export const UploadDropzone: FC<UploadDropzoneType> = ({
57
57
  const theme = useTheme();
58
58
  const { colorFamilies } = theme;
59
59
  const colorGroup = colorFamilyOverride || colorFamilies[dropzoneColorFamily || DropzoneColorFamilyEnum.Purple];
60
+ const accentColor = colorGroup.secondaryText || colorGroup.main;
60
61
  const acceptObject = createAcceptObject(acceptedFileTypes);
61
62
 
62
63
  const [errorSummary, setErrorSummary] = useState<Array<FileError>>([]);
@@ -186,7 +187,7 @@ export const UploadDropzone: FC<UploadDropzoneType> = ({
186
187
  {displayFileInline && !multipleFileUploads && errorSummary?.[0] ? (
187
188
  <InlineFileItemBox>
188
189
  <InlineIconBox>
189
- {errorSummary.length > 0 ? <FileErrorIcon fill={theme.input.failColor} /> : <FileComplete fill={colorGroup.hover} />}
190
+ {errorSummary.length > 0 ? <FileErrorIcon fill={theme.input.failColor} /> : <FileComplete fill={accentColor} />}
190
191
  </InlineIconBox>
191
192
  <InlineFileTextBox>
192
193
  <Truncate>{errorSummary?.[0]?.name}</Truncate>
@@ -210,12 +211,11 @@ export const UploadDropzone: FC<UploadDropzoneType> = ({
210
211
  <UploadIconBox>
211
212
  <UploadDocument
212
213
  boxColor={disabled ? theme?.uploadDropzone?.disabledColorLight : colorGroup.medium}
213
- fill={disabled ? theme.uploadDropzone.disabledColorDark : colorGroup.hover}
214
+ fill={disabled ? theme.uploadDropzone.disabledColorDark : accentColor}
214
215
  />
215
216
  </UploadIconBox>
216
217
  <TextSection $disabled={disabled} $isDragging={isDragActive} $themeOverride={themeOverride}>
217
- {description ||
218
- defaultDescripion(disabled ? theme.uploadDropzone.disabledColorText : colorGroup.hover, acceptObject, disabled)}
218
+ {description || defaultDescripion(disabled ? theme.uploadDropzone.disabledColorText : accentColor, acceptObject, disabled)}
219
219
  </TextSection>
220
220
  </>
221
221
  )}
@@ -237,7 +237,7 @@ export const UploadDropzone: FC<UploadDropzoneType> = ({
237
237
  {fileList.map((item, idx) => (
238
238
  <FileItemBox key={`fileitem_${item?.name}_${idx}`}>
239
239
  <ItemIconBox>
240
- <File fill={colorGroup.hover} />
240
+ <File fill={accentColor} />
241
241
  </ItemIconBox>
242
242
  <Truncate>{item.name}</Truncate>
243
243
  <RightAligned>
package/src/theme.ts CHANGED
@@ -806,6 +806,7 @@ export const cerebellumTheme: DefaultTheme = {
806
806
  main: colors.PURPLE_55,
807
807
  hover: colors.PURPLE_70,
808
808
  text: colors.WHITE,
809
+ secondaryText: colors.PURPLE_75,
809
810
  },
810
811
  RED: {
811
812
  light: colors.RED_5,
@@ -1332,7 +1333,7 @@ export const cerebellumTheme: DefaultTheme = {
1332
1333
  listDeleteColor: colors.BLUE_100,
1333
1334
  minHeight: 180,
1334
1335
  paddingString: "37px 26px 32px 26px",
1335
- textColor: "#767689",
1336
+ textColor: colors.COOL_GREY_70,
1336
1337
  },
1337
1338
  userCard: {
1338
1339
  avatarBackgroundColor: colors.BLUE_55,