openmastery / semantic-ui-theme

Theme editor and manager for the Semantic-UI framework
MIT License
15 stars 0 forks source link

The big idea #1

Open levithomason opened 7 years ago

levithomason commented 7 years ago

Let's layout the goals of this project and break down a roadmap to getting there. I'll update this description as we develop the requirements.


Initial Proposal

I would suggest replacing all CSS with a CSS-in-JS solution be deferred for a later time. Instead, I think we would be well served by a theme builder around customizing the LESS build of SUI. LESS provides an in-browser compiler that makes this very easy. We can run this in a web worker so as not to block the main ui thread.

Users would have photoshop-like controls (i.e. color pickers, range sliders, etc.) for tweaking the global variables, component variables, and adding LESS overrides. The LESS editor and all input fields would have typeahead support for variables to make things easier for the user. The user could then download the customized theme CSS and/or LESS.

The benefit here is that we can leverage the already existing SUI CSS teams to manage the CSS/LESS for us. Our system would only have to update the LESS package, parse it, and generate the controls for users.

Todo

Web-based theme editor web app

Right now, this list is based on the idea of editing a LESS theme. We're also experimenting with porting the LESS to CSS-in-JS, in which case some of this will not apply. I've marked items that do not apply to CSS-in-JS with 🚫 CSS-in-JS.

NPM theme editor package

p3nGu1nZz commented 7 years ago

here is a rough idea of what the editor might look like. mockup-example

p3nGu1nZz commented 7 years ago

that sounds pretty lit. Over the next couple days i will work on reviewing the SUI-LESS repo and apis. I think one of the first items we need to do is get some type of skeleton example apps for each of the support frameworks.

levithomason commented 7 years ago

At the end of the day, all frameworks have to render valid SUI HTML for the browser. We can snipe the HTML layouts from https://semantic-ui.com/usage/layout.html for the first step, especially the theming example. It showcases many elements and variations, which will be a good start for theming.

p3nGu1nZz commented 7 years ago

I just quick review of the SUI sources and this article and here is a quick overview of the stuff i think we need to create:

Components

Scope

Future

p3nGu1nZz commented 7 years ago

Use Case [1] - Create Theme in Editor

1) User clones semantic-ui-theme repo 2) Runs the project and views the Layout in the browser 3) User Clicks on a ui component in layout 4) ui component settings loaded into property panel 5) user modifies settings in the property panel 6) layout updates with the new property settings in real time 7) user saves the theme 8) theme is written to JSON file within the semantic-ui-theme project

Use Case [2] - Load Theme in Editor

1) User clones semantic-ui-theme repo 2) Runs the project and views the Layout in the browser 3) User clicks load theme in the property panel 4) The theme file is validate 5) the Layout is updated with the theme in the browser 6) user edits some ui component properties 7) user saves the updated theme 8) theme is written to JSON file within the semantic-ui-theme project

Use Case [3] - Apply Theme in Project

1) User adds semantic-ui-theme package dependency to project's package.json 2) Specifies theme configuration in package.json => loads theme file from asset directory 3) adds build:sui:theme' to scripts in package.json 4) runsyarn build:sui:theme 5) addssemantic-ui-theme/sematic-min.css` to index.js 6) user starts app

levithomason commented 7 years ago

I've updated the todos with the ideas proposed. There are some differences.

I really like the single JSON file idea! I opted to download it rather than write it to the filesystem. This way, we can stay serverless and run in the browser.

I opted to have a selector to switch between site variables and component variables, opposed to clicking on ui components to edit them. Users will want to click on components to test their click behavior. To hop into editing a component, we could include some kind of modifier + click functionality or a feature similar to Chrome Dev Tools "inspect element" selector button where you first click a selector button then select the component you want to edit. This can shake out in the details.

We will be exploring ways to auto parse the LESS into CSS-in-JS styles in this repo as well. If successful, we may end up shifting todos a bit. See the notes about that in the description. The single JSON file is even more awesome because that could end up being the CSS-in-JS theme config as well.

p3nGu1nZz commented 7 years ago

those are great changes, yes i didn't mean to download it. it should just write it to the file system in a theme dir or something in the project. the system should be smart enough to know to load a theme and include it in the rendering. I also did not mean having to run this as a separate server. Its just a mode you run your existing react app as.

i like the modifier inspector key thingy.. great idea.

sounds like the core of this is to get the LESS to JCSS working.. even if we have to manually edit the JSON file in dev tools for testing, that is okay.

my question is, would users be editing the LESS? or is this static. I can only imagine them editing the LESS if they modified the SUI components or added there own. If this is the case i would like to exclude that from our scope.

levithomason commented 7 years ago

my question is, would users be editing the LESS?

I think users use our theme editor only. That theme editor builds JS objects that define theme variables for use in the LESS framework. So, the user never directly sees nor interacts with the LESS.

We can use our JS variables for one of two things. First, short-term, we simply inject the values into the LESS build during compile (LESS has methods for this). Second, long-term, we can use the JS variables directly in a CSS-in-JS solution.

Pseudo Example

Have a look at the button.variables LESS file. It defines things like:

/* Button */
@verticalMargin: 0em;
@horizontalMargin: 0.25em;
@backgroundColor: #E0E1E2;
@backgroundImage: none;
@background: @backgroundColor @backgroundImage;
@lineHeight: 1em;

We would then port this to JavaScript:

// Button
const verticalMargin = '0em'
const horizontalMargin = '0.25em'
const backgroundColor = '#E0E1E2'
const backgroundImage = 'none'
const background = `${backgroundColor} ${backgroundImage}`
const lineHeight = '1em'

Now, we can put these values into the state of a React app. We can provide components to update them with controls that understand these type of values. When updated, we can recompile the LESS for the affected component(s) and re-render.

In the future, when Semantic UI React is updated to handle CSS-in-JS styles, we can use the values directly in the components themselves.

p3nGu1nZz commented 7 years ago

Okay that makes sense, good example.

What do you think about building a simple object graph of the possible types of components we can make use of some good inheritance.. IE button class extends a ui class object.

Each of the ui class objects would contain properties identified by an class as well. Such that some of the properties store a url string (like backgroundImage), where as other store a distance? (like lineHeight) This will allows us to be able to determine the type of property editor by just injecting the property into.

Each property would be of a class defining its type of values, and would be mapped to a collection of LESS properties using regex annotation. These classes can also have decorators and get/set which can be overloaded. This will allow us to easily hook in signaling to make these object properties observable. EX. when we change a value in one property of an object it will ripple the changes with events.. Also if the names in LESS change or new ones added, we just have to change the mapping function of each of the objects.

I think it will take us a bit of work to figure out and create all of the object class types we need, as well as how to define all of the property classes. Having a short term way of just recompiling and re-rendering is okay. Once that is solid, it would be easier for us to add some events in to dynamically update the values. If we know that the full re-render works correctly, then we can just compare the dynamic rendering to the full re-render and see if the layout visually changes. and inspect the css layout in devTools.

lastly we can make some unit tests for each of the components which can set the ground work for the dynamic updating and mapping functions.

levithomason commented 7 years ago

I think from here we do some R&D and prototype a few solutions.

I would suggest we create a minimal LESS theme in less-parser. Let's just include a single made up component with only a few properties and variables. This would not be an actual Semantic UI LESS file, but a very minimal test sample of our own. This way, it will be easy to grok and ready against.

Then, we can each write a solution for converting it to JS, updating the variables, and compiling it.

p3nGu1nZz commented 7 years ago

i think this would be a good first start. maybe start with something dumb stupid simple like a <p> or <h1>..<h6>

here is a link for reference on how to setup less in the project http://lesscss.org/#getting-started

and you can envoke the compiler from code here

var less = require('less');

less.render('.class { width: (1 + 1) }', function (e, output) {
  console.log(output.css);
});

and a link to the api here http://lesscss.org/usage/index.html

after reading the documents.. less.parser is deprecated and we should use `less.render' see: http://lesscss.org/usage/#programmatic-usage

create the LESS => CSS renderer is pretty straightforward. i purpose 1) create react app with create-react-app package 2) install LESS node in package.json 3) create example layout with a simple

..

as react component 4) create basic LESS file to be loaded by the layout from 3) 5) add LESS file and requires to layout from 3) 6) build and run app 7) make some changes to LESS and see layout update in browser .. hot code

we should also look at using it directly i the browser http://lesscss.org/usage/#using-less-in-the-browser

simply the javascript needed is:

p3nGu1nZz commented 7 years ago

good work on the todo! i got some work i need to finish up on a project then i will see about creating a skeleton app in react sometime later tonight or tomorow.

brianespinosa commented 7 years ago

I think users use our theme editor only. That theme editor builds JS objects that define theme variables for use in the LESS framework. So, the user never directly sees nor interacts with the LESS.

We can use our JS variables for one of two things. First, short-term, we simply inject the values into the LESS build during compile (LESS has methods for this). Second, long-term, we can use the JS variables directly in a CSS-in-JS solution.

I know it is not part of the LESS repository, but the Gulp build process in SUI core has a lot of other power for adding additional styles and overrides via .overrides and .variables files. I assume we would not want to replicate the .overrides functionality? I think there are ways we could approach those features in a future solution once we get all of this first work done and the initial CSS-in-JS. I know we are not doing those now, but I'd like us to think about those issues and how we will solve them as we begin to architect this. I'd hate for us to paint ourselves into a corner on any of this work in a way that would require us to refactor later.

brianespinosa commented 7 years ago

Regarding the theme editor web app, I am happy to start putting together the UI and sections for all of that. Do we have any preference on how that is done? I was considering just throwing together a create-react-app project for it and propping it up that way for now. That way we don't need to worry about managing too many of the core dependencies. We can always eject at some point in the future if needed.

p3nGu1nZz commented 7 years ago

@brianespinosa that is a great point of the semantic API. I agree with you on nore replicating that and should use those.

Yes, i was thinking the same with CRA. That stuff works outta the box. As for layout of the editor i was thinking a property panel that slides in and out of the right hand side. Maybe on the left side have a tree navigator that slides in and out. This would let you see all of the components that you could style. click on one shows the properties to edit in the right property panel. Future work could include being able to add these panels to any project and allow people to edit the theme directly on their app.

Also i would like to try to avoid any path that requires ejecting the application.

p3nGu1nZz commented 7 years ago

here is an example (ghetto) https://www.bootstrap-live-customizer.com/

brianespinosa commented 7 years ago

Yeah, not trying to reinvent the wheel with this. Your initial screenshot and the above link make sense. I think I should have something basic ready to poke at in the theme editor folder by Monday. 💪

I just found out I am moving at the end of the month, so I need to jump on this now before life gets crazy.

levithomason commented 7 years ago

Hey folks, just finished up a video call with @jlukic about this. We've agreed to take this theming project as an opportunity to create a single theme config that can compile down to any CSS implementation. We'd like to use YML for the theme config for its syntax simplicity.

We need to think of this YML config as the AST for all other implementations. YML is easily converted to JSON, so it isn't much different than we were already planning. What is different is that when designing the structure we'll need to think about how each part of the theme config will be converted to LESS/SASS/CSS/CSS-in-JS syntax.

There are no functions in YML. The LESS distribution uses minimal LESS functions. We'd like to use little to no functions moving forward. We will likely have to keep the lighten and darken functions. For required functions, we'll need to define the functions in YML. Probably an array of allowed functions or similar. Values in the YML can use only those defined functions. Finally, the parser we write will be able to map the respective YML function to each CSS implementation or compile the value and insert it into a vanilla CSS distribution.

The last design goal is to keep the YML as flat as possible. We'll begin with site.variables support only, so that should be fairly easy. Let's avoid nesting values.

This implementation will replace SUI core LESS/CSS. I think we're ready then to start prototyping something in YML that can compile down to both LESS/CSS and match the output of the current SUI distributions.

p3nGu1nZz commented 7 years ago

sorry been busy with my main project i have been working on.. I will dedicate some more time to this during the week coming up. i got a crazy deadline for the 20th this month im trying to make it.

YML is a good choice, makes no real difference to me.. it sounds like a smart choice. i trust you guys on making that call.

ass for functions we have a set of predefined allowed functions, stubbed or not, that we let the users be able to override. But I agree i dont want this cluttered with functions that gets mess and hacky.. Forcing users to have to override is a good way to box in the extent of functions.

i agree with the no nesting, flat is best for config stuff.

I have spent the last week experimenting with how LESS gets compiled and used within projects and specifically SUI.

At the end of the day we just need a *.min.css file that you can add into your project and reference it statically. We can defer the backwards transpiling of our YML to other version of SUI later.. for now lets just work off the edge..

question; do you know if there are any inconsistencies between site.variables in say vanilla SUI or react sui or angular sui? i would think we just have ot make it work with vanilla SUI and it should work for the other flavors. Correct assumption?

great work everyone so far. i think we have a good team and am excited to get this feature working.. next we can work on a view editor for the various sui components ;)

levithomason commented 7 years ago

question; do you know if there are any inconsistencies between site.variables in say vanilla SUI or react sui or angular sui?

The CSS and HTML markup is identical between all implementations. The various implementations only exist as different JS frameworks and libraries have different patterns for generating HTML. However, they all generate the same valid SUI HTML markup.

brianespinosa commented 7 years ago

Exciting news that we're going to be able to make this core for SUI. 🎉

It turns out... I did NOT get to finish the baseline UI yet for this. But I have a good start. I did most of the work on a plane heading back from Chicago. ;) I had to spend the weekend patching holes in plaster instead of in front of the computer. I think I should be able to get a decent baseline together by the end of the week though.

I forgot to share that I created separate project boards in the repo so we can manage work there. Feel free to create actionable items there for planning purposes.

p3nGu1nZz commented 7 years ago

^^ ive been snooping on that. Thanks for setting that stuff up. :)

yes that is exciting news.

i think i will start with writing the process that does the conversion of JSS (JavaScript Styles / YAML) into CSS. Any thoughts on skipping out the entire LESS/SASS/SCSS and having our compiler be able to build our JSS into CSS (static) or JS (dynamic) directly.

Im thinking that by allowing users to implement static CSS (great for CDN) or dynamically with JS module that renders CSS into a style tag on the page. I have done this in the past and it works surprisingly well. here is an example of some dynamic JS CSS

var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.cssClass { color: #F00; }';
document.getElementsByTagName('head')[0].appendChild(style);

document.getElementById('someElementId').className = 'cssClass';

mind you there are much better ways to do this, but you get the idea. There are alot of advantages of directly manipulting DOM styles in memory verses through a cached css. By utilizing convention over configuration, we should be able to line up style and rendering function name with semantic for super speedy rendering that just works.

Our theme editor should be able to set and get these style with programmatic API in our JS module that is imported into the view. This would implicitly update the styles for DOM. I think we want our users to be editing the YML file then using our theme module to load the YML dynamically as JS or statically with JS that either injects the styles into the head or loads a static min css for legacy.

I will be adding items into the project board this week.

p3nGu1nZz commented 7 years ago

i forgot to mention that keeping our data as flat (normalized) as possible will benefit us in faster loading times, and smaller file size with compression (browserify)

p3nGu1nZz commented 7 years ago

okay i did a bunch of project management work today and setup and configured our projects and task boards. i also made a bunch of issues for the #3 main issue (the compiler). I updated the names of the child project root directories, and rebased all of our branches with these changes into master.. Going forward i don't see any need for changes the master readme. Lets update the child project readme's then worry about combining this info in the develop branch.

I propose that we defer the CI setup until we have a pre-release for the MVP. Great work everyone

@brianespinosa good luck with your move, hope everything went smooth with that.

levithomason commented 7 years ago

Hey folks, looks like I may have come across a little bit of funding from a high profile client for this editor. I will catch up and what has been done here and make some more progress soon.

brianespinosa commented 7 years ago

Awesome @levithomason

And as an update on the UI progress, I've come to a full stop for the moment. Work on this got superseded by work patching holes in plaster and also fixing unforeseen plumbing problems. I should be able to double back onto this after the 1st once my move is complete.

p3nGu1nZz commented 7 years ago

@levithomason that is most excellant. understood about time commitments and such. we all are very busy people, plus i follow your work on the semantic-react project so i know that consumes you at times. we got this :)

@brianespinosa dont stress it. I know all to well what its like balancing moving and working on multiple projects and personal life. real development is a slow but persistent process that doesn't happen over night.

i put in a decent amount of time last week working on trying to get some clarity on the project and setting up the repository and a really ghetto master build process to test against semantic-ui releases. IE added a submodule to the project and some gulp tasks to generate a web app in the build directory of the semantic-ui example code. eventually when we make more progress on the child projects the master build task will execute the builds on the child projects and pull all of the distributables into the build to test against these semantic example sources for now. we can worry about setting up CI and npm/yarn packaging after we get the MVP proof of concepts working fully.

kara

hugomn commented 6 years ago

Hey guys! Is this project still being developed? I would like to help somehow.

levithomason commented 6 years ago

This repo never got the attention it needed. Semantic UI React has started a v2 effort in collaboration with Microsoft. You can see that here: https://github.com/levithomason/stardust.