From 77aa4606d8805c6b0e94f087ec1cafa80812e658 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 13 Nov 2022 00:15:12 +0900 Subject: [PATCH] Add a readme --- .gitignore | 2 +- README.md | 213 ++++++++++++++++++++++ examples/next-example/src/pages/_app.tsx | 36 ++++ package.json | 1 + packages/yoshiki/package.json | 27 ++- packages/yoshiki/src/index.ts | 3 +- packages/yoshiki/src/native/generator.tsx | 15 +- packages/yoshiki/src/native/index.ts | 4 +- packages/yoshiki/src/react/generator.tsx | 6 +- packages/yoshiki/src/react/index.tsx | 6 - packages/yoshiki/src/theme.tsx | 16 +- packages/yoshiki/src/web.ts | 6 + packages/yoshiki/tsconfig.json | 6 +- 13 files changed, 308 insertions(+), 33 deletions(-) create mode 100644 README.md create mode 100644 examples/next-example/src/pages/_app.tsx create mode 100644 packages/yoshiki/src/web.ts diff --git a/.gitignore b/.gitignore index deb3e06..3b69def 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,4 @@ yarn-error.log* !.yarn/sdks .expo - +dist/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..25b0be0 --- /dev/null +++ b/README.md @@ -0,0 +1,213 @@ +# yoshiki + +## Features + +- Same interface for React and React Native +- Universal API working for builtins, any component library or your own +- Breakpoints as objects +- User defined theme support +- Shorthands (`m` for `margin`, `paddingX` for `paddingLeft` and `paddingRight`...) +- Atomic CSS generation +- SSR support + +## Usage + +```tsx +import { Stylable, useYoshiki } from "yoshiki"; + +const ColoredDiv = ({ color }: { color: string }) => { + const { css } = useYoshiki(); + + return ( +
theme.spaccing, + m: 1, + })} + > +

Text inside the colored div.

+
+ ); +}; +``` + +Or for React Native components, simply use the `yoshiki/native` import. +Notice that the only difference between the two are the components and the import. + +```tsx +import { Text, View } from "react-native"; +import { Stylable, useYoshiki } from "yoshiki/native"; + +const ColoredBox = ({ color }: { color: string }) => { + const { css } = useYoshiki(); + + return ( + theme.spaccing, + m: 1, + })} + > + Text inside the colored box. + + ); +}; +``` + +## Recipes + +### Customize your own components + +In order to theme your own components, you need to forward some props to the root element like the following example: + +```tsx +const Example = (props) => { + return ( +
+

Example component

+
+ ); +}; +``` + +If you want to use yoshiki to theme your component and allow others components to override styles, pass +the props to the `css` function. + +```tsx +import { useYoshiki } from "yoshiki"; + +const Example = (props) => { + const { css } = useYoshiki(); + + return ( +
+

Example component

+
+ ); +}; +``` + +To stay type-safe and ensure you don't forget to pass down the props, yoshiki exposes the `Stylable` type, so you can do: + +```tsx +import { ReactNode } from "react"; +import { useYoshiki, Stylable } from "yoshiki"; +// or +// import { useYoshiki, Stylable } from "yoshiki/native"; + +const Example = (props: Stylable) => { + const { css } = useYoshiki(); + + return ( +
+ Example component +
+ ); +}; + +const ExampleText = ({ children, ...props }: { children: ReactNode } & Stylable) => { + const { css } = useYoshiki(); + + return

{children}

; +}; +``` + +Yoshiki will handle overrides so the `ExampleText`'s p element will have a padding of `15px`. + +### Server Side Rendering (SSR) + +#### Generic + +To support server side rendering, you need to create a style registry and wrap your app with a `StyleRegistryProvider`. + +```tsx +import { StyleRegistryProvider, createStyleRegistry } from "yoshiki"; + +const registry = createStyleRegistry(); + +const html = renderToString( + + + , +); + +// A list of classes to append to your html head. +const style = registry.flush(); +``` + +#### Next + +Simply use the following `getInitialProps` inside the `pages/_document.tsx` file. + +```tsx +import { StyleRegistryProvider, createStyleRegistry } from "yoshiki"; +import Document, { DocumentContext } from "next/document"; + +Document.getInitialProps = async (ctx: DocumentContext) => { + const renderPage = ctx.renderPage; + const registry = createStyleRegistry(); + + ctx.renderPage = () => + renderPage({ + enhanceApp: (App) => (props) => { + return ( + + + + ); + }, + }); + + const props = await ctx.defaultGetInitialProps(ctx); + return { + ...props, + styles: ( + <> + {props.styles} + {registry.flushToComponent()} + + ), + }; +}; + +export default Document; +``` + +### Theme + +To use the theme, you need to wrap your app with a `ThemeProvider`. If you are using typescript, you will also +need to use module augmentation to add your properties to the theme object. + +```tsx +import { Theme, ThemeProvider, useYoshiki } from "yoshiki"; + +declare module "yoshiki" { + export interface Theme { + spacing: string; + name: string; + } +} + +const defaultTheme: Theme = { + spacing: "24px", + name: "yoshiki", +}; + +const App = () => { + return ( + + + + ); +}; + +const AppName = () => { + const { css, theme } = useYoshiki(); + + return

theme.spacing })}>{theme.name}

; +}; +``` diff --git a/examples/next-example/src/pages/_app.tsx b/examples/next-example/src/pages/_app.tsx new file mode 100644 index 0000000..fdfcd2f --- /dev/null +++ b/examples/next-example/src/pages/_app.tsx @@ -0,0 +1,36 @@ +// +// Copyright (c) Zoe Roux and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. +// + +import { Theme, ThemeProvider, useYoshiki } from "yoshiki"; +import { AppProps } from "next/app"; + +declare module "yoshiki" { + export interface Theme { + spacing: string; + name: string; + } +} + +export const theme: Theme = { + spacing: "24px", + name: "yoshiki", +}; + +const AppName = () => { + const { css, theme } = useYoshiki(); + + return

theme.spacing })}>{theme.name}

; +}; + +const App = ({ Component, pageProps }: AppProps) => { + return ( + + + + + ); +}; + +export default App; diff --git a/package.json b/package.json index 6bc71be..914febf 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "license": "MIT", "private": true, "scripts": { + "build": "yarn workspace yoshiki build", "next": "yarn workspace next-example dev", "expo": "yarn workspace expo-example dev", "lint": "eslint . --ext .ts,.tsx " diff --git a/packages/yoshiki/package.json b/packages/yoshiki/package.json index bc0c05f..fd9eee1 100644 --- a/packages/yoshiki/package.json +++ b/packages/yoshiki/package.json @@ -1,11 +1,28 @@ { "name": "yoshiki", - "version": "1.0.0", - "main": "src/index.ts", - "types": "src/index.ts", + "version": "0.1.0", + "author": "Zoe Roux (https://github.com/AnonymusRaccoon)", + "license": "MIT", + "keywords": [ + "react", + "react-native", + "css-in-js" + ], + "repository": "https://github.com/AnonymusRaccoon/yoshiki", + "homepage": "https://github.com/AnonymusRaccoon/yoshiki", + "bugs": { + "url": "https://github.com/AnonymusRaccoon/yoshiki/issues" + }, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "source": "src/index.ts", "exports": { - ".": "./src/index.ts", - "./native": "./src/native/index.ts" + ".": "./dist/index.ts", + "./native": "./dist/native/index.ts", + "./web": "./dist/index.ts" + }, + "scripts": { + "build": "tsc --build ." }, "packageManager": "yarn@3.2.4", "peerDependencies": { diff --git a/packages/yoshiki/src/index.ts b/packages/yoshiki/src/index.ts index fedcbbe..f47dda5 100644 --- a/packages/yoshiki/src/index.ts +++ b/packages/yoshiki/src/index.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for details. // -export { type Theme, breakpoints, useTheme } from "./theme"; +export { type Theme, breakpoints, useTheme, ThemeProvider, defaultTheme } from "./theme"; export { useYoshiki, @@ -11,5 +11,4 @@ export { StyleRegistryProvider, createStyleRegistry, type Stylable, - type CssObject, } from "./react"; diff --git a/packages/yoshiki/src/native/generator.tsx b/packages/yoshiki/src/native/generator.tsx index fffab5a..b3449b5 100644 --- a/packages/yoshiki/src/native/generator.tsx +++ b/packages/yoshiki/src/native/generator.tsx @@ -12,10 +12,6 @@ import { isBreakpoints } from "../utils"; type EnhancedStyle = { [key in keyof Properties]: YoshikiStyle; }; -export type CssObject = - | EnhancedStyle - | EnhancedStyle - | EnhancedStyle; type Properties = ViewStyle | TextStyle | ImageStyle; const useBreakpoint = (): number => { @@ -51,10 +47,13 @@ export const useYoshiki = () => { const theme = useTheme(); return { - css: (css: CssObject, leftOvers?: { style?: Properties }) => { + css: