Skip to content

chore(scss): migrate core mixin kibanaFullBodyHeight to Emotion#220494

Merged
afharo merged 13 commits intoelastic:mainfrom
afharo:core/remove-scss-mixin-kibanaFullBodyHeight
May 19, 2025
Merged

chore(scss): migrate core mixin kibanaFullBodyHeight to Emotion#220494
afharo merged 13 commits intoelastic:mainfrom
afharo:core/remove-scss-mixin-kibanaFullBodyHeight

Conversation

@afharo
Copy link
Member

@afharo afharo commented May 8, 2025

Summary

#214729 started migrating away from the mixin kibanaFullBodyHeight.
This PR removes the other usages and the mixin itself.

@afharo afharo self-assigned this May 8, 2025
@afharo afharo added backport:version Backport to applied version labels v8.19.0 labels May 8, 2025
@afharo afharo marked this pull request as ready for review May 8, 2025 15:15
@afharo afharo requested review from a team as code owners May 8, 2025 15:15
@afharo afharo added backport:skip This PR does not require backporting release_note:skip Skip the PR/issue when compiling release notes Team:Platform-Design Team Label for Kibana Design Team. Support the Analyze group of plugins. Team:Kibana Management Dev Tools, Index Management, Upgrade Assistant, ILM, Ingest Node Pipelines, and more t// and removed backport:skip This PR does not require backporting labels May 8, 2025
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-management (Team:Kibana Management)

@afharo afharo added the Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas t// label May 8, 2025
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-presentation (Team:Presentation)

Comment on lines -40 to -42
.painlessLabMainContainer {
@include kibanaFullBodyHeight($bodyOffset);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could have removed only this one... but I got carried over and ported all the CSS in this file 😬


.euiColorPicker__emptySwatch {
position: relative;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure where this is leveraged, so I decided to keep it for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That appears to be an EUI-specific css class; however, I find no reference of it the EUI repo. I tried jumping back in time to older versions, but its hard to search that way... still didn't find anything.

Given it is scoped to the Maps app (#maps-plugin id), and the color pickers on the layers seem to behave the same with it commented out (tested that), I personally feel confident in removing it.

@ThomThomson ThomThomson requested a review from mbondyra May 8, 2025 16:32
Copy link
Contributor

@ryankeairns ryankeairns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested full screen in Discover, Dashboard, and Maps. All work as expected.
Changes lgtm.

<div id="react-maps-root">
<div
id="react-maps-root"
css={css`
Copy link
Contributor

@mbondyra mbondyra May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For performance reasons, we avoid inlining css inside components. Instead, we declare styles outside the component or memoize them when possible. Otherwise, the styles are re-serialized on every render. These are small (sub-millisecond) operations, but they accumulate—so as a rule, we should always avoid inline css unless absolutely necessary.
(Optimization I here: https://engineering.deptagency.com/optimizing-emotion-in-react)

<div id="maps-plugin" className={this.props.isFullScreen ? 'mapFullScreen' : ''}>
<div
id="maps-plugin"
css={css`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For performance, avoid composing styles directly inside the css`` template. Instead, define static and conditional styles outside, and pass them as an array. This prevents re-serializing the template on each render and improves readability.

const mapsPluginStyles = {
  display: 'flex',
  flexDirection: 'column',
  width: '100%',
  overflow: 'hidden',
};

const fullscreenStyles = { height: '100vh !important' };

css={[kibanaFullBodyHeightCss(), mapsPluginStyles, isFullScreen && fullscreenStyles]}

(reference read: https://douges.dev/blog/taming-the-beast-that-is-css-in-js)

Comment on lines +103 to +107
css={css`
${kibanaFullBodyHeightCss(bodyOffset)}
overflow: hidden;
flex-shrink: 1;
`}
Copy link
Contributor

@mbondyra mbondyra May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overflow and flex-shrink styles should be moved outside the component as a static object. But there's another issue here—we’ve recently agreed to avoid dynamic styles in css prop and use the style prop instead.

So the preferred approach is:

const mapsPluginStyles = {
  overflow: 'hidden',
  flexShrink: 1,
};

css={mapsPluginStyles} style={kibanaFullBodyHeightCss(bodyOffset)}

Note: kibanaFullBodyHeightCss should be refactored to return a plain object instead of a css string, so it can be used with the style prop:

export const kibanaFullBodyHeightCss = (additionalOffset = 0) => ({
  height: `calc(
    100vh - var(--kbnAppHeadersOffset, var(--euiFixedHeadersOffset, 0)) - ${additionalOffset}px
  )`,
});

🔗 Discussion reference

@afharo afharo requested review from a team as code owners May 9, 2025 16:15
@afharo afharo requested a review from mbondyra May 9, 2025 16:15
Comment on lines +22 to +24
export const kibanaFullBodyHeightCss = (additionalOffset = '0px') => ({
height: `calc(100vh - var(--kbnAppHeadersOffset, var(--euiFixedHeadersOffset, 0)) - ${additionalOffset})`,
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allowing a more free form input rather than integer px. This allows linking to vars, making other calculations, etc.

@@ -19,11 +19,9 @@ import bg_bottom_branded_dark from './styles/core_app/images/bg_bottom_branded_d
// The `--kbnAppHeadersOffset` CSS variable is automatically updated by
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File renamed because the linter complained about the name not following snake_case format.

const dscDocsPageCss = css`
${kibanaFullBodyHeightCss(54)}; // 54px is the action bar height
`;
const dscDocsPageCss = kibanaFullBodyHeightCss('54px'); // 54px is the action bar height
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to wrap it in a css template. Slight perf improvement.

Comment on lines +17 to +19
export const mapFullScreenStyles = {
height: '100vh !important',
};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intentionally not adding the type CSSObject because this type is not compatible with the style prop 🤷, and I'm using it there because it's a dynamic style.

Copy link
Contributor

@jughosta jughosta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Data Discovery changes LGTM 👍

Copy link
Contributor

@mattkime mattkime left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code changes look good and work well, thanks!

Copy link
Contributor

@jloleysens jloleysens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job! Core changes LGTM. Did a code-only review and left a suggestion I'd like to get your thoughts on.

(I'm assuming code owners will check the appearance of their apps are as expected 🤞🏻 ) appears they did 😉

* }
* const styles = useMemoizedStyles(componentStyles);
*/
export const useMemoizedStyles = (styleMap: StyleMap) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat!

Not intended as a blocker, but I wonder if we don't achieve a decent enough developer UX when grabbing the euiTheme object from css prop on components (e.g.).

Then to get the style definition "statically" colocated outside components we could use TS like:

// css_utils.ts
import type { Attributes } from 'react';

// Helper type for getting CSS attribute from React
export type CSSAttribute = Required<Attributes>['css'];
export type StyleMap = Record<string, CSSAttribute>;

// somewhere_else.ts
import type { CSSAttribute, StyleMap } from 'css_utils'

const styles: CSSAttribute = ({ euiTheme }) => ({
  '& + &': { marginTop: euiTheme.size.s },
  backgroundColor: euiTheme.colors.backgroundBasePrimary,
  body: '1vh',
  // ...
});

<MyComponent css={styles} />

// or

const styles = {
  container: () => ...
} satisfies StyleMap;

<MyComponent css={styles.container} />

...but I'm not an emotion expert! Perhaps your way is more performant/easier to use.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mbondyra, can you help me answer this question? 😇

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @jloleysens — it's mostly a performance thing 🙂 With this approach, all styles are memoized.

That syntactic sugar you mentioned can actually hurt performance, since the function runs and re-serializes styles on every render—even though it looks cleaner in the JSX. There's also a small mistake in this comment: elastic/eui#6828 (comment) — defining the function outside the component doesn't help, because it still runs on each render as long as it’s a function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation, that makes sense 👍🏻

Co-authored-by: Jean-Louis Leysens <jloleysens@gmail.com>
@afharo afharo enabled auto-merge (squash) May 19, 2025 20:34
@afharo afharo merged commit 9c20f23 into elastic:main May 19, 2025
8 checks passed
@afharo afharo deleted the core/remove-scss-mixin-kibanaFullBodyHeight branch May 19, 2025 21:41
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.19

https://github.com/elastic/kibana/actions/runs/15123770596

@elasticmachine
Copy link
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #18 / Actions and Triggers app Connectors General connector functionality should test a connector and display a successful result

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
painlessLab 38 25 -13

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
discover 1006.9KB 1007.0KB +31.0B
maps 3.0MB 3.0MB -309.0B
painlessLab 15.8KB 16.2KB +444.0B
searchprofiler 43.0KB 43.2KB +182.0B
total +348.0B

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
core 439.6KB 439.8KB +170.0B
painlessLab 11.0KB 5.7KB -5.3KB
searchprofiler 16.5KB 16.4KB -123.0B
total -5.3KB

History

cc @afharo

@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.19 Backport failed because of merge conflicts

Manual backport

To create the backport manually run:

node scripts/backport --pr 220494

Questions ?

Please refer to the Backport tool documentation

@afharo
Copy link
Member Author

afharo commented May 20, 2025

Cancelling backport because there are breaking changes in some of the modified files.

@afharo afharo added backport:skip This PR does not require backporting and removed backport:version Backport to applied version labels v8.19.0 labels May 20, 2025
akowalska622 pushed a commit to akowalska622/kibana that referenced this pull request May 29, 2025
…astic#220494)

Co-authored-by: mbondyra <marta.bondyra@elastic.co>
Co-authored-by: Marta Bondyra <4283304+mbondyra@users.noreply.github.com>
Co-authored-by: Matthew Kime <matt@mattki.me>
Co-authored-by: Jean-Louis Leysens <jloleysens@gmail.com>
qn895 pushed a commit to qn895/kibana that referenced this pull request Jun 3, 2025
…astic#220494)

Co-authored-by: mbondyra <marta.bondyra@elastic.co>
Co-authored-by: Marta Bondyra <4283304+mbondyra@users.noreply.github.com>
Co-authored-by: Matthew Kime <matt@mattki.me>
Co-authored-by: Jean-Louis Leysens <jloleysens@gmail.com>
@mbondyra mbondyra added backport:version Backport to applied version labels v8.19.0 and removed backport:skip This PR does not require backporting labels Jun 18, 2025
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.19

https://github.com/elastic/kibana/actions/runs/15735705068

@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.19 Backport failed because of merge conflicts

Manual backport

To create the backport manually run:

node scripts/backport --pr 220494

Questions ?

Please refer to the Backport tool documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting release_note:skip Skip the PR/issue when compiling release notes Team:Kibana Management Dev Tools, Index Management, Upgrade Assistant, ILM, Ingest Node Pipelines, and more t// Team:Platform-Design Team Label for Kibana Design Team. Support the Analyze group of plugins. Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas t// v9.1.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants