Skip to content

Commit fa66e5a

Browse files
committed
feat(ui-number-input): rewrite NumberInput to the new theming system
- Converted `NumberInput` from class-based to functional component - It uses the theme from TextInput, they are the same in Figma - The styling of the upper label/messages are not done, they are coming in `FormFieldLayout` Tokens are also not fully used (they are used only in `TextInput`): - `fontSizeSm`, `heightSm`, `paddingHorizontalSm`: This component has no small size - `gapContent`: This is a gap between the text and elements rendered after it, `NumberInput` does not have such To test: - Check the examples in the docs, they should function exactly as before - Compare its CSS to the ones in Figma Completes INSTUI-4814
1 parent 650e4e6 commit fa66e5a

File tree

14 files changed

+483
-357
lines changed

14 files changed

+483
-357
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,5 @@
131131
"browserslist": [
132132
"extends @instructure/browserslist-config-instui"
133133
],
134-
"packageManager": "pnpm@10.23.0"
134+
"packageManager": "pnpm@10.23.0+sha512.21c4e5698002ade97e4efe8b8b4a89a8de3c85a37919f957e7a0f30f38fbc5bbdd05980ffe29179b2fb6e6e691242e098d945d1601772cad0fef5fb6411e2a4b"
135135
}

packages/__docs__/resolve.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ const alias = {
9292
),
9393
'@instructure/ui-grid$': path.resolve(import.meta.dirname, '../ui-grid/src/'),
9494
'@instructure/ui-i18n$': path.resolve(import.meta.dirname, '../ui-i18n/src/'),
95+
'@instructure/ui-icons-lucide': path.resolve(import.meta.dirname, '../ui-icons-lucide/src/'),
9596
'@instructure/ui-img$': path.resolve(import.meta.dirname, '../ui-img/src/'),
9697
'@instructure/ui-instructure$': path.resolve(import.meta.dirname, '../ui-instructure/src/'),
9798
'@instructure/ui-link$': path.resolve(import.meta.dirname, '../ui-link/src/'),

packages/emotion/src/styleUtils/calcFocusOutlineStyles.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const calcFocusOutlineStyles = (
7878
transition: 'outline-color 0.2s, outline-offset 0.25s'
7979
}),
8080
outlineOffset: '-0.8rem',
81+
outlineStyle: 'solid',
8182
outlineColor: alpha(outlineStyle.outlineColor, 0),
8283
'&:focus': {
8384
...outlineStyle,

packages/emotion/src/useStyle.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ const isNewThemeObject = (obj: BaseThemeOrOverride): obj is Theme => {
6060
const useStyle = <P extends GenerateStyleParams>(useStyleParams: {
6161
generateStyle: P
6262
params?: SecondParameter<P>
63-
componentId: keyof NewComponentTypes
63+
// needs to be a string too because it might be a child component
64+
componentId: keyof NewComponentTypes | string
6465
themeOverride: ThemeOverrideValue | undefined
6566
displayName?: string
6667
//in case of a child component needed to use it's parent's tokens, provide parent's name

packages/ui-icons-lucide/src/wrapLucideIcon/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ export function wrapLucideIcon(Icon: LucideIcon): LucideIcon {
146146
return (
147147
<span css={styles?.lucideIcon} className={className} style={style}>
148148
<Icon
149+
name={Icon.displayName}
149150
ref={handleElementRef}
150151
size={numericSize}
151152
color={customColor}

packages/ui-icons-lucide/src/wrapLucideIcon/styles.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,12 @@ const generateStyle = (
4949
if (color === 'inherit') {
5050
colorStyle = { color: 'inherit' }
5151
} else if (color in componentTheme) {
52-
/**
53-
* Direct theme property access
54-
*/
52+
// Direct theme property access
5553
colorStyle = {
5654
color: componentTheme[color as keyof typeof componentTheme] as string
5755
}
5856
} else {
59-
/**
60-
* Custom CSS color (e.g., "#ff0000", "rgb(255, 0, 0)")
61-
*/
57+
// Custom CSS color (e.g., "#ff0000", "rgb(255, 0, 0)")
6258
colorStyle = { color }
6359
}
6460
}

packages/ui-number-input/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"@instructure/shared-types": "workspace:*",
3838
"@instructure/ui-a11y-utils": "workspace:*",
3939
"@instructure/ui-form-field": "workspace:*",
40-
"@instructure/ui-icons": "workspace:*",
40+
"@instructure/ui-icons-lucide": "workspace:*",
4141
"@instructure/ui-react-utils": "workspace:*",
4242
"@instructure/ui-utils": "workspace:*",
4343
"@instructure/uid": "workspace:*",

packages/ui-number-input/src/NumberInput/README.md

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ Note that this field **does not work
88
uncontrolled** - you must pass event handlers if you want it to respond to
99
user input.
1010

11-
This example handles arrow buttons, up/down arrow keys, and typing into
12-
the input. It also includes an `onBlur` handler that displays an error message
13-
if the input is invalid or missing.
11+
This example handles arrow buttons, up/down arrow keys, and typing into the input. It also includes an `onBlur` handler that displays an error message if the input is invalid or missing.
1412

1513
```js
1614
---
@@ -150,16 +148,43 @@ render(<Example />)
150148

151149
> Note: `NumberInput` accepts a string or number as its `value`. However, the value returned by the `onChange` callback is always a string and should be converted to a number before attempting to augment it.
152150
153-
NumberInput comes in 2 sizes. The default size is "medium".
151+
You can see here most of the visual states of the component.
154152

155153
```js
156154
---
157-
type: example
155+
type: example
158156
---
159-
<div>
160-
<NumberInput renderLabel="Default-size input" /><br/>
161-
<NumberInput size="large" renderLabel="Large-size input" />
162-
</div>
157+
<Flex gap='medium' direction='column'>
158+
<NumberInput
159+
renderLabel='normal'
160+
placeholder="placeholder"
161+
/>
162+
<NumberInput
163+
interaction='disabled'
164+
renderLabel='disabled'
165+
placeholder="placeholder"
166+
/>
167+
<NumberInput
168+
interaction='readonly'
169+
renderLabel='readonly'
170+
placeholder="placeholder"
171+
/>
172+
<NumberInput
173+
renderLabel='with error message'
174+
placeholder="placeholder"
175+
messages={[{ text: 'This is an error.', type: 'error' }]}
176+
/>
177+
<NumberInput
178+
renderLabel='with success message'
179+
placeholder="placeholder"
180+
messages={[{ text: 'Great success!', type: 'success' }]}
181+
/>
182+
<NumberInput
183+
renderLabel='large size (default is "medium")'
184+
placeholder="placeholder"
185+
size='large'
186+
/>
187+
</Flex>
163188
```
164189

165190
### Guidelines

packages/ui-number-input/src/NumberInput/__tests__/NumberInput.test.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ import '@testing-library/jest-dom'
2929

3030
import { NumberInput } from '../index'
3131

32-
import { IconZoomInLine, IconZoomOutLine } from '@instructure/ui-icons'
32+
import {
33+
ChevronUpInstUIIcon,
34+
ChevronDownInstUIIcon
35+
} from '@instructure/ui-icons-lucide'
3336

3437
describe('<NumberInput />', () => {
3538
let consoleWarningMock: ReturnType<typeof vi.spyOn>
@@ -139,7 +142,7 @@ describe('<NumberInput />', () => {
139142
it('shows arrow spinbuttons by default', async () => {
140143
const { container } = render(<NumberInput renderLabel="Label" />)
141144
const buttons = container.querySelectorAll(
142-
'button[class$="-numberInput_arrow'
145+
'button[class$="-numberInput_arrow"]'
143146
)
144147

145148
expect(buttons).toHaveLength(2)
@@ -150,7 +153,7 @@ describe('<NumberInput />', () => {
150153
<NumberInput renderLabel="Label" showArrows={false} />
151154
)
152155
const buttons = container.querySelectorAll(
153-
'button[class$="-numberInput_arrow'
156+
'button[class$="-numberInput_arrow"]'
154157
)
155158

156159
expect(buttons).toHaveLength(0)
@@ -162,7 +165,7 @@ describe('<NumberInput />', () => {
162165
<NumberInput renderLabel="Label" onIncrement={onIncrement} />
163166
)
164167
const buttons = container.querySelectorAll(
165-
'button[class$="-numberInput_arrow'
168+
'button[class$="-numberInput_arrow"]'
166169
)
167170

168171
userEvent.click(buttons[0])
@@ -182,7 +185,7 @@ describe('<NumberInput />', () => {
182185
/>
183186
)
184187
const buttons = container.querySelectorAll(
185-
'button[class$="-numberInput_arrow'
188+
'button[class$="-numberInput_arrow"]'
186189
)
187190

188191
userEvent.click(buttons[0])
@@ -198,7 +201,7 @@ describe('<NumberInput />', () => {
198201
<NumberInput renderLabel="Label" readOnly onIncrement={onIncrement} />
199202
)
200203
const buttons = container.querySelectorAll(
201-
'button[class$="-numberInput_arrow'
204+
'button[class$="-numberInput_arrow"]'
202205
)
203206

204207
userEvent.click(buttons[0])
@@ -215,7 +218,7 @@ describe('<NumberInput />', () => {
215218
)
216219

217220
const buttons = container.querySelectorAll(
218-
'button[class$="-numberInput_arrow'
221+
'button[class$="-numberInput_arrow"]'
219222
)
220223

221224
userEvent.click(buttons[1])
@@ -235,7 +238,7 @@ describe('<NumberInput />', () => {
235238
/>
236239
)
237240
const buttons = container.querySelectorAll(
238-
'button[class$="-numberInput_arrow'
241+
'button[class$="-numberInput_arrow"]'
239242
)
240243

241244
userEvent.click(buttons[1])
@@ -251,7 +254,7 @@ describe('<NumberInput />', () => {
251254
<NumberInput renderLabel="Label" readOnly onDecrement={onDecrement} />
252255
)
253256
const buttons = container.querySelectorAll(
254-
'button[class$="-numberInput_arrow'
257+
'button[class$="-numberInput_arrow"]'
255258
)
256259

257260
userEvent.click(buttons[1])
@@ -277,19 +280,19 @@ describe('<NumberInput />', () => {
277280
onIncrement={onIncrement}
278281
onDecrement={onDecrement}
279282
renderIcons={{
280-
increase: <IconZoomInLine />,
281-
decrease: <IconZoomOutLine />
283+
increase: <ChevronUpInstUIIcon />,
284+
decrease: <ChevronDownInstUIIcon />
282285
}}
283286
/>
284287
)
285288

286-
const zoomInIcon = container.querySelector('svg[name="IconZoomIn"]')
287-
const zoomOutIcon = container.querySelector('svg[name="IconZoomOut"]')
289+
const zoomInIcon = container.querySelector('svg[name="ChevronUp"]')
290+
const zoomOutIcon = container.querySelector('svg[name="ChevronDown"]')
288291
expect(zoomInIcon).toBeInTheDocument()
289292
expect(zoomOutIcon).toBeInTheDocument()
290293

291294
const buttons = container.querySelectorAll(
292-
'button[class$="-numberInput_arrow'
295+
'button[class$="-numberInput_arrow"]'
293296
)
294297

295298
userEvent.click(buttons[0])

0 commit comments

Comments
 (0)