@itwin/itwinui-react 3.0.0-dev.13 → 3.0.0-dev.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/cjs/core/Carousel/Carousel.d.ts +12 -5
  3. package/cjs/core/Carousel/Carousel.js +9 -39
  4. package/cjs/core/Carousel/CarouselContext.d.ts +0 -4
  5. package/cjs/core/Carousel/CarouselDot.js +1 -1
  6. package/cjs/core/Carousel/CarouselDotsList.js +26 -2
  7. package/cjs/core/Carousel/CarouselNavigation.d.ts +1 -1
  8. package/cjs/core/Carousel/CarouselNavigation.js +4 -17
  9. package/cjs/core/Carousel/CarouselSlide.d.ts +1 -1
  10. package/cjs/core/Carousel/CarouselSlide.js +12 -2
  11. package/cjs/core/Carousel/CarouselSlider.d.ts +1 -1
  12. package/cjs/core/Carousel/CarouselSlider.js +2 -2
  13. package/cjs/core/Slider/Slider.d.ts +2 -6
  14. package/cjs/core/Slider/Slider.js +8 -22
  15. package/cjs/core/Slider/Thumb.d.ts +1 -2
  16. package/cjs/core/Slider/Thumb.js +1 -5
  17. package/cjs/core/Tabs/Tabs.js +12 -18
  18. package/cjs/core/ThemeProvider/ThemeProvider.d.ts +3 -2
  19. package/cjs/core/ThemeProvider/ThemeProvider.js +14 -7
  20. package/cjs/core/Tile/Tile.js +11 -10
  21. package/cjs/core/utils/components/WithCSSTransition.js +7 -1
  22. package/cjs/core/utils/hooks/useOverflow.js +3 -1
  23. package/cjs/styles.js +8 -10
  24. package/esm/core/Carousel/Carousel.d.ts +12 -5
  25. package/esm/core/Carousel/Carousel.js +9 -39
  26. package/esm/core/Carousel/CarouselContext.d.ts +0 -4
  27. package/esm/core/Carousel/CarouselDot.js +1 -1
  28. package/esm/core/Carousel/CarouselDotsList.js +26 -2
  29. package/esm/core/Carousel/CarouselNavigation.d.ts +1 -1
  30. package/esm/core/Carousel/CarouselNavigation.js +5 -22
  31. package/esm/core/Carousel/CarouselSlide.d.ts +1 -1
  32. package/esm/core/Carousel/CarouselSlide.js +15 -3
  33. package/esm/core/Carousel/CarouselSlider.d.ts +1 -1
  34. package/esm/core/Carousel/CarouselSlider.js +2 -2
  35. package/esm/core/Slider/Slider.d.ts +2 -6
  36. package/esm/core/Slider/Slider.js +8 -19
  37. package/esm/core/Slider/Thumb.d.ts +1 -2
  38. package/esm/core/Slider/Thumb.js +1 -5
  39. package/esm/core/Tabs/Tabs.js +13 -17
  40. package/esm/core/ThemeProvider/ThemeProvider.d.ts +3 -2
  41. package/esm/core/ThemeProvider/ThemeProvider.js +14 -7
  42. package/esm/core/Tile/Tile.js +11 -10
  43. package/esm/core/utils/components/WithCSSTransition.js +7 -1
  44. package/esm/core/utils/hooks/useOverflow.js +3 -1
  45. package/esm/styles.js +8 -10
  46. package/package.json +2 -2
  47. package/styles.css +31 -45
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.0.0-dev.15
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1649](https://github.com/iTwin/iTwinUI/pull/1649): ThemeProvider will now inherit `portalContainer` if also inheriting theme.
8
+
9
+ ## 3.0.0-dev.14
10
+
11
+ ### Major Changes
12
+
13
+ - [#1626](https://github.com/iTwin/iTwinUI/pull/1626): Improved carousel accessibility and changed the markup so that the dots are present before the slides.
14
+ - [#1469](https://github.com/iTwin/iTwinUI/pull/1469): Updated internal DOM structure in Slider.
15
+
16
+ ### Patch Changes
17
+
18
+ - [#1632](https://github.com/iTwin/iTwinUI/pull/1632): Adjusted gap between adjacent icons in searchbox.
19
+
3
20
  ## 3.0.0-dev.13
4
21
 
5
22
  ### Major Changes
@@ -237,6 +254,18 @@
237
254
  - Updated dependencies:
238
255
  - @itwin/itwinui-css@2.0.0-dev.0
239
256
 
257
+ ## 2.12.14
258
+
259
+ ### Patch Changes
260
+
261
+ - [#1643](https://github.com/iTwin/iTwinUI/pull/1643): Fixed an issue where ProgressRadial was not respecting explicit size.
262
+
263
+ ## 2.12.13
264
+
265
+ ### Patch Changes
266
+
267
+ - [#1634](https://github.com/iTwin/iTwinUI/pull/1634): Fix overflow visible items count when item is larger than container.
268
+
240
269
  ## 2.12.12
241
270
 
242
271
  ### Patch Changes
@@ -14,7 +14,8 @@ type CarouselProps = {
14
14
  };
15
15
  /**
16
16
  * The Carousel component consists of a set of slides, normally displayed one at a time. A navigation section is
17
- * located below the slides, consisting of "dots" and "previous"/"next" buttons, used for changing slides.
17
+ * shown below the slides, consisting of "dots" and "previous"/"next" buttons, used for changing slides; this navigation
18
+ * section must be present _before_ the slides in DOM order, even though it is visually shown below the slides.
18
19
  *
19
20
  * The currently shown slide can also be changed using the left/right arrow keys or by dragging on a touch device.
20
21
  *
@@ -22,20 +23,23 @@ type CarouselProps = {
22
23
  *
23
24
  * @example
24
25
  * <Carousel>
26
+ * <Carousel.Navigation />
25
27
  * <Carousel.Slider>
26
28
  * <Carousel.Slide>...</Carousel.Slide>
27
29
  * <Carousel.Slide>...</Carousel.Slide>
28
30
  * <Carousel.Slide>...</Carousel.Slide>
29
31
  * </Carousel.Slider>
30
- * <Carousel.Navigation />
31
32
  * </Carousel>
32
33
  */
33
34
  export declare const Carousel: PolymorphicForwardRefComponent<"section", CarouselProps> & {
34
- Slider: PolymorphicForwardRefComponent<"ol", {}>;
35
- Slide: PolymorphicForwardRefComponent<"li", {
35
+ Slider: PolymorphicForwardRefComponent<"div", {}>;
36
+ Slide: PolymorphicForwardRefComponent<"div", {
36
37
  index?: number | undefined;
37
38
  }>;
38
- Navigation: PolymorphicForwardRefComponent<"nav", {}> & {
39
+ /**
40
+ * Contains the dots and previous/next buttons for navigating the slides. Must be present _before_ the slides in DOM.
41
+ */
42
+ Navigation: PolymorphicForwardRefComponent<"div", {}> & {
39
43
  PreviousButton: PolymorphicForwardRefComponent<"button", Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
40
44
  ref?: ((instance: HTMLButtonElement | null) => void) | React.RefObject<HTMLButtonElement> | null | undefined;
41
45
  }, "label" | "as" | "size" | "htmlDisabled" | "styleType" | "isActive" | "iconProps"> & {
@@ -55,6 +59,9 @@ export declare const Carousel: PolymorphicForwardRefComponent<"section", Carouse
55
59
  as?: "button" | undefined;
56
60
  }>;
57
61
  };
62
+ /**
63
+ * Contains the dots for activating the slides. Must be present _before_ the slides in DOM.
64
+ */
58
65
  DotsList: PolymorphicForwardRefComponent<"div", {
59
66
  length?: number | undefined;
60
67
  currentIndex?: number | undefined;
@@ -38,42 +38,9 @@ const CarouselComponent = React.forwardRef((props, ref) => {
38
38
  scrollToSlide.current(userActiveIndex, {
39
39
  instant: justMounted.current,
40
40
  });
41
- // re-focus the carousel for keyboard nav, but not on first mount
42
- // because it shows outline and might interfere with other components
43
- if (!justMounted.current) {
44
- carouselRef.current?.focus({ preventScroll: true });
45
- }
46
41
  justMounted.current = false;
47
42
  }, [userActiveIndex]);
48
43
  const [slideCount, setSlideCount] = React.useState(0);
49
- const [keysPressed, setKeysPressed] = React.useState({});
50
- const handleKeyDown = (event) => {
51
- if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
52
- return;
53
- }
54
- const key = event.key;
55
- if (key === 'ArrowLeft' || key === 'ArrowRight') {
56
- setKeysPressed((old) => ({ ...old, [key]: true }));
57
- }
58
- };
59
- const handleKeyUp = (event) => {
60
- switch (event.key) {
61
- case 'ArrowLeft': {
62
- setKeysPressed((old) => ({ ...old, ArrowLeft: false }));
63
- const prevIndex = (slideCount + currentIndex - 1) % slideCount;
64
- scrollToSlide.current(prevIndex);
65
- setCurrentIndex(prevIndex);
66
- break;
67
- }
68
- case 'ArrowRight': {
69
- setKeysPressed((old) => ({ ...old, ArrowRight: false }));
70
- const nextIndex = (slideCount + currentIndex + 1) % slideCount;
71
- scrollToSlide.current(nextIndex);
72
- setCurrentIndex(nextIndex);
73
- break;
74
- }
75
- }
76
- };
77
44
  const userOnSlideChange = (0, index_js_1.useLatestRef)(onSlideChange);
78
45
  React.useEffect(() => {
79
46
  userOnSlideChange.current?.(currentIndex);
@@ -83,9 +50,6 @@ const CarouselComponent = React.forwardRef((props, ref) => {
83
50
  {
84
51
  as: 'section',
85
52
  'aria-roledescription': 'carousel',
86
- tabIndex: 0,
87
- onKeyDown: handleKeyDown,
88
- onKeyUp: handleKeyUp,
89
53
  ref: refs,
90
54
  className: (0, classnames_1.default)('iui-carousel', className),
91
55
  ...rest,
@@ -99,7 +63,6 @@ const CarouselComponent = React.forwardRef((props, ref) => {
99
63
  setCurrentIndex,
100
64
  slideCount,
101
65
  setSlideCount,
102
- keysPressed,
103
66
  idPrefix: id,
104
67
  isManuallyUpdating,
105
68
  scrollToSlide,
@@ -111,7 +74,8 @@ const CarouselComponent = React.forwardRef((props, ref) => {
111
74
  });
112
75
  /**
113
76
  * The Carousel component consists of a set of slides, normally displayed one at a time. A navigation section is
114
- * located below the slides, consisting of "dots" and "previous"/"next" buttons, used for changing slides.
77
+ * shown below the slides, consisting of "dots" and "previous"/"next" buttons, used for changing slides; this navigation
78
+ * section must be present _before_ the slides in DOM order, even though it is visually shown below the slides.
115
79
  *
116
80
  * The currently shown slide can also be changed using the left/right arrow keys or by dragging on a touch device.
117
81
  *
@@ -119,18 +83,24 @@ const CarouselComponent = React.forwardRef((props, ref) => {
119
83
  *
120
84
  * @example
121
85
  * <Carousel>
86
+ * <Carousel.Navigation />
122
87
  * <Carousel.Slider>
123
88
  * <Carousel.Slide>...</Carousel.Slide>
124
89
  * <Carousel.Slide>...</Carousel.Slide>
125
90
  * <Carousel.Slide>...</Carousel.Slide>
126
91
  * </Carousel.Slider>
127
- * <Carousel.Navigation />
128
92
  * </Carousel>
129
93
  */
130
94
  exports.Carousel = Object.assign(CarouselComponent, {
131
95
  Slider: CarouselSlider_js_1.CarouselSlider,
132
96
  Slide: CarouselSlide_js_1.CarouselSlide,
97
+ /**
98
+ * Contains the dots and previous/next buttons for navigating the slides. Must be present _before_ the slides in DOM.
99
+ */
133
100
  Navigation: CarouselNavigation_js_1.CarouselNavigation,
101
+ /**
102
+ * Contains the dots for activating the slides. Must be present _before_ the slides in DOM.
103
+ */
134
104
  DotsList: CarouselDotsList_js_1.CarouselDotsList,
135
105
  Dot: CarouselDot_js_1.CarouselDot,
136
106
  });
@@ -16,10 +16,6 @@ export declare const CarouselContext: React.Context<{
16
16
  * State updater for slideCount.
17
17
  */
18
18
  setSlideCount: (length: number | ((old: number) => void)) => void;
19
- /**
20
- * Stateful value of the left/right arrow keys currently pressed.
21
- */
22
- keysPressed: Record<string, boolean>;
23
19
  /**
24
20
  * Prefix used for setting id for internal carousel components.
25
21
  */
@@ -17,7 +17,7 @@ exports.CarouselDot = React.forwardRef((props, ref) => {
17
17
  const { isActive, isSmaller, isSmall, className, ...rest } = props;
18
18
  return React.createElement(index_js_1.ButtonBase, {
19
19
  role: 'tab',
20
- tabIndex: -1,
20
+ tabIndex: isActive ? 0 : -1,
21
21
  className: (0, classnames_1.default)(
22
22
  'iui-carousel-navigation-dot',
23
23
  {
@@ -53,6 +53,7 @@ exports.CarouselDotsList = React.forwardRef((props, ref) => {
53
53
  context.setCurrentIndex(index);
54
54
  context.scrollToSlide.current(index);
55
55
  }
56
+ listRef.current?.children[index]?.focus();
56
57
  onSlideChange?.(index);
57
58
  },
58
59
  [context, onSlideChange],
@@ -105,13 +106,12 @@ exports.CarouselDotsList = React.forwardRef((props, ref) => {
105
106
  index < firstVisibleDotIndex || index > lastVisibleDotIndex;
106
107
  return React.createElement(CarouselDot_js_1.CarouselDot, {
107
108
  key: index,
108
- 'aria-label': `Slide ${index}`,
109
+ 'aria-label': `Slide ${index + 1}`,
109
110
  isActive: index === currentIndex,
110
111
  onClick: () => handleSlideChange(index),
111
112
  isSmall: isSecondSmallDot,
112
113
  isSmaller: isFirstSmallDot || isClipped,
113
114
  id: idPrefix && `${idPrefix}--dot-${index}`,
114
- 'aria-controls': idPrefix && `${idPrefix}--slide-${index}`,
115
115
  });
116
116
  });
117
117
  }, [
@@ -138,6 +138,27 @@ exports.CarouselDotsList = React.forwardRef((props, ref) => {
138
138
  justMounted.current = false;
139
139
  }
140
140
  }, [currentIndex, firstVisibleDotIndex, slideCount, visibleCount, width]);
141
+ const handleKeyDown = (event) => {
142
+ if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
143
+ return;
144
+ }
145
+ const key = event.key;
146
+ if (key === 'ArrowLeft' || key === 'ArrowRight') {
147
+ event.preventDefault();
148
+ }
149
+ };
150
+ const handleKeyUp = (event) => {
151
+ switch (event.key) {
152
+ case 'ArrowLeft': {
153
+ handleSlideChange((slideCount + currentIndex - 1) % slideCount);
154
+ break;
155
+ }
156
+ case 'ArrowRight': {
157
+ handleSlideChange((slideCount + currentIndex + 1) % slideCount);
158
+ break;
159
+ }
160
+ }
161
+ };
141
162
  return React.createElement(
142
163
  React.Fragment,
143
164
  null,
@@ -151,6 +172,9 @@ exports.CarouselDotsList = React.forwardRef((props, ref) => {
151
172
  role: 'tablist',
152
173
  'aria-label': 'Slides',
153
174
  ref: refs,
175
+ onKeyDown: handleKeyDown,
176
+ onKeyUp: handleKeyUp,
177
+ tabIndex: -1,
154
178
  ...rest,
155
179
  },
156
180
  children ?? dots,
@@ -6,7 +6,7 @@ import type { PolymorphicForwardRefComponent } from '../utils/index.js';
6
6
  *
7
7
  * `children` can be specified to override what is shown in this navigation section.
8
8
  */
9
- export declare const CarouselNavigation: PolymorphicForwardRefComponent<"nav", {}> & {
9
+ export declare const CarouselNavigation: PolymorphicForwardRefComponent<"div", {}> & {
10
10
  PreviousButton: PolymorphicForwardRefComponent<"button", Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
11
11
  ref?: ((instance: HTMLButtonElement | null) => void) | React.RefObject<HTMLButtonElement> | null | undefined;
12
12
  }, "label" | "as" | "size" | "htmlDisabled" | "styleType" | "isActive" | "iconProps"> & {
@@ -17,7 +17,6 @@ const CarouselNavigationComponent = React.forwardRef((props, ref) => {
17
17
  return React.createElement(
18
18
  index_js_1.Box,
19
19
  {
20
- as: 'nav',
21
20
  className: (0, classnames_1.default)(
22
21
  'iui-carousel-navigation',
23
22
  className,
@@ -49,20 +48,14 @@ const PreviousButton = React.forwardRef((props, ref) => {
49
48
  if (!context) {
50
49
  throw new Error('CarouselNavigation should be used inside Carousel');
51
50
  }
52
- const {
53
- slideCount,
54
- currentIndex,
55
- setCurrentIndex,
56
- keysPressed,
57
- scrollToSlide,
58
- } = context;
51
+ const { slideCount, currentIndex, setCurrentIndex, scrollToSlide } = context;
59
52
  return React.createElement(
60
53
  IconButton_js_1.IconButton,
61
54
  {
62
55
  styleType: 'borderless',
63
56
  size: 'small',
64
57
  tabIndex: -1,
65
- 'data-pressed': keysPressed['ArrowLeft'] || undefined,
58
+ 'aria-label': 'Previous',
66
59
  ref: ref,
67
60
  ...props,
68
61
  onClick: (e) => {
@@ -81,20 +74,14 @@ const NextButton = React.forwardRef((props, ref) => {
81
74
  if (!context) {
82
75
  throw new Error('CarouselNavigation should be used inside Carousel');
83
76
  }
84
- const {
85
- slideCount,
86
- currentIndex,
87
- setCurrentIndex,
88
- keysPressed,
89
- scrollToSlide,
90
- } = context;
77
+ const { slideCount, currentIndex, setCurrentIndex, scrollToSlide } = context;
91
78
  return React.createElement(
92
79
  IconButton_js_1.IconButton,
93
80
  {
94
81
  styleType: 'borderless',
95
82
  size: 'small',
96
83
  tabIndex: -1,
97
- 'data-pressed': keysPressed['ArrowRight'] || undefined,
84
+ 'aria-label': 'Next',
98
85
  ref: ref,
99
86
  ...props,
100
87
  onClick: (e) => {
@@ -12,5 +12,5 @@ type CarouselSlideProps = {
12
12
  * It is recommended that the slide content bring its own dimensions (esp. height) and that
13
13
  * the dimensions should be the same for all slides.
14
14
  */
15
- export declare const CarouselSlide: PolymorphicForwardRefComponent<"li", CarouselSlideProps>;
15
+ export declare const CarouselSlide: PolymorphicForwardRefComponent<"div", CarouselSlideProps>;
16
16
  export {};
@@ -22,7 +22,7 @@ exports.CarouselSlide = React.forwardRef((props, ref) => {
22
22
  if (!context || index == null) {
23
23
  throw new Error('CarouselSlide must be used within Carousel');
24
24
  }
25
- const { isManuallyUpdating, setCurrentIndex } = context;
25
+ const { isManuallyUpdating, currentIndex, setCurrentIndex } = context;
26
26
  const updateActiveIndexOnScroll = React.useCallback(() => {
27
27
  // only update index if scroll was triggered by browser
28
28
  if (!isManuallyUpdating.current) {
@@ -38,15 +38,25 @@ exports.CarouselSlide = React.forwardRef((props, ref) => {
38
38
  return React.createElement(
39
39
  index_js_1.Box,
40
40
  {
41
- as: 'li',
42
41
  className: (0, classnames_1.default)(
43
42
  'iui-carousel-slider-item',
44
43
  className,
45
44
  ),
46
45
  role: 'tabpanel',
47
46
  'aria-roledescription': 'slide',
47
+ tabIndex: index === currentIndex ? 0 : undefined,
48
48
  ref: refs,
49
+ inert: index !== currentIndex ? '' : undefined,
49
50
  ...rest,
51
+ onKeyDown: (0, index_js_1.mergeEventHandlers)(
52
+ props.onKeyDown,
53
+ (event) => {
54
+ // prevent default browser scrolling on arrow keys because focus will get lost when slide switches
55
+ if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
56
+ event.preventDefault();
57
+ }
58
+ },
59
+ ),
50
60
  },
51
61
  children,
52
62
  );
@@ -2,4 +2,4 @@ import type { PolymorphicForwardRefComponent } from '../utils/index.js';
2
2
  /**
3
3
  * `CarouselSlider` is the scrollable list that should consist of `CarouselSlide` components.
4
4
  */
5
- export declare const CarouselSlider: PolymorphicForwardRefComponent<"ol", {}>;
5
+ export declare const CarouselSlider: PolymorphicForwardRefComponent<"div", {}>;
@@ -27,6 +27,7 @@ exports.CarouselSlider = React.forwardRef((props, ref) => {
27
27
  React.isValidElement(child)
28
28
  ? React.cloneElement(child, {
29
29
  id: `${idPrefix}--slide-${index}`,
30
+ 'aria-labelledby': `${idPrefix}--dot-${index}`,
30
31
  index,
31
32
  })
32
33
  : child,
@@ -65,11 +66,10 @@ exports.CarouselSlider = React.forwardRef((props, ref) => {
65
66
  return React.createElement(
66
67
  index_js_1.Box,
67
68
  {
68
- as: 'ol',
69
- 'aria-live': 'polite',
70
69
  className: (0, classnames_1.default)('iui-carousel-slider', className),
71
70
  ref: refs,
72
71
  onScroll: handleOnScroll,
72
+ tabIndex: -1,
73
73
  ...rest,
74
74
  },
75
75
  items,
@@ -65,9 +65,9 @@ export type SliderProps = {
65
65
  */
66
66
  maxLabel?: React.ReactNode;
67
67
  /**
68
- * Additional props for container `<div>` that hold the slider rail, thumbs, and tracks.
68
+ * Additional props for container `<div>` that hold the slider thumbs, and tracks.
69
69
  */
70
- railContainerProps?: React.HTMLAttributes<HTMLDivElement>;
70
+ trackContainerProps?: React.HTMLAttributes<HTMLDivElement>;
71
71
  /**
72
72
  * Allows props to be passed for slider-min
73
73
  */
@@ -76,10 +76,6 @@ export type SliderProps = {
76
76
  * Allows props to be passed for slider-max
77
77
  */
78
78
  maxProps?: React.ComponentProps<'span'>;
79
- /**
80
- * Allows props to be passed for slider-rail
81
- */
82
- railProps?: React.ComponentProps<'div'>;
83
79
  /**
84
80
  * Allows props to be passed for slider-track
85
81
  */
@@ -90,10 +90,9 @@ exports.Slider = React.forwardRef((props, ref) => {
90
90
  onUpdate,
91
91
  thumbProps,
92
92
  className,
93
- railContainerProps,
93
+ trackContainerProps,
94
94
  minProps,
95
95
  maxProps,
96
- railProps,
97
96
  trackProps,
98
97
  tickProps,
99
98
  ticksProps,
@@ -332,12 +331,9 @@ exports.Slider = React.forwardRef((props, ref) => {
332
331
  index_js_1.Box,
333
332
  {
334
333
  ref: ref,
335
- className: (0, classnames_1.default)(
336
- 'iui-slider-component-container',
337
- `iui-slider-${orientation}`,
338
- { 'iui-disabled': disabled },
339
- className,
340
- ),
334
+ className: (0, classnames_1.default)('iui-slider-container', className),
335
+ 'data-iui-orientation': orientation,
336
+ 'data-iui-disabled': disabled ? 'true' : undefined,
341
337
  ...rest,
342
338
  },
343
339
  minValueLabel &&
@@ -356,26 +352,17 @@ exports.Slider = React.forwardRef((props, ref) => {
356
352
  React.createElement(
357
353
  index_js_1.Box,
358
354
  {
359
- as: 'div',
360
355
  ref: containerRef,
361
- ...railContainerProps,
356
+ ...trackContainerProps,
362
357
  className: (0, classnames_1.default)(
363
- 'iui-slider-container',
358
+ 'iui-slider',
364
359
  {
365
360
  'iui-grabbing': undefined !== activeThumbIndex,
366
361
  },
367
- railContainerProps?.className,
362
+ trackContainerProps?.className,
368
363
  ),
369
364
  onPointerDown: handlePointerDownOnSlider,
370
365
  },
371
- React.createElement(index_js_1.Box, {
372
- as: 'div',
373
- ...railProps,
374
- className: (0, classnames_1.default)(
375
- 'iui-slider-rail',
376
- railProps?.className,
377
- ),
378
- }),
379
366
  currentValues.map((thumbValue, index) => {
380
367
  const [minVal, maxVal] = getAllowableThumbRange(index);
381
368
  const thisThumbProps = thumbProps?.(index);
@@ -394,7 +381,6 @@ exports.Slider = React.forwardRef((props, ref) => {
394
381
  step: step,
395
382
  sliderMin: min,
396
383
  sliderMax: max,
397
- orientation: orientation,
398
384
  });
399
385
  }),
400
386
  React.createElement(Track_js_1.Track, {
@@ -405,8 +391,8 @@ exports.Slider = React.forwardRef((props, ref) => {
405
391
  orientation: orientation,
406
392
  ...trackProps,
407
393
  }),
408
- tickMarkArea,
409
394
  ),
395
+ tickMarkArea,
410
396
  maxValueLabel &&
411
397
  React.createElement(
412
398
  index_js_1.Box,
@@ -1,6 +1,5 @@
1
1
  import * as React from 'react';
2
2
  import { Tooltip } from '../Tooltip/Tooltip.js';
3
- import type { SliderProps } from './Slider.js';
4
3
  type ThumbProps = {
5
4
  /**
6
5
  * Thumb value.
@@ -54,7 +53,7 @@ type ThumbProps = {
54
53
  * Additional props for Thumb.
55
54
  */
56
55
  thumbProps?: React.HTMLAttributes<HTMLDivElement>;
57
- } & Pick<SliderProps, 'orientation'>;
56
+ };
58
57
  /**
59
58
  * Thumb is a local component used to show and modify the values maintained by the Slider.
60
59
  * Only one Thumb can be active at a time. A Thumb is made active when the user selects
@@ -30,7 +30,6 @@ const Thumb = (props) => {
30
30
  tooltipProps,
31
31
  thumbProps,
32
32
  disabled,
33
- orientation,
34
33
  } = props;
35
34
  const thumbRef = React.useRef(null);
36
35
  const handleOnKeyboardEvent = React.useCallback(
@@ -97,13 +96,10 @@ const Thumb = (props) => {
97
96
  },
98
97
  React.createElement(index_js_1.Box, {
99
98
  ...rest,
100
- 'data-index': index,
101
99
  ref: thumbRef,
102
100
  style: {
103
101
  ...style,
104
- ...(orientation === 'horizontal'
105
- ? { insetInlineStart: `${lowPercent}%` }
106
- : { insetBlockEnd: `${lowPercent}%` }),
102
+ '--iui-slider-thumb-position': `${lowPercent}%`,
107
103
  },
108
104
  className: (0, classnames_1.default)(
109
105
  'iui-slider-thumb',
@@ -10,11 +10,6 @@ const classnames_1 = tslib_1.__importDefault(require('classnames'));
10
10
  const React = tslib_1.__importStar(require('react'));
11
11
  const index_js_1 = require('../utils/index.js');
12
12
  const Icon_js_1 = require('../Icon/Icon.js');
13
- // Checking user motion preference for scroll into view animation
14
- const isMotionOk = () =>
15
- (0, index_js_1.getWindow)()?.matchMedia?.(
16
- '(prefers-reduced-motion: no-preference)',
17
- )?.matches;
18
13
  const TabsWrapper = React.forwardRef((props, ref) => {
19
14
  const {
20
15
  className,
@@ -124,21 +119,19 @@ const Tab = React.forwardRef((props, forwardedRef) => {
124
119
  const { tabsWidth } = (0, index_js_1.useSafeContext)(TabListContext);
125
120
  const tabRef = React.useRef();
126
121
  const isActive = activeValue === value;
122
+ const isActiveRef = (0, index_js_1.useLatestRef)(isActive);
123
+ // Scroll to active tab only on initial render
127
124
  (0, index_js_1.useIsomorphicLayoutEffect)(() => {
128
- if (isActive) {
129
- if (orientation === 'horizontal') {
130
- tabRef.current?.scrollIntoView({
131
- inline: 'center',
132
- behavior: isMotionOk() ? 'smooth' : 'auto',
133
- });
134
- } else {
135
- tabRef.current?.scrollIntoView({
136
- block: 'center',
137
- behavior: isMotionOk() ? 'smooth' : 'auto',
138
- });
139
- }
125
+ if (isActiveRef.current) {
126
+ tabRef.current?.parentElement?.scrollTo({
127
+ [orientation === 'horizontal' ? 'left' : 'top']:
128
+ tabRef.current?.[
129
+ orientation === 'horizontal' ? 'offsetLeft' : 'offsetTop'
130
+ ] - 4,
131
+ behavior: 'instant', // not using 'smooth' to reduce layout shift on page load
132
+ });
140
133
  }
141
- }, [isActive]);
134
+ }, []);
142
135
  const updateStripe = () => {
143
136
  const currentTabRect = tabRef.current?.getBoundingClientRect();
144
137
  setStripeProperties({
@@ -238,6 +231,7 @@ const Tab = React.forwardRef((props, forwardedRef) => {
238
231
  ),
239
232
  onKeyDown: (0, index_js_1.mergeEventHandlers)(props.onKeyDown, onKeyDown),
240
233
  onFocus: (0, index_js_1.mergeEventHandlers)(props.onFocus, () => {
234
+ tabRef.current?.scrollIntoView({ block: 'nearest', inline: 'nearest' });
241
235
  if (focusActivationMode === 'auto' && !props.disabled) {
242
236
  setActiveValue(value);
243
237
  }
@@ -17,9 +17,10 @@ type RootProps = {
17
17
  * This can cause a flash of incorrect theme on first render.
18
18
  *
19
19
  * The 'inherit' option is intended to be used by packages, to enable incremental adoption
20
- * of iTwinUI v2 in app that might be using v1 in other places.
20
+ * of iTwinUI while respecting the theme set by the consuming app. It will fall back to 'light'
21
+ * if no parent theme is found. Additionally, it will attempt to inherit the `portalContainer` if possible.
21
22
  *
22
- * @default 'light'
23
+ * @default 'inherit'
23
24
  */
24
25
  theme?: ThemeType | 'inherit';
25
26
  themeOptions?: Pick<ThemeOptions, 'highContrast'> & {
@@ -48,10 +48,17 @@ exports.ThemeProvider = React.forwardRef((props, forwardedRef) => {
48
48
  portalContainer: portalContainerProp,
49
49
  ...rest
50
50
  } = props;
51
- const [portalContainer, setPortalContainer] = (0,
52
- index_js_1.useControlledState)(null, portalContainerProp);
53
- const [parentTheme, rootRef] = useParentTheme();
51
+ const [parentTheme, rootRef, parentContext] = useParentTheme();
54
52
  const theme = themeProp === 'inherit' ? parentTheme || 'light' : themeProp;
53
+ /**
54
+ * We will portal our portal container into `portalContainer` prop (if specified),
55
+ * or inherit `portalContainer` from context (if also inheriting theme).
56
+ */
57
+ const portaledPortalContainer =
58
+ portalContainerProp ||
59
+ (themeProp === 'inherit' ? parentContext?.portalContainer : undefined);
60
+ const [portalContainer, setPortalContainer] = (0,
61
+ index_js_1.useControlledState)(null, portaledPortalContainer);
55
62
  const shouldApplyBackground = themeOptions?.applyBackground ?? !parentTheme;
56
63
  const contextValue = React.useMemo(
57
64
  () => ({ theme, themeOptions, portalContainer }),
@@ -75,14 +82,14 @@ exports.ThemeProvider = React.forwardRef((props, forwardedRef) => {
75
82
  Toaster_js_1.ToastProvider,
76
83
  null,
77
84
  children,
78
- portalContainerProp
85
+ portaledPortalContainer
79
86
  ? ReactDOM.createPortal(
80
87
  React.createElement(Toaster_js_1.Toaster, null),
81
- portalContainerProp,
88
+ portaledPortalContainer,
82
89
  )
83
90
  : React.createElement(
84
91
  'div',
85
- { ref: setPortalContainer },
92
+ { ref: setPortalContainer, style: { display: 'contents' } },
86
93
  React.createElement(Toaster_js_1.Toaster, null),
87
94
  ),
88
95
  ),
@@ -144,5 +151,5 @@ const useParentTheme = () => {
144
151
  ?.getAttribute('data-iui-theme'),
145
152
  );
146
153
  }, []);
147
- return [parentContext?.theme ?? parentThemeState, rootRef];
154
+ return [parentContext?.theme ?? parentThemeState, rootRef, parentContext];
148
155
  };