From b9f6e971356e961be8f6c7b60f9c181414d6735e Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Sun, 1 Mar 2026 16:22:24 +0000
Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Standardize=20CustomC?=
=?UTF-8?q?heckbox=20with=20grid=20and=20accessibility=20props?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: godie <227743+godie@users.noreply.github.com>
---
src/components/PlayerCasoContainer.jsx | 1 -
src/components/Profile.jsx | 19 ++--
src/components/admin/AnswerForm.jsx | 37 ++++---
src/components/custom/CustomCheckbox.jsx | 98 +++++++++++++++----
src/components/custom/CustomCheckbox.test.jsx | 85 ++++++++++++++++
5 files changed, 195 insertions(+), 45 deletions(-)
create mode 100644 src/components/custom/CustomCheckbox.test.jsx
diff --git a/src/components/PlayerCasoContainer.jsx b/src/components/PlayerCasoContainer.jsx
index 44ffcf7..e8d138c 100644
--- a/src/components/PlayerCasoContainer.jsx
+++ b/src/components/PlayerCasoContainer.jsx
@@ -5,7 +5,6 @@ import ExamService from "../services/ExamService";
import { useHistory } from 'react-router-dom';
import { alertError, alertSuccess } from "../services/AlertService";
import CasoContext from "../context/CasoContext";
-import { CustomButton } from "./custom";
import EnarmUtil from "../modules/EnarmUtil";
import ContributionTypeSelector from "./ContributionTypeSelector";
import ContributionsSummary from "./ContributionsSummary";
diff --git a/src/components/Profile.jsx b/src/components/Profile.jsx
index 70cda21..642ade9 100644
--- a/src/components/Profile.jsx
+++ b/src/components/Profile.jsx
@@ -302,14 +302,17 @@ const Profile = () => {
{categories.map(cat => {
const isSelected = selectedSpecialties.includes(cat.id);
return (
-
- toggleSpecialty(cat.id)}
- />
-
+ toggleSpecialty(cat.id)}
+ s={12}
+ m={6}
+ l={4}
+ style={{ marginBottom: '1rem' }}
+ />
);
})}
diff --git a/src/components/admin/AnswerForm.jsx b/src/components/admin/AnswerForm.jsx
index faa8cce..e99ff50 100644
--- a/src/components/admin/AnswerForm.jsx
+++ b/src/components/admin/AnswerForm.jsx
@@ -25,25 +25,24 @@ const AnswerForm = ({
return (
-
-
- {
- onChangeAnswer(
- questionIndex,
- answerIndex,
- "is_correct",
- event
- );
- }}
- name={answerIsCorrectName}
- value="true"
- />
-
-
+ {
+ onChangeAnswer(
+ questionIndex,
+ answerIndex,
+ "is_correct",
+ event
+ );
+ }}
+ name={answerIsCorrectName}
+ value="true"
+ />
{
const inputRef = useRef(null);
@@ -26,22 +34,70 @@ const CustomCheckbox = ({
inputClasses += ' indeterminate-checkbox';
}
- // The main wrapper is the label for Materialize checkboxes
- return (
-
+ // Construct grid and wrapper classes
+ const hasGrid = s || m || l || xl || offset || wrapperClassName;
+ let finalWrapperClasses = wrapperClassName;
+ if (s) finalWrapperClasses += ` col s${s}`;
+ if (m) finalWrapperClasses += ` col m${m}`;
+ if (l) finalWrapperClasses += ` col l${l}`;
+ if (xl) finalWrapperClasses += ` col xl${xl}`;
+ if (offset) {
+ offset.split(' ').forEach(off => {
+ if (off) finalWrapperClasses += ` offset-${off}`;
+ });
+ }
+
+ const helperTextId = helperText ? `${id}-helper` : undefined;
+
+ const checkboxContent = (
+ <>
+
+ {helperText && {helperText}}
+ >
);
+
+ if (hasGrid) {
+ return (
+
+ {checkboxContent}
+
+ );
+ }
+
+ return checkboxContent;
};
CustomCheckbox.propTypes = {
@@ -54,6 +110,14 @@ CustomCheckbox.propTypes = {
labelClassName: PropTypes.string, // For the label element
indeterminate: PropTypes.bool,
value: PropTypes.string, // HTML value attribute for the checkbox
+ s: PropTypes.number,
+ m: PropTypes.number,
+ l: PropTypes.number,
+ xl: PropTypes.number,
+ offset: PropTypes.string,
+ required: PropTypes.bool,
+ helperText: PropTypes.string,
+ wrapperClassName: PropTypes.string,
};
export default CustomCheckbox;
diff --git a/src/components/custom/CustomCheckbox.test.jsx b/src/components/custom/CustomCheckbox.test.jsx
new file mode 100644
index 0000000..dfc413d
--- /dev/null
+++ b/src/components/custom/CustomCheckbox.test.jsx
@@ -0,0 +1,85 @@
+import { render, screen } from '@testing-library/react';
+import { describe, test, expect } from 'vitest';
+import CustomCheckbox from './CustomCheckbox';
+
+describe('CustomCheckbox', () => {
+ test('renders correctly with label', () => {
+ render();
+ expect(screen.getByLabelText(/Test Label/)).toBeInTheDocument();
+ });
+
+ test('applies grid classes and style to wrapper div', () => {
+ const { container } = render(
+
+ );
+
+ const wrapper = container.firstChild;
+ expect(wrapper.tagName).toBe('DIV');
+ expect(wrapper).toHaveClass('col');
+ expect(wrapper).toHaveClass('s12');
+ expect(wrapper).toHaveClass('m6');
+ expect(wrapper).toHaveClass('offset-s1');
+ expect(wrapper).toHaveStyle('margin-bottom: 16px');
+ expect(wrapper).toHaveAttribute('data-testid', 'outer-wrapper');
+ });
+
+ test('applies style and custom props to label if not wrapped in div', () => {
+ const { container } = render(
+
+ );
+ const label = container.firstChild;
+ expect(label.tagName).toBe('LABEL');
+ expect(label).toHaveStyle('color: red');
+ expect(label).toHaveAttribute('data-custom', 'test');
+ });
+
+ test('renders required indicator and aria-required', () => {
+ render();
+
+ const input = screen.getByLabelText(/Required Label/);
+ expect(input).toHaveAttribute('aria-required', 'true');
+
+ const asterisk = screen.getByTitle('Obligatorio');
+ expect(asterisk).toBeInTheDocument();
+ expect(asterisk).toHaveClass('red-text');
+ expect(asterisk.textContent).toBe('*');
+ });
+
+ test('renders helper text and links with aria-describedby', () => {
+ render();
+
+ const helper = screen.getByText('Be careful');
+ expect(helper).toBeInTheDocument();
+ expect(helper).toHaveClass('helper-text');
+ expect(helper).toHaveAttribute('id', 'help-check-helper');
+
+ const input = screen.getByLabelText(/Help Label/);
+ expect(input).toHaveAttribute('aria-describedby', 'help-check-helper');
+ });
+
+ test('does not wrap in div if no grid or wrapperClassName provided', () => {
+ const { container } = render();
+ expect(container.firstChild.tagName).toBe('LABEL');
+ });
+
+ test('wraps in div if wrapperClassName is provided', () => {
+ const { container } = render(
+
+ );
+ expect(container.firstChild.tagName).toBe('DIV');
+ expect(container.firstChild).toHaveClass('custom-wrap');
+ });
+});