Skip to content

Commit 699d54a

Browse files
committed
Add custom UI examples
1 parent 09350c5 commit 699d54a

31 files changed

+5468
-167
lines changed

package-lock.json

Lines changed: 2193 additions & 148 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"js-yaml": "^4.1.0",
2929
"oidc-client-ts": "^3.1.0",
3030
"react": "19.0.0",
31+
"react-aria-components": "^1.7.1",
3132
"react-dom": "19.0.0",
3233
"react-error-boundary": "^5.0.0",
3334
"react-hook-form": "^7.54.2",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.avatar {
2+
width: 2rem;
3+
height: 2rem;
4+
5+
padding: 0;
6+
border-radius: 50%;
7+
8+
font-weight: 700;
9+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Button, ButtonProps } from '../Button/Button.tsx';
2+
import clsx from 'clsx';
3+
4+
import classes from './Avatar.module.css';
5+
6+
export interface AvatarProps extends Omit<ButtonProps, 'children'> {
7+
initials?: string;
8+
}
9+
10+
export function Avatar({ initials, className, ...rest }: AvatarProps) {
11+
return (
12+
<Button
13+
design="primary"
14+
className={clsx(classes.avatar, className)}
15+
{...rest}
16+
>
17+
{initials}
18+
</Button>
19+
);
20+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.button {
2+
height: 2.25rem;
3+
4+
border: 1px solid;
5+
border-radius: 0.375em;
6+
margin: 0;
7+
padding: 0.5em 0.75em;
8+
9+
font-size: var(--mcp-font-size);
10+
11+
outline: none;
12+
13+
14+
&[data-pressed] {
15+
outline: 2px solid var(--mcp-color-outline-focus);
16+
outline-offset: -1px;
17+
}
18+
19+
&[data-focus-visible] {
20+
outline: 2px solid var(--mcp-color-outline-focus);
21+
outline-offset: -1px;
22+
}
23+
24+
25+
/** Design: Default */
26+
&[data-mcp-button-design="default"] {
27+
background-color: var(--mcp-color-default);
28+
border-color: var(--mcp-color-default-border);
29+
color: var(--mcp-color-text-dark);
30+
31+
&[data-hovered] {
32+
background-color: var(--mcp-color-default-hover);
33+
}
34+
}
35+
36+
/** Design: Primary */
37+
&[data-mcp-button-design="primary"] {
38+
background-color: var(--mcp-color-primary);
39+
border-color: var(--mcp-color-primary-border);
40+
color: var(--mcp-color-white);
41+
42+
&[data-hovered] {
43+
background-color: var(--mcp-color-primary-hover);
44+
}
45+
}
46+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {
2+
Button as ButtonBase,
3+
ButtonProps as ButtonBaseProps,
4+
} from 'react-aria-components';
5+
6+
import clsx from 'clsx';
7+
8+
import classes from './Button.module.css';
9+
10+
export interface ButtonProps extends ButtonBaseProps {
11+
design?: 'default' | 'primary';
12+
}
13+
14+
export function Button({
15+
design = 'default',
16+
className,
17+
children,
18+
...rest
19+
}: ButtonProps) {
20+
return (
21+
<ButtonBase
22+
className={clsx(classes.button, className)}
23+
data-mcp-button-design={design}
24+
{...rest}
25+
>
26+
{children}
27+
</ButtonBase>
28+
);
29+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.svg {
2+
width: 1rem;
3+
height: 1rem;
4+
5+
fill: var(--mcp-color-text-dark);
6+
7+
&[data-mcp-icon-design="warning"] {
8+
fill: var(--mcp-color-text-warning);
9+
}
10+
11+
&[data-mcp-icon-design="negative"] {
12+
fill: var(--mcp-color-text-negative);
13+
}
14+
15+
&[data-mcp-icon-design="positive"] {
16+
fill: var(--mcp-color-text-positive);
17+
}
18+
}

src/@ui-components/Icon/Icon.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import IconPaths from './IconPaths.ts';
2+
3+
import classes from './Icon.module.css';
4+
import clsx from 'clsx';
5+
6+
export interface IconProps {
7+
src: keyof typeof IconPaths;
8+
design?: 'neutral' | 'positive' | 'negative' | 'warning';
9+
alt?: string;
10+
className?: string;
11+
}
12+
13+
export function Icon({ design = 'neutral', src, alt, className }: IconProps) {
14+
return (
15+
<svg
16+
className={clsx(classes.svg, className)}
17+
viewBox="0 0 512 512"
18+
role="presentation"
19+
focusable="false"
20+
preserveAspectRatio="xMidYMid meet"
21+
aria-hidden="true"
22+
xmlns="http://www.w3.org/2000/svg"
23+
data-mcp-icon-design={design}
24+
aria-label={alt}
25+
>
26+
<g role="presentation">
27+
<path d={IconPaths[src]?.path} />
28+
</g>
29+
</svg>
30+
);
31+
}

src/@ui-components/Icon/IconPaths.ts

Lines changed: 2486 additions & 0 deletions
Large diffs are not rendered by default.

src/@ui-components/Menu/Menu.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { MenuTrigger } from 'react-aria-components';
2+
3+
import { ReactNode } from 'react';
4+
5+
export interface MenuProps {
6+
/** Any button (e.g. `MenuButton` or `Button`) and `MenuList` */
7+
children: ReactNode;
8+
}
9+
10+
export function Menu({ children }: MenuProps) {
11+
return <MenuTrigger>{children}</MenuTrigger>;
12+
}

0 commit comments

Comments
 (0)