Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into rohan/nested-dropdown…
Browse files Browse the repository at this point in the history
…-menu-stay-open
  • Loading branch information
r100-stack committed Mar 27, 2024
2 parents 005bd2c + 6fabef3 commit 09ce20a
Show file tree
Hide file tree
Showing 18 changed files with 135 additions and 157 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-mugs-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@itwin/itwinui-css": patch
---

Fixed a regression in `iui-tabs` where the panel content was not occupying the full width of the container.
5 changes: 5 additions & 0 deletions .changeset/spicy-plums-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@itwin/itwinui-react": minor
---

Bumped the minimum required version of `@floating-ui/react` from `^0.26.3` to `^0.26.10`. (Make sure to also update transitive deps!)
3 changes: 0 additions & 3 deletions examples/Tabs.actions.css

This file was deleted.

2 changes: 1 addition & 1 deletion examples/Tabs.actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Tabs, Button } from '@itwin/itwinui-react';

export default () => {
return (
<Tabs.Wrapper className='demo-container'>
<Tabs.Wrapper>
<Tabs.TabList>
<Tabs.Tab value='apple' label='Apple' key='apple' />
<Tabs.Tab value='orange' label='Orange' key='orange' />
Expand Down
3 changes: 0 additions & 3 deletions examples/Tabs.borderless.css

This file was deleted.

2 changes: 1 addition & 1 deletion examples/Tabs.borderless.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Tabs } from '@itwin/itwinui-react';

export default () => {
return (
<Tabs.Wrapper type='borderless' className='demo-container'>
<Tabs.Wrapper type='borderless'>
<Tabs.TabList>
<Tabs.Tab value='apple' label='Apple' key='apple' />
<Tabs.Tab value='orange' label='Orange' key='orange' />
Expand Down
3 changes: 0 additions & 3 deletions examples/Tabs.controlled.css

This file was deleted.

1 change: 0 additions & 1 deletion examples/Tabs.controlled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export default () => {
value={currentTabValue}
onValueChange={(value) => setCurrentTabValue(value)}
defaultValue='pear'
className='demo-container'
>
<Tabs.TabList>
<Tabs.Tab value='apple' label='Apple' key='apple' />
Expand Down
3 changes: 0 additions & 3 deletions examples/Tabs.main.css

This file was deleted.

2 changes: 1 addition & 1 deletion examples/Tabs.main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Tabs } from '@itwin/itwinui-react';

export default () => {
return (
<Tabs.Wrapper className='demo-container'>
<Tabs.Wrapper>
<Tabs.TabList>
<Tabs.Tab value='apple' label='Apple' key='apple' />
<Tabs.Tab value='orange' label='Orange' key='orange' />
Expand Down
3 changes: 0 additions & 3 deletions examples/Tabs.pill.css

This file was deleted.

2 changes: 1 addition & 1 deletion examples/Tabs.pill.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Tabs } from '@itwin/itwinui-react';

export default () => {
return (
<Tabs.Wrapper type='pill' className='demo-container'>
<Tabs.Wrapper type='pill'>
<Tabs.TabList>
<Tabs.Tab value='apple' label='Apple' key='apple' />
<Tabs.Tab value='orange' label='Orange' key='orange' />
Expand Down
1 change: 1 addition & 0 deletions packages/itwinui-css/src/tabs/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ $borderless-horizontal-tab-min-height: calc(
grid-template-columns: 1fr auto;
grid-template-rows: auto 1fr;
contain: inline-size;
inline-size: 100%;

.iui-tabs {
display: flex;
Expand Down
11 changes: 11 additions & 0 deletions packages/itwinui-react/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 3.7.4

### Patch Changes

- [#1944](https://github.com/iTwin/iTwinUI/pull/1944): Fixed an issue where `Tooltip` would stay open after clicking on the trigger element. The tooltip will now be correctly dismissed upon click.

Also affects other components that use tooltips internally: `IconButton`, `SideNavigation`, etc.

- [#1955](https://github.com/iTwin/iTwinUI/pull/1955): Fixed a regression in `Tabs` where the panel content was not occupying the full width of the container.
- [#1954](https://github.com/iTwin/iTwinUI/pull/1954): Fixed an issue in older Safari versions where visually-hidden styles inside `ProgressRadial` were not being applied.

## 3.7.3

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/itwinui-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@itwin/itwinui-react",
"version": "3.7.3",
"version": "3.7.4",
"author": "Bentley Systems",
"license": "MIT",
"type": "module",
Expand Down Expand Up @@ -77,7 +77,7 @@
"dev:styles": "pnpm build:styles --watch"
},
"dependencies": {
"@floating-ui/react": "^0.26.3",
"@floating-ui/react": "^0.26.10",
"@itwin/itwinui-illustrations-react": "^2.1.0",
"classnames": "^2.3.2",
"react-table": "^7.8.0",
Expand Down
8 changes: 5 additions & 3 deletions packages/itwinui-react/src/core/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
offset,
flip,
shift,
useClick,
useHover,
useFocus,
useDismiss,
Expand Down Expand Up @@ -173,10 +172,13 @@ const useTooltip = (options: TooltipOptions = {}) => {
useHover(floating.context, {
delay: delay ?? { open: 50, close: 250 },
handleClose: safePolygon({ buffer: -Infinity }),
move: false,
}),
useFocus(floating.context),
useClick(floating.context),
useDismiss(floating.context),
useDismiss(floating.context, {
referencePress: true,
referencePressEvent: 'click',
}),
]);

// Manually add attributes and event handlers to external reference element,
Expand Down
126 changes: 84 additions & 42 deletions packages/itwinui-react/src/core/utils/components/ShadowRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,24 @@
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { useLatestRef, useLayoutEffect } from '../hooks/index.js';

const isBrowser = typeof document !== 'undefined';
const supportsDSD =
isBrowser && 'shadowRootMode' in HTMLTemplateElement.prototype;
const supportsAdoptedStylesheets =
isBrowser && 'adoptedStyleSheets' in Document.prototype;

type ShadowRootProps = { children: React.ReactNode; css?: string };

/**
* Wrapper around `<template>` element that attaches shadow root to its parent
* and moves its children into the shadow root.
*
* @private
*/
export const ShadowRoot = ({
children,
css,
}: {
children: React.ReactNode;
css?: string;
}) => {
const [shadowRoot, setShadowRoot] = React.useState<ShadowRoot>();
export const ShadowRoot = ({ children, css }: ShadowRootProps) => {
const isFirstRender = useIsFirstRender();
const styleSheet = React.useRef<CSSStyleSheet>();

const attachShadowRef = React.useCallback(
(template: HTMLTemplateElement | null) => {
const parent = template?.parentElement;
if (!template || !parent) {
return;
}
if (parent.shadowRoot) {
parent.shadowRoot.replaceChildren(); // Remove previous shadowroot content
}
queueMicrotask(() => {
const shadow =
parent.shadowRoot || parent.attachShadow({ mode: 'open' });

if (css && supportsAdoptedStylesheets) {
styleSheet.current ||= new CSSStyleSheet();
styleSheet.current.replaceSync(css);
shadow.adoptedStyleSheets = [styleSheet.current];
}

ReactDOM.flushSync(() => setShadowRoot(shadow));
});
},
[css],
);

if (!isBrowser) {
return (
Expand All @@ -68,19 +38,91 @@ export const ShadowRoot = ({
return null;
}

return (
<>
{shadowRoot ? (
ReactDOM.createPortal(children, shadowRoot)
) : (
<template ref={attachShadowRef} />
)}
</>
return <ClientShadowRoot css={css}>{children}</ClientShadowRoot>;
};

// ----------------------------------------------------------------------------

const ClientShadowRoot = ({ children, css }: ShadowRootProps) => {
const templateRef = React.useRef<HTMLTemplateElement>(null);
const shadowRoot = useShadowRoot(templateRef, { css });

// fallback to <style> tag if adoptedStyleSheets is not supported
const fallbackCss =
!supportsAdoptedStylesheets && css ? <style>{css}</style> : null;

return shadowRoot ? (
ReactDOM.createPortal(
<>
{fallbackCss}
{children}
</>,
shadowRoot,
)
) : (
<template ref={templateRef} />
);
};

// ----------------------------------------------------------------------------

/**
* Given a ref, this hook will return a shadowRoot attached to its parent element.
*
* The css will be added to the shadowRoot using `adoptedStyleSheets` (if supported).
*/
function useShadowRoot(
templateRef: React.RefObject<HTMLElement>,
{ css = '' },
) {
const [shadowRoot, setShadowRoot] = React.useState<ShadowRoot | null>(null);
const styleSheet = React.useRef<CSSStyleSheet>();
const latestCss = useLatestRef(css);

useLayoutEffect(() => {
const parent = templateRef.current?.parentElement;
if (!parent) {
return;
}

if (parent.shadowRoot) {
parent.shadowRoot.replaceChildren(); // Remove previous shadowroot content
}

const shadow = parent.shadowRoot || parent.attachShadow({ mode: 'open' });

if (supportsAdoptedStylesheets) {
// create an empty stylesheet and add it to the shadowRoot
const currentWindow = shadow.ownerDocument.defaultView || globalThis;
styleSheet.current = new currentWindow.CSSStyleSheet();
shadow.adoptedStyleSheets = [styleSheet.current];

// add the CSS immediately to avoid FOUC (one-time)
if (latestCss.current) {
styleSheet.current.replaceSync(latestCss.current);
}
}

queueMicrotask(() => {
// Flush the state immediately to ensure layout measurements in parent component are correct
ReactDOM.flushSync(() => setShadowRoot(shadow));
});

return () => void setShadowRoot(null);
}, [templateRef, latestCss]);

// Synchronize `css` with contents of the existing stylesheet
useLayoutEffect(() => {
if (css && supportsAdoptedStylesheets) {
styleSheet.current?.replaceSync(css);
}
}, [css]);

return shadowRoot;
}

// ----------------------------------------------------------------------------

function useIsFirstRender() {
const [isFirstRender, setIsFirstRender] = React.useState(true);
React.useEffect(() => setIsFirstRender(false), []);
Expand Down
Loading

0 comments on commit 09ce20a

Please sign in to comment.