frutjam 0.8.1-beta.4 → 0.8.1-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ [![Total Downloads](https://img.shields.io/npm/dt/frutjam.svg)](https://www.npmjs.com/package/frutjam)
2
+ [![Latest Release](https://img.shields.io/npm/v/frutjam.svg)](https://github.com/nezanuha/frutjam/releases)
3
+ [![License](https://img.shields.io/npm/l/frutjam.svg)](https://github.com/nezanuha/frutjam/blob/master/LICENSE)
4
+ [![Secured](https://img.shields.io/badge/Security-Passed-green)](https://snyk.io/test/github/nezanuha/frutjam)
5
+
6
+ ---
7
+
8
+ ## ⚡ Frutjam — Tailwind CSS UI Library for Fast Development
9
+
10
+ **Frutjam** is a lightweight UI library built on top of **Tailwind CSS**, designed to help developers build accessible, SEO-friendly, and W3C-compliant interfaces—fast.
11
+
12
+ With a wide selection of prebuilt components and themes, Frutjam makes it easy to hit the ground running or fully customize your design system.
13
+
14
+ ---
15
+
16
+ ### ✨ Features
17
+
18
+ * 🧱 **Prebuilt UI Components** — Plug-and-play components to save time
19
+ * 🎨 **Customizable Themes** — Use built-in themes or create your own
20
+ * ♿ **Accessibility-First** — Follows accessibility best practices
21
+ * 🔍 **SEO-Friendly** — Semantic markup optimized for search engines
22
+ * ✅ **W3C Standards** — Clean, valid HTML structure
23
+ * ⚙️ **Built for Tailwind CSS** — Seamless integration with your Tailwind setup
24
+
25
+ ---
26
+
27
+ ### 🚀 Installation
28
+
29
+ ```bash
30
+ npm install frutjam
31
+ ```
32
+
33
+ ---
34
+
35
+ ### 📦 Usage
36
+
37
+ Import Tailwind CSS and Frutjam into your main stylesheet:
38
+
39
+ ```css
40
+ @import "tailwindcss";
41
+ @import "frutjam";
42
+ ```
43
+
44
+ That’s it — you're ready to build with Frutjam components!
45
+
46
+ ---
47
+
48
+ ### 📚 Documentation
49
+
50
+ For examples, theming, and full usage guides, visit:
51
+ 👉 **[frutjam.com](https://frutjam.com)**
52
+
53
+ ---
54
+
55
+ ## 🤝 Contributing
56
+
57
+ Contributions are welcome! If you find a bug, have a feature request, or want to help improve the library:
58
+
59
+ 1. Fork the repo
60
+ 2. Create a new branch
61
+ 3. Submit a pull request
62
+
63
+ Please check the [contributing guidelines](.github/CONTRIBUTING.md) before starting.
64
+
65
+ ---
66
+
67
+ ## 📄 License
68
+
69
+ This project is licensed under the [MIT License](LICENSE).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frutjam",
3
- "version": "0.8.1-beta.4",
3
+ "version": "0.8.1-beta.5",
4
4
  "description": "A utility-first CSS framework UI Library",
5
5
  "main": "./dist/frutjam.css",
6
6
  "browser": "dist/frutjam.css",
@@ -37,8 +37,8 @@
37
37
  "url": "https://github.com/nezanuha/frutjam/issues"
38
38
  },
39
39
  "dependencies": {
40
- "@tailwindcss/postcss": "^4.1.6",
41
- "tailwindcss": "^4.1.6"
40
+ "@tailwindcss/postcss": "^4.1.7",
41
+ "tailwindcss": "^4.1.7"
42
42
  },
43
43
  "devDependencies": {
44
44
  "css-loader": "^7.1.2",
@@ -1,33 +1,39 @@
1
1
  @import '../theme/jams/base.css';
2
2
  @utility accordion {
3
- @layer components {
4
- @apply grid divide-y divide-info-100 border border-info-100 cursor-pointer rounded-md;
3
+ @apply divide-y divide-core-200 dark:divide-core-900;
5
4
 
6
- &>details {
7
- @apply text-pretty;
8
-
9
- &>*:not(summary){
10
- @apply px-4 pb-4;
11
- }
12
- &>summary::marker{
13
- @apply content-none;
14
- }
15
- &>summary{
16
- @apply flex gap-4 items-center justify-between p-4 font-medium;
17
- &::after {
18
- @apply content-[url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAyMCAyMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZT0icmdiYSg1Myw1Myw1MywxKSIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij4KICA8cGF0aCBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Im0xOS41IDguMjUtNy41IDcuNS03LjUtNy41Ii8+Cjwvc3ZnPg==')];
19
- @apply inline-block text-inherit;
20
- }
5
+ display: grid;
6
+ border: 1px solid light-dark(
7
+ var(--core-200),
8
+ var(--core-900)
9
+ );
10
+ border-radius: var(--radius-accordion);
11
+ cursor: pointer;
12
+
13
+ &>details {
14
+ @apply text-pretty;
15
+
16
+ &>*:not(summary){
17
+ @apply px-4 pb-4;
18
+ }
19
+ &>summary::marker{
20
+ @apply content-none;
21
+ }
22
+ &>summary{
23
+ @apply flex gap-4 items-center justify-between p-4 font-medium;
24
+ &::after {
25
+ @apply content-[url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAyMCAyMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZT0icmdiYSg1Myw1Myw1MywxKSIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij4KICA8cGF0aCBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Im0xOS41IDguMjUtNy41IDcuNS03LjUtNy41Ii8+Cjwvc3ZnPg==')];
26
+ @apply inline-block text-inherit;
21
27
  }
22
28
  }
29
+ }
23
30
 
24
- &>details[open] {
31
+ &>details[open] {
25
32
 
26
- &>summary {
27
- @apply pb-4;
28
- &::after {
29
- @apply rotate-180 origin-center transition-transform duration-300;
30
- }
33
+ &>summary {
34
+ @apply pb-4;
35
+ &::after {
36
+ @apply rotate-180 origin-center transition-transform duration-300;
31
37
  }
32
38
  }
33
39
  }
@@ -0,0 +1,52 @@
1
+ @utility container {
2
+ margin-inline: auto;
3
+ padding-inline: 1rem;
4
+ @media (width >= 640px) { /* sm */
5
+ padding-inline: 2rem;
6
+ }
7
+ @media (width >= 1024px) { /* lg */
8
+ padding-inline: 4rem;
9
+ }
10
+ }
11
+
12
+ @utility container-xs {
13
+ max-width: 320px;
14
+ margin-inline: auto;
15
+ padding-inline: 1rem;
16
+ }
17
+ @utility container-sm {
18
+ max-width: 640px;
19
+ margin-inline: auto;
20
+ padding-inline: 1rem;
21
+ }
22
+ @utility container-md {
23
+ max-width: 768px;
24
+ margin-inline: auto;
25
+ padding-inline: 1rem;
26
+ }
27
+
28
+ @utility container-lg {
29
+ max-width: 1024px;
30
+ margin-inline: auto;
31
+ padding-inline: 1rem;
32
+ }
33
+
34
+ @utility container-xl {
35
+ max-width: 1280px;
36
+ margin-inline: auto;
37
+ padding-inline: 1rem;
38
+ }
39
+
40
+ @utility container-2xl {
41
+ max-width: 1536px;
42
+ margin-inline: auto;
43
+ padding-inline: 1rem;
44
+ }
45
+
46
+ @utility container-full {
47
+ width: 100vw;
48
+ max-width: 100vw;
49
+ margin-inline: auto;
50
+ padding-inline: 1rem;
51
+ box-sizing: border-box;
52
+ }
@@ -1,93 +1,98 @@
1
1
  @import "../theme/jams/base.css";
2
2
  @utility drawer {
3
- @layer components {
4
- @apply pointer-events-none invisible fixed inset-0 m-0 grid h-full max-h-none w-full max-w-none place-items-start bg-transparent p-0 text-inherit z-999 overflow-hidden overscroll-contain;
5
-
6
- &:not(drawer:not([open]):not(.drawer-open)),
7
- &::backdrop {
8
- @apply starting:invisible;
9
- background: light-dark(
10
- color-mix(in oklab,var(--color-default-100)30%,var(--color-default-900)20%),
11
- color-mix(in oklab,var(--color-default-800)50%,transparent)
12
- );
13
- }
3
+ @apply pointer-events-none invisible fixed inset-0 m-0 grid h-full max-h-none w-full max-w-none place-items-start bg-transparent p-0 text-inherit z-999 overflow-hidden overscroll-contain;
4
+
5
+ &:not(drawer:not([open]):not(.drawer-open)),
6
+ &::backdrop {
7
+ @apply starting:invisible;
8
+ background: light-dark(
9
+ color-mix(in oklab,var(--color-default-100)30%,var(--color-default-900)20%),
10
+ color-mix(in oklab,var(--color-default-800)50%,transparent)
11
+ );
12
+ }
14
13
 
15
- &[open], &.drawer-open{
16
- @apply pointer-events-auto visible starting:invisible;
14
+ &[open], &.drawer-open{
15
+ @apply pointer-events-auto visible starting:invisible;
17
16
 
18
- .drawer-body {
19
- translate: 0 0;
20
- scale: 1;
21
- opacity: 1;
22
- }
17
+ .drawer-body {
18
+ translate: 0 0;
19
+ scale: 1;
20
+ opacity: 1;
23
21
  }
24
22
  }
25
23
  }
26
24
 
27
25
  @utility drawer-backdrop {
28
- @layer components {
29
- @apply col-start-1 row-start-1 grid self-stretch justify-self-stretch text-transparent -z-1;
30
- button {
31
- @apply cursor-pointer;
32
- }
26
+ @apply col-start-1 row-start-1 grid self-stretch justify-self-stretch text-transparent -z-1;
27
+ button {
28
+ @apply cursor-pointer;
33
29
  }
34
30
  }
35
31
 
36
32
  @utility drawer-body {
37
- @layer components {
38
- @apply bg-core-50 text-core-950 rounded-none shadow-xl shadow-black/10 forced-colors:outline col-start-1 row-start-1 h-screen max-h-none w-11/12 w-auto max-w-none p-1 transition-all duration-200 overflow-y-auto overscroll-contain;
39
- translate: -100% 0;
40
- scale: 1;
41
- }
33
+ @apply rounded-none forced-colors:outline col-start-1 row-start-1 h-screen max-h-none w-11/12 w-auto max-w-none p-1 overflow-y-auto overscroll-contain;
34
+ translate: -100% 0;
35
+ scale: 1;
36
+
37
+ --tw-shadow-color: light-dark(
38
+ color-mix(in oklab,var(--core-300)50%,transparent),
39
+ color-mix(in oklab,var(--core-900)60%,transparent)
40
+ );
41
+
42
+ background: light-dark(
43
+ var(--core-50),
44
+ var(--core-950)
45
+ );
46
+ color: light-dark(
47
+ var(--default-800),
48
+ var(--default-50)
49
+ );
50
+ border: 1px solid light-dark(
51
+ var(--core-300),
52
+ var(--core-900)
53
+ );
54
+ transition: translate 0.3s ease-out, visibility 0.3s allow-discrete, background-color 0.3s ease-out, opacity 0.1s ease-out;
42
55
  }
43
56
 
44
57
 
45
58
  @utility drawer-top {
46
- @layer components {
47
- @apply place-items-start;
59
+ @apply place-items-start;
48
60
 
49
- :where(.drawer-body) {
50
- @apply h-auto w-full max-w-none rounded-none;
51
- max-height: calc(100vh - 5em);
52
- translate: 0 -100%;
53
- scale: 1;
54
- }
61
+ :where(.drawer-body) {
62
+ @apply h-auto w-full max-w-none rounded-none;
63
+ max-height: calc(100vh - 5em);
64
+ translate: 0 -100%;
65
+ scale: 1;
55
66
  }
56
67
  }
57
68
 
58
69
  @utility drawer-bottom {
59
- @layer components {
60
- @apply place-items-end;
70
+ @apply place-items-end;
61
71
 
62
- :where(.drawer-body) {
63
- @apply h-auto w-full max-w-none rounded-none;
64
- max-height: calc(100vh - 5em);
65
- translate: 0 100%;
66
- scale: 1;
67
- }
72
+ :where(.drawer-body) {
73
+ @apply h-auto w-full max-w-none rounded-none;
74
+ max-height: calc(100vh - 5em);
75
+ translate: 0 100%;
76
+ scale: 1;
68
77
  }
69
78
  }
70
79
 
71
80
  @utility drawer-start {
72
- @layer components {
73
- @apply place-items-start;
81
+ @apply place-items-start;
74
82
 
75
- :where(.drawer-body) {
76
- @apply h-screen max-h-none w-auto max-w-none rounded-none;
77
- translate: -100% 0;
78
- scale: 1;
79
- }
83
+ :where(.drawer-body) {
84
+ @apply h-screen max-h-none w-auto max-w-none rounded-none;
85
+ translate: -100% 0;
86
+ scale: 1;
80
87
  }
81
88
  }
82
89
 
83
90
  @utility drawer-end {
84
- @layer components {
85
- @apply place-items-end;
91
+ @apply place-items-end;
86
92
 
87
- :where(.drawer-body) {
88
- @apply h-screen max-h-none w-auto max-w-none rounded-none;
89
- translate: 100% 0;
90
- scale: 1;
91
- }
93
+ :where(.drawer-body) {
94
+ @apply h-screen max-h-none w-auto max-w-none rounded-none;
95
+ translate: 100% 0;
96
+ scale: 1;
92
97
  }
93
98
  }
@@ -2,7 +2,6 @@
2
2
  @import "../theme/placement.css";
3
3
 
4
4
  @utility dropdown {
5
- @layer components {
6
5
  @apply relative inline-block;
7
6
  position-area: var(--anchor-v, bottom) var(--anchor-h, span-right);
8
7
 
@@ -80,13 +79,28 @@
80
79
  @apply hidden origin-top opacity-0 scale-95;
81
80
  }
82
81
  }
83
- }
84
82
  }
85
83
 
86
84
  @utility dropdown-body {
87
- @layer components {
88
- @apply bg-core-50 text-core-950 rounded-[var(--radius-size)] border border-black/30 shadow-xl shadow-black/10 forced-colors:outline col-start-1 row-start-1 max-h-screen p-3 transition-all duration-150 scale-95 opacity-0 overflow-y-auto overscroll-contain;
89
- }
85
+ @apply shadow forced-colors:outline col-start-1 row-start-1 max-h-screen p-3 transition-all duration-150 scale-95 opacity-0 overflow-y-auto overscroll-contain;
86
+
87
+ --tw-shadow-color: light-dark(
88
+ color-mix(in oklab,var(--core-300)50%,transparent),
89
+ color-mix(in oklab,var(--core-900)60%,transparent)
90
+ );
91
+ border: 1px solid light-dark(
92
+ var(--core-200),
93
+ var(--core-900)
94
+ );
95
+ border-radius: var(--radius-dropdown);
96
+ background: light-dark(
97
+ var(--core-50),
98
+ var(--core-950)
99
+ );
100
+ color: light-dark(
101
+ var(--core-800),
102
+ var(--core-50)
103
+ );
90
104
  }
91
105
 
92
106
  /* placements */
@@ -0,0 +1,17 @@
1
+ @utility header {
2
+ @apply gap-3 py-2;
3
+ display: flex;
4
+ justify-content: space-between;
5
+ align-items:center;
6
+ margin-left: auto;
7
+ margin-right: auto;
8
+ background-color: light-dark(var(--core-50), var(--core-950));
9
+ color: light-dark(var(--core-900), var(--core-50));
10
+ border-bottom: 1px solid light-dark(var(--core-200), var(--core-800));
11
+ top: 0;
12
+ z-index: 999;
13
+ }
14
+
15
+ @utility header-sticky {
16
+ position: sticky;
17
+ }
@@ -37,8 +37,8 @@
37
37
  var(--core-950)
38
38
  );
39
39
  color: light-dark(
40
- var(--default-800),
41
- var(--default-50)
40
+ var(--core-800),
41
+ var(--core-50)
42
42
  );
43
43
  border: 1px solid light-dark(
44
44
  var(--core-300),
@@ -1,27 +1,23 @@
1
1
  @utility nav-* {
2
- @layer components {
3
- &:is(.nav-list) {
4
- @apply flex w-full gap-2;
5
- }
6
- }
2
+ width: 100%;
3
+ &:is(.nav-list) {
4
+ @apply gap-2;
5
+ display: flex;
6
+ }
7
7
  }
8
8
 
9
9
  /* placements */
10
10
 
11
11
  @utility nav-x-* {
12
- @layer components {
13
- @apply [justify-self:--value(--x-*)];
14
- & > :where(.nav-list) {
15
- @apply [justify-content:--value(--x-*)] items-center flex-row gap-x-2;
16
- }
12
+ @apply [justify-self:--value(--x-*)];
13
+ & > :where(.nav-list) {
14
+ @apply [justify-content:--value(--x-*)] items-center flex-row gap-x-2;
17
15
  }
18
16
  }
19
17
 
20
18
  @utility nav-y-* {
21
- @layer components {
22
- @apply [justify-self:--value(--y-*)];
23
- & > :where(.nav-list) {
24
- @apply items-start flex-col gap-y-1;
25
- }
26
- }
19
+ @apply [justify-self:--value(--y-*)];
20
+ & > :where(.nav-list) {
21
+ @apply items-start flex-col gap-y-1 w-full;
22
+ }
27
23
  }
@@ -0,0 +1,29 @@
1
+ @utility surface {
2
+ background-color: light-dark(var(--core-50), var(--core-950));
3
+ color: light-dark(var(--core-900), var(--core-50));
4
+ }
5
+
6
+ @utility surface-1 {
7
+ background-color: light-dark(var(--core-100), var(--core-900));
8
+ color: light-dark(var(--core-800), var(--core-100));
9
+ }
10
+
11
+ @utility surface-2 {
12
+ background-color: light-dark(var(--core-200), var(--core-800));
13
+ color: light-dark(var(--core-700), var(--core-200));
14
+ }
15
+
16
+ @utility surface-3 {
17
+ background-color: light-dark(var(--core-300), var(--core-700));
18
+ color: light-dark(var(--core-600), var(--core-300));
19
+ }
20
+
21
+ @utility surface-4 {
22
+ background-color: light-dark(var(--core-400), var(--core-600));
23
+ color: light-dark(var(--core-500), var(--core-400));
24
+ }
25
+
26
+ @utility surface-5 {
27
+ background-color: light-dark(var(--core-500), var(--core-500));
28
+ color: light-dark(var(--core-400), var(--core-500));
29
+ }
package/src/main.css CHANGED
@@ -1,3 +1,5 @@
1
+ @import "./components/header.css";
2
+ @import "./components/container.css";
1
3
  @import "./components/button.css";
2
4
  @import "./components/input.css";
3
5
  @import "./components/modal.css";
@@ -5,6 +5,8 @@
5
5
  --radius-input: 0.5rem;
6
6
  --radius-checkbox: 0.375rem;
7
7
  --radius-modal: 1rem;
8
+ --radius-accordion: 0.5rem;
9
+ --radius-dropdown: 0.5rem;
8
10
 
9
11
  --core-50: oklch(.985 .001 106.423);
10
12
  --core-100: oklch(.97 .001 106.424);
@@ -11,6 +11,8 @@
11
11
  --radius-input: 0.5rem;
12
12
  --radius-checkbox: 0.375rem;
13
13
  --radius-modal: 1rem;
14
+ --radius-accordion: 0.5rem;
15
+ --radius-dropdown: 0.5rem;
14
16
 
15
17
  --core-50: oklch(.985 .001 106.423);
16
18
  --core-100: oklch(.97 .001 106.424);
@@ -1,12 +1,10 @@
1
1
  @utility heading-* {
2
- @layer utilities {
3
- @apply font-bold text-balance;
4
- color:light-dark(
5
- var(--core-950)
6
- var(--core-50)
7
- );
8
- font-size: --value(--text-*);
2
+ @apply font-bold text-balance;
3
+ color:light-dark(
4
+ var(--core-950)
5
+ var(--core-50)
6
+ );
7
+ font-size: --value(--text-*);
9
8
 
10
- /* todo: make it heading-md instead of heading-base */
11
- }
9
+ /* todo: make it heading-md instead of heading-base */
12
10
  }