Skip to content
Open
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
69 changes: 69 additions & 0 deletions apps/docs/.storybook/preview.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,72 @@
margin-top: 1.5rem;
margin-bottom: 0.5rem;
}

/* Tables — hairline horizontal rules, navy header row, zebra body */
.sbdocs table {
width: 100%;
border-collapse: collapse;
margin: 1.5rem 0;
font-size: 0.875rem;
}

.sbdocs thead tr {
background: #18405e;
}

.sbdocs th {
/* !important: beats Storybook's own emotion-injected table text color,
which loads after this stylesheet and wins the specificity tie */
color: #ffffff !important;
text-align: left;
font-weight: 600;
padding: 0.5rem 0.75rem;
}

.sbdocs td {
padding: 0.5rem 0.75rem;
border: none;
border-bottom: 1px solid #d7e6f2;
}

.sbdocs tbody tr:nth-of-type(even) {
background: #f8fafc;
}

/* Code — hairline border, blue-tinted background, mono face */
.sbdocs pre {
background: #f3f8fc;
border: 1px solid #d7e6f2;
border-radius: 2px;
padding: 1rem;
}

.sbdocs pre code {
font-family: "Roboto Mono", monospace;
color: #18405e;
background: none;
border: none;
padding: 0;
}

.sbdocs :not(pre) > code {
font-family: "Roboto Mono", monospace;
background: #eef5fb;
border: 1px solid #d7e6f2;
border-radius: 2px;
padding: 0.1rem 0.35rem;
color: #18405e;
}

/* Blockquotes as callouts — left accent bar, tinted background */
.sbdocs blockquote {
margin: 1.5rem 0;
padding: 0.75rem 1rem;
border-left: 3px solid #3489ca;
background: #eef5fb;
color: #5a5f5f;
}

.sbdocs blockquote p {
margin: 0;
}
175 changes: 175 additions & 0 deletions apps/docs/src/components/UiShowcaseDemo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import { theme } from "@ot/config";
import type { ReactNode } from "react";
import {
Box,
BtnGroup,
Button,
ButtonNoBorder,
ButtonPrimary,
Chip,
ChipList,
LabelChip,
LongText,
NewChip,
Stack,
ThemeProvider,
Tooltip,
Typography,
} from "ui";

function ComponentLabel({ children }: { children: string }) {
return (
<Typography variant="monoText" display="block" sx={{ color: "text.secondary", mb: 1 }}>
{children}
</Typography>
);
}

function ShowcaseCard({ title, children }: { title: string; children: ReactNode }) {
return (
<Box
sx={{
border: "1px solid",
borderColor: "#d7e6f2",
borderRadius: 0,
overflow: "hidden",
display: "flex",
flexDirection: "column",
}}
>
<Box sx={{ bgcolor: "#eef5fb", px: 2, py: 1 }}>
<Typography
variant="monoText"
sx={{
color: "secondary.main",
textTransform: "uppercase",
letterSpacing: "0.08em",
fontWeight: 700,
}}
>
{title}
</Typography>
</Box>
<Stack spacing={3} sx={{ p: 2, flex: 1 }}>
{children}
</Stack>
</Box>
);
}

function ButtonsShowcase() {
return (
<ShowcaseCard title="Buttons">
<div>
<ComponentLabel>Button — outlined (default)</ComponentLabel>
<Stack direction="row" spacing={2} flexWrap="wrap">
<Button variant="outlined">Outlined</Button>
<Button variant="contained">Contained</Button>
<Button variant="text">Text</Button>
</Stack>
</div>
<div>
<ComponentLabel>ButtonPrimary — filled brand color</ComponentLabel>
<ButtonPrimary variant="contained">Save changes</ButtonPrimary>
</div>
<div>
<ComponentLabel>ButtonNoBorder — border hidden until hover (AOTF toolbar triggers)</ComponentLabel>
<ButtonNoBorder variant="outlined">Advanced filters</ButtonNoBorder>
</div>
<div>
<ComponentLabel>BtnGroup — tab-like switcher over arbitrary content</ComponentLabel>
<BtnGroup
btnGroup={{
table: { title: "Table", component: <Typography variant="body2">Table view</Typography> },
chart: { title: "Chart", component: <Typography variant="body2">Chart view</Typography> },
}}
/>
</div>
</ShowcaseCard>
);
}

function ChipsShowcase() {
return (
<ShowcaseCard title="Chips & labels">
<div>
<ComponentLabel>Chip — outlined/small default, full MUI ChipProps</ComponentLabel>
<Stack direction="row" spacing={1} flexWrap="wrap">
<Chip label="Default" />
<Chip label="Clickable" clickable onClick={() => {}} />
<Chip label="Filled medium" variant="filled" size="medium" color="primary" />
</Stack>
</div>
<div>
<ComponentLabel>ChipList — horizontal list, each chip optionally linked + tooltipped</ComponentLabel>
<Stack direction="row" spacing={0} flexWrap="wrap">
<ChipList
items={[
{ label: "GWAS", tooltip: "Genome-wide association study" },
{ label: "UniProt", url: "https://www.uniprot.org", tooltip: "External source" },
]}
/>
</Stack>
</div>
<div>
<ComponentLabel>LabelChip — label/value pair with optional link</ComponentLabel>
<LabelChip label="VEP" value="Missense variant" to="https://www.ensembl.org/info/genome/variation/prediction/predicted_data.html" />
</div>
<div>
<ComponentLabel>NewChip — small "new" badge (currently unused in this monorepo)</ComponentLabel>
<NewChip className="" />
</div>
</ShowcaseCard>
);
}

function TextTooltipsShowcase() {
return (
<ShowcaseCard title="Text & tooltips">
<div>
<ComponentLabel>LongText — clamps to lineLimit, expands on click</ComponentLabel>
<Box sx={{ maxWidth: 420 }}>
<LongText lineLimit={2}>
Open Targets combines evidence from genetics, genomics, transcriptomics, drugs,
animal models, and scientific literature to score and rank target-disease
associations for drug target identification and prioritisation.
</LongText>
</Box>
</div>
<div>
<ComponentLabel>Tooltip — themed wrapper around MUI Tooltip, optional "?" trigger</ComponentLabel>
<Stack direction="row" spacing={3} alignItems="center">
<Tooltip title="Hover for detail">
<span>Hover me</span>
</Tooltip>
<Typography variant="body2">
Score
<Tooltip title="Association score, 0 to 1" showHelpIcon>
<span />
</Tooltip>
</Typography>
</Stack>
</div>
</ShowcaseCard>
);
}

function UiShowcaseDemo() {
return (
<ThemeProvider theme={theme}>
<Box
sx={{
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))",
gap: 3,
}}
>
<ButtonsShowcase />
<ChipsShowcase />
<TextTooltipsShowcase />
</Box>
</ThemeProvider>
);
}

export default UiShowcaseDemo;
2 changes: 2 additions & 0 deletions apps/docs/src/docs/Architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ Shared, low-level React components that have no data-fetching logic. Design-syst

Current components include: `Link`, `Chip`, `OtTable`, `OtTableSSP`, `DataDownloader`, `ApiPlaygroundDrawer`, `NavBar`, `Footer`, `ObsPlot`, `Section`, `Summary`, `Tooltip`, `Viewer`, providers (`OTApolloProvider`, `ThemeProvider`, `PlatformApiProvider`), and ~60 others.

`ui` also re-exports ~60 `@mui/material` primitives (`Box`, `Typography`, `Dialog*`, `Card*`, `Menu*`, etc.) as a plain pass-through facade. `packages/sections` and `apps/platform` import these from `ui` rather than `@mui/material` directly, making `ui` the single swap point for the in-progress MUI → shadcn/ui migration. `Chip`, `Button`, `Tooltip`, and `Link` are custom wrapped components — the raw MUI versions are available aliased as `MuiChip`, `MuiButton`, `MuiTooltip`, `MuiLink` for the rare case a call site needs the unstyled original. `styled`/`useTheme`/`Theme` are deliberately excluded from the facade and still imported directly from `@mui/material/styles` — they're theming utilities, not components, and aren't affected by the shadcn swap.

### `packages/sections`

Composed widgets that combine UI primitives with domain knowledge and GraphQL queries. Organised by entity type:
Expand Down
14 changes: 14 additions & 0 deletions apps/docs/src/docs/GettingStarted.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ yarn dev:platform # http://localhost:3000

Storybook hot-reloads on save, so no config change is needed when you add either.

## Importing MUI components

In `packages/sections` and `apps/platform`, import MUI primitives from `ui` rather than `@mui/material` directly:

```tsx
// Do
import { Box, Typography, Dialog } from "ui";

// Don't
import { Box, Typography, Dialog } from "@mui/material";
```

`ui` re-exports these as a facade so it stays the single point of change for the ongoing MUI → shadcn/ui migration (see **Architecture / packages/ui**). `styled` and `useTheme` are the exception — keep importing those from `@mui/material/styles`.

## Adding a UI component story

```tsx
Expand Down
3 changes: 1 addition & 2 deletions apps/docs/src/docs/Introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ The Platform is a React SPA built as a Yarn monorepo. This Storybook documents t
| **Getting Started** | Prerequisites, running the docs, and adding your own stories and pages |
| **Architecture** | The monorepo layout, package roles, dependency graph, and data flow |
| **Packages** | API reference for `ot-config`, `ot-constants`, `ot-utils`, and `sections` |
| **Components** | Hand-written docs for `Table`, `DataTable`, and the 3D `Viewer` |
| **Components** | Hand-written docs for `Table`, `DataTable`, the 3D `Viewer`, and a live showcase of smaller `packages/ui` primitives (buttons, chips, tooltips) |
| **Configuration** | Partner preview and private instance options |
| **UI Components** | Auto-generated docs for `packages/ui` primitives |
| **Sections** | Stories for the composed data widgets in `packages/sections` |
| **Associations** | Dedicated docs for the Associations on the Fly toolkit |

Expand Down
48 changes: 48 additions & 0 deletions apps/docs/src/docs/components/Showcase.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Meta } from "@storybook/addon-docs/blocks";
import UiShowcaseDemo from "../../components/UiShowcaseDemo";

<Meta title="Components/Showcase" />

# UI Component Showcase

Live gallery of the smaller `packages/ui` primitives touched by the MUI facade migration (#1004) —
prop shapes here reflect the current, post-migration behavior. For `Table`/`DataTable` and the 3D
`Viewer`, see their own dedicated pages.

<UiShowcaseDemo />

---

## Buttons

- **`Button`** — thin `styled()` wrapper around MUI's `Button`, currently a no-op pass-through. The
app theme (`@ot/config`) forces a 1px border onto every `MuiButton` root by default.
- **`ButtonPrimary`** — `Button` filled with the brand primary color.
- **`ButtonNoBorder`** — hides that theme-forced border until hover. Built for AOTF's toolbar
triggers (Advanced filters, Column options, Upload, Export), whose "no border" look turned out to
be intentional, not a default.
- **`PopoverButton`** — takes its visual variant via an `as` prop (`Button` by default), not a
boolean flag, so it composes with any of the above. Not shown live here since it requires a
FontAwesome `IconDefinition`; see `packages/ui/src/components/Button.tsx`.
- **`BtnGroup`** — a tab-like switcher over arbitrary `ReactNode` content, keyed by an object rather
than an array.

## Chips & labels

- **`Chip`** — defaults to `variant="outlined"` `size="small"`, but takes the full MUI `ChipProps`
(`color`, `sx`, `clickable`, `onClick`, ...) so any caller can override. `forwardRef`-wrapped so it
works as a direct child of `Grow`/`Fade`/`Collapse`.
- **`ChipList`** — renders a list of `{ label, tooltip?, url? }` items; a chip becomes a clickable
link when `url` is set.
- **`LabelChip`** — a two-part label/value pill (e.g. `VEP` / `Missense variant`) with an optional
link and tooltip.
- **`NewChip`** — small "new" badge. Currently unused anywhere in this monorepo — kept for future
use, not deleted speculatively.

## Text & tooltips

- **`LongText`** — clamps content to `lineLimit` lines and reveals a "show more" toggle when it
overflows. `displayText` overrides the toggle's label (e.g. for a translated string) instead of
the default `"show more"`/`"hide"`.
- **`Tooltip`** — themed wrapper around MUI's `Tooltip`. Pass `showHelpIcon` to render a `?`
superscript trigger instead of wrapping the children directly.
Loading