Skip to content

Commit da99426

Browse files
committed
Highlight card during sidebar navigation
1 parent df88d2d commit da99426

File tree

9 files changed

+849
-2039
lines changed

9 files changed

+849
-2039
lines changed

browser/data-browser/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"@types/react-pdf": "^7.0.0",
6161
"@types/react-window": "^1.8.8",
6262
"@vitejs/plugin-react": "^4.3.4",
63-
"babel-plugin-react-compiler": "19.0.0-beta-21e868a-20250216",
63+
"babel-plugin-react-compiler": "19.1.0-rc.2",
6464
"babel-plugin-styled-components": "^2.1.4",
6565
"csstype": "^3.1.3",
6666
"gh-pages": "^5.0.0",

browser/data-browser/src/views/Card/ResourceCard.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ interface ResourceCardProps extends CardViewPropsBase {
3838
* (shortname) is rendered prominently at the top.
3939
*/
4040
function ResourceCard(
41-
props: ResourceCardProps & JSX.IntrinsicElements['div'],
41+
props: ResourceCardProps &
42+
JSX.IntrinsicElements['div'] & { className?: string },
4243
): JSX.Element {
43-
const { subject, initialInView } = props;
44+
const { initialInView, className, ...rest } = props;
4445
const [isShown, setIsShown] = useState(false);
4546
// The (more expensive) ResourceCardInner is only rendered when the component has been in View
4647
const { ref, inView } = useInView({
@@ -56,13 +57,13 @@ function ResourceCard(
5657

5758
return (
5859
<Suspense>
59-
<Card ref={ref} {...props} about={subject}>
60+
<Card {...rest} ref={ref} about={props.subject} className={className}>
6061
{isShown ? (
6162
<ResourceCardInner {...props} />
6263
) : (
6364
<>
6465
<h2>
65-
<AtomicLink subject={subject}>{subject}</AtomicLink>
66+
<AtomicLink subject={props.subject}>{props.subject}</AtomicLink>
6667
</h2>
6768
<p>Resource is loading...</p>
6869
</>

browser/data-browser/src/views/OntologyPage/Class/ClassCardRead.tsx

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
11
import { core, useArray, useResource, useString } from '@tomic/react';
22

3-
import { Card } from '../../../components/Card';
43
import { PropertyLineRead } from '../Property/PropertyLineRead';
54
import { styled } from 'styled-components';
65
import { FaCube } from 'react-icons/fa';
76
import { Column, Row } from '../../../components/Row';
87
import Markdown from '../../../components/datatypes/Markdown';
98
import { AtomicLink } from '../../../components/AtomicLink';
10-
import { toAnchorId } from '../../../helpers/toAnchorId';
11-
import { ViewTransitionProps } from '../../../helpers/ViewTransitionProps';
12-
import {
13-
RESOURCE_PAGE_TRANSITION_TAG,
14-
transitionName,
15-
} from '../../../helpers/transitionName';
169
import { NewClassInstanceButton } from './NewClassInstanceButton';
1710

1811
import type { JSX } from 'react';
12+
import { TargetableCard } from '../TargetableCard';
1913

2014
interface ClassCardReadProps {
2115
subject: string;
@@ -28,10 +22,10 @@ export function ClassCardRead({ subject }: ClassCardReadProps): JSX.Element {
2822
const [recommends] = useArray(resource, core.properties.recommends);
2923

3024
return (
31-
<StyledCard subject={subject}>
25+
<TargetableCard subject={subject}>
3226
<Column>
3327
<Row center justify='space-between'>
34-
<StyledH3 id={toAnchorId(subject)}>
28+
<StyledH3>
3529
<FaCube />
3630
<AtomicLink subject={subject}>{resource.title}</AtomicLink>
3731
</StyledH3>
@@ -55,15 +49,10 @@ export function ClassCardRead({ subject }: ClassCardReadProps): JSX.Element {
5549
)}
5650
</StyledTable>
5751
</Column>
58-
</StyledCard>
52+
</TargetableCard>
5953
);
6054
}
6155

62-
const StyledCard = styled(Card)<ViewTransitionProps>`
63-
padding-bottom: ${p => p.theme.size()};
64-
${props => transitionName(RESOURCE_PAGE_TRANSITION_TAG, props.subject)};
65-
`;
66-
6756
const StyledH3 = styled.h3`
6857
display: flex;
6958
align-items: center;

browser/data-browser/src/views/OntologyPage/Class/ClassCardWrite.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,16 @@ import {
44
} from '../../../components/ResourceContextMenu';
55
import { urls, useArray, useProperty, useResource } from '@tomic/react';
66
import { useCallback, type JSX } from 'react';
7-
import { Card } from '../../../components/Card';
87
import { styled } from 'styled-components';
98
import { FaCube } from 'react-icons/fa';
109
import { Column, Row } from '../../../components/Row';
1110
import { OntologyDescription } from '../OntologyDescription';
1211
import { PropertyLineWrite } from '../Property/PropertyLineWrite';
1312
import InputSwitcher from '../../../components/forms/InputSwitcher';
14-
import { toAnchorId } from '../../../helpers/toAnchorId';
1513
import { AddPropertyButton } from './AddPropertyButton';
1614
import { ErrorChipInput } from '../../../components/forms/ErrorChip';
1715
import { useOntologyContext } from '../OntologyContext';
16+
import { TargetableCard } from '../TargetableCard';
1817

1918
interface ClassCardWriteProps {
2019
subject: string;
@@ -52,8 +51,11 @@ export function ClassCardWrite({ subject }: ClassCardWriteProps): JSX.Element {
5251
};
5352

5453
return (
55-
<StyledCard data-testid={`class-card-write-${resource.title}`}>
56-
<Column id={toAnchorId(subject)}>
54+
<StyledCard
55+
subject={subject}
56+
data-testid={`class-card-write-${resource.title}`}
57+
>
58+
<Column>
5759
<Row center justify='space-between'>
5860
<TitleWrapper>
5961
<FaCube />
@@ -103,8 +105,8 @@ export function ClassCardWrite({ subject }: ClassCardWriteProps): JSX.Element {
103105
);
104106
}
105107

106-
const StyledCard = styled(Card)`
107-
padding-bottom: ${p => p.theme.margin}rem;
108+
const StyledCard = styled(TargetableCard)`
109+
padding-bottom: ${p => p.theme.size()}rem;
108110
max-width: 100rem;
109111
110112
border: ${p =>

browser/data-browser/src/views/OntologyPage/OntologyPage.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,20 @@ import { OntologySidebar } from './OntologySidebar';
1010
import { styled } from 'styled-components';
1111
import { ClassCardRead } from './Class/ClassCardRead';
1212
import { PropertyCardRead } from './Property/PropertyCardRead';
13-
import ResourceCard from '../Card/ResourceCard';
1413
import { Button } from '../../components/Button';
1514
import { Column, Row } from '../../components/Row';
1615
import { FaEdit, FaEye } from 'react-icons/fa';
1716
import { OntologyDescription } from './OntologyDescription';
1817
import { ClassCardWrite } from './Class/ClassCardWrite';
1918
import { NewClassButton } from './NewClassButton';
20-
import { toAnchorId } from '../../helpers/toAnchorId';
2119
import { OntologyContextProvider } from './OntologyContext';
2220
import { PropertyCardWrite } from './Property/PropertyCardWrite';
2321
import { Graph } from './Graph';
2422
import { CreateInstanceButton } from './CreateInstanceButton';
2523
import { useState } from 'react';
2624
import { NewPropertyButton } from './NewPropertyButton';
2725
import { InfoTitle } from './InfoTitle';
26+
import { TargetableResourceCard } from './TargetableCard';
2827

2928
const isEmpty = (arr: Array<unknown>) => arr.length === 0;
3029

@@ -124,7 +123,7 @@ export function OntologyPage({ resource }: ResourcePageProps) {
124123
{editMode && <CreateInstanceButton ontology={resource} />}
125124
{instances.map(c => (
126125
<li key={c}>
127-
<ResourceCard subject={c} id={toAnchorId(c)} />
126+
<TargetableResourceCard subject={c} />
128127
</li>
129128
))}
130129
{!editMode && instances.length === 0 && <span>No instances</span>}

browser/data-browser/src/views/OntologyPage/Property/PropertyCardRead.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
import { Card } from '../../../components/Card';
2-
import { urls, useArray, useResource, useString } from '@tomic/react';
1+
import { core, useArray, useResource, useString } from '@tomic/react';
32
import { FaHashtag } from 'react-icons/fa';
43
import { styled } from 'styled-components';
54
import Markdown from '../../../components/datatypes/Markdown';
65
import { Column, Row } from '../../../components/Row';
76
import { InlineFormattedResourceList } from '../../../components/InlineFormattedResourceList';
87
import { InlineDatatype } from '../InlineDatatype';
98
import { AtomicLink } from '../../../components/AtomicLink';
10-
import { toAnchorId } from '../../../helpers/toAnchorId';
119

1210
import type { JSX } from 'react';
11+
import { TargetableCard } from '../TargetableCard';
1312

1413
interface PropertyCardReadProps {
1514
subject: string;
@@ -19,11 +18,11 @@ export function PropertyCardRead({
1918
subject,
2019
}: PropertyCardReadProps): JSX.Element {
2120
const resource = useResource(subject);
22-
const [description] = useString(resource, urls.properties.description);
23-
const [allowsOnly] = useArray(resource, urls.properties.allowsOnly);
21+
const [description] = useString(resource, core.properties.description);
22+
const [allowsOnly] = useArray(resource, core.properties.allowsOnly);
2423

2524
return (
26-
<StyledCard id={toAnchorId(subject)}>
25+
<TargetableCard subject={subject}>
2726
<Column>
2827
<Row center justify='space-between'>
2928
<Heading>
@@ -42,7 +41,7 @@ export function PropertyCardRead({
4241
</>
4342
)}
4443
</Column>
45-
</StyledCard>
44+
</TargetableCard>
4645
);
4746
}
4847

@@ -57,7 +56,3 @@ const Heading = styled.h3`
5756
const SubHeading = styled.h4`
5857
margin-bottom: 0px;
5958
`;
60-
61-
const StyledCard = styled(Card)`
62-
padding-bottom: ${p => p.theme.margin}rem;
63-
`;

browser/data-browser/src/views/OntologyPage/Property/PropertyCardWrite.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
import { useCallback, type JSX } from 'react';
2-
import { Card } from '../../../components/Card';
32
import { urls, useCanWrite, useProperty, useResource } from '@tomic/react';
43
import { FaHashtag } from 'react-icons/fa';
54
import { styled } from 'styled-components';
65
import { Column, Row } from '../../../components/Row';
7-
import { toAnchorId } from '../../../helpers/toAnchorId';
86
import InputSwitcher from '../../../components/forms/InputSwitcher';
97
import {
108
ContextMenuOptions,
119
ResourceContextMenu,
1210
} from '../../../components/ResourceContextMenu';
1311
import { useOntologyContext } from '../OntologyContext';
1412
import { PropertyFormCommon } from './PropertyFormCommon';
13+
import { TargetableCard } from '../TargetableCard';
1514

1615
interface PropertyCardWriteProps {
1716
subject: string;
@@ -36,7 +35,7 @@ export function PropertyCardWrite({
3635
}, [removeProperty, subject]);
3736

3837
return (
39-
<StyledCard id={toAnchorId(subject)}>
38+
<StyledCard subject={subject}>
4039
<Column>
4140
<Row center justify='space-between'>
4241
<TitleWrapper>
@@ -71,7 +70,7 @@ const TitleWrapper = styled.div`
7170
}
7271
`;
7372

74-
const StyledCard = styled(Card)`
73+
const StyledCard = styled(TargetableCard)`
7574
border: ${p =>
7675
p.theme.darkMode ? `1px solid ${p.theme.colors.bg2}` : 'none'};
7776
padding-bottom: ${p => p.theme.margin}rem;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { css, keyframes, styled } from 'styled-components';
2+
import { toAnchorId } from '../../helpers/toAnchorId';
3+
import { Card } from '../../components/Card';
4+
5+
import ResourceCard from '../Card/ResourceCard';
6+
7+
type TargetableCardProps = {
8+
subject: string;
9+
className?: string;
10+
};
11+
12+
export const TargetableCard = ({
13+
subject,
14+
className,
15+
children,
16+
}: React.PropsWithChildren<TargetableCardProps>) => {
17+
return (
18+
<StyledCard
19+
id={toAnchorId(subject ?? '')}
20+
about={subject}
21+
className={className}
22+
>
23+
{children}
24+
</StyledCard>
25+
);
26+
};
27+
28+
export const TargetableResourceCard = ({ subject }: TargetableCardProps) => {
29+
return (
30+
<StyledResourceCard subject={subject} id={toAnchorId(subject ?? '')} />
31+
);
32+
};
33+
34+
const targetHighlight = keyframes`
35+
from {
36+
box-shadow: var(--target-animation-base-shadow), 0 0 0 2px var(--target-animation-color);
37+
}
38+
to {
39+
box-shadow: var(--target-animation-base-shadow);
40+
}
41+
`;
42+
43+
const styles = css`
44+
--target-animation-color: ${p => p.theme.colors.main};
45+
--target-animation-base-shadow: ${p => p.theme.boxShadow};
46+
padding-bottom: ${p => p.theme.size()};
47+
48+
&:target {
49+
box-shadow:
50+
var(--target-animation-base-shadow),
51+
0 0 0 2px var(--target-animation-color);
52+
animation: 500ms ease-out 1.5s forwards ${targetHighlight};
53+
}
54+
`;
55+
const StyledCard = styled(Card)`
56+
${styles}
57+
`;
58+
const StyledResourceCard = styled(ResourceCard)`
59+
${styles}
60+
`;

0 commit comments

Comments
 (0)