Skip to content

Commit

Permalink
docs: Implemented "recipe" page (#791)
Browse files Browse the repository at this point in the history
* Implemented recipe page with examples of common styling patterns
  • Loading branch information
aminaopio authored Dec 22, 2024
1 parent c43e68a commit 2d9ceaa
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 0 deletions.
93 changes: 93 additions & 0 deletions apps/docs/docs/learn/06-recipes/01-contextual-styles.mdx
Original file line number Diff line number Diff line change
@@ -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 (
<div {...stylex.props(styles.base, isOpen ? styles.open : styles.closed)}>
{children}
</div>
);
}

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 (
<SidebarContext.Provider value={isSidebarOpen}>
<button onClick={() => setIsSidebarOpen(!isSidebarOpen)}>
Toggle Sidebar
</button>
<Sidebar>
<p>Sidebar Content</p>
</Sidebar>
</SidebarContext.Provider>
);
}
```

52 changes: 52 additions & 0 deletions apps/docs/docs/learn/06-recipes/02-variants.mdx
Original file line number Diff line number Diff line change
@@ -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 <button {...props} {...stylex.props(styles.base, variants[variant], props.style)} />;
}

// Usage
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
```
76 changes: 76 additions & 0 deletions apps/docs/docs/learn/06-recipes/03-descendant styles.mdx
Original file line number Diff line number Diff line change
@@ -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 (
<div {...stylex.props(styles.parent)}>
{children}
</div>
);
}
```

### 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 (
<span {...stylex.props(styles.child)}><Icon />A Row</span>
);
}
```
4 changes: 4 additions & 0 deletions apps/docs/docs/learn/06-recipes/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "Recipes",
"position": 4
}

0 comments on commit 2d9ceaa

Please sign in to comment.