nitro-web 0.0.36 → 0.0.38

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.
@@ -1,5 +1,5 @@
1
1
  import { twMerge } from 'tailwind-merge'
2
- import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/20/solid'
2
+ import { ChevronDown, ChevronUp } from 'lucide-react'
3
3
 
4
4
  type Button = React.ButtonHTMLAttributes<HTMLButtonElement> & {
5
5
  color?: 'primary'|'secondary'|'black'|'white'
@@ -47,12 +47,12 @@ export function Button({
47
47
  lg: 'px-3.5 py-2.5 px-button-x-lg py-button-y-lg text-sm rounded-md',
48
48
  }
49
49
 
50
- const contentLayout = `w-full gap-x-1.5 ${iconPosition == 'none' ? '' : 'inline-flex items-center justify-center'}`
50
+ const contentLayout = `gap-x-1.5 ${iconPosition == 'none' ? '' : 'inline-flex items-center justify-center'}`
51
51
  const loading = isLoading ? '[&>*]:opacity-0 text-opacity-0' : ''
52
52
 
53
53
  function getIcon(Icon: React.ReactNode | 'v') {
54
- if (Icon == 'v' || Icon == 'down') return <ChevronDownIcon className="size-5 -my-6 -mx-1" />
55
- if (Icon == '^' || Icon == 'up') return <ChevronUpIcon className="size-5 -my-6 -mx-1" />
54
+ if (Icon == 'v' || Icon == 'down') return <ChevronDown size={16.5} className="mt-[-1.4rem] mb-[-1.5rem] -mx-0.5" />
55
+ if (Icon == '^' || Icon == 'up') return <ChevronUp size={16.5} className="mt-[-1.4rem] mb-[-1.5rem] -mx-0.5" />
56
56
  else return Icon
57
57
  }
58
58
 
@@ -1,8 +1,6 @@
1
1
  // Todo: show correct message type, e.g. error, warning, info, success `${store.message.type || 'success'}`
2
2
  import { isObject, isString, queryObject } from 'nitro-web/util'
3
- import { Transition } from '@headlessui/react'
4
- import { CheckCircleIcon } from '@heroicons/react/24/outline'
5
- import { XMarkIcon } from '@heroicons/react/20/solid'
3
+ import { X, CircleCheck } from 'lucide-react'
6
4
  import { MessageObject } from 'nitro-web/types'
7
5
 
8
6
  /**
@@ -85,16 +83,15 @@ export function Message() {
85
83
  className="pointer-events-none fixed inset-0 flex items-end px-4 py-6 sm:items-start sm:p-6 z-20 nitro-message"
86
84
  >
87
85
  <div className="flex w-full flex-col items-center space-y-4 sm:items-end">
88
- {/* Notification panel, dynamically insert this into the live region when it needs to be displayed */}
89
- <Transition show={isObject(store.message) && visible}>
90
- <div className="pointer-events-auto max-w-[350px] overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black/5
91
- transition data-[closed]:data-[enter]:translate-y-2 data-[enter]:transform data-[closed]:opacity-0 data-[enter]:duration-300
92
- data-[leave]:duration-100 data-[enter]:ease-out data-[leave]:ease-in data-[closed]:data-[enter]:sm:translate-x-2
93
- data-[closed]:data-[enter]:sm:translate-y-0">
94
- <div className="p-4">
86
+ {isObject(store.message) && (
87
+ <div className={
88
+ 'overflow-hidden pointer-events-auto max-w-[350px] rounded-md bg-white shadow-lg ring-1 ring-black/5 transition ' +
89
+ (visible ? 'translate-x-0 opacity-100' : 'translate-x-1 opacity-0')
90
+ }>
91
+ <div className="p-3">
95
92
  <div className="flex items-start">
96
93
  <div className="shrink-0">
97
- <CheckCircleIcon aria-hidden="true" className="size-6 text-green-400" />
94
+ <CircleCheck aria-hidden="true" size={21} className="text-green-400 mt-0.5" />
98
95
  </div>
99
96
  <div className="ml-3 flex-1 pt-0.5">
100
97
  <p className="text-sm font-medium text-gray-900">{typeof store.message === 'object' && store.message?.text}
@@ -105,17 +102,17 @@ export function Message() {
105
102
  <button
106
103
  type="button"
107
104
  onClick={hide}
108
- className="inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2
105
+ className="inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2
109
106
  focus:ring-indigo-500 focus:ring-offset-2"
110
107
  >
111
108
  <span className="sr-only">Close</span>
112
- <XMarkIcon aria-hidden="true" className="size-5" />
109
+ <X aria-hidden="true" size={19} className="mt-0.5" />
113
110
  </button>
114
111
  </div>
115
112
  </div>
116
113
  </div>
117
114
  </div>
118
- </Transition>
115
+ )}
119
116
  </div>
120
117
  </div>
121
118
  </>
@@ -1,14 +1,17 @@
1
1
  // Component: https://tailwindui.com/components/application-ui/application-shells/sidebar#component-a69d85b6237ea2ad506c00ef1cd39a38
2
+ import { css } from 'twin.macro'
2
3
  import avatarImg from 'nitro-web/client/imgs/avatar.jpg'
3
4
  import { injectedConfig } from 'nitro-web'
4
5
  import {
6
+ Bars3Icon,
5
7
  HomeIcon,
6
8
  UsersIcon,
9
+ XMarkIcon,
7
10
  ArrowLeftCircleIcon,
8
11
  PaintBrushIcon,
9
12
  } from '@heroicons/react/24/outline'
10
13
 
11
- const sidebarWidth = 'w-[19rem] lg:w-80'
14
+ const sidebarWidth = 'w-80'
12
15
 
13
16
  export type SidebarProps = {
14
17
  Logo?: React.FC<{ width?: string, height?: string }>;
@@ -24,10 +27,52 @@ export function Sidebar({ Logo, menu, links }: SidebarProps) {
24
27
  const [sidebarOpen, setSidebarOpen] = useState(false)
25
28
  return (
26
29
  <>
27
- {/* Static sidebar for desktop */}
28
- <div className={`relative inset-y-0 z-50 flex flex-col ${sidebarWidth}`}>
30
+ {/* desktop sidebar */}
31
+ <div css={style} className={
32
+ 'fixed inset-y-0 z-50 flex flex-col ease-in-out lg:left-0 lg:translate-x-0 lg:!delay-0 lg:!duration-0 ' +
33
+ (
34
+ sidebarOpen
35
+ ? 'left-0 translate-x-[0px] sidebar-transition '
36
+ : 'left-[-100%] translate-x-[-100%] sidebar-transition-delay '
37
+ ) +
38
+ sidebarWidth
39
+ }>
40
+ <div className={
41
+ 'absolute left-full top-0 flex w-16 justify-center pt-5 lg:hidden duration-300 ease ' +
42
+ (sidebarOpen ? 'opacity-100' : 'opacity-0')
43
+ }>
44
+ <button type="button" onClick={() => setSidebarOpen(false)} className="-m-2.5 p-2.5">
45
+ <XMarkIcon aria-hidden="true" className="size-6 text-white" />
46
+ </button>
47
+ </div>
29
48
  <SidebarContents Logo={Logo} menu={menu} links={links} />
30
49
  </div>
50
+
51
+ {/* mobile backdrop */}
52
+ <div
53
+ css={style}
54
+ onClick={() => setSidebarOpen(false)}
55
+ className={'fixed w-full z-[49] inset-0 bg-gray-900/70 ease-linear lg:hidden ' +
56
+ (
57
+ sidebarOpen
58
+ ? 'left-0 opacity-100 sidebar-transition '
59
+ : 'left-[-100%] opacity-0 sidebar-transition-delay '
60
+ )
61
+ }
62
+ />
63
+
64
+ {/* mobile sidebar topbar */}
65
+ <div className="sticky top-0 z-40 flex items-center gap-x-6 bg-white px-4 py-4 shadow-sm sm:px-6 lg:hidden">
66
+ <button type="button" onClick={() => setSidebarOpen(true)} className="-m-2.5 p-2.5 text-gray-700 lg:hidden">
67
+ <Bars3Icon aria-hidden="true" className="size-6" />
68
+ </button>
69
+ <div className="flex-1 text-sm/6 font-semibold text-gray-900">Dashboard</div>
70
+ <Link to="#">
71
+ <img alt="" src={avatarImg} className="size-8 rounded-full bg-gray-50" />
72
+ </Link>
73
+ </div>
74
+
75
+ <div class={`${sidebarWidth}`} />
31
76
  </>
32
77
  )
33
78
  }
@@ -56,13 +101,13 @@ function SidebarContents ({ Logo, menu, links }: SidebarProps) {
56
101
 
57
102
  // Sidebar component, swap this element with another sidebar if you like
58
103
  return (
59
- <div className="flex grow flex-col gap-y-8 overflow-y-auto py-5 px-10 border-r bg-primary border-gray-200 text-white">
104
+ <div className="flex grow flex-col gap-y-8 overflow-y-auto bg-white py-5 px-10 lg:border-r lg:border-gray-200">
60
105
  {Logo && (
61
106
  <div className="flex h-16 shrink-0 items-center gap-2 justify-bedtween">
62
107
  <Link to="/">
63
108
  <Logo width="70" height={undefined} />
64
109
  </Link>
65
- <span className="text-[9px] text-gray-200 font-semibold mt-4">{injectedConfig.version}</span>
110
+ <span className="text-[9px] text-gray-900 font-semibold mt-4">{injectedConfig.version}</span>
66
111
  </div>
67
112
  )}
68
113
  <nav className="flex flex-1 flex-col">
@@ -125,7 +170,7 @@ function SidebarContents ({ Logo, menu, links }: SidebarProps) {
125
170
  </ul>
126
171
  </li>
127
172
 
128
- <li className="-mx-6 mt-auto block">
173
+ <li className="-mx-6 mt-auto hidden lg:block">
129
174
  <Link
130
175
  to="#"
131
176
  className="flex items-center gap-x-4 px-6 py-3 text-sm/6 font-semibold text-gray-900 hover:bg-gray-50"
@@ -138,4 +183,13 @@ function SidebarContents ({ Logo, menu, links }: SidebarProps) {
138
183
  </nav>
139
184
  </div>
140
185
  )
141
- }
186
+ }
187
+
188
+ const style = css`
189
+ &.sidebar-transition-delay {
190
+ transition: transform 300ms, opacity 300ms, left 0ms 300ms;
191
+ }
192
+ &.sidebar-transition {
193
+ transition: transform 300ms, opacity 300ms, left 0ms 0ms;
194
+ }
195
+ `
@@ -10,6 +10,7 @@ import {
10
10
  EyeIcon,
11
11
  EyeSlashIcon,
12
12
  } from '@heroicons/react/20/solid'
13
+ // Maybe use fill-current tw class for lucide icons (https://github.com/lucide-icons/lucide/discussions/458)
13
14
 
14
15
  type InputProps = React.InputHTMLAttributes<HTMLInputElement>
15
16
  type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>
@@ -18,7 +19,7 @@ type FieldExtraProps = {
18
19
  name: string
19
20
  id?: string
20
21
  // state object to get the value, and check errors against
21
- state?: { errors: Errors, [key: string]: unknown }
22
+ state?: { errors?: Errors, [key: string]: unknown }
22
23
  type?: 'text' | 'password' | 'email' | 'filter' | 'search' | 'textarea' | 'currency' | 'date' | 'color'
23
24
  icon?: React.ReactNode
24
25
  iconPos?: 'left' | 'right'
@@ -1,6 +1,6 @@
1
1
  import { Drop, Dropdown, Field, Select, Button, Checkbox, GithubLink, Modal, Calendar, injectedConfig } from 'nitro-web'
2
2
  import { getCountryOptions, getCurrencyOptions, ucFirst } from 'nitro-web/util'
3
- import { CheckIcon } from '@heroicons/react/20/solid'
3
+ import { Check } from 'lucide-react'
4
4
 
5
5
  export function Styleguide() {
6
6
  const [customerSearch, setCustomerSearch] = useState('')
@@ -106,9 +106,11 @@ export function Styleguide() {
106
106
  <div><Button color="primary" size="sm">*-sm button</Button></div>
107
107
  <div><Button color="primary">*-md (default)</Button></div>
108
108
  <div><Button color="primary" size="lg">*-lg button</Button></div>
109
- <div><Button IconLeft={<CheckIcon class="size-5 -my-5 -mx-0.5" />}>IconLeft</Button></div>
110
- <div><Button IconLeft={<CheckIcon class="size-5 -my-5 -mx-0.5" />} className="w-[160px]">IconLeft 160px</Button></div>
111
- <div><Button IconLeftEnd={<CheckIcon class="size-5 -my-5 -mx-0.5" />} className="w-[190px]">IconLeftEnd 190px</Button></div>
109
+ <div><Button IconLeft={<Check size={19} className="-my-5 -mx-0.5" />}>IconLeft</Button></div>
110
+ <div><Button IconLeft={<Check size={19} className="-my-5 -mx-0.5" />}
111
+ className="w-[160px]">IconLeft 160px</Button></div>
112
+ <div><Button IconLeftEnd={<Check size={19} className="-my-5 -mx-0.5" />}
113
+ className="w-[190px]">IconLeftEnd 190px</Button></div>
112
114
  <div><Button IconRight="v">IconRight</Button></div>
113
115
  <div><Button IconRightEnd="v" className="w-[190px]">IconRightEnd 190px</Button></div>
114
116
  <div><Button color="primary" IconRight="v" isLoading>primary isLoading</Button></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nitro-web",
3
- "version": "0.0.36",
3
+ "version": "0.0.38",
4
4
  "repository": "github:boycce/nitro-web",
5
5
  "homepage": "https://boycce.github.io/nitro-web/",
6
6
  "description": "Nitro is a battle-tested, modular base project to turbocharge your projects, styled using Tailwind 🚀",