@hanzo/ui 0.5.23 → 1.0.8

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.
@@ -9,12 +9,16 @@ import { Sheet, SheetContent, SheetTrigger } from '../primitives/sheet'
9
9
  const DrawerMenu: React.FC<PropsWithChildren & {
10
10
  trigger: ReactNode
11
11
  className?: string
12
- showLogo?: boolean
12
+ showLogo?: boolean,
13
+ propogate?: boolean
14
+ asChild?: boolean
13
15
  }> = ({
14
16
  trigger,
15
17
  children,
16
18
  className='',
17
- showLogo=true
19
+ showLogo=true,
20
+ propogate=true,
21
+ asChild=false
18
22
  }) => {
19
23
 
20
24
  const [open, setOpen] = React.useState(false)
@@ -31,14 +35,13 @@ const DrawerMenu: React.FC<PropsWithChildren & {
31
35
 
32
36
  return (
33
37
  <Sheet open={open} onOpenChange={setOpen} >
34
- <SheetTrigger>
38
+ <SheetTrigger className={className} asChild={asChild}>
35
39
  {trigger}
36
40
  </SheetTrigger>
37
41
  <SheetContent
38
42
  side="right"
39
- className={className}
40
43
  closeButtonClass='text-inherit opacity-90'
41
- onClick={onAction}
44
+ onClick={propogate ? onAction : () => {}}
42
45
  closeElement={<LucideX className='h-6 w-6 text-inherit'/>}
43
46
  centerElement={showLogo ? <Logo size='xs' className='' /> : null}
44
47
  >
@@ -19,36 +19,45 @@ const Header: React.FC<{
19
19
  const allElements = (featured) ? [...common, ...featured] : common
20
20
  // TODO move 13px into a size class and configure twMerge to recognize say, 'text-size-nav'
21
21
  // (vs be beat out by 'text-color-nav')
22
- const navItemClx = 'font-nav h-8 tracking-[-0.3px] !text-[13px]/[13px]'
22
+ const navItemClx = 'font-nav h-8 !text-[13px]/[13px]'
23
23
 
24
24
  return (
25
25
  <header className={cn('bg-background sticky z-10 top-0 ', className)} >
26
26
  {/* md or larger */}
27
- <div className="hidden md:flex flex-row md:h-[80px] items-center justify-between px-[32px] 2xl:mx-auto max-w-screen-2xl">
27
+ <div className={
28
+ 'hidden md:flex flex-row md:h-[80px] items-center justify-between ' +
29
+ 'px-[32px] 2xl:mx-auto max-w-screen-2xl'
30
+ }>
28
31
  <Logo size='md' className='hidden lg:flex' key='two'/>
29
32
  <Logo size='sm' className='hidden md:flex lg:hidden' key='one'/>
30
33
  {/* md or larger */}
31
- <NavItems
32
- currentAs={siteDef.currentAs}
33
- items={allElements}
34
- className='hidden md:flex md:gap-4 lg:justify-between lg:gap-7 '
35
- itemClx={navItemClx}
36
- key='three'
37
- />
34
+ <div className='flex gap-7 items-center'>
35
+ <NavItems
36
+ currentAs={siteDef.currentAs}
37
+ items={allElements}
38
+ className='hidden md:flex md:gap-4 lg:justify-between lg:gap-7 '
39
+ itemClx={navItemClx}
40
+ key='three'
41
+ />
42
+ {siteDef.nav.cart}
43
+ </div>
38
44
  </div>
39
45
  {/* smaller than md: mobile style drawer menu */}
40
46
  <div className="flex md:hidden h-[44px] items-center justify-between px-2">
41
47
  <Logo size='sm' />
42
- <DrawerMenu
43
- className='p-0 text-primary' // ui has 'text-inherit', so need this for close buttons to appear.
44
- trigger={<Icons.burger className='h-7 w-7'/>}
45
- >
46
- <MobileNav
47
- siteDef={siteDef}
48
- className='pt-12'
49
- commonItemClx='px-10 text-l h-10 justify-start border-b rounded-none'
50
- />
51
- </DrawerMenu>
48
+ <div className='flex gap-4'>
49
+ {siteDef.nav.cart}
50
+ <DrawerMenu
51
+ className='p-0 text-primary' // ui has 'text-inherit', so need this for close buttons to appear.
52
+ trigger={<Icons.burger className='h-7 w-7'/>}
53
+ >
54
+ <MobileNav
55
+ siteDef={siteDef}
56
+ className='pt-12'
57
+ commonItemClx='px-10 text-l h-10 justify-start border-b rounded-none'
58
+ />
59
+ </DrawerMenu>
60
+ </div>
52
61
  </div>
53
62
  </header>
54
63
  )
@@ -7,10 +7,12 @@ declare global {
7
7
  export const FB_PIXEL_ID = process.env.NEXT_PUBLIC_FACEBOOK_PIXEL_ID
8
8
 
9
9
  export const pageview = () => {
10
+ // @ts-ignore
10
11
  window.fbq('track', 'PageView')
11
12
  }
12
13
 
13
14
  // https://developers.facebook.com/docs/facebook-pixel/advanced/
14
15
  export const event = (name: string, options = {}) => {
16
+ // @ts-ignore
15
17
  window.fbq('track', name, options)
16
18
  }
@@ -1,4 +1,5 @@
1
1
  ### ...Huh?
2
2
  #### Sorry, we're fresh out of those.
3
3
  <br/>
4
- #### ...try something from the [Home Page](/)?
4
+ #### ...try something from the [Home Page](/)?
5
+
@@ -12,7 +12,7 @@ const NotFound: React.FC<{
12
12
  }> = ({
13
13
  siteDef
14
14
  }) => (<>
15
- <Main className='h-[700px]'>
15
+ <Main className='xs:h-[100svh] xs:px-8 sm:px-10 sm:h-[700px]'>
16
16
  <ApplyTypography className='mt-[200px] flex flex-col md:gap-8 '>
17
17
  <NotFoundMDX />
18
18
  </ApplyTypography>
@@ -1,18 +1,20 @@
1
1
  import React, { type PropsWithChildren } from 'react'
2
2
 
3
+ import type { Viewport } from 'next'
4
+
3
5
  import Header from '../common/header'
4
6
  import type { SiteDef } from '../types'
5
7
  import getAppRouterBodyFontClasses from './get-app-router-font-classes'
6
8
  import { FacebookPixelHead, FacebookPixel } from './analytics/pixel-analytics'
7
9
  import { GoogleAnalytics } from '@next/third-parties/google'
8
10
 
9
- // Next 14: https://nextjs.org/docs/app/building-your-application/upgrading/codemods#use-viewport-export
11
+ // Next 14: https://nextjs.org/docs/app/building-your-application/upgrading/codemods#use-viewport-export
10
12
  const viewport = {
11
13
  themeColor: [
12
14
  { media: '(prefers-color-scheme: light)', color: 'white' },
13
15
  { media: '(prefers-color-scheme: dark)', color: 'black' },
14
16
  ],
15
- }
17
+ } satisfies Viewport
16
18
 
17
19
  /*
18
20
  These '.variable' fields are actually autogenerate css classnames that *define* the actual
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/ui",
3
- "version": "0.5.23",
3
+ "version": "1.0.8",
4
4
  "description": "Library that contains shared UI primitives, support for a common design system, and other boilerplate support.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -11,7 +11,7 @@
11
11
  "license": "BSD-3-Clause",
12
12
  "repository": {
13
13
  "type": "git",
14
- "url": "git+https://github.com/hanzoai/ui.git",
14
+ "url": "git+https://github.com/hanzoai/react-sdk.git",
15
15
  "directory": "pkgs/hanzo-ui"
16
16
  },
17
17
  "files": [
@@ -46,6 +46,7 @@
46
46
  "@hookform/resolvers": "^3.3.2",
47
47
  "@next/third-parties": "^14.1.0",
48
48
  "@radix-ui/react-accordion": "^1.1.2",
49
+ "@radix-ui/react-aspect-ratio": "^1.0.3",
49
50
  "@radix-ui/react-avatar": "^1.0.3",
50
51
  "@radix-ui/react-checkbox": "^1.0.4",
51
52
  "@radix-ui/react-dialog": "^1.0.5",
@@ -53,6 +54,7 @@
53
54
  "@radix-ui/react-label": "^2.0.2",
54
55
  "@radix-ui/react-popover": "^1.0.6",
55
56
  "@radix-ui/react-progress": "^1.0.3",
57
+ "@radix-ui/react-radio-group": "^1.1.3",
56
58
  "@radix-ui/react-scroll-area": "^1.0.5",
57
59
  "@radix-ui/react-select": "^2.0.0",
58
60
  "@radix-ui/react-separator": "^1.0.3",
@@ -60,6 +62,8 @@
60
62
  "@radix-ui/react-switch": "^1.0.3",
61
63
  "@radix-ui/react-tabs": "^1.0.4",
62
64
  "@radix-ui/react-toast": "^1.1.5",
65
+ "@radix-ui/react-toggle": "^1.0.3",
66
+ "@radix-ui/react-toggle-group": "^1.0.4",
63
67
  "@tailwindcss/container-queries": "^0.1.1",
64
68
  "class-variance-authority": "^0.7.0",
65
69
  "clsx": "^2.1.0",
@@ -76,20 +80,17 @@
76
80
  "react-intersection-observer": "^9.7.0",
77
81
  "react-social-icons": "^6.4.0",
78
82
  "tailwind-merge": "^2.2.0",
79
- "tailwindcss-animate": "^1.0.6",
80
83
  "tailwindcss-interaction-media": "^0.1.0",
81
84
  "validator": "^13.11.0",
82
85
  "zod": "3.21.4"
83
86
  },
84
87
  "peerDependencies": {
85
- "@next/mdx": "^14.1.0",
86
88
  "next": "^14.1.0",
87
89
  "next-themes": "^0.2.1",
88
90
  "react": "^18.2.0",
89
91
  "react-dom": "^18.2.0"
90
92
  },
91
93
  "devDependencies": {
92
- "@mdx-js/esbuild": "^3.0.0",
93
94
  "@mdx-js/loader": "^3.0.0",
94
95
  "@mdx-js/react": "^3.0.0",
95
96
  "@types/facebook-pixel": "^0.0.30",
@@ -98,11 +99,7 @@
98
99
  "@types/mdx": "^2.0.9",
99
100
  "@types/react": "^18.2.48",
100
101
  "@types/react-dom": "^18.2.18",
101
- "autoprefixer": "^10.4.16",
102
- "path": "^0.12.7",
103
- "postcss": "^8.4.33",
104
- "postcss-import": "^16.0.0",
105
102
  "tailwindcss": "^3.4.1",
106
- "typescript": "^5.3.3"
103
+ "typescript": "5.3.3"
107
104
  }
108
105
  }
@@ -0,0 +1,5 @@
1
+ "use client"
2
+ import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
3
+ const AspectRatio = AspectRatioPrimitive.Root
4
+
5
+ export default AspectRatio
@@ -6,7 +6,7 @@ import { cn } from "../util"
6
6
 
7
7
  const variant = {
8
8
  primary: "bg-primary text-primary-fg hover:bg-primary-hover font-nav whitespace-nowrap not-typography",
9
- secondary: "bg-secondary text-secondary-fg hover:bg-secondary/80 font-nav whitespace-nowrap not-typography",
9
+ secondary: "bg-secondary text-secondary-fg hover:bg-secondary-hover font-nav whitespace-nowrap not-typography",
10
10
  outline: "text-foreground bg-background border border-muted-4 hover:bg-level-1 hover:text-accent hover:border-accent font-nav whitespace-nowrap not-typography",
11
11
  destructive: "bg-destructive text-destructive-fg font-sans whitespace-nowrap hover:bg-destructive-hover",
12
12
  ghost: "text-foreground hover:bg-level-1 hover:text-accent whitespace-nowrap font-sans ",
@@ -16,25 +16,38 @@ const variant = {
16
16
 
17
17
  const size = {
18
18
  link: '',
19
- sm: "h-9 px-3 text-xs ",
19
+ xs: "h-8 px-2 text-xs",
20
+ sm: "h-9 px-3 text-xs",
20
21
  square: 'h-10 py-2 px-2 text-sm aspect-square',
21
22
  default: "h-10 py-2 px-4 text-sm lg:min-w-[220px]",
22
- lg: "h-10 px-8 rounded-lg text-sm md:text-base min-w-0 md:min-w-[260px] lg:min-w-[300px]",
23
+ lg: "h-10 px-8 text-sm md:text-base min-w-0 md:min-w-[260px] lg:min-w-[300px]",
23
24
  icon: "h-10 w-10",
24
25
  }
25
26
 
27
+ const rounded = {
28
+ full: 'rounded-full',
29
+ sm: 'rounded-sm',
30
+ md: 'rounded-md',
31
+ lg: 'rounded-lg',
32
+ xl: 'rounded-xl',
33
+ none: ''
34
+ }
35
+
36
+
26
37
  const buttonVariants = cva(
27
- "flex items-center justify-center rounded-md font-medium transition-colors " +
38
+ "flex items-center justify-center font-medium transition-colors " +
28
39
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 " +
29
40
  "disabled:opacity-50 disabled:pointer-events-none ring-offset-background",
30
41
  {
31
42
  variants: {
32
43
  variant,
33
- size
44
+ size,
45
+ rounded
34
46
  },
35
47
  defaultVariants: {
36
48
  variant: "primary",
37
49
  size: "default",
50
+ rounded: 'md'
38
51
  },
39
52
  }
40
53
  )
@@ -50,11 +63,11 @@ interface ButtonProps extends
50
63
  }
51
64
 
52
65
  const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
53
- ({ className, variant, size, asChild = false, ...props }, ref) => {
66
+ ({ className, variant, size, rounded, asChild = false, ...props }, ref) => {
54
67
  const Comp = asChild ? Slot : "button"
55
68
  return (
56
69
  <Comp
57
- className={cn(buttonVariants({ variant, size, className }))}
70
+ className={cn(buttonVariants({ variant, size, rounded }), className )}
58
71
  ref={ref}
59
72
  {...props}
60
73
  />
@@ -50,7 +50,7 @@ const DialogClose = React.forwardRef<
50
50
  <DialogPrimitive.Close
51
51
  ref={ref}
52
52
  className={cn(
53
- "absolute right-4 top-3 p-1 justify-self-start hover:brightness-105 hover:scale-110 duration-100 ring-1 ring-muted transition bg-secondary-500 hover:text-primary-text focus:outline-none rounded-full items-center",
53
+ "absolute right-4 top-3 p-1 justify-self-start hover:brightness-105 hover:scale-110 duration-100 ring-1 ring-muted transition hover:text- focus:outline-none rounded-full items-center",
54
54
  className
55
55
  )}
56
56
  {...props}
@@ -71,7 +71,7 @@ const DialogContent = React.forwardRef<
71
71
  <DialogPrimitive.Content
72
72
  ref={ref}
73
73
  className={cn(
74
- "fixed z-50 grid w-full gap-4 rounded-t-lg bg-secondary-800 p-4 shadow-lg animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-sm sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",
74
+ "fixed z-50 grid w-full gap-4 rounded-t-lg bg-level-1 p-4 shadow-lg animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-sm sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",
75
75
  className
76
76
  )}
77
77
  {...props}
@@ -118,7 +118,7 @@ const DialogTitle = React.forwardRef<
118
118
  <DialogPrimitive.Title
119
119
  ref={ref}
120
120
  className={cn(
121
- "text-lg font-semibold leading-none tracking-tight text-primary-text",
121
+ "text-lg font-semibold leading-none tracking-tight text-foreground",
122
122
  className
123
123
  )}
124
124
  {...props}
@@ -132,7 +132,7 @@ const DialogDescription = React.forwardRef<
132
132
  >(({ className, ...props }, ref) => (
133
133
  <DialogPrimitive.Description
134
134
  ref={ref}
135
- className={cn("text-sm text-secondary-text", className)}
135
+ className={cn("text-sm text-muted", className)}
136
136
  {...props}
137
137
  />
138
138
  ))
@@ -124,11 +124,18 @@ export {
124
124
  AvatarFallback
125
125
  } from './avatar'
126
126
 
127
+ export { Toggle, toggleVariants } from './toggle'
128
+ export { ToggleGroup, ToggleGroupItem } from './toggle-group'
129
+
130
+
127
131
  export { ScrollArea, ScrollBar } from './scroll-area'
128
132
 
129
133
  export { Toaster } from './toaster'
130
134
  export { useToast, toast } from './use-toast'
135
+ export { RadioGroup, RadioGroupItem } from './radio-group'
131
136
 
137
+ export { default as AspectRatio } from './aspect-ratio'
138
+ export { default as Badge } from './badge'
132
139
  export { default as VideoPlayer } from './video-player'
133
140
  export { default as YouTubeEmbed } from './youtube-embed'
134
141
  export { default as Switch } from './switch'
@@ -141,4 +148,5 @@ export { default as Skeleton } from './skeleton'
141
148
  export { default as InlineIcon } from './inline-icon'
142
149
  export { default as NavItems} from './nav-items'
143
150
  export { default as Main } from './main'
151
+ export { default as ListBox } from './list-box'
144
152
 
@@ -0,0 +1,74 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import { cn } from '../util'
4
+
5
+ function Item<T>({
6
+ value,
7
+ label,
8
+ className,
9
+ onClick,
10
+ first=false,
11
+ last=false,
12
+ selected=false
13
+ }:{
14
+ value: T
15
+ label: string
16
+ className: string
17
+ onClick: (val: T) => void
18
+ first?: boolean
19
+ last?: boolean
20
+ selected?: boolean
21
+ }) {
22
+
23
+ return (
24
+ <div
25
+ className={cn(
26
+ 'font-normal text-muted-1 px-3 py-1 cursor-pointer hover:text-foreground ',
27
+ last ? '' : 'border-b',
28
+ selected ? 'font-semibold text-accent hover:text-accent' : '',
29
+ className
30
+ )}
31
+ onClick={() => {onClick(value)}}
32
+ >
33
+ <span>{label}</span>
34
+ </div>
35
+ )
36
+ }
37
+
38
+ function ListBox<T>({
39
+ values,
40
+ labels,
41
+ onValueChange,
42
+ value,
43
+ isEqual,
44
+ outClx = '',
45
+ itemClx = ''
46
+ }:{
47
+ values: T[]
48
+ labels: string[]
49
+ onValueChange: (val: T) => void
50
+ value: T | undefined
51
+ isEqual: (v1: T, v2: T) => boolean
52
+ outClx?: string
53
+ itemClx?: string
54
+ }): JSX.Element {
55
+
56
+ return (
57
+ <div className={cn('border rounded-md select-none', outClx)} >
58
+ {values.map((val, i) => (
59
+ <Item<T>
60
+ value={val}
61
+ label={labels[i]}
62
+ onClick={onValueChange}
63
+ className={itemClx}
64
+ first={i === 0}
65
+ last={i === values.length - 1}
66
+ selected={value && isEqual(val, value)}
67
+ key={labels[i]}
68
+ />
69
+ ))}
70
+ </div>
71
+ )
72
+ }
73
+
74
+ export default ListBox
@@ -5,11 +5,15 @@ const c = 'max-w-screen-2xl 2xl:w-[1500px] lg:mx-auto ' +
5
5
  'flex flex-col justify-start items-stretch ' +
6
6
  'p-4 md:px-6 lg:px-8 '
7
7
 
8
- const Main: React.FC<PropsWithChildren & { className?: string }> = ({
8
+ const Main: React.FC<PropsWithChildren & {
9
+ id?: string
10
+ className?: string
11
+ }> = ({
9
12
  children,
10
13
  className='',
14
+ id
11
15
  }) => (
12
- <main className={cn(c, className)}>
16
+ <main id={id ?? 'HZO_UI_MAIN'} className={cn(c, className)}>
13
17
  {children}
14
18
  </main>
15
19
  )
@@ -0,0 +1,44 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
5
+ import { Circle } from "lucide-react"
6
+
7
+ import { cn } from "../util"
8
+
9
+ const RadioGroup = React.forwardRef<
10
+ React.ElementRef<typeof RadioGroupPrimitive.Root>,
11
+ React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
12
+ >(({ className, ...props }, ref) => {
13
+ return (
14
+ <RadioGroupPrimitive.Root
15
+ className={cn("grid gap-2", className)}
16
+ {...props}
17
+ ref={ref}
18
+ />
19
+ )
20
+ })
21
+ RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
22
+
23
+ const RadioGroupItem = React.forwardRef<
24
+ React.ElementRef<typeof RadioGroupPrimitive.Item>,
25
+ React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
26
+ >(({ className, ...props }, ref) => {
27
+ return (
28
+ <RadioGroupPrimitive.Item
29
+ ref={ref}
30
+ className={cn(
31
+ "aspect-square h-4 w-4 rounded-full border border-muted text-foreground ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
32
+ className
33
+ )}
34
+ {...props}
35
+ >
36
+ <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
37
+ <Circle className="h-2.5 w-2.5 fill-current text-current" />
38
+ </RadioGroupPrimitive.Indicator>
39
+ </RadioGroupPrimitive.Item>
40
+ )
41
+ })
42
+ RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
43
+
44
+ export { RadioGroup, RadioGroupItem }
@@ -32,7 +32,7 @@ const SheetOverlay = React.forwardRef<
32
32
  SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
33
33
 
34
34
  const sheetVariants = cva(
35
- 'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-300',
35
+ 'fixed z-50 gap-4 bg-background p-3 sm:p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-300',
36
36
  {
37
37
  variants: {
38
38
  side: {
@@ -6,7 +6,7 @@ function Skeleton({
6
6
  }: React.HTMLAttributes<HTMLDivElement>) {
7
7
  return (
8
8
  <div
9
- className={cn('animate-pulse rounded-md bg-muted', className)}
9
+ className={cn('animate-pulse rounded-md bg-level-2', className)}
10
10
  {...props}
11
11
  />
12
12
  )
@@ -0,0 +1,63 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group'
5
+ import type { VariantProps } from 'class-variance-authority'
6
+
7
+ import { cn } from '../util'
8
+ import { toggleVariants } from './toggle'
9
+
10
+ const ToggleGroupContext = React.createContext<
11
+ VariantProps<typeof toggleVariants>
12
+ >({
13
+ size: 'default',
14
+ variant: 'default',
15
+ rounded: 'md'
16
+ })
17
+
18
+ const ToggleGroup = React.forwardRef<
19
+ React.ElementRef<typeof ToggleGroupPrimitive.Root>,
20
+ React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
21
+ VariantProps<typeof toggleVariants>
22
+ >(({ className, variant, size, rounded, children, ...props }, ref) => (
23
+ <ToggleGroupPrimitive.Root
24
+ ref={ref}
25
+ className={cn('flex items-center justify-center gap-1', className)}
26
+ {...props}
27
+ >
28
+ <ToggleGroupContext.Provider value={{ variant, size, rounded }}>
29
+ {children}
30
+ </ToggleGroupContext.Provider>
31
+ </ToggleGroupPrimitive.Root>
32
+ ))
33
+
34
+ ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName
35
+
36
+ const ToggleGroupItem = React.forwardRef<
37
+ React.ElementRef<typeof ToggleGroupPrimitive.Item>,
38
+ React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
39
+ VariantProps<typeof toggleVariants>
40
+ >(({ className, children, variant, size, rounded, ...props }, ref) => {
41
+ const context = React.useContext(ToggleGroupContext)
42
+
43
+ return (
44
+ <ToggleGroupPrimitive.Item
45
+ ref={ref}
46
+ className={cn(
47
+ toggleVariants({
48
+ variant: context.variant || variant,
49
+ size: context.size || size,
50
+ rounded: context.rounded || rounded,
51
+ }),
52
+ className
53
+ )}
54
+ {...props}
55
+ >
56
+ {children}
57
+ </ToggleGroupPrimitive.Item>
58
+ )
59
+ })
60
+
61
+ ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName
62
+
63
+ export { ToggleGroup, ToggleGroupItem }
@@ -0,0 +1,72 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as TogglePrimitive from '@radix-ui/react-toggle'
5
+ import { cva, type VariantProps } from 'class-variance-authority'
6
+
7
+ import { cn } from '../util'
8
+
9
+ const toggleVariants = cva(
10
+ 'inline-flex items-center justify-center text-sm font-medium ' +
11
+ 'ring-offset-background ' +
12
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ' +
13
+ 'focus-visible:ring-offset-2 disabled:pointer-events-none ' +
14
+ 'active:bg-level-3 active:text-accent ',
15
+ {
16
+ variants: {
17
+ variant: {
18
+ default: 'text-muted-1 hover:text-accent ' +
19
+ 'data-[state=off]:bg-level-1 hover:data-[state=off]:text-foreground ' +
20
+ 'data-[state=on]:text-foreground data-[state=on]:bg-level-3 ' +
21
+ 'data-[state=on]:hover:bg-level-3 ',
22
+
23
+ outline: 'border border-muted-3 text-muted-1 ' +
24
+ 'data-[state=off]:bg-level-1 hover:data-[state=off]:text-foreground ' +
25
+ 'data-[state=on]:bg-level-3 data-[state=on]:border-muted data-[state=on]:text-foreground',
26
+ },
27
+ size: {
28
+ default: 'h-10 px-3',
29
+ sm: 'h-9 px-2',
30
+ lg: 'h-11 px-5',
31
+ },
32
+ rounded: {
33
+ full: 'rounded-full',
34
+ sm: 'rounded-sm',
35
+ lsm: 'rounded-l-sm',
36
+ rsm: 'rounded-r-sm',
37
+ md: 'rounded-md',
38
+ lmd: 'rounded-l-md',
39
+ rmd: 'rounded-r-md',
40
+ lg: 'rounded-lg',
41
+ llg: 'rounded-l-lg',
42
+ rlg: 'rounded-r-lg',
43
+ xl: 'rounded-xl',
44
+ lxl: 'rounded-l-xl',
45
+ rxl: 'rounded-r-xl',
46
+ none: 'rounded-none'
47
+ }
48
+
49
+ },
50
+ defaultVariants: {
51
+ variant: 'default',
52
+ size: 'default',
53
+ rounded: 'md'
54
+ },
55
+ }
56
+ )
57
+
58
+ const Toggle = React.forwardRef<
59
+ React.ElementRef<typeof TogglePrimitive.Root>,
60
+ React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
61
+ VariantProps<typeof toggleVariants>
62
+ >(({ className, variant, size, rounded, ...props }, ref) => (
63
+ <TogglePrimitive.Root
64
+ ref={ref}
65
+ className={cn(toggleVariants({ variant, size, rounded} ), className )}
66
+ {...props}
67
+ />
68
+ ))
69
+
70
+ Toggle.displayName = TogglePrimitive.Root.displayName
71
+
72
+ export { Toggle, toggleVariants }
@@ -17,7 +17,7 @@ export const fontFamily = (ignoreTheme: any): {
17
17
  }
18
18
 
19
19
  export const fontSize = {
20
- xxs: ['0.6.5rem', { lineHeight: '0.8rem' }], // very fine print
20
+ xxs: ['0.65rem', { lineHeight: '0.8rem' }], // very fine print
21
21
  xs: ['0.8rem', { lineHeight: '1rem' }], // fine print
22
22
  sm: ['0.9rem', { lineHeight: '1.2rem' }], // 'standard' some news article cards (set manually when using typography-sm)
23
23
  base: ['1rem', { lineHeight: 1.4 }],
@@ -611,6 +611,7 @@ export default {
611
611
  ...breakpoints(theme('screens')),
612
612
  }),
613
613
  minHeight: {
614
+ ...spacing,
614
615
  0: '0px',
615
616
  full: '100%',
616
617
  screen: '100vh',
@@ -618,13 +619,15 @@ export default {
618
619
  max: 'max-content',
619
620
  fit: 'fit-content',
620
621
  },
621
- minWidth: {
622
+ minWidth: ({ theme, breakpoints }) => ({
623
+ ...spacing,
622
624
  0: '0px',
623
625
  full: '100%',
624
626
  min: 'min-content',
625
627
  max: 'max-content',
626
628
  fit: 'fit-content',
627
- },
629
+ ...breakpoints(theme('screens')),
630
+ }),
628
631
  objectPosition: {
629
632
  bottom: 'bottom',
630
633
  center: 'center',
@@ -769,7 +772,10 @@ export default {
769
772
  2: '2',
770
773
  },
771
774
  supports: {},
772
- data: {},
775
+ data: {
776
+ on: 'state~="on"',
777
+ off: 'state~="off"',
778
+ },
773
779
  textColor: ({ theme }) => theme('colors'),
774
780
  textDecorationColor: ({ theme }) => theme('colors'),
775
781
  textDecorationThickness: {
package/types/site-def.ts CHANGED
@@ -7,7 +7,9 @@ interface SiteDef {
7
7
  /** common elements (will auto-select currentAs if it's provide) */
8
8
  /** optional feature element. right-most after 'elements' (any min-w is ignored) */
9
9
  common: LinkDef[]
10
- featured?: LinkDef[]
10
+ featured?: LinkDef[]
11
+ auth?: boolean
12
+ cart?: React.ReactNode
11
13
  }
12
14
 
13
15
  /**