mirror of https://github.com/sunface/rust-course
parent
42db49c060
commit
3a1c406da4
@ -0,0 +1,123 @@
|
||||
import {
|
||||
chakra,
|
||||
Flex,
|
||||
Button,
|
||||
IconButton,
|
||||
useColorMode,
|
||||
useColorModeValue,
|
||||
Box,
|
||||
useRadioGroup,
|
||||
HStack,
|
||||
Input
|
||||
} from "@chakra-ui/react"
|
||||
import { useViewportScroll } from "framer-motion"
|
||||
import NextLink from "next/link"
|
||||
import React from "react"
|
||||
import { FaMoon, FaSun } from "react-icons/fa"
|
||||
import Logo, { LogoIcon } from "src/components/logo"
|
||||
import RadioCard from "components/radio-card"
|
||||
import { EditMode } from "src/types/editor"
|
||||
|
||||
|
||||
|
||||
|
||||
function HeaderContent(props:any) {
|
||||
const { toggleColorMode: toggleMode } = useColorMode()
|
||||
const text = useColorModeValue("dark", "light")
|
||||
const SwitchIcon = useColorModeValue(FaMoon, FaSun)
|
||||
|
||||
const editOptions = [EditMode.Edit,EditMode.Preview]
|
||||
const { getRootProps, getRadioProps } = useRadioGroup({
|
||||
name: "framework",
|
||||
defaultValue: EditMode.Edit,
|
||||
onChange: (v) => {
|
||||
props.changeEditMode(v)
|
||||
},
|
||||
})
|
||||
const group = getRootProps()
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex w="100%" h="100%" align="center" justify="space-between" px={{ base: "4", md: "6" }}>
|
||||
<Flex align="center">
|
||||
<NextLink href="/" passHref>
|
||||
<chakra.a display={{ base: "none", md: "block" }} style={{ marginTop: '-5px' }} aria-label="Chakra UI, Back to homepage">
|
||||
<Logo width="130" />
|
||||
</chakra.a>
|
||||
</NextLink>
|
||||
<NextLink href="/" passHref>
|
||||
<chakra.a display={{ base: "block", md: "none" }} aria-label="Chakra UI, Back to homepage">
|
||||
<LogoIcon />
|
||||
</chakra.a>
|
||||
</NextLink>
|
||||
</Flex>
|
||||
<Box>
|
||||
<Input value={props.ar.title} placeholder="Title..." onChange={props.changeTitle} focusBorderColor={useColorModeValue('teal.400','teal.100')} variant="flushed"/>
|
||||
</Box>
|
||||
<HStack {...group}>
|
||||
{editOptions.map((value) => {
|
||||
const radio = getRadioProps({ value })
|
||||
return (
|
||||
<RadioCard key={value} {...radio} bg="teal" color="white">
|
||||
{value}
|
||||
</RadioCard>
|
||||
)
|
||||
})}
|
||||
</HStack>
|
||||
<Box
|
||||
color={useColorModeValue("gray.500", "gray.400")}
|
||||
>
|
||||
<IconButton
|
||||
size="md"
|
||||
fontSize="lg"
|
||||
aria-label={`Switch to ${text} mode`}
|
||||
variant="ghost"
|
||||
color="current"
|
||||
ml={{ base: "0", md: "1" }}
|
||||
onClick={toggleMode}
|
||||
_focus={null}
|
||||
icon={<SwitchIcon />}
|
||||
/>
|
||||
<Button layerStyle="colorButton" ml="2" onClick={props.publish}>发布</Button>
|
||||
</Box>
|
||||
</Flex>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function EditorNav(props) {
|
||||
const bg = useColorModeValue("white", "gray.800")
|
||||
const ref = React.useRef<HTMLHeadingElement>()
|
||||
const [y, setY] = React.useState(0)
|
||||
const { height = 0 } = ref.current?.getBoundingClientRect() ?? {}
|
||||
|
||||
const { scrollY } = useViewportScroll()
|
||||
React.useEffect(() => {
|
||||
return scrollY.onChange(() => setY(scrollY.get()))
|
||||
}, [scrollY])
|
||||
|
||||
return (
|
||||
<chakra.header
|
||||
ref={ref}
|
||||
shadow={y > height ? "sm" : undefined}
|
||||
transition="box-shadow 0.2s"
|
||||
pos="fixed"
|
||||
top="0"
|
||||
zIndex="3"
|
||||
bg={bg}
|
||||
left="0"
|
||||
right="0"
|
||||
borderTop="4px solid"
|
||||
borderTopColor="teal.400"
|
||||
width="full"
|
||||
>
|
||||
<chakra.div height="4.5rem" mx="auto" maxW="1200px">
|
||||
<HeaderContent {...props} />
|
||||
</chakra.div>
|
||||
</chakra.header>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditorNav
|
||||
|
@ -0,0 +1,26 @@
|
||||
import { chakra } from "@chakra-ui/react"
|
||||
import Container from "components/container"
|
||||
import SEO from "components/seo"
|
||||
import siteConfig from "configs/site-config"
|
||||
import Nav from "layouts/nav/nav"
|
||||
import PageContainer from "layouts/page-container"
|
||||
import { useRouter } from "next/router"
|
||||
import React from "react"
|
||||
|
||||
const UserPage = () => {
|
||||
const router = useRouter()
|
||||
return (
|
||||
<>
|
||||
<SEO
|
||||
title={siteConfig.seo.title}
|
||||
description={siteConfig.seo.description}
|
||||
/>
|
||||
<Nav />
|
||||
<PageContainer>
|
||||
<chakra.h1>{router.query.username}的博文{router.query.post_slug}</chakra.h1>
|
||||
</PageContainer>
|
||||
</>
|
||||
)}
|
||||
|
||||
export default UserPage
|
||||
|
@ -0,0 +1,26 @@
|
||||
import { chakra } from "@chakra-ui/react"
|
||||
import Container from "components/container"
|
||||
import SEO from "components/seo"
|
||||
import siteConfig from "configs/site-config"
|
||||
import Nav from "layouts/nav/nav"
|
||||
import PageContainer from "layouts/page-container"
|
||||
import { useRouter } from "next/router"
|
||||
import React from "react"
|
||||
|
||||
const UserPage = () => {
|
||||
const router = useRouter()
|
||||
return (
|
||||
<>
|
||||
<SEO
|
||||
title={siteConfig.seo.title}
|
||||
description={siteConfig.seo.description}
|
||||
/>
|
||||
<Nav />
|
||||
<PageContainer>
|
||||
<chakra.h1>{router.query.username}'s home</chakra.h1>
|
||||
</PageContainer>
|
||||
</>
|
||||
)}
|
||||
|
||||
export default UserPage
|
||||
|
@ -0,0 +1,83 @@
|
||||
import { Box, Button,createStandaloneToast} from '@chakra-ui/react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { MarkdownEditor } from 'components/markdown-editor/editor';
|
||||
import PageContainer from 'layouts/page-container';
|
||||
import EditorNav from 'layouts/editor-nav'
|
||||
import { EditMode } from 'src/types/editor';
|
||||
import { MarkdownRender } from 'components/markdown-editor/render';
|
||||
import { Post } from 'src/types/posts';
|
||||
import { requestApi } from 'utils/axios/request';
|
||||
import { useRouter } from 'next/router';
|
||||
const toast = createStandaloneToast()
|
||||
|
||||
const content = `
|
||||
# test原创
|
||||
`
|
||||
|
||||
function PostEditPage() {
|
||||
const router = useRouter()
|
||||
const {id} = router.query
|
||||
const [editMode, setEditMode] = useState(EditMode.Edit)
|
||||
const [ar,setAr] = useState({
|
||||
md: content,
|
||||
title: ''
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (id && id !== 'new') {
|
||||
requestApi.get(`/editor/post/${id}`).then(res => setAr(res.data))
|
||||
}
|
||||
},[id])
|
||||
const onChange = newMd => {
|
||||
setAr({
|
||||
...ar,
|
||||
md: newMd
|
||||
})
|
||||
}
|
||||
|
||||
const publish = async () => {
|
||||
await requestApi.post(`/editor/post`, ar)
|
||||
toast({
|
||||
description: "发布成功",
|
||||
status: "success",
|
||||
duration: 2000,
|
||||
isClosable: true,
|
||||
})
|
||||
router.push('/editor/posts')
|
||||
}
|
||||
|
||||
console.log(ar)
|
||||
return (
|
||||
<PageContainer
|
||||
nav={<EditorNav
|
||||
ar={ar}
|
||||
changeEditMode={(v) => setEditMode(v)}
|
||||
changeTitle={(e) => {setAr({...ar, title: e.target.value})}}
|
||||
publish={() => publish()}
|
||||
/>}
|
||||
>
|
||||
<Box style={{ height: 'calc(100vh - 145px)' }}>
|
||||
{editMode === EditMode.Edit ?
|
||||
<MarkdownEditor
|
||||
options={{
|
||||
overrides: {
|
||||
Button: {
|
||||
component: Button,
|
||||
},
|
||||
},
|
||||
}}
|
||||
onChange={(md) => onChange(md)}
|
||||
md={ar.md}
|
||||
/> :
|
||||
<Box height="100%" p="6">
|
||||
<MarkdownRender md={ar.md} />
|
||||
</Box>
|
||||
}
|
||||
</Box>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export default PostEditPage
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
package api
|
@ -1,44 +1,92 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/imdotdev/im.dev/server/internal/posts"
|
||||
"github.com/imdotdev/im.dev/server/internal/session"
|
||||
"github.com/imdotdev/im.dev/server/pkg/common"
|
||||
"github.com/imdotdev/im.dev/server/pkg/e"
|
||||
)
|
||||
|
||||
func GetEditorArticles(c *gin.Context) {
|
||||
func GetEditorPosts(c *gin.Context) {
|
||||
user := session.CurrentUser(c)
|
||||
ars, err := posts.UserArticles(int64(user.ID))
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
logger.Warn("get user articles error", "error", err)
|
||||
c.JSON(http.StatusInternalServerError, common.RespInternalError())
|
||||
ars, err := posts.UserPosts(int64(user.ID))
|
||||
if err != nil {
|
||||
c.JSON(err.Status, common.RespError(err.Message))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, common.RespSuccess(ars))
|
||||
}
|
||||
|
||||
func PostEditorArticle(c *gin.Context) {
|
||||
err := posts.PostArticle(c)
|
||||
func SubmitPost(c *gin.Context) {
|
||||
err := posts.SubmitPost(c)
|
||||
if err != nil {
|
||||
logger.Warn("post article error", "error", err)
|
||||
c.JSON(400, common.RespError(err.Error()))
|
||||
logger.Warn("submit post error", "error", err)
|
||||
c.JSON(err.Status, common.RespError(err.Message))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, common.RespSuccess(nil))
|
||||
}
|
||||
|
||||
func DeleteEditorArticle(c *gin.Context) {
|
||||
err := posts.DeleteArticle(c)
|
||||
func DeletePost(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if id == 0 {
|
||||
c.JSON(http.StatusBadRequest, common.RespError(e.ParamInvalid))
|
||||
return
|
||||
}
|
||||
|
||||
user := session.CurrentUser(c)
|
||||
creator, err := posts.GetPostCreator(id)
|
||||
if err != nil {
|
||||
logger.Warn("delete article error", "error", err)
|
||||
c.JSON(400, common.RespError(err.Error()))
|
||||
c.JSON(err.Status, common.RespError(err.Message))
|
||||
return
|
||||
}
|
||||
|
||||
if user.ID != creator {
|
||||
c.JSON(http.StatusForbidden, common.RespError(e.NoPermission))
|
||||
return
|
||||
}
|
||||
|
||||
err = posts.DeletePost(id)
|
||||
if err != nil {
|
||||
c.JSON(err.Status, common.RespError(err.Message))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, common.RespSuccess(nil))
|
||||
}
|
||||
|
||||
func GetEditorPost(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
fmt.Println(c.Param("id"))
|
||||
if id == 0 {
|
||||
c.JSON(http.StatusBadRequest, common.RespError(e.ParamInvalid))
|
||||
return
|
||||
}
|
||||
|
||||
user := session.CurrentUser(c)
|
||||
creator, err := posts.GetPostCreator(id)
|
||||
if err != nil {
|
||||
c.JSON(err.Status, common.RespError(err.Message))
|
||||
return
|
||||
}
|
||||
|
||||
if user.ID != creator {
|
||||
c.JSON(http.StatusForbidden, common.RespError(e.NoPermission))
|
||||
return
|
||||
}
|
||||
|
||||
ar, err := posts.GetPost(id)
|
||||
if err != nil {
|
||||
c.JSON(err.Status, common.RespError(err.Message))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, common.RespSuccess(ar))
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package e
|
||||
|
||||
type Error struct {
|
||||
Status int
|
||||
Message string
|
||||
}
|
||||
|
||||
func New(status int, msg string) *Error {
|
||||
return &Error{
|
||||
Status: status,
|
||||
Message: msg,
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
DB = "数据库异常"
|
||||
Internal = "服务器内部错误"
|
||||
NeedLogin = "你需要登录才能访问该页面"
|
||||
NoEditorPermission = "只有编辑角色才能执行此操作"
|
||||
ParamInvalid = "请求参数不正确"
|
||||
NotFound = "目标不存在"
|
||||
NoPermission = "你没有权限执行此操作"
|
||||
)
|
@ -1,7 +0,0 @@
|
||||
package errcode
|
||||
|
||||
const DB = "database error"
|
||||
const Internal = "server internal error"
|
||||
const NeedLogin = "你需要登录才能访问该页面"
|
||||
const NoEditorPermission = "只有编辑角色才能执行此操作"
|
||||
const ParamInvalid = "请求参数不正确"
|
@ -0,0 +1,12 @@
|
||||
package utils
|
||||
|
||||
import "github.com/golang/snappy"
|
||||
|
||||
func Compress(s string) []byte {
|
||||
encoded := snappy.Encode(nil, []byte(s))
|
||||
return encoded
|
||||
}
|
||||
|
||||
func Uncompress(b []byte) ([]byte, error) {
|
||||
return snappy.Decode(nil, b)
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
import React from "react"
|
||||
import {chakra, Heading, VStack, Text, HStack,Button, Flex,PropsOf } from "@chakra-ui/react"
|
||||
import { Article } from "src/types/posts"
|
||||
import moment from 'moment'
|
||||
import { requestApi } from "utils/axios/request"
|
||||
|
||||
type Props = PropsOf<typeof chakra.div> & {
|
||||
article: Article
|
||||
showActions: boolean
|
||||
onEdit?: any
|
||||
onDelete?: any
|
||||
}
|
||||
|
||||
|
||||
export const TextArticleCard= (props:Props) =>{
|
||||
const {article,showActions,onEdit,onDelete, ...rest} = props
|
||||
|
||||
const gap = moment(article.created).fromNow()
|
||||
const onDeleteArticle = async () => {
|
||||
await requestApi.delete(`/editor/article/${article.id}`)
|
||||
onDelete()
|
||||
}
|
||||
return (
|
||||
<Flex justifyContent="space-between" {...rest}>
|
||||
<VStack alignItems="left">
|
||||
<Heading size="sm">{props.article.title}</Heading>
|
||||
<Text fontSize=".9rem">发布于{gap}</Text>
|
||||
</VStack>
|
||||
{props.showActions && <HStack>
|
||||
<Button size="sm" colorScheme="teal" variant="outline" onClick={onEdit}>Edit</Button>
|
||||
<Button size="sm" onClick={onDeleteArticle}>Delete</Button>
|
||||
</HStack>}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export default TextArticleCard
|
@ -0,0 +1,45 @@
|
||||
import React from 'react';
|
||||
import 'highlight.js/styles/atom-one-dark.css';
|
||||
import { chakra,PropsOf } from '@chakra-ui/react';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import 'react-markdown-editor-lite/lib/index.css';
|
||||
|
||||
const MdEditor = dynamic(() => import('react-markdown-editor-lite'), {
|
||||
ssr: false
|
||||
});
|
||||
|
||||
|
||||
|
||||
type Props = PropsOf<typeof chakra.div> & {
|
||||
md: string
|
||||
onChange: any
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function MarkdownEditor(props) {
|
||||
function handleEditorChange({html, text}) {
|
||||
props.onChange(text)
|
||||
}
|
||||
|
||||
return (
|
||||
<MdEditor
|
||||
width="100%"
|
||||
value={props.md}
|
||||
style={{ height: "102%" }}
|
||||
renderHTML={_ => null}
|
||||
onChange={handleEditorChange}
|
||||
config={{
|
||||
canView: false,
|
||||
view:{
|
||||
menu: true,
|
||||
md: true,
|
||||
html: false,
|
||||
fullScreen: true,
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
import Markdown from 'markdown-to-jsx';
|
||||
import hljs from 'highlight.js';
|
||||
import 'highlight.js/styles/atom-one-dark.css';
|
||||
import { chakra,PropsOf } from '@chakra-ui/react';
|
||||
|
||||
type Props = PropsOf<typeof chakra.div> & {
|
||||
md: string
|
||||
}
|
||||
|
||||
|
||||
export function MarkdownRender({ md,...rest }:Props) {
|
||||
const rootRef = useRef<HTMLDivElement>();
|
||||
|
||||
useEffect(() => {
|
||||
rootRef.current.querySelectorAll('pre code').forEach((block) => {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
}, [md]);
|
||||
|
||||
return (
|
||||
<div ref={rootRef} style={{height:'100%'}}>
|
||||
<Markdown children={md} {...rest} style={{height:'100%',fontSize: '14px'}}></Markdown>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
import React from "react"
|
||||
import {chakra, Heading, VStack, Text, HStack,Button, Flex,PropsOf, Tag } from "@chakra-ui/react"
|
||||
import { Post } from "src/types/posts"
|
||||
import moment from 'moment'
|
||||
|
||||
type Props = PropsOf<typeof chakra.div> & {
|
||||
post: Post
|
||||
showActions: boolean
|
||||
onEdit?: any
|
||||
onDelete?: any
|
||||
}
|
||||
|
||||
|
||||
export const TextPostCard= (props:Props) =>{
|
||||
const {post,showActions,onEdit,onDelete, ...rest} = props
|
||||
|
||||
const gap = moment(post.created).fromNow()
|
||||
return (
|
||||
<Flex justifyContent="space-between" {...rest}>
|
||||
<VStack alignItems="left" as="a" href={post.url ? post.url : `/${post.creator.username}/${post.slug}`}>
|
||||
<Heading size="sm" display="flex" alignItems="center">
|
||||
{post.url ? <Tag size="sm" mr="2">外部</Tag> : <Tag size="sm" mr="2">原创</Tag>}
|
||||
{post.title}
|
||||
</Heading>
|
||||
<Text fontSize=".9rem">发布于{gap}</Text>
|
||||
</VStack>
|
||||
{props.showActions && <HStack>
|
||||
<Button size="sm" colorScheme="teal" variant="outline" onClick={onEdit}>Edit</Button>
|
||||
<Button size="sm" onClick={props.onDelete}>Delete</Button>
|
||||
</HStack>}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export default TextPostCard
|
@ -0,0 +1,35 @@
|
||||
import { Box, useRadio } from "@chakra-ui/react"
|
||||
|
||||
function RadioCard(props) {
|
||||
const { getInputProps, getCheckboxProps} = useRadio(props)
|
||||
|
||||
const input = getInputProps()
|
||||
const checkbox = getCheckboxProps()
|
||||
|
||||
return (
|
||||
<Box as="label">
|
||||
<input {...input} />
|
||||
<Box
|
||||
{...checkbox}
|
||||
cursor="pointer"
|
||||
borderWidth="1px"
|
||||
borderRadius="md"
|
||||
boxShadow="md"
|
||||
_checked={{
|
||||
bg: props.bg,
|
||||
color: props.color,
|
||||
borderColor: props.bg,
|
||||
}}
|
||||
_focus={{
|
||||
boxShadow: "outline",
|
||||
}}
|
||||
px={2}
|
||||
py={1}
|
||||
>
|
||||
{props.children}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default RadioCard
|
@ -0,0 +1,4 @@
|
||||
export enum EditMode {
|
||||
Edit = '编辑',
|
||||
Preview = '预览'
|
||||
}
|
@ -1,11 +1,14 @@
|
||||
import {User} from './session'
|
||||
|
||||
export interface Article {
|
||||
export interface Post {
|
||||
id?: number
|
||||
slug?: string
|
||||
creator?: User
|
||||
title: string
|
||||
url: string
|
||||
cover: string
|
||||
creatorId?: number
|
||||
title?: string
|
||||
md?: string
|
||||
url?: string
|
||||
cover?: string
|
||||
brief?: string
|
||||
created?: string
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
export default function layerStyles(theme) {
|
||||
return {
|
||||
textSecondary: {
|
||||
opacity: "0.8"
|
||||
},
|
||||
colorButton: {
|
||||
bg: "linear-gradient(270deg,#0076f5,#0098a3)",
|
||||
color: "white",
|
||||
_hover: {
|
||||
cursor: 'pointer'
|
||||
},
|
||||
_focus: null
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import { mode } from "@chakra-ui/theme-tools"
|
||||
import userCustomTheme from "./user-custom"
|
||||
|
||||
export default function reactMarkdownStyles(props) {
|
||||
return {
|
||||
'.rc-md-editor': {
|
||||
borderWidth: '0px',
|
||||
background: 'transparent',
|
||||
textarea: {
|
||||
background: 'transparent!important',
|
||||
color: mode("#2D3748!important", "rgba(255, 255, 255, 0.92)!important")(props),
|
||||
},
|
||||
'.rc-md-navigation' :{
|
||||
background: 'transparent',
|
||||
borderBottomColor: mode(userCustomTheme.borderColor.light, userCustomTheme.borderColor.dark + '!important')(props),
|
||||
'.navigation-nav' :{
|
||||
'.button': {
|
||||
color: mode("#2D3748!important", "rgba(255, 255, 255, 0.92)!important")(props),
|
||||
}
|
||||
}
|
||||
},
|
||||
'.drop-wrap' : {
|
||||
background: mode("white", "#1A202C")(props),
|
||||
borderWidth: '1px',
|
||||
borderColor: mode(userCustomTheme.borderColor.light, userCustomTheme.borderColor.dark + '!important')(props),
|
||||
},
|
||||
'.header-list .list-item': {
|
||||
_hover: {
|
||||
background: 'transparent'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import { extendTheme } from "@chakra-ui/react"
|
||||
const theme = extendTheme()
|
||||
const userCustomTheme = {
|
||||
borderColor: {
|
||||
light: theme.colors.gray['200'],
|
||||
dark: theme.colors.whiteAlpha['300']
|
||||
}
|
||||
}
|
||||
|
||||
export default userCustomTheme
|
Loading…
Reference in new issue