1
0
mirror of https://github.com/nostalgic-css/NES.css.git synced 2025-04-20 22:22:05 +02:00

create button element

This commit is contained in:
BcRikko 2023-04-01 22:36:20 +09:00
parent 18cf59f0da
commit 17b49006e5
24 changed files with 408 additions and 98 deletions

View File

@ -1,5 +1,6 @@
import { Preview } from '@storybook/html'
import '../src/core'
import './style.css'
const preview: Preview = {
parameters: {

11
.storybook/style.css Normal file
View File

@ -0,0 +1,11 @@
@import url(https://fonts.googleapis.com/css?family=Press+Start+2P);
body {
font-family: "Press Start 2P", sans-serif;
}
.stack {
display: flex;
gap: 1rem;
align-items: flex-start;
}

View File

@ -1,7 +0,0 @@
{
"extends": "stylelint-config-recommended",
"rules": {
"no-duplicate-selectors": null,
"no-descending-specificity": null
}
}

19
.stylelintrc.js Normal file
View File

@ -0,0 +1,19 @@
module.exports = {
extends: [
"stylelint-config-recommended",
"stylelint-config-recess-order"
],
rules: {
"no-duplicate-selectors": null,
"no-descending-specificity": null,
"custom-property-pattern": [
/** Global Variables */
"^nes-[a-z0-9-]+$",
/** Private Variables */
"^nes_[a-z0-9-]+$"
].join('|')
},
plugins: [
"stylelint-order"
]
}

61
package-lock.json generated
View File

@ -22,6 +22,7 @@
"react-dom": "^18.2.0",
"storybook": "^7.0.0",
"stylelint": "^15.3.0",
"stylelint-config-recess-order": "^4.0.0",
"stylelint-config-recommended": "^11.0.0",
"typescript": "^5.0.3"
}
@ -11135,6 +11136,15 @@
"node": ">=4"
}
},
"node_modules/postcss-sorting": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-8.0.2.tgz",
"integrity": "sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==",
"dev": true,
"peerDependencies": {
"postcss": "^8.4.20"
}
},
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
@ -12625,6 +12635,18 @@
"url": "https://opencollective.com/stylelint"
}
},
"node_modules/stylelint-config-recess-order": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-recess-order/-/stylelint-config-recess-order-4.0.0.tgz",
"integrity": "sha512-sOb+OofMryBR91CbzgV2FavpONqiIeAE7cfrgyUHqePblWBKsYzoUuWThI5EjPRA7KKeovm6ykr7twWYLeafPQ==",
"dev": true,
"dependencies": {
"stylelint-order": "6.x"
},
"peerDependencies": {
"stylelint": ">=15"
}
},
"node_modules/stylelint-config-recommended": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-11.0.0.tgz",
@ -12634,6 +12656,19 @@
"stylelint": "^15.3.0"
}
},
"node_modules/stylelint-order": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-6.0.3.tgz",
"integrity": "sha512-1j1lOb4EU/6w49qZeT2SQVJXm0Ht+Qnq9GMfUa3pMwoyojIWfuA+JUDmoR97Bht1RLn4ei0xtLGy87M7d29B1w==",
"dev": true,
"dependencies": {
"postcss": "^8.4.21",
"postcss-sorting": "^8.0.2"
},
"peerDependencies": {
"stylelint": "^14.0.0 || ^15.0.0"
}
},
"node_modules/stylelint/node_modules/balanced-match": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz",
@ -21851,6 +21886,13 @@
"util-deprecate": "^1.0.2"
}
},
"postcss-sorting": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-8.0.2.tgz",
"integrity": "sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==",
"dev": true,
"requires": {}
},
"postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
@ -23023,6 +23065,15 @@
}
}
},
"stylelint-config-recess-order": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-recess-order/-/stylelint-config-recess-order-4.0.0.tgz",
"integrity": "sha512-sOb+OofMryBR91CbzgV2FavpONqiIeAE7cfrgyUHqePblWBKsYzoUuWThI5EjPRA7KKeovm6ykr7twWYLeafPQ==",
"dev": true,
"requires": {
"stylelint-order": "6.x"
}
},
"stylelint-config-recommended": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-11.0.0.tgz",
@ -23030,6 +23081,16 @@
"dev": true,
"requires": {}
},
"stylelint-order": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-6.0.3.tgz",
"integrity": "sha512-1j1lOb4EU/6w49qZeT2SQVJXm0Ht+Qnq9GMfUa3pMwoyojIWfuA+JUDmoR97Bht1RLn4ei0xtLGy87M7d29B1w==",
"dev": true,
"requires": {
"postcss": "^8.4.21",
"postcss-sorting": "^8.0.2"
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",

View File

@ -36,6 +36,7 @@
"react-dom": "^18.2.0",
"storybook": "^7.0.0",
"stylelint": "^15.3.0",
"stylelint-config-recess-order": "^4.0.0",
"stylelint-config-recommended": "^11.0.0",
"typescript": "^5.0.3"
}

View File

@ -0,0 +1,6 @@
code {
padding: 3px 5px;
font-family: monospace;
background-color: #fefefe;
border: 1px solid #eee;
}

View File

@ -0,0 +1,42 @@
import type { GeneratedDocument } from ".."
import './PropsDocs.module.css'
type Props = {
json: GeneratedDocument
}
export function PropsDocs({ json }: Props) {
const hasProperties = Array.isArray(json) && json.length > 0
if (hasProperties === false) {
return <p>Has no property</p>
}
return (
<table>
<thead>
<tr>
<th>@property</th>
<th>syntax</th>
<th>inherits</th>
<th>initial-value</th>
<th>comments</th>
</tr>
</thead>
<tbody>
{json.map(doc => {
return (
<tr>
<td><code>{doc.property}</code></td>
<td><code>{doc.syntax}</code></td>
<td><code>{doc.inherits}</code></td>
<td><code>{doc["initial-value"]}</code></td>
<td>{doc.comments}</td>
</tr>
)
})}
</tbody>
</table>
)
}

View File

@ -2,8 +2,7 @@ import type { Config } from ".";
export const config: Config = {
include: [
'../../src/**/*.css'
'../../src/**/*.properties.css'
],
exclude: [],
filename: '.properties.json'
exclude: []
}

View File

@ -6,9 +6,6 @@ import { config }from './config'
export type Config =
& FindMatchingFilesConfig
& {
filename: string
}
export type GeneratedDocument = Doc[]
@ -17,7 +14,7 @@ console.time('[docgen]')
const files = findMatchingFiles(config.include, config.exclude)
const writers = files.map(async file => {
const filename = path.parse(file).name + config.filename
const filename = path.parse(file).name + '.json'
const exportPath = path.join(path.dirname(file), filename)
const css = await fs.promises.readFile(file, 'utf8')

View File

@ -13,12 +13,15 @@ export function extractProperties(css: string): Doc[] {
const root = postcss.parse(css)
root.walkAtRules('property', rule => {
const doc: Record<string, unknown> = {}
const doc = {} as Record<keyof Doc, unknown>
doc.property = rule.params
rule.walkComments(comment => { doc['comments'] = comment.text })
rule.walkComments(comment => { doc.comments = comment.text })
rule.walkDecls(/(syntax|inherits|initial-value)/, decl => {
doc[decl.prop] = decl.value
if (isDecls(decl.prop)) {
doc[decl.prop] = decl.value
}
})
docs.push(doc as Doc)
@ -26,3 +29,7 @@ export function extractProperties(css: string): Doc[] {
return docs
}
function isDecls(key: any): key is keyof Doc {
return Array<keyof Doc>('comments', 'property', 'syntax', 'inherits', 'initial-value').includes(key)
}

View File

@ -12,3 +12,7 @@ textarea {
font-size: inherit;
line-height: inherit;
}
:focus {
outline-offset: 2px;
}

View File

@ -1 +1,2 @@
import './foundation.css'
import './palette.css'

25
src/core/palette.css Normal file
View File

@ -0,0 +1,25 @@
/* keep */
:root {
--nes-color-dark: hsl(210, 10%, 15%);
--nes-color-light: hsl(0, 0%, 100%);
--nes-color-default: hsl(0, 0%, 100%);
--nes-color-default-tint: hsl(0, 0%, 90%);
--nes-color-default-shade: hsl(0, 0%, 70%);
--nes-color-primary: hsl(204, 86%, 50%);
--nes-color-primary-tint: hsl(204, 86%, 45%);
--nes-color-primary-shade: hsl(204, 86%, 40%);
--nes-color-secondary: hsl(85, 58%, 50%);
--nes-color-secondary-tint: hsl(85, 58%, 45%);
--nes-color-secondary-shade: hsl(85, 58%, 40%);
--nes-color-warning: hsl(51, 93%, 50%);
--nes-color-warning-tint: hsl(51, 93%, 45%);
--nes-color-warning-shade: hsl(51, 93%, 40%);
--nes-color-danger: hsl(10, 75%, 60%);
--nes-color-danger-tint: hsl(10, 75%, 50%);
--nes-color-danger-shade: hsl(10, 75%, 40%);
}

View File

@ -1 +0,0 @@
/* keep */

View File

@ -1,50 +1,53 @@
@property --nes-btn-border-width {
/* border width */
syntax: '<line-width>';
inherits: false;
initial-value: 4px;
}
@property --nes-btn-border-color {
/* border color */
syntax: '<color>';
inherits: false;
initial-value: black;
}
@property --nes-btn-border-inset-color {
/* inset border color */
syntax: '<color>';
inherits: false;
initial-value: gray;
}
/**
* CSS Variables
* Override & Local CSS Variables
*/
.nes-btn {
--nes-btn-border-width: 4px;
--nes-btn-border-color: black;
--nes-btn-border-inset-color: gray;
--nes_btn-inner:
inset 0 calc(var(--nes-btn-border-width-inner) * -1) var(--nes-btn-border-color-inner),
inset calc(var(--nes-btn-border-width-inner) * -1) 0 var(--nes-btn-border-color-inner);
}
.nes-btn:active {
--nes_btn-inner:
inset 0 var(--nes-btn-border-width-inner) var(--nes-btn-border-color-inner),
inset var(--nes-btn-border-width-inner) 0 var(--nes-btn-border-color-inner);
}
/**
* Basic Style
*/
.nes-btn {
border: solid var(--nes-btn-border-width) var(--nes-btn-border-color);
box-shadow:
inset 0 calc(var(--nes-btn-border-width) * -1) var(--nes-btn-border-inset-color),
inset calc(var(--nes-btn-border-width) * -1) 0 var(--nes-btn-border-inset-color);
--nes-n: var(--nes-btn-border-width);
--nes-m: calc(100% - var(--nes-btn-border-width));
clip-path: polygon(
0 var(--nes-n), var(--nes-n) var(--nes-n), var(--nes-n) 0,
var(--nes-m) 0, var(--nes-m) var(--nes-n), 100% var(--nes-n),
100% var(--nes-m), var(--nes-m) var(--nes-m), var(--nes-m) 100%,
var(--nes-n) 100%, var(--nes-n) var(--nes-m), 0 var(--nes-m)
);
padding: 0.5em 1em;
position: relative;
z-index: 0;
padding: 0.8em 1em;
color: var(--nes-btn-color);
background-color: transparent;
border: none;
}
/**
* Outside border & background-color style
*/
.nes-btn::before {
position: absolute;
inset: var(--nes-btn-border-width);
z-index: -1;
color: var(--nes-btn-border-color);
content: "";
background-color: var(--nes-btn-bg-color);
box-shadow:
0 var(--nes-btn-border-width),
var(--nes-btn-border-width) 0,
0 calc(var(--nes-btn-border-width) * -1),
calc(var(--nes-btn-border-width) * -1) 0;
}
/**
* Inside border style
*/
.nes-btn::after {
position: absolute;
inset: var(--nes-btn-border-width);
content: "";
box-shadow: var(--nes_btn-inner);
}

View File

@ -0,0 +1,41 @@
@property --nes-btn-color {
syntax: '<color>';
inherits: true;
initial-value: var(--nes-color-dark);
}
@property --nes-btn-bg-color {
syntax: '<color>';
inherits: true;
initial-value: var(--nes-color-default);
}
@property --nes-btn-border-color {
/* border color */
syntax: '<color>';
inherits: true;
initial-value: var(--nes-color-dark);
}
@property --nes-btn-border-color-inner {
/* inset border color */
syntax: '<color>';
inherits: true;
initial-value: var(--nes-color-default-shade);
}
@property --nes-btn-border-width {
/* border width */
syntax: '<line-width>';
inherits: true;
initial-value: 4px;
}
@property --nes-btn-border-width-inner {
/* border width */
syntax: '<line-width>';
inherits: true;
initial-value: 4px;
}

View File

@ -0,0 +1,42 @@
[
{
"property": "--nes-btn-color",
"syntax": "'<color>'",
"inherits": "true",
"initial-value": "var(--nes-color-dark)"
},
{
"property": "--nes-btn-bg-color",
"syntax": "'<color>'",
"inherits": "true",
"initial-value": "var(--nes-color-default)"
},
{
"property": "--nes-btn-border-color",
"comments": "border color",
"syntax": "'<color>'",
"inherits": "true",
"initial-value": "var(--nes-color-dark)"
},
{
"property": "--nes-btn-border-color-inner",
"comments": "inset border color",
"syntax": "'<color>'",
"inherits": "true",
"initial-value": "var(--nes-color-default-shade)"
},
{
"property": "--nes-btn-border-width",
"comments": "border width",
"syntax": "'<line-width>'",
"inherits": "true",
"initial-value": "4px"
},
{
"property": "--nes-btn-border-width-inner",
"comments": "border width",
"syntax": "'<line-width>'",
"inherits": "true",
"initial-value": "4px"
}
]

View File

@ -1,5 +1,8 @@
import { Canvas, Meta, Story } from "@storybook/addon-docs";
import "./button.css";
import "./index.css";
import { PropsDocs } from '../../../scripts/docgen/PropsDocs'
import json from './button.properties.json'
<Meta title="MDX/Elements/Button" />
@ -10,46 +13,27 @@ This is button.
<Canvas>
<Story name="Button">
{() => `
<button class="nes-btn">
Click me!
</button>
<div class="stack">
<button class="nes-btn">
Default
</button>
<button class="nes-btn isPrimary">
Primary
</button>
<button class="nes-btn isSecondary">
Secondary
</button>
<button class="nes-btn isWarning">
Warning
</button>
<button class="nes-btn isDanger">
Danger
</button>
</div>
`}
</Story>
</Canvas>
## CSS Variables
<table>
<thead>
<tr>
<th>@property</th>
<th>syntax</th>
<th>inherits</th>
<th>initial-value</th>
<th>comments</th>
</tr>
</thead>
<tbody>
<tr>
<td>`--nes-btn-border-width`</td>
<td>`<line-width>`</td>
<td>`false`</td>
<td>`4px`</td>
<td>...</td>
</tr>
<tr>
<td>`--nes-btn-border-color`</td>
<td>`<color>`</td>
<td>`false`</td>
<td>`black`</td>
<td>...</td>
</tr>
<tr>
<td>`--nes-btn-border-inset-color`</td>
<td>`<color>`</td>
<td>`false`</td>
<td>`gray`</td>
<td>...</td>
</tr>
</tbody>
</table>
<PropsDocs json={json}></PropsDocs>

View File

@ -0,0 +1,68 @@
/**
* Global CSS Variables
*
* There are variables that you can change.
*/
:root .nes-btn {
/* Color theme */
--nes-btn-color: var(--nes-color-dark);
--nes-btn-bg-color: var(--nes-color-default);
--nes-btn-border-color: var(--nes-color-dark);
--nes-btn-border-color-inner: var(--nes-color-default-shade);
/* Appearance */
--nes-btn-border-width: 4px;
--nes-btn-border-width-inner: 4px;
}
:root .nes-btn:hover {
--nes-btn-border-width-inner: 6px;
--nes-btn-bg-color: var(--nes-color-default-tint);
}
/**
* Primary theme
*/
:root .nes-btn.isPrimary {
--nes-btn-color: var(--nes-color-light);
--nes-btn-bg-color: var(--nes-color-primary);
--nes-btn-border-color-inner: var(--nes-color-primary-shade);
}
:root .nes-btn.isPrimary:hover {
--nes-btn-bg-color: var(--nes-color-primary-tint);
}
/**
* Secondary theme
*/
:root .nes-btn.isSecondary {
--nes-btn-color: var(--nes-color-light);
--nes-btn-bg-color: var(--nes-color-secondary);
--nes-btn-border-color-inner: var(--nes-color-secondary-shade);
}
:root .nes-btn.isSecondary:hover {
--nes-btn-bg-color: var(--nes-color-secondary-tint);
}
/**
* Warning theme
*/
:root .nes-btn.isWarning {
--nes-btn-color: var(--nes-color-dark);
--nes-btn-bg-color: var(--nes-color-warning);
--nes-btn-border-color-inner: var(--nes-color-warning-shade);
}
:root .nes-btn.isWarning:hover {
--nes-btn-bg-color: var(--nes-color-warning-tint);
}
/**
* Danger theme
*/
:root .nes-btn.isDanger {
--nes-btn-color: var(--nes-color-light);
--nes-btn-bg-color: var(--nes-color-danger);
--nes-btn-border-color-inner: var(--nes-color-danger-shade);
}
:root .nes-btn.isDanger:hover {
--nes-btn-bg-color: var(--nes-color-danger-tint);
}

View File

@ -0,0 +1,3 @@
@import './button.properties.css';
@import './button.theme.css';
@import './button.css';

View File

@ -1 +0,0 @@
import 'button.css'

View File

@ -8,6 +8,7 @@
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"jsx": "react-jsx",
"isolatedModules": true,
/** Interop Constraints */

5
types/env.d.ts vendored
View File

@ -1,6 +1,9 @@
import type { GeneratedDocument } from "../scripts/docgen"
declare module '*.css';
declare module '*.css' {
const styles: Record<string, string>
export default styles
}
declare module '*.properties.json' {
const json: GeneratedDocument