-
-
Notifications
You must be signed in to change notification settings - Fork 53
number field component #1241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
number field component #1241
Conversation
WalkthroughA new modular NumberField component for React is introduced, consisting of a root context provider and three subcomponents (Input, Increment, Decrement). The implementation includes context management, state handling for controlled and uncontrolled usage, keyboard event support, and a dedicated SCSS stylesheet. Storybook stories demonstrate usage scenarios. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant NumberField.Root
participant NumberFieldContext
participant NumberField.Input
participant NumberField.Increment
participant NumberField.Decrement
User->>NumberField.Root: Render with props
NumberField.Root->>NumberFieldContext: Provide context (value, handlers)
User->>NumberField.Input: Render inside Root
NumberField.Input->>NumberFieldContext: Consume context (inputValue, handlers)
User->>NumberField.Increment: Render inside Root
NumberField.Increment->>NumberFieldContext: Consume context (handleStep)
User->>NumberField.Decrement: Render inside Root
NumberField.Decrement->>NumberFieldContext: Consume context (handleStep)
User->>NumberField.Input: Type or press arrow keys
NumberField.Input->>NumberFieldContext: Call handleOnChange or handleStep
NumberFieldContext->>NumberField.Root: Update value/state
Estimated code review effort3 (~45 minutes) Suggested labels
Suggested reviewers
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
npm error Exit handler never called! 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (3)
src/components/ui/NumberField/fragments/NumberFieldIncrement.tsx (1)
5-8: Fix missing semicolon in type definition.The
classNameproperty is missing a semicolon.export type NumberFieldIncrementProps = { - className?: string + className?: string; children?: React.ReactNode }src/components/ui/NumberField/fragments/NumberFieldInput.tsx (1)
44-46: Improve readability by formatting the input element.The input element is on a single long line making it difficult to read and maintain.
Apply this diff to improve formatting:
return ( - <input type="number" onKeyDown={handleKeyDown} value={inputValue === '' ? '' : inputValue} onChange={(e) => { const val = e.target.value; handleOnChange(val === '' ? '' : Number(val)); }} id={id} name={name} disabled={disabled} readOnly={readOnly} required={required} className={clsx(`${rootClass}-input`, className)}/> + <input + type="number" + onKeyDown={handleKeyDown} + value={inputValue === '' ? '' : inputValue} + onChange={(e) => { + const val = e.target.value; + handleOnChange(val === '' ? '' : Number(val)); + }} + id={id} + name={name} + disabled={disabled} + readOnly={readOnly} + required={required} + className={clsx(`${rootClass}-input`, className)} + /> );src/components/ui/NumberField/stories/NumberField.stories.tsx (1)
24-24: Consider removing redundantdefaultValuein controlled mode.In the Controlled story, you're passing both
value={value}anddefaultValue={3}. When using controlled mode, thedefaultValueprop is typically not needed since thevalueprop takes precedence.Consider this change for clarity:
-<NumberField.Root value={value} onValueChange={setValue} defaultValue={3} step={1} min={0} max={10} largeStep={5}> +<NumberField.Root value={value} onValueChange={setValue} step={1} min={0} max={10} largeStep={5}>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
src/components/ui/NumberField/NumberField.tsx(1 hunks)src/components/ui/NumberField/contexts/NumberFieldContext.tsx(1 hunks)src/components/ui/NumberField/fragments/NumberFieldDecrement.tsx(1 hunks)src/components/ui/NumberField/fragments/NumberFieldIncrement.tsx(1 hunks)src/components/ui/NumberField/fragments/NumberFieldInput.tsx(1 hunks)src/components/ui/NumberField/fragments/NumberFieldRoot.tsx(1 hunks)src/components/ui/NumberField/stories/NumberField.stories.tsx(1 hunks)styles/themes/components/number-field.scss(1 hunks)styles/themes/default.scss(1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: kotAPI
PR: rad-ui/ui#1031
File: src/components/ui/Accordion/fragments/AccordionRoot.tsx:41-44
Timestamp: 2025-04-07T04:38:34.864Z
Learning: The Accordion component in rad-ui/ui supports both controlled and uncontrolled modes through props like `value`, `defaultValue`, and `onValueChange`. When implementing controlled components, remember to: 1) Initialize state from defaultValue, 2) Update internal state when value changes (controlled mode), 3) Call onValueChange callback, and 4) Prevent internal state updates when in controlled mode.
Learnt from: decipher-cs
PR: rad-ui/ui#417
File: src/components/ui/Dropdown/Dropdown.stories.tsx:43-50
Timestamp: 2024-12-12T08:34:33.079Z
Learning: Ensure to verify existing ARIA attributes in components before suggesting additions during code reviews, especially in the `Dropdown.Trigger` component in `src/components/ui/Dropdown/Dropdown.stories.tsx`.
src/components/ui/NumberField/fragments/NumberFieldDecrement.tsx (1)
Learnt from: decipher-cs
PR: #417
File: src/components/ui/Dropdown/Dropdown.stories.tsx:43-50
Timestamp: 2024-12-12T08:34:33.079Z
Learning: Ensure to verify existing ARIA attributes in components before suggesting additions during code reviews, especially in the Dropdown.Trigger component in src/components/ui/Dropdown/Dropdown.stories.tsx.
styles/themes/components/number-field.scss (1)
Learnt from: kotAPI
PR: #1031
File: src/components/ui/Accordion/fragments/AccordionRoot.tsx:41-44
Timestamp: 2025-04-07T04:38:34.864Z
Learning: The Accordion component in rad-ui/ui supports both controlled and uncontrolled modes through props like value, defaultValue, and onValueChange. When implementing controlled components, remember to: 1) Initialize state from defaultValue, 2) Update internal state when value changes (controlled mode), 3) Call onValueChange callback, and 4) Prevent internal state updates when in controlled mode.
src/components/ui/NumberField/NumberField.tsx (1)
Learnt from: decipher-cs
PR: #417
File: src/components/ui/Dropdown/Dropdown.stories.tsx:43-50
Timestamp: 2024-12-12T08:34:33.079Z
Learning: Ensure to verify existing ARIA attributes in components before suggesting additions during code reviews, especially in the Dropdown.Trigger component in src/components/ui/Dropdown/Dropdown.stories.tsx.
src/components/ui/NumberField/fragments/NumberFieldIncrement.tsx (1)
Learnt from: decipher-cs
PR: #417
File: src/components/ui/Dropdown/Dropdown.stories.tsx:43-50
Timestamp: 2024-12-12T08:34:33.079Z
Learning: Ensure to verify existing ARIA attributes in components before suggesting additions during code reviews, especially in the Dropdown.Trigger component in src/components/ui/Dropdown/Dropdown.stories.tsx.
src/components/ui/NumberField/stories/NumberField.stories.tsx (2)
Learnt from: decipher-cs
PR: #417
File: src/components/ui/Dropdown/Dropdown.stories.tsx:43-50
Timestamp: 2024-12-12T08:34:33.079Z
Learning: Ensure to verify existing ARIA attributes in components before suggesting additions during code reviews, especially in the Dropdown.Trigger component in src/components/ui/Dropdown/Dropdown.stories.tsx.
Learnt from: kotAPI
PR: #1031
File: src/components/ui/Accordion/fragments/AccordionRoot.tsx:41-44
Timestamp: 2025-04-07T04:38:34.864Z
Learning: The Accordion component in rad-ui/ui supports both controlled and uncontrolled modes through props like value, defaultValue, and onValueChange. When implementing controlled components, remember to: 1) Initialize state from defaultValue, 2) Update internal state when value changes (controlled mode), 3) Call onValueChange callback, and 4) Prevent internal state updates when in controlled mode.
src/components/ui/NumberField/fragments/NumberFieldRoot.tsx (1)
Learnt from: kotAPI
PR: #1031
File: src/components/ui/Accordion/fragments/AccordionRoot.tsx:41-44
Timestamp: 2025-04-07T04:38:34.864Z
Learning: The Accordion component in rad-ui/ui supports both controlled and uncontrolled modes through props like value, defaultValue, and onValueChange. When implementing controlled components, remember to: 1) Initialize state from defaultValue, 2) Update internal state when value changes (controlled mode), 3) Call onValueChange callback, and 4) Prevent internal state updates when in controlled mode.
🧬 Code Graph Analysis (1)
src/components/ui/NumberField/fragments/NumberFieldRoot.tsx (1)
src/core/hooks/useControllableState/index.tsx (1)
useControllableState(15-78)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (10)
styles/themes/default.scss (1)
40-40: LGTM! Import correctly integrated.The number-field component import is properly placed in alphabetical order and follows the established pattern for component style imports.
src/components/ui/NumberField/NumberField.tsx (1)
11-14: LGTM! Clean compound component pattern.The static property assignments follow a clean compound component pattern that enforces modular usage of the NumberField subcomponents.
styles/themes/components/number-field.scss (1)
16-25: LGTM! Excellent cross-browser spinner hiding.The input styling properly removes native number input spinners across all major browsers using both webkit and standard properties.
src/components/ui/NumberField/fragments/NumberFieldDecrement.tsx (1)
12-15: LGTM! Proper context validation.The context validation and error handling follow good practices, ensuring the component can only be used within the proper provider.
src/components/ui/NumberField/fragments/NumberFieldIncrement.tsx (1)
12-15: LGTM! Consistent error handling pattern.The context validation follows the same reliable pattern used in the decrement component.
src/components/ui/NumberField/fragments/NumberFieldInput.tsx (1)
8-24: Good context usage and error handling.The component properly validates context presence and provides a helpful error message. The destructuring of context values is clean and the type safety is maintained.
src/components/ui/NumberField/contexts/NumberFieldContext.tsx (1)
1-18: Well-structured context definition.The context type is comprehensive and properly typed. The union type
number | ''forinputValueis appropriate for handling empty form states, and the handler function signatures are clear and well-defined.src/components/ui/NumberField/stories/NumberField.stories.tsx (1)
10-58: Excellent story coverage demonstrating component versatility.The stories effectively showcase the three main usage patterns: uncontrolled, controlled, and form integration. The consistent prop usage and clear examples make this component easy to understand and use.
src/components/ui/NumberField/fragments/NumberFieldRoot.tsx (2)
26-32: Excellent implementation of controlled/uncontrolled pattern.The use of
useControllableStatefollows the established pattern from other components in the codebase. The component properly initializes fromdefaultValueand handles both controlled and uncontrolled modes correctly.
33-49: Solid boundary constraint implementation.The
handleOnChangefunction properly enforces min/max boundaries and handles the empty string case correctly. The logic flow is clear and handles edge cases appropriately.
| const NumberFieldDecrement = ({ children, className }: NumberFieldDecrementProps) => { | ||
| const context = useContext(NumberFieldContext); | ||
| if (!context) { | ||
| console.error('NumberFieldDecrement must be used within a NumberField'); | ||
| return null; | ||
| } | ||
| const { handleStep, rootClass } = context; | ||
| return ( | ||
| <button onClick={() => handleStep({ direction: 'decrement', type: 'small' })} className={clsx(`${rootClass}-decrement`, className)}> | ||
| {children} | ||
| </button> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add accessibility attributes and consider disabled state.
The button lacks accessibility attributes that would help screen readers understand its purpose. Consider adding ARIA attributes and disabled state support.
-const NumberFieldDecrement = ({ children, className }: NumberFieldDecrementProps) => {
+const NumberFieldDecrement = ({ children, className, ...buttonProps }: NumberFieldDecrementProps) => {
const context = useContext(NumberFieldContext);
if (!context) {
console.error('NumberFieldDecrement must be used within a NumberField');
return null;
}
- const { handleStep, rootClass } = context;
+ const { handleStep, rootClass, isDisabled } = context;
return (
- <button onClick={() => handleStep({ direction: 'decrement', type: 'small' })} className={clsx(`${rootClass}-decrement`, className)}>
+ <button
+ onClick={() => handleStep({ direction: 'decrement', type: 'small' })}
+ className={clsx(`${rootClass}-decrement`, className)}
+ aria-label="Decrement value"
+ disabled={isDisabled}
+ {...buttonProps}
+ >
{children}
</button>
);You'll also need to update the props type:
export type NumberFieldDecrementProps = {
className?: string;
children?: React.ReactNode
-}
+} & React.ButtonHTMLAttributes<HTMLButtonElement>;Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/components/ui/NumberField/fragments/NumberFieldDecrement.tsx around lines
10 to 22, the button element lacks accessibility attributes and does not handle
a disabled state. Update the component to accept a disabled prop, add
appropriate ARIA attributes such as aria-label to describe the button's action,
and apply the disabled attribute to the button element when needed. Also, update
the NumberFieldDecrementProps type to include the disabled property to support
this functionality.
| const NumberFieldIncrement = ({ children, className }: NumberFieldIncrementProps) => { | ||
| const context = useContext(NumberFieldContext); | ||
| if (!context) { | ||
| console.error('NumberFieldIncrement must be used within a NumberField'); | ||
| return null; | ||
| } | ||
| const { handleStep, rootClass } = context; | ||
|
|
||
| return ( | ||
| <button onClick={() => handleStep({ direction: 'increment', type: 'small' })} className={clsx(`${rootClass}-increment`, className)}> | ||
| {children} | ||
| </button> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add accessibility attributes and consider disabled state.
Similar to the decrement component, this button needs accessibility attributes and disabled state support for a complete implementation.
-const NumberFieldIncrement = ({ children, className }: NumberFieldIncrementProps) => {
+const NumberFieldIncrement = ({ children, className, ...buttonProps }: NumberFieldIncrementProps) => {
const context = useContext(NumberFieldContext);
if (!context) {
console.error('NumberFieldIncrement must be used within a NumberField');
return null;
}
- const { handleStep, rootClass } = context;
+ const { handleStep, rootClass, isDisabled } = context;
return (
- <button onClick={() => handleStep({ direction: 'increment', type: 'small' })} className={clsx(`${rootClass}-increment`, className)}>
+ <button
+ onClick={() => handleStep({ direction: 'increment', type: 'small' })}
+ className={clsx(`${rootClass}-increment`, className)}
+ aria-label="Increment value"
+ disabled={isDisabled}
+ {...buttonProps}
+ >
{children}
</button>
);Update the props type as well:
export type NumberFieldIncrementProps = {
className?: string;
children?: React.ReactNode
-}
+} & React.ButtonHTMLAttributes<HTMLButtonElement>;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const NumberFieldIncrement = ({ children, className }: NumberFieldIncrementProps) => { | |
| const context = useContext(NumberFieldContext); | |
| if (!context) { | |
| console.error('NumberFieldIncrement must be used within a NumberField'); | |
| return null; | |
| } | |
| const { handleStep, rootClass } = context; | |
| return ( | |
| <button onClick={() => handleStep({ direction: 'increment', type: 'small' })} className={clsx(`${rootClass}-increment`, className)}> | |
| {children} | |
| </button> | |
| ); | |
| }; | |
| const NumberFieldIncrement = ({ children, className, ...buttonProps }: NumberFieldIncrementProps) => { | |
| const context = useContext(NumberFieldContext); | |
| if (!context) { | |
| console.error('NumberFieldIncrement must be used within a NumberField'); | |
| return null; | |
| } | |
| const { handleStep, rootClass, isDisabled } = context; | |
| return ( | |
| <button | |
| onClick={() => handleStep({ direction: 'increment', type: 'small' })} | |
| className={clsx(`${rootClass}-increment`, className)} | |
| aria-label="Increment value" | |
| disabled={isDisabled} | |
| {...buttonProps} | |
| > | |
| {children} | |
| </button> | |
| ); | |
| }; | |
| export type NumberFieldIncrementProps = { | |
| className?: string; | |
| children?: React.ReactNode | |
| } & React.ButtonHTMLAttributes<HTMLButtonElement>; |
🤖 Prompt for AI Agents
In src/components/ui/NumberField/fragments/NumberFieldIncrement.tsx around lines
10 to 23, the increment button lacks accessibility attributes and disabled state
handling. Add appropriate ARIA attributes such as aria-label to describe the
button's action, and include a disabled prop to control when the button should
be inactive. Update the component's props type to accept a disabled boolean and
apply it to the button element, ensuring consistent behavior and accessibility
similar to the decrement component.
| const NumberField = () => { | ||
| console.warn('Direct usage of NumberField is not supported. Please use NumberField.Root, NumberField.Item instead.'); | ||
| return null; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect component name in warning message.
The warning message mentions "NumberField.Item" but should reference "NumberField.Input" based on the actual subcomponents exposed.
- console.warn('Direct usage of NumberField is not supported. Please use NumberField.Root, NumberField.Item instead.');
+ console.warn('Direct usage of NumberField is not supported. Please use NumberField.Root, NumberField.Input, NumberField.Increment, NumberField.Decrement instead.');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const NumberField = () => { | |
| console.warn('Direct usage of NumberField is not supported. Please use NumberField.Root, NumberField.Item instead.'); | |
| return null; | |
| }; | |
| const NumberField = () => { | |
| console.warn( | |
| 'Direct usage of NumberField is not supported. Please use NumberField.Root, NumberField.Input, NumberField.Increment, NumberField.Decrement instead.' | |
| ); | |
| return null; | |
| }; |
🤖 Prompt for AI Agents
In src/components/ui/NumberField/NumberField.tsx between lines 6 and 9, the
warning message incorrectly references "NumberField.Item" instead of
"NumberField.Input". Update the warning string to mention "NumberField.Input" to
accurately reflect the actual subcomponents users should use.
| .rad-ui-number-field-increment{ | ||
| width: 2rem; | ||
| height: 2rem; | ||
| display: flex; | ||
| align-items: center; | ||
| color: var(--rad-ui-color-accent-50); | ||
| justify-content: center; | ||
| border: 1px solid var(--rad-ui-color-accent-1000); | ||
| background: var(--rad-ui-color-accent-900); | ||
| cursor: pointer; | ||
| font-size: 1.25rem; | ||
| border-radius: 0.375rem; | ||
| transition: background 0.2s, border-color 0.2s; | ||
|
|
||
| &:hover { | ||
| background: var(--rad-ui-color-accent-800); | ||
| border-color: var(--rad-ui-color-accent-600); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| .rad-ui-number-field-decrement { | ||
| width: 2rem; | ||
| height: 2rem; | ||
| display: flex; | ||
| align-items: center; | ||
| color: var(--rad-ui-color-accent-50); | ||
| justify-content: center; | ||
| border: 1px solid var(--rad-ui-color-accent-1000); | ||
| background: var(--rad-ui-color-accent-900); | ||
| cursor: pointer; | ||
| font-size: 1.25rem; | ||
| border-radius: 0.375rem; | ||
| transition: background 0.2s, border-color 0.2s; | ||
|
|
||
| &:hover { | ||
| background: var(--rad-ui-color-accent-800); | ||
| border-color: var(--rad-ui-color-accent-600); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Refactor to eliminate code duplication between increment and decrement buttons.
The increment and decrement button styles are nearly identical, leading to code duplication that violates the DRY principle.
+ .rad-ui-number-field-button {
+ width: 2rem;
+ height: 2rem;
+ display: flex;
+ align-items: center;
+ color: var(--rad-ui-color-accent-50);
+ justify-content: center;
+ border: 1px solid var(--rad-ui-color-accent-1000);
+ background: var(--rad-ui-color-accent-900);
+ cursor: pointer;
+ font-size: 1.25rem;
+ border-radius: 0.375rem;
+ transition: background 0.2s, border-color 0.2s;
+
+ &:hover {
+ background: var(--rad-ui-color-accent-800);
+ border-color: var(--rad-ui-color-accent-600);
+ }
+ }
- .rad-ui-number-field-increment{
- width: 2rem;
- height: 2rem;
- display: flex;
- align-items: center;
- color: var(--rad-ui-color-accent-50);
- justify-content: center;
- border: 1px solid var(--rad-ui-color-accent-1000);
- background: var(--rad-ui-color-accent-900);
- cursor: pointer;
- font-size: 1.25rem;
- border-radius: 0.375rem;
- transition: background 0.2s, border-color 0.2s;
-
- &:hover {
- background: var(--rad-ui-color-accent-800);
- border-color: var(--rad-ui-color-accent-600);
- }
- }
- .rad-ui-number-field-decrement {
- width: 2rem;
- height: 2rem;
- display: flex;
- align-items: center;
- color: var(--rad-ui-color-accent-50);
- justify-content: center;
- border: 1px solid var(--rad-ui-color-accent-1000);
- background: var(--rad-ui-color-accent-900);
- cursor: pointer;
- font-size: 1.25rem;
- border-radius: 0.375rem;
- transition: background 0.2s, border-color 0.2s;
-
- &:hover {
- background: var(--rad-ui-color-accent-800);
- border-color: var(--rad-ui-color-accent-600);
- }
- }
+ .rad-ui-number-field-increment {
+ @extend .rad-ui-number-field-button;
+ }
+
+ .rad-ui-number-field-decrement {
+ @extend .rad-ui-number-field-button;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .rad-ui-number-field-increment{ | |
| width: 2rem; | |
| height: 2rem; | |
| display: flex; | |
| align-items: center; | |
| color: var(--rad-ui-color-accent-50); | |
| justify-content: center; | |
| border: 1px solid var(--rad-ui-color-accent-1000); | |
| background: var(--rad-ui-color-accent-900); | |
| cursor: pointer; | |
| font-size: 1.25rem; | |
| border-radius: 0.375rem; | |
| transition: background 0.2s, border-color 0.2s; | |
| &:hover { | |
| background: var(--rad-ui-color-accent-800); | |
| border-color: var(--rad-ui-color-accent-600); | |
| } | |
| } | |
| .rad-ui-number-field-decrement { | |
| width: 2rem; | |
| height: 2rem; | |
| display: flex; | |
| align-items: center; | |
| color: var(--rad-ui-color-accent-50); | |
| justify-content: center; | |
| border: 1px solid var(--rad-ui-color-accent-1000); | |
| background: var(--rad-ui-color-accent-900); | |
| cursor: pointer; | |
| font-size: 1.25rem; | |
| border-radius: 0.375rem; | |
| transition: background 0.2s, border-color 0.2s; | |
| &:hover { | |
| background: var(--rad-ui-color-accent-800); | |
| border-color: var(--rad-ui-color-accent-600); | |
| } | |
| } | |
| .rad-ui-number-field-button { | |
| width: 2rem; | |
| height: 2rem; | |
| display: flex; | |
| align-items: center; | |
| color: var(--rad-ui-color-accent-50); | |
| justify-content: center; | |
| border: 1px solid var(--rad-ui-color-accent-1000); | |
| background: var(--rad-ui-color-accent-900); | |
| cursor: pointer; | |
| font-size: 1.25rem; | |
| border-radius: 0.375rem; | |
| transition: background 0.2s, border-color 0.2s; | |
| &:hover { | |
| background: var(--rad-ui-color-accent-800); | |
| border-color: var(--rad-ui-color-accent-600); | |
| } | |
| } | |
| .rad-ui-number-field-increment { | |
| @extend .rad-ui-number-field-button; | |
| } | |
| .rad-ui-number-field-decrement { | |
| @extend .rad-ui-number-field-button; | |
| } |
🤖 Prompt for AI Agents
In styles/themes/components/number-field.scss between lines 28 and 67, the
styles for .rad-ui-number-field-increment and .rad-ui-number-field-decrement are
nearly identical, causing code duplication. Refactor by extracting the shared
styles into a common class or placeholder selector and then extend or apply that
shared style to both increment and decrement classes to adhere to the DRY
principle.
closes #1227
Summary by CodeRabbit
New Features
Style
Documentation