diff --git a/apps/docs/docs/learn/06-recipes/01-contextual-styles.mdx b/apps/docs/docs/learn/06-recipes/01-contextual-styles.mdx new file mode 100644 index 00000000..78fbc96d --- /dev/null +++ b/apps/docs/docs/learn/06-recipes/01-contextual-styles.mdx @@ -0,0 +1,93 @@ +--- +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +sidebar_position: 6 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Conditional styles based on context + +StyleX lets you apply styles conditionally. Any condition can be used to do so, `Props`, `State` or `Context`. + +The React Context API (and other similar APIs) can be used to avoid prop-drilling +and provide conditions that child component can read and apply styles conditionally. + +Context can help reduce prop-drilling by sharing state across components. This can often +an alternative to using descendent selectors where the same results can be achieved +*without* "styling at a distance". + +For example, you can manage the open or closed state of a sidebar using React Context +and conditionally apply styles: + +## Defining context and styles + +This file sets up the `SidebarContext` and defines the styles for the sidebar in one place. +The context provides a way to share the open/closed state, and the styles determine +the appearance of the sidebar based on that state. + +```tsx +import { createContext } from 'react'; +import * as stylex from '@stylexjs/stylex'; + +export default createContext(false); +``` +## Building the sidebar component +The `Sidebar` component uses the `SidebarContext` to determine its open or closed state +and conditionally applies the appropriate styles. + +```tsx +import React, { useContext } from 'react'; +import * as stylex from '@stylexjs/stylex'; +import { SidebarContext } from './SidebarContext'; + +export default function Sidebar({ children }) { + const isOpen = useContext(SidebarContext); + + return ( +
+ {children} +
+ ); +} + +const styles = stylex.create({ + base: {...}, + open: { + width: 250, + }, + closed: { + width: 50, + }, +}); +``` + +## Using the sidebar in a parent component + +The `App` component manages the sidebar's open/closed state and provides it to + child components through `SidebarContext.Provider`. A button toggles the sidebar state dynamically. + +```tsx +import React, { useState } from 'react'; +import SidebarContext from './SidebarContext'; +import Sidebar from './Sidebar'; + +export default function App() { + const [isSidebarOpen, setIsSidebarOpen] = useState(false); + + return ( + + + +

Sidebar Content

+
+
+ ); +} +``` + diff --git a/apps/docs/docs/learn/06-recipes/02-variants.mdx b/apps/docs/docs/learn/06-recipes/02-variants.mdx new file mode 100644 index 00000000..677cb92b --- /dev/null +++ b/apps/docs/docs/learn/06-recipes/02-variants.mdx @@ -0,0 +1,52 @@ +--- +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +sidebar_position: 5 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Variants + +The "variants" pattern allows you to conditionally apply one of several predefined styles based on a value. This is especially useful for theming or dynamic component behavior. + +### Example: Button Variants + +Here’s how you can create a button component with different visual styles based on a `variant` prop: + +```tsx +import * as stylex from '@stylexjs/stylex'; + +const styles = stylex.create({ + base: { + appearance: 'none', + borderWidth: 0, + }, +}); +const variants = stylex.create({ + primary: { + backgroundColor: { + default: 'blue', + ':hover': 'darkblue', + }, + color: 'white', + }, + secondary: { + backgroundColor: { + default: 'gray', + ':hover': 'darkgray', + }, + color: 'white', + }, +}); +function Button({ variant = 'primary', ...props }) { + return + +``` \ No newline at end of file diff --git a/apps/docs/docs/learn/06-recipes/03-descendant styles.mdx b/apps/docs/docs/learn/06-recipes/03-descendant styles.mdx new file mode 100644 index 00000000..e04ce0ba --- /dev/null +++ b/apps/docs/docs/learn/06-recipes/03-descendant styles.mdx @@ -0,0 +1,76 @@ +--- +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +sidebar_position: 7 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Descendant styles dependent on ancestor state + +## Example: Sidebar + +Consider the case where the content within a sidebar needs to have conditional styles applied +when the sidebar as whole is hovered. + +Using CSS variables, you can style descendants based on a parent's state, such as `:hover`. + +### Step 1 +Define one or more variables using `stylex.defineVars`: + +```tsx variables.stylex.ts +// variables.stylex.ts +import * as stylex from '@stylexjs/stylex'; + +export const vars = stylex.defineVars({ + childColor: 'black', +}); +``` + +### Step 2 +Define conditional styles setting the value for the variable in the ancestor component. + +```tsx +import * as stylex from '@stylexjs/stylex'; +import { vars } from './variables.stylex'; + +const styles = stylex.create({ + parent: { + [vars.childColor]: { + default: 'black', + ':hover': 'blue', + }, + }, +}); + +function ParentWithHover({children}) { + return ( +
+ {children} +
+ ); +} +``` + +### Step 3 +Use the variable to style the child component + +```tsx +import * as stylex from '@stylexjs/stylex'; +import { vars } from './variables.stylex'; + +const styles = stylex.create({ + row: { + color: vars.childColor, + } +}); + +function ParentWithHover() { + return ( + A Row + ); +} +``` diff --git a/apps/docs/docs/learn/06-recipes/_category_.json b/apps/docs/docs/learn/06-recipes/_category_.json new file mode 100644 index 00000000..3a9a5262 --- /dev/null +++ b/apps/docs/docs/learn/06-recipes/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Recipes", + "position": 4 +}