# Next Meeting 2020-11-22/3?
# 2020-11-20
### Perf
- [1] Must have build time optimizations
- Even if not solved, must prove it CAN be added soon
- Runtime, obviously fast as possible :/
### Specificity
Specificity is in JS, not CSS selectors in sheet
- User can't see it to work around it
- User has no control over it when it doesn't work
- Underlying changes break the user (atomic plus stylex)
Render/write order of styles at runtime (overrides, new theme, etc)
- [1] CSS insertion at runtime (support proper document)
- [2] SSR support (req stable classes)
### Dynamic Styles
Enable build-time optimizations, no runtime values?
- No props
- No conditional styles (ie Teams variables usage)
- Caveat, themes are OK, they're available at build time
- [X] Theme "swtiching" live must work
## Next
Try stylex as mid-solution that uses atomic but also provides ordering for specificity as well as build time optimizations.
- [ ] Miro and/or Shift to get stylex algorithm working, try makeStyles() api updates first
# makeStyles 2020-11-16
CONCLUSION:
Miro - test makeStyles in v0 Docs Avatar
Levi - test makeStyles in Teams Avatar
David - test makeStyles in Ribbon Button
REQUIREMENT:
Deterministic styles due to deterministic order of dep graph.
ASSUMES top-level imports are 1:1 with dep graph order.
Caveats where makeStyles call order doesn't follow dep graph:
- Execution order of the graph is non-deterministic when lazy loading components since top-level execution order is based on runtime logic.
-
If the requirement is not ALWAYS true, this solution will not work.
## Tests
### iFrame/Multi-Window
How will we render parent styles in iframe?
1. iframe src
2. iframe injection (Teams)
- BaseButton (F)
- Button (T)
- CallingButton -> iFrame
### Multiple Experiences
Override styles are dependent on dependency graph.
```
A: .ui-button { border: 1px }
B: ...
Style: A B C D E ...
\ /
\ /
\ /
Comp: X (has overrides that work for A styles)
|
BaseX
- X has overrides that assume stylesheet A exists FIRST
- X breaks when overrides written to stylesheet B
```
## Async Imports
This makes the _execution order_ of dependency graph non-deterministic. The graph itself is still deterministic.
```
import { fooButtonStyles, barButtonStyles }
fooButtonStyles()
barButtonStyles()
const Base =
if foo import 'foo-button' ()
else if bar import 'bar-button' ()
makeStyles { button overrides }
```
### Workaround
The solution (entirely resolvable by the consumer dev) is to avoid using styles from the parent across the async boundary.
Bad:
Need to automate preventing this pattern
- Cannot apply top-level makeStyles classes to lazy components
- Instead, load the styles at the same time as the component (lazy)
```tsx=
const MyDialog = React.lazy(() => import('./OtherComponent'));
const useAppClasses = makeStyles({
dialog: { background: 'red' }
})
const App = () => {
const classes = useAppClasses();
return (
<div>
<Suspense fallback={<h1>Loading profile...</h1>}>
<MyDialog className={classes.dialog} slot={{ className: classes.foo }} />
</Suspense>
</div>;
);
}
```
Better: no classes across boundaries
My dialog self-contained in another `MyDialog.tsx` file:
```tsx
import { Dialog } from 'fluentui';
const useAppClasses = makeStyles({
dialog: { background: 'red' }
})
export const MyDialog = () => {
const classes = useClasses();
return <Dialog className={classes.dialog }/>
```
Dialog is async imported without classes:
```tsx
const MyDialog = React.lazy(() => import('./MyDialog'));
const App = () => {
const classes = useAppClasses();
return (
<div>
<Suspense fallback={<h1>Loading profile...</h1>}>
<MyDialog />
</Suspense>
</div>;
);
}
```
## Sharing styles dictates style import order
Just like CSS stylesheets, the import order of the styles MUST be maintained to ensure specificity is maintained.
```jsx
focusRing.ts
export const focusRing = makeStyles({ring: { outline: '1px solid red'}})
export const focusRingOverrides = {ring: { outline: '1px solid red'}}
fileA.ts
import {Button}
import focusRing
const focusRing2
<Button className={focusRing} />
fileB.ts
import {MenuButton}
import focusRing
<MenuButton className={focusRing} />
Dialog: uses A first, then b:
.Button
.focusRing
.MenuButton
Toolbar: uses B first, then a:
.Button
.MenuButton
.focusRing
expected:
.Button
.MenuButton
.focusRing
```
Thought: is this a restriction we can live with? Essentially, we're saying: when you override stuff, it should live in the same file that imports the thing it overides. That is; if focusRing should be shared by both things, it would be resolved by having the focusRing import both things it overrides (Button and MenuButton) before makeStyles is called.
Alternative idea: How override classes could solve specificity:
```tsx
const useClasses = makeStyles({...});
const Button = (props) => {
const classes = useClasses({
overrideClasses: {
root: props.className
}
});
return <button className={classes.root} />
}
```
Downsides mentioned:
* Every override layer would need to pass along the styles this way, adds complexity:
```
A5
A6.2
A6.1
A6
A7
<Avatar className={myOverrides.avatar}
```
```jsx
MyButton.ts
import Button
makeStyles({ ... })
MyExp.ts
import MyButton
.Button
.overrides
OtherExpButton.ts
import Button
makeStyles({ ... })
OtherExp.ts
import OtherExpButton
.Button
.OtherExpButton (overrides)
import MyButton
.MyButton
. overrides break because they don't know about ^^^
```