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

refactor(misc): CSS harcoded variables and classes replaced with react-tokens and react-styles #9266

Merged
merged 21 commits into from
Oct 12, 2023

Conversation

adamviktora
Copy link
Contributor

@adamviktora adamviktora commented Jun 13, 2023

What: Closes #9116

Notes, further related issues and some questions I have:

  1. CSS values were replaced with tokens in all .tsx files and .md demos, which include parts of TS code.
  2. CSS values were not replaced in .css and .md files.
  3. I was replacing mainly strings containing pf-v5 prefix, there are still plenty of them (usually some modifiers) starting with just pf- that could also be replaced.
  4. I was not able to replace values in any of the integration tests in packages/react-integration/cypress/integration as the react-tokens and react-styles packages cannot be imported due to configuration of package.json -- looking at it right now
  5. These CSS variables don't have a react token:
  1. There are lots of CSS classes which are not directly included in react-styles and I had to compute them from parts of string like this for example: "pf-v5-c-code-editor__keyboard-shortcuts" -> {'${styles.codeEditor}__keyboard-shortcuts'}

@adamviktora adamviktora marked this pull request as draft June 13, 2023 08:30
@patternfly-build
Copy link
Contributor

patternfly-build commented Jun 13, 2023

@adamviktora adamviktora marked this pull request as ready for review June 22, 2023 14:43
@tlabaj tlabaj requested a review from mcoker August 2, 2023 20:23
Copy link
Contributor

@nicolethoen nicolethoen left a comment

Choose a reason for hiding this comment

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

This PR is going to conflict with @kmcfaul's #9392. Where she is cleaning up usage of the screen reader class names. It may be worth either leaving it to katie to handle all those classes to make sure you don't undo anything she's doing - or make the same changes in your PR if hers merges first.

packages/react-core/src/components/Alert/examples/Alert.md Outdated Show resolved Hide resolved
packages/react-core/src/components/Badge/Badge.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, this file sort of demonstrates the difference between the hardcoded class and the one imported from utilities. I don't think we want that.

@@ -647,7 +648,9 @@ class CodeEditor extends React.Component<CodeEditorProps, CodeEditorState> {
{...getRootProps({
onClick: (event) => event.stopPropagation() // Prevents clicking TextArea from opening file dialog
})}
className={`pf-v5-c-file-upload ${isDragActive && 'pf-m-drag-hover'} ${isLoading && 'pf-m-loading'}`}
className={`${fileUploadStyles.fileUpload} ${isDragActive && fileUploadStyles.modifiers.dragHover} ${
Copy link
Contributor

Choose a reason for hiding this comment

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

@mcoker shouldn't these styles be available in the code editor stylesheet rather than also needing to load file upload stylesheet?

Copy link
Contributor

Choose a reason for hiding this comment

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

@tlabaj good question! Nope we don't include the file upload component styles in the code editor. AFAIK we don't do that for any component - a component only includes its styles. As far as I can tell, the only reason file upload styles are being imported is to get the loading state, which is not supported in the code editor. I don't think the way we're applying the file upload styles here is ideal though, I'm surprised it works the way it is 😅 I suppose it's worth considering if we need the loading styles at all? And if so, I suppose we should add them to the code editor. It should be a really simple addition.

We have since introduced the multiple file upload component, which mimics the empty state in its presentation. I wonder if that might be a more suitable component to use here instead of the empty state for uploading a file?

Copy link
Contributor

Choose a reason for hiding this comment

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

@mcoker I will open a follow up issue to reconsider this implementation

@@ -24,12 +25,12 @@ export const AboutModalComplexUserPositionedContent: React.FunctionComponent = (
hasNoContentContainer={true}
productName="Product Name"
>
<TextContent id="test1" className="pf-v5-u-py-xl">
<TextContent id="test1" className={spacing.pyXl}>
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it might be more meaningful for the consumer to see the actual class name in the example.
@mcoker what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

I have an issue in org to improve our documentation around react-tokens and react-styles so that products can better utilize them. I'd personally advocate for demonstrating how to use them well since this will reduce the work required to migrate to new major versions of PF. This avoids the hardcoding of strings with versioned prefixes.

@@ -19,7 +19,7 @@ export const AboutModalBoxContent: React.FunctionComponent<AboutModalBoxContentP
...props
}: AboutModalBoxContentProps) => (
<div className={css(styles.aboutModalBoxContent)} {...props}>
<div className={css('pf-v5-c-about-modal-box__body')}>
<div className={css(`${styles.aboutModalBox}__body`)}>
Copy link
Contributor

Choose a reason for hiding this comment

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

I do not think this change is needed. THe reason the class is hard coded here is because it is a placeholder and has no associated styles

Copy link
Contributor

Choose a reason for hiding this comment

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

The benefit to making changes like this one, as the versioned prefixes change over time, we won't need to come back and change all these hard coded strings - they will update automatically.

@@ -85,14 +86,14 @@ test('Renders with inherited element props spread to the component', () => {
expect(screen.getByRole('heading')).toHaveAccessibleName('Label');
});

test('Renders with class name pf-v5-c-accordion__expandable-content', () => {
test(`Renders with class name ${styles.accordionExpandableContent}`, () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

@wise-king-sullyman, what do you think about updating the test like this? Will loading the stylesheets impact performance?

Copy link
Contributor

Choose a reason for hiding this comment

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

It might impact performance, I'm honestly not sure if it would really be noticeable or not.

I think it's worth trying though, if we can't do this or something like it we'll have to update all of the classnames each major release, which isn't ideal.

Copy link
Contributor

Choose a reason for hiding this comment

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

Probably minimal. They job looks like it still completes in 4 minutes.

@@ -30,7 +31,7 @@ export const DrawerStackedContentBodyElements: React.FunctionComponent = () => {
const panelContent = (
<DrawerPanelContent>
<DrawerHead>
<h3 className="pf-v5-c-title pf-m-2xl" tabIndex={isExpanded ? 0 : -1} ref={drawerRef}>
<h3 className={`${styles.title} ${styles.modifiers['2xl']}`} tabIndex={isExpanded ? 0 : -1} ref={drawerRef}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment here about this not being meaningful.
Can we just use the title component here @mcoker ?

Copy link
Contributor

Choose a reason for hiding this comment

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

either that, or the styles object should be updated to explicitly note that we are loading Title styles and not drawer styles as I might assume from reading this quickly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I will use the Title component

@@ -40,7 +41,7 @@ export const DualListSelectorControlBase: React.FunctionComponent<DualListSelect
const privateRef = React.useRef(null);
const ref = innerRef || privateRef;
return (
<div className={css('pf-v5-c-dual-list-selector__controls-item', className)} {...props}>
<div className={css(`${styles.dualListSelectorControls}-item`, className)} {...props}>
Copy link
Contributor

Choose a reason for hiding this comment

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

same comment about this not being needed. This applies to everywhere this change was made.

Copy link
Contributor

Choose a reason for hiding this comment

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

I still want to push back on this. I think this is a pretty good improvement.
The benefit to making changes like this one, as the versioned prefixes change over time, we won't need to come back and change all these hard coded strings - they will update automatically.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

@nicolethoen nicolethoen left a comment

Choose a reason for hiding this comment

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

This is looking really good to me!
The only change I'd still encourage is to make sure that the Drawer examples that are loading Title styles be clear which styles they are using. the styles object should be called titleStyles or something similar to be clearer.

@tlabaj
Copy link
Contributor

tlabaj commented Sep 1, 2023

@adamviktora I opened the following issues for the Slider token
#9563
patternfly/patternfly#5892

@tlabaj
Copy link
Contributor

tlabaj commented Sep 1, 2023

@mcoker can you please answer Adam's question about this

--pf-v5-global--default-color--200 - this one should probably be --pf-v5-global--Color--200 ?

@mcoker
Copy link
Contributor

mcoker commented Sep 5, 2023

Hey @adamviktora re:

--pf-v5-global--default-color--200 - this one should probably be --pf-v5-global--Color--200 ?

The equivalent of that one in v5 is --pf-v5-global--custom-color--200. That said, if you're referring to this example below, unless the point of it being custom is that you can change the color, we could just remove the custom color and leave the text as "Custom item" - that should be obvious enough? wdyt @tlabaj?

content: <span style={{ color: 'var(--pf-v5-global--default-color--200)' }}>Custom item</span>

Screenshot 2023-09-05 at 10 37 04 AM

Copy link
Contributor

@mcoker mcoker left a comment

Choose a reason for hiding this comment

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

This LGTM! I left some nit comments, but even if you want to make them, I think they should be in a separate PR. Not sure if I could re-review this one 😅

The only one I'm not sure if it needs to be updated is a place you're no longer using .join() in a var assignment - #9266 (comment). You included .join() other places you made that same update to the button classNames but not that one.

@@ -18,6 +18,9 @@ propComponents:
section: components
---

import styles from '@patternfly/react-styles/css/components/Title/title';
Copy link
Contributor

Choose a reason for hiding this comment

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

just a nit but should this be namespaced like titleStyles or something since this is the drawer component?

@@ -40,7 +41,7 @@ export const DualListSelectorControlBase: React.FunctionComponent<DualListSelect
const privateRef = React.useRef(null);
const ref = innerRef || privateRef;
return (
<div className={css('pf-v5-c-dual-list-selector__controls-item', className)} {...props}>
<div className={css(`${styles.dualListSelectorControls}-item`, className)} {...props}>
Copy link
Contributor

Choose a reason for hiding this comment

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

@@ -10,6 +10,8 @@ import WarningTriangleIcon from '@patternfly/react-icons/dist/esm/icons/warning-
import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon';
import BullhornIcon from '@patternfly/react-icons/dist/esm/icons/bullhorn-icon';
import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing';
import styles from '@patternfly/react-styles/css/components/Form/form';
Copy link
Contributor

Choose a reason for hiding this comment

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

should we import this as formStyles?

@@ -376,7 +377,7 @@ test('Passes Popper an appendTo value of the presentation element', async () =>
await user.click(screen.getByRole('tab'));

// This assertion relies on the structure of the Popper mock to verify the correct props are being sent to Popper
expect(screen.getByText('Append to class name: pf-v5-c-tabs__item pf-m-overflow')).toBeVisible();
expect(screen.getByText(`Append to class name: ${styles.tabsItem} pf-m-overflow`)).toBeVisible();
Copy link
Contributor

Choose a reason for hiding this comment

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

should this use the styles.modifiers object?

Suggested change
expect(screen.getByText(`Append to class name: ${styles.tabsItem} pf-m-overflow`)).toBeVisible();
expect(screen.getByText(`Append to class name: ${styles.tabsItem} ${styles.modifiers.overflow}`)).toBeVisible();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

about the styles.modifiers we can do this in a separate PR, there is a ton of pf-m-something classes in the codebase, but as they don't use the -v5- version, I don't know if is it necessary

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool, sounds good! There could be a future where we version modifiers, and if we used styles.modifiers, it would pull that in. IMO it's probably better to not hard code as much as we can, too.

@@ -180,7 +181,7 @@ describe('TextInputGroupMain', () => {
expect(hintInput).toBeInTheDocument();
});

it('renders the hint input with classes pf-v5-c-text-input-group__text-input and pf-m-hint', () => {
it(`renders the hint input with classes ${styles.textInputGroupTextInput} and pf-m-hint`, () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

should this use the styles.modifiers obj?

Suggested change
it(`renders the hint input with classes ${styles.textInputGroupTextInput} and pf-m-hint`, () => {
it(`renders the hint input with classes ${styles.textInputGroupTextInput} and ${styles.modifiers.hint}`, () => {

@@ -20,6 +20,7 @@ import {
getResizeObserver
} from '@patternfly/react-core';
import DashboardWrapper from '@patternfly/react-core/src/demos/examples/DashboardWrapper';
import styles from '@patternfly/react-styles/css/components/Masthead/masthead';
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
import styles from '@patternfly/react-styles/css/components/Masthead/masthead';
import mastheadStyles from '@patternfly/react-styles/css/components/Masthead/masthead';

InputGroupItem
} from '@patternfly/react-core';
import { css } from '@patternfly/react-styles';
import styles from '@patternfly/react-styles/css/components/Button/button';
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
import styles from '@patternfly/react-styles/css/components/Button/button';
import buttonStyles from '@patternfly/react-styles/css/components/Button/button';

@@ -36,7 +45,7 @@ export class AlertGroupDemo extends React.Component<{}, AlertGroupDemoState> {
this.setState({ alerts: [...this.state.alerts, ...incomingAlerts] });
};
const getUniqueId = () => new Date().getTime();
const btnClasses = ['pf-v5-c-button', 'pf-m-secondary'].join(' ');
const btnClasses = css(styles.button, styles.modifiers.secondary);
Copy link
Contributor

Choose a reason for hiding this comment

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

you use .join() in other places where you're doing this. is that needed?

Suggested change
const btnClasses = css(styles.button, styles.modifiers.secondary);
const btnClasses = css(styles.button, styles.modifiers.secondary).join(' ');

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am using the css function here, which is a wrapper which "joins args into a className string".
So [styles.button, styles.modifiers.secondary].join(' '); is the same as css(styles.button, styles.modifiers.secondary).

We could probably use the css(classnames) function everywhere, instead of [classnames].join(" "), but the result is the same.

@@ -1,5 +1,8 @@
import React, { Component } from 'react';
import { Chip, ChipGroup } from '@patternfly/react-core';
import { css } from '@patternfly/react-styles';
import styles from '@patternfly/react-styles/css/components/Title/title';
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
import styles from '@patternfly/react-styles/css/components/Title/title';
import titleStyles from '@patternfly/react-styles/css/components/Title/title';

@@ -2,6 +2,7 @@ import * as React from 'react';
import { css } from '@patternfly/react-styles';
import styles from '@patternfly/react-styles/css/components/Table/table';
import scrollStyles from '@patternfly/react-styles/css/components/Table/table-scrollable';
import stylesTreeView from '@patternfly/react-styles/css/components/Table/table-tree-view';
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
import stylesTreeView from '@patternfly/react-styles/css/components/Table/table-tree-view';
import treeViewStyles from '@patternfly/react-styles/css/components/Table/table-tree-view';

@adamviktora
Copy link
Contributor Author

@mcoker thanks for the review! I did some changes in this PR, but they can be viewed separately in this commit: 85850e8 (nothing crucial though, mostly renaming styles -> buttonStyles and similar changes)

Copy link
Contributor

@mcoker mcoker left a comment

Choose a reason for hiding this comment

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

🎃👍

@tlabaj tlabaj merged commit e054f9e into patternfly:main Oct 12, 2023
10 checks passed
@patternfly-build
Copy link
Contributor

Your changes have been released in:

  • @patternfly/react-code-editor@5.2.0-prerelease.6
  • @patternfly/react-core@5.2.0-prerelease.6
  • @patternfly/react-docs@6.2.0-prerelease.6
  • @patternfly/react-integration@5.1.1-prerelease.11
  • demo-app-ts@5.1.1-prerelease.29
  • @patternfly/react-table@5.2.0-prerelease.6

Thanks for your contribution! 🎉

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

Successfully merging this pull request may close these issues.

Replace hard coded reference to CSS vars with imported react-tokens
6 participants