Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
buraksakalli committed Nov 6, 2023
0 parents commit 1d5a62a
Show file tree
Hide file tree
Showing 21 changed files with 3,814 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
25 changes: 25 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: "🚀 release"

on:
release:
types: [published]

jobs:
release:
name: 🚀 release
runs-on: ubuntu-latest
steps:
- name: 📚 checkout
uses: actions/checkout@v3.1.0
- name: 🟢 node
uses: actions/setup-node@v3.5.0
with:
node-version: 14
registry-url: https://registry.npmjs.org
- run: npm run preci
- run: npm run ci
- run: npm run build
- name: 🚀 publish
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
94 changes: 94 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Keycap

[![npm version](https://badge.fury.io/js/keycap.svg)](https://badge.fury.io/js/keycap)
![keycap](https://github.com/buraksakalli/keycap/assets/10114716/ea114e89-6fbc-47c6-ad87-b71046cec882)

Keycap is a lightweight, customizable keyboard key (kbd) component for React. It's designed to visually represent keyboard keys in your user interface, complete with a "pressed" style to give users feedback when keys are active.

## Features

- Lightweight with no external dependencies.
- Easy to use and integrate into your React projects.
- Customizable styles for both light and dark mode.
- Pressed key state for interactive feedback.

## Installation

To install the package, use npm:

````bash
npm install keycap

or yarn:

```bash
yarn add keycap
````
## Usage
Here is a basic example of how to use the `Keycap` component:
```jsx
import { Keycap } from "keycap";

function App() {
return (
<div>
<Keycap activeKey="A">A</Keycap>
<Keycap activeKey="B">B</Keycap>
<Keycap activeKey="C">C</Keycap>
<Keycap activeKey="Meta"></Keycap>
<Keycap activeKey="Enter"></Keycap>
</div>
);
}

export default App;
```
## Props
- `activeKey`: (string) The key that the `Keycap` component should respond to.
- `children`: (node) The content to display inside the keycap, typically a single letter or symbol.
- `className`: (string) Optional. A class name to add custom styles to the keycap.
## Styling
The component uses the following CSS variables for theming, which you can override in your stylesheet:
```css
/* Light Mode */
--keycap-text-color: rgb(150, 159, 175);
--keycap-gradient: linear-gradient(
-225deg,
rgb(213, 219, 228) 0%,
rgb(248, 248, 248) 100%
);
--keycap-key-shadow: inset 0 -2px 0 0 rgb(205, 205, 230), inset 0 0 1px 1px #fff,
0 1px 2px 1px rgba(30, 35, 90, 0.4);
--keycap-key-pressed-shadow: inset 0 -2px 0 0 #cdcde6, inset 0 0 1px 1px #fff,
0 1px 1px 0 rgba(30, 35, 90, 0.4);
/* Dark Mode */
--keycap-text-color-dark: rgb(127, 132, 151);
--keycap-gradient-dark: linear-gradient(
-26.5deg,
rgb(38, 39, 43) 0%,
rgb(58, 59, 63) 100%
);
--keycap-key-shadow-dark: inset 0 -2px 0 0 rgb(28, 29, 33), inset 0 0 1px 1px
rgb(48, 49, 53), 0 2px 2px 0 rgba(3, 4, 9, 0.3);
--keycap-key-pressed-shadow-dark: inset 0 -2px 0 0 rgb(28, 29, 33), inset 0 0
1px 1px rgb(48, 49, 53), 0 1px 1px 0 rgba(3, 4, 9, 0.5);
```
You can customize these variables in your CSS to match your app's theme.
## Contributing
If you have any suggestions or improvements, please submit a pull request or open an issue. Contributions are always welcome!
## License
This project is licensed under the MIT License
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Keycap Lib | React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
52 changes: 52 additions & 0 deletions lib/_components/Keycap/Keycap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"use client";

import { FC, ReactNode, useEffect, useState } from "react";

import styles from "./button.module.css";

interface KbdProps extends React.HTMLAttributes<HTMLElement> {
children: ReactNode;
activeKey: string;
}

const useKeyPress = (targetKey: string): boolean => {
const [isKeyPressed, setIsKeyPressed] = useState<boolean>(false);

useEffect(() => {
const handleKeyDown = ({ key }: KeyboardEvent) => {
if (key === targetKey) {
setIsKeyPressed(true);
}
};

const handleKeyUp = ({ key }: KeyboardEvent) => {
if (key === targetKey) {
setIsKeyPressed(false);
}
};

window.addEventListener("keydown", handleKeyDown);
window.addEventListener("keyup", handleKeyUp);

return () => {
window.removeEventListener("keydown", handleKeyDown);
window.removeEventListener("keyup", handleKeyUp);
};
}, [targetKey]);

return isKeyPressed;
};

export const Keycap: FC<KbdProps> = ({ activeKey, children, ...props }) => {
const isKeyDown = useKeyPress(activeKey);

const className = isKeyDown
? `${styles.key} ${styles.keyPressed}`
: styles.key;

return (
<kbd {...props} className={className}>
{children}
</kbd>
);
};
52 changes: 52 additions & 0 deletions lib/_components/Keycap/button.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
:root {
--keycap-text-color: rgb(120, 130, 140);

--keycap-gradient: linear-gradient(
-225deg,
rgb(233, 236, 239) 0%,
rgb(255, 255, 255) 100%
);

--keycap-key-shadow: inset 0 -2px 0 0 rgb(205, 210, 220),
inset 0 0 1px 1px #ffffff, 0 1px 2px 1px rgba(30, 35, 90, 0.25);

--keycap-key-pressed-shadow: inset 0 -2px 0 0 rgb(195, 200, 210),
inset 0 0 1px 1px #ffffff, 0 1px 1px 0 rgba(30, 35, 90, 0.35);
}

html[data-theme="dark"] {
--keycap-gradient: linear-gradient(
-26.5deg,
rgb(38, 39, 43) 0%,
rgb(58, 59, 63) 100%
);
--keycap-key-shadow: inset 0 -2px 0 0 rgb(28, 29, 33),
inset 0 0 1px 1px rgb(48, 49, 53), 0 2px 2px 0 rgba(3, 4, 9, 0.3);

--keycap-key-pressed-shadow: inset 0 -2px 0 0 rgb(28, 29, 33),
inset 0 0 1px 1px rgb(48, 49, 53), 0 1px 1px 0 rgba(3, 4, 9, 0.5);
--keycap-text-color: rgb(138, 139, 143);
}

.key {
align-items: center;
background: var(--keycap-gradient);
border-radius: 3px;
box-shadow: var(--keycap-key-shadow);
color: var(--keycap-text-color);
display: flex;
height: 18px;
justify-content: center;
margin-right: 0.4em;
position: relative;
padding: 0px 0px 2px 0px;
border: 0px;
top: -1px;
width: 20px;
user-select: none;
}

.keyPressed {
transform: translate3d(0, 1px, 0);
box-shadow: var(--keycap-key-pressed-shadow);
}
1 change: 1 addition & 0 deletions lib/_components/Keycap/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./Keycap";
1 change: 1 addition & 0 deletions lib/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Keycap } from "./_components/Keycap";
1 change: 1 addition & 0 deletions lib/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
Loading

0 comments on commit 1d5a62a

Please sign in to comment.