-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #737 from omnifed/734-feat-create-usecanvascolors-…
…hook 734 feat create usecanvascolors hook
- Loading branch information
Showing
7 changed files
with
242 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
docs/app/react/use-root-colors/components/canvas-preview.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
'use client' | ||
|
||
import { useRootColors } from '@cerberus-design/react' | ||
import { VStack } from '@cerberus-design/styled-system/jsx' | ||
import { useEffect, useRef } from 'react' | ||
|
||
const colorList = ['dataViz.diverging.50', 'dataViz.diverging.200'] | ||
|
||
export default function CanvasPreview() { | ||
const colors = useRootColors(colorList) | ||
const canvasRef = useRef<HTMLCanvasElement>(null) | ||
|
||
useEffect(() => { | ||
if (!canvasRef.current) return | ||
if (Object.keys(colors).length !== colorList.length) return | ||
|
||
const ctx = canvasRef.current.getContext('2d') | ||
if (!ctx) return | ||
|
||
ctx.fillStyle = colors['dataViz.diverging.50'] | ||
ctx.fillRect(0, 0, 100, 100) | ||
|
||
ctx.fillStyle = colors['dataViz.diverging.200'] | ||
ctx.fillRect(100, 0, 100, 100) | ||
}, [colors]) | ||
|
||
return ( | ||
<VStack> | ||
<canvas | ||
width="200" | ||
height="100" | ||
ref={canvasRef} | ||
style={{ border: '1px solid black' }} | ||
/> | ||
<small>This is adding data-viz colors to a canvas element.</small> | ||
</VStack> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
--- | ||
heading: 'useRootColors' | ||
description: 'Get Cerberus colors from the document root.' | ||
npm: '@cerberus-design/react' | ||
source: 'hooks/useRootColors.ts' | ||
recipe: '' | ||
a11y: 'utilities' | ||
--- | ||
|
||
import CodePreview from '@/app/components/CodePreview' | ||
import { | ||
WhenToUseAdmonition | ||
} from '@/app/components/Admonition' | ||
import CanvasPreview from './components/canvas-preview' | ||
|
||
<WhenToUseAdmonition description="When you want to use Cerberus colors within a `canvas` element." /> | ||
|
||
This hook allows you to access Cerberus colors from the document root which is useful when you want to use Cerberus colors within a `canvas` element. | ||
|
||
## Usage | ||
|
||
<CodePreview preview={<CanvasPreview />}> | ||
```tsx title="some-chart.tsx" {18} | ||
'use client' | ||
|
||
import { useRootColors } from '@cerberus/react' | ||
import { useEffect, useState, useRef } from 'react' | ||
|
||
// This is a list of Cerberus colors to use in the chart | ||
const colorList = [ | ||
'dataViz.diverging.50', | ||
'dataViz.diverging.100', | ||
'dataViz.diverging.200', | ||
] | ||
|
||
// This is settings for X chart library | ||
const chartSettings = {} | ||
|
||
function SomeChart() { | ||
const [settings, setSettings] = useState(chartSettings) | ||
const colors = useRootColors(colorList) | ||
const hasSetColors = useRef<boolean>(false) | ||
|
||
useEffect(() => { | ||
if (Object.keys(colors).length && !hasSetColors.current) { | ||
setSettings({ | ||
...settings, | ||
something: { | ||
bgColor: colors[colorList[0]], | ||
}, | ||
somethingElse: { | ||
bgColor: colors[colorList[1]], | ||
}, | ||
}) | ||
hasSetColors.current = true | ||
} | ||
}, [colors]) | ||
|
||
return ( | ||
<SomeChartLib settings={settings} /> | ||
) | ||
} | ||
``` | ||
</CodePreview> | ||
|
||
## API | ||
|
||
```ts showLineNumbers=false | ||
define function useRootColors(colors: string[] = []): Record<string, string> | ||
``` | ||
|
||
### Arguments | ||
|
||
The `useRootColors` hook accepts the following optional arguments: | ||
|
||
| Name | Default | Description | | ||
| ------------ | ---------- | ------------------------------------------------ | | ||
| `colors` | `[]` | An array of Cerberus color keys to retrieve. | | ||
|
||
### Return | ||
|
||
The `useRootColors` hook returns a memoized object with the same properties as the options object passed in. | ||
|
||
```ts | ||
{ | ||
'dataViz.diverging.50': '#F7F7F7', | ||
'dataViz.diverging.100': '#E5E5E5', | ||
'dataViz.diverging.200': '#C6C6C6', | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import ApiLinks from '@/app/components/ApiLinks' | ||
import OnThisPage from '../../components/OnThisPage' | ||
import { PageMainContent, PageSections } from '../../components/PageLayout' | ||
import UseThemeDoc, { frontmatter } from './doc.mdx' | ||
import FeatureHeader from '@/app/components/FeatureHeader' | ||
import type { MatchFeatureKind } from '@/app/components/MatchFeatureImg' | ||
|
||
export default function UseRootColorsPage() { | ||
return ( | ||
<> | ||
<PageMainContent> | ||
<FeatureHeader | ||
heading={frontmatter.heading} | ||
description={frontmatter.description} | ||
a11y={frontmatter.a11y as MatchFeatureKind} | ||
/> | ||
<ApiLinks {...frontmatter} /> | ||
<main> | ||
<UseThemeDoc /> | ||
</main> | ||
</PageMainContent> | ||
|
||
<PageSections> | ||
<OnThisPage /> | ||
</PageSections> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
'use client' | ||
|
||
import { useEffect, useReducer } from 'react' | ||
|
||
/** | ||
* This module provides a hook to get Cerberus colors from the document root. | ||
* @module useRootColors | ||
*/ | ||
|
||
export type RootColorsResult = Record<string, string> | ||
|
||
/** | ||
* This hook returns a record of Cerberus colors from the document root. | ||
* This is useful when you are working with a component that uses the `<canvas>` | ||
* element. | ||
* @param colors - An array of Cerberus tokens to get from the document root (i.e. `['dataViz.diverging.50', 'dataViz.diverging.200']`). | ||
* @returns A record of Cerberus colors where the key is the token name provided and the value is the color hex. | ||
*/ | ||
export function useRootColors(colors: string[] = []): RootColorsResult { | ||
const [state, dispatch] = useReducer(rootColorsReducer, {}) | ||
|
||
useEffect(() => { | ||
if (Object.keys(state).length === colors.length) return | ||
|
||
const rootStyles = getComputedStyle(document.body) | ||
const rootColors = colors.reduce((acc, color) => { | ||
const formattedColor = color | ||
.replace(/([a-z])([A-Z])/g, '$1-$2') | ||
.toLowerCase() | ||
.replaceAll('.', '-') | ||
acc[color as keyof typeof acc] = rootStyles | ||
.getPropertyValue(`--cerberus-colors-${formattedColor}`) | ||
.trim() | ||
return acc | ||
}, {} as RootColorsResult) | ||
|
||
dispatch(rootColors) | ||
}, [colors]) | ||
|
||
// reducer is already memoized | ||
return state | ||
} | ||
|
||
function rootColorsReducer( | ||
state: Record<string, string>, | ||
action: Record<string, string>, | ||
): Record<string, string> { | ||
return { ...state, ...action } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { describe, test, expect, afterEach } from 'bun:test' | ||
import { render, screen, cleanup } from '@testing-library/react' | ||
import { useRootColors } from '@cerberus-design/react' | ||
import { setupStrictMode } from '@/utils' | ||
|
||
describe('useRootColors', () => { | ||
setupStrictMode() | ||
afterEach(cleanup) | ||
|
||
function Test() { | ||
const colors = useRootColors([ | ||
'dataViz.diverging.50', | ||
'dataViz.diverging.200', | ||
]) | ||
|
||
return ( | ||
<div> | ||
{Object.keys(colors).map((color) => ( | ||
<div key={color}> | ||
<span>{color}</span> | ||
</div> | ||
))} | ||
</div> | ||
) | ||
} | ||
|
||
test('should return a record of colors', () => { | ||
render(<Test />) | ||
// There's no document to store styles in a test environment, so we can't | ||
// test this hook to the full extent. | ||
expect(screen.getByText(/dataViz.diverging.50/i)).toBeTruthy() | ||
expect(screen.getByText(/dataViz.diverging.200/i)).toBeTruthy() | ||
}) | ||
}) |