-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Allo 👋
This is an initial effort to organize and catalog the meta data we need to create fully visually editable components.
It's super early, and we are more concerned with identifying the needs and less concerned with solutioning the perfect API at this stage.
Here's one pseudo-code approach with fake examples. Please pick it apart for what won't work:
Registering a component
// Creates a new CSS-in-JS component and registers it with interop:
const Slider = interop({ elem: 'div', name: 'Slider' });
// 1. We need to know about default styles
Slider.style({
color: 'gray',
'&:hover': {
color: 'darkgray',
}
});
// 2. We need to know about variant props
Slider.variants({
color: {
red: {
color: 'red',
},
blue: {
color: 'blue',
}
}
});
// 3. We need to know about utility props:
Slider.util([color, backgroundColor, margin]);
// 4. We need to know about possible states, both CSS and manual:
Slider.states(['hover', 'highlighted', 'focused']);
// 5. We need to know which properties are editable in the UI:
Slider.styleProperties({
'Fill': 'backgroundColor', // individual properties, friendlyName -> CSS Property
textPanel: true, // predefined groupings of properties in a panel
})
// 6. We need to know about children parts:
const Track = Slider.addChild({ elem: 'div', name: 'Track' });
Track.style({
backgroundColor: 'black',
});
Track.styleProperties({
'height': 'height'
});
// 7. We need to know about non-variant props for the top level component...
// there's opportunity here to use something like TypeScript parsing to build
// these automatically, but starting with a brute force method:
Slider.defineProps({
upsideDown: Types.Boolean,
twoHandles: Types.Boolean,
})
Using the Parts to build a component
Registering a new component with interop will return a Styled Component (or CSS-in-JS component of your choosing). We'll probably need to re-arrange this example code or use a property to access the CSS-in-JS component like <Slider.Component />
const MySlider = ({ sliderCss, trackCss }) => (
// Note sliderCss.highlighted is available here to do custom state wire-up
<Slider css={sliderCss}>
<Track css={trackCss} />
</Slider>
);
Creating examples
// We can just use the real component:
Slider.example = MySlider;
// Or a custom new component:
Slider.example = ({ sliderCss, trackCss }) => (
<Slider css={sliderCss}>
<Track css={trackCss} someExampleProp={true} />
</Slider>
);
// Examples get passed a partState object that lets them have custom logic based on forced states from the editor:
type ExampleProps = {
sliderCss: StyleConfigPart,
trackCss: StyleConfigPart,
partState: { [partId: string]: string } // like { slider: 'normal', track: 'normal' }
}
// Each part can have its own example when selected (will default to parent's example):
Track.example = ({ sliderCss, trackCss, partState }) => {
console.log(partState);
/* ^^^ outputs:
{
slider: 'normal',
track: 'hover'
}
*/
return (
<div>
Track is hovered? {String(partState.track === 'hover')}
<Track trackCss={trackCss} />
</div>
);
}
Collocating docs
Though I think most docs will be built visually in the Style Guide visual editor, they'll write to the same JSON object as the rest of this... so I think there should be function endpoints to write it too. This is the least defined part of all of this, but wanted to keep it on the list of needs.
Slider.addDocBlock({
name: 'DocBlock 1',
// MDX? JSX? MD? Plain text? HTML!?!
code: (
<div>Only use this in the header</div>
),
});
Data IDs to support hover highlights:
// Rendered HTML for the above examples to support hover highlights and potentially click to select:
<div data-part-id="some-unique-slider">
<div data-part-id="unique-id-track"></div>
</div>
Global helper data
// Globally, there exists a properties to scale mapping to give the correct theme values in the UI:
const scaleKey = {
'backgroundColor': ThemeScale.Colors,
'padding': ThemeScale.size,
};
// And a property to group map to keep properties organized for good muscle memory:
const propertiesToGroups = {
'backgroundColor': PropertyGroups.Colors,
'letterSpacing': PropertyGroups.Text
}
What am I forgetting?!