TODO list, lists, tables, cards, icon in button, password input, required fields generalization.

+ Add TODO list.
+ Add lists style.
+ Add tables style.
+ Add cards style.
+ Add password input.
* Generalize required field component.
* Fix icon position in buttons.
* Fix custom class of boxes.
This commit is contained in:
Madeorsk 2024-06-09 09:22:32 +02:00
parent 60892d4adc
commit 6acbf75ed7
Signed by: Madeorsk
SSH key fingerprint: SHA256:J9G0ofIOLKf7kyS2IfrMqtMaPdfsk1W02+oGueZzDDU
13 changed files with 305 additions and 15 deletions

View file

@ -2,13 +2,35 @@ import React from "react";
import "../index"; import "../index";
import {Checkbox} from "../src/Components/Forms/Checkbox"; import {Checkbox} from "../src/Components/Forms/Checkbox";
import { Radio } from "../src/Components/Forms/Radio"; import { Radio } from "../src/Components/Forms/Radio";
import {FloppyDisk, TrashSimple, XCircle} from "@phosphor-icons/react";
import {Card} from "../src/Components/Card";
import {PasswordInput} from "../src/Components/Forms/PasswordInput";
import {RequiredField} from "../src/Components/Forms/RequiredField";
export function DemoApp() export function DemoApp()
{ {
return ( return (
<div className={"app"}> <main className={"app"}>
<h1>KernelUI</h1> <h1>KernelUI</h1>
<h2>TODO</h2>
<ul>
<li>Popover / Tooltips</li>
<li>Datepicker / Timepicker</li>
<li>Selects</li>
<li>Loaders</li>
<li>Menu</li>
<li>Tabs / Apps selectors</li>
<li>App steps</li>
<li>Pagination</li>
<li>Apps</li>
<li>Global states</li>
<li>Async</li>
<li>Subapps</li>
<li>Modals</li>
</ul>
<h2>Headings</h2> <h2>Headings</h2>
<h1>Demo app</h1> <h1>Demo app</h1>
@ -28,23 +50,27 @@ export function DemoApp()
<button type={"button"}>A cool button</button> <button type={"button"}>A cool button</button>
<a className={"button"} href={"#"}>A link button</a> <a className={"button"} href={"#"}>A link button</a>
<button type={"button"} className={"flat"}>A flat button</button> <button type={"button"} className={"flat"}>A flat button</button>
<button type={"button"} className={"validation"}>A validation button</button> <button type={"button"} className={"validation"}><FloppyDisk weight={"bold"} /> A validation button</button>
<button type={"button"} className={"cancel"}>A cancellation button</button> <button type={"button"} className={"cancel"}><XCircle weight={"bold"} /> A cancellation button</button>
<button type={"button"} className={"delete"}>A deletion button</button> <button type={"button"} className={"delete"}><TrashSimple weight={"bold"} /> A deletion button</button>
<h2>Forms</h2> <h2>Forms</h2>
<form> <form>
<label> <label>
Text label <span className={"required"}></span> Text label <RequiredField />
<input type={"text"} placeholder={"Normal demo text"}/> <input type={"text"} placeholder={"Normal demo text"} required={true} />
</label> </label>
<label> <label>
Textarea label <span className={"required"}></span> Textarea label <RequiredField />
<textarea placeholder={"A normal textarea."}></textarea> <textarea placeholder={"A normal textarea."} required={true}></textarea>
</label> </label>
<PasswordInput>
Test password
</PasswordInput>
<Checkbox>Checkbox demo</Checkbox> <Checkbox>Checkbox demo</Checkbox>
<Radio name={"radio-test"}>Radio box test</Radio> <Radio name={"radio-test"}>Radio box test</Radio>
<Radio name={"radio-test"}>Radio box test</Radio> <Radio name={"radio-test"}>Radio box test</Radio>
@ -56,7 +82,13 @@ export function DemoApp()
<a href={"#"}>Link test</a> <a href={"#"}>Link test</a>
</div> </div>
<p> <p>
<strong>Lorem ipsum</strong> dolor <code>sit amet</code>, <em>consectetur</em> adipiscing elit. Donec accumsan pulvinar felis, vitae eleifend augue lacinia tempus. Integer nec iaculis ante. Duis a quam urna. Nullam tincidunt rutrum felis, a efficitur enim facilisis sit amet. Quisque dictum semper sagittis. Maecenas in orci hendrerit, tempor nunc non, tempus mi. Praesent blandit varius rutrum. Nullam quis mauris eros. Vestibulum commodo libero sed pellentesque pharetra. Donec eget fringilla ante. Aliquam id leo massa. Duis dictum nunc ut dolor iaculis malesuada. Nulla elementum justo a sem eleifend finibus. Phasellus bibendum elit nibh, at tempor odio efficitur id. <strong>Lorem ipsum</strong> dolor <code>sit amet</code>, <em>consectetur</em> adipiscing elit. Donec accumsan
pulvinar felis, vitae eleifend augue lacinia tempus. Integer nec iaculis ante. Duis a quam urna. Nullam
tincidunt rutrum felis, a efficitur enim facilisis sit amet. Quisque dictum semper sagittis. Maecenas in orci
hendrerit, tempor nunc non, tempus mi. Praesent blandit varius rutrum. Nullam quis mauris eros. Vestibulum
commodo libero sed pellentesque pharetra. Donec eget fringilla ante. Aliquam id leo massa. Duis dictum nunc ut
dolor iaculis malesuada. Nulla elementum justo a sem eleifend finibus. Phasellus bibendum elit nibh, at tempor
odio efficitur id.
</p> </p>
<h2>Steps</h2> <h2>Steps</h2>
@ -66,6 +98,78 @@ export function DemoApp()
<h3 className={"step"}>Step two</h3> <h3 className={"step"}>Step two</h3>
<h3 className={"step"}>Step three</h3> <h3 className={"step"}>Step three</h3>
</div> </div>
</div>
<h2>Lists</h2>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
<ol>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ol>
<h2>Tables</h2>
<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th colSpan={2}>Column 3</th>
</tr>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lorem</td>
<td>Ipsum</td>
<td>Dolor</td>
<td>Amet</td>
</tr>
<tr>
<td>Foo</td>
<td>Bar</td>
<td>Baz</td>
<td>John</td>
</tr>
<tr>
<td>Alice</td>
<td>Bob</td>
<td></td>
<td>Jack</td>
</tr>
</tbody>
</table>
<h2>Cards</h2>
<Card>
<h3>Card title</h3>
<p>Donec lobortis quam sapien, et efficitur dolor laoreet ut. Ut pretium, lacus at bibendum rutrum, nibh nibh scelerisque nisi, nec semper dolor turpis sed tortor. Nulla massa sapien, accumsan id vestibulum et, elementum eget metus. Morbi quis bibendum purus. Nunc at fermentum tortor. Quisque viverra diam in sem auctor blandit. Vestibulum dignissim bibendum nunc, non tristique quam sollicitudin eu. Ut feugiat lectus tellus, tempus viverra sapien aliquet vel. Morbi ac est mauris. Praesent facilisis ut tellus at cursus. Aenean placerat nulla non mi vulputate hendrerit. Praesent fermentum dui eu gravida pharetra. Quisque rhoncus, magna non congue egestas, leo lorem malesuada felis, eu imperdiet orci magna ultrices est.</p>
<button type={"button"}>Button position ?</button>
<button type={"button"}>Button position ?</button>
</Card>
<Card>
<p>Another small card</p>
</Card>
</main>
); );
} }

10
src/Components/Card.tsx Normal file
View file

@ -0,0 +1,10 @@
import React, {PropsWithChildren} from "react";
export function Card({children, className, ...props}: PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>): React.ReactElement
{
return (
<div className={`card${className ? ` ${className}` : ""}`} {...props}>
{children}
</div>
);
}

View file

@ -1,10 +1,10 @@
import React from "react"; import React from "react";
import {Check} from "@phosphor-icons/react"; import {Check} from "@phosphor-icons/react";
export function Checkbox({children, type, ...inputProps}: React.PropsWithChildren<React.InputHTMLAttributes<HTMLInputElement>>): React.ReactElement export function Checkbox({children, className, type, ...inputProps}: React.PropsWithChildren<React.InputHTMLAttributes<HTMLInputElement>>): React.ReactElement
{ {
return ( return (
<label className={"box"}> <label className={`box${className ? ` ${className}` : ""}`}>
<input type={"checkbox"} {...inputProps} /> <input type={"checkbox"} {...inputProps} />
<a className={"button"} tabIndex={-1}><Check weight={"bold"} /></a> <a className={"button"} tabIndex={-1}><Check weight={"bold"} /></a>
{children} {children}

View file

@ -0,0 +1,23 @@
import React, {useState} from "react";
import {Eye, EyeSlash} from "@phosphor-icons/react";
export function PasswordInput({children, className, type, ...props}: React.PropsWithChildren<React.InputHTMLAttributes<HTMLInputElement>>): React.ReactElement
{
const [showPassword, setShowPassword] = useState(false);
return (
<label className={`password${className ? ` ${className}` : ""}`}>
{children}
<div>
<input type={showPassword ? "text" : "password"} {...props} />
<a className={"button"} tabIndex={-1} onClick={() => {
setShowPassword(!showPassword);
}}>
{
showPassword ? <EyeSlash weight={"bold"} /> : <Eye weight={"bold"} />
}
</a>
</div>
</label>
);
}

View file

@ -1,10 +1,10 @@
import React from "react"; import React from "react";
import {Check} from "@phosphor-icons/react"; import {Check} from "@phosphor-icons/react";
export function Radio({children, type, ...inputProps}: React.PropsWithChildren<React.InputHTMLAttributes<HTMLInputElement>>): React.ReactElement export function Radio({children, className, type, ...inputProps}: React.PropsWithChildren<React.InputHTMLAttributes<HTMLInputElement>>): React.ReactElement
{ {
return ( return (
<label className={"box"}> <label className={`box${className ? ` ${className}` : ""}`}>
<input type={"radio"} {...inputProps} /> <input type={"radio"} {...inputProps} />
<a className={"button"} tabIndex={-1}><Check weight={"bold"} /></a> <a className={"button"} tabIndex={-1}><Check weight={"bold"} /></a>
{children} {children}

View file

@ -0,0 +1,6 @@
import React from "react";
export function RequiredField({className, ...props}: React.HTMLAttributes<HTMLSpanElement>): React.ReactElement
{
return <span className={`required${className ? ` ${className}` : ""}`} {...props}></span>;
}

View file

@ -1,6 +1,9 @@
@import "components/_button"; @import "components/_button";
@import "components/_card";
@import "components/_form"; @import "components/_form";
@import "components/_headings"; @import "components/_headings";
@import "components/_link"; @import "components/_link";
@import "components/_list";
@import "components/_steps"; @import "components/_steps";
@import "components/_table";

View file

@ -4,7 +4,7 @@ a.button, button, input[type="submit"], input[type="reset"]
display: inline-block; display: inline-block;
margin: auto 0.33em; margin: 0.2em 0.33em;
padding: 0.45em 0.66em; padding: 0.45em 0.66em;
width: fit-content; width: fit-content;
border-radius: 0.25em; border-radius: 0.25em;
@ -19,6 +19,7 @@ a.button, button, input[type="submit"], input[type="reset"]
font-weight: 600; font-weight: 600;
text-decoration: none; text-decoration: none;
vertical-align: middle;
cursor: pointer; cursor: pointer;
@ -101,4 +102,12 @@ a.button, button, input[type="submit"], input[type="reset"]
outline-color: var(--red); outline-color: var(--red);
} }
} }
svg
{ // Icon style.*
display: inline-block;
margin-top: -0.2em;
margin-right: 0.2em;
vertical-align: middle;
}
} }

View file

@ -0,0 +1,32 @@
.card
{
margin: 0.5em auto;
padding: 1.4em;
width: 50em;
max-width: 92%;
box-sizing: border-box;
border-radius: 0.25em;
border: solid var(--background-darkest) thin;
background: var(--background-lighter);
h1, h2, h3, h4, h5, h6
{
margin: 0.33em 0 0.5em 0;
}
button
{
display: block;
margin-left: auto;
}
> :first-child
{
margin-top: 0;
}
> :last-child
{
margin-bottom: 0;
}
}

View file

@ -2,3 +2,4 @@
@import "forms/_box"; @import "forms/_box";
@import "forms/_input"; @import "forms/_input";
@import "forms/_label"; @import "forms/_label";
@import "forms/_password-input";

View file

@ -0,0 +1,15 @@
ul
{
list-style: "";
padding: 0 2em;
> li
{
padding: 0 0 0 0.5em;
}
}
ul, ol
{
margin: 1em auto;
}

View file

@ -0,0 +1,42 @@
table
{
margin: auto;
border-collapse: collapse;
background: var(--background-lighter);
//border: solid var(--background-darkest) thin;
border-radius: 0.25em;
thead
{
}
tbody
{
tr
{
&:nth-child(even)
{
background: var(--background-lightest);
}
&:hover
{
background: var(--background-darker);
}
}
}
tr
{
transition: background 0.1s ease;
border-bottom: solid var(--background-darkest) thin;
background: transparent;
}
th, td
{
padding: 0.4em 0.6em;
text-align: left;
}
}

View file

@ -0,0 +1,45 @@
label.password
{
> div
{
position: relative;
> input
{
padding-right: 2.5em;
padding-right: 2.5em;
}
a.button
{
position: absolute;
top: 0;
bottom: 0;
right: 0.45em;
margin: auto;
padding: 0;
width: 1.75em;
height: 1.75em;
box-shadow: 0 0 0 0 transparent;
border: none;
background: transparent;
color: var(--foreground-lightest);
&:hover
{
background: var(--background-darker);
}
> svg
{
display: block;
margin: 0.4em auto 0;
vertical-align: middle;
}
vertical-align: middle;
}
}
}