mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
UI: Redesign sidebar footer
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'fumadocs-ui': patch
|
||||
'@fumadocs/base-ui': patch
|
||||
---
|
||||
|
||||
Redesign sidebar footer
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import { createLinkItemRenderer } from '@/components/sidebar/link-item';
|
||||
import { buttonVariants } from '@/components/ui/button';
|
||||
import { SearchTrigger } from '@/layouts/shared/slots/search-trigger';
|
||||
import { Check, ChevronsUpDown, Languages, SidebarIcon } from 'lucide-react';
|
||||
import { Check, ChevronDown, ChevronsUpDown, Languages, SidebarIcon } from 'lucide-react';
|
||||
import { mergeRefs } from '@/utils/merge-refs';
|
||||
import { useDocsLayout } from '../client';
|
||||
import { LinkItem } from '@/layouts/shared';
|
||||
@@ -29,7 +29,7 @@ const itemVariants = cva(
|
||||
'transition-colors hover:bg-fd-accent/50 hover:text-fd-accent-foreground/80 hover:transition-none',
|
||||
},
|
||||
highlight: {
|
||||
true: "data-[active=true]:before:content-[''] data-[active=true]:before:bg-fd-primary data-[active=true]:before:absolute data-[active=true]:before:w-px data-[active=true]:before:inset-y-2.5 data-[active=true]:before:start-2.5",
|
||||
true: "data-[active=true]:before:content-[''] data-[active=true]:before:bg-fd-primary data-[active=true]:before:absolute data-[active=true]:before:w-px data-[active=true]:before:inset-y-2.5 data-[active=true]:before:inset-s-2.5",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -105,13 +105,18 @@ export function Sidebar({ footer, banner, collapsible = true, components, ...res
|
||||
</div>
|
||||
{viewport}
|
||||
{(slots.languageSelect || iconLinks.length > 0 || slots.themeSwitch || footer) && (
|
||||
<div className="flex flex-col border-t p-4 pt-2 empty:hidden">
|
||||
<div className="flex text-fd-muted-foreground items-center empty:hidden">
|
||||
{slots.languageSelect && (
|
||||
<slots.languageSelect.root>
|
||||
<Languages className="size-4.5" />
|
||||
</slots.languageSelect.root>
|
||||
)}
|
||||
<div className="flex flex-col p-4 pt-2">
|
||||
{slots.languageSelect && (
|
||||
<slots.languageSelect.root
|
||||
variant="secondary"
|
||||
className="text-fd-muted-foreground text-start justify-start bg-fd-secondary/50 mb-2"
|
||||
>
|
||||
<Languages className="size-4.5" />
|
||||
<slots.languageSelect.text />
|
||||
<ChevronDown className="ms-auto size-3.5" />
|
||||
</slots.languageSelect.root>
|
||||
)}
|
||||
<div className="flex text-fd-muted-foreground items-center border bg-fd-secondary/50 p-0.5 pe-0 rounded-lg empty:hidden">
|
||||
{iconLinks.map((item, i) => (
|
||||
<LinkItem
|
||||
key={i}
|
||||
@@ -122,7 +127,9 @@ export function Sidebar({ footer, banner, collapsible = true, components, ...res
|
||||
{item.icon}
|
||||
</LinkItem>
|
||||
))}
|
||||
{slots.themeSwitch && <slots.themeSwitch className="ms-auto p-0" />}
|
||||
{slots.themeSwitch && (
|
||||
<slots.themeSwitch className="px-1 py-0 border-y-0 border-e-0 rounded-none ms-auto *:rounded-md" />
|
||||
)}
|
||||
</div>
|
||||
{footer}
|
||||
</div>
|
||||
@@ -201,14 +208,14 @@ function SidebarContent({ ref: refProp, className, children, ...props }: Compone
|
||||
data-sidebar-placeholder=""
|
||||
className="sticky top-(--fd-docs-row-1) z-20 [grid-area:sidebar] pointer-events-none *:pointer-events-auto h-[calc(var(--fd-docs-height)-var(--fd-docs-row-1))] md:layout:[--fd-sidebar-width:268px] max-md:hidden"
|
||||
>
|
||||
{collapsed && <div className="absolute start-0 inset-y-0 w-4" {...rest} />}
|
||||
{collapsed && <div className="absolute inset-s-0 inset-y-0 w-4" {...rest} />}
|
||||
<aside
|
||||
id="nd-sidebar"
|
||||
ref={mergeRefs(ref, refProp, asideRef)}
|
||||
data-collapsed={collapsed}
|
||||
data-hovered={collapsed && hovered}
|
||||
className={cn(
|
||||
'absolute flex flex-col w-full start-0 inset-y-0 items-end bg-fd-card text-sm border-e duration-250 *:w-(--fd-sidebar-width)',
|
||||
'absolute flex flex-col w-full inset-s-0 inset-y-0 items-end bg-fd-card text-sm border-e duration-250 *:w-(--fd-sidebar-width)',
|
||||
collapsed && [
|
||||
'inset-y-2 rounded-xl transition-transform border w-(--fd-sidebar-width)',
|
||||
hovered
|
||||
@@ -229,7 +236,7 @@ function SidebarContent({ ref: refProp, className, children, ...props }: Compone
|
||||
<div
|
||||
data-sidebar-panel=""
|
||||
className={cn(
|
||||
'fixed flex top-[calc(--spacing(4)+var(--fd-docs-row-3))] start-4 shadow-lg transition-opacity rounded-xl p-0.5 border bg-fd-muted text-fd-muted-foreground z-10',
|
||||
'fixed flex top-[calc(--spacing(4)+var(--fd-docs-row-3))] inset-s-4 shadow-lg transition-opacity rounded-xl p-0.5 border bg-fd-muted text-fd-muted-foreground z-10',
|
||||
(!collapsed || hovered) && 'pointer-events-none opacity-0',
|
||||
)}
|
||||
>
|
||||
@@ -262,7 +269,7 @@ function SidebarDrawer({
|
||||
<Base.SidebarDrawerOverlay className="fixed z-40 inset-0 backdrop-blur-xs data-[state=open]:animate-fd-fade-in data-[state=closed]:animate-fd-fade-out" />
|
||||
<Base.SidebarDrawerContent
|
||||
className={cn(
|
||||
'fixed text-[0.9375rem] flex flex-col shadow-lg border-s end-0 inset-y-0 w-[85%] max-w-[380px] z-40 bg-fd-background data-[state=open]:animate-fd-sidebar-in data-[state=closed]:animate-fd-sidebar-out',
|
||||
'fixed text-[0.9375rem] flex flex-col shadow-lg border-s inset-e-0 inset-y-0 w-[85%] max-w-[380px] z-40 bg-fd-background data-[state=open]:animate-fd-sidebar-in data-[state=closed]:animate-fd-sidebar-out',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@@ -377,7 +384,7 @@ function SidebarFolderContent({
|
||||
cn(
|
||||
'relative flex flex-col gap-0.5 pt-0.5',
|
||||
depth === 1 &&
|
||||
"before:content-[''] before:absolute before:w-px before:inset-y-1 before:bg-fd-border before:start-2.5",
|
||||
"before:content-[''] before:absolute before:w-px before:inset-y-1 before:bg-fd-border before:inset-s-2.5",
|
||||
typeof className === 'function' ? className(state) : className,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export function Header(props: ComponentProps<'header'>) {
|
||||
color: 'ghost',
|
||||
size: 'icon-sm',
|
||||
}),
|
||||
'text-fd-muted-foreground data-[collapsed=false]:hidden max-md:hidden',
|
||||
'-ms-1.5 text-fd-muted-foreground data-[collapsed=false]:hidden max-md:hidden',
|
||||
)}
|
||||
>
|
||||
<SidebarIcon />
|
||||
|
||||
@@ -306,14 +306,7 @@ export function Sidebar({ banner, footer, components, collapsible = true, ...res
|
||||
if (typeof footer === 'function') return createElement(footer, props);
|
||||
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
className={cn(
|
||||
'hidden flex-row text-fd-muted-foreground items-center border-t p-4 pt-2',
|
||||
iconLinks.length > 0 && 'max-lg:flex',
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
<div {...props}>
|
||||
{props.children}
|
||||
{footer}
|
||||
</div>
|
||||
@@ -375,6 +368,10 @@ export function Sidebar({ banner, footer, components, collapsible = true, ...res
|
||||
})}
|
||||
{viewport}
|
||||
{renderFooter({
|
||||
className: cn(
|
||||
'hidden flex-row text-fd-muted-foreground items-center border-t px-4 py-2.5',
|
||||
iconLinks.length > 0 && 'max-lg:flex',
|
||||
),
|
||||
children: iconLinks.map((item, i) => (
|
||||
<LinkItem
|
||||
key={i}
|
||||
@@ -415,7 +412,7 @@ export function Sidebar({ banner, footer, components, collapsible = true, ...res
|
||||
{viewport}
|
||||
{renderFooter({
|
||||
className: cn(
|
||||
'hidden flex-row items-center justify-end',
|
||||
'hidden flex-row text-fd-muted-foreground items-center border-t p-4 pt-2 justify-end',
|
||||
(slots.languageSelect || slots.themeSwitch) && 'flex',
|
||||
iconLinks.length > 0 && 'max-lg:flex',
|
||||
),
|
||||
|
||||
@@ -4,10 +4,18 @@ import { useI18n } from '@/contexts/i18n';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { buttonVariants } from '@/components/ui/button';
|
||||
import type { VariantProps } from 'class-variance-authority';
|
||||
|
||||
export type LanguageSelectProps = ComponentProps<'button'>;
|
||||
export interface LanguageSelectProps extends ComponentProps<'button'> {
|
||||
variant?: VariantProps<typeof buttonVariants>['variant'];
|
||||
}
|
||||
|
||||
export function LanguageSelect(props: LanguageSelectProps): React.ReactElement {
|
||||
export function LanguageSelect({
|
||||
className,
|
||||
variant = 'ghost',
|
||||
children,
|
||||
...rest
|
||||
}: LanguageSelectProps): React.ReactElement {
|
||||
const context = useI18n();
|
||||
if (!context.locales) throw new Error('Missing `<I18nProvider />`');
|
||||
|
||||
@@ -15,19 +23,15 @@ export function LanguageSelect(props: LanguageSelectProps): React.ReactElement {
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
aria-label={context.text.chooseLanguage}
|
||||
{...props}
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: 'ghost',
|
||||
className: 'gap-1.5 p-1.5',
|
||||
}),
|
||||
props.className,
|
||||
)}
|
||||
className={(s) =>
|
||||
cn(buttonVariants({ variant }), 'gap-1.5 p-1.5', s.open && 'bg-fd-accent', className)
|
||||
}
|
||||
{...rest}
|
||||
>
|
||||
{props.children}
|
||||
{children}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="flex flex-col overflow-x-hidden p-0">
|
||||
<p className="mb-1 p-2 text-xs font-medium text-fd-muted-foreground">
|
||||
<PopoverContent className="flex flex-col gap-0.5 p-1">
|
||||
<p className="p-2 text-xs font-medium text-fd-muted-foreground">
|
||||
{context.text.chooseLanguage}
|
||||
</p>
|
||||
{context.locales.map((item) => (
|
||||
@@ -35,10 +39,10 @@ export function LanguageSelect(props: LanguageSelectProps): React.ReactElement {
|
||||
key={item.locale}
|
||||
type="button"
|
||||
className={cn(
|
||||
'p-2 text-start text-sm',
|
||||
'px-2 py-1.5 text-start text-sm rounded-lg transition-colors',
|
||||
item.locale === context.locale
|
||||
? 'bg-fd-primary/10 font-medium text-fd-primary'
|
||||
: 'hover:bg-fd-accent hover:text-fd-accent-foreground',
|
||||
? 'bg-fd-primary/10 text-fd-primary'
|
||||
: 'text-fd-muted-foreground hover:bg-fd-accent hover:text-fd-accent-foreground',
|
||||
)}
|
||||
onClick={() => {
|
||||
context.onChange?.(item.locale);
|
||||
|
||||
@@ -29,7 +29,7 @@ export function ThemeSwitch({ className, mode = 'light-dark', ...props }: ThemeS
|
||||
}, []);
|
||||
|
||||
const container = cn(
|
||||
'inline-flex items-center rounded-full border p-1 *:rounded-full',
|
||||
'inline-flex items-center rounded-full border p-1 overflow-hidden *:rounded-full',
|
||||
className,
|
||||
);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import { createLinkItemRenderer } from '@/components/sidebar/link-item';
|
||||
import { buttonVariants } from '@/components/ui/button';
|
||||
import { SearchTrigger } from '@/layouts/shared/slots/search-trigger';
|
||||
import { Check, ChevronsUpDown, Languages, SidebarIcon } from 'lucide-react';
|
||||
import { Check, ChevronDown, ChevronsUpDown, Languages, SidebarIcon } from 'lucide-react';
|
||||
import { mergeRefs } from '@/utils/merge-refs';
|
||||
import { useDocsLayout } from '../client';
|
||||
import { LinkItem } from '@/layouts/shared';
|
||||
@@ -29,7 +29,7 @@ const itemVariants = cva(
|
||||
'transition-colors hover:bg-fd-accent/50 hover:text-fd-accent-foreground/80 hover:transition-none',
|
||||
},
|
||||
highlight: {
|
||||
true: "data-[active=true]:before:content-[''] data-[active=true]:before:bg-fd-primary data-[active=true]:before:absolute data-[active=true]:before:w-px data-[active=true]:before:inset-y-2.5 data-[active=true]:before:start-2.5",
|
||||
true: "data-[active=true]:before:content-[''] data-[active=true]:before:bg-fd-primary data-[active=true]:before:absolute data-[active=true]:before:w-px data-[active=true]:before:inset-y-2.5 data-[active=true]:before:inset-s-2.5",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -103,13 +103,18 @@ export function Sidebar({ footer, banner, collapsible = true, components, ...res
|
||||
</div>
|
||||
{viewport}
|
||||
{(slots.languageSelect || iconLinks.length > 0 || slots.themeSwitch || footer) && (
|
||||
<div className="flex flex-col border-t p-4 pt-2 empty:hidden">
|
||||
<div className="flex text-fd-muted-foreground items-center empty:hidden">
|
||||
{slots.languageSelect && (
|
||||
<slots.languageSelect.root>
|
||||
<Languages className="size-4.5" />
|
||||
</slots.languageSelect.root>
|
||||
)}
|
||||
<div className="flex flex-col p-4 pt-2">
|
||||
{slots.languageSelect && (
|
||||
<slots.languageSelect.root
|
||||
variant="secondary"
|
||||
className="text-fd-muted-foreground text-start justify-start bg-fd-secondary/50 mb-2"
|
||||
>
|
||||
<Languages className="size-4.5" />
|
||||
<slots.languageSelect.text />
|
||||
<ChevronDown className="ms-auto size-3.5" />
|
||||
</slots.languageSelect.root>
|
||||
)}
|
||||
<div className="flex text-fd-muted-foreground items-center border bg-fd-secondary/50 p-0.5 pe-0 rounded-lg empty:hidden">
|
||||
{iconLinks.map((item, i) => (
|
||||
<LinkItem
|
||||
key={i}
|
||||
@@ -120,7 +125,9 @@ export function Sidebar({ footer, banner, collapsible = true, components, ...res
|
||||
{item.icon}
|
||||
</LinkItem>
|
||||
))}
|
||||
{slots.themeSwitch && <slots.themeSwitch className="ms-auto p-0" />}
|
||||
{slots.themeSwitch && (
|
||||
<slots.themeSwitch className="px-1 py-0 border-y-0 border-e-0 rounded-none ms-auto *:rounded-md" />
|
||||
)}
|
||||
</div>
|
||||
{footer}
|
||||
</div>
|
||||
@@ -199,14 +206,14 @@ function SidebarContent({ ref: refProp, className, children, ...props }: Compone
|
||||
data-sidebar-placeholder=""
|
||||
className="sticky top-(--fd-docs-row-1) z-20 [grid-area:sidebar] pointer-events-none *:pointer-events-auto h-[calc(var(--fd-docs-height)-var(--fd-docs-row-1))] md:layout:[--fd-sidebar-width:268px] max-md:hidden"
|
||||
>
|
||||
{collapsed && <div className="absolute start-0 inset-y-0 w-4" {...rest} />}
|
||||
{collapsed && <div className="absolute inset-s-0 inset-y-0 w-4" {...rest} />}
|
||||
<aside
|
||||
id="nd-sidebar"
|
||||
ref={mergeRefs(ref, refProp, asideRef)}
|
||||
data-collapsed={collapsed}
|
||||
data-hovered={collapsed && hovered}
|
||||
className={cn(
|
||||
'absolute flex flex-col w-full start-0 inset-y-0 items-end bg-fd-card text-sm border-e duration-250 *:w-(--fd-sidebar-width)',
|
||||
'absolute flex flex-col w-full inset-s-0 inset-y-0 items-end bg-fd-card text-sm border-e duration-250 *:w-(--fd-sidebar-width)',
|
||||
collapsed && [
|
||||
'inset-y-2 rounded-xl transition-transform border w-(--fd-sidebar-width)',
|
||||
hovered
|
||||
@@ -227,7 +234,7 @@ function SidebarContent({ ref: refProp, className, children, ...props }: Compone
|
||||
<div
|
||||
data-sidebar-panel=""
|
||||
className={cn(
|
||||
'fixed flex top-[calc(--spacing(4)+var(--fd-docs-row-3))] start-4 shadow-lg transition-opacity rounded-xl p-0.5 border bg-fd-muted text-fd-muted-foreground z-10',
|
||||
'fixed flex top-[calc(--spacing(4)+var(--fd-docs-row-3))] inset-s-4 shadow-lg transition-opacity rounded-xl p-0.5 border bg-fd-muted text-fd-muted-foreground z-10',
|
||||
(!collapsed || hovered) && 'pointer-events-none opacity-0',
|
||||
)}
|
||||
>
|
||||
@@ -260,7 +267,7 @@ function SidebarDrawer({
|
||||
<Base.SidebarDrawerOverlay className="fixed z-40 inset-0 backdrop-blur-xs data-[state=open]:animate-fd-fade-in data-[state=closed]:animate-fd-fade-out" />
|
||||
<Base.SidebarDrawerContent
|
||||
className={cn(
|
||||
'fixed text-[0.9375rem] flex flex-col shadow-lg border-s end-0 inset-y-0 w-[85%] max-w-[380px] z-40 bg-fd-background data-[state=open]:animate-fd-sidebar-in data-[state=closed]:animate-fd-sidebar-out',
|
||||
'fixed text-[0.9375rem] flex flex-col shadow-lg border-s inset-e-0 inset-y-0 w-[85%] max-w-[380px] z-40 bg-fd-background data-[state=open]:animate-fd-sidebar-in data-[state=closed]:animate-fd-sidebar-out',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@@ -368,7 +375,7 @@ function SidebarFolderContent({
|
||||
className={cn(
|
||||
'relative',
|
||||
depth === 1 &&
|
||||
"before:content-[''] before:absolute before:w-px before:inset-y-1 before:bg-fd-border before:start-2.5",
|
||||
"before:content-[''] before:absolute before:w-px before:inset-y-1 before:bg-fd-border before:inset-s-2.5",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -58,7 +58,7 @@ export function Header(props: ComponentProps<'header'>) {
|
||||
color: 'ghost',
|
||||
size: 'icon-sm',
|
||||
}),
|
||||
'text-fd-muted-foreground data-[collapsed=false]:hidden max-md:hidden',
|
||||
'-ms-1.5 text-fd-muted-foreground data-[collapsed=false]:hidden max-md:hidden',
|
||||
)}
|
||||
>
|
||||
<SidebarIcon />
|
||||
|
||||
@@ -298,14 +298,7 @@ export function Sidebar({ banner, footer, components, collapsible = true, ...res
|
||||
if (typeof footer === 'function') return createElement(footer, props);
|
||||
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
className={cn(
|
||||
'hidden flex-row text-fd-muted-foreground items-center border-t p-4 pt-2',
|
||||
iconLinks.length > 0 && 'max-lg:flex',
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
<div {...props}>
|
||||
{props.children}
|
||||
{footer}
|
||||
</div>
|
||||
@@ -365,6 +358,10 @@ export function Sidebar({ banner, footer, components, collapsible = true, ...res
|
||||
})}
|
||||
{viewport}
|
||||
{renderFooter({
|
||||
className: cn(
|
||||
'hidden flex-row text-fd-muted-foreground items-center border-t px-4 py-2.5',
|
||||
iconLinks.length > 0 && 'max-lg:flex',
|
||||
),
|
||||
children: iconLinks.map((item, i) => (
|
||||
<LinkItem
|
||||
key={i}
|
||||
@@ -405,7 +402,7 @@ export function Sidebar({ banner, footer, components, collapsible = true, ...res
|
||||
{viewport}
|
||||
{renderFooter({
|
||||
className: cn(
|
||||
'hidden flex-row items-center justify-end',
|
||||
'hidden flex-row text-fd-muted-foreground items-center border-t p-4 pt-2 justify-end',
|
||||
(slots.languageSelect || slots.themeSwitch) && 'flex',
|
||||
iconLinks.length > 0 && 'max-lg:flex',
|
||||
),
|
||||
|
||||
@@ -4,10 +4,18 @@ import { useI18n } from '@/contexts/i18n';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { buttonVariants } from '@/components/ui/button';
|
||||
import type { VariantProps } from 'class-variance-authority';
|
||||
|
||||
export type LanguageSelectProps = ComponentProps<'button'>;
|
||||
export interface LanguageSelectProps extends ComponentProps<'button'> {
|
||||
variant?: VariantProps<typeof buttonVariants>['variant'];
|
||||
}
|
||||
|
||||
export function LanguageSelect(props: LanguageSelectProps): React.ReactElement {
|
||||
export function LanguageSelect({
|
||||
className,
|
||||
variant = 'ghost',
|
||||
children,
|
||||
...rest
|
||||
}: LanguageSelectProps): React.ReactElement {
|
||||
const context = useI18n();
|
||||
if (!context.locales) throw new Error('Missing `<I18nProvider />`');
|
||||
|
||||
@@ -15,19 +23,17 @@ export function LanguageSelect(props: LanguageSelectProps): React.ReactElement {
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
aria-label={context.text.chooseLanguage}
|
||||
{...props}
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: 'ghost',
|
||||
className: 'gap-1.5 p-1.5',
|
||||
}),
|
||||
props.className,
|
||||
buttonVariants({ variant }),
|
||||
'gap-1.5 p-1.5 data-[state=open]:bg-fd-accent',
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{props.children}
|
||||
{children}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="flex flex-col overflow-x-hidden p-0">
|
||||
<p className="mb-1 p-2 text-xs font-medium text-fd-muted-foreground">
|
||||
<PopoverContent className="flex flex-col gap-0.5 p-1">
|
||||
<p className="p-2 text-xs font-medium text-fd-muted-foreground">
|
||||
{context.text.chooseLanguage}
|
||||
</p>
|
||||
{context.locales.map((item) => (
|
||||
@@ -35,10 +41,10 @@ export function LanguageSelect(props: LanguageSelectProps): React.ReactElement {
|
||||
key={item.locale}
|
||||
type="button"
|
||||
className={cn(
|
||||
'p-2 text-start text-sm',
|
||||
'px-2 py-1.5 text-start text-sm rounded-lg transition-colors',
|
||||
item.locale === context.locale
|
||||
? 'bg-fd-primary/10 font-medium text-fd-primary'
|
||||
: 'hover:bg-fd-accent hover:text-fd-accent-foreground',
|
||||
? 'bg-fd-primary/10 text-fd-primary'
|
||||
: 'text-fd-muted-foreground hover:bg-fd-accent hover:text-fd-accent-foreground',
|
||||
)}
|
||||
onClick={() => {
|
||||
context.onChange?.(item.locale);
|
||||
|
||||
@@ -29,7 +29,7 @@ export function ThemeSwitch({ className, mode = 'light-dark', ...props }: ThemeS
|
||||
}, []);
|
||||
|
||||
const container = cn(
|
||||
'inline-flex items-center rounded-full border p-1 *:rounded-full',
|
||||
'inline-flex items-center rounded-full border p-1 overflow-hidden *:rounded-full',
|
||||
className,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user