Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/tailwind support #1466

Merged
merged 11 commits into from
Jul 7, 2021
Merged

Feature/tailwind support #1466

merged 11 commits into from
Jul 7, 2021

Conversation

seanparsons
Copy link
Contributor

Fixes #1458

Problem:
Users would like to be able to use Tailwind in projects, which currently they cannot do because Tailwind can often involve a command line process being run against a project.

Fix:
Primarily we use Twind to incorporate the configured style parts into the canvas, as unlike Tailwind itself it can be run in the browser. Once appropriate Tailwind and Postcss configuration is detected then it becomes automatically incorporated into the canvas and preview.

Commit Details:

  • useTwind hook implemented to either remove or add in the processed style element containing the configured Tailwind content. Uses the regular Tailwind configuration file format and filename.
  • Updated TypeScript to 4.1.3.
  • Added in support for module.exports in project files, similar to what is done for dependencies by including the same variables into the scope. Also extracts the contents of module.exports when producing the output of a module.
  • Trigger Twind when tailwind is configured in a postcss config.
  • Ensure that the required dependencies for tailwind are included in the dependencies of the project.
  • Support disabling the preflight of Tailwind.
  • Invokes injectTwind for the preview.
  • Better handle the selectors produced by Twind to ensure that they are encapsulated inside the canvas, having html and body target the root of the canvas.
  • Move all: initial from the canvas container to an enclosing div.
  • Memoized rule modifications to keep things smooth in the canvas.

@github-actions
Copy link
Contributor

github-actions bot commented Jul 6, 2021

Link to test editor
Scroll Canvas: 42.6ms (31.7-72.9ms) | Resize: 90.1ms (16.7-453.1ms) | Selection: 320ms (257.2-689.2ms) | Calc Pi: 40ms (37-60ms) | Empty Dispatch: 54ms (46.4-153.6ms) | (Chart)

Comment on lines +439 to +443
<div
style={{
all: 'initial',
}}
>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change was deliberate, and is the cause of the snapshot changes. Tailwind provides a "preflight" which adds CSS rules for the root of the doc. We obviously don't want that to affect the editor, so we scope all of the rules so that they are applied to descendants of the canvas-container only. That means we have to update those root rules to apply directly to the canvas-container element, which this all: 'initial' was interfering with. By moving the all: 'initial' up a level, we are still able to reset the styling on the canvas in a way that doesn't interfere with the tailwind preflight.

@@ -183,7 +183,8 @@
"string-hash": "1.1.3",
"strip-ansi": "6.0.0",
"tippy.js": "6.2.6",
"typescript": "4.0.5",
"twind": "0.16.16",
"typescript": "4.1.3",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Twind required a slightly updated version of TS, which is the cause of some unrelated changes elsewhere. There is a much newer version, but we didn't want to introduce too much noise into this PR, so that is something we should tackle separately.

Comment on lines +87 to +104
let module = {
exports: {},
}

// Mirrors the same thing in evaluateJs.
let process = {
env: {
NODE_ENV: 'production',
},
}

let executionScope: MapLike<any> = {
require: userRequireFn,
module: module,
exports: module.exports,
process: process,
...requireResult,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the comment, this is to mirror the behaviour we use when evaluating npm dependencies in evaluator.ts, as without this we weren't able to use the sample config from tailwind's docs

@@ -333,11 +333,13 @@ describe('transpileCode', () => {

var icon_css_1 = __importDefault(require(\\"./icon.css\\"));

exports.App = function (props) {
var App = function App(props) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fallout from the TS update

Comment on lines +334 to +338
const fromDependencies = Utils.path<unknown>(['dependencies', dependencyToCheck], parsedJSON)
const fromDevDependencies = Utils.path<unknown>(
['devDependencies', dependencyToCheck],
parsedJSON,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created the follow up ticket #1468 for this, because we need further support for devDependencies

) {
return prefixSelector
} else if (lowerCaseSelector === 'body') {
return `${prefixSelector} > *`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required because of the subtle difference between using the html vs the body selector. Tailwind uses both in the preflight, in one case attaching a specific font-family rule to the html selector, and then attaching font-family: inherit to the body selector.

}, [prefixSelector, shouldUseTwind, tailwindConfig])
}

export function injectTwind(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a non-hooks version of the above for use in the preview because the preview render function (which needs to call this) isn't a React component. It's a bit rubbish having to effectively duplicate the logic like this :/

@@ -281,7 +281,7 @@ const config = {
contentBase: path.join(__dirname, 'resources'),
watchContentBase: true, // Watch the above folder for changes too
overlay: {
warnings: true,
warnings: false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because of the TS update. For some reason (a few hours were lost trying to figure this one out), TS 4.1+ results in the following warning, which we weren't able rectify:

WARNING in ./node_modules/typescript/lib/typescript.js
Module not found: Error: Can't resolve 'perf_hooks' in '/home/rheese/Workspace/Utopia/utopia/editor/node_modules/typescript/lib'
 @ ./node_modules/typescript/lib/typescript.js
 @ ./src/core/workers/ts/ts-worker.ts
 @ ./src/core/workers/ts/ts.worker.ts

This appears to be related to this change, and maybe needs further investigation if it can't be fixed by replacing the ts-loader with babel


return {
...tailwindConfig,
preflight: preflightEnabled,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the difference between preflight and non-preflight for the canvas?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just determining whether or not the preflight should be included. It doesn't mess up the styling of the canvas.

@Rheeseyb Rheeseyb merged commit 1e69b53 into master Jul 7, 2021
@Rheeseyb Rheeseyb deleted the feature/tailwind-support branch July 7, 2021 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Basic Tailwind support via Twind
4 participants