From 125dc90b211a9fdedf2033056b9ad169518c7234 Mon Sep 17 00:00:00 2001 From: Naman Goel Date: Sun, 22 Dec 2024 12:24:32 +0300 Subject: [PATCH] docs: iterate on recipes section --- ...tyles.mdx => 01-context-driven-styles.mdx} | 6 +- .../docs/learn/06-recipes/02-variants.mdx | 201 +++++++++++++++++- .../learn/06-recipes/03-descendant styles.mdx | 14 +- 3 files changed, 210 insertions(+), 11 deletions(-) rename apps/docs/docs/learn/06-recipes/{01-contextual-styles.mdx => 01-context-driven-styles.mdx} (96%) diff --git a/apps/docs/docs/learn/06-recipes/01-contextual-styles.mdx b/apps/docs/docs/learn/06-recipes/01-context-driven-styles.mdx similarity index 96% rename from apps/docs/docs/learn/06-recipes/01-contextual-styles.mdx rename to apps/docs/docs/learn/06-recipes/01-context-driven-styles.mdx index 78fbc96d..ef09a872 100644 --- a/apps/docs/docs/learn/06-recipes/01-contextual-styles.mdx +++ b/apps/docs/docs/learn/06-recipes/01-context-driven-styles.mdx @@ -9,7 +9,7 @@ sidebar_position: 6 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Conditional styles based on context +# Context-driven styles StyleX lets you apply styles conditionally. Any condition can be used to do so, `Props`, `State` or `Context`. @@ -35,7 +35,9 @@ 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. @@ -80,7 +82,7 @@ export default function App() { return ( - diff --git a/apps/docs/docs/learn/06-recipes/02-variants.mdx b/apps/docs/docs/learn/06-recipes/02-variants.mdx index 677cb92b..c570ca06 100644 --- a/apps/docs/docs/learn/06-recipes/02-variants.mdx +++ b/apps/docs/docs/learn/06-recipes/02-variants.mdx @@ -11,11 +11,15 @@ 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. +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 +It is common to have different styles for different "variants" of a component. Some other styling solutions provide +an explicit API for defining variants. In StyleX, you can define variants with a simple pattern instead. -Here’s how you can create a button component with different visual styles based on a `variant` prop: +## Example: Button Variants + +Here’s how you can create a button component with different visual styles based on `variant` props: ```tsx import * as stylex from '@stylexjs/stylex'; @@ -26,7 +30,150 @@ const styles = stylex.create({ borderWidth: 0, }, }); -const variants = stylex.create({ +const colorVariants = stylex.create({ + primary: { + backgroundColor: { + default: 'blue', + ':hover': 'darkblue', + }, + color: 'white', + }, + secondary: { + backgroundColor: { + default: 'gray', + ':hover': 'darkgray', + }, + color: 'white', + }, +}); +const sizeVariants = stylex.create({ + small: { + fontSize: '1rem', + paddingBlock: 4, + paddingInline: 8 + }, + medium: { + fontSize: '1.2rem', + paddingBlock: 8, + paddingInline: 16 + }, +}); + +type Props = { + color: keyof typeof colorVariants, + size: keyof typeof sizeVariants, + ... +}; + +function Button({ + color = 'primary', + size = 'small', + ...props +}: Props) { + return ( + + +``` +## Compound Variants + +Sometimes variants are dependent on a combination of variants props. + +In most cases, it's simpler to leverage StyleX’s deterministic style merging to simplify this +behaviour. + +### Example: A `disabled` prop + +```tsx +import * as stylex from '@stylexjs/stylex'; + +const styles = stylex.create({ + base: {...}, + disabled: { + backgroundColor: 'grey', + color: 'rgb(204, 204, 204)', + cursor: 'not-allowed', + }, +}); +const colorVariants = stylex.create({ + primary: { + backgroundColor: { + default: 'blue', + ':hover': 'darkblue', + }, + color: 'white', + }, + secondary: { + backgroundColor: { + default: 'gray', + ':hover': 'darkgray', + }, + color: 'white', + }, +}); +const sizeVariants = stylex.create({...}); + +type Props = { + color?: keyof typeof colorVariants, + size?: keyof typeof sizeVariants, + disabled?: boolean, + ... +}; + +function Button({ + color = 'primary', + size = 'small', + disabled = false, + ...props, +}: Props) { + return ( + + +``` + +There may be other scenarios where you need to be more explicit about the styles +that should applied under various condition. You can do this by declaring multiple +style definitions for a particular variant. + +### Example: Two definitions for `color` variant styles + +```tsx +import * as stylex from '@stylexjs/stylex'; + +const styles = stylex.create({ + base: {...}, +}); +const colorVariantsEnabled = stylex.create({ primary: { backgroundColor: { default: 'blue', @@ -42,11 +189,49 @@ const variants = stylex.create({ 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 index e04ce0ba..9d680c81 100644 --- a/apps/docs/docs/learn/06-recipes/03-descendant styles.mdx +++ b/apps/docs/docs/learn/06-recipes/03-descendant styles.mdx @@ -9,7 +9,13 @@ sidebar_position: 7 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Descendant styles dependent on ancestor state +# Variables for descendant styles + +It is not uncommon to define styles on an element that are dependent on a parent element's state, +such as applying some styles conditionally when the parent element is hovered. + +StyleX doesn't allow arbitrary selectors or "styling at a distance". However, variables can be +used to achieve the same results in a safe and composable way. ## Example: Sidebar @@ -19,6 +25,7 @@ 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 @@ -31,6 +38,7 @@ export const vars = stylex.defineVars({ ``` ### Step 2 + Define conditional styles setting the value for the variable in the ancestor component. ```tsx @@ -56,6 +64,7 @@ function ParentWithHover({children}) { ``` ### Step 3 + Use the variable to style the child component ```tsx @@ -74,3 +83,6 @@ function ParentWithHover() { ); } ``` + +This pattern makes it explicit what styles are being defined on an ancestor element, while leaving +the child element in control to use those styles explicitly and to override it as needed. \ No newline at end of file