From bff6602095b4f45c3a8551b49a153809628a45a6 Mon Sep 17 00:00:00 2001 From: Tony Won Date: Wed, 14 Aug 2024 15:38:13 +0900 Subject: [PATCH] feat(plugin-basic-ui): remove div wrapper in plugin-basic-ui --- .../plugin-basic-ui/src/basicUIPlugin.css.ts | 24 ------ .../plugin-basic-ui/src/basicUIPlugin.tsx | 69 ++++++++--------- .../src/components/AppBar.css.ts | 75 ++++++++++--------- .../src/components/AppScreen.css.ts | 20 ++--- .../src/components/RootStyles.ts | 27 +++++++ 5 files changed, 111 insertions(+), 104 deletions(-) create mode 100644 extensions/plugin-basic-ui/src/components/RootStyles.ts diff --git a/extensions/plugin-basic-ui/src/basicUIPlugin.css.ts b/extensions/plugin-basic-ui/src/basicUIPlugin.css.ts index 4d2e27dd..5411da0a 100644 --- a/extensions/plugin-basic-ui/src/basicUIPlugin.css.ts +++ b/extensions/plugin-basic-ui/src/basicUIPlugin.css.ts @@ -1,9 +1,7 @@ import { createGlobalTheme, createGlobalThemeContract, - createTheme, } from "@vanilla-extract/css"; -import { recipe } from "@vanilla-extract/recipes"; const GLOBAL_VARS = { backgroundColor: "background-color", @@ -81,13 +79,6 @@ const cupertinoValues: GlobalVars = { }, }; -export const android = createTheme(globalVars, { - ...androidValues, -}); -export const cupertino = createTheme(globalVars, { - ...cupertinoValues, -}); - createGlobalTheme( ":root[data-stackflow-plugin-basic-ui-theme=cupertino]", globalVars, @@ -98,18 +89,3 @@ createGlobalTheme( globalVars, androidValues, ); - -export const stackWrapper = recipe({ - base: {}, - variants: { - theme: { - android, - cupertino, - }, - loading: { - true: { - pointerEvents: "none", - }, - }, - }, -}); diff --git a/extensions/plugin-basic-ui/src/basicUIPlugin.tsx b/extensions/plugin-basic-ui/src/basicUIPlugin.tsx index 36bf02c7..760c5f4e 100644 --- a/extensions/plugin-basic-ui/src/basicUIPlugin.tsx +++ b/extensions/plugin-basic-ui/src/basicUIPlugin.tsx @@ -3,8 +3,9 @@ import { assignInlineVars } from "@vanilla-extract/dynamic"; import { createContext, useContext } from "react"; import * as css from "./basicUIPlugin.css"; +import { RootStyles } from "./components/RootStyles"; import type { RecursivePartial } from "./utils"; -import { compact, compactMap, isBrowser } from "./utils"; +import { compactMap } from "./utils"; type BasicUIPluginOptions = RecursivePartial & { theme: "android" | "cupertino"; @@ -50,6 +51,37 @@ export const basicUIPlugin: ( const _options = typeof options === "function" ? options({ initialContext }) : options; + /** + * Assign CSS Variables + */ + const styles: { [key: string]: string | undefined } = assignInlineVars( + compactMap({ + [css.globalVars.backgroundColor]: _options.backgroundColor, + [css.globalVars.dimBackgroundColor]: _options.dimBackgroundColor, + [css.globalVars.transitionDuration]: `${stack.transitionDuration}ms`, + [css.globalVars.computedTransitionDuration]: + stack.globalTransitionState === "loading" + ? `${stack.transitionDuration}ms` + : "0ms", + [css.globalVars.appBar.borderColor]: _options.appBar?.borderColor, + [css.globalVars.appBar.borderSize]: _options.appBar?.borderSize, + [css.globalVars.appBar.height]: _options.appBar?.height, + [css.globalVars.appBar.iconColor]: _options.appBar?.iconColor, + [css.globalVars.appBar.textColor]: _options.appBar?.textColor, + [css.globalVars.appBar.minSafeAreaInsetTop]: + _options.appBar?.minSafeAreaInsetTop, + [css.globalVars.bottomSheet.borderRadius]: + _options.bottomSheet?.borderRadius, + [css.globalVars.modal.borderRadius]: _options.modal?.borderRadius, + }), + ); + + /** + * Prevent pointer events when transitioning + */ + styles["pointer-events"] = + stack.globalTransitionState === "loading" ? "none" : "auto"; + return ( -
- {stack.render()} -
+ + {stack.render()}
); }, diff --git a/extensions/plugin-basic-ui/src/components/AppBar.css.ts b/extensions/plugin-basic-ui/src/components/AppBar.css.ts index 6078901b..b862d2be 100644 --- a/extensions/plugin-basic-ui/src/components/AppBar.css.ts +++ b/extensions/plugin-basic-ui/src/components/AppBar.css.ts @@ -1,7 +1,7 @@ import { style } from "@vanilla-extract/css"; import { recipe } from "@vanilla-extract/recipes"; -import { android, cupertino, globalVars } from "../basicUIPlugin.css"; +import { globalVars } from "../basicUIPlugin.css"; import { f } from "../styles"; import { background, @@ -40,17 +40,18 @@ export const appBar = recipe({ zIndex: vars.zIndexes.appBar, transition: transitions(appBarCommonTransition), selectors: { - [`${cupertino} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=cupertino] &": { position: "absolute", }, - [`${cupertino} ${exitActive} &`]: { - transform: "translate3d(100%, 0, 0)", - transition: transitions({ - ...appBarCommonTransition, - transform: "0s", - }), - }, - [`${android} &`]: { + [`:root[data-stackflow-plugin-basic-ui-theme=cupertino] ${exitActive} &`]: + { + transform: "translate3d(100%, 0, 0)", + transition: transitions({ + ...appBarCommonTransition, + transform: "0s", + }), + }, + ":root[data-stackflow-plugin-basic-ui-theme=android] &": { opacity: 0, transform: "translate3d(0, 10rem, 0)", transition: transitions({ @@ -60,8 +61,8 @@ export const appBar = recipe({ }), }, [` - ${android} ${enterActive} &, - ${android} ${enterDone} & + :root[data-stackflow-plugin-basic-ui-theme=android] ${enterActive} &, + :root[data-stackflow-plugin-basic-ui-theme=android] ${enterDone} & `]: { opacity: 1, transform: "translate3d(0, 0, 0)", @@ -78,7 +79,7 @@ export const appBar = recipe({ modalPresentationStyle: { fullScreen: { selectors: { - [`${cupertino} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=cupertino] &": { transform: "translate3d(0, 100vh, 0)", transition: transitions({ ...appBarCommonTransition, @@ -87,36 +88,38 @@ export const appBar = recipe({ }), }, [` - ${cupertino} ${enterActive} &, - ${cupertino} ${enterDone} & + :root[data-stackflow-plugin-basic-ui-theme=cupertino] ${enterActive} &, + :root[data-stackflow-plugin-basic-ui-theme=cupertino] ${enterDone} & `]: { transform: "translate3d(0, 0, 0)", }, - [`${cupertino} ${exitActive} &`]: { - transform: "translate3d(0, 100vh, 0)", - transition: transitions({ - ...appBarCommonTransition, - transform: vars.transitionDuration, - opacity: vars.transitionDuration, - }), - }, + [`:root[data-stackflow-plugin-basic-ui-theme=cupertino] ${exitActive} &`]: + { + transform: "translate3d(0, 100vh, 0)", + transition: transitions({ + ...appBarCommonTransition, + transform: vars.transitionDuration, + opacity: vars.transitionDuration, + }), + }, }, }, }, activityEnterStyle: { slideInLeft: { selectors: { - [`${android} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=android] &": { opacity: 1, transform: "translate3d(0, 0, 0)", }, - [`${android} ${exitActive} &`]: { - transform: "translate3d(100%, 0, 0)", - transition: transitions({ - ...appBarCommonTransition, - transform: "0s", - }), - }, + [`:root[data-stackflow-plugin-basic-ui-theme=android] ${exitActive} &`]: + { + transform: "translate3d(100%, 0, 0)", + transition: transitions({ + ...appBarCommonTransition, + transform: "0s", + }), + }, }, }, }, @@ -189,7 +192,7 @@ export const centerMain = recipe({ color: globalVars.appBar.textColorTransitionDuration, }), selectors: { - [`${android} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=android] &": { width: "100%", justifyContent: "flex-start", paddingLeft: "1rem", @@ -198,7 +201,7 @@ export const centerMain = recipe({ fontWeight: "bold", boxSizing: "border-box", }, - [`${cupertino} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=cupertino] &": { position: "absolute", display: "flex", alignItems: "center", @@ -221,7 +224,7 @@ export const centerMain = recipe({ hasLeft: { true: { selectors: { - [`${android} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=android] &": { paddingLeft: "0.375rem", }, }, @@ -243,7 +246,7 @@ export const centerMainEdge = style([ display: "none", width: vars.appBar.center.mainWidth, selectors: { - [`${cupertino} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=cupertino] &": { display: "block", }, }, @@ -273,7 +276,7 @@ export const right = style([ display: "none", }, selectors: { - [`${android} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=android] &": { padding: "0 0.5rem 0 0", }, }, diff --git a/extensions/plugin-basic-ui/src/components/AppScreen.css.ts b/extensions/plugin-basic-ui/src/components/AppScreen.css.ts index fe37d789..84014de9 100644 --- a/extensions/plugin-basic-ui/src/components/AppScreen.css.ts +++ b/extensions/plugin-basic-ui/src/components/AppScreen.css.ts @@ -1,7 +1,7 @@ import { createThemeContract, style } from "@vanilla-extract/css"; import { recipe } from "@vanilla-extract/recipes"; -import { android, cupertino, globalVars } from "../basicUIPlugin.css"; +import { globalVars } from "../basicUIPlugin.css"; import { f } from "../styles"; export const vars = createThemeContract({ @@ -59,7 +59,7 @@ export const dim = style([ opacity: 0, zIndex: vars.zIndexes.dim, selectors: { - [`${android} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=android] &": { height: "10rem", background: `linear-gradient(${globalVars.dimBackgroundColor}, rgba(0, 0, 0, 0))`, }, @@ -92,22 +92,22 @@ export const paper = recipe({ }, zIndex: vars.zIndexes.paper, selectors: { - [`${cupertino} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=cupertino] &": { transform: "translate3d(100%, 0, 0)", }, [` - ${cupertino} ${enterActive} &, - ${cupertino} ${enterDone} & + :root[data-stackflow-plugin-basic-ui-theme=cupertino] ${enterActive} &, + :root[data-stackflow-plugin-basic-ui-theme=cupertino] ${enterDone} & `]: { transform: "translate3d(0, 0, 0)", }, - [`${android} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=android] &": { opacity: 0, transform: "translate3d(0, 10rem, 0)", }, [` - ${android} ${enterActive} &, - ${android} ${enterDone} & + :root[data-stackflow-plugin-basic-ui-theme=android] ${enterActive} &, + :root[data-stackflow-plugin-basic-ui-theme=android] ${enterDone} & `]: { opacity: 1, transform: "translate3d(0, 0, 0)", @@ -146,7 +146,7 @@ export const paper = recipe({ modalPresentationStyle: { fullScreen: { selectors: { - [`${cupertino} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=cupertino] &": { transform: "translate3d(0, 100%, 0)", }, }, @@ -155,7 +155,7 @@ export const paper = recipe({ activityEnterStyle: { slideInLeft: { selectors: { - [`${android} &`]: { + ":root[data-stackflow-plugin-basic-ui-theme=android] &": { transform: "translate3d(50%, 0, 0)", }, }, diff --git a/extensions/plugin-basic-ui/src/components/RootStyles.ts b/extensions/plugin-basic-ui/src/components/RootStyles.ts new file mode 100644 index 00000000..9c261a4c --- /dev/null +++ b/extensions/plugin-basic-ui/src/components/RootStyles.ts @@ -0,0 +1,27 @@ +import { useLayoutEffect } from "react"; + +export type RootStylesProps = { + theme: "android" | "cupertino"; + styles: { + [cssVarName: string]: string | undefined; + }; +}; +export function RootStyles({ theme, styles }: RootStylesProps) { + useLayoutEffect(() => { + const root = document.querySelector(":root") as HTMLHtmlElement; + + if (!root) { + return; + } + + for (const [key, value] of Object.entries(styles)) { + if (value) { + root.style.setProperty(key, value); + } + } + + root.dataset.stackflowPluginBasicUiTheme = theme; + }, [styles, theme]); + + return null; +}