dojo / cli

:rocket: Dojo - command line tooling.
http://dojo.io
Other
26 stars 34 forks source link

Command: Theme generation #168

Closed bitpshr closed 6 years ago

bitpshr commented 6 years ago

Enhancement

We should create a tool that helps with theme generation. Specifically, the tool should help improve the following processes:

Package Version: rc

umaar commented 6 years ago

Still learning, so some ideas might not make sense!

Exploring ideas to improve the theming story

Introduction

This GitHub comment outlines my investigation into the mechanisms and potential improvements for theming.

The points below are numbered so you can quickly refer to it in your response.

1. Clarification on one problem we wish to solve

When theming some widgets, for example built-in Dojo 2 Button widget, you may wish to override the existing styling:

Note: A widget must specify class names as themable so they be overridden.

When you, an end-user, would like to consume a widget and override its themable classes, you might create a new CSS file styles/themes/dark/button.m.css:

.selector1 {
  color: red;
}

.selector2 {
  color: blue;
}

The main problem is this: How does an end user know: a) which selectors they can style. b) What part of the widget is affected by such a selector.

2. Potential solution: Autosuggest

As a user, if I were writing a theme CSS file for a widget, it'd be great to get autosuggest values for the available selectors. Some editors do this based on the HTML which is detected.

How: I can only think of users having to install a custom code editor plugin which isn't ideal. So this is probably not feasible.

3. Potential solution: Scaffolding

Just like how there are tools and plugins to convert HTML to CSS, what if we could generate a styles/themes/dark/button.m.css file automatically, with the selectors already present, and rules ready to be filled in?

How:

To think about:

4. Potential solution: Terminal logging

What if the Dojo CLI logged a message to the terminal to alert the user when they have used a class which is not themeable.

To think about:

5. Potential solution: DevTools console logging

What if the browser console logged the available themable classes.

To think about:

6. Potential solution: Education

Educate and encourage widget authors to add all themable classes to their readme documentation.

To think about:

7. Potential solution: DevTools extension

Inspect and see original class names through a DevTools extension.

To think about:

8. Potential solution: Removing the unique classname transformation

In a traditional app, if I were using a third party component, I might inspect it with DevTools, see what classes are used, write out the class in my custom.css file and override things. Dojo 2 users can't do that because the classes have been "scoped" and can change. What if Dojo 2 was rearchitected so original class names were preserved? This would help with the problem being discussed in this comment, but also have improved developer ergonomics in view-source, inspect-element & testing workflows. To achieve the goal of scoping CSS, that could be explored separately (for example something like the scoped attribute - however this was removed from the spec).

To clarify: if we achieve this, the user would then have to 'inspect element' and use the class in their theme, however this doesn't necessarily identify which classes are available for theming and which are not.

To think about:

A side issue

When exploring themes, I tried to understand how I could extend an existing theme from node_modules.

The problem is this: If you try to use composes with compiled/built CSS code:

composes: root from '../../../../node_modules/@dojo/widgets/themes/dojo/button.m.css';

The classes in that file have been 'scoped' and cannot be imported as the user would expect.

9. Potential solution: Publish raw CSS

Publish the raw CSS files (e.g. to the NPM repository) so they can be 'composed' from directly,

To think about:

10. Potential solution: Extend the composes method

Noticed that the raw CSS module turns into a few files, one of which is: node_modules/@dojo/widgets/themes/dojo/button.m.css.js which has a piece of JSON inside it like this:

{"root":"_1lZxc2Ul","addon":"TAlDrfED","pressed":"_37ji2mWW","popup":"_29G5UqBS","disabled":"GlYj4g4z"," _key":"dojo-button"}

So I wonder if the composes function (not sure who or what implements it) can somehow be enhanced so if it detects a .js extension:

.selector {
  composes: root from '../../../../node_modules/@dojo/widgets/themes/dojo/button.m.js' /* <-- Notice the .js extension */
}

It automatically reads the JSON from that file and figures out which style rule you meant.

11. Potential solution: Extend the composes method with source maps

When you write composes: root from '../../../../node_modules/@dojo/widgets/themes/dojo/button.m.css';

The composes function could check if there is a sourcemap, if there is, it extracts the relevant (e.g. root) selector from the original file since the source map should have this information.

Another side issue:

Would be nice to enhance the composes function so it provides logging if it can not find the class the user is trying to import.

Update - Generating theme files

It's probably worth improving the experience of creating theme files. For example:

import * as Header from './Header.m.css';

export default {
    'Header': Header
}

If you change 'Header' -> into 'header' there are no errors and it can take a while to realize what the problem is.

umaar commented 6 years ago

@agubler @matt-gadd @kitsonk let me know if you have any thoughts/clarifications 👍

tomdye commented 6 years ago

Having spent some time looking into this, I think that the problem of scaffolding out a new theme for existing widgets can be achieved by making a few changes to our theming approach:

The above changes create a structure which allows for themeable css to be easily located and for it's location to be consistent between both distributable components and a users application.

I have created a command line POC that locates and scaffolds a theme for a user given the packagenames they with to theme and the widgets within those packages. This uses the generate .m.css.d.ts files.

Links:

POC Video: choice 1

umaar commented 6 years ago

This comment is concerning project coordination to enable the theme generation command. This comment is mainly for my benefit. As there are a few 'moving pieces', I really want to make sure my understanding on this is solid, hence the long explanation! There's nothing critical people need to read.

This comment is full of assumptions on my part so I hope people can correct any mistakes you notice! This is my understanding of what we need to do to accomplish this goal:

To run: dojo create app -n my-app and then dojo create theme and successfully create a theme file and CSS files.

When the user runs: dojo create app, the repo dojo/cli-create-app is used to scaffold out a new app. The package.json of that repo, comes from here: src/templates/package.json so we need to consider two things here:

  1. Is the reference to "@dojo/widgets": "~0.3.0" up to date? Will it pull in the latest version of dojo/widgets?
  2. When you run dojo create something in your brand new Dojo 2 app, it checks for a repo in node_modules named cli-create-something. We have created a https://github.com/dojo/cli-create-theme (PR still needs merging) so we need to add that repo to the devDependencies of the templated package.json within cli-create-app. (question: can we merge it?)

The above two points, when executed, should mean: when you run dojo create app -n my-app, you now get a new command dojo create theme.

Moving onto the next point: the widgets repo has changed, and as a result, its 'output' (e.g. the artifact) must also change. This will not happen by default. To clarify what the change is: The artifact is a dojo-widgets-0.3.1-rc.1.tgz file. Unzipping that presents a file like dojo-widgets/dist/package/theme/button/button.m.css.js which contains a snippet of code like this: " _key":"dojo-button". Our goal was to change that so it turns into: " _key":"@dojo/widgets/button"

To achieve this: We must ensure dojo/widgets pulls in the latest grunt-dojo2 which (I think) it already does as "grunt-dojo2": "latest" is present in the package.json file of the dojo/widgets repo. When it pulls in the latest grunt-dojo2 code (warning: PR still needs to be merged), it will receive new functionality which means means building the widgets repo will in turn create dojo-widgets/dist/package/theme/button/button.m.css.js files which has this: " _key":"@dojo/widgets/button"

Finally, when we run dojo create theme, thanks to the points previously mentioned, it should work!

umaar commented 6 years ago

Also can we merge this one? https://github.com/dojo/cli-create-theme/pull/1

umaar commented 6 years ago

We have discussed part of https://github.com/dojo/cli/issues/168#issuecomment-354773648 and agreed that when scaffolding out a new app, we will not bundle this new create theme command with it.

Would still appreciate a review on https://github.com/dojo/cli-create-theme/pull/1 !

umaar commented 6 years ago

Can we start 'releasing' projects? More so that I and others can test the feature out end-to-end and we could do some QA on it! Do we have any resources that explain the whole process? Like when do we release and how does it work, and who does it?

agubler commented 6 years ago

I think we can consider this epic as closed now that we have published the initial release of @dojo/cli-create-theme - All enhancements are now tracked as issues on the cli-create-theme repo.