Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ module.exports = {
},
},
onBrokenLinks: 'warn',
onBrokenMarkdownLinks: 'warn',
markdown: {
hooks: {
onBrokenMarkdownLinks: 'warn',
},
},
favicon: 'img/meta/favicon-96x96.png',
organizationName: 'ionic-team',
projectName: 'ionic-docs',
Expand Down Expand Up @@ -353,7 +357,7 @@ module.exports = {
name: 'ionic-docs-ads',
async loadContent() {
const repoName = 'ionicframeworkcom';
const endpoint = prismic.getEndpoint(repoName);
const endpoint = prismic.getRepositoryEndpoint(repoName);
const client = prismic.createClient(endpoint, {
fetch,
});
Expand Down
6,515 changes: 3,928 additions & 2,587 deletions package-lock.json

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@
]
},
"dependencies": {
"@docusaurus/core": "^3.7.0",
"@docusaurus/mdx-loader": "^3.7.0",
"@docusaurus/plugin-client-redirects": "^3.7.0",
"@docusaurus/preset-classic": "^3.7.0",
"@docusaurus/core": "^3.10.2",
"@docusaurus/mdx-loader": "^3.10.2",
"@docusaurus/plugin-client-redirects": "^3.10.2",
"@docusaurus/preset-classic": "^3.10.2",
"@floating-ui/react": "^0.27.20",
"@ionic-internal/ionic-ds": "^7.0.0",
"@mdx-js/react": "^3.0.0",
"@prismicio/client": "^6.4.2",
"@prismicio/react": "^2.2.0",
"@prismicio/client": "^7.21.8",
"@prismicio/react": "^3.4.1",
"@stackblitz/sdk": "^1.6.0",
"@tippyjs/react": "^4.2.6",
"clsx": "^1.1.1",
"crowdin": "^3.5.0",
"docusaurus-plugin-copy-page-button": "^0.8.2",
Expand All @@ -55,18 +55,18 @@
"fs-extra": "^9.1.0",
"modern-normalize": "^1.1.0",
"prism-react-renderer": "^2.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"remark-html": "^16.0.1",
"remark-parse": "^11.0.0",
"sass": "^1.44.0",
"semver": "^7.3.5"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.7.0",
"@docusaurus/tsconfig": "^3.7.0",
"@docusaurus/module-type-aliases": "^3.10.2",
"@docusaurus/tsconfig": "^3.10.2",
"@ionic/prettier-config": "^3.0.0",
"@types/react": "^18.2.29",
"@types/react": "^19.2.18",
"cspell": "^6.31.3",
"html-loader": "^3.1.0",
"hygen": "^6.2.11",
Expand Down
4 changes: 2 additions & 2 deletions src/components/global/Codepen/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import React, { type ReactNode } from 'react';

import { useScript } from '@site/src/utils/hooks';

function CodePen(props): JSX.Element {
function CodePen(props): ReactNode {
const status = useScript('https://static.codepen.io/assets/embed/ei.js');
// console.log('test',status, props)
return (
Expand Down
4 changes: 2 additions & 2 deletions src/components/global/DocsCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { type ReactNode } from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
Expand All @@ -16,7 +16,7 @@ interface Props extends React.HTMLAttributes<HTMLDivElement> {
size?: 'md' | 'lg';
}

function DocsCard(props: Props): JSX.Element {
function DocsCard(props: Props): ReactNode {
const isStatic = typeof props.href === 'undefined';
const isOutbound = typeof props.href !== 'undefined' ? /^http/.test(props.href) : false;
const header = props.header === 'undefined' ? null : <header className="Card-header">{props.header}</header>;
Expand Down
4 changes: 2 additions & 2 deletions src/components/global/DocsCards/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import React, { type ReactNode } from 'react';

import './cards.css';

function DocsCards(props): JSX.Element {
function DocsCards(props): ReactNode {
return <docs-cards class={props.className}>{props.children}</docs-cards>;
}

Expand Down
34 changes: 14 additions & 20 deletions src/components/global/Playground/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import { EditorOptions, openAngularEditor, openHtmlEditor, openReactEditor, open
import { useColorMode } from '@docusaurus/theme-common';
import { ConsoleItem, Mode, UsageTarget } from './playground.types';

import Tippy from '@tippyjs/react';
import 'tippy.js/dist/tippy.css';
import Tooltip from '../Tooltip';
import PlaygroundTabs from '../PlaygroundTabs';
import TabItem from '@theme/TabItem';
import TabItem from '../PlaygroundTabs/TabItem';

import { IconHtml, IconTs, IconVue, IconDefault, IconCss, IconDots } from './icons';

Expand Down Expand Up @@ -47,10 +46,10 @@ const ControlButton = forwardRef(
);
if (disabled) {
return (
<Tippy theme="playground" arrow={false} placement="bottom" content={`Unavailable for ${label}`}>
{/* Tippy requires a wrapper element for disabled elements: https://atomiks.github.io/tippyjs/v5/creating-tooltips/#disabled-elements */}
<Tooltip content={`Unavailable for ${label}`}>
{/* Disabled elements do not emit pointer events, so the wrapper is what triggers the tooltip. */}
<div>{controlButton}</div>
</Tippy>
</Tooltip>
);
}
return controlButton;
Expand Down Expand Up @@ -652,9 +651,7 @@ export default function Playground({
value={fileName}
label={fileName}
key={fileName}
{...{
icon: getFileIcon(fileName),
}}
icon={getFileIcon(fileName)}
>
<div id={getCodeSnippetId(usageTarget, fileName)}>{codeSnippets[usageTarget][fileName]}</div>
</TabItem>
Expand Down Expand Up @@ -742,7 +739,7 @@ export default function Playground({
/>
</div>
<div className="playground__control-group playground__control-group--end">
<Tippy theme="playground" arrow={false} placement="bottom" content="Open in StackBlitz">
<Tooltip content="Open in StackBlitz">
<button className="playground__icon-button playground__icon-button--primary" onClick={openEditor}>
<svg
aria-hidden="true"
Expand All @@ -759,11 +756,8 @@ export default function Playground({
/>
</svg>
</button>
</Tippy>
<Tippy
theme="playground"
arrow={false}
placement="bottom"
</Tooltip>
<Tooltip
content={
hasUsageTargetOptions
? 'For multi-file examples, use the copy buttons on the code blocks'
Expand Down Expand Up @@ -792,8 +786,8 @@ export default function Playground({
<rect x="3" y="3" width="8" height="8" rx="1.5" stroke="current" />
</svg>
</button>
</Tippy>
<Tippy theme="playground" arrow={false} placement="bottom" content="Reset demo">
</Tooltip>
<Tooltip content="Reset demo">
<button className="playground__icon-button" onClick={resetDemo}>
<svg
aria-hidden="true"
Expand All @@ -817,8 +811,8 @@ export default function Playground({
/>
</svg>
</button>
</Tippy>
<Tippy theme="playground" arrow={false} placement="bottom" content="Report an issue">
</Tooltip>
<Tooltip content="Report an issue">
<a
className="playground__icon-button"
href="https://github.com/ionic-team/ionic-docs/issues/new/choose"
Expand All @@ -833,7 +827,7 @@ export default function Playground({
/>
</svg>
</a>
</Tippy>
</Tooltip>
</div>
</div>
{renderIframes
Expand Down
13 changes: 0 additions & 13 deletions src/components/global/Playground/playground.css
Original file line number Diff line number Diff line change
Expand Up @@ -383,19 +383,6 @@
background: var(--playground-code-background);
}

/* Tooltip styling */
.tippy-box[data-theme="playground"] {
background-color: var(--c-carbon-90);
border-radius: 8px;
line-height: initial;
font-size: 12px;
}

.tippy-box[data-theme="playground"] .tippy-content {
padding: 6px 10px;
}


/* Loading Screen */
.playground .playground__loading {
position: absolute;
Expand Down
35 changes: 35 additions & 0 deletions src/components/global/PlaygroundTabs/TabItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* A single tab panel within PlaygroundTabs.
*
* PlaygroundTabs decides which panel is visible by cloning these with a
* className, so this renders the panel and nothing else. Use it in place of
* `@theme/TabItem`, which only works inside Docusaurus' own Tabs.
*/

import React, { type ReactNode } from 'react';
import clsx from 'clsx';

import styles from './styles.module.css';

export interface TabItemProps {
/** Identifies the tab. Must be unique among sibling tabs. */
value: string;
/** Text shown in the tab. Falls back to `value`. */
label?: string;
/** Rendered before the label in the tab. */
icon?: ReactNode;
/** Selects this tab when nothing else is selected. */
default?: boolean;
/** Extra attributes spread onto the tab itself. */
attributes?: { [key: string]: unknown };
className?: string;
children?: ReactNode;
}

export default function TabItem({ children, className }: TabItemProps): ReactNode {
return (
<div role="tabpanel" className={clsx(styles.tabPanel, className)}>
{children}
</div>
);
}
22 changes: 16 additions & 6 deletions src/components/global/PlaygroundTabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,34 @@
* LICENSE file in the root directory of this source tree.
*/

import React, { useState, cloneElement, isValidElement, type ReactElement, useRef, createRef, useEffect } from 'react';
import React, {
useState,
cloneElement,
isValidElement,
type ReactElement,
type ReactNode,
useRef,
createRef,
useEffect,
} from 'react';
import useIsBrowser from '@docusaurus/useIsBrowser';
import { duplicates } from '@docusaurus/theme-common';
import { useScrollPositionBlocker } from '@docusaurus/theme-common/internal';
import type { Props } from '@theme/Tabs';
import type { Props as TabItemProps } from '@theme/TabItem';
import type { TabItemProps } from './TabItem';

import clsx from 'clsx';

import styles from './styles.module.css';

// A very rough duck type, but good enough to guard against mistakes while
// allowing customization
function isTabItem(comp: ReactElement): comp is ReactElement<TabItemProps & { icon?: JSX.Element }> {
return typeof comp.props.value !== 'undefined';
function isTabItem(comp: ReactElement): comp is ReactElement<TabItemProps & { icon?: ReactNode }> {
const { props } = comp;
return !!props && typeof props === 'object' && 'value' in props;
}

function TabsComponent(props: Props): JSX.Element {
function TabsComponent(props: Props): ReactNode {
const { lazy, block, defaultValue: defaultValueProp, values: valuesProp, groupId, className } = props;
const [leftNavVisible, setLeftNavVisible] = useState(false);
const [rightNavVisible, setRightNavVisible] = useState(false);
Expand Down Expand Up @@ -233,7 +243,7 @@ function TabsComponent(props: Props): JSX.Element {
);
}

export default function PlaygroundTabs(props: Props): JSX.Element {
export default function PlaygroundTabs(props: Props): ReactNode {
const isBrowser = useIsBrowser();
return (
<TabsComponent
Expand Down
4 changes: 4 additions & 0 deletions src/components/global/PlaygroundTabs/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
margin-top: 0 !important;
}

.tabPanel > *:last-child {
margin-bottom: 0;
}

.tabIcon {
display: inline-flex;
padding: 0 8px;
Expand Down
74 changes: 74 additions & 0 deletions src/components/global/Tooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* A hover/focus tooltip for a single child element.
*
* The child becomes the trigger, so it must be an element that accepts a ref
* and DOM props. Disabled elements never emit pointer events, so wrap those in
* a plain element (e.g. `<div>`) and pass that as the child instead.
*/

import React, { cloneElement, useState, type ReactElement, type ReactNode, type Ref } from 'react';
import {
autoUpdate,
flip,
offset,
shift,
useDismiss,
useFloating,
useFocus,
useHover,
useInteractions,
useMergeRefs,
useRole,
useTransitionStyles,
FloatingPortal,
} from '@floating-ui/react';

import './tooltip.css';

interface TooltipProps {
content: ReactNode;
/** The trigger element. Its `ref` is declared here because it arrives as a prop. */
children: ReactElement<{ ref?: Ref<Element> } & Record<string, unknown>>;
}

export default function Tooltip({ content, children }: TooltipProps): ReactNode {
const [open, setOpen] = useState(false);

const { refs, floatingStyles, context } = useFloating({
open,
onOpenChange: setOpen,
placement: 'bottom',
middleware: [offset(10), flip(), shift({ padding: 5 })],
whileElementsMounted: autoUpdate,
});

const { getReferenceProps, getFloatingProps } = useInteractions([
useHover(context, { move: false }),
useFocus(context),
useDismiss(context),
useRole(context, { role: 'tooltip' }),
]);

// Fade in/out rather than appearing instantly.
const { isMounted, styles: transitionStyles } = useTransitionStyles(context, {
duration: { open: 300, close: 250 },
});

// Preserve any ref the trigger already carries.
const referenceRef = useMergeRefs([refs.setReference, children.props.ref]);

return (
<>
{cloneElement(children, getReferenceProps({ ...children.props, ref: referenceRef }))}
{isMounted && (
<FloatingPortal>
<div ref={refs.setFloating} className="tooltip__root" style={floatingStyles} {...getFloatingProps()}>
<div className="tooltip" style={transitionStyles}>
{content}
</div>
</div>
</FloatingPortal>
)}
</>
);
}
Loading
Loading