mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
Merge pull request #2004 from fveiraswww/feat/banner-hex-colors
UI: Support `rainbowColors` API in `<Banner />` component
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-ui': patch
|
||||
---
|
||||
|
||||
Support `rainbowColors` API in `<Banner />` component
|
||||
@@ -45,6 +45,7 @@ import { getMDXComponents } from '@/mdx-components';
|
||||
import { APIPage } from 'fumadocs-openapi/ui';
|
||||
import { LLMCopyButton, ViewOptions } from './page.client';
|
||||
import * as path from 'node:path';
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
function PreviewRenderer({ preview }: { preview: string }): ReactNode {
|
||||
if (preview && preview in Preview) {
|
||||
@@ -131,6 +132,7 @@ export default async function Page(props: {
|
||||
</HoverCard>
|
||||
);
|
||||
},
|
||||
Banner,
|
||||
Mermaid,
|
||||
TypeTable,
|
||||
AutoTypeTable: (props) => (
|
||||
|
||||
@@ -241,16 +241,30 @@ export function banner(): ReactNode {
|
||||
</Banner>
|
||||
|
||||
<Banner
|
||||
className="z-0"
|
||||
id="test-rainbow"
|
||||
className="z-0"
|
||||
variant="rainbow"
|
||||
changeLayout={false}
|
||||
>
|
||||
Using the <code>rainbow</code> variant
|
||||
</Banner>
|
||||
|
||||
<Banner className="z-0" id="test" changeLayout={false}>
|
||||
Be careful, this banner can be closed
|
||||
<Banner
|
||||
id="test"
|
||||
className="z-0"
|
||||
variant="rainbow"
|
||||
rainbowColors={[
|
||||
'rgba(255,100,0, 0.5)',
|
||||
'rgba(255,100,0, 0.5)',
|
||||
'transparent',
|
||||
'rgba(255,100,0, 0.5)',
|
||||
'transparent',
|
||||
'rgba(255,100,0, 0.5)',
|
||||
'transparent',
|
||||
]}
|
||||
changeLayout={false}
|
||||
>
|
||||
customise the <code>rainbow</code> variant
|
||||
</Banner>
|
||||
</div>
|
||||
</Wrapper>
|
||||
|
||||
@@ -35,6 +35,22 @@ Change the default variant.
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
<Banner variant="rainbow">Hello World</Banner>;
|
||||
|
||||
// customise colors
|
||||
<Banner
|
||||
variant="rainbow"
|
||||
rainbowColors={[
|
||||
'rgba(255,100,0, 0.5)',
|
||||
'rgba(255,100,0, 0.5)',
|
||||
'transparent',
|
||||
'rgba(255,100,0, 0.5)',
|
||||
'transparent',
|
||||
'rgba(255,100,0, 0.5)',
|
||||
'transparent',
|
||||
]}
|
||||
>
|
||||
Hello World
|
||||
</Banner>;
|
||||
```
|
||||
|
||||
### Change Layout
|
||||
|
||||
@@ -5,11 +5,19 @@ import { X } from 'lucide-react';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { buttonVariants } from '@/components/ui/button';
|
||||
|
||||
type BannerVariant = 'rainbow' | 'normal';
|
||||
|
||||
export function Banner({
|
||||
id,
|
||||
variant = 'normal',
|
||||
changeLayout = true,
|
||||
height = '3rem',
|
||||
rainbowColors = [
|
||||
'rgba(0,149,255,0.56)',
|
||||
'rgba(231,77,255,0.77)',
|
||||
'rgba(255,0,0,0.73)',
|
||||
'rgba(131,255,166,0.66)',
|
||||
],
|
||||
...props
|
||||
}: HTMLAttributes<HTMLDivElement> & {
|
||||
/**
|
||||
@@ -20,7 +28,12 @@ export function Banner({
|
||||
/**
|
||||
* @defaultValue 'normal'
|
||||
*/
|
||||
variant?: 'rainbow' | 'normal';
|
||||
variant?: BannerVariant;
|
||||
|
||||
/**
|
||||
* For rainbow variant only, customise the colors
|
||||
*/
|
||||
rainbowColors?: string[];
|
||||
|
||||
/**
|
||||
* Change Fumadocs layout styles
|
||||
@@ -43,7 +56,8 @@ export function Banner({
|
||||
id={id}
|
||||
{...props}
|
||||
className={cn(
|
||||
'sticky top-0 z-40 flex flex-row items-center justify-center bg-fd-secondary px-4 text-center text-sm font-medium',
|
||||
'sticky top-0 z-40 flex flex-row items-center justify-center px-4 text-center text-sm font-medium',
|
||||
variant === 'normal' && 'bg-fd-secondary',
|
||||
variant === 'rainbow' && 'bg-fd-background',
|
||||
!open && 'hidden',
|
||||
props.className,
|
||||
@@ -70,7 +84,11 @@ export function Banner({
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{variant === 'rainbow' ? rainbowLayer : null}
|
||||
{variant === 'rainbow'
|
||||
? flow({
|
||||
colors: rainbowColors,
|
||||
})
|
||||
: null}
|
||||
{props.children}
|
||||
{id ? (
|
||||
<button
|
||||
@@ -84,8 +102,8 @@ export function Banner({
|
||||
buttonVariants({
|
||||
color: 'ghost',
|
||||
className:
|
||||
'absolute end-2 top-1/2 -translate-y-1/2 text-fd-muted-foreground',
|
||||
size: 'icon',
|
||||
'absolute end-2 top-1/2 -translate-y-1/2 text-fd-muted-foreground/50',
|
||||
size: 'icon-sm',
|
||||
}),
|
||||
)}
|
||||
>
|
||||
@@ -99,50 +117,28 @@ export function Banner({
|
||||
const maskImage =
|
||||
'linear-gradient(to bottom,white,transparent), radial-gradient(circle at top center, white, transparent)';
|
||||
|
||||
const rainbowLayer = (
|
||||
<>
|
||||
<div
|
||||
className="absolute inset-0 z-[-1]"
|
||||
style={
|
||||
{
|
||||
maskImage,
|
||||
maskComposite: 'intersect',
|
||||
animation: 'fd-moving-banner 16s linear infinite',
|
||||
'--start': 'rgba(0,87,255,0.5)',
|
||||
'--mid': 'rgba(255,0,166,0.77)',
|
||||
'--end': 'rgba(255,77,0,0.4)',
|
||||
'--via': 'rgba(164,255,68,0.4)',
|
||||
animationDirection: 'reverse',
|
||||
backgroundImage:
|
||||
'repeating-linear-gradient(60deg, var(--end), var(--start) 2%, var(--start) 5%, transparent 8%, transparent 14%, var(--via) 18%, var(--via) 22%, var(--mid) 28%, var(--mid) 30%, var(--via) 34%, var(--via) 36%, transparent, var(--end) calc(50% - 12px))',
|
||||
backgroundSize: '200% 100%',
|
||||
mixBlendMode: 'difference',
|
||||
} as object
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="absolute inset-0 z-[-1]"
|
||||
style={
|
||||
{
|
||||
maskImage,
|
||||
maskComposite: 'intersect',
|
||||
animation: 'fd-moving-banner 20s linear infinite',
|
||||
'--start': 'rgba(255,120,120,0.5)',
|
||||
'--mid': 'rgba(36,188,255,0.4)',
|
||||
'--end': 'rgba(64,0,255,0.51)',
|
||||
'--via': 'rgba(255,89,0,0.56)',
|
||||
backgroundImage:
|
||||
'repeating-linear-gradient(45deg, var(--end), var(--start) 4%, var(--start) 8%, transparent 9%, transparent 14%, var(--mid) 16%, var(--mid) 20%, transparent, var(--via) 36%, var(--via) 40%, transparent 42%, var(--end) 46%, var(--end) calc(50% - 16.8px))',
|
||||
backgroundSize: '200% 100%',
|
||||
mixBlendMode: 'color-dodge',
|
||||
} as object
|
||||
}
|
||||
/>
|
||||
<style>
|
||||
{`@keyframes fd-moving-banner {
|
||||
function flow({ colors }: { colors: string[] }) {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="absolute inset-0 z-[-1]"
|
||||
style={
|
||||
{
|
||||
maskImage,
|
||||
maskComposite: 'intersect',
|
||||
animation: 'fd-moving-banner 20s linear infinite',
|
||||
backgroundImage: `repeating-linear-gradient(70deg, ${[...colors, colors[0]].map((color, i) => `${color} ${(i * 50) / colors.length}%`).join(', ')})`,
|
||||
backgroundSize: '200% 100%',
|
||||
filter: 'saturate(2)',
|
||||
} as object
|
||||
}
|
||||
/>
|
||||
<style>
|
||||
{`@keyframes fd-moving-banner {
|
||||
from { background-position: 0% 0; }
|
||||
to { background-position: 100% 0; }
|
||||
}`}
|
||||
</style>
|
||||
</>
|
||||
);
|
||||
</style>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user