-
Notifications
You must be signed in to change notification settings - Fork 65
Description
Despite the fact only React usage is documented, @griffel/react is actually just a thin wrapper around the core functionality that is framework-agnostic (see also #370).
However, the ergonomics of using @griffel/core directly are questionable because while the React wrapper's makeStyles function returns a hook that ensures that the provided renderer and writing direction are used, @griffel/core's makeStyles returns a function that expects those context parameters to be provided as arguments so that it can spit out the actual class string:
const renderer = createDOMRenderer();
const dir = 'ltr';
const getStylesA = makeStyles({ root: { color: 'red' }});
const classesA = getStylesA({ renderer, dir });
const getStylesB = makeStyles({ root: { color: 'green' }});
const classesB = getStylesB({ renderer, dir });To simplify vanilla usage, I suggest providing a Griffel class whose instances would include pre-configured makeStyles, makeResetStyles and makeStaticStyles functions that return the class strings directly. The code above could then be simplified to this:
const { makeStyles } = new Griffel();
const classesA = makeStyles({ root: { color: 'red' }});
const classesB = makeStyles({ root: { color: 'green' }});You would of course be able to also provide your custom renderer and writing direction with new Griffel({ renderer, dir }), but if you didn't, a renderer would be created automatically with a createDOMRenderer() call and the left-to-right direction would be assumed. This would be in accordance with the default values of the React wrapper's RendererContext and TextDirectionContext.
Implementation is pretty straight-forward:
type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
type TextDirection = "ltr" | "rtl";
interface GriffelOptions {
insertionFactory?: GriffelInsertionFactory;
renderer?: GriffelRenderer;
dir?: TextDirection;
}
class Griffel
implements WithRequired<GriffelOptions, "renderer" | "dir">
{
insertionFactory?: GriffelInsertionFactory = undefined;
renderer: GriffelRenderer = createDOMRenderer();
dir: TextDirection = "ltr";
constructor(options?: GriffelOptions) {
Object.assign(this, options);
}
makeStyles = <Slots extends string | number>(
stylesBySlots: StylesBySlots<Slots>
) => {
const { insertionFactory, renderer, dir } = this;
return makeStyles(stylesBySlots, insertionFactory)({ renderer, dir });
};
makeResetStyles = (styles: GriffelResetStyle) => {
const { insertionFactory, renderer, dir } = this;
return makeResetStyles(styles, insertionFactory)({ renderer, dir });
};
makeStaticStyles = (styles: GriffelStaticStyles | GriffelStaticStyles[]) => {
const { insertionFactory, renderer } = this;
return makeStaticStyles(styles, insertionFactory)({ renderer });
};
}This is the code I would have to write if I were to employ Griffel in non-React projects today. It would be great if @griffel/core itself included such a class, as it would make it truly ready for framework-agnostic usage.
I would like to hear feedback from maintainers and could then submit a pull request if this addition to the library is deemed reasonable.