dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.19k stars 9.93k forks source link

Theming Blazor App #16270

Closed miroslavp closed 4 years ago

miroslavp commented 6 years ago

I know that we are at the very early development stage, however, I think this would be very cool to have in some of the future versions. What I would like to see is the ability to theme my Blazor app. Something that resembles the WebForms Themes would suffice.

You can see more about it here: https://msdn.microsoft.com/en-us/library/ykzx33wh.aspx

The theme will be responsible for adding the corresponding theme css links as well as setting components properties that are specified in the skin files (the "skin" term is borrowed from WebForms).

So if the Counter component has an "IncrementBy" property, we can specify different value in the skin file for each theme.

Theme1 skin file content: <Counter IncrementBy="1" />

Theme2 skin file content:

<Counter IncrementBy="10" />

This way we can customize the behavior of our components based on the selected theme.

Also, if we don't want it to apply to all Counter components we can specify SkinId like this

<Counter IncrementBy="1" SkinId="MainPage"/>

which means that the IncrementBy property will be initially set to 1, only for Counter components that has SkinId property value of "MainPage".

I hope my English makes sense :)

awulkan commented 6 years ago

I don't really understand. You can already customize your design any way you want with css. What benefits would this have?

miroslavp commented 6 years ago

@AWulkan As I said, it's not about the design, it's about functionality that you can control only through properties. Imagine that you have a component that can present data in multiple ways. The component vendor that you got the component from, provides you with an easy way to switch between different layouts without touching the css.

<SomeFancyControl Items=@bind(items) ViewAs="Grid" /> <SomeFancyControl Items=@bind(items) ViewAs="List" /> <SomeFancyControl Items=@bind(items) ViewAs="Carousel" /> or in case of a chart where data is visualized on a canvas and you can't control it with css <Chart Data=@bind(data) Type="Pie" /> <Chart Data=@bind(data) Type="Bar" />

Or if you have a data grid and you want to specify the number of items per page depending on the currently selected theme ... or you want to specify different culture (or date/time format) on each theme.

Or if you have a puzzle component and you want to configure it differently for each theme <Puzzle Rows="4" Columns="4" Image="/images/USA.png" /> <Puzzle Rows="16" Columns="16" Image="/images/UK.png" />

I can keep giving you other examples, but I think you get the idea.

keithwill commented 6 years ago

@miroslavp This would require logic inside of the components to implement each of the themes. The selected theme(s) would be an application selection.

What is it you are asking for to be added to the Blazor project?

miroslavp commented 6 years ago

@keithwill

This would require logic inside of the components to implement each of the themes.

This is not true. Please read how the themes and skins work in WebForms.

What is it you are asking for to be added to the Blazor project?

I want to be able to set initial property values to some of my components based on the selected theme.

awulkan commented 6 years ago

"I want to be able to set initial property values to some of my components based on the selected theme."

Can't you already do that when you initialize the component?

MihaMarkic commented 6 years ago
<SomeFancyControl Items=@bind(items) ViewAs="Grid" />
<SomeFancyControl Items=@bind(items) ViewAs="List" />

Can't you have a global variable 'SomeFancyControlViewAs' somewhere instead?

brunopbarrote commented 6 years ago

I thinks it's too old, and it was helpful on Webforms era. But nowadays so much easier do that on css directly.

miroslavp commented 6 years ago

@brunopbarrote Please explain to me 1.how you can control what's drawn on a canvas through css

  1. or how you can set a src of an img tag with css and make it work for all browsers (btw setting image as a background is not quite the same, so save that example for yourself).
  2. Also there are complex dom manipulations and animations that are only possible through JS (or through C#, when Mono team adds the libraries for that)
miroslavp commented 6 years ago

Now, on second thought, I think a more MVCish oriented approach would be better. Instead of just specifying simple property values (like in the WebForms skin files), we can override the whole page component views depending on the selected theme. We can borrow the idea from this feature in MVC where you can provide separate views for mobile devices. In our case we can provide different views for each theme.

Overriding Views, Layouts, and Partial Views

So in MVC you can have

MainPage.cshtml MainPage.Mobile.cshtml

whereas in Blazor we can make it more generic like MainPage.cshtml MainPage.Theme1.cshtml MainPage.Theme2.cshtml

What do you guys think?

EdCharbeneau commented 6 years ago

Just let css do it's job. The more frameworks interfere with how styles are implemented, the worse off we all are.

If it isn't broke...

miroslavp commented 6 years ago

@EdCharbeneau Did you even read my posts? CSS is not a magic wand. You can't do everything with CSS. And it's not only about styles, but also structure and behavior

conficient commented 6 years ago

@miroslavp I understand what you were talking about in the original post.

It would be something like the Skins we had back in WebForms. I used them, but they were rather clumsy and when you created complex GridView or DetailView objects it got very messy. Just consider the number of controls Microsoft had to create back then to make it work: https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols(v=vs.110).aspx

Blazor's focus is creating a web application framework that renders HTML and can be styled using CSS. I don't love CSS either, but it's what we have. Bootstrap et al make it tolerable.

The Blazor team are not going to divert from this down a son-of-webforms road. They are not going to implement XAML on the browser (check out https://github.com/praeclarum/Ooui if you want that).

If you're looking for a more structured UI then Blazor will allow you to create it yourself. You could create wrapper components that implement your styling rules - e.g. <StyledTextbox Value=...> - you could use whatever C# mechanism you like in Blazor to pass the style rules to the component then.

miroslavp commented 6 years ago

@conficient

It would be something like the Skins we had back in WebForms. I used them, but they were rather clumsy and when you created complex GridView or DetailView objects it got very messy. Just consider the number of controls Microsoft had to create back then to make it work: https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols(v=vs.110).aspx

Not sure how this is related to skins.

Blazor's focus is creating a web application framework that renders HTML and can be styled using CSS. I don't love CSS either, but it's what we have. Bootstrap et al make it tolerable.

Don't get me wrong. I LOVE css! I don't want CSS to be replaced, but rather complemented. There are things that you just can't make with CSS ... like executing complex logic for example.

The Blazor team are not going to divert from this down a son-of-webforms road. They are not going to implement XAML on the browser (check out https://github.com/praeclarum/Ooui if you want that).

TBH, I don't like WebForms. I just mentioned skins, because they were useful mechanism to set initial property values. And properties as you may know are not necessarily related to styling (look my examples above). Who said anything about XAML?!

How about my last suggestion about using "Overriding Views, Layouts, and Partial Views"? This is used in MVC, so it is not WebForms related. I noticed that you disliked that post, but didn't give any reason why.

EdCharbeneau commented 6 years ago

I'm confident that you can do everything in css or Scss. With proper HTML and style sheets you can build complex data grids, charts, and scheduler components that can be completely themed by changing a few Scss variables.

Furthermore Scss can do very complex logic.

"Skins" or themes that only work in Blazor just aren't necessary. Additionally they would add complexity for no good reason.

miroslavp commented 6 years ago

@EdCharbeneau

I'm confident that you can do everything in css or Scss. With proper HTML and style sheets you can build complex data grids, charts, and scheduler components that can be completely themed by changing a few Scss variables.

Yeah? How do you control what's drawn on a canvas through Scss variables? There are some components that use canvas internally.

"Skins" or themes that only work in Blazor just aren't necessary. Additionally they would add complexity for no good reason.

What about "Overriding Views", the way MVC does it for mobile pages? I've used that in numerous projects and it works great. You can completely change the markup for mobile pages, You can use the same data model and business logic, but the markup can be completely different. That's even better than skins and is much cleaner. You just create another view with the same file name and add .Mobile.cshtml at the end. We can use the same technique for theming the components.

awulkan commented 6 years ago

@miroslavp

"Yeah? How do you control what's drawn on a canvas through Scss variables? There are some components that use canvas internally."

If you need to use canvas for something, then you'd just create a javascript interop for it I guess. I don't understand what canvas has to do with styling though.

"What about "Overriding Views", the way MVC does it for mobile pages? I've used that in numerous projects and it works great. You can completely change the markup for mobile pages, You can use the same data model and business logic, but the markup can be completely different. That's even better than skins and is much cleaner. You just create another view with the same file name and add .Mobile.cshtml at the end. We can use the same technique for theming the components."

Just learn to do responsive css design? It's generally not a good idea to serve totally different markup depending on what kind of device you think the user is using.

brunopbarrote commented 6 years ago

You just create another view with the same file name and add .Mobile.cshtml at the end. We can use the same technique for theming the components.

Usually if you made your html well structured, you don't need to change the markup.

Edit: @AWulkan answered same as me

miroslavp commented 6 years ago

@AWulkan

If you need to use canvas for something, then you'd just create a javascript interop for it I guess. I don't understand what canvas has to do with styling though.

I already gave you a simple example of a component that presents charts differently depending on a property value <Chart Data=@bind(data) Type="Pie" /> <Chart Data=@bind(data) Type="Bar" /> In the first case, it shows data as a Pie chart. The second one shows data as bars. Depending on provided value it executes different code that draws the chart on the canvas. It's not only charts. You can have other complex components that depend solely or partially on canvases.

Just learn to do responsive css design? It's generally not a good idea to serve totally different markup depending on what kind of device you think the user is using.

Can you cite the source of your claim? It is called "dynamic serving" and Google is perfectly fine with it. See here dynamic serving The .Mobile.cshtml thing was just an example to illustrate the "view overriding" feature. My point here is not to display components differently on every device!! My point is to display it differently depending on a selected theme.

In fact, Razor/Blazor is already doing that sort of things with constructs like

`@if (condition) {

} else { }` We are talking web APPLICATIONs here, not websites. The end result should be a useful app like Photoshop or Google Docs. The markup is not the primary focus in this case.
EdCharbeneau commented 6 years ago

We [Progress/Telerik] do this all the time with HTML/CSS/JS even when using canvas.

https://www.telerik.com/kendo-angular-ui/components/charts/sparkline/

Our charts don't rely on Angular needing some baked in Theme system. We just use the tools provided by the web.

miroslavp commented 6 years ago

@EdCharbeneau This is exactly the type of controls I'm talking about. Now, imagine you have 5 of those charts in your web app located on different pages. How would you change their type from, say, "pie" to "bar" at runtime if you wish to? Not imperatively, but with css!

Our charts don't rely on Angular needing some baked in Theme system.

Your charts don't need to rely on any Theme system! I don't think you get how theming works at all. It's the theme that updates the control state. The control itself is not aware of the existence of the theme.

P.S. I have friends working at Telerik here in Sofia, Bulgaria as senior devs and my office is just 2 intersections away from them. They can understand me what I'm saying, but obviously not you. Sigh

miroslavp commented 6 years ago

This dating site software, for example, uses WebForms themes and just by switching the theme, it changes the whole look and feel (each theme includes its own css as well as skins for changing property values of the server side controls)

dating site themes