Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(floating-ui): add feature flag for dynamic floating-ui styles #17446

Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
33c3a12
feat(feature-flag): create floating styles feature flag
annawen1 Sep 11, 2024
4a9f95f
feat(dropdown): add feature flag logic to dropdown and popover
annawen1 Sep 11, 2024
447e51f
Merge branch 'main' into feat/feature-flag-floating-styles
annawen1 Sep 16, 2024
94f8bd6
feat(toggletip): add feature flag story
annawen1 Sep 16, 2024
e57eae7
feat(floating-ui): add additional components
annawen1 Sep 16, 2024
13a8042
Merge remote-tracking branch 'upstream/main' into feat/feature-flag-f…
annawen1 Sep 23, 2024
148c054
chore: shorten flag name
annawen1 Sep 23, 2024
c86b9bc
chore: shorten flag name
annawen1 Sep 23, 2024
4ca0926
chore: the rest of the auto align components
annawen1 Sep 23, 2024
cb20e52
chore: set a few controls
annawen1 Sep 23, 2024
044b1c0
Merge branch 'main' into feat/feature-flag-floating-styles
annawen1 Sep 24, 2024
6598c75
chore: resolve merge conflict
annawen1 Oct 8, 2024
6fe3100
Update packages/react/src/components/FeatureFlags/overview.mdx
annawen1 Oct 8, 2024
1c10dd0
Merge branch 'main' into feat/feature-flag-floating-styles
annawen1 Oct 8, 2024
8926896
chore(storybook): add meta isTemplate to overview doc
annawen1 Oct 8, 2024
90b53cb
Update packages/react/src/components/Popover/DynamicStyles.featurefla…
annawen1 Oct 11, 2024
f85285b
Added tests for FluidTimePicker (#17541)
guidari Oct 8, 2024
36bc225
Added typescript types to fluid combobox and its skeleton state (#17563)
riddhybansal Oct 8, 2024
561e9eb
chore(deps): bump rollup (#17631)
dependabot[bot] Oct 9, 2024
09e0b63
test(togglesmallskeleton): add test coverage (#17674)
alisonjoseph Oct 9, 2024
e11b039
fix(FileUploaderDropContainer): resolve click handler errorerror (#17…
emyarod Oct 9, 2024
e811736
feat: combobox's new feature, autocomplete with typeahead (#17268)
Gururajj77 Oct 9, 2024
a899f7b
chore(storybook): move feature flag overview under welcome (#17685)
annawen1 Oct 9, 2024
f944e26
docs(web-components): remove old storybook copy (#17655)
abdonrd Oct 9, 2024
7596e86
docs(date-time-format): update link to carbon-for-products page (#17692)
janhassel Oct 9, 2024
9b73dfb
test(tabs): increase coverage (#17565)
ariellalgilmore Oct 9, 2024
2ba7b2c
fix(date-picker): clearing input and selecting a date (#17669)
ariellalgilmore Oct 9, 2024
77a7327
chore(chat-button-toggle-skeleton): test updates (#17440)
ariellalgilmore Oct 9, 2024
d040496
chore(release): v11.68.0 (#17696)
carbon-automation[bot] Oct 9, 2024
d18e138
test: increase test coverage to 100% for Tag (#17614)
2nikhiltom Oct 9, 2024
d64492f
fix: increase test coverage for ToggleTip (#17661)
2nikhiltom Oct 9, 2024
fc55a79
chore(issue-templates): always apply needs triage label (#17681)
tay1orjones Oct 9, 2024
929ac98
fix: link overview page is not loading (#17710)
preetibansalui Oct 10, 2024
fb6bcb6
test(structured-list): increase coverage (#17705)
ariellalgilmore Oct 10, 2024
dc2aebe
fix(tabs): add icon only 1px spacing (#17671)
alisonjoseph Oct 10, 2024
a7b5141
ci(actions): add workflow to calculate and surface PR merge rate (#17…
tay1orjones Oct 10, 2024
fa1548e
fix(TreeNode): preserve nested node expand state (#17630)
emyarod Oct 10, 2024
cf0a241
feat(tabs): added hover and active styles (#16523)
soumyaraju Oct 10, 2024
fa24616
chore(deps): update dependency @types/prop-types to v15.7.13 (#17657)
renovate[bot] Oct 10, 2024
43f1eea
fix(combobox): rendering aria-label (#17678)
ariellalgilmore Oct 10, 2024
729cf7d
fix: implement unique dynamic id generation for FileUploader componen…
Shankar-CodeJunkie Oct 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/feature-flags/feature-flags.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,8 @@ feature-flags:
description: >
Enable the new focus wrap behavior that doesn't use sentinel nodes
enabled: false
- name: enable-v12-dynamic-floating-styles
description: >
Enable dynamic setting of floating styles for components like Popover,
Tooltip, etc.
enabled: false
21 changes: 13 additions & 8 deletions packages/react/src/components/ComboBox/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { FormContext } from '../FluidForm';
import { useFloating, flip, autoUpdate } from '@floating-ui/react';
import { hide } from '@floating-ui/dom';
import { TranslateWithId } from '../../types/common';
import { useFeatureFlag } from '../FeatureFlags';

const {
InputBlur,
Expand Down Expand Up @@ -388,20 +389,24 @@ const ComboBox = forwardRef(
slug,
...rest
} = props;

const enableFloatingStyles =
useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;

const { refs, floatingStyles, middlewareData } = useFloating(
autoAlign
enableFloatingStyles
? {
placement: direction,
strategy: 'fixed',
middleware: [flip(), hide()],
middleware: autoAlign ? [flip(), hide()] : undefined,
whileElementsMounted: autoUpdate,
}
: {}
);
const parentWidth = (refs?.reference?.current as HTMLElement)?.clientWidth;

useEffect(() => {
if (autoAlign) {
if (enableFloatingStyles) {
const updatedFloatingStyles = {
...floatingStyles,
visibility: middlewareData.hide?.referenceHidden
Expand All @@ -417,7 +422,7 @@ const ComboBox = forwardRef(
refs.floating.current.style.width = parentWidth + 'px';
}
}
}, [autoAlign, floatingStyles, refs.floating, parentWidth]);
}, [enableFloatingStyles, floatingStyles, refs.floating, parentWidth]);
const prefix = usePrefix();
const { isFluid } = useContext(FormContext);
const textInput = useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -607,7 +612,7 @@ const ComboBox = forwardRef(
[`${prefix}--list-box--up`]: direction === 'top',
[`${prefix}--combo-box--warning`]: showWarning,
[`${prefix}--combo-box--readonly`]: readOnly,
[`${prefix}--autoalign`]: autoAlign,
[`${prefix}--autoalign`]: enableFloatingStyles,
});

const titleClasses = cx(`${prefix}--label`, {
Expand Down Expand Up @@ -785,10 +790,10 @@ const ComboBox = forwardRef(
() =>
getMenuProps({
'aria-label': deprecatedAriaLabel || ariaLabel,
ref: autoAlign ? refs.setFloating : null,
ref: enableFloatingStyles ? refs.setFloating : null,
}),
[
autoAlign,
enableFloatingStyles,
deprecatedAriaLabel,
ariaLabel,
getMenuProps,
Expand All @@ -815,7 +820,7 @@ const ComboBox = forwardRef(
light={light}
size={size}
warn={warn}
ref={autoAlign ? refs.setReference : null}
ref={enableFloatingStyles ? refs.setReference : null}
warnText={warnText}
warnTextId={warnTextId}>
<div className={`${prefix}--list-box__field`}>
Expand Down
13 changes: 12 additions & 1 deletion packages/react/src/components/ComboButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
autoUpdate,
} from '@floating-ui/react';
import { hide } from '@floating-ui/dom';
import { useFeatureFlag } from '../FeatureFlags';
import mergeRefs from '../../tools/mergeRefs';
import { MenuAlignment } from '../MenuButton';
import { TranslateWithId } from '../../types/common';
Expand Down Expand Up @@ -97,10 +98,20 @@ const ComboButton = React.forwardRef<HTMLDivElement, ComboButtonProps>(
},
forwardRef
) {
// feature flag utilized to separate out only the dynamic styles from @floating-ui
// flag is turned on when collision detection (ie. flip, hide) logic is not desired
const enableOnlyFloatingStyles = useFeatureFlag(
'enable-v12-dynamic-floating-styles'
);

const id = useId('combobutton');
const prefix = usePrefix();
const containerRef = useRef<HTMLDivElement>(null);
const middlewares = [flip({ crossAxis: false }), hide()];
let middlewares: any[] = [];

if (!enableOnlyFloatingStyles) {
middlewares = [flip({ crossAxis: false }), hide()];
}

if (menuAlignment === 'bottom' || menuAlignment === 'top') {
middlewares.push(
Expand Down
21 changes: 14 additions & 7 deletions packages/react/src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
size as floatingSize,
} from '@floating-ui/react';
import { hide } from '@floating-ui/dom';
import { useFeatureFlag } from '../FeatureFlags';

const { ItemMouseMove, MenuMouseLeave } =
useSelect.stateChangeTypes as UseSelectInterface['stateChangeTypes'] & {
Expand Down Expand Up @@ -274,8 +275,12 @@ const Dropdown = React.forwardRef(
}: DropdownProps<ItemType>,
ref: ForwardedRef<HTMLButtonElement>
) => {
const enableFloatingStyles = useFeatureFlag(
'enable-v12-dynamic-floating-styles'
);

const { refs, floatingStyles, middlewareData } = useFloating(
autoAlign
enableFloatingStyles || autoAlign
? {
placement: direction,

Expand All @@ -294,16 +299,18 @@ const Dropdown = React.forwardRef(
});
},
}),
flip(),
hide(),
autoAlign && flip(),
autoAlign && hide(),
],
whileElementsMounted: autoUpdate,
}
: {} // When autoAlign is turned off, floating-ui will not be used
: {}
// When autoAlign is turned off & the `enable-v12-dynamic-floating-styles` feature flag is not
// enabled, floating-ui will not be used
);

useEffect(() => {
if (autoAlign) {
if (enableFloatingStyles || autoAlign) {
const updatedFloatingStyles = {
...floatingStyles,
visibility: middlewareData.hide?.referenceHidden
Expand Down Expand Up @@ -503,7 +510,7 @@ const Dropdown = React.forwardRef(
const menuProps = useMemo(
() =>
getMenuProps({
ref: autoAlign ? refs.setFloating : null,
ref: enableFloatingStyles || autoAlign ? refs.setFloating : null,
}),
[autoAlign, getMenuProps, refs.setFloating]
);
Expand Down Expand Up @@ -534,7 +541,7 @@ const Dropdown = React.forwardRef(
warnText={warnText}
light={light}
isOpen={isOpen}
ref={autoAlign ? refs.setReference : null}
ref={enableFloatingStyles || autoAlign ? refs.setReference : null}
id={id}>
{invalid && (
<WarningFilled className={`${prefix}--list-box__invalid-icon`} />
Expand Down
36 changes: 20 additions & 16 deletions packages/react/src/components/FeatureFlags/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,16 @@ For more details on this approach, see the
[feature flag documentation](https://github.com/carbon-design-system/carbon/blob/main/docs/experimental-code.md)
in the Carbon monorepo.

| Flag | Description | Default | Javascript flag | Sass flag |
| -------------------------------------------------- | ------------------------------------------------------------------------ | ------- | --------------- | --------- |
| `enable-experimental-tile-contrast` | Enable the improved styling for tiles that provides better contrast | `false` | | ✅ |
| `enable-experimental-focus-wrap-without-sentinels` | Enable the new focus wrap behavior that doesn't use sentinel nodes | `false` | ✅ | |
| `enable-treeview-controllable` | Enable the new TreeView controllable API | `false` | ✅ | |
| `enable-v12-tile-default-icons` | Enable default icons for Tile components | `false` | ✅ | |
| `enable-v12-overflowmenu` | Enable the use of the v12 OverflowMenu leveraging the Menu subcomponents | `false` | ✅ | |
| `enable-v12-tile-radio-icons` | Enable rendering of default icons in the tile components | `false` | ✅ | ✅ |
| `enable-v12-structured-list-visible-icons` | Enable icon components within StructuredList to always be visible | `false` | | ✅ |
| Flag | Description | Default | Javascript flag | Sass flag |
| -------------------------------------------------- | ------------------------------------------------------------------------------------ | ------- | --------------- | --------- |
| `enable-experimental-tile-contrast` | Enable the improved styling for tiles that provides better contrast | `false` | | ✅ |
| `enable-experimental-focus-wrap-without-sentinels` | Enable the new focus wrap behavior that doesn't use sentinel nodes | `false` | ✅ | |
| `enable-treeview-controllable` | Enable the new TreeView controllable API | `false` | ✅ | |
| `enable-v12-tile-default-icons` | Enable default icons for Tile components | `false` | ✅ | |
| `enable-v12-overflowmenu` | Enable the use of the v12 OverflowMenu leveraging the Menu subcomponents | `false` | ✅ | |
| `enable-v12-tile-radio-icons` | Enable rendering of default icons in the tile components | `false` | ✅ | ✅ |
| `enable-v12-structured-list-visible-icons` | Enable icon components within StructuredList to always be visible | `false` | | ✅ |
| `enable-v12-dynamic-floating-styles` | Enable dynamic setting of floating styles for components like Popover, Tooltip, etc. | `false` | ✅ | ✅ |

## Turning on feature flags in Javascript/react

Expand Down Expand Up @@ -117,11 +118,14 @@ Feature flags can also be enabled via the provided `enable()` mixin

## FeatureFlags Prop Update

The `FeatureFlags` component has been updated to improve compatibility. The `flags` object prop is now deprecated and is replaced with individual boolean props for each feature flag.

The `flags` prop will be removed in a future release. Instead, use individual boolean props for each feature flag.
A `featureflag-deprecate-flags-prop` codemod has been provided to help deprecate the `flags` object prop and switch to individual boolean props.
The `FeatureFlags` component has been updated to improve compatibility. The
`flags` object prop is now deprecated and is replaced with individual boolean
props for each feature flag.

The `flags` prop will be removed in a future release. Instead, use individual
boolean props for each feature flag. A `featureflag-deprecate-flags-prop`
codemod has been provided to help deprecate the `flags` object prop and switch
to individual boolean props.
annawen1 marked this conversation as resolved.
Show resolved Hide resolved

```bash
npx @carbon/upgrade migrate featureflag-deprecate-flags-prop --write
Expand All @@ -130,9 +134,9 @@ npx @carbon/upgrade migrate featureflag-deprecate-flags-prop --write
```jsx
//Before migration

<FeatureFlags
<FeatureFlags
flags={{
'enable-v12-tile-default-icons': true,
'enable-v12-tile-default-icons': true,
}}>
<App />
</FeatureFlags>
Expand All @@ -143,4 +147,4 @@ npx @carbon/upgrade migrate featureflag-deprecate-flags-prop --write
<FeatureFlags enableV12TileDefaultIcons>
<App />
</FeatureFlags>
```
```
14 changes: 13 additions & 1 deletion packages/react/src/components/MenuButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
size as floatingSize,
autoUpdate,
} from '@floating-ui/react';
import { useFeatureFlag } from '../FeatureFlags';
import mergeRefs from '../../tools/mergeRefs';

const validButtonKinds = ['primary', 'tertiary', 'ghost'];
Expand Down Expand Up @@ -97,10 +98,20 @@ const MenuButton = forwardRef<HTMLDivElement, MenuButtonProps>(
},
forwardRef
) {
// feature flag utilized to separate out only the dynamic styles from @floating-ui
// flag is turned on when collision detection (ie. flip, hide) logic is not desired
const enableOnlyFloatingStyles = useFeatureFlag(
'enable-v12-dynamic-floating-styles'
);

const id = useId('MenuButton');
const prefix = usePrefix();
const triggerRef = useRef<HTMLDivElement>(null);
const middlewares = [flip({ crossAxis: false })];
let middlewares: any[] = [];

if (!enableOnlyFloatingStyles) {
middlewares = [flip({ crossAxis: false })];
}

if (menuAlignment === 'bottom' || menuAlignment === 'top') {
middlewares.push(
Expand All @@ -113,6 +124,7 @@ const MenuButton = forwardRef<HTMLDivElement, MenuButtonProps>(
})
);
}

const { refs, floatingStyles, placement, middlewareData } = useFloating({
placement: menuAlignment,

Expand Down
28 changes: 19 additions & 9 deletions packages/react/src/components/MultiSelect/MultiSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
autoUpdate,
} from '@floating-ui/react';
import { hide } from '@floating-ui/dom';
import { useFeatureFlag } from '../FeatureFlags';

const {
ItemClick,
Expand Down Expand Up @@ -362,8 +363,11 @@ const MultiSelect = React.forwardRef(
const [topItems, setTopItems] = useState([]);
const [itemsCleared, setItemsCleared] = useState(false);

const enableFloatingStyles =
useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;

const { refs, floatingStyles, middlewareData } = useFloating(
autoAlign
enableFloatingStyles
? {
placement: direction,

Expand All @@ -375,23 +379,23 @@ const MultiSelect = React.forwardRef(

// Middleware order matters, arrow should be last
middleware: [
flip({ crossAxis: false }),
autoAlign && flip({ crossAxis: false }),
floatingSize({
apply({ rects, elements }) {
Object.assign(elements.floating.style, {
width: `${rects.reference.width}px`,
});
},
}),
hide(),
autoAlign && hide(),
],
whileElementsMounted: autoUpdate,
}
: {}
);

useLayoutEffect(() => {
if (autoAlign) {
if (enableFloatingStyles) {
const updatedFloatingStyles = {
...floatingStyles,
visibility: middlewareData.hide?.referenceHidden
Expand All @@ -404,7 +408,13 @@ const MultiSelect = React.forwardRef(
}
});
}
}, [autoAlign, floatingStyles, refs.floating, middlewareData, open]);
}, [
enableFloatingStyles,
floatingStyles,
refs.floating,
middlewareData,
open,
]);

const {
selectedItems: controlledSelectedItems,
Expand Down Expand Up @@ -551,7 +561,7 @@ const MultiSelect = React.forwardRef(
selectedItems && selectedItems.length > 0,
[`${prefix}--list-box--up`]: direction === 'top',
[`${prefix}--multi-select--readonly`]: readOnly,
[`${prefix}--autoalign`]: autoAlign,
[`${prefix}--autoalign`]: enableFloatingStyles,
[`${prefix}--multi-select--selectall`]: selectAll,
});

Expand Down Expand Up @@ -689,9 +699,9 @@ const MultiSelect = React.forwardRef(
const menuProps = useMemo(
() =>
getMenuProps({
ref: autoAlign ? refs.setFloating : null,
ref: enableFloatingStyles ? refs.setFloating : null,
}),
[autoAlign, getMenuProps, refs.setFloating]
[enableFloatingStyles, getMenuProps, refs.setFloating]
);

return (
Expand Down Expand Up @@ -729,7 +739,7 @@ const MultiSelect = React.forwardRef(
)}
<div
className={multiSelectFieldWrapperClasses}
ref={autoAlign ? refs.setReference : null}>
ref={enableFloatingStyles ? refs.setReference : null}>
{selectedItems.length > 0 && (
<ListBox.Selection
readOnly={readOnly}
Expand Down
Loading
Loading