Merge pull request #29002 from backstage/canon-icon-provider
CanonProvider → IconProvider
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/canon': minor
|
||||
---
|
||||
|
||||
We are renaming CanonProvider to IconProvider to improve clarity on how to override icons.
|
||||
@@ -17,7 +17,7 @@ building it incrementally with not conflict with the existing theming system.
|
||||
|
||||
Install Canon using a package manager.
|
||||
|
||||
<CodeBlock lang="shell" code={`npm install @backstage/canon`} />
|
||||
<CodeBlock lang="shell" code={`yarn add @backstage/canon`} />
|
||||
|
||||
### 2. Import the css files
|
||||
|
||||
@@ -28,19 +28,7 @@ import '@backstage/canon/css/core.css';
|
||||
import '@backstage/canon/css/components.css';
|
||||
```
|
||||
|
||||
### 3. Add the theme provider
|
||||
|
||||
Add the theme provider to your application.
|
||||
|
||||
```tsx
|
||||
import { ThemeProvider } from '@backstage/canon';
|
||||
|
||||
<ThemeProvider>
|
||||
<App />
|
||||
</ThemeProvider>;
|
||||
```
|
||||
|
||||
### 4. Start building ✨
|
||||
### 3. Start building ✨
|
||||
|
||||
Now you can start building your plugin using the new design system.
|
||||
|
||||
|
||||
@@ -9,7 +9,15 @@ selection for you to use in your application. The list of names is set down
|
||||
below. To use an icon, you can use the `Icon` component and pass the name of
|
||||
the icon you want to use.
|
||||
|
||||
<CodeBlock title="Icon component" code={`<Icon name="heart" />`} />
|
||||
<CodeBlock code={`<Icon name="heart" />`} />
|
||||
|
||||
## Icon overrides
|
||||
|
||||
You can override any icons in our library by using the `IconProvider` at the root of your application.
|
||||
|
||||
<CodeBlock
|
||||
code={`<IconProvider overrides={{ heart: () => <div>Custom Icon</div> }} />`}
|
||||
/>
|
||||
|
||||
## Icon library
|
||||
|
||||
|
||||
@@ -105,19 +105,3 @@ the value, you add an object with the value and the breakpoint prefix.
|
||||
// Responsive value
|
||||
|
||||
<Button size={{ xs: 'small', md: 'medium' }}>Button</Button>`} />
|
||||
|
||||
## How to update breakpoints
|
||||
|
||||
The set of keys are not to be changed, but you can update the minimum width of
|
||||
each breakpoint in the theme provider.
|
||||
|
||||
<CodeBlock
|
||||
code={`<CanonProvider breakpoints={{
|
||||
xs: 0,
|
||||
sm: 640,
|
||||
md: 768,
|
||||
lg: 1024,
|
||||
xl: 1280,
|
||||
'2xl': 1536,
|
||||
}} />`}
|
||||
/>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { CanonProvider } from '../../../packages/canon/src/contexts/canon';
|
||||
import { PlaygroundProvider } from '@/utils/playground-context';
|
||||
|
||||
export const Providers = ({ children }: { children: ReactNode }) => {
|
||||
return (
|
||||
<CanonProvider>
|
||||
<PlaygroundProvider>{children}</PlaygroundProvider>
|
||||
</CanonProvider>
|
||||
);
|
||||
return <PlaygroundProvider>{children}</PlaygroundProvider>;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import type { Preview, ReactRenderer } from '@storybook/react';
|
||||
import { withThemeByDataAttribute } from '@storybook/addon-themes';
|
||||
import { CanonProvider } from '../src/contexts/canon';
|
||||
|
||||
// Canon specific styles
|
||||
import '../src/css/core.css';
|
||||
@@ -87,11 +86,7 @@ const preview: Preview = {
|
||||
(element as HTMLElement).style.backgroundColor = 'var(--canon-bg)';
|
||||
});
|
||||
|
||||
return (
|
||||
<CanonProvider>
|
||||
<Story />
|
||||
</CanonProvider>
|
||||
);
|
||||
return <Story />;
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
```ts
|
||||
/// <reference types="react" />
|
||||
|
||||
import { Context } from 'react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { Field as Field_2 } from '@base-ui-components/react/field';
|
||||
import { ForwardRefExoticComponent } from 'react';
|
||||
@@ -162,23 +163,6 @@ export interface ButtonProps {
|
||||
variant?: ButtonOwnProps['variant'];
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface CanonContextProps {
|
||||
// (undocumented)
|
||||
icons: IconMap;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const CanonProvider: (props: CanonProviderProps) => React_2.JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface CanonProviderProps {
|
||||
// (undocumented)
|
||||
children?: ReactNode;
|
||||
// (undocumented)
|
||||
overrides?: Partial<Record<IconNames, React_2.ComponentType>>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const Checkbox: React_2.ForwardRefExoticComponent<
|
||||
CheckboxProps & React_2.RefAttributes<HTMLButtonElement>
|
||||
@@ -617,6 +601,15 @@ export type HeightProps = GetPropDefTypes<typeof heightPropDefs>;
|
||||
// @public (undocumented)
|
||||
export const Icon: (props: IconProps) => React_2.JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const IconContext: Context<IconContextProps>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface IconContextProps {
|
||||
// (undocumented)
|
||||
icons: IconMap;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type IconMap = Partial<Record<IconNames, React.ComponentType>>;
|
||||
|
||||
@@ -651,6 +644,17 @@ export type IconProps = {
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const IconProvider: (props: IconProviderProps) => React_2.JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface IconProviderProps {
|
||||
// (undocumented)
|
||||
children?: ReactNode;
|
||||
// (undocumented)
|
||||
overrides?: Partial<Record<IconNames, React.ComponentType>>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const icons: IconMap;
|
||||
|
||||
@@ -968,7 +972,7 @@ export interface TextProps {
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const useCanon: () => CanonContextProps;
|
||||
export const useIcons: () => IconContextProps;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface UtilityProps extends SpaceProps {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import React from 'react';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { Icon } from './Icon';
|
||||
import { CanonProvider } from '../../contexts/canon';
|
||||
import { IconProvider } from './provider';
|
||||
import { icons } from './icons';
|
||||
|
||||
const meta = {
|
||||
@@ -52,9 +52,9 @@ export const WithCustomIcon: Story = {
|
||||
},
|
||||
decorators: [
|
||||
Story => (
|
||||
<CanonProvider overrides={{ arrowDown: () => <div>Custom Icon</div> }}>
|
||||
<IconProvider overrides={{ arrowDown: () => <div>Custom Icon</div> }}>
|
||||
<Story />
|
||||
</CanonProvider>
|
||||
</IconProvider>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { useCanon } from '../../contexts/canon';
|
||||
import { useIcons } from './context';
|
||||
import type { IconProps } from './types';
|
||||
import clsx from 'clsx';
|
||||
|
||||
/** @public */
|
||||
export const Icon = (props: IconProps) => {
|
||||
const { name, size, className, style, ...restProps } = props;
|
||||
const { icons } = useCanon();
|
||||
const { icons } = useIcons();
|
||||
|
||||
const CanonIcon = icons[name] as React.ComponentType<Omit<IconProps, 'name'>>;
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createContext, useContext } from 'react';
|
||||
import { icons } from './icons';
|
||||
import type { IconContextProps } from './types';
|
||||
|
||||
/** @public */
|
||||
export const IconContext = createContext<IconContextProps>({
|
||||
icons,
|
||||
});
|
||||
|
||||
/** @public */
|
||||
export const useIcons = () => useContext(IconContext);
|
||||
@@ -14,6 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './Icon';
|
||||
// Icons
|
||||
export * from './icons';
|
||||
|
||||
// Icon component
|
||||
export * from './Icon';
|
||||
|
||||
// Context and Provider
|
||||
export * from './context';
|
||||
export * from './provider';
|
||||
|
||||
// Types
|
||||
export type * from './types';
|
||||
|
||||
+7
-24
@@ -14,38 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { createContext, ReactNode, useContext } from 'react';
|
||||
import { icons } from '../components/Icon/icons';
|
||||
import { IconMap, IconNames } from '../components/Icon/types';
|
||||
import React from 'react';
|
||||
import { icons } from './icons';
|
||||
import { IconContext } from './context';
|
||||
import type { IconProviderProps } from './types';
|
||||
|
||||
/** @public */
|
||||
export interface CanonContextProps {
|
||||
icons: IconMap;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface CanonProviderProps {
|
||||
children?: ReactNode;
|
||||
overrides?: Partial<Record<IconNames, React.ComponentType>>;
|
||||
}
|
||||
|
||||
const CanonContext = createContext<CanonContextProps>({
|
||||
icons,
|
||||
});
|
||||
|
||||
/** @public */
|
||||
export const CanonProvider = (props: CanonProviderProps) => {
|
||||
export const IconProvider = (props: IconProviderProps) => {
|
||||
const { children, overrides } = props;
|
||||
|
||||
// Merge provided overrides with default icons
|
||||
const combinedIcons = { ...icons, ...overrides };
|
||||
|
||||
return (
|
||||
<CanonContext.Provider value={{ icons: combinedIcons }}>
|
||||
<IconContext.Provider value={{ icons: combinedIcons }}>
|
||||
{children}
|
||||
</CanonContext.Provider>
|
||||
</IconContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export const useCanon = () => useContext(CanonContext);
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
/** @public */
|
||||
export type IconNames =
|
||||
| 'arrowDown'
|
||||
@@ -47,3 +49,14 @@ export type IconProps = {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export interface IconContextProps {
|
||||
icons: IconMap;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface IconProviderProps {
|
||||
children?: ReactNode;
|
||||
overrides?: Partial<Record<IconNames, React.ComponentType>>;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
// Providers
|
||||
export * from './contexts/canon';
|
||||
export * from './components/Icon/context';
|
||||
|
||||
// Layout components
|
||||
export * from './components/Box';
|
||||
|
||||
Reference in New Issue
Block a user