-
Notifications
You must be signed in to change notification settings - Fork 53
feat(variants): Add variants to compose. #2281
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { configure } from '@storybook/react'; | ||
import { withInfo } from '@storybook/addon-info'; | ||
import { addDecorator } from '@storybook/react'; | ||
|
||
addDecorator(withInfo()); | ||
|
||
const req = require.context('../src', true, /\.stories\.tsx$/); | ||
|
||
function loadStories() { | ||
return req.keys().map(req); | ||
} | ||
|
||
configure(loadStories, module); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
const webpackConfig = require('@fluentui/scripts/config/storybook/webpack.config'); | ||
module.exports = webpackConfig; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import React from 'react'; | ||
|
||
import { ThemeProvider } from './../../components/ThemeProvider/ThemeProvider'; | ||
import { compose } from './../../compose'; | ||
import { Variant } from './../../variant'; | ||
import { theme } from './../theme'; | ||
|
||
export default { | ||
component: 'complex compose', | ||
title: 'Slightly More Complex Compose Demos', | ||
}; | ||
|
||
const BaseDisplay: React.FunctionComponent<{ | ||
classes: any; | ||
slots: any; | ||
slotProps: any; | ||
title: string; | ||
}> = props => { | ||
return ( | ||
<div className={props.classes.root}> | ||
<props.slots.header className={props.classes.header}>{props.title}</props.slots.header> | ||
{props.children} | ||
</div> | ||
); | ||
}; | ||
|
||
const ComposedDisplay = compose(BaseDisplay as any, { | ||
slots: { | ||
header: 'h2', | ||
}, | ||
tokens: { | ||
fontWeight: 300, | ||
borderRadius: 0, | ||
disabled: false, | ||
}, | ||
styles: (tokens: any) => { | ||
const style: any = { | ||
root: { | ||
background: 'red', | ||
borderRadius: tokens.borderRadius, | ||
margin: 10, | ||
padding: 10, | ||
}, | ||
header: { | ||
fontWeight: tokens.fontWeight, | ||
}, | ||
}; | ||
if (!tokens.disabled) { | ||
style.root['&:hover'] = { | ||
background: 'blue', | ||
}; | ||
style.header['&:hover'] = { | ||
textDecoration: 'underline', | ||
}; | ||
} else { | ||
style.root.background = '#ddd'; | ||
style.root.color = '#333'; | ||
} | ||
return style; | ||
}, | ||
variants: { | ||
disabled: Variant.boolean({ disabled: true }), | ||
strong: Variant.boolean({ fontWeight: 700 }), | ||
rounded: Variant.boolean({ borderRadius: 30 }), | ||
}, | ||
}); | ||
|
||
export const composedDemo = () => ( | ||
<ThemeProvider theme={theme}> | ||
<ComposedDisplay>I am children</ComposedDisplay> | ||
</ThemeProvider> | ||
); | ||
|
||
export const variantDemo = () => { | ||
return ( | ||
<ThemeProvider theme={theme}> | ||
<ComposedDisplay title="Lorem Ipsum">Default control</ComposedDisplay> | ||
<ComposedDisplay title="Lorem Ipsum" strong> | ||
Strong variant | ||
</ComposedDisplay> | ||
<ComposedDisplay title="Lorem Ipsum" rounded> | ||
Rounded variant | ||
</ComposedDisplay> | ||
<ComposedDisplay title="Lorem Ipsum" strong rounded> | ||
Strong & rounded variants | ||
</ComposedDisplay> | ||
<ComposedDisplay title="Lorem Ipsum" disabled> | ||
Disabled variant | ||
</ComposedDisplay> | ||
<ComposedDisplay title="Lorem Ipsum" strong disabled> | ||
Strong & Disabled variant | ||
</ComposedDisplay> | ||
<ComposedDisplay title="Lorem Ipsum" rounded disabled> | ||
Rounded & Disabled variant | ||
</ComposedDisplay> | ||
<ComposedDisplay title="Lorem Ipsum" strong rounded disabled> | ||
Strong & Rounded & Disabled variants | ||
</ComposedDisplay> | ||
</ThemeProvider> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import React from 'react'; | ||
|
||
import { ThemeProvider } from './../../components/ThemeProvider/ThemeProvider'; | ||
import { compose } from './../../compose'; | ||
import { Variant } from './../../variant'; | ||
import { theme } from './../theme'; | ||
|
||
export default { | ||
component: 'compose', | ||
title: 'Compose Demos', | ||
}; | ||
|
||
const BaseDiv: React.FunctionComponent<{ classes: any }> = props => { | ||
return <div className={props.classes.root}>{props.children}</div>; | ||
}; | ||
|
||
const ComposedDiv = compose(BaseDiv as any, { | ||
tokens: { | ||
fontWeight: 300, | ||
borderRadius: 0, | ||
}, | ||
styles: (tokens: any) => { | ||
return { | ||
root: { | ||
background: 'red', | ||
fontWeight: tokens.fontWeight, | ||
borderRadius: tokens.borderRadius, | ||
margin: 10, | ||
padding: 10, | ||
}, | ||
}; | ||
}, | ||
variants: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can see that this is inspired from the work we have done on #2200 however after playing a bit with it, I have some doubts about how it would work when you will need to combine variants together. More over, usually for some variants like disable, you want to override everything that was previously defined (like no hover styles for example), would lieke to hear from you how you envision these to work. Generally, I think it would be useful to see more complex styles examples that will require the above mention scenarios. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added another scenario with a |
||
strong: Variant.boolean({ fontWeight: 700 }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks interesting, however sometimes in the definition of the styles we will want to specify something if some variant is not defined, how would that work? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For lack of a variant, the styles will default to whatever was defined in the base set of tokens. It would be easy to define another style of variant (eg |
||
rounded: Variant.boolean({ borderRadius: 30 }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to reiterate some verbal discussion we had, I think it'd be neat if variants could also support slot implementations at component creation time rather than have to be passed in at render time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks pretty good. One thought I have - do we have a perf test validating the compose examples? Could we maybe hook one up to Checkbox proto or Slider or something? |
||
}, | ||
}); | ||
|
||
export const composedDemo = () => ( | ||
<ThemeProvider theme={theme}> | ||
<ComposedDiv>I am children</ComposedDiv> | ||
</ThemeProvider> | ||
); | ||
|
||
export const variantDemo = () => { | ||
return ( | ||
<ThemeProvider theme={theme}> | ||
<ComposedDiv>Default control</ComposedDiv> | ||
<ComposedDiv strong>Strong variant</ComposedDiv> | ||
<ComposedDiv rounded>Rounded variant</ComposedDiv> | ||
<ComposedDiv strong rounded> | ||
Strong & rounded variants | ||
</ComposedDiv> | ||
</ThemeProvider> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { initializeStyling, IColorRamp, ITheme } from './../index'; | ||
|
||
initializeStyling(); | ||
|
||
const emptyRamp: IColorRamp = { values: [], index: -1 }; | ||
export const theme: ITheme = { | ||
components: {}, | ||
colors: { | ||
background: 'white', | ||
bodyText: 'black', | ||
subText: 'black', | ||
disabledText: 'green', | ||
brand: emptyRamp, | ||
accent: emptyRamp, | ||
neutral: emptyRamp, | ||
success: emptyRamp, | ||
warning: emptyRamp, | ||
danger: emptyRamp, | ||
}, | ||
fonts: { | ||
default: '', | ||
userContent: '', | ||
mono: '', | ||
}, | ||
fontSizes: { | ||
base: 1, | ||
scale: 1, | ||
unit: 'rem', | ||
}, | ||
animations: { | ||
fadeIn: {}, | ||
fadeOut: {}, | ||
}, | ||
direction: 'ltr', | ||
spacing: { | ||
base: 0, | ||
scale: 0, | ||
unit: 'rem', | ||
}, | ||
radius: { | ||
base: 0, | ||
scale: 0, | ||
unit: 'rem', | ||
}, | ||
icons: {}, | ||
schemes: {}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this was intentional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now it is, as this PR doesn't yet implement correct caching based on props. Will be in a following PR once we ratify the design of variants. Good callout though!