Skip to content

Conversation

@Markionium
Copy link
Member

@Markionium Markionium commented Apr 20, 2018

Pull request checklist

  • Addresses an existing issue: Fixes #0000
  • Include a change request file using $ npm run change

Description of changes

Adds the option to disable global classNames through the theme by setting the disableGlobalClassNames flag on the theme.

The issue that this PR solves is that global css overrides are a pain and being able to exclude them from the rendered components makes the render output saver to unexpected css overrides done by other fabric users on the same webpage.

Focus areas to test

(optional)

* master:
  DetailsRow: Flexshrink fix (microsoft#4622)
  [TextField] Implemented masking (microsoft#3783)
  Applying package updates.
  ComboBox: Add any event as additional parameter to onChanged callback for saving pending changes (microsoft#4594)
  Remove usage of Number.NaN (microsoft#4615)
@Markionium Markionium requested a review from dzearing April 20, 2018 18:31
@Markionium
Copy link
Member Author

Markionium commented Apr 20, 2018

I haven't found a good solution yet for globals in selectors that are not part of the same mergeStylesSet. Like the .contextualHost in the example below from office-ui-fabric-react/packages/office-ui-fabric-react/src/components/Persona/Persona.styles.ts

        selectors: {
          '.contextualHost': {
            display: 'none',
          },

          ':hover': {
            selectors: {
              '$primaryText': {
                color: palette.neutralDark,
              }
            }
          }
        }

Additionally this only takes care of global styles in the getStyles functions where we have the theme available. It does not work for all the instances where we just use css().

phkuo
phkuo previously requested changes Apr 21, 2018
import { loadTheme as legacyLoadTheme } from '@microsoft/load-themed-styles';

const defaultThemeFlags: IThemeFlags = {
disableGlobalClassNames: false,
Copy link
Contributor

Choose a reason for hiding this comment

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

This should NOT be part of the theme, it's part of the global settings of the page. (In other words, it wouldn't make sense for this setting to change when you change the theme.)

Copy link
Member

Choose a reason for hiding this comment

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

@phkuo Assuming we mix together themes, it makes sense to me. I'm a little confused. In a portion of the ui, we expect the styling to not have global class names. It feels like the right approach to me.

Copy link
Contributor

Choose a reason for hiding this comment

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

What do you mean by "we mix together themes"?

The theme is independent of the CSS on the page. It doesn't know and it doesn't care about CSS. It should be portable between web and non-web platforms.

Let's say you have custom CSS on the page targeting global classes for a web part. It doesn't make sense that as you go from theme to theme, that web part randomly does or doesn't pick up your custom CSS. If you put custom global CSS on the page, you want to separately manage whether it applies or not independent of the theme. This setting should not be tied to the theme.

It should be treated like "theme" with @Customizable, where you can mark portions of the page with it. Then you can turn it on/off globally, or just set it for one dialog or panel.

Copy link
Member

@dzearing dzearing Apr 23, 2018

Choose a reason for hiding this comment

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

If I understand you correctly, are you suggesting that:

  1. We add a prop to every component like "disableGlobalClassNames".
  2. We make that customizable.
  3. We pipe this into the getStyles function props.
  4. We use that prop, rather than theme.flags.disableGlobalClassNames

Because that seems really no better and just adds bloat. Is that somehow making devs' lives easier? Or the implementation cleaner?

When you say that you "hate adding more burden of knowledge on devs", what do you mean? What burden are you referring to? If I'm missing something, can you help come up with a clear alternative solution?

Copy link
Contributor

Choose a reason for hiding this comment

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

@dzearing
1.-3. seem like exactly the thing Customizer is for, no? Yes it does add bloat. I assumed any kind of global setting we'd want to be able to control it on a scoped basis as well. But I'm okay passing on it.

"Burden of knowledge" as in now every control has to have a const GlobalClassNames as well, on top of all the other stuff they already must do for getStyles(). I already have a two page document for myself on converting existing SCSS controls over to getStyles(), and I'm STILL adding to it. (I need to find time to polish and publish it.) I believe frameworks should remove boiler plate code, not add to it.
My proposed alternative is to put the logic in mergeStyles() (somewhere deep down in _processArgs()). If the passed in thing is a string, and it's not in our hash table, then throw it away.

I still STRONGLY believe it shouldn't be on the theme object. Example: you have a restaurant with a website. Part of the page is some list/table component that's the kids' menu. They're using global CSS to make the kids' menu Comic Sans, because it's a kids menu. Then they download some themes from online. Half the themes randomly make the kids' menu not respect the Comic Sans style, half of them do, with no rhyme or reason.
The theme should not contain settings.

Copy link
Member

@dzearing dzearing Apr 24, 2018

Choose a reason for hiding this comment

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

I think we should not have global classes at all. They are a relic of the past and create a mess of pollution, bugs, and frustration.

But this is a compromise. We don't want to break backwards compatibility for the things we define.

If a caller passes in a global classname, that's fine. So no, this is not something we would "disable in mergeStyles".

So the "burden of knowledge" does not impact the consumer. It is 100% transparent to them. I think you're only concern is inside of Fabric components? But again, think of this as a flight that is by default on, but can be opted out of on demand.

Yes customizer can handle this. I'm not completely sure it makes sense to pollute the documented props with this though. THAT is a burden to the consumer.

Copy link
Member Author

@Markionium Markionium Apr 24, 2018

Choose a reason for hiding this comment

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

@phkuo I kind of see your point and i had the same thought as you at first, that we could maybe do this in mergeStyles, but it also seems like the wrong place to do this and not really related to it's responsibilities.

As David says, we are doing this as a temporary solution and we would eventually like to remove global styles altogether, when that happens we can remove this flag from the theme again.

Additionally we are making people more aware when they are adding global styles by having them write the boiler plate (in the component.styles.ts files) might actually be a good thing as then they might reconsider if they actually need them in the first place ;)

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, so we'd do this for existing global class names, and then going forward we'd say no more global class names? In that case, you're right, it's no additional burden and there's no reason to pipe it through @customizer.

We want this on by default, right?

@phkuo
Copy link
Contributor

phkuo commented Apr 21, 2018

@dzearing Can't we do this in mergeStyles/mergeStyleSets (not sure which, haven't looked at the code in a while), if it's of type string then discard it? Possibly with a check to verify it's not an autogenerated class name that we've stored somewhere. I hate that we're adding more and more burden of knowledge on devs.

@dzearing
Copy link
Member

@phkuo I don't think we want to do this as a default for devs, so adding it to the type-safe ITheme interface seems pretty reasonable. It's far better than FabricConfig globals!

@Markionium
Copy link
Member Author

@dzearing any ideas on how to resolve the thing i mentioned above?

#4635 (comment)

For example i had to revert this guy as i thought this would work, but screener will fail. (i'm used to it working from mergeStyleSets.)
bf0be8e#diff-866543420638c86a15e73d841b74e7a5

Any ideas? else i can do a bit more digging :) I suspect it has to do with how the result of getStyles is handled.

@dzearing
Copy link
Member

dzearing commented Apr 23, 2018

I don't understand the purpose of

        selectors: {
          '.contextualHost': {
            display: 'none',
          },

@jordandrako ? (In persona.styles.ts)

@dzearing
Copy link
Member

@Markionium yeah that's a confusing issue. "Reaching into" the private styling implementation of another component is really violating, as it can easily break, or be deprecated (I think in this specific example, I can't see a reason why we have that selector there.)

There are potentially cases where it makes sense, but I would rather do something like "import this classname constant from another file and reference it". If we did that then yes, we would still have a global class name, which really is used as an identifier more than a style representation.

Maybe I can catch you in the morning on monday and chat about it.

@jordandrako
Copy link
Contributor

@dzearing It was in the sass file.

@dzearing
Copy link
Member

@jordandrako I think it can be removed. There are no references to that in the repo that i see.

import { IFontStyles } from './IFontStyles';
import { ISemanticColors } from './ISemanticColors';

export interface IThemeFlags {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need a whole list of flags for the theme. This isn't something we want to be adding to. We can have it as a sibling to isInverted, and then just document it as... internal use only? Something that cautions people that it's for a very narrow use case and most people don't need to worry about it.

Copy link
Member Author

Choose a reason for hiding this comment

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

That sounds sensible to me. I've moved this onto the theme object and added a big comment ;)

@dzearing
Copy link
Member

@Markionium Philip and I talked offline and he was misunderstanding this change. I think we're good now.

* master: (42 commits)
  Applying package updates.
  ProgressIndicator: Finish conversion to mergeStyles (microsoft#4595)
  Fix props validation for Breadcrumb (microsoft#4666)
  No unused vars part of ts (microsoft#4670)
  Picker/Autofill: fixes several minor bugs. (microsoft#4569)
  Fix Calendar component PREV/NEXT month, year, and "Go to today" handlers firing twice (microsoft#4662)
  Applying package updates.
  Merge styles order (microsoft#4664)
  Fabric component: revert class change and make it backwards compatible (microsoft#4671)
  Addressing Issue microsoft#3707 - OverflowSet: Add the ability to set aria-label (microsoft#4667)
  Fix input type for Tile ARIA label prop (microsoft#4668)
  Fix theme slots for DetailsList header colors (microsoft#4658)
  Applying package updates.
  Jolore/calendar updates (microsoft#4643)
  Remove wordWrap setting. (microsoft#4657)
  Pivot: convert to mergeStyles - part 1  (microsoft#4656)
  Use the `data-is-scrollable` attribute on the correct ScrollablePane div (microsoft#4602)
  Applying package updates.
  Remove unused iconClassName prop from Nav.types (microsoft#4634)
  Jest snapshots: classes in animations should autoexpand. (microsoft#4647)
  ...
* master:
  Added className to Calendar component (microsoft#4680)
  Fix bug for OWA+Safari+popup (microsoft#4681)
  Add optional props for custom divider rendering (microsoft#4687)
  Update package.json
  Add isEqual and isNotEqual utility (microsoft#4603)
  Fix minor typos (microsoft#4683)
  Allow function to be passed to Customizer settings/scopedSettings (microsoft#4677)
@Markionium Markionium force-pushed the mapol/noGlobalClassNames branch from 207d174 to 04df532 Compare April 27, 2018 10:04
@Markionium Markionium force-pushed the mapol/noGlobalClassNames branch from 3e06c04 to da15818 Compare April 27, 2018 10:49
@dzearing dzearing merged commit 6608006 into microsoft:master Apr 27, 2018
@microsoft microsoft locked as resolved and limited conversation to collaborators Aug 31, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants