ui(components): migrates to new toolbar ui components and Numeric for Input InputRange and InputDoubleRange (#4728)
Co-authored-by: sedghi <ar.sedghi@gmail.com>
This commit is contained in:
1 parent
ac5ae4a29e
commit
a8d84443a9
116 files changed
+2930
-1038
No files matched your search
File renamed without changes.
@@ -0,0 +1,199 @@
|
||||
---
|
||||
title: Input Number, Range, and Double Range
|
||||
---
|
||||
|
||||
|
||||
# Migration Guide: Moving to `Numeric` Component
|
||||
|
||||
This guide explains how to migrate from the existing `Input`, `InputRange`, and `InputDoubleRange` components to the new `Numeric` meta component.
|
||||
|
||||
|
||||
## Why Migrate?
|
||||
|
||||
The old components relied heavily on props, making them complex and difficult to maintain and apply custom styles. The new `Numeric` component provides a structured approach with a context-based API, reducing prop clutter and improving reusability.
|
||||
|
||||
|
||||
## `Input` > `Numeric.NumberInput`
|
||||
|
||||
### Basic Usage
|
||||
|
||||
**Old Usage:**
|
||||
|
||||
```tsx
|
||||
<Input
|
||||
id="example"
|
||||
label="Enter a number"
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
type="number"
|
||||
/>
|
||||
```
|
||||
|
||||
**New Usage:**
|
||||
|
||||
```tsx
|
||||
<Numeric.Container mode="number" value={value} onChange={setValue}>
|
||||
<Numeric.Label>Enter a number</Numeric.Label>
|
||||
<Numeric.NumberInput />
|
||||
</Numeric.Container>
|
||||
```
|
||||
|
||||
|
||||
|
||||
### `Input` with Custom Classes
|
||||
|
||||
#### **Old Usage (with containerClassName, labelClassName, and className)**
|
||||
|
||||
In the old implementation, we manually applied `containerClassName`, `labelClassName`, and `className` to style the `Input` component:
|
||||
|
||||
```tsx
|
||||
<Input
|
||||
id="example"
|
||||
label="Enter a number"
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
type="number"
|
||||
containerClassName="flex flex-col space-y-2"
|
||||
labelClassName="text-gray-500 text-sm"
|
||||
className="border rounded p-2"
|
||||
/>
|
||||
```
|
||||
|
||||
|
||||
**New Usage (Migrating to `Numeric.NumberInput`)**
|
||||
|
||||
With `Numeric`, you should wrap everything inside `Numeric.Container`, and you can directly apply class names to its subcomponents:
|
||||
|
||||
```tsx
|
||||
<Numeric.Container mode="number" value={value} onChange={setValue} className="flex flex-col space-y-2">
|
||||
<Numeric.Label className="text-gray-500 text-sm">Enter a number</Numeric.Label>
|
||||
<Numeric.NumberInput className="border rounded p-2" />
|
||||
</Numeric.Container>
|
||||
```
|
||||
|
||||
|
||||
## `InputRange` > `Numeric.SingleRange`
|
||||
|
||||
### Basic Usage
|
||||
|
||||
**Old Usage:**
|
||||
|
||||
```tsx
|
||||
<InputRange
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
minValue={0}
|
||||
maxValue={100}
|
||||
step={1}
|
||||
showLabel
|
||||
/>
|
||||
```
|
||||
|
||||
**New Usage:**
|
||||
|
||||
```tsx
|
||||
<Numeric.Container mode="singleRange" value={value} onChange={setValue} min={0} max={100} step={1}>
|
||||
<Numeric.Label showValue>Range</Numeric.Label>
|
||||
<Numeric.SingleRange showNumberInput />
|
||||
</Numeric.Container>
|
||||
```
|
||||
|
||||
|
||||
### Custom Classes
|
||||
|
||||
**Old Usage**
|
||||
|
||||
```tsx
|
||||
<InputRange
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
minValue={0}
|
||||
maxValue={100}
|
||||
step={1}
|
||||
containerClassName="flex flex-col space-y-2"
|
||||
inputClassName="w-full bg-gray-700"
|
||||
labelClassName="text-gray-500 text-sm"
|
||||
labelVariant="body1"
|
||||
showLabel={true}
|
||||
labelPosition="left"
|
||||
/>
|
||||
```
|
||||
|
||||
**New Usage**
|
||||
|
||||
```tsx
|
||||
<Numeric.Container mode="singleRange" value={value} onChange={setValue} min={0} max={100} step={1} className="flex flex-col space-y-2">
|
||||
<Numeric.Label className="text-gray-500 text-sm">Range</Numeric.Label>
|
||||
<Numeric.SingleRange sliderClassName="w-full bg-gray-700" />
|
||||
</Numeric.Container>
|
||||
```
|
||||
|
||||
:::note
|
||||
You now have more control over the position of the label and the slider. You can use pretty much any layout you want, whether that's flex, grid, or something else. Instead of relying on `labelPosition` to position the label, you're free to use the layout that works best for you.
|
||||
:::
|
||||
|
||||
|
||||
### AllowNumberEdit
|
||||
|
||||
**Old Usage:**
|
||||
|
||||
```tsx
|
||||
<InputRange
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
minValue={0}
|
||||
maxValue={100}
|
||||
step={1}
|
||||
allowNumberEdit={true}
|
||||
showAdjustmentArrows={true}
|
||||
/>
|
||||
```
|
||||
|
||||
**New Usage:**
|
||||
|
||||
Using `Numeric.SingleRange` and `showNumberInput`
|
||||
|
||||
```tsx
|
||||
<Numeric.Container mode="singleRange" value={value} onChange={setValue} min={0} max={100} step={1}>
|
||||
<Numeric.Label showValue>Range</Numeric.Label>
|
||||
<Numeric.SingleRange showNumberInput />
|
||||
</Numeric.Container>
|
||||
```
|
||||
|
||||
|
||||
## `InputDoubleRange` > `Numeric.DoubleRange`
|
||||
|
||||
|
||||
### Basic Usage
|
||||
**Old Usage:**
|
||||
|
||||
```tsx
|
||||
<InputDoubleRange
|
||||
values={rangeValues}
|
||||
onChange={setRangeValues}
|
||||
minValue={0}
|
||||
maxValue={100}
|
||||
step={5}
|
||||
showLabel
|
||||
/>
|
||||
```
|
||||
|
||||
**New Usage:**
|
||||
|
||||
```tsx
|
||||
<Numeric.Container mode="doubleRange" values={rangeValues} onChange={setRangeValues} min={0} max={100} step={5}>
|
||||
<Numeric.Label showValue>Range</Numeric.Label>
|
||||
<Numeric.DoubleRange showNumberInputs />
|
||||
</Numeric.Container>
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Summary of Changes
|
||||
|
||||
| Old Component | New Component Equivalent |
|
||||
|--------------------|------------------------|
|
||||
| `<Input>` | `<Numeric.NumberInput>` |
|
||||
| `<InputRange>` | `<Numeric.SingleRange>` |
|
||||
| `<InputDoubleRange>` | `<Numeric.DoubleRange>` |
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Tests
|
||||
---
|
||||
|
||||
|
||||
## 1. ToolButton `data-active` Attribute
|
||||
|
||||
- **Previous**: Checked for a `bg-primary-light` class to determine if a tool was active.
|
||||
- **Now**: Check for the HTML attribute `data-active="true"`.
|
||||
|
||||
### Example
|
||||
|
||||
```diff
|
||||
- cy.get('@wwwcButton').should('have.class', 'bg-primary-light');
|
||||
+ cy.get('@wwwcButton').should('have.attr', 'data-active', 'true');
|
||||
```
|
||||
|
||||
## 2. Additional Data Attributes
|
||||
|
||||
- Each tool button now includes:
|
||||
- `data-tool="<toolId>"`
|
||||
- `data-active="<true|false>"`
|
||||
|
||||
This makes it easier to identify and assert on specific tools in the DOM.
|
||||
|
||||
### Example
|
||||
|
||||
```diff
|
||||
- <span data-cy={id}>
|
||||
+ <span
|
||||
+ data-cy={id}
|
||||
+ data-tool={id}
|
||||
+ data-active={isActive}
|
||||
+ >
|
||||
```
|
||||
|
||||
## 3. MPR Button Class Change
|
||||
|
||||
If you were targeting the `ohif-disabled` class, you need to update your tests to target the `cursor-not-allowed` class.
|
||||
|
||||
- **Previous**: `ohif-disabled`
|
||||
- **Now**: `cursor-not-allowed`
|
||||
|
||||
### Example
|
||||
|
||||
```diff
|
||||
- cy.get('[data-cy="MPR"]').should('have.class', 'ohif-disabled');
|
||||
+ cy.get('[data-cy="MPR"]').should('have.class', 'cursor-not-allowed');
|
||||
```
|
||||
|
||||
## 4. Removal of Stack Scroll Alias
|
||||
|
||||
- The `[data-cy="StackScroll"]` element is no longer reliably in the DOM at study load.
|
||||
- If needed, reintroduce or conditionally assert its presence when appropriate.
|
||||
|
||||
```diff
|
||||
- cy.get('[data-cy="StackScroll"]').as('stackScrollBtn');
|
||||
+ // Removed due to absence in DOM at study load
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
1. **Replace** all checks for `bg-primary-light` with `data-active="true"`.
|
||||
2. **Use** `data-tool` and `data-active` attributes for more robust DOM selection and assertions.
|
||||
3. **Update** MPR button checks to `cursor-not-allowed`.
|
||||
4. **Remove** the `[data-cy="StackScroll"]` alias (or only use it when the element is present).
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
title: Toolbar
|
||||
---
|
||||
|
||||
# Toolbar
|
||||
|
||||
## New Toolbar uiType
|
||||
|
||||
We have two new toolbar button types: `ohif.toolButtonList` and `ohif.toolButton`, which are intended to replace the `ohif.radioGroup` and `ohif.splitButton` types.
|
||||
|
||||
Note that these are backward compatible, so if you are not ready to pick up the new ui types (which are more flexible and powerful), you can continue using the old types.
|
||||
|
||||
|
||||
```js
|
||||
// Old type
|
||||
{
|
||||
uiType: 'ohif.radioGroup',
|
||||
}
|
||||
|
||||
// New type
|
||||
{
|
||||
uiType: 'ohif.toolButton',
|
||||
}
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```js
|
||||
// Old type
|
||||
{
|
||||
uiType: 'ohif.splitButton',
|
||||
}
|
||||
|
||||
// New type
|
||||
{
|
||||
uiType: 'ohif.toolButtonList',
|
||||
}
|
||||
```
|
||||
|
||||
The `ohif.buttonGroup` and `ohif.radioGroup` types used in the Toolbox have been replaced with `ohif.toolBoxButtonGroup` and `ohif.toolBoxButton` to reflect their usage in the Toolbox, which has distinct styling.
|
||||
|
||||
```js
|
||||
// Old type
|
||||
{
|
||||
uiType: 'ohif.buttonGroup',
|
||||
}
|
||||
|
||||
// New type
|
||||
{
|
||||
uiType: 'ohif.toolBoxButtonGroup',
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
```js
|
||||
// Old type
|
||||
{
|
||||
uiType: 'ohif.radioGroup',
|
||||
}
|
||||
|
||||
// New type
|
||||
{
|
||||
uiType: 'ohif.toolBoxButton',
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## getToolbarModule
|
||||
|
||||
|
||||
The `getToolbarModule` function previously returned `disabled`, `disabledText`, and `className` as part of its evaluation process for the button state. These properties will still be returned, but common class names are now handled internally by the new UI button components, including `ToolButton`, `ToolButtonList`, `Toolbox`, and `ToolBoxGroup`. You can override the `className` if you need to.
|
||||
|
||||
|
||||
## ToolBox
|
||||
|
||||
Previously, the segmentation toolbox was not using an `evaluator` property. This is now taken into account
|
||||
|
||||
|
||||
```js
|
||||
// old
|
||||
{
|
||||
id: 'BrushTools',
|
||||
uiType: 'ohif.buttonGroup',
|
||||
props: {
|
||||
groupId: 'BrushTools',
|
||||
items: []
|
||||
}
|
||||
}
|
||||
|
||||
// now
|
||||
{
|
||||
id: 'BrushTools',
|
||||
uiType: 'ohif.buttonGroup',
|
||||
props: {
|
||||
groupId: 'BrushTools',
|
||||
evaluate: 'evaluate.cornerstone.hasSegmentation',
|
||||
items: []
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in new issue
Block a user