Skip to content

Commit ebce165

Browse files
author
Josep Martins
committed
Add anchor links
1 parent ca54cf4 commit ebce165

File tree

7 files changed

+91
-57
lines changed

7 files changed

+91
-57
lines changed

packages/design-tokens/src/tokens/functional/components/accordion/colors.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
module.exports = {
22
brand: {
33
Accordion: {
4+
anchorLink: {
5+
color: {
6+
default: {
7+
value: 'var(--base-color-scale-blue-5)',
8+
dark: 'var(--base-color-scale-blue-3)'
9+
}
10+
}
11+
},
412
toggle: {
513
color: {
614
start: {

packages/react/src/Accordion/Accordion.module.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
left: 0;
1818
}
1919

20+
.Accordion:hover .Accordion__summary-anchor-link {
21+
opacity: 1;
22+
}
23+
2024
.Accordion:hover::after {
2125
transform: scaleY(0.35);
2226
}
@@ -90,6 +94,15 @@ details[open] > .Accordion__summary::after {
9094
transform: rotateZ(180deg);
9195
}
9296

97+
.Accordion__summary-anchor-link {
98+
opacity: 0;
99+
transition: opacity 0.2s ease;
100+
margin-left: var(--base-size-4);
101+
display: inline-flex;
102+
padding: var(--base-size-4);
103+
color: var(--brand-Accordion-anchorLink-color-default);
104+
}
105+
93106
.Accordion__content {
94107
color: var(--brand-color-text-muted);
95108
font-family: var(--brand-fontStack-sansSerif);

packages/react/src/Accordion/Accordion.module.css.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
declare const styles: {
22
readonly "Accordion": string;
3+
readonly "Accordion__summary-anchor-link": string;
34
readonly "Accordion__summary": string;
45
readonly "Accordion__summary-heading": string;
56
readonly "Accordion__content": string;

packages/react/src/Accordion/Accordion.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ import '@primer/brand-primitives/lib/design-tokens/css/tokens/functional/compone
1111

1212
/** * Main Stylesheet (as a CSS Module) */
1313
import styles from './Accordion.module.css'
14+
import {LinkIcon} from '@primer/octicons-react'
1415

1516
export type AccordionRootProps = BaseProps<HTMLDetailsElement> & {
1617
open?: boolean // Manually declared due to known issue with the native open attribute: https://github.com/facebook/react/issues/15486
18+
url?: string
1719
children: React.ReactElement<AccordionHeadingProps | AccordionContentProps>[]
1820
} & React.HTMLAttributes<HTMLDetailsElement>
1921

@@ -23,7 +25,7 @@ type ValidRootChildren = {
2325
}
2426

2527
export const AccordionRoot = forwardRef<HTMLDetailsElement, AccordionRootProps>(
26-
({children, className, open = false, ...rest}, ref) => {
28+
({children, className, url, open = false, ...rest}, ref) => {
2729
const {AccordionHeading: HeadingChild, AccordionContent: AccordionContentChild} = React.Children.toArray(
2830
children
2931
).reduce<ValidRootChildren>(
@@ -33,7 +35,9 @@ export const AccordionRoot = forwardRef<HTMLDetailsElement, AccordionRootProps>(
3335
acc.AccordionContent = child
3436
}
3537
if (child.type === AccordionHeading) {
36-
acc.AccordionHeading = child
38+
acc.AccordionHeading = React.cloneElement(child, {
39+
url
40+
})
3741
}
3842
}
3943
return acc
@@ -53,14 +57,20 @@ export const AccordionRoot = forwardRef<HTMLDetailsElement, AccordionRootProps>(
5357
type AccordionHeadingProps = BaseProps<HTMLHeadingElement> & {
5458
className?: string
5559
children: string
60+
url?: string
5661
}
5762

5863
export const AccordionHeading = forwardRef<HTMLHeadingElement, AccordionHeadingProps>(
59-
({children, className, ...rest}, ref) => {
64+
({children, className, url, ...rest}, ref) => {
6065
return (
6166
<summary className={clsx(styles.Accordion__summary, className)} ref={ref} {...rest}>
6267
<Heading as="h4" className={styles['Accordion__summary-heading']}>
6368
{children}
69+
{url ? (
70+
<a href={url} className={styles['Accordion__summary-anchor-link']}>
71+
<LinkIcon size={16} />
72+
</a>
73+
) : null}
6474
</Heading>
6575
</summary>
6676
)

packages/react/src/FAQ/FAQ.features.stories.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,56 @@ export const HeadingLeftAligned: ComponentStory<typeof FAQ> = () => {
160160
)
161161
}
162162

163+
export const DeepLink: ComponentStory<typeof FAQ> = () => {
164+
return (
165+
<Container>
166+
<FAQ>
167+
<FAQ.Heading>Frequently asked&nbsp;questions</FAQ.Heading>
168+
<>
169+
{fixtureData.map(({question, answer}, id) => {
170+
return (
171+
<FAQ.Item id={`asdfasdfadsf-${id.toString()}`} key={id}>
172+
<FAQ.Question>{question}</FAQ.Question>
173+
<FAQ.Answer>{answer}</FAQ.Answer>
174+
</FAQ.Item>
175+
)
176+
})}
177+
</>
178+
<>
179+
{fixtureData.map(({question, answer}, id) => {
180+
return (
181+
<FAQ.Item id={`test-${id.toString()}`} key={question}>
182+
<FAQ.Question>{question}</FAQ.Question>
183+
<FAQ.Answer>{answer}</FAQ.Answer>
184+
</FAQ.Item>
185+
)
186+
})}
187+
</>
188+
<>
189+
{fixtureData.map(({question, answer}, id) => {
190+
return (
191+
<FAQ.Item id={`test-${id.toString()}`} key={question}>
192+
<FAQ.Question>{question}</FAQ.Question>
193+
<FAQ.Answer>{answer}</FAQ.Answer>
194+
</FAQ.Item>
195+
)
196+
})}
197+
</>
198+
<>
199+
{fixtureData.map(({question, answer}, id) => {
200+
return (
201+
<FAQ.Item id={`test-${id.toString()}`} key={question}>
202+
<FAQ.Question>{question}</FAQ.Question>
203+
<FAQ.Answer>{answer}</FAQ.Answer>
204+
</FAQ.Item>
205+
)
206+
})}
207+
</>
208+
</FAQ>
209+
</Container>
210+
)
211+
}
212+
163213
export const Groups: ComponentStory<typeof FAQ> = () => {
164214
return (
165215
<Container>

packages/react/src/FAQ/FAQ.stories.tsx

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const Default = () => (
1212
<FAQ>
1313
<FAQ.Heading align="center">Frequently asked&nbsp;questions</FAQ.Heading>
1414
<FAQ.Subheading align="start">Subscriptions and payments</FAQ.Subheading>
15-
<FAQ.Item open>
15+
<FAQ.Item>
1616
<FAQ.Question>What&apos;s included in the GitHub for Startups offer?</FAQ.Question>
1717
<FAQ.Answer>
1818
<p>
@@ -136,57 +136,5 @@ export const Default = () => (
136136
</p>
137137
</FAQ.Answer>
138138
</FAQ.Item>
139-
<FAQ.Item id="test-1">
140-
<FAQ.Question>This is a test of an anchored link to a FAQ item</FAQ.Question>
141-
<FAQ.Answer>
142-
<p>
143-
Any investor, accelerator, or startup support organization is eligible to apply for the GitHub for Startups
144-
program. If you’re not currently eligible for the GitHub for Startups but would like to try GitHub Enterprise,
145-
please feel to sign up for a trial.
146-
</p>
147-
<p>
148-
Any investor, accelerator, or startup support organization is eligible to apply for the GitHub for Startups
149-
program. If you’re not currently eligible for the GitHub for Startups but would like to try GitHub Enterprise,
150-
please feel to sign up for a trial.
151-
</p>
152-
<p>
153-
Any investor, accelerator, or startup support organization is eligible to apply for the GitHub for Startups
154-
program. If you’re not currently eligible for the GitHub for Startups but would like to try GitHub Enterprise,
155-
please feel to sign up for a trial.
156-
</p>
157-
<p>
158-
Any investor, accelerator, or startup support organization is eligible to apply for the GitHub for Startups
159-
program. If you’re not currently eligible for the GitHub for Startups but would like to try GitHub Enterprise,
160-
please feel to sign up for a trial.
161-
</p>
162-
<p>
163-
Any investor, accelerator, or startup support organization is eligible to apply for the GitHub for Startups
164-
program. If you’re not currently eligible for the GitHub for Startups but would like to try GitHub Enterprise,
165-
please feel to sign up for a trial. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vitae elit
166-
libero, a pharetra augue. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
167-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
168-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
169-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
170-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
171-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
172-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
173-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
174-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
175-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
176-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
177-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
178-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
179-
ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh
180-
ultricies vehicula ut id elit. Nullam id
181-
</p>
182-
<p>
183-
{' '}
184-
<InlineLink href="https://copilot.github.com/" target="_blank" rel="noreferrer">
185-
Apply here
186-
</InlineLink>
187-
.
188-
</p>
189-
</FAQ.Answer>
190-
</FAQ.Item>
191139
</FAQ>
192140
)

packages/react/src/FAQ/FAQ.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,12 @@ const FAQRoot = forwardRef<HTMLElement, FAQRootProps>(({children, className, ...
5353
})
5454
}
5555
if (child.type === AccordionRoot) {
56+
const url = child.props.id ? `#${child.props.id}` : undefined
57+
const open = hash && hash.substring(1) === child.props.id ? true : child.props.open
58+
5659
return React.cloneElement(child, {
57-
open: hash && hash.substring(1) === child.props.id ? true : child.props.open
60+
open,
61+
url
5862
})
5963
}
6064
}

0 commit comments

Comments
 (0)