#ButtonTypes
Explore tagged Tumblr posts
priyasinghi · 8 months ago
Text
Types of Coat Buttons
Understanding the different types of coat buttons is essential to making the best choice for your coat. Let's explore the most common types and their specific uses.
Functional Buttons
Functional button coat go beyond mere decoration; they serve a practical purpose. Here’s a closer look at these essential buttons:
Dress Buttons: Typically found on formal coats and jackets, dress buttons are designed to enhance the garment’s elegance and sophistication.
Military Buttons: Characterized by intricate designs, military buttons are ideal for coats with a classic or historical style, adding a distinctive touch.
Shank Buttons: These button coat are attached with a small stem, making them perfect for thicker fabrics or where additional space is required, ensuring both functionality and ease of use.
Decorative Buttons
Decorative buttons add flair and personality to your coat. While they may not always serve a functional purpose, they are excellent for enhancing the overall appearance of your coat:
Novelty Buttons: Available in various shapes and designs, novelty buttons range from quirky to elegant, allowing you to make a bold fashion statement.
Covered Buttons: Crafted from the same fabric as the coat, covered button coats offer a seamless and sophisticated look, blending effortlessly with the garment.
Gemstone Buttons: Embellished with gemstones or crystals, these button coats add a touch of luxury and sparkle, elevating the coat’s appearance to a new level of elegance.
Choosing the right button coat can significantly impact your coat's style and functionality, so understanding these options will help you make the best choice.
This guide will equip you with the knowledge to take your garment construction skills to the next level and create clothes that look and feel truly professional.
0 notes
all-hallows-street · 1 year ago
Text
All Saints Street Extra Comics Translations 1-3
Tumblr media Tumblr media
Apologies for the delay! We are finally publishing translations for the All Saints Street manhua.
We will be uploading them on this drive for now and later upload to mangadex. I will have to ask you to NOT SHARE this drive PUBLICALLY, feel free to share it privately.
Example of what to do: sending the drive link to friends on discord.
Example of what not to do: posting the drive link to twitter. We are going to start with some older extras that were never translated to get a good idea for a workflow and fix problems as they rise. After that we are going to prioritize translating chapters 486-500 (why? well, if you know you know) so we can also start working on simultaneous text translations for new chapter releases. What I mean by this is that as soon as a new chapter comes out, we can upload an english text translation alongside it, like the japanese translation team does now.
Tumblr media
Here is an example with the bonus comics:
I am also hoping this will be a good accessibility feature. Likewise, I am releasing to the public the table I translated from the japanese group. It is a rough Work-In-Progress table, but for me it has been an invaluable whenever I have to look up a certain chapter. I even made a search engine to look up chapters by character appearance.
Meanwhile we will be going back and re-lettering chapters that have been translated by independent efforts and uploading them to Mangadex. We have obtained permission from both @saints-street-translated and @wan-sheng-jie for this! After that the translation will continue in two fronts: the comic translations from 501 onwards and releasing text translations for new comics.
Translating the whole manhua will be a looooong process. Right now, we have text translations for all extra comics, but the lettering has been going slow. That's why we are still open to more volunteers to join us for the role of cleaner/typesetter! You don't need qualifications or even software (we will get it for you cough), just time and a disposition to learn.
TL;DR
ASS manhua translation is resuming.
Older Extra comics will be translated first.
We will translate 486-500 ASAP.
We will release text translations for newer comics.
We will remake the translations for 405-485 to upload to MangaDex.
 We need YOU to typeset the ASS comics into English!
226 notes · View notes
sphinxshreya · 1 month ago
Text
Boost Click-Through Rates with Effective Website Button Design!
A well-designed button improves UX, engagement, and conversions. From CTA to navigation, explore different UX button types and create seamless user interactions. Ready to optimize your website buttons for better results?
Read more : https://www.sphinx-solution.com/blog/types-of-ux-buttons/
WebsiteButtonDesign #UX #ButtonTypes #UIUX #WebDesign
0 notes
willgreys · 3 years ago
Text
Sedelco display master
Tumblr media
#SEDELCO DISPLAY MASTER HOW TO#
#SEDELCO DISPLAY MASTER FULL#
#SEDELCO DISPLAY MASTER FREE#
Clicking the Select button causes a postback. Note that the GridView lists the name and price for all of the products along with a Select LinkButton. Let's view our progress thus far through a browser. Take a moment to ensure that your GridView's DataKeyNames property is set to ProductID. However, for the selectable GridView in this tutorial, as well as for future tutorials in which we'll be examining inserting, updating, and deleting, the DataKeyNames property must be set properly. While this property has been set for us automatically in the preceding tutorials, the examples would have worked without the DataKeyNames property specified. The DataKeyNames property is automatically set to the uniquely-identifying data field(s) when you bind a data source to a GridView, DetailsView, or FormView through the Designer. The SelectedValue property returns the value of the first DataKeyNames data field for the selected row where as the SelectedDataKey property returns the selected row's DataKey object, which contains all of the values for the specified data key fields for that row. The DataKeyNames property is used to associate one or more data field values with each row and is commonly used to attribute uniquely identifying information from the underlying data with each GridView row. The SelectedIndex property returns the index of the selected row, whereas the SelectedValue and SelectedDataKey properties return values based upon the GridView's DataKeyNames property. In addition to the SelectedRow property, the GridView provides the SelectedIndex, SelectedValue, and SelectedDataKey properties. When a GridView row's Select button is clicked a postback ensues and the GridView's SelectedRow property is updated. By default, the Select buttons are rendered as LinkButtons, but you can use Buttons or ImageButtons instead through the CommandField's ButtonType property. This results in a Select button for each row of the GridView, as Figure 6 illustrates. To accomplish this, simply check the Enable Selection checkbox in the GridView's smart tag.įigure 6: Make the GridView's Rows Selectable ( Click to view full-size image)Ĭhecking the Enabling Selection option adds a CommandField to the ProductsGrid GridView with its ShowSelectButton property set to True. Next, we need to mark the GridView as selectable, which will add a Select button to each row. These steps can be accomplished graphically, by clicking the Edit Columns link from the GridView's smart tag, or by manually configuring the declarative syntax.įigure 5: Remove All But the ProductName and UnitPrice BoundFields ( Click to view full-size image)
#SEDELCO DISPLAY MASTER FREE#
Also, feel free to customize these BoundFields as needed, such as formatting the UnitPrice BoundField as a currency and changing the HeaderText properties of the BoundFields. Next, add a new ObjectDataSource named AllProductsDataSource that invokes the ProductsBLL class's GetProducts() method.įigure 2: Create an ObjectDataSource Named AllProductsDataSource ( Click to view full-size image)įigure 3: Use the ProductsBLL Class ( Click to view full-size image)įigure 4: Configure the ObjectDataSource to Invoke the GetProducts() Method ( Click to view full-size image)Įdit the GridView's fields removing all but the ProductName and UnitPrice BoundFields. Start by adding a GridView control to the DetailsBySelecting.aspx page in the Filtering folder, setting its ID property to ProductsGrid. The GridView control can be configured to include a Select button for each row that causes a postback and marks that row as the GridView's SelectedRow. For the single page master/details report, we will need a Button for each GridView row that, when clicked, shows the details. Such a hyperlink was added to each GridView row using a HyperLinkField. Recall that in the two-page master/detail report that each master record included a hyperlink that, when clicked, sent the user to the details page passing the clicked row's SupplierID value in the querystring.
#SEDELCO DISPLAY MASTER FULL#
Clicking the Select button for a particular product will cause its full details to be displayed in a DetailsView control on the same page.įigure 1: Clicking the Select Button Displays the Product's Details ( Click to view full-size image) Step 1: Creating a Selectable GridView This tutorial will have a GridView whose rows include the name and price of each product along with a Select button. This two page report format can be condensed into one page.
#SEDELCO DISPLAY MASTER HOW TO#
In the previous tutorial we saw how to create a master/detail report using two web pages: a "master" web page, from which we displayed the list of suppliers and a "details" web page that listed those products provided by the selected supplier. Clicking the Select button for a particular product will cause its full details to be displayed in a DetailsView control on the same page.
Tumblr media
0 notes
tonkijazz · 3 years ago
Text
Buttonbar style java
Tumblr media
#Buttonbar style java how to#
#Buttonbar style java skin#
Finally, the show() method is called to display the final results. Then a tile pane is created, on which addChildren() method is called to attach the button inside the scene. The function setTitle() is used to provide title to the stage.
#Buttonbar style java how to#
Specifically, the code shows you how to use JavaFX ButtonBar setStyle (String value) Example 1. The button will be created inside a scene, which in turn will be hosted inside a stage. The following code shows how to use ButtonBar from.
Program to create a button and add it to the stage: This program creates a Button indicated by the name b.
#Buttonbar style java skin#
Gets the value of the property cancelButton.Ī Cancel Button is the button that receives a keyboard VK_ESC pressĪ default Button is the button that receives a keyboard VK_ENTER pressĬreate a new instance of the default skin for this control.īelow programs illustrate the use of Button in JavaFX. Gets the value of the property defaultButton.
Sets the value of the property defaultButton ButtonBar.AlertDialog> f00You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above. These examples are extracted from open source projects. In other words, any Node may be annotated (via the setButtonData (Node, ButtonData) method, placed inside a ButtonBar (via the getButtons () list), and will then be positioned relative to all other nodes in the button list based on their annotations, as well as the overarching button order specified for. The following examples show how to use (). Sets the value of the property cancelButton. A ButtonBar is essentially a HBox, with the additional functionality for operating system specific button placement. <li>Button(String t, Node g): creates a button with the specified text and icon for its label. <li>Button(String t): creates a button with the specified text as its label. <li>Button(): creates a button with an empty string for its label. Buttons can also respond to mouse events by implementing an EventHandler to process the MouseEvent. In this program, we need to import another new package because we are dealing with event handling and this package provides classes and interfaces that are used for event handling in awt and Swing. This Action Event can be managed by an EventHandler. In the first step, we need to import all essential packages. This region also has a custom style applied to the button container Dec 12. When the button is pressed an Action Event is sent. demonstrates a button bar that can be used to navigate between widgets. <li>Cancel Button: A cancel button that receives a keyboard VK_ENTER press. It was primarily designed for the Java ME platform, as a low-end sibling for Opera Mobile. <li>Default Button: A default button that receives a keyboard VK_ENTER press at any loca-tion on the Internet in a plug-and-play fashion. In all other situations, the dialog will refuse to respond to all close requests, remaining open until the user clicks on one of the available buttons in the DialogPane area of the dialog. Button order code:L RIGHT public static final ButtonBar. <li>ISRO CS Syllabus for Scientist/Engineer Examīutton in JavaFX can be of three different types: The button has a ButtonType whose ButtonBar.ButtonData returns true when () is called. Methods declared in class getClass, notify, notifyAll, wait, wait, wait Enum Constant Detail LEFT public static final ButtonBar.ButtonDataLEFT Buttons with this style tag will statically end up on the left end of the bar. <li>ISRO CS Original Papers and Official Keys. <li>GATE CS Original Papers and Official Keys. Note that, like the HTML style attribute, this variable contains style properties and values and not the selector portion of a style rule. This is analogous to the 'style' attribute of an HTML element. The most convenient approach is probably a simple subclass of VBox: import . A string representation of the CSS style associated with this specific Node. Example The following code shows how to use ButtonBar from . This is useful if you want to lay out a button bar that includes a button with a long text. You need two things: to set fillWidth to true on the VBox, and to set maxWidth on each button. The method getStylesheets() returns the list of stylesheets to use with this Parent. <a href="https://tumbadental.com/?q=cT1CdXR0b25iYXIlMjBzdHlsZSUyMGphdmEmcD1Wb3ZhbiZzPVR1bWJsZVIgUFJPJnI9VHVtYmxyLmNvbSZjPUNBVDExJnNjPWJ1dHRvbiZkPTEwLjIwMjImdD10dW1iYWRlbnRhbC5jb20mbV9yPXRvbmtpamF6ei50dW1ibHIuY29tJms9VGV4dA==" target="_blank"><img style="cursor: pointer; display: block; margin-left: auto; margin-right: auto;" src="https://64.media.tumblr.com/825f76cc91ecb7f90539fb8b01a92acf/b190bc32b32ab97c-97/s540x810/794795c8b3de0768b9ed336716efabfabc08832e.jpg" alt="Buttonbar style java"/>
0 notes
Text
Webinar: 15 September 22 • 8pm • $15.00 non members • Register via www.NabsInc.com •
Webinar: 15 September 22 • 8pm • $15.00 non members • Register via www.NabsInc.com •
Sponsored byThe Education Committee ofThe National Association of Black Storytellers, IncPresenter: Anthony AudainDate: Thursday, September 15, 2022Time: 8:00 pm. – 9:30 pm. ESTParticipants Need: Paper, pen, pencil, eraser, or iPad tabletTo register Go to nabsinc.org / Go to Calendar / Find the search buttonType September 15th / press the search button / find Plant A seed See what grows-click the…
View On WordPress
1 note · View note
asscrabb · 3 years ago
Text
Хакеры объявили о взломе почты ВГТРК и опубликовали архив на 786 ГБ. Что Bellingcat нашла в предполагаемой утечке Статьи редакции
Наука 2 часа {"isShowSubscribedButtonLabels":true,"subsiteId":214346,"isShowNotificationsButton":false,"isSubscribed":false,"isNotificationsEnabled":false,"type":"full","buttonType":"inline","size":"tiny","mobileSize":"","subscribeButtonIcon":"v_follow","isShortOnMobile":false,"gtm":"Subsc https://tjournal.ru/analysis/584218-hakery-obyavili-o-vzlome-pochty-vgtrk-i-opublikovali-arhiv-na-786-gb-chto-bellingcat-nashla-v-predpolagaemoy-utechke
0 notes
holytheoristtastemaker · 5 years ago
Link
In this post, we’ll look at several different ways you can build reusable React components that leverage Tailwind under the hood while exposing a nice interface to other components. This will improve your code by moving from long lists of class names to semantic props that are easier to read and maintain. You will need to have worked with React in order to get a good understanding of this post. Tailwind is a very popular CSS framework that provides low-level utility classes to help developers build custom designs. It’s grown in popularity over the last few years because it solves two problems really well:
Tailwind makes it easy to make iterative changes to HTML without digging through stylesheets to find matching CSS selectors.
Tailwind has sane conventions and defaults. This makes it easy for people to get started without writing CSS from scratch.
Add the comprehensive documentation and it’s no surprise why Tailwind is so popular. These methods will help you transform code that looks like this:
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Enable </button>
To code that looks like this:
<Button size="sm" textColor="white" bgColor="blue-500"> Enable </Button>
The difference between both snippets is that in the first we made use of a standard HTML button tag, while the second used a <Button> component. The <Button> component had been built for reusability and is easier to read since it has better semantics. Instead of a long list of class names, it uses properties to set various attributes such as size, textColor, and bgColor. Let’s get started.
Method 1: Controlling Classes With The Classnames Module
A simple way to adapt Tailwind into a React application is to embrace the class names and toggle them programmatically. The classnames npm module makes it easy to toggle classes in React. To demonstrate how you may use this, let’s take a use case where you have <Button> components in your React application.
// This could be hard to read. <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Enable</button> // This is more conventional React. <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Let’s see how to separate Tailwind classes so people using this <Button> component can use React props such as size, textColor, and bgColor.
Pass props such as bgColor and textColor directly into the class name string template.
Use objects to programmatically switch class names (as we have done with the size prop)
In the example code below, we’ll take a look at both approaches.
// Button.jsx import classnames from 'classnames'; function Button ({size, bgColor, textColor, children}) { return ( <button className={classnames("bg-${bgColor} text-${textColor} font-bold py-2 px-4 rounded", { "text-xs": size === 'sm' "text-xl": size === 'lg', })}> {children} </button> ) }; export default Button;
In the code above, we define a Button component that takes the following props:
size Defines the size of the button and applies the Tailwind classes text-xs or text-xl
bgColor Defines the background color of the button and applies the Tailwind bg-* classes.
textColor Defines the text color of the button and applies the Tailwind text-* classes.
children Any subcomponents will be passed through here. It will usually contain the text within the <Button>.
By defining Button.jsx, we can now import it in and use React props instead of class names. This makes our code easier to read and reuse.
import Button from './Button'; <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Using Class Names For Interactive Components
A Button is a very simple use-case. What about something more complicated? Well, you can take this further to make interactive components. For example, let’s look at a dropdown that is made using Tailwind.
Your browser does not support the video tag.
An interactive dropdown built using Tailwind and class name toggling. For this example, we create the HTML component using Tailwind CSS classnames but we expose a React component that looks like this:
<Dropdown options={\["Edit", "Duplicate", "Archive", "Move", "Delete"\]} onOptionSelect={(option) => { console.log("Selected Option", option)} } />
Looking at the code above, you’ll notice that we don’t have any Tailwind classes. They are all hidden inside the implementation code of <Dropdown/>. The user of this Dropdown component just has to provide a list of options and a click handler, onOptionSelect when an option is clicked. Let’s see how this component can be built using Tailwind. Removing some of the unrelated code, here’s the crux of the logic. You can view this Codepen for a complete example.
import classNames from 'classnames'; function Dropdown({ options, onOptionSelect }) { // Keep track of whether the dropdown is open or not. const [isActive, setActive] = useState(false); const buttonClasses = `inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-blue-500 active:text-gray-200 transition ease-in-out duration-150`; return ( // Toggle the dropdown if the button is clicked <button onClick={() => setActive(!isActive)} className={buttonClasses}> Options </button> // Use the classnames module to toggle the Tailwind .block and .hidden classes <div class={classNames("origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg", { block: isActive, hidden: !isActive })}> // List items are rendered here. {options.map((option) => <div key={option} onClick={(e) => onOptionSelect(option)}>{option}</div>)} </div> ) } export default Dropdown;
The dropdown is made interactive by selectively showing or hiding it using the .hidden and .block classes. Whenever the <button> is pressed, we fire the onClick handler that toggles the isActive state. If the button is active (isActive === true), we set the block class. Otherwise, we set the hidden class. These are both Tailwind classes for toggling display behavior. In summary, the classnames module is a simple and effective way to programmatically control class names for Tailwind. It makes it easier to separate logic into React props, which makes your components easier to reuse. It works for simple and interactive components.
Method 2: Using Constants To Define A Design System
Another way of using Tailwind and React together is by using constants and mapping props to a specific constant. This is effective for building design systems. Let’s demonstrate with an example. Start with a theme.js file where you list out your design system.
// theme.js (you can call it whatever you want) export const ButtonType = { primary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", secondary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", basic: "bg-white hover:bg-gray-700 text-gray-700 font-bold rounded", delete: "bg-red-300 hover:bg-red-500 text-white font-bold rounded" }; export const ButtonSize = { sm: "py-2 px-4 text-xs", lg: "py-3 px-6 text-lg" }
In this case, we have two sets of constants:
ButtonType defines how buttons are styled in our app.
ButtonSizes defines the sizes of buttons in our app.
Now, let’s write our <Button> component:
import {ButtonType, ButtonSize} from './theme'; function Button({size, type, children}) { // This can be improved. I’m keeping it simple here by joining two strings. const classNames = ButtonType[type] + " " + ButtonSize[size]; return ( <button className={classNames}>{children}</button> ) } export default Button;
We use the ButtonType and ButtonSize constants to create a list of class names. This makes the interface of our <Button> much nicer. It lets us use size and type props instead of putting everything in a class name string.
// Cleaner and well defined props. <Button size="xs" type="primary">Enable</Button>
Versus the prior approach:
// Exposing class names <button className="py-2 px-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Enable</button>
If you need to redefine how buttons look in your application, just edit the theme.js file and all buttons in your app will automatically update. This can be easier than searching for class names in various components.
Method 3: Composing Utilities With @apply
A third way to improve the legibility of your React components is using CSS and the @apply pattern available in PostCSS to extract repeated classes. This pattern involves using stylesheets and post-processors. Let’s demonstrate how this works through an example. Suppose you have a Button group that has a Primary and a Secondary Button.
Tumblr media
A Button Group consisting of a primary and secondary button. (Large preview)
<button className="py-2 px-4 mr-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Update Now</button> <button className="py-2 px-4 text-xs mr-4 hover:bg-gray-100 text-gray-700 border-gray-300 border font-bold rounded">Later</button>
Using the @apply pattern, you can write this HTML as:
<button className="btn btn-primary btn-xs">Update Now</button> <button className="btn btn-secondary btn-xs">Later</button>
Which can then be adopted to React to become:
import classnames from "classnames"; function Button ({size, type, children}) { const bSize = "btn-" + size; const bType = "btn-" + type; return ( <button className={classnames("btn", bSize, bType)}>{children}</button> ) } Button.propTypes = { size: PropTypes.oneOf(['xs, xl']), type: PropTypes.oneOf(['primary', 'secondary']) }; // Using the Button component. <Button type="primary" size="xs">Update Now</Button> <Button type="secondary" size="xs">Later</Button>
Here’s how you would create these BEM-style classnames such as .btn, .btn-primary, and others. Start by creating a button.css file:
/\* button.css \*/ @tailwind base; @tailwind components; .btn { @apply py-2 px-4 mr-4 font-bold rounded; } .btn-primary { @apply bg-blue-500 hover:bg-blue-700 text-white; } .btn-secondary { @apply hover:bg-gray-700 text-gray-700 border-gray-300 border; } .btn-xs { @apply text-xs; } .btn-xl { @apply text-xl; } @tailwind utilities;
The code above isn’t real CSS but it will get compiled by PostCSS. There’s a GitHub repository available here which shows how to setup PostCSS and Tailwind for a JavaScript project. There’s also a short video that demonstrates how to set it up here.
Disadvantages Of Using @apply
The concept of extracting Tailwind utility classes into higher-level CSS classes seems like it makes sense, but it has some disadvantages which you should be aware of. Let’s highlight these with another example. First, by extracting these class names out, we lose some information. For example, we need to be aware that .btn-primary has to be added to a component that already has .btn applied to it. Also, .btn-primary and .btn-secondary can’t be applied together. This information is not evident by just looking at the classes. If this component was something more complicated, you would also need to understand the parent-child relationship between the classes. In a way, this is the problem that Tailwind was designed to solve, and by using @apply, we are bringing the problems back, in a different way. Here’s a video where Adam Wathan — the creator of Tailwind — dives into the pros and cons of using @apply.
Summary
In this article, we looked at three ways that you can integrate Tailwind into a React application to build reusable components. These methods help you to build React components that have a cleaner interface using props.
Use the classnames module to programmatically toggle classes.
Define a constants file where you define a list of classes per component state.
Use @apply to extract higher-level CSS classes.
0 notes
120stillwell · 5 years ago
Link
For just $82.00 Note: This is Chinese version.(Chinese version comes with a Chinese manual) .The watch display is just Chinese, the app can follow your mobile language.Specification: Brand: Xiaomi Amazfit Bluetooth Version: Bluetooth 4.0 Waterproof: Yes IP rating: IP68 Functions:Bluetooth calling: Phone call reminder Messaging: Message reminder Health tracker: Heart rate monitor,Sleep monitorOperating mode: Press buttonType of battery: Lithium-ion polymer battery Battery Capacity: 190mAhPeople: Female table,Male tableShape of the dial: Rectangle Case material: Polycarbonate Band material: SiliconeProduct size (L x W x H): 19.5*3.5*0.8cm  Package size (L x W x H): 5*5*5cm Product weight: 0.0320 kg Package weight: 0.2070 kg Main Features:Sleep monitoring:Carefully monitor your sleep qualityHeart rate monitor:Considerate monitor contact designed on the behind of the watch, take care of your health anytime and anywhereBluetooth 4.0:Connected with mobile phone App, stable, fast and super low consumption1.28 inch with 2.5D Corning Gorilla Glass screenBest suitable screen size with high definition picture displaying gives you great experience Package Contents: 1 x Smartwatch 1 x Charging Cable,,,,,,,,
0 notes
douglassmiith · 5 years ago
Text
Building Reusable React Components Using Tailwind
About The Author
Tilo Mitra studied Engineering at the University of Waterloo. He is an Engineering Manager and a Software Engineer. He’s been writing in JavaScript … More about Tilo …
Tailwind is a popular utility-first CSS framework that provides low-level class names to web developers. It does not have any JavaScript and works well with existing frameworks such as React, Vue, Angular, Ember, and others. Whilst this is positive, it can be confusing for new developers to understand how to integrate Tailwind in their applications. In this article, we’ll explore ways to build reusable React components using Tailwind.
In this post, we’ll look at several different ways you can build reusable React components that leverage Tailwind under the hood while exposing a nice interface to other components. This will improve your code by moving from long lists of class names to semantic props that are easier to read and maintain.
You will need to have worked with React in order to get a good understanding of this post.
Tailwind is a very popular CSS framework that provides low-level utility classes to help developers build custom designs. It’s grown in popularity over the last few years because it solves two problems really well:
Tailwind makes it easy to make iterative changes to HTML without digging through stylesheets to find matching CSS selectors.
Tailwind has sane conventions and defaults. This makes it easy for people to get started without writing CSS from scratch.
Add the comprehensive documentation and it’s no surprise why Tailwind is so popular.
These methods will help you transform code that looks like this:
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Enable</button>
To code that looks like this:
<Button size="sm" textColor="white" bgColor="blue-500"> Enable</Button>
The difference between both snippets is that in the first we made use of a standard HTML button tag, while the second used a <Button> component. The <Button> component had been built for reusability and is easier to read since it has better semantics. Instead of a long list of class names, it uses properties to set various attributes such as size, textColor, and bgColor.
Let’s get started.
Method 1: Controlling Classes With The Classnames Module
A simple way to adapt Tailwind into a React application is to embrace the class names and toggle them programmatically.
The classnames npm module makes it easy to toggle classes in React. To demonstrate how you may use this, let’s take a use case where you have <Button> components in your React application.
// This could be hard to read.<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Enable</button> // This is more conventional React.<Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Let’s see how to separate Tailwind classes so people using this <Button> component can use React props such as size, textColor, and bgColor.
Pass props such as bgColor and textColor directly into the class name string template.
Use objects to programmatically switch class names (as we have done with the size prop)
In the example code below, we’ll take a look at both approaches.
// Button.jsximport classnames from 'classnames'; function Button ({size, bgColor, textColor, children}) { return ( <button className={classnames("bg-${bgColor} text-${textColor} font-bold py-2 px-4 rounded", { "text-xs": size === 'sm' "text-xl": size === 'lg', })}> {children} </button> )}; export default Button;
In the code above, we define a Button component that takes the following props:
size Defines the size of the button and applies the Tailwind classes text-xs or text-xl
bgColor Defines the background color of the button and applies the Tailwind bg-* classes.
textColor Defines the text color of the button and applies the Tailwind text-* classes.
children Any subcomponents will be passed through here. It will usually contain the text within the <Button>.
By defining Button.jsx, we can now import it in and use React props instead of class names. This makes our code easier to read and reuse.
import Button from './Button';<Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Using Class Names For Interactive Components
A Button is a very simple use-case. What about something more complicated? Well, you can take this further to make interactive components.
For example, let’s look at a dropdown that is made using Tailwind.
Your browser does not support the video tag.
An interactive dropdown built using Tailwind and class name toggling.
For this example, we create the HTML component using Tailwind CSS classnames but we expose a React component that looks like this:
<Dropdown options={\["Edit", "Duplicate", "Archive", "Move", "Delete"\]} onOptionSelect={(option) => { console.log("Selected Option", option)} } />
Looking at the code above, you’ll notice that we don’t have any Tailwind classes. They are all hidden inside the implementation code of <Dropdown/>. The user of this Dropdown component just has to provide a list of options and a click handler, onOptionSelect when an option is clicked.
Let’s see how this component can be built using Tailwind.
Removing some of the unrelated code, here’s the crUX of the logic. You can view this Codepen for a complete example.
import classNames from 'classnames'; function Dropdown({ options, onOptionSelect }) { // Keep track of whether the dropdown is open or not. const [isActive, setActive] = useState(false); const buttonClasses = `inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-blue-500 active:text-gray-200 transition ease-in-out duration-150`; return ( // Toggle the dropdown if the button is clicked <button onClick={() => setActive(!isActive)} className={buttonClasses}> Options </button> // Use the classnames module to toggle the Tailwind .block and .hidden classes <div class={classNames("origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg", { block: isActive, hidden: !isActive })}> // List items are rendered here. {options.map((option) => <div key={option} onClick={(e) => onOptionSelect(option)}>{option}</div>)} </div> )} export default Dropdown;
The dropdown is made interactive by selectively showing or hiding it using the .hidden and .block classes. Whenever the <button> is pressed, we fire the onClick handler that toggles the isActive state. If the button is active (isActive === true), we set the block class. Otherwise, we set the hidden class. These are both Tailwind classes for toggling display behavior.
In summary, the classnames module is a simple and effective way to programmatically control class names for Tailwind. It makes it easier to separate logic into React props, which makes your components easier to reuse. It works for simple and interactive components.
Method 2: Using Constants To Define A Design System
Another way of using Tailwind and React together is by using constants and mapping props to a specific constant. This is effective for building design systems. Let’s demonstrate with an example.
Start with a theme.js file where you list out your design system.
// theme.js (you can call it whatever you want)export const ButtonType = { primary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", secondary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", basic: "bg-white hover:bg-gray-700 text-gray-700 font-bold rounded", delete: "bg-red-300 hover:bg-red-500 text-white font-bold rounded"}; export const ButtonSize = { sm: "py-2 px-4 text-xs", lg: "py-3 px-6 text-lg"}
In this case, we have two sets of constants:
ButtonType defines how buttons are styled in our app.
ButtonSizes defines the sizes of buttons in our app.
Now, let’s write our <Button> component:
import {ButtonType, ButtonSize} from './theme'; function Button({size, type, children}) { // This can be improved. I’m keeping it simple here by joining two strings. const classNames = ButtonType[type] + " " + ButtonSize[size]; return ( <button className={classNames}>{children}</button> )}export default Button;
We use the ButtonType and ButtonSize constants to create a list of class names. This makes the interface of our <Button> much nicer. It lets us use size and type props instead of putting everything in a class name string.
// Cleaner and well defined props.<Button size="xs" type="primary">Enable</Button>
Versus the prior approach:
// Exposing class names<button className="py-2 px-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Enable</button>
If you need to redefine how buttons look in your application, just edit the theme.js file and all buttons in your app will automatically update. This can be easier than searching for class names in various components.
Method 3: Composing Utilities With @apply
A third way to improve the legibility of your React components is using CSS and the @apply pattern available in PostCSS to extract repeated classes. This pattern involves using stylesheets and post-processors.
Let’s demonstrate how this works through an example. Suppose you have a Button group that has a Primary and a Secondary Button.
A Button Group consisting of a primary and secondary button. (Large preview)
<button className="py-2 px-4 mr-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Update Now</button> <button className="py-2 px-4 text-xs mr-4 hover:bg-gray-100 text-gray-700 border-gray-300 border font-bold rounded">Later</button>
Using the @apply pattern, you can write this HTML as:
<button className="btn btn-primary btn-xs">Update Now</button><button className="btn btn-secondary btn-xs">Later</button>
Which can then be adopted to React to become:
import classnames from "classnames"; function Button ({size, type, children}) { const bSize = "btn-" + size; const bType = "btn-" + type; return ( <button className={classnames("btn", bSize, bType)}>{children}</button> )} Button.propTypes = { size: PropTypes.oneOf(['xs, xl']), type: PropTypes.oneOf(['primary', 'secondary'])}; // Using the Button component.<Button type="primary" size="xs">Update Now</Button><Button type="secondary" size="xs">Later</Button>
Here’s how you would create these BEM-style classnames such as .btn, .btn-primary, and others. Start by creating a button.css file:
/\* button.css \*/ @tailwind base;@tailwind components; .btn { @apply py-2 px-4 mr-4 font-bold rounded;}.btn-primary { @apply bg-blue-500 hover:bg-blue-700 text-white;}.btn-secondary { @apply hover:bg-gray-700 text-gray-700 border-gray-300 border;}.btn-xs { @apply text-xs;}.btn-xl { @apply text-xl;} @tailwind utilities;
The code above isn’t real CSS but it will get compiled by PostCSS. There’s a GitHub repository available here which shows how to setup PostCSS and Tailwind for a JavaScript project.
There’s also a short video that demonstrates how to set it up here.
Disadvantages Of Using @apply
The concept of extracting Tailwind utility classes into higher-level CSS classes seems like it makes sense, but it has some disadvantages which you should be aware of. Let’s highlight these with another example.
First, by extracting these class names out, we lose some information. For example, we need to be aware that .btn-primary has to be added to a component that already has .btn applied to it. Also, .btn-primary and .btn-secondary can’t be applied together. This information is not evident by just looking at the classes.
If this component was something more complicated, you would also need to understand the parent-child relationship between the classes. In a way, this is the problem that Tailwind was designed to solve, and by using @apply, we are bringing the problems back, in a different way.
Here’s a video where Adam Wathan — the creator of Tailwind — dives into the pros and cons of using @apply.
Summary
In this article, we looked at three ways that you can integrate Tailwind into a React application to build reusable components. These methods help you to build React components that have a cleaner interface using props.
Use the classnames module to programmatically toggle classes.
Define a constants file where you define a list of classes per component state.
Use @apply to extract higher-level CSS classes.
If you have any questions, send me a message on Twitter at @tilomitra.
Recommended Reading on SmashingMag:
(ks, ra, il)
Website Design & SEO Delray Beach by DBL07.co
Delray Beach SEO
Via http://www.scpie.org/building-reusable-react-components-using-tailwind/
source https://scpie.weebly.com/blog/building-reusable-react-components-using-tailwind
0 notes
laurelkrugerr · 5 years ago
Text
Building Reusable React Components Using Tailwind
About The Author
Tilo Mitra studied Engineering at the University of Waterloo. He is an Engineering Manager and a Software Engineer. He’s been writing in JavaScript … More about Tilo …
Tailwind is a popular utility-first CSS framework that provides low-level class names to web developers. It does not have any JavaScript and works well with existing frameworks such as React, Vue, Angular, Ember, and others. Whilst this is positive, it can be confusing for new developers to understand how to integrate Tailwind in their applications. In this article, we’ll explore ways to build reusable React components using Tailwind.
In this post, we’ll look at several different ways you can build reusable React components that leverage Tailwind under the hood while exposing a nice interface to other components. This will improve your code by moving from long lists of class names to semantic props that are easier to read and maintain.
You will need to have worked with React in order to get a good understanding of this post.
Tailwind is a very popular CSS framework that provides low-level utility classes to help developers build custom designs. It’s grown in popularity over the last few years because it solves two problems really well:
Tailwind makes it easy to make iterative changes to HTML without digging through stylesheets to find matching CSS selectors.
Tailwind has sane conventions and defaults. This makes it easy for people to get started without writing CSS from scratch.
Add the comprehensive documentation and it’s no surprise why Tailwind is so popular.
These methods will help you transform code that looks like this:
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Enable </button>
To code that looks like this:
<Button size="sm" textColor="white" bgColor="blue-500"> Enable </Button>
The difference between both snippets is that in the first we made use of a standard HTML button tag, while the second used a <Button> component. The <Button> component had been built for reusability and is easier to read since it has better semantics. Instead of a long list of class names, it uses properties to set various attributes such as size, textColor, and bgColor.
Let’s get started.
Method 1: Controlling Classes With The Classnames Module
A simple way to adapt Tailwind into a React application is to embrace the class names and toggle them programmatically.
The classnames npm module makes it easy to toggle classes in React. To demonstrate how you may use this, let’s take a use case where you have <Button> components in your React application.
// This could be hard to read. <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Enable</button> // This is more conventional React. <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Let’s see how to separate Tailwind classes so people using this <Button> component can use React props such as size, textColor, and bgColor.
Pass props such as bgColor and textColor directly into the class name string template.
Use objects to programmatically switch class names (as we have done with the size prop)
In the example code below, we’ll take a look at both approaches.
// Button.jsx import classnames from 'classnames'; function Button ({size, bgColor, textColor, children}) { return ( <button className={classnames("bg-${bgColor} text-${textColor} font-bold py-2 px-4 rounded", { "text-xs": size === 'sm' "text-xl": size === 'lg', })}> {children} </button> ) }; export default Button;
In the code above, we define a Button component that takes the following props:
size Defines the size of the button and applies the Tailwind classes text-xs or text-xl
bgColor Defines the background color of the button and applies the Tailwind bg-* classes.
textColor Defines the text color of the button and applies the Tailwind text-* classes.
children Any subcomponents will be passed through here. It will usually contain the text within the <Button>.
By defining Button.jsx, we can now import it in and use React props instead of class names. This makes our code easier to read and reuse.
import Button from './Button'; <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Using Class Names For Interactive Components
A Button is a very simple use-case. What about something more complicated? Well, you can take this further to make interactive components.
For example, let’s look at a dropdown that is made using Tailwind.
Your browser does not support the video tag.
An interactive dropdown built using Tailwind and class name toggling.
For this example, we create the HTML component using Tailwind CSS classnames but we expose a React component that looks like this:
<Dropdown options={\["Edit", "Duplicate", "Archive", "Move", "Delete"\]} onOptionSelect={(option) => { console.log("Selected Option", option)} } />
Looking at the code above, you’ll notice that we don’t have any Tailwind classes. They are all hidden inside the implementation code of <Dropdown/>. The user of this Dropdown component just has to provide a list of options and a click handler, onOptionSelect when an option is clicked.
Let’s see how this component can be built using Tailwind.
Removing some of the unrelated code, here’s the crUX of the logic. You can view this Codepen for a complete example.
import classNames from 'classnames'; function Dropdown({ options, onOptionSelect }) { // Keep track of whether the dropdown is open or not. const [isActive, setActive] = useState(false); const buttonClasses = `inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-blue-500 active:text-gray-200 transition ease-in-out duration-150`; return ( // Toggle the dropdown if the button is clicked <button onClick={() => setActive(!isActive)} className={buttonClasses}> Options </button> // Use the classnames module to toggle the Tailwind .block and .hidden classes <div class={classNames("origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg", { block: isActive, hidden: !isActive })}> // List items are rendered here. {options.map((option) => <div key={option} onClick={(e) => onOptionSelect(option)}>{option}</div>)} </div> ) } export default Dropdown;
The dropdown is made interactive by selectively showing or hiding it using the .hidden and .block classes. Whenever the <button> is pressed, we fire the onClick handler that toggles the isActive state. If the button is active (isActive === true), we set the block class. Otherwise, we set the hidden class. These are both Tailwind classes for toggling display behavior.
In summary, the classnames module is a simple and effective way to programmatically control class names for Tailwind. It makes it easier to separate logic into React props, which makes your components easier to reuse. It works for simple and interactive components.
Method 2: Using Constants To Define A Design System
Another way of using Tailwind and React together is by using constants and mapping props to a specific constant. This is effective for building design systems. Let’s demonstrate with an example.
Start with a theme.js file where you list out your design system.
// theme.js (you can call it whatever you want) export const ButtonType = { primary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", secondary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", basic: "bg-white hover:bg-gray-700 text-gray-700 font-bold rounded", delete: "bg-red-300 hover:bg-red-500 text-white font-bold rounded" }; export const ButtonSize = { sm: "py-2 px-4 text-xs", lg: "py-3 px-6 text-lg" }
In this case, we have two sets of constants:
ButtonType defines how buttons are styled in our app.
ButtonSizes defines the sizes of buttons in our app.
Now, let’s write our <Button> component:
import {ButtonType, ButtonSize} from './theme'; function Button({size, type, children}) { // This can be improved. I’m keeping it simple here by joining two strings. const classNames = ButtonType[type] + " " + ButtonSize[size]; return ( <button className={classNames}>{children}</button> ) } export default Button;
We use the ButtonType and ButtonSize constants to create a list of class names. This makes the interface of our <Button> much nicer. It lets us use size and type props instead of putting everything in a class name string.
// Cleaner and well defined props. <Button size="xs" type="primary">Enable</Button>
Versus the prior approach:
// Exposing class names <button className="py-2 px-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Enable</button>
If you need to redefine how buttons look in your application, just edit the theme.js file and all buttons in your app will automatically update. This can be easier than searching for class names in various components.
Method 3: Composing Utilities With @apply
A third way to improve the legibility of your React components is using CSS and the @apply pattern available in PostCSS to extract repeated classes. This pattern involves using stylesheets and post-processors.
Let’s demonstrate how this works through an example. Suppose you have a Button group that has a Primary and a Secondary Button.
A Button Group consisting of a primary and secondary button. (Large preview)
<button className="py-2 px-4 mr-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Update Now</button> <button className="py-2 px-4 text-xs mr-4 hover:bg-gray-100 text-gray-700 border-gray-300 border font-bold rounded">Later</button>
Using the @apply pattern, you can write this HTML as:
<button className="btn btn-primary btn-xs">Update Now</button> <button className="btn btn-secondary btn-xs">Later</button>
Which can then be adopted to React to become:
import classnames from "classnames"; function Button ({size, type, children}) { const bSize = "btn-" + size; const bType = "btn-" + type; return ( <button className={classnames("btn", bSize, bType)}>{children}</button> ) } Button.propTypes = { size: PropTypes.oneOf(['xs, xl']), type: PropTypes.oneOf(['primary', 'secondary']) }; // Using the Button component. <Button type="primary" size="xs">Update Now</Button> <Button type="secondary" size="xs">Later</Button>
Here’s how you would create these BEM-style classnames such as .btn, .btn-primary, and others. Start by creating a button.css file:
/\* button.css \*/ @tailwind base; @tailwind components; .btn { @apply py-2 px-4 mr-4 font-bold rounded; } .btn-primary { @apply bg-blue-500 hover:bg-blue-700 text-white; } .btn-secondary { @apply hover:bg-gray-700 text-gray-700 border-gray-300 border; } .btn-xs { @apply text-xs; } .btn-xl { @apply text-xl; } @tailwind utilities;
The code above isn’t real CSS but it will get compiled by PostCSS. There’s a GitHub repository available here which shows how to setup PostCSS and Tailwind for a JavaScript project.
There’s also a short video that demonstrates how to set it up here.
Disadvantages Of Using @apply
The concept of extracting Tailwind utility classes into higher-level CSS classes seems like it makes sense, but it has some disadvantages which you should be aware of. Let’s highlight these with another example.
First, by extracting these class names out, we lose some information. For example, we need to be aware that .btn-primary has to be added to a component that already has .btn applied to it. Also, .btn-primary and .btn-secondary can’t be applied together. This information is not evident by just looking at the classes.
If this component was something more complicated, you would also need to understand the parent-child relationship between the classes. In a way, this is the problem that Tailwind was designed to solve, and by using @apply, we are bringing the problems back, in a different way.
Here’s a video where Adam Wathan — the creator of Tailwind — dives into the pros and cons of using @apply.
Summary
In this article, we looked at three ways that you can integrate Tailwind into a React application to build reusable components. These methods help you to build React components that have a cleaner interface using props.
Use the classnames module to programmatically toggle classes.
Define a constants file where you define a list of classes per component state.
Use @apply to extract higher-level CSS classes.
If you have any questions, send me a message on Twitter at @tilomitra.
Recommended Reading on SmashingMag:
(ks, ra, il)
Website Design & SEO Delray Beach by DBL07.co
Delray Beach SEO
source http://www.scpie.org/building-reusable-react-components-using-tailwind/ source https://scpie1.blogspot.com/2020/05/building-reusable-react-components.html
0 notes
riichardwilson · 5 years ago
Text
Building Reusable React Components Using Tailwind
About The Author
Tilo Mitra studied Engineering at the University of Waterloo. He is an Engineering Manager and a Software Engineer. He’s been writing in JavaScript … More about Tilo …
Tailwind is a popular utility-first CSS framework that provides low-level class names to web developers. It does not have any JavaScript and works well with existing frameworks such as React, Vue, Angular, Ember, and others. Whilst this is positive, it can be confusing for new developers to understand how to integrate Tailwind in their applications. In this article, we’ll explore ways to build reusable React components using Tailwind.
In this post, we’ll look at several different ways you can build reusable React components that leverage Tailwind under the hood while exposing a nice interface to other components. This will improve your code by moving from long lists of class names to semantic props that are easier to read and maintain.
You will need to have worked with React in order to get a good understanding of this post.
Tailwind is a very popular CSS framework that provides low-level utility classes to help developers build custom designs. It’s grown in popularity over the last few years because it solves two problems really well:
Tailwind makes it easy to make iterative changes to HTML without digging through stylesheets to find matching CSS selectors.
Tailwind has sane conventions and defaults. This makes it easy for people to get started without writing CSS from scratch.
Add the comprehensive documentation and it’s no surprise why Tailwind is so popular.
These methods will help you transform code that looks like this:
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Enable </button>
To code that looks like this:
<Button size="sm" textColor="white" bgColor="blue-500"> Enable </Button>
The difference between both snippets is that in the first we made use of a standard HTML button tag, while the second used a <Button> component. The <Button> component had been built for reusability and is easier to read since it has better semantics. Instead of a long list of class names, it uses properties to set various attributes such as size, textColor, and bgColor.
Let’s get started.
Method 1: Controlling Classes With The Classnames Module
A simple way to adapt Tailwind into a React application is to embrace the class names and toggle them programmatically.
The classnames npm module makes it easy to toggle classes in React. To demonstrate how you may use this, let’s take a use case where you have <Button> components in your React application.
// This could be hard to read. <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Enable</button> // This is more conventional React. <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Let’s see how to separate Tailwind classes so people using this <Button> component can use React props such as size, textColor, and bgColor.
Pass props such as bgColor and textColor directly into the class name string template.
Use objects to programmatically switch class names (as we have done with the size prop)
In the example code below, we’ll take a look at both approaches.
// Button.jsx import classnames from 'classnames'; function Button ({size, bgColor, textColor, children}) { return ( <button className={classnames("bg-${bgColor} text-${textColor} font-bold py-2 px-4 rounded", { "text-xs": size === 'sm' "text-xl": size === 'lg', })}> {children} </button> ) }; export default Button;
In the code above, we define a Button component that takes the following props:
size Defines the size of the button and applies the Tailwind classes text-xs or text-xl
bgColor Defines the background color of the button and applies the Tailwind bg-* classes.
textColor Defines the text color of the button and applies the Tailwind text-* classes.
children Any subcomponents will be passed through here. It will usually contain the text within the <Button>.
By defining Button.jsx, we can now import it in and use React props instead of class names. This makes our code easier to read and reuse.
import Button from './Button'; <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Using Class Names For Interactive Components
A Button is a very simple use-case. What about something more complicated? Well, you can take this further to make interactive components.
For example, let’s look at a dropdown that is made using Tailwind.
Your browser does not support the video tag.
An interactive dropdown built using Tailwind and class name toggling.
For this example, we create the HTML component using Tailwind CSS classnames but we expose a React component that looks like this:
<Dropdown options={\["Edit", "Duplicate", "Archive", "Move", "Delete"\]} onOptionSelect={(option) => { console.log("Selected Option", option)} } />
Looking at the code above, you’ll notice that we don’t have any Tailwind classes. They are all hidden inside the implementation code of <Dropdown/>. The user of this Dropdown component just has to provide a list of options and a click handler, onOptionSelect when an option is clicked.
Let’s see how this component can be built using Tailwind.
Removing some of the unrelated code, here’s the crUX of the logic. You can view this Codepen for a complete example.
import classNames from 'classnames'; function Dropdown({ options, onOptionSelect }) { // Keep track of whether the dropdown is open or not. const [isActive, setActive] = useState(false); const buttonClasses = `inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-blue-500 active:text-gray-200 transition ease-in-out duration-150`; return ( // Toggle the dropdown if the button is clicked <button onClick={() => setActive(!isActive)} className={buttonClasses}> Options </button> // Use the classnames module to toggle the Tailwind .block and .hidden classes <div class={classNames("origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg", { block: isActive, hidden: !isActive })}> // List items are rendered here. {options.map((option) => <div key={option} onClick={(e) => onOptionSelect(option)}>{option}</div>)} </div> ) } export default Dropdown;
The dropdown is made interactive by selectively showing or hiding it using the .hidden and .block classes. Whenever the <button> is pressed, we fire the onClick handler that toggles the isActive state. If the button is active (isActive === true), we set the block class. Otherwise, we set the hidden class. These are both Tailwind classes for toggling display behavior.
In summary, the classnames module is a simple and effective way to programmatically control class names for Tailwind. It makes it easier to separate logic into React props, which makes your components easier to reuse. It works for simple and interactive components.
Method 2: Using Constants To Define A Design System
Another way of using Tailwind and React together is by using constants and mapping props to a specific constant. This is effective for building design systems. Let’s demonstrate with an example.
Start with a theme.js file where you list out your design system.
// theme.js (you can call it whatever you want) export const ButtonType = { primary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", secondary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", basic: "bg-white hover:bg-gray-700 text-gray-700 font-bold rounded", delete: "bg-red-300 hover:bg-red-500 text-white font-bold rounded" }; export const ButtonSize = { sm: "py-2 px-4 text-xs", lg: "py-3 px-6 text-lg" }
In this case, we have two sets of constants:
ButtonType defines how buttons are styled in our app.
ButtonSizes defines the sizes of buttons in our app.
Now, let’s write our <Button> component:
import {ButtonType, ButtonSize} from './theme'; function Button({size, type, children}) { // This can be improved. I’m keeping it simple here by joining two strings. const classNames = ButtonType[type] + " " + ButtonSize[size]; return ( <button className={classNames}>{children}</button> ) } export default Button;
We use the ButtonType and ButtonSize constants to create a list of class names. This makes the interface of our <Button> much nicer. It lets us use size and type props instead of putting everything in a class name string.
// Cleaner and well defined props. <Button size="xs" type="primary">Enable</Button>
Versus the prior approach:
// Exposing class names <button className="py-2 px-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Enable</button>
If you need to redefine how buttons look in your application, just edit the theme.js file and all buttons in your app will automatically update. This can be easier than searching for class names in various components.
Method 3: Composing Utilities With @apply
A third way to improve the legibility of your React components is using CSS and the @apply pattern available in PostCSS to extract repeated classes. This pattern involves using stylesheets and post-processors.
Let’s demonstrate how this works through an example. Suppose you have a Button group that has a Primary and a Secondary Button.
A Button Group consisting of a primary and secondary button. (Large preview)
<button className="py-2 px-4 mr-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Update Now</button> <button className="py-2 px-4 text-xs mr-4 hover:bg-gray-100 text-gray-700 border-gray-300 border font-bold rounded">Later</button>
Using the @apply pattern, you can write this HTML as:
<button className="btn btn-primary btn-xs">Update Now</button> <button className="btn btn-secondary btn-xs">Later</button>
Which can then be adopted to React to become:
import classnames from "classnames"; function Button ({size, type, children}) { const bSize = "btn-" + size; const bType = "btn-" + type; return ( <button className={classnames("btn", bSize, bType)}>{children}</button> ) } Button.propTypes = { size: PropTypes.oneOf(['xs, xl']), type: PropTypes.oneOf(['primary', 'secondary']) }; // Using the Button component. <Button type="primary" size="xs">Update Now</Button> <Button type="secondary" size="xs">Later</Button>
Here’s how you would create these BEM-style classnames such as .btn, .btn-primary, and others. Start by creating a button.css file:
/\* button.css \*/ @tailwind base; @tailwind components; .btn { @apply py-2 px-4 mr-4 font-bold rounded; } .btn-primary { @apply bg-blue-500 hover:bg-blue-700 text-white; } .btn-secondary { @apply hover:bg-gray-700 text-gray-700 border-gray-300 border; } .btn-xs { @apply text-xs; } .btn-xl { @apply text-xl; } @tailwind utilities;
The code above isn’t real CSS but it will get compiled by PostCSS. There’s a GitHub repository available here which shows how to setup PostCSS and Tailwind for a JavaScript project.
There’s also a short video that demonstrates how to set it up here.
Disadvantages Of Using @apply
The concept of extracting Tailwind utility classes into higher-level CSS classes seems like it makes sense, but it has some disadvantages which you should be aware of. Let’s highlight these with another example.
First, by extracting these class names out, we lose some information. For example, we need to be aware that .btn-primary has to be added to a component that already has .btn applied to it. Also, .btn-primary and .btn-secondary can’t be applied together. This information is not evident by just looking at the classes.
If this component was something more complicated, you would also need to understand the parent-child relationship between the classes. In a way, this is the problem that Tailwind was designed to solve, and by using @apply, we are bringing the problems back, in a different way.
Here’s a video where Adam Wathan — the creator of Tailwind — dives into the pros and cons of using @apply.
Summary
In this article, we looked at three ways that you can integrate Tailwind into a React application to build reusable components. These methods help you to build React components that have a cleaner interface using props.
Use the classnames module to programmatically toggle classes.
Define a constants file where you define a list of classes per component state.
Use @apply to extract higher-level CSS classes.
If you have any questions, send me a message on Twitter at @tilomitra.
Recommended Reading on SmashingMag:
(ks, ra, il)
Website Design & SEO Delray Beach by DBL07.co
Delray Beach SEO
source http://www.scpie.org/building-reusable-react-components-using-tailwind/ source https://scpie.tumblr.com/post/619137817668452352
0 notes
scpie · 5 years ago
Text
Building Reusable React Components Using Tailwind
About The Author
Tilo Mitra studied Engineering at the University of Waterloo. He is an Engineering Manager and a Software Engineer. He’s been writing in JavaScript … More about Tilo …
Tailwind is a popular utility-first CSS framework that provides low-level class names to web developers. It does not have any JavaScript and works well with existing frameworks such as React, Vue, Angular, Ember, and others. Whilst this is positive, it can be confusing for new developers to understand how to integrate Tailwind in their applications. In this article, we’ll explore ways to build reusable React components using Tailwind.
In this post, we’ll look at several different ways you can build reusable React components that leverage Tailwind under the hood while exposing a nice interface to other components. This will improve your code by moving from long lists of class names to semantic props that are easier to read and maintain.
You will need to have worked with React in order to get a good understanding of this post.
Tailwind is a very popular CSS framework that provides low-level utility classes to help developers build custom designs. It’s grown in popularity over the last few years because it solves two problems really well:
Tailwind makes it easy to make iterative changes to HTML without digging through stylesheets to find matching CSS selectors.
Tailwind has sane conventions and defaults. This makes it easy for people to get started without writing CSS from scratch.
Add the comprehensive documentation and it’s no surprise why Tailwind is so popular.
These methods will help you transform code that looks like this:
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Enable </button>
To code that looks like this:
<Button size="sm" textColor="white" bgColor="blue-500"> Enable </Button>
The difference between both snippets is that in the first we made use of a standard HTML button tag, while the second used a <Button> component. The <Button> component had been built for reusability and is easier to read since it has better semantics. Instead of a long list of class names, it uses properties to set various attributes such as size, textColor, and bgColor.
Let’s get started.
Method 1: Controlling Classes With The Classnames Module
A simple way to adapt Tailwind into a React application is to embrace the class names and toggle them programmatically.
The classnames npm module makes it easy to toggle classes in React. To demonstrate how you may use this, let’s take a use case where you have <Button> components in your React application.
// This could be hard to read. <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Enable</button> // This is more conventional React. <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Let’s see how to separate Tailwind classes so people using this <Button> component can use React props such as size, textColor, and bgColor.
Pass props such as bgColor and textColor directly into the class name string template.
Use objects to programmatically switch class names (as we have done with the size prop)
In the example code below, we’ll take a look at both approaches.
// Button.jsx import classnames from 'classnames'; function Button ({size, bgColor, textColor, children}) { return ( <button className={classnames("bg-${bgColor} text-${textColor} font-bold py-2 px-4 rounded", { "text-xs": size === 'sm' "text-xl": size === 'lg', })}> {children} </button> ) }; export default Button;
In the code above, we define a Button component that takes the following props:
size Defines the size of the button and applies the Tailwind classes text-xs or text-xl
bgColor Defines the background color of the button and applies the Tailwind bg-* classes.
textColor Defines the text color of the button and applies the Tailwind text-* classes.
children Any subcomponents will be passed through here. It will usually contain the text within the <Button>.
By defining Button.jsx, we can now import it in and use React props instead of class names. This makes our code easier to read and reuse.
import Button from './Button'; <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>
Using Class Names For Interactive Components
A Button is a very simple use-case. What about something more complicated? Well, you can take this further to make interactive components.
For example, let’s look at a dropdown that is made using Tailwind.
Your browser does not support the video tag.
An interactive dropdown built using Tailwind and class name toggling.
For this example, we create the HTML component using Tailwind CSS classnames but we expose a React component that looks like this:
<Dropdown options={\["Edit", "Duplicate", "Archive", "Move", "Delete"\]} onOptionSelect={(option) => { console.log("Selected Option", option)} } />
Looking at the code above, you’ll notice that we don’t have any Tailwind classes. They are all hidden inside the implementation code of <Dropdown/>. The user of this Dropdown component just has to provide a list of options and a click handler, onOptionSelect when an option is clicked.
Let’s see how this component can be built using Tailwind.
Removing some of the unrelated code, here’s the crUX of the logic. You can view this Codepen for a complete example.
import classNames from 'classnames'; function Dropdown({ options, onOptionSelect }) { // Keep track of whether the dropdown is open or not. const [isActive, setActive] = useState(false); const buttonClasses = `inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-blue-500 active:text-gray-200 transition ease-in-out duration-150`; return ( // Toggle the dropdown if the button is clicked <button onClick={() => setActive(!isActive)} className={buttonClasses}> Options </button> // Use the classnames module to toggle the Tailwind .block and .hidden classes <div class={classNames("origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg", { block: isActive, hidden: !isActive })}> // List items are rendered here. {options.map((option) => <div key={option} onClick={(e) => onOptionSelect(option)}>{option}</div>)} </div> ) } export default Dropdown;
The dropdown is made interactive by selectively showing or hiding it using the .hidden and .block classes. Whenever the <button> is pressed, we fire the onClick handler that toggles the isActive state. If the button is active (isActive === true), we set the block class. Otherwise, we set the hidden class. These are both Tailwind classes for toggling display behavior.
In summary, the classnames module is a simple and effective way to programmatically control class names for Tailwind. It makes it easier to separate logic into React props, which makes your components easier to reuse. It works for simple and interactive components.
Method 2: Using Constants To Define A Design System
Another way of using Tailwind and React together is by using constants and mapping props to a specific constant. This is effective for building design systems. Let’s demonstrate with an example.
Start with a theme.js file where you list out your design system.
// theme.js (you can call it whatever you want) export const ButtonType = { primary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", secondary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", basic: "bg-white hover:bg-gray-700 text-gray-700 font-bold rounded", delete: "bg-red-300 hover:bg-red-500 text-white font-bold rounded" }; export const ButtonSize = { sm: "py-2 px-4 text-xs", lg: "py-3 px-6 text-lg" }
In this case, we have two sets of constants:
ButtonType defines how buttons are styled in our app.
ButtonSizes defines the sizes of buttons in our app.
Now, let’s write our <Button> component:
import {ButtonType, ButtonSize} from './theme'; function Button({size, type, children}) { // This can be improved. I’m keeping it simple here by joining two strings. const classNames = ButtonType[type] + " " + ButtonSize[size]; return ( <button className={classNames}>{children}</button> ) } export default Button;
We use the ButtonType and ButtonSize constants to create a list of class names. This makes the interface of our <Button> much nicer. It lets us use size and type props instead of putting everything in a class name string.
// Cleaner and well defined props. <Button size="xs" type="primary">Enable</Button>
Versus the prior approach:
// Exposing class names <button className="py-2 px-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Enable</button>
If you need to redefine how buttons look in your application, just edit the theme.js file and all buttons in your app will automatically update. This can be easier than searching for class names in various components.
Method 3: Composing Utilities With @apply
A third way to improve the legibility of your React components is using CSS and the @apply pattern available in PostCSS to extract repeated classes. This pattern involves using stylesheets and post-processors.
Let’s demonstrate how this works through an example. Suppose you have a Button group that has a Primary and a Secondary Button.
A Button Group consisting of a primary and secondary button. (Large preview)
<button className="py-2 px-4 mr-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Update Now</button> <button className="py-2 px-4 text-xs mr-4 hover:bg-gray-100 text-gray-700 border-gray-300 border font-bold rounded">Later</button>
Using the @apply pattern, you can write this HTML as:
<button className="btn btn-primary btn-xs">Update Now</button> <button className="btn btn-secondary btn-xs">Later</button>
Which can then be adopted to React to become:
import classnames from "classnames"; function Button ({size, type, children}) { const bSize = "btn-" + size; const bType = "btn-" + type; return ( <button className={classnames("btn", bSize, bType)}>{children}</button> ) } Button.propTypes = { size: PropTypes.oneOf(['xs, xl']), type: PropTypes.oneOf(['primary', 'secondary']) }; // Using the Button component. <Button type="primary" size="xs">Update Now</Button> <Button type="secondary" size="xs">Later</Button>
Here’s how you would create these BEM-style classnames such as .btn, .btn-primary, and others. Start by creating a button.css file:
/\* button.css \*/ @tailwind base; @tailwind components; .btn { @apply py-2 px-4 mr-4 font-bold rounded; } .btn-primary { @apply bg-blue-500 hover:bg-blue-700 text-white; } .btn-secondary { @apply hover:bg-gray-700 text-gray-700 border-gray-300 border; } .btn-xs { @apply text-xs; } .btn-xl { @apply text-xl; } @tailwind utilities;
The code above isn’t real CSS but it will get compiled by PostCSS. There’s a GitHub repository available here which shows how to setup PostCSS and Tailwind for a JavaScript project.
There’s also a short video that demonstrates how to set it up here.
Disadvantages Of Using @apply
The concept of extracting Tailwind utility classes into higher-level CSS classes seems like it makes sense, but it has some disadvantages which you should be aware of. Let’s highlight these with another example.
First, by extracting these class names out, we lose some information. For example, we need to be aware that .btn-primary has to be added to a component that already has .btn applied to it. Also, .btn-primary and .btn-secondary can’t be applied together. This information is not evident by just looking at the classes.
If this component was something more complicated, you would also need to understand the parent-child relationship between the classes. In a way, this is the problem that Tailwind was designed to solve, and by using @apply, we are bringing the problems back, in a different way.
Here’s a video where Adam Wathan — the creator of Tailwind — dives into the pros and cons of using @apply.
Summary
In this article, we looked at three ways that you can integrate Tailwind into a React application to build reusable components. These methods help you to build React components that have a cleaner interface using props.
Use the classnames module to programmatically toggle classes.
Define a constants file where you define a list of classes per component state.
Use @apply to extract higher-level CSS classes.
If you have any questions, send me a message on Twitter at @tilomitra.
Recommended Reading on SmashingMag:
(ks, ra, il)
Website Design & SEO Delray Beach by DBL07.co
Delray Beach SEO
source http://www.scpie.org/building-reusable-react-components-using-tailwind/
0 notes
tak4hir0 · 5 years ago
Link
React TypeScript: Basics and Best PracticesAn updated handbook/cheat sheet for working with React.js with TypeScript.There is no single “right” way of writing React code using TypeScript. As with other technologies, if your code compiles and works, you probably did something right. That being said, there are “best practices” that you’d want to consider following, especially when writing code others will have to either read or re-use for their own purposes. So, here I’m going to list some useful code-snippets that follow said “best practices”. There are a lot of them, some that you might’ve used already in the past and some that might be new. Just go through the list and make mental notes. Bookmarking this article for future reference might be a good idea as well. Making your components ready for sharing, with TypeScriptExample: browsing through shared React components in bit.devBit.dev has become a very popular alternative to traditional component libraries as it offers a way to “harvest” and share individual components from any codebase (to a single component hub). By building projects using React with TS, you make sure your components are easily comprehensible to other developers (as well as to your future self). That is absolutely crucial for making them ready for sharing. It’s a great way to write maintainable code and optimize your team collaboration. Learn more about sharing and reusing React TS components across repos here: Getting startedcreate-react-app with TypeScript$ npx create-react-app your-app-name --template typescriptIf you’re more of a fan of Yarn, you can use the following command: $ yarn create react-app your-app-name --template typescriptIn either case, notice how we’re not directly using the app, rather, we’re using other tools that will download the latest version of the app whenever it’s required. This helps ensure you’re not using an outdated version. BasicsSome of the very interesting tidbits added by TS to the language are: InterfacesOne of the many benefits TypeScript brings to the table, is access to constructs such as this, which allows you to define the interface of your components or even any other complex objects you might want to use with them, such as the shape your Props object will have (i.e how many properties and their types). The above code ensures that whoever uses your components needs to add exactly 3 properties: text: which needs to be a Stringtype: which needs to be a ButtonType option (I’ll cover Enums in a second)action: which is a simple functionNote that we “extended” the FC (Functional Component) type with our own custom interface. That gives our function all the generic functional component definitions such as the ‘children’ prop and a return type that must be assignable to JSX.Element. If you ignore one of them or send something that’s not compatible, both the TypeScript compiler and your IDE (assuming you’re using a JavaScript specific IDE, such as Code) will notify you and won’t allow you to continue until you fix it. A better way to define our ExtendedButton element would be to extend a native HTML button element type like so: But more on that topic later in this post… Also, note that when working with Bit.dev or react-docgen, the following syntax is required to auto-generate docs: (The props are defined directly and explicitly using :IButtonProps in addition to defining the component with ) EnumsJust like with Interfaces, Enums allow you to define a set of related constants as part of a single entity. Importing and using Enums: Please note that unlike Interfaces or Types, Enums will get translated into plain JavaScript. So, for example, this: enum SelectableButtonTypes {Important = "important",Optional = "optional",Irrelevant = "irrelevant"}will transform into this: "use strict";var SelectableButtonTypes;(function (SelectableButtonTypes) {SelectableButtonTypes["Important"] = "important";SelectableButtonTypes["Optional"] = "optional";SelectableButtonTypes["Irrelevant"] = "irrelevant";})(SelectableButtonTypes || (SelectableButtonTypes = {}));Interfaces vs Types aliasA common question that newcomers to TypeScript have is whether they should be using Interfaces or Type Aliases for different parts of their code — after all, the official documentation is a bit unclear regarding that topic. Truth is, although these entities are conceptually different, in practice, they are quite similar: They can both be extended.2. They can both be used to define the shape of objects. 3. They both can be implemented in the same way. The only extra feature Interfaces bring to the table (that Type aliases don’t), is “declaration merging” which means you can define the same interface several times and with each definition, the properties get merged: Optional types for your propsPart of the benefits of using Interfaces is that you’re able to enforce the properties of your props for your components. However, thanks to the optional syntax available through TypeScript, you can also define optional props, like this: HooksHooks are the new mechanics React provides to interact with several of its features (such as the state) without the need to define a class. Adding type check to hooksHooks such as useState receive a parameter and correctly return the state (again, that’s for this case) and a function to set it. Thanks to TypeScript’s type validation, you can enforce the type (or interface) of the initial value of the state, like this: Nullable values to hooksHowever, if the initial value for your hook can potentially be a null, then the above example will fail. For these cases, TypeScript allows you to set an optional type as well, making sure you’re covered from all sides. That way you’re ensuring you keep type checks, but allow for those scenarios where the initial value can come as null. Generic ComponentsMuch like the way you define generic functions and interfaces in TypeScript, you can define generic components, allowing you to re-use them for different data types. You can do this for props and states as well. You can then use the component either by taking advantage of type inference or directly specifying the data types, likes so: Type inference exampleDirectly declared typesFor the latter, note that if your list contains strings instead of numbers, TypeScript will throw an error during the transpilation process. Extending HTML ElementsSometimes, your components function and behave like native HTML elements (on steroids). For example, a “borederd box” (which is simply a component that always renders a div with a default border) or a “big submit” (which again, is nothing but your good old submit button with a default size and maybe some custom behavior). For these scenarios, it’s best to define your component type as a native HTML element or an extension of it. As you can see, I’ve extended HTML’s default props and added a new one: “title” for my specific needs. Event TypesAs you probably know, React provides its own set of events, which is why you can’t directly use the good old HTML Events. That being said, you do have access to all the useful UI events you need, so much so in fact, that they have the same names as well, so make sure you reference them directly like React.MouseEvent or just remember to import them from React like so: import React, { Component, MouseEvent } from 'react';The benefits of using TypeScript here, is that we can also use Generics (like in the previous example) to restrict the elements a particular event handler can be used on. For example, the following code will not work: And you’ll see an error message similar to the following: You can, however, use unions to allow a single handler to be re-used by multiple components: Integrated type definitionFinally, for the last tip, I wanted to mention the index.d.ts and the global.d.ts files. They’re both installed when you add React to your project (if you used npm, you’ll find them inside the npm_modules/@types folder. These files contain type and interface definitions used by React, so if you need to understand the props of one particular type, you can simply open these files and review their content. For example: There you can see a small section of the index.d.ts file, showing the different signatures for the createElement function. ConclusionThere is a lot more you can achieve by using TypeScript as part of your React toolchain, so if you saw at least one snippet that you liked here, consider reading up on how to gradually migrate your React projects to TypeScript or even learn how to design your own React TypeScript libraries here. Either way, I hope you got something out of this article, and feel free to leave any other tips or tricks you’ve picked up over the years of using TypeScript for your React projects! See you on the next one! Learn More
0 notes
dougmeet · 6 years ago
Link
0 notes
oniktech-blog · 6 years ago
Text
Xiaomi AMAZFIT Bip Pace Youth GPS Bluetooth Smart Watch - Black
Xiaomi AMAZFIT Bip Pace Youth GPS Bluetooth Smart Watch - Black to #USA #UK #China #freeshipping and more
Specification: Brand: Xiaomi Amazfit Bluetooth Version: Bluetooth 4.0 Waterproof: YesIP rating : IP68
Functions: Bluetooth calling: Phone call reminder Messaging Message reminderHealth tracker:Heart rate monitor,Sleep monitorOperating mode: Press buttonType of battery: Lithium-ion polymer batteryBattery Capacity: 190mAhPeople:Female table,Male tableShape of the…
View On WordPress
0 notes