Note: This is a real example, not a tutorial on how to print "hello world" with an npm package. So buckle up buckaroo. π€
Do you want to easily share code between projects? Do you want to keep that code private but avoid the monthly fee for privately publishing to npmjs dot com? Then this is the tutorial for you.
We'll be building an npm package, adding JavaScript and CSS, uploading to a private git repo on Bitbucket and making a simple project to test the package with.
Final product: https://github.com/mocasalter/npm-package-demo
When we're done your package will accessibly⨠hide outline focus styles for mouse users but show them for keyboard users*. Like this:
Pre reqs
I assume that you know how to use the command line, have the npm CLI and NodeJs installed and know how to use them, and have git installed and have a decent grasp of how it works.
1. Start a new package
In your CLI, run these commands to make a new folder, navigate into that folder and initialize a new npm package.
mkdir smart-focus-ring
cd smart-focus-ring
npm init -y
Make a new folder called lib and a new file called index.js. Index is the default entry point file for an npm package, and lib will hold the custom files.
mkdir lib
touch index.js
Then open the smart-focus-ring folder in a text editor. If you have Visual Studio Code installed you can run the command $ code .
.
Open package.json and add this files array. That will ensure the lib directory is downloaded whenever the package is installed.
{
"otherStuff": "",
"files": [
"lib"
]
}
2. Add JavaScript
Create a new file in lib called smart-focus-ring.js and paste in this code.
function handleFirstTab(e) {
if (e.keyCode === 9) {
// the "I am a keyboard user" key
document.body.classList.add('user-is-tabbing');
window.removeEventListener('keydown', handleFirstTab);
}
}
function smartFocusRing() {
window.addEventListener('keydown', handleFirstTab);
}
module.exports = smartFocusRing;
It adds a class user-is-tabbing
to the body when the user hits the tab key.
That last line module.exports
exposes the smartFocusRing
function as a module so we can use it in index.js.
3. Export the function
Now import smartFocusRing
into index.js.
const smartFocusRing = require('./lib/smart-focus-ring.js');
module.exports = smartFocusRing;
module.export
-ing from the package's entry point (index.js) makes smartFocusRing
available to any project that has installed the smart-focus-ring package.
4. Add CSS
Now add CSS to make the style changes based on whether the user-is-tabbing
class is present on the body.
In the lib folder, add a new file called styles.css and paste in this code.
/* Hide the focus ring until we know it's needed */
button:focus,
input:focus,
select:focus,
textarea:focus {
outline: none;
}
.user-is-tabbing button:focus,
.user-is-tabbing input:focus,
.user-is-tabbing select:focus,
.user-is-tabbing textarea:focus {
outline: 2px solid #7aacfe !important; /* for non-webkit browsers */
outline: 5px auto -webkit-focus-ring-color !important;
}
Your directory should look like this.
ββββlib
β β smart-focus-ring.js
β β styles.css
β index.js
β package.json
5. Publish to Bitbucket
At this point you could publish to npm if you wanted to but there's a monthly fee for private packages so we'll use Bitbucket instead.
Run these commands to create a new repo inside the smart-focus-ring folder.
cd /path-to/smart-focus-ring
git init
git add .
git commit -m "Initial commit"
Then create an account on bitbucket.org and a new, private git repo on Bitbucket.
Run these commands to upload your local repo to Bitbucket.
git remote add origin git@bitbucket.org:YOURUSERNAME/smart-focus-ring.git
git push -u origin master
And you'll see a warning that looks something like this.
This is where things get interesting.
SSH keys
That warning comes up because you haven't given your computer permission to use your private Bitbucket repo yet. To do so, follow Atlassian's walk through on setting up SSH keys for Bitbucket for your operating system.
...Or if your privacy isn't that important, you can go to your Bitbucket repo, select Settings and uncheck the box for "This is a private repository."
Then run this command again and that warning should be gone.
git push -u origin master
6. Make a test project
Create a new project folder, initialize npm and make some files.
mkdir tester-project
cd tester-project
npm init -y
touch index.js
touch index.html
Add some html to index.html.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tester Project</title>
<style>
body{font-family:"Open Sans",sans-serif;}
button{border:none;border-radius:0;padding:0.65em 1.2em;cursor:pointer;color:#fff;background:#8d6e91;}
button:focus{background:#AB90B2}
</style>
</head>
<body>
<h1>Tester Project</h1>
<button type="button">button</button>
<script src="index.js"></script>
</body>
</html>
And install a bundler so we'll have ES6 module support.
npm install -g parcel-bundler
Run the bundler and go to the url it gives you. Mine was localhost:1234.
parcel index.html
Now try clicking the button. See how it has a focus ring? Once the package is installed, that focus ring will only show if you've indicated keyboard navigation by hitting the tab key.
7. Import the module
Install the package using your Bitbucket user name.
npm i git+ssh://git@bitbucket.org:YOUR-USER-NAME/smart-focus-ring.git
Import the smart-focus-ring assets into the index.js file and call the smartFocusRing
function.
import smartFocusRing from 'smart-focus-ring';
import './node_modules/smart-focus-ring/lib/styles.css';
smartFocusRing();
Then run Parcel and go to the url it provides.
parcel index.html
Now if you click the button the focus ring will be gone, but it will appear when you hit the tab key. All thanks to your npm package! Congratulations! π₯³
*As seen in Removing that ugly :focus ring (and keeping it too).
Top comments (2)
I liked your post but the title is misleading. It's not a npm package. Instead of downloading from npm, we are downloading directly from code repository.
Exactly. The post title is misleading!