I'm looking to find best practices for providing developers the ability to style elements that exist within my React shared component.
For instance, I have a drop down and I wanted the developers to be able to select a predefined theme that would enable then to select a highlight color, font size, font family for the list element that exists within my drop down component. I created enums for the each of the default themes and provided a way to allow devs to define the theme object and add css to the properties that sat behind that enum. I then injected the style into the functional component.
However, I quickly realized that if I didn't provide a way for the developer to lets say adjust a facet of an element outside of the scope of the theme interface such as the font weight, the developer would not be able to style it and i'd have to go in and add it in and test that it works with all the other style combinations which became tedious and a lot of overhead.
I was wondering if there is an implementation whereby I provide refs to the elements in the component and provide and open-ended CSSProperties style prop that would allow the dev to style to their hearts content? Is there a best practice to do this? Please provide a short example if possible?
One caveat is that frameworks such as Next JS will encode the css modules and make it difficult to allow the user to provide css that'll manipulate the component due to the css element encoding or appended id's. This is why I thought the refs approach might work.
The best solution for you would be using :part . This allows styling through the shadow dom boundary of the parts of your component that you want.
See:
mozilla documentation
an explanation by the person who proposed this: explainer
and some other documentation
Related
I've been loving checking out styled-components, but getting a bit stuck with the concept of extracting everything out into a component, and how to tweak styles for a particular use case. For example:
<Flex>
<MyStyledTitle>Hello I am a Title</MyStyledTitle>
<MyStyledBodyText>blah</MyStyledBodyText>
</Flex>
Let's say that I wanted to make the following customisations for this use case:
styled title grey (subdued text colour),
the body text to have a right margin of 100px (don't ask why).
The styled-components way, the first part could be done like:
<MyStyledTitle colorTint='subdued' />
or even
<MyStyledTitle>
<SubduedText>MyTitle</SubduedText>
</MyStyledTitle>
Perhaps using a prop for title that lets you configure it to use subdued text or ANOTHER hild component that defines the grey text..
But what about for the second option...
<MyStyledBodyText style={{paddingRight: 100}} />
Inline style? Use a Grid or layout component around it?
At which point does something become a specific styled-component and if not, then how does one customise smaller style changes?
While i really like this idea of removing the mapping between component + class name, I guess i'm feeling a bit torn between the classical idea of having a 'style sheet' file that can contain all the classes and modifier css, then using a presenter to choose between the combinations of css classes.
I might be missing something here, but just keen to see some bigger examples of styled components in practice. Any links / tips would be greatly appreciated!
We've been using styled-components in our project extensively. Few basic patterns/conventions we use are
Components created using StyledComponents are not used across React Components. Under extreme scenarios, we pull them into external files and export.
DIV is the most extensively used styled-component (styled.div). (Ofcourse we do use other html elements like button, table td etc., but styled explicitly).
Different styles for the same HTML element (or) React Component are declared explicitly as different styles. (If you refer to FAQ section of the styled-components docs, you might notice these - https://github.com/styled-components/styled-components/blob/master/docs/faq.md)
Overall to answer your question, we have moved away from the classical stylesheet and as well thinking about combining multiple styles. It has worked well, except that looking up on unit tests is a bit painful.
Thanks
I would like to offer my users the ability to customize the look and feel of the website.
I am giving them a color picker to choose a color scheme. I would like to dynamically generate few matching colors and apply them.
My questions are:
1.) How can i generate a color scheme based on the choosen color ? (some matching colors and contrasting colors for the background)
2.) What are the best practices for achieving a themable interface ?
I am writing an AngularJS SPA app with pure HTML with REST API as backend.
Right now for my 2nd question, I am retrieving the color setting and applying them for body.
<body style="background:color:{{bgcolor}}; color:{{fgcolor}}">
I am looking for something more elegant.
You can do this with ngStyle as you have above... but as you noted, it's not very elegant.
The simple truth is that nothing in AngularJS itself is really designed to address this problem other than the ngStyle directive itself. However, while I haven't exactly seen a "best practice" for this, you might take some ideas from Drupal's "Color" module, which is one of its base/core modules. You can do the same thing in Angular very easily.
What this does is go back to stylesheets, which I'm assuming you skipped over because it didn't seem like an obvious solution for something dynamic. But they have a clever answer. In a piece of code, after the user picks a color, they write out a stylesheet with a unique ID for its filename. They put these in a directory where other user-uploaded assets are kept, so they don't mix with core site code (minimize the potential attack vector). Then they only need a simple rule in the page to include the stylesheet itself.
You can easily emulate all of this with Angular, although you'll need your server's help, of course. But the nice thing about it is it's much easier for you to maintain. Instead of having to "sprinkle" ngStyle directives all over the place (one on everything you want styled) and potentially having conflicts with other things you want to do on some of those elements, the stylesheet can work exactly the way it's supposed to: using classes to target specific elements. You can make a template stylesheet that's easy to maintain, so that's a natural fit... and the best part is, it's easy to hook everything up.
My script should select some items and apply Effect->3D->Extrude&bevel to them.
Which objects and methods should be used?
I use JavaScript in AI CS6.
Thanks.
--
Update: I need to set the values for effect parameters (angles, depth etc.) in script.
--
Update 2: Probably it's possible to patch an AI file with needed values for the GraphicStyle, and then open it and apply the style where needed. But I'd like to know if there is less dirty solution.
Using documents[0].selection[0].reflect.properties in ExtendScript toolkit to find out what properties basic paths have, I don’t see any way to set this effect directly.
When I search the JavaScript Reference for Illustrator, the only mention I see of appearance is when it talks about graphic styles.
So what I tried was drawing two rectangles, applying the 3D effect to one of them, and saving it as a new graphic style:
Then in the script, you can select the other rectangle and then apply the graphic style with
documents[0].graphicStyles[6].applyTo(documents[0].selection[0])
Unfortunately, the documentation does say
Scripts cannot create new graphic styles.
One thing that might be work would be to distribute a document with the script that has all the graphic styles you might want to apply, and then apply them to objects in the target document…
I understand that content, presentation, and behavior are supposed to be separated by using HTML, CSS, and JS to implement them independently. Is there a best practice for binding these elements concretely while maintaining loose coupling in a dynamic web app? Is it even possible? Optimally without depending on jQuery?
To clarify what I'm talking about: HTML has no mechanism for the definition of new tags, so when your JavaScript model needs to generate content, the tags and structure for its presentation are necessarily defined in JS or somehow made accessible to it, tightly coupling behavior to content.
Before someone calls over-OOP, the reason I want to keep tags and CSS classes out of JS is that I don't even want to commit to HTML as a front end. There are at least five different representations of my underlying model that I'll eventually want, and tightly coupling the model to HTML rules out at least two of them.
Is there some way to late bind the model to the target representation without sacrificing dynamics or loose coupling? Like an XML document corresponding model elements to template HTML snippets?
UPDATE
Though it seems backward to provide concrete details of a question about factoring and OO best practice, I want to provide a much fresher example of the entanglement of form & function inherent to HTML. The entanglement of content & behavior between HTML and JS is the problem, though, not the example, and I want an answer that doesn't break when I change the details. It's from a very different project than the one I was working when I first asked this question, but the gist is the same:
I have some HTML for a UI widget. It is a view that represents a model object - a selection of palettes - to the user. Palettes themselves are part of the app's task, so they're not view, they're model.
I want to use this widget in at least 2 different dialogs (and any I might want in the future). In one, I need a changed selection to cause immediate action, the recoloring of a set of images in canvas elements that are part of the same dialog. In another, I just need to have two different sets to select from - one selection in each set.
I do not want to copy and paste this widget's HTML form or JS behavior because I want maintenance and revision to propagate from one base thing to all of its instances. Thus, only one instance of the widget, whatever its form may be, may exist in my source.
I do not want to have my JS rendering HTML tags directly because doing so will forfeit my IDE's error checking and content assistance on the HTML. Further, if there are problems with the HTML output, their source in my JS will be less clear because the process of generating the HTML doesn't look like HTML or necessarily reflect its structure. Finally, I want to test the effects of changes to the widget's CSS and HTML independently of my JS.
I do not want to involve additional dependencies e.g. separate templating & parameterization languages in my source because changes to various standards or evolving needs may break their compatibility, or they may themselves become unmaintained, in the future, leaving me with a massive quantity of useless source. Depending on jQuery is okay because it does more for normalizing between browsers (not to mention for convenience) than it is likely to ever break given its ubiquity, but other libraries will be regarded with extreme suspicion.
I want to specify the details of altering and retrieving the widget's state (what colors compose the palettes, how the user chooses among them) in JS that references only the widget and its component parts, since it's going to be a part of multiple dialogs that use its information in different ways.
Simultaneously, other JS code (the dialog's behavior) needs to be able to observe and initialize the widget's state - but without including any specific references to the widget's internal structure, which may some day change to accommodate new features, fix bugs, etc.
For simply making multiple copies of the widget's HTML, I can settle on calling jquery.clone on a template node that exists in an HTML file, and inserting the contents where I need them, from the function that sets up the dialog. HTML makes things difficult when any of the cloned elements have id or name attributes, but careful handling during cloning can make unique identifiers, point their corresponding label elements and href attributes at the new identifiers, and keep the old ones accessible in data attributes. So all is well and good for structure & content, and obviously the CSS presentation propagates to the clone just fine.
The rub comes when I try to implement the widget's interface with its dialog's controller. What is the most future-proof way to expose the widget's state's abstraction? I.e. I don't want to use widgetJquery.find('input:checked').val() to get the selected color from code that doesn't absolutely have to commit to a selection being based on a checked input element whose value attribute is a set of serialized colors.
I hope that makes it more clear what I'm looking for without muddling the question with details.
You can always have different XSLTs parse an XML.
But, it seems you try to abstract tooo much.
use the MVC, use different views to parse.
The methodology you write about is common in old systems, I worked with more than 10 years ago, there is probably a good reason evolution killed it.
Loose coupling is best achieved archtecturally using design patterns. A great example of how to achieve loose coupling is found in the Mediator Pattern. However, there are several patterns to use.
I suggest reading Addy Osmani's 'Essential JavaScript design Patterns' for comprehensive coverage of a range of patterns.
Enjoy!
I have created a Javascript based element that can be embedded into websites. The Javascript itself adds the HTML code into a pre-defined HTML container and dynamically loads the necessary CSS file that contain the element's visual definitions.
The problem starts when the site itself has its own definitions for general items. For example: The site's CSS defines a certain list style which is applied on the element's list because the element's CSS doesn't define an explicit list style or if the site's CSS overrides the element's CSS definition.
For the time being, I was able to solve this specific issue by explicitly defining the list's style and adding the !important definition. However, I would definitely want to go for a more robust solution that will assure that:
1. CSS definitions from the site's CSS that are not explicitly defined in the element's CSS will not be applied on the element
2. I will not need to explicitly add the !important definition to every one of my CSS definitions
Is there a general way in which I can specify that a site's CSS will not be applied on a certain element or that only a certain CSS will be applied to a specific element?
Any help will be greatly appreciated.
You need to use a localised reset.
Grab an existing CSS reset, such as Eric Meyer's Reset Reloaded and namespace all the selectors with your parent element, e.g. #something a { ... }.
I was going to put up the same answer as Alex, but he beat me - but I was also going to add:
If you're not going to use #alex's suggestion then ultimately you have to explicitly style all of your elements the way that you want them to appear; using selectors that keep your styles local too (and don't interfere with the parent site) - in the same way that the localised reset is suggested.
Update
Or you could do what Google Translate and many other widget-type things do, usually a no-no but in dynamic scenarios I think perfectly acceptable; since the visual style of your elements is not just important to you but to the container site: use inline styles.
Final update
So I thought I'd just double check what Google Translate does. And of course it's an iFrame inject in addition to using inline styles. They no doubt use inline styles to maximise compatibility and so that the browser doesn't have to make another request to get the stylesheet; and they would be using an iFrame so they can ensure a consistent look and feel.
Consider both of those points in tandem - and weigh that up against the amount of work that might be required in resettting all the styles for a minority portion of the page; or defining rules for every CSS property you need to control - which, let's face it, is basically all visual CSS properties.
The iFrame solution actually seems to offer the best solution - if you can use it; hence I've +1'd the first comment by #roberkules on your question.