A simple, working demo

This commit is contained in:
Copple committed 2022-04-18 21:54:55 +02:00
1 parent 1b66498f7e
commit 8b33597257
21 files changed
+2714 -88

No files matched your search

+10
View File
@@ -11,6 +11,7 @@
- [Supabase Studio Development Server](#supabase-studio-development-server)
- [Finally](#finally)
- [Community Channels](#community-channels)
- [Monorepo](#monorepo)
## Development Setup
@@ -165,3 +166,12 @@ Did you have an issue, like a merge conflict, or don't know how to open a pull r
## Community Channels
Stuck somewhere? Have any questions? please join the [Discord Community Server](https://discord.supabase.com/) or the [Github Discussions](https://github.com/supabase/supabase/discussions). We are here to help!
## Monorepo
This is a monorepo, using Turborepo. You must be using NPM 7 or higher.
- Install a package: `npm install <package name> -w=<workspace to install in>`. eg:
- `npm install @supabase/ui -w ui`: installs into `./packages/ui`
- `npm install @supabase/ui -w docs`: installs into `./packages/docs`
+2 -2
View File
@@ -1,5 +1,5 @@
const withTM = require("next-transpile-modules")(["ui"]);
const withTM = require('next-transpile-modules')(['ui'])
module.exports = withTM({
reactStrictMode: true,
});
})
+4 -4
View File
@@ -9,18 +9,18 @@
"lint": "next lint"
},
"dependencies": {
"next": "12.0.8",
"next": "12.1.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"ui": "*"
},
"devDependencies": {
"@types/node": "^17.0.12",
"@types/react": "17.0.39",
"config": "*",
"eslint": "7.32.0",
"eslint": "8.9.0",
"next-transpile-modules": "9.0.0",
"tsconfig": "*",
"@types/node": "^17.0.12",
"@types/react": "17.0.37",
"typescript": "^4.5.3"
}
}
-10
View File
@@ -1,10 +0,0 @@
import { Button } from "ui";
export default function Docs() {
return (
<div>
<h1>Docs</h1>
<Button />
</div>
);
}
+1
View File
@@ -0,0 +1 @@
module.exports = require('config/postcss.config')
+30
View File
@@ -0,0 +1,30 @@
const navigation = [
{ name: 'Guides', href: '#', icon: null, current: true },
{ name: 'Reference', href: '#', icon: null, current: false },
{ name: 'Examples', href: '#', icon: null, current: false },
{ name: 'API', href: '#', icon: null, current: false },
{ name: 'Forum', href: '#', icon: null, current: false },
]
function classNames(...classes: string[]) {
return classes.filter(Boolean).join(' ')
}
export default function Sidebar() {
return (
<nav className="space-y-1 px-2">
{navigation.map((item) => (
<a
key={item.name}
href={item.href}
className={classNames(
item.current ? 'bg-indigo-800 text-white' : 'text-indigo-100 hover:bg-indigo-600',
'group flex items-center rounded-md px-2 py-2 text-base font-medium'
)}
>
{item.name}
</a>
))}
</nav>
)
}
+9
View File
@@ -0,0 +1,9 @@
import React from 'react'
import Docs from '.'
import '../styles/tailwind.css'
const Index = () => {
return <Docs />
}
export default Index
+13
View File
@@ -0,0 +1,13 @@
import { Button, Layouts } from 'ui'
import Sidebar from '../components/Sidebar'
export default function Docs() {
return (
<Layouts.SidebarLayout sidebarContent={<Sidebar />}>
<>
<h1>Docs</h1>
<Button />
</>
</Layouts.SidebarLayout>
)
}
+3
View File
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+1
View File
@@ -0,0 +1 @@
module.exports = require('config/tailwind.config')
File renamed without changes.
+2175 -69
View File
File diff suppressed because it is too large. Load diff
+4 -1
View File
@@ -22,7 +22,6 @@
"perf:kong": "ab -t 5 -c 20 -T application/json http://localhost:8000/",
"perf:meta": "ab -t 5 -c 20 -T application/json http://localhost:5555/tables"
},
"dependencies": {},
"devDependencies": {
"@babel/core": "^7.16.0",
"@babel/preset-env": "^7.16.4",
@@ -30,12 +29,16 @@
"@supabase/supabase-js": "^1.28.1",
"@types/jest": "^27.0.3",
"@types/node": "^14.14.14",
"autoprefixer": "^10.4.4",
"axios": "^0.24.0",
"babel-jest": "^27.3.1",
"dotenv": "^10.0.0",
"faker": "^5.5.3",
"jest": "^27.3.1",
"postcss": "^8.4.12",
"prettier": "^2.5.1",
"prettier-plugin-tailwindcss": "^0.1.8",
"tailwindcss": "^3.0.24",
"ts-jest": "^27.0.7",
"ts-node": "^9.1.1",
"turbo": "latest",
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
+7
View File
@@ -0,0 +1,7 @@
module.exports = {
content: ['../../packages/ui/**/*.{ts,tsx}', './src/**/*.{ts,tsx}'],
theme: {
extend: {},
},
plugins: [],
}
+8 -1
View File
@@ -1,2 +1,9 @@
import * as React from "react";
import React from "react";
import SidebarLayout from "./layouts/SidebarLayout";
export * from "./Button";
export const Layouts = {
SidebarLayout,
}
+196
View File
@@ -0,0 +1,196 @@
import { Fragment, useState } from 'react'
import { Dialog, Menu, Transition } from '@headlessui/react'
const userNavigation = [
{ name: 'Your Profile', href: '#' },
{ name: 'Settings', href: '#' },
{ name: 'Sign out', href: '#' },
]
function classNames(...classes: string[]) {
return classes.filter(Boolean).join(' ')
}
export default function SidebarLayout({ children, sidebarContent }: { children: React.ReactNode, sidebarContent: React.ReactNode }) {
const [sidebarOpen, setSidebarOpen] = useState(false)
return (
<>
<div>
<Transition.Root show={sidebarOpen} as={Fragment}>
<Dialog as="div" className="fixed inset-0 z-40 flex md:hidden" onClose={setSidebarOpen}>
<Transition.Child
as={Fragment}
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Dialog.Overlay className="fixed inset-0 bg-gray-600 bg-opacity-75" />
</Transition.Child>
<Transition.Child
as={Fragment}
enter="transition ease-in-out duration-300 transform"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
leave="transition ease-in-out duration-300 transform"
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
>
<div className="relative flex w-full max-w-xs flex-1 flex-col bg-indigo-700 pt-5 pb-4">
<Transition.Child
as={Fragment}
enter="ease-in-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in-out duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="absolute top-0 right-0 -mr-12 pt-2">
<button
type="button"
className="ml-1 flex h-10 w-10 items-center justify-center rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
onClick={() => setSidebarOpen(false)}
>
<span className="sr-only">Close sidebar</span>
{/* <XIcon className="h-6 w-6 text-white" aria-hidden="true" /> */}
</button>
</div>
</Transition.Child>
<div className="flex flex-shrink-0 items-center px-4">
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/workflow-logo-indigo-300-mark-white-text.svg"
alt="Workflow"
/>
</div>
<div className="mt-5 h-0 flex-1 overflow-y-auto">
{sidebarContent}
</div>
</div>
</Transition.Child>
<div className="w-14 flex-shrink-0" aria-hidden="true">
{/* Dummy element to force sidebar to shrink to fit close icon */}
</div>
</Dialog>
</Transition.Root>
{/* Static sidebar for desktop */}
<div className="hidden md:fixed md:inset-y-0 md:flex md:w-64 md:flex-col">
{/* Sidebar component, swap this element with another sidebar if you like */}
<div className="flex flex-grow flex-col overflow-y-auto bg-indigo-700 pt-5">
<div className="flex flex-shrink-0 items-center px-4">
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/workflow-logo-indigo-300-mark-white-text.svg"
alt="Workflow"
/>
</div>
<div className="mt-5 flex flex-1 flex-col">
{sidebarContent}
</div>
</div>
</div>
<div className="flex flex-1 flex-col md:pl-64">
<div className="sticky top-0 z-10 flex h-16 flex-shrink-0 bg-white shadow">
<button
type="button"
className="border-r border-gray-200 px-4 text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500 md:hidden"
onClick={() => setSidebarOpen(true)}
>
<span className="sr-only">Open sidebar</span>M
</button>
<div className="flex flex-1 justify-between px-4">
<div className="flex flex-1">
<form className="flex w-full md:ml-0" action="#" method="GET">
<label htmlFor="search-field" className="sr-only">
Search
</label>
<div className="relative w-full text-gray-400 focus-within:text-gray-600">
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center">
🔎
</div>
<input
id="search-field"
className="block h-full w-full border-transparent py-2 pl-8 pr-3 text-gray-900 placeholder-gray-500 focus:border-transparent focus:placeholder-gray-400 focus:outline-none focus:ring-0 sm:text-sm"
placeholder="Search"
type="search"
name="search"
/>
</div>
</form>
</div>
<div className="ml-4 flex items-center md:ml-6">
<button
type="button"
className="rounded-full bg-white p-1 text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
<span className="sr-only">View notifications</span>
{/* <BellIcon className="h-6 w-6" aria-hidden="true" /> */}
</button>
{/* Profile dropdown */}
<Menu as="div" className="relative ml-3">
<div>
<Menu.Button className="flex max-w-xs items-center rounded-full bg-white text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<span className="sr-only">Open user menu</span>
<img
className="h-8 w-8 rounded-full"
src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
alt=""
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
{userNavigation.map((item) => (
<Menu.Item key={item.name}>
{({ active }) => (
<a
href={item.href}
className={classNames(
active ? 'bg-gray-100' : '',
'block px-4 py-2 text-sm text-gray-700'
)}
>
{item.name}
</a>
)}
</Menu.Item>
))}
</Menu.Items>
</Transition>
</Menu>
</div>
</div>
</div>
<main>
<div className="py-6">
<div className="mx-auto max-w-7xl px-4 sm:px-6 md:px-8">
<h1 className="text-2xl font-semibold text-gray-900">Dashboard</h1>
</div>
<div className="mx-auto max-w-7xl px-4 sm:px-6 md:px-8">
{/* Replace with your content */}
{children}
{/* /End replace */}
</div>
</div>
</main>
</div>
</div>
</>
)
}
+238
View File
@@ -0,0 +1,238 @@
import { Fragment, useState } from 'react'
import { Dialog, Menu, Transition } from '@headlessui/react'
const navigation = [
{ name: 'Dashboard', href: '#', icon: null, current: true },
{ name: 'Team', href: '#', icon: null, current: false },
{ name: 'Projects', href: '#', icon: null, current: false },
{ name: 'Calendar', href: '#', icon: null, current: false },
{ name: 'Documents', href: '#', icon: null, current: false },
{ name: 'Reports', href: '#', icon: null, current: false },
]
const userNavigation = [
{ name: 'Your Profile', href: '#' },
{ name: 'Settings', href: '#' },
{ name: 'Sign out', href: '#' },
]
function classNames(...classes: string[]) {
return classes.filter(Boolean).join(' ')
}
export default function SidebarLayout({children}: {children: React.ReactNode}) {
const [sidebarOpen, setSidebarOpen] = useState(false)
return (
<>
<div>
<Transition.Root show={sidebarOpen} as={Fragment}>
<Dialog as="div" className="fixed inset-0 flex z-40 md:hidden" onClose={setSidebarOpen}>
<Transition.Child
as={Fragment}
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Dialog.Overlay className="fixed inset-0 bg-gray-600 bg-opacity-75" />
</Transition.Child>
<Transition.Child
as={Fragment}
enter="transition ease-in-out duration-300 transform"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
leave="transition ease-in-out duration-300 transform"
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
>
<div className="relative flex-1 flex flex-col max-w-xs w-full pt-5 pb-4 bg-indigo-700">
<Transition.Child
as={Fragment}
enter="ease-in-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in-out duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="absolute top-0 right-0 -mr-12 pt-2">
<button
type="button"
className="ml-1 flex items-center justify-center h-10 w-10 rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
onClick={() => setSidebarOpen(false)}
>
<span className="sr-only">Close sidebar</span>
{/* <XIcon className="h-6 w-6 text-white" aria-hidden="true" /> */}
</button>
</div>
</Transition.Child>
<div className="flex-shrink-0 flex items-center px-4">
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/workflow-logo-indigo-300-mark-white-text.svg"
alt="Workflow"
/>
</div>
<div className="mt-5 flex-1 h-0 overflow-y-auto">
<nav className="px-2 space-y-1">
{navigation.map((item) => (
<a
key={item.name}
href={item.href}
className={classNames(
item.current
? 'bg-indigo-800 text-white'
: 'text-indigo-100 hover:bg-indigo-600',
'group flex items-center px-2 py-2 text-base font-medium rounded-md'
)}
>
{/* <item.icon
className="mr-4 flex-shrink-0 h-6 w-6 text-indigo-300"
aria-hidden="true"
/> */}
{item.name}
</a>
))}
</nav>
</div>
</div>
</Transition.Child>
<div className="flex-shrink-0 w-14" aria-hidden="true">
{/* Dummy element to force sidebar to shrink to fit close icon */}
</div>
</Dialog>
</Transition.Root>
{/* Static sidebar for desktop */}
<div className="hidden md:flex md:w-64 md:flex-col md:fixed md:inset-y-0">
{/* Sidebar component, swap this element with another sidebar if you like */}
<div className="flex flex-col flex-grow pt-5 bg-indigo-700 overflow-y-auto">
<div className="flex items-center flex-shrink-0 px-4">
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/workflow-logo-indigo-300-mark-white-text.svg"
alt="Workflow"
/>
</div>
<div className="mt-5 flex-1 flex flex-col">
<nav className="flex-1 px-2 pb-4 space-y-1">
{navigation.map((item) => (
<a
key={item.name}
href={item.href}
className={classNames(
item.current
? 'bg-indigo-800 text-white'
: 'text-indigo-100 hover:bg-indigo-600',
'group flex items-center px-2 py-2 text-sm font-medium rounded-md'
)}
>
{item.name}
</a>
))}
</nav>
</div>
</div>
</div>
<div className="md:pl-64 flex flex-col flex-1">
<div className="sticky top-0 z-10 flex-shrink-0 flex h-16 bg-white shadow">
<button
type="button"
className="px-4 border-r border-gray-200 text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500 md:hidden"
onClick={() => setSidebarOpen(true)}
>
<span className="sr-only">Open sidebar</span>M
</button>
<div className="flex-1 px-4 flex justify-between">
<div className="flex-1 flex">
<form className="w-full flex md:ml-0" action="#" method="GET">
<label htmlFor="search-field" className="sr-only">
Search
</label>
<div className="relative w-full text-gray-400 focus-within:text-gray-600">
<div className="absolute inset-y-0 left-0 flex items-center pointer-events-none">
Icon
</div>
<input
id="search-field"
className="block w-full h-full pl-8 pr-3 py-2 border-transparent text-gray-900 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-0 focus:border-transparent sm:text-sm"
placeholder="Search"
type="search"
name="search"
/>
</div>
</form>
</div>
<div className="ml-4 flex items-center md:ml-6">
<button
type="button"
className="bg-white p-1 rounded-full text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
<span className="sr-only">View notifications</span>
{/* <BellIcon className="h-6 w-6" aria-hidden="true" /> */}
</button>
{/* Profile dropdown */}
<Menu as="div" className="ml-3 relative">
<div>
<Menu.Button className="max-w-xs bg-white flex items-center text-sm rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<span className="sr-only">Open user menu</span>
<img
className="h-8 w-8 rounded-full"
src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
alt=""
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
{userNavigation.map((item) => (
<Menu.Item key={item.name}>
{({ active }) => (
<a
href={item.href}
className={classNames(
active ? 'bg-gray-100' : '',
'block px-4 py-2 text-sm text-gray-700'
)}
>
{item.name}
</a>
)}
</Menu.Item>
))}
</Menu.Items>
</Transition>
</Menu>
</div>
</div>
</div>
<main>
<div className="py-6">
<div className="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
<h1 className="text-2xl font-semibold text-gray-900">Dashboard</h1>
</div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
{/* Replace with your content */}
{children}
{/* /End replace */}
</div>
</div>
</main>
</div>
</div>
</>
)
}
+5 -1
View File
@@ -4,11 +4,15 @@
"main": "./index.tsx",
"types": "./index.tsx",
"license": "MIT",
"dependencies": {
"@headlessui/react": "^1.5.0",
"@supabase/ui": "^0.37.0-alpha.50"
},
"devDependencies": {
"@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11",
"tsconfig": "*",
"config": "*",
"tsconfig": "*",
"typescript": "^4.5.3"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = require('config/postcss.config')
+1
View File
@@ -0,0 +1 @@
module.exports = require('config/tailwind.config')