Skip to content

Commit 75392a8

Browse files
committed
feat!: update to uikit 7
1 parent e897f50 commit 75392a8

File tree

20 files changed

+296
-256
lines changed

20 files changed

+296
-256
lines changed

.storybook/main.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ const config: StorybookConfig = {
99
'./theme-addon/register.tsx',
1010
'@storybook/addon-webpack5-compiler-babel',
1111
'@storybook/addon-storysource',
12-
'@storybook/addon-styling-webpack',
1312
{
1413
name: '@storybook/addon-styling-webpack',
1514
options: {

package-lock.json

Lines changed: 154 additions & 98 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"@gravity-ui/prettier-config": "^1.1.0",
6868
"@gravity-ui/stylelint-config": "^4.0.1",
6969
"@gravity-ui/tsconfig": "^1.0.0",
70-
"@gravity-ui/uikit": "^6.15.0",
70+
"@gravity-ui/uikit": "^7.0.0-beta.5",
7171
"@storybook/addon-a11y": "^8.4.7",
7272
"@storybook/addon-actions": "^8.4.7",
7373
"@storybook/addon-essentials": "^8.4.7",
@@ -117,7 +117,7 @@
117117
"typescript": "^5.7.2"
118118
},
119119
"peerDependencies": {
120-
"@gravity-ui/uikit": "^6.0.0",
120+
"@gravity-ui/uikit": "^7.0.0",
121121
"react": ">=17.0.0",
122122
"react-dom": ">=17.0.0"
123123
},

src/components/CalendarView/hooks/useCalendarProps.ts

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22

33
import {useFocusWithin} from '@gravity-ui/uikit';
4-
import type {ButtonProps} from '@gravity-ui/uikit';
4+
import type {ButtonButtonProps} from '@gravity-ui/uikit';
55

66
import type {CalendarProps} from '../../Calendar/Calendar';
77
import {formatDateTime} from '../../utils/dates';
@@ -43,7 +43,7 @@ export function useCalendarProps(props: CalendarProps, state: CalendarState | Ra
4343
const isNextModeLast = modeIndex + 2 === state.availableModes.length;
4444
const modeDisabled = state.disabled || isModeLast;
4545

46-
const modeButtonProps: ButtonProps = {
46+
const modeButtonProps: ButtonButtonProps = {
4747
disabled: state.disabled,
4848
// FIXME: do not use button class name
4949
className: modeDisabled ? buttonDisabledClassName : undefined,
@@ -55,11 +55,9 @@ export function useCalendarProps(props: CalendarProps, state: CalendarState | Ra
5555
state.setFocused(true);
5656
}
5757
},
58-
extraProps: {
59-
'aria-disabled': modeDisabled ? 'true' : undefined,
60-
'aria-description': getAriaDescriptionForModeButton(state.mode, state.availableModes),
61-
'aria-live': 'polite',
62-
},
58+
'aria-disabled': modeDisabled ? 'true' : undefined,
59+
'aria-description': getAriaDescriptionForModeButton(state.mode, state.availableModes),
60+
'aria-live': 'polite',
6361
children: title,
6462
};
6563

@@ -73,7 +71,7 @@ export function useCalendarProps(props: CalendarProps, state: CalendarState | Ra
7371
}
7472
});
7573

76-
const previousButtonProps: ButtonProps = {
74+
const previousButtonProps: ButtonButtonProps = {
7775
disabled: state.disabled,
7876
// FIXME: do not use button class name
7977
className: previousDisabled ? buttonDisabledClassName : undefined,
@@ -92,10 +90,8 @@ export function useCalendarProps(props: CalendarProps, state: CalendarState | Ra
9290
: () => {
9391
previousFocused.current = false;
9492
},
95-
extraProps: {
96-
'aria-label': i18n('Previous'),
97-
'aria-disabled': previousDisabled ? 'true' : undefined,
98-
},
93+
'aria-label': i18n('Previous'),
94+
'aria-disabled': previousDisabled ? 'true' : undefined,
9995
};
10096

10197
const nextFocused = React.useRef(false);
@@ -108,7 +104,7 @@ export function useCalendarProps(props: CalendarProps, state: CalendarState | Ra
108104
}
109105
});
110106

111-
const nextButtonProps: ButtonProps = {
107+
const nextButtonProps: ButtonButtonProps = {
112108
disabled: state.disabled,
113109
// FIXME: do not use button class name
114110
className: nextDisabled ? buttonDisabledClassName : undefined,
@@ -127,10 +123,8 @@ export function useCalendarProps(props: CalendarProps, state: CalendarState | Ra
127123
: () => {
128124
nextFocused.current = false;
129125
},
130-
extraProps: {
131-
'aria-label': i18n('Next'),
132-
'aria-disabled': previousDisabled ? 'true' : undefined,
133-
},
126+
'aria-label': i18n('Next'),
127+
'aria-disabled': previousDisabled ? 'true' : undefined,
134128
};
135129

136130
return {

src/components/DatePicker/DatePicker.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export interface DatePickerProps<T = DateTime>
4444
}
4545

4646
export function DatePicker({className, ...props}: DatePickerProps) {
47-
const anchorRef = React.useRef<HTMLDivElement>(null);
47+
const [anchor, setAnchor] = React.useState<HTMLDivElement | null>(null);
4848

4949
const state = useDatePickerState(props);
5050

@@ -60,8 +60,8 @@ export function DatePicker({className, ...props}: DatePickerProps) {
6060
<MobileCalendar props={props} state={state} />
6161
) : (
6262
!isOnlyTime && (
63-
<div ref={anchorRef} className={b('popup-anchor')}>
64-
<Popup anchorRef={anchorRef} {...popupProps}>
63+
<div ref={setAnchor} className={b('popup-anchor')}>
64+
<Popup anchorElement={anchor} {...popupProps}>
6565
<div className={b('popup-content')}>
6666
{typeof props.children === 'function' ? (
6767
props.children(calendarProps)
@@ -89,10 +89,7 @@ export function DatePicker({className, ...props}: DatePickerProps) {
8989
<Icon data={CalendarIcon} />
9090
</Button>
9191
)}
92-
{!isMobile && isOnlyTime && (
93-
<StubButton size={calendarButtonProps.size} icon={ClockIcon} />
94-
)}
95-
{isMobile && (
92+
{(isMobile || isOnlyTime) && (
9693
<StubButton
9794
size={calendarButtonProps.size}
9895
icon={isOnlyTime ? ClockIcon : CalendarIcon}

src/components/DatePicker/hooks/useDatePickerProps.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React from 'react';
33
import {isDateTime} from '@gravity-ui/date-utils';
44
import type {DateTime} from '@gravity-ui/date-utils';
55
import {useFocusWithin, useForkRef} from '@gravity-ui/uikit';
6-
import type {ButtonProps, PopupProps, TextInputProps} from '@gravity-ui/uikit';
6+
import type {ButtonButtonProps, PopupProps, TextInputProps} from '@gravity-ui/uikit';
77

88
import type {CalendarInstance, CalendarProps} from '../../Calendar';
99
import {useDateFieldProps} from '../../DateField';
@@ -21,7 +21,7 @@ interface InnerDatePickerProps<T = DateTime> {
2121
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2222
groupProps: React.HTMLAttributes<unknown> & {ref: React.Ref<any>};
2323
fieldProps: TextInputProps;
24-
calendarButtonProps: ButtonProps & {ref: React.Ref<HTMLButtonElement>};
24+
calendarButtonProps: ButtonButtonProps & {ref: React.Ref<HTMLButtonElement>};
2525
popupProps: PopupProps;
2626
calendarProps: CalendarProps<T> & {ref: React.Ref<CalendarInstance>};
2727
timeInputProps: DateFieldProps<T>;
@@ -114,11 +114,9 @@ export function useDatePickerProps<T extends DateTime | RangeValue<DateTime>>(
114114
ref: calendarButtonRef,
115115
size: getButtonSizeForInput(props.size),
116116
disabled: state.disabled,
117-
extraProps: {
118-
'aria-label': i18n('Calendar'),
119-
'aria-haspopup': 'dialog',
120-
'aria-expanded': state.isOpen,
121-
},
117+
'aria-label': i18n('Calendar'),
118+
'aria-haspopup': 'dialog',
119+
'aria-expanded': state.isOpen,
122120
view: 'flat-secondary',
123121
onClick: () => {
124122
setActive(true);
@@ -127,26 +125,30 @@ export function useDatePickerProps<T extends DateTime | RangeValue<DateTime>>(
127125
},
128126
popupProps: {
129127
open: state.isOpen,
130-
onEscapeKeyDown: () => {
131-
state.setOpen(false, 'EscapeKeyDown');
132-
focusInput();
133-
},
134-
onOutsideClick: (e) => {
135-
if (e.target !== calendarButtonRef.current) {
136-
state.setOpen(false, 'ClickOutside');
137-
}
138-
if (e.target && groupRef.current?.contains(e.target as Node)) {
139-
focusInput();
128+
onOpenChange: (open, e, reason) => {
129+
if (!open) {
130+
if (reason === 'escape-key') {
131+
state.setOpen(false, 'EscapeKeyDown');
132+
focusInput();
133+
} else if (reason === 'outside-press') {
134+
if (!e?.target || !calendarButtonRef.current?.contains(e.target as Node)) {
135+
state.setOpen(false, 'ClickOutside');
136+
}
137+
138+
if (e?.target && groupRef.current?.contains(e.target as Node)) {
139+
focusInput();
140+
}
141+
}
140142
}
141143
},
142-
onTransitionExited: () => {
144+
onTransitionOutComplete: () => {
143145
setFocusedDate(
144146
isDateTime(state.dateFieldState.displayValue)
145147
? state.dateFieldState.displayValue
146148
: state.dateFieldState.displayValue.start,
147149
);
148150
},
149-
focusTrap: !props.disableFocusTrap,
151+
modal: !props.disableFocusTrap,
150152
disablePortal: props.disablePortal,
151153
},
152154
calendarProps: {

src/components/RangeDatePicker/RangeDatePicker.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const b = block('range-date-picker');
2424
export type RangeDatePickerProps = DatePickerProps<RangeValue<DateTime>>;
2525

2626
export function RangeDatePicker({className, ...props}: RangeDatePickerProps) {
27-
const anchorRef = React.useRef<HTMLDivElement>(null);
27+
const [anchor, setAnchor] = React.useState<HTMLDivElement | null>(null);
2828

2929
const state = useRangeDatePickerState(props);
3030

@@ -36,8 +36,8 @@ export function RangeDatePicker({className, ...props}: RangeDatePickerProps) {
3636
return (
3737
<div className={b(null, className)} {...groupProps}>
3838
{!isOnlyTime && (
39-
<div ref={anchorRef} className={b('popup-anchor')}>
40-
<Popup anchorRef={anchorRef} {...popupProps}>
39+
<div ref={setAnchor} className={b('popup-anchor')}>
40+
<Popup anchorElement={anchor} {...popupProps}>
4141
<div className={b('popup-content')}>
4242
{typeof props.children === 'function' ? (
4343
props.children({...calendarProps, value: state.value})

src/components/RangeDateSelection/RangeDateSelection.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export function RangeDateSelection(props: RangeDateSelectionProps) {
9999
state.scale(0.5);
100100
state.endDragging();
101101
}}
102-
extraProps={{'aria-label': i18n('Decrease range')}}
102+
aria-label={i18n('Decrease range')}
103103
>
104104
<Icon data={Minus} />
105105
</Button>
@@ -111,7 +111,7 @@ export function RangeDateSelection(props: RangeDateSelectionProps) {
111111
state.scale(1.5);
112112
state.endDragging();
113113
}}
114-
extraProps={{'aria-label': i18n('Increase range')}}
114+
aria-label={i18n('Increase range')}
115115
>
116116
<Icon data={Plus} />
117117
</Button>

src/components/RelativeDateField/RelativeDateField.tsx

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ export function RelativeDateField(props: RelativeDateFieldProps) {
4949

5050
const isMobile = useMobile();
5151

52-
const anchorRef = React.useRef<HTMLElement>(null);
52+
const [anchor, setAnchor] = React.useState<HTMLElement | null>(null);
5353

5454
const [isOpen, setOpen] = React.useState(false);
5555

5656
const {focusWithinProps} = useFocusWithin({
57-
onBlurWithin: () => {
58-
setOpen(false);
57+
onFocusWithinChange: (isFocusWithin) => {
58+
setOpen(isFocusWithin);
5959
},
6060
isDisabled: isMobile,
6161
});
@@ -70,14 +70,20 @@ export function RelativeDateField(props: RelativeDateFieldProps) {
7070
<TextInput
7171
{...inputProps}
7272
className={b('field')}
73-
ref={anchorRef}
74-
onFocus={(e) => {
75-
if (!isMobile) {
73+
ref={setAnchor}
74+
onBlur={props.onBlur}
75+
onKeyDown={(e) => {
76+
inputProps.onKeyDown?.(e);
77+
if (
78+
!e.defaultPrevented &&
79+
e.altKey &&
80+
(e.key === 'ArrowDown' || e.key === 'ArrowUp')
81+
) {
82+
e.preventDefault();
83+
e.stopPropagation();
7684
setOpen(true);
7785
}
78-
props.onFocus?.(e);
7986
}}
80-
onBlur={props.onBlur}
8187
/>
8288
<HiddenInput
8389
name={props.name}
@@ -89,7 +95,15 @@ export function RelativeDateField(props: RelativeDateFieldProps) {
8995
form={props.form}
9096
/>
9197
{!isMobile && (
92-
<Popup anchorRef={anchorRef} open={isOpen}>
98+
<Popup
99+
anchorElement={anchor}
100+
open={isOpen}
101+
onOpenChange={(_open, _event, reason) => {
102+
if (reason === 'escape-key') {
103+
setOpen(false);
104+
}
105+
}}
106+
>
93107
<div className={b('popup-content')}>
94108
<Calendar {...calendarProps} />
95109
{props.hasTime ? (

src/components/RelativeDatePicker/RelativeDatePicker.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ export function RelativeDatePicker(props: RelativeDatePickerProps) {
6161
timeInputProps,
6262
} = useRelativeDatePickerProps(state, props);
6363

64-
const anchorRef = React.useRef<HTMLDivElement>(null);
65-
const handleRef = useForkRef(anchorRef, groupProps.ref);
64+
const [anchor, setAnchor] = React.useState<HTMLElement | null>(null);
65+
const handleRef = useForkRef(groupProps.ref, setAnchor);
6666

6767
const isMobile = useMobile();
6868
const isOnlyTime = state.datePickerState.hasTime && !state.datePickerState.hasDate;
@@ -130,7 +130,7 @@ export function RelativeDatePicker(props: RelativeDatePickerProps) {
130130
form={props.form}
131131
/>
132132
{!isMobile && !isOnlyTime && (
133-
<Popup {...popupProps} anchorRef={anchorRef}>
133+
<Popup {...popupProps} anchorElement={anchor}>
134134
<div className={b('popup-content')}>
135135
{typeof props.children === 'function' ? (
136136
props.children(calendarProps)

0 commit comments

Comments
 (0)