-
+
+
+ {breadcrumb.section && breadcrumb.sectionLink ? (
+ <>
+
+ {breadcrumb.section}
+
+
+ {breadcrumb.title}
+ >
+ ) : (
+ {breadcrumb.title}
+ )}
+
+
+
+
+ Version {version}
+
+
+
+
+
+
+
+
+
+
+
+
-
- Version {version} - Alpha
-
-
);
};
diff --git a/docs-ui/src/components/Toolbar/theme-name.module.css b/docs-ui/src/components/Toolbar/theme-name.module.css
deleted file mode 100644
index 56f3401d8d..0000000000
--- a/docs-ui/src/components/Toolbar/theme-name.module.css
+++ /dev/null
@@ -1,110 +0,0 @@
-.Select {
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 0.75rem;
- height: 3rem;
- padding-left: 1.25rem;
- padding-right: 1rem;
- margin: 0;
- outline: 0;
- border: 1px solid var(--color-gray-200);
- border-radius: 3rem;
- font-family: inherit;
- font-size: 1rem;
- line-height: 1.5rem;
- color: var(--color-gray-900);
- cursor: pointer;
- user-select: none;
- background-color: var(--action);
-
- &:focus-visible {
- outline: 2px solid var(--color-blue);
- outline-offset: -1px;
- }
-}
-
-.Popup {
- box-sizing: border-box;
- padding-block: 0.25rem;
- border-radius: 0.375rem;
- background-color: var(--bg);
- color: var(--color-gray-900);
- border: 1px solid var(--border);
- padding-inline: 0.25rem;
- transform-origin: var(--transform-origin);
- transition: transform 150ms, opacity 150ms;
-
- &[data-starting-style],
- &[data-ending-style] {
- opacity: 0;
- transform: scale(0.9);
- }
-
- &[data-side='none'] {
- transition: none;
- transform: none;
- opacity: 1;
- }
-
- @media (prefers-color-scheme: light) {
- outline: 1px solid var(--color-gray-200);
- box-shadow: 0px 10px 15px -3px var(--color-gray-200),
- 0px 4px 6px -4px var(--color-gray-200);
- }
-
- @media (prefers-color-scheme: dark) {
- outline: 1px solid var(--color-gray-300);
- outline-offset: -1px;
- }
-}
-
-.Popup[data-trigger='Select'] {
- min-width: var(--trigger-width);
-
- .ListBox {
- display: block;
- width: unset;
- max-height: inherit;
- min-height: unset;
- border: none;
-
- .react-aria-Header {
- padding-left: 1.571rem;
- }
- }
-
- .Item {
- position: relative;
- padding: 0 0.571rem 0 1.571rem;
- height: 2rem;
- display: flex;
- align-items: center;
-
- &[data-focus-visible] {
- outline: none;
- }
-
- &[data-selected] {
- font-weight: 600;
- background: unset;
- color: var(--text-color);
-
- &::before {
- content: '✓';
- content: '✓' / '';
- alt: ' ';
- position: absolute;
- left: 4px;
- }
- }
-
- &[data-focused],
- &[data-pressed] {
- background: var(--bg);
- color: var(--primary);
- cursor: pointer;
- }
- }
-}
diff --git a/docs-ui/src/components/Toolbar/theme-name.tsx b/docs-ui/src/components/Toolbar/theme-name.tsx
deleted file mode 100644
index ae9e7f9f35..0000000000
--- a/docs-ui/src/components/Toolbar/theme-name.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-'use client';
-
-import {
- Button,
- ListBox,
- ListBoxItem,
- Popover,
- Select,
- SelectValue,
-} from 'react-aria-components';
-import styles from './theme-name.module.css';
-import { usePlayground } from '@/utils/playground-context';
-import { RiArrowDownSLine } from '@remixicon/react';
-
-const themes = [
- { name: 'Backstage', value: 'backstage' },
- { name: 'Spotify', value: 'spotify' },
- { name: 'Custom theme', value: 'custom' },
-];
-
-export const ThemeNameSelector = () => {
- const { selectedThemeName, setSelectedThemeName } = usePlayground();
-
- return (
-
- );
-};
diff --git a/docs-ui/src/components/Toolbar/theme.module.css b/docs-ui/src/components/Toolbar/theme.module.css
deleted file mode 100644
index c5490a72d7..0000000000
--- a/docs-ui/src/components/Toolbar/theme.module.css
+++ /dev/null
@@ -1,79 +0,0 @@
-.tabs {
- border-radius: 0.375rem;
- width: 100%;
-}
-
-.tabsTheme {
- width: 100px;
- border-radius: 0.375rem;
-}
-
-.list {
- display: flex;
- position: relative;
- z-index: 0;
- gap: 0.25rem;
-}
-
-.tab {
- display: flex;
- align-items: center;
- justify-content: center;
- border: 0;
- margin: 0;
- outline: 0;
- background: none;
- appearance: none;
- color: var(--secondary);
- user-select: none;
- flex: 1;
- cursor: pointer;
- width: 3rem;
- height: 3rem;
-
- &[data-selected] {
- color: var(--primary);
-
- & p {
- color: var(--primary);
- }
- }
-
- @media (hover: hover) {
- &:hover {
- color: var(--primary);
- }
- }
-
- &:focus-visible {
- position: relative;
-
- &::before {
- content: '';
- position: absolute;
- inset: 0.25rem 0;
- border-radius: 0.25rem;
- outline: 2px solid var(--action);
- outline-offset: -1px;
- }
- }
-}
-
-.tab p {
- color: var(--secondary) !important;
-}
-
-.indicator {
- position: absolute;
- z-index: -1;
- left: 0;
- top: 50%;
- translate: var(--active-tab-left) -50%;
- width: var(--active-tab-width);
- height: 3rem;
- border-radius: 3rem;
- background-color: var(--action);
- transition-property: translate, width;
- transition-duration: 200ms;
- transition-timing-function: ease-in-out;
-}
diff --git a/docs-ui/src/components/Toolbar/theme.tsx b/docs-ui/src/components/Toolbar/theme.tsx
deleted file mode 100644
index 7ece7bfe7b..0000000000
--- a/docs-ui/src/components/Toolbar/theme.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-'use client';
-
-import { Tabs } from '@base-ui-components/react/tabs';
-import { usePlayground } from '@/utils/playground-context';
-import styles from './theme.module.css';
-import { RiMoonLine, RiSunLine } from '@remixicon/react';
-
-export const ThemeSelector = () => {
- const { selectedTheme, setSelectedTheme } = usePlayground();
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/docs-ui/src/utils/playground-context.tsx b/docs-ui/src/utils/playground-context.tsx
index 2f8ffbaee4..401b079966 100644
--- a/docs-ui/src/utils/playground-context.tsx
+++ b/docs-ui/src/utils/playground-context.tsx
@@ -4,6 +4,7 @@ import {
ReactNode,
useState,
useEffect,
+ Key,
} from 'react';
import { components } from './data';
@@ -16,8 +17,8 @@ const PlaygroundContext = createContext<{
setSelectedScreenSizes: (screenSizes: string[]) => void;
selectedComponents: string[];
setSelectedComponents: (components: string[]) => void;
- selectedTheme: Theme;
- setSelectedTheme: (theme: Theme) => void;
+ selectedTheme: Set
;
+ setSelectedTheme: (keys: Set) => void;
selectedThemeName: ThemeName;
setSelectedThemeName: (themeName: ThemeName) => void;
}>({
@@ -25,7 +26,7 @@ const PlaygroundContext = createContext<{
setSelectedScreenSizes: () => {},
selectedComponents: [],
setSelectedComponents: () => {},
- selectedTheme: 'light',
+ selectedTheme: new Set(['light']),
setSelectedTheme: () => {},
selectedThemeName: 'backstage',
setSelectedThemeName: () => {},
@@ -40,16 +41,24 @@ export const PlaygroundProvider = ({ children }: { children: ReactNode }) => {
const [selectedComponents, setSelectedComponents] = useState(
components.map(component => component.slug),
);
- const [selectedTheme, setSelectedTheme] = useState('light');
+ const [selectedTheme, setSelectedTheme] = useState>(
+ new Set(['light']),
+ );
const [selectedThemeName, setSelectedThemeName] =
useState('backstage');
// Load saved theme from localStorage after hydration
useEffect(() => {
if (isBrowser) {
- const savedTheme = localStorage.getItem('theme-mode') as Theme;
- if (savedTheme) {
- setSelectedTheme(savedTheme);
+ const savedThemeString = localStorage.getItem('theme-mode');
+ if (savedThemeString) {
+ // Parse the comma-separated string back into a Set
+ const themeArray = savedThemeString
+ .split(',')
+ .filter(Boolean) as Theme[];
+ setSelectedTheme(new Set(themeArray));
+ } else {
+ setSelectedTheme(new Set(['light']));
}
}
}, [isBrowser]);
@@ -68,9 +77,9 @@ export const PlaygroundProvider = ({ children }: { children: ReactNode }) => {
if (isBrowser) {
document.documentElement.setAttribute(
'data-theme-mode',
- selectedTheme || 'light',
+ Array.from(selectedTheme).join(','),
);
- localStorage.setItem('theme-mode', selectedTheme || 'light');
+ localStorage.setItem('theme-mode', Array.from(selectedTheme).join(','));
}
}, [selectedTheme, isBrowser]);