diff --git a/apps/website/src/docs/components/mdx-components/codeblock/frame-provider.tsx b/apps/website/src/docs/components/mdx-components/codeblock/frame-provider.tsx
index cd68ac99c..cd8dda733 100644
--- a/apps/website/src/docs/components/mdx-components/codeblock/frame-provider.tsx
+++ b/apps/website/src/docs/components/mdx-components/codeblock/frame-provider.tsx
@@ -5,7 +5,7 @@ import weakMemoize from '@emotion/weak-memoize'
import { FrameContextConsumer, useFrame } from 'react-frame-component'
import { SaasProvider } from '@saas-ui/react'
import theme from '../../../../styles/theme'
-import { GlobalStyle, useColorMode } from '@chakra-ui/system'
+import { ColorMode, GlobalStyle, useColorMode } from '@chakra-ui/system'
let memoizedCreateCacheWithContainer = weakMemoize((container: Node) => {
let newCache = createCache({ key: 'frame', container })
@@ -26,7 +26,7 @@ export const FrameProvider = (props) => {
-
+
{props.children}
)
@@ -35,37 +35,100 @@ export const FrameProvider = (props) => {
)
}
-const ColorModeScript = () => {
- const { document, window } = useFrame()
+const ColorModeScript = ({ colorMode }) => {
+ const { getSystemTheme, setClassName, setDataset } = useColorModeUtils()
+
+ const setColorMode = React.useCallback(
+ (value: ColorMode | 'system') => {
+ //
+ const resolved = value === 'system' ? getSystemTheme() : value
+
+ setClassName(resolved === 'dark')
+ setDataset(resolved)
+ },
+ [getSystemTheme, setClassName, setDataset]
+ )
React.useEffect(() => {
- try {
- if (!document || !window) return
- var a = function (c) {
- var v = '(prefers-color-scheme: dark)',
- h = window.matchMedia(v).matches ? 'dark' : 'light',
- r = c === 'system' ? h : c,
- o = document.documentElement,
- s = document.body,
- l = 'chakra-ui-light',
- d = 'chakra-ui-dark',
- i = r === 'dark'
- return (
- s.classList.add(i ? d : l),
- s.classList.remove(i ? l : d),
- (o.style.colorScheme = r),
- (o.dataset.theme = r),
- r
- )
- },
- n = a,
- m = 'dark',
- e = 'chakra-ui-color-mode',
- t = localStorage.getItem(e)
- t ? a(t) : localStorage.setItem(e, a(m))
- } catch (a) {
- console.log(a)
- }
- }, [])
+ setColorMode(colorMode)
+ }, [colorMode, setColorMode])
+
return null
}
+
+const classNames = {
+ light: 'chakra-ui-light',
+ dark: 'chakra-ui-dark',
+}
+
+type UtilOptions = {
+ preventTransition?: boolean
+ document?: Document
+}
+
+function useColorModeUtils(options: UtilOptions = {}) {
+ const { preventTransition = true } = options
+
+ const frame = useFrame()
+
+ const doc = frame?.document ?? document
+ const win = frame?.window ?? window
+
+ const utils = {
+ setDataset: (value: ColorMode) => {
+ const cleanup = preventTransition ? utils.preventTransition() : undefined
+ doc.documentElement.dataset.theme = value
+ doc.documentElement.style.colorScheme = value
+ cleanup?.()
+ },
+ setClassName(dark: boolean) {
+ doc.body.classList.add(dark ? classNames.dark : classNames.light)
+ doc.body.classList.remove(dark ? classNames.light : classNames.dark)
+ },
+ query() {
+ return win.matchMedia('(prefers-color-scheme: dark)')
+ },
+ getSystemTheme(fallback?: ColorMode) {
+ const dark = utils.query().matches ?? fallback === 'dark'
+ return dark ? 'dark' : 'light'
+ },
+ addListener(fn: (cm: ColorMode) => unknown) {
+ const mql = utils.query()
+ const listener = (e: MediaQueryListEvent) => {
+ fn(e.matches ? 'dark' : 'light')
+ }
+
+ if (typeof mql.addListener === 'function') mql.addListener(listener)
+ else mql.addEventListener('change', listener)
+
+ return () => {
+ if (typeof mql.removeListener === 'function')
+ mql.removeListener(listener)
+ else mql.removeEventListener('change', listener)
+ }
+ },
+ preventTransition() {
+ const css = document.createElement('style')
+ css.appendChild(
+ document.createTextNode(
+ `*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}`
+ )
+ )
+ doc.head.appendChild(css)
+
+ return () => {
+ // force a reflow
+ ;(() => win.getComputedStyle(doc.body))()
+
+ // wait for next tick
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ doc.head.removeChild(css)
+ })
+ })
+ }
+ },
+ }
+
+ return utils
+}
diff --git a/apps/website/src/docs/components/mdx-components/codeblock/react-live-block.tsx b/apps/website/src/docs/components/mdx-components/codeblock/react-live-block.tsx
index 9d95f0a29..00c34b4bf 100644
--- a/apps/website/src/docs/components/mdx-components/codeblock/react-live-block.tsx
+++ b/apps/website/src/docs/components/mdx-components/codeblock/react-live-block.tsx
@@ -162,7 +162,7 @@ function ReactLiveBlock({
}, [frameRef, inline])
const frame = inline ? (
-
+
) : (
setFrameRef(ref)} width="100%" height="100%">
@@ -200,11 +200,15 @@ function ReactLiveBlock({
width="4px"
bg="muted"
mx="2"
- height="100px"
+ height="80px"
rounded="full"
_hover={{
bg: 'primary.500',
}}
+ _focus={{
+ outline: 'none',
+ bg: 'primary.500',
+ }}
/>
diff --git a/apps/website/src/pages/docs/components/authentication/auth/usage.mdx b/apps/website/src/pages/docs/components/authentication/auth/usage.mdx
index d4515e9d3..6b284d68a 100644
--- a/apps/website/src/pages/docs/components/authentication/auth/usage.mdx
+++ b/apps/website/src/pages/docs/components/authentication/auth/usage.mdx
@@ -49,14 +49,15 @@ If you need more flexiblity it's possible to use these components directly.
The default authentication strategy is `magiclink`.
```jsx center=true height=550px
+import { SaasUILogo } from '@saas-ui/assets'
import { Card, CardHeader, CardBody } from '@chakra-ui/react'
import { Auth } from '@saas-ui/auth'
export default function AuthPage() {
return (
-
-
+
+
@@ -71,14 +72,15 @@ export default function AuthPage() {
Using the `type` prop you can switch to password login.
```jsx center=true height=550px
+import { SaasUILogo } from '@saas-ui/assets'
import { Card, CardHeader, CardBody } from '@chakra-ui/react'
import { Auth } from '@saas-ui/auth'
export default function AuthPage() {
return (
-
-
+
+
@@ -93,14 +95,15 @@ export default function AuthPage() {
Using the `providers` prop you can add social login buttons.
```jsx center=true height=550px
+import { SaasUILogo } from '@saas-ui/assets'
import { Card, CardHeader, CardBody } from '@chakra-ui/react'
import { Auth } from '@saas-ui/auth'
export default function AuthPage() {
return (
-
-
+
+
-
-
+
+
-
-
+
+
@@ -173,6 +178,7 @@ export default function AuthPage() {
Use the `redirectTo` prop to redirect the user after login.
```jsx center=true height=550px
+import { SaasUILogo } from '@saas-ui/assets'
import { Card, CardHeader, CardBody } from '@chakra-ui/react'
import { useSnackbar } from '@saas-ui/react'
import { Auth } from '@saas-ui/auth'
@@ -187,8 +193,8 @@ const getAbsoluteUrl = (path: string) => {
export default function AuthPage() {
return (
-
-
+
+
{
export default function AuthPage() {
return (
-
-
+
+
{
export default function AuthPage() {
return (
-
-
+
+
{
`useHotkeysShortcut` returns the command value and can be used to show the key combinations to your users.
-```jsx inline=true live=false
+```jsx center=true inline=true live=false
import { Kbd } from '@chakra-ui/react'
import { useHotkeysShortcut } from '@saas-ui/react'
@@ -246,7 +246,7 @@ The `HotkeysList` component can be used to list all available hotkeys in your ap
Press `?` to open the modal.
-```jsx inline=true
+```jsx center=true inline=true
import {
Box,
Text,