Skip to content

Commit

Permalink
v0.2.1-beta.3
Browse files Browse the repository at this point in the history
  • Loading branch information
CarcajadaArtificial committed Jul 26, 2023
1 parent 6b91f35 commit 61399e3
Show file tree
Hide file tree
Showing 38 changed files with 607 additions and 310 deletions.
9 changes: 4 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# Changelog

## v0.2.1-beta.2
## v0.2.1-beta.3

### Updated `deno.json` to support standard scripts for fmt and linting.

- `/deno.json`
### Updated project using `deno fmt`

## Changes so far

Expand All @@ -25,7 +23,8 @@
- [ ] Create an organized collection of island functions
- [ ] Update component features
- [ ] **Card**: Add text, image, gradient spacers, and chips feature.
- [ ] **Navigation**: Add appear/disappear when scrolling interaction on a fixed navigation.
- [ ] **Navigation**: Add appear/disappear when scrolling interaction on a
fixed navigation.
- [ ] **Code**: Add copy to clipboard.
- [ ] **Separator**: Add gradient separators.
- [x] **Header**, **Footer**: Add spacers with gradients that change.
Expand Down
146 changes: 106 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,104 @@
# 🍱 Lunchbox
``Hello ( ´ ω ` )ノ゙`` Welcome to 🍱 Lunchbox. So... you're into Deno 🦕 Fresh 🍋? Damn, me too. I've found myself using nothing but Fresh for most of my web dev projects. But I'm not that much of a user of existing web component libraries. Even though I respect these, I'm more of a _do-it-yourself_ kind of guy. That is why I created Lunchbox, and I couldn't help creating an opinionated product that is built to have my dream features.

``Hello ( ´ ω ` )ノ゙`` Welcome to 🍱 Lunchbox. So... you're into Deno 🦕 Fresh
🍋? Damn, me too. I've found myself using nothing but Fresh for most of my web
dev projects. But I'm not that much of a user of existing web component
libraries. Even though I respect these, I'm more of a _do-it-yourself_ kind of
guy. That is why I created Lunchbox, and I couldn't help creating an opinionated
product that is built to have my dream features.

## Ideas behind the library
Alright, so what are these features? Instead of listing what can _technically_ be done with this library, the way to describe it is by its core ideas.

Alright, so what are these features? Instead of listing what can _technically_
be done with this library, the way to describe it is by its core ideas.

### Based on [Atomic Design](https://atomicdesign.bradfrost.com/table-of-contents/)
Shoutout to [Brad Frost](https://bradfrost.com/), thank you for this great piece of work. A popular concept about modularity in design systems is to consider them inherently hierarchical. In this, I strongly disagree because atoms are of no less importance than organisms. But I do agree that they have one fundamentally different characteristic. Atoms are components only made by nature's _subatomic particles_ a.k.a. pure HTML Elements. Am I stretching too far with the atomic analogy?

Shoutout to [Brad Frost](https://bradfrost.com/), thank you for this great piece
of work. A popular concept about modularity in design systems is to consider
them inherently hierarchical. In this, I strongly disagree because atoms are of
no less importance than organisms. But I do agree that they have one
fundamentally different characteristic. Atoms are components only made by
nature's _subatomic particles_ a.k.a. pure HTML Elements. Am I stretching too
far with the atomic analogy?

- **Atoms**
- ✅ [Button](https://deno.land/x/[email protected]/components/Button/index.tsx)
- ✅ [Code](https://deno.land/x/[email protected]/components/Code/index.tsx)
- ✅ [Layout](https://deno.land/x/[email protected]/components/Layout/index.tsx)
- ✅ [Link](https://deno.land/x/[email protected]/components/Link/index.tsx)
- ✅ [Panel](https://deno.land/x/[email protected]/components/Panel/index.tsx)
- ✅ [Separator](https://deno.land/x/[email protected]/components/Separator/index.tsx)
- ✅ [Text](https://deno.land/x/[email protected]/components/Text/index.tsx)
- ⏳ Time
- ⏳ Markdown
- ⏳ Spinner
- ⏳ Screen
- Molecules
- ✅ [Card](https://deno.land/x/[email protected]/components/Card/index.tsx)
- ✅ [Footer](https://deno.land/x/[email protected]/components/Footer/index.tsx)
- ✅ [Header](https://deno.land/x/[email protected]/components/Header/index.tsx)
- ✅ [Input](https://deno.land/x/[email protected]/components/Input/index.tsx)
- ✅ [Linkmap](https://deno.land/x/[email protected]/components/Linkmap/index.tsx)
- ✅ [Main](https://deno.land/x/[email protected]/components/Main/index.tsx)
- ✅ [Navigation](https://deno.land/x/[email protected]/components/Navigation/index.tsx)
- ✅ [Select](https://deno.land/x/[email protected]/components/Select/index.tsx)
- ✅ [TextArea](https://deno.land/x/[email protected]/components/TextArea/index.tsx)
- ⏳ Menu
- ⏳ Fieldset
- ⏳ Chip
- ⏳ Page
- ⏳ Dialog
-
[Button](https://deno.land/x/[email protected]/components/Button/index.tsx)
-[Code](https://deno.land/x/[email protected]/components/Code/index.tsx)
-
[Layout](https://deno.land/x/[email protected]/components/Layout/index.tsx)
-[Link](https://deno.land/x/[email protected]/components/Link/index.tsx)
-[Panel](https://deno.land/x/[email protected]/components/Panel/index.tsx)
-
[Separator](https://deno.land/x/[email protected]/components/Separator/index.tsx)
-[Text](https://deno.land/x/[email protected]/components/Text/index.tsx)
- ⏳ Time
- ⏳ Markdown
- ⏳ Spinner
- ⏳ Screen
- Molecules
-[Card](https://deno.land/x/[email protected]/components/Card/index.tsx)
-
[Footer](https://deno.land/x/[email protected]/components/Footer/index.tsx)
-
[Header](https://deno.land/x/[email protected]/components/Header/index.tsx)
-[Input](https://deno.land/x/[email protected]/components/Input/index.tsx)
-
[Linkmap](https://deno.land/x/[email protected]/components/Linkmap/index.tsx)
-[Main](https://deno.land/x/[email protected]/components/Main/index.tsx)
-
[Navigation](https://deno.land/x/[email protected]/components/Navigation/index.tsx)
-
[Select](https://deno.land/x/[email protected]/components/Select/index.tsx)
-
[TextArea](https://deno.land/x/[email protected]/components/TextArea/index.tsx)
- ⏳ Menu
- ⏳ Fieldset
- ⏳ Chip
- ⏳ Page
- ⏳ Dialog

### Trivial HTML good practices
Component libraries are usually ambiguous about how they handle inner logic, creating the need to _find out how does it do X_. For example, some might have only one component for both `<input/>` and `<textarea/>`, which might change depending on a prop. "Or was it something else? Wait, what was the name of the class that changes when it's a TextArea?" Having it closer to the HTML Element logic makes the inner logic of the components really obvious and apparent.

Let's take as an example the `<Input>` component. When using it you're expected to use the best practices with it, plus additional features. These best practices are multidisciplinary. The field of UX foments the use of a label and a contextual error message to guide the user. That gives us the props `<Input label="" error="" />`. These features are not native to the simple `<input />` HTEML element, it must work together with other elements. It is in this next area where the good practices aren't forgotten. Like nesting the input inside a label element (`<label><input /></label>`). Finally, every visual element inside the component was designed to maintain a perfect vertical rhythm for good aesthetic practices even in the aesthetics of the interface.
Component libraries are usually ambiguous about how they handle inner logic,
creating the need to _find out how does it do X_. For example, some might have
only one component for both `<input/>` and `<textarea/>`, which might change
depending on a prop. "Or was it something else? Wait, what was the name of the
class that changes when it's a TextArea?" Having it closer to the HTML Element
logic makes the inner logic of the components really obvious and apparent.

Let's take as an example the `<Input>` component. When using it you're expected
to use the best practices with it, plus additional features. These best
practices are multidisciplinary. The field of UX foments the use of a label and
a contextual error message to guide the user. That gives us the props
`<Input label="" error="" />`. These features are not native to the simple
`<input />` HTEML element, it must work together with other elements. It is in
this next area where the good practices aren't forgotten. Like nesting the input
inside a label element (`<label><input /></label>`). Finally, every visual
element inside the component was designed to maintain a perfect vertical rhythm
for good aesthetic practices even in the aesthetics of the interface.

### Configure anything easily
Let us continue with the example of the `<Input />` component. As a very strict rule, all components must be able to render a useful default state without any defined prop. so simply using `<Input />` will create a functional input field even without a label or anything. Likewise, styles and CSS classes are optional and can be removed with the universal prop `nostyles`.

Also, additional classes can be appended simply by adding a class to the component. Having `<Input class="x" />` will add the class `"x"` to the `<input />` element inside it. Additionally, a reference can be forwarded to the same element using the universal prop `fref` like this. Having `<Input fref={inputRef} />` will forward the reference to the `<input />` element inside it.
Let us continue with the example of the `<Input />` component. As a very strict
rule, all components must be able to render a useful default state without any
defined prop. so simply using `<Input />` will create a functional input field
even without a label or anything. Likewise, styles and CSS classes are optional
and can be removed with the universal prop `nostyles`.

Also, additional classes can be appended simply by adding a class to the
component. Having `<Input class="x" />` will add the class `"x"` to the
`<input />` element inside it. Additionally, a reference can be forwarded to the
same element using the universal prop `fref` like this. Having
`<Input fref={inputRef} />` will forward the reference to the `<input />`
element inside it.

Every HTML Element and framework component that make up a particular component
will be called a _"piece"_. Every piece of every component can be referenced
using the universal component `fwd`. This is an oversimplified html code for the
`<Input />` component:

Every HTML Element and framework component that make up a particular component will be called a _"piece"_. Every piece of every component can be referenced using the universal component `fwd`. This is an oversimplified html code for the `<Input />` component:
```html
<!-- Piece name: -->
<div> <!-- wrapper -->
Expand All @@ -55,26 +109,38 @@ Every HTML Element and framework component that make up a particular component w
<span></span> <!-- error -->
</div>
```
The piece name is used in the CSS classes (`comp-#NAME#_#PIECE#`) and in the `fwd` prop (`<Input fwd={{ label: {class: 'x'} }}` will add the class `'x'` to the piece "label").

The piece name is used in the CSS classes (`comp-#NAME#_#PIECE#`) and in the
`fwd` prop (`<Input fwd={{ label: {class: 'x'} }}` will add the class `'x'` to
the piece "label").

## Getting started
Deno counts with various ways of importing modules, for example the good ol' url import:

Deno counts with various ways of importing modules, for example the good ol' url
import:

```ts
import { Button } from 'https://deno.land/x/[email protected]/mod.ts'
import { Button } from 'https://deno.land/x/[email protected]/mod.ts';
```
But let's be reasonable, almost nobody would do something like this, you would have to update multiple files and imports whenever the module updates. Personally, I'm more of an `import_map.json`.

But let's be reasonable, almost nobody would do something like this, you would
have to update multiple files and imports whenever the module updates.
Personally, I'm more of an `import_map.json`.

```json
{
"imports": {
"lunchbox": "https://deno.land/x/[email protected]/mod.ts"
}
}
```

This way, the usage would be really clean and easier to maintain:

```tsx
import { Button } from 'lunchbox';

export default function() {
return <Button>Click Me!</Button>
export default function () {
return <Button>Click Me!</Button>;
}
```
6 changes: 3 additions & 3 deletions components/Button/setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cn, opt, applyDefaults, partializeClasses } from '../../src/utils.ts';
import { applyDefaults, cn, opt, partializeClasses } from '../../src/utils.ts';
import { BUTTON_TYPES } from '../../src/enums.ts';
import { iComponent } from '../../src/types.ts';

Expand Down Expand Up @@ -29,10 +29,10 @@ export default (props: Partial<iButton>) => {
? 'comp-button_panel'
: props.type === 'contrast'
? 'clr-bg-input'
: 'clr-bg-input'
: 'clr-bg-input',
),
p.class,
p.nostyle
p.nostyle,
),
});

Expand Down
50 changes: 31 additions & 19 deletions components/Card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,42 @@ import Text from '../Text/index.tsx';
import Linkmap from '../Linkmap/index.tsx';

export default function (props: Partial<iCard>) {
const { c, fref, fwd, children, card_title, top_gradient_pattern, bottom_gradient_pattern, ...p } =
setup(props);
const {
c,
fref,
fwd,
children,
card_title,
top_gradient_pattern,
bottom_gradient_pattern,
...p
} = setup(props);

return (
<div ref={fwd.wrapper?.ref!} class={c.wrapper}>
{top_gradient_pattern ? (
<Gradient
fref={fwd.top_gradient?.fref}
class={c.top_gradient}
flip
gradient_pattern={top_gradient_pattern}
/>
) : null}
{top_gradient_pattern
? (
<Gradient
fref={fwd.top_gradient?.fref}
class={c.top_gradient}
flip
gradient_pattern={top_gradient_pattern}
/>
)
: null}
<Panel fref={fref} class={c.card} {...p}>
{card_title ? <Text type="subheading">{card_title}</Text> : null}
<div class="comp-card_content">{children}</div>
{card_title ? <Text type='subheading'>{card_title}</Text> : null}
<div class='comp-card_content'>{children}</div>
</Panel>
{bottom_gradient_pattern ? (
<Gradient
fref={fwd.bottom_gradient?.fref}
class={c.bottom_gradient}
gradient_pattern={bottom_gradient_pattern}
/>
) : null}
{bottom_gradient_pattern
? (
<Gradient
fref={fwd.bottom_gradient?.fref}
class={c.bottom_gradient}
gradient_pattern={bottom_gradient_pattern}
/>
)
: null}
</div>
);
}
16 changes: 12 additions & 4 deletions components/Card/setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cn, opt, applyDefaults, partializeClasses } from '../../src/utils.ts';
import { applyDefaults, cn, opt, partializeClasses } from '../../src/utils.ts';
import { iComponent, iFwd } from '../../src/types.ts';
import { GRADIENT_PATTERNS } from '../../src/enums.ts';
import { iGradient } from '../Gradient/setup.ts';
Expand Down Expand Up @@ -30,12 +30,20 @@ export default (props: Partial<iCard>) => {
const classes = partializeClasses({
card: opt(cn('comp-card clr-bg-panel'), p.class, p.nostyle),
wrapper: opt(cn('comp-card_wrapper'), wrapper?.class, wrapper?.nostyle),
top_gradient: opt(cn('comp-card_gradient'), top_gradient?.class, top_gradient?.nostyle),
bottom_gradient: opt(cn('comp-card_gradient'), bottom_gradient?.class, bottom_gradient?.nostyle),
top_gradient: opt(
cn('comp-card_gradient'),
top_gradient?.class,
top_gradient?.nostyle,
),
bottom_gradient: opt(
cn('comp-card_gradient'),
bottom_gradient?.class,
bottom_gradient?.nostyle,
),
gradient: opt(
cn('comp-card_gradient comp-gradient comp-gradient_zigzag'),
gradient?.class,
gradient?.nostyle
gradient?.nostyle,
),
});

Expand Down
8 changes: 6 additions & 2 deletions components/Code/setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cn, opt, applyDefaults, partializeClasses } from '../../src/utils.ts';
import { applyDefaults, cn, opt, partializeClasses } from '../../src/utils.ts';
import { iComponent, iFwd } from '../../src/types.ts';

export type iCode = iComponent & {
Expand All @@ -18,7 +18,11 @@ export default (props: Partial<iCode>) => {

const classes = partializeClasses({
code: opt(cn('comp-code clr-txt-personality'), p.class, p.nostyle),
wrapper: opt(cn('comp-code_wrapper clr-bg-panel'), wrapper?.class, wrapper?.nostyle),
wrapper: opt(
cn('comp-code_wrapper clr-bg-panel'),
wrapper?.class,
wrapper?.nostyle,
),
});

delete p.class;
Expand Down
Loading

0 comments on commit 61399e3

Please sign in to comment.