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
16 changes: 15 additions & 1 deletion apps/landing/devup.json
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,21 @@
},
null,
null
]
],
"code": {
"fontFamily": "D2Coding",
"fontWeight": 400,
"fontSize": "13px",
"lineHeight": 1.5,
"letterSpacing": "0em"
},
"eyebrow": {
"fontFamily": "D2Coding",
"fontWeight": 400,
"fontSize": "11px",
"lineHeight": 1.4,
"letterSpacing": "0.14em"
}
}
}
}
238 changes: 238 additions & 0 deletions apps/landing/src/app/_components/code-tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
import { Box, Text } from '@devup-ui/react'

import { CodeWindow, HighlightedCode } from './code-window'

export interface CodeExample {
key: string
label: string
file: string
html: string
}

export type CodeExampleQuad = [CodeExample, CodeExample, CodeExample, CodeExample]

// devup-ui extracts `selectors` strings at build time, so each of the 4
// fixed tabs is written out literally rather than generated by a .map()
// over a runtime key — a template-literal selector key can't be statically
// extracted into CSS.
//
// Each target element (label / title / panel) declares its own "when am I
// shown" condition anchored on the checkbox's id (`#code-tab-N:checked ~ *
// &`), rather than the checkbox declaring rules for elements elsewhere in
// the tree. The checkbox's own `:checked` state isn't observable from the
// checkbox's position in isolation, so ownership of the visibility rule
// belongs on the element it affects.
export function CodeTabs({ examples: [a, b, c, d] }: { examples: CodeExampleQuad }) {
return (
<Box>
<Box
as="input"
boxSize="1px"
defaultChecked
id="code-tab-0"
name="code-tab"
opacity="0"
overflow="hidden"
position="absolute"
type="radio"
/>
<Box
as="input"
boxSize="1px"
id="code-tab-1"
name="code-tab"
opacity="0"
overflow="hidden"
position="absolute"
type="radio"
/>
<Box
as="input"
boxSize="1px"
id="code-tab-2"
name="code-tab"
opacity="0"
overflow="hidden"
position="absolute"
type="radio"
/>
<Box
as="input"
boxSize="1px"
id="code-tab-3"
name="code-tab"
opacity="0"
overflow="hidden"
position="absolute"
type="radio"
/>
<CodeWindow
tabs={
<>
<Box
as="label"
border="1px solid transparent"
borderRadius="4px"
color="$caption"
cursor="pointer"
htmlFor="code-tab-0"
px="12px"
py="6px"
selectors={{
'#code-tab-0:checked ~ * &': {
bg: '$containerBackground',
border: '1px solid $border',
color: '$title',
},
'#code-tab-0:focus-visible ~ * &': {
boxShadow: '0 0 0 2px $vespertidePrimary',
},
}}
transition="color .15s, background .15s"
typography="eyebrow"
>
{a.label}
</Box>
<Box
as="label"
border="1px solid transparent"
borderRadius="4px"
color="$caption"
cursor="pointer"
htmlFor="code-tab-1"
px="12px"
py="6px"
selectors={{
'#code-tab-1:checked ~ * &': {
bg: '$containerBackground',
border: '1px solid $border',
color: '$title',
},
'#code-tab-1:focus-visible ~ * &': {
boxShadow: '0 0 0 2px $vespertidePrimary',
},
}}
transition="color .15s, background .15s"
typography="eyebrow"
>
{b.label}
</Box>
<Box
as="label"
border="1px solid transparent"
borderRadius="4px"
color="$caption"
cursor="pointer"
htmlFor="code-tab-2"
px="12px"
py="6px"
selectors={{
'#code-tab-2:checked ~ * &': {
bg: '$containerBackground',
border: '1px solid $border',
color: '$title',
},
'#code-tab-2:focus-visible ~ * &': {
boxShadow: '0 0 0 2px $vespertidePrimary',
},
}}
transition="color .15s, background .15s"
typography="eyebrow"
>
{c.label}
</Box>
<Box
as="label"
border="1px solid transparent"
borderRadius="4px"
color="$caption"
cursor="pointer"
htmlFor="code-tab-3"
px="12px"
py="6px"
selectors={{
'#code-tab-3:checked ~ * &': {
bg: '$containerBackground',
border: '1px solid $border',
color: '$title',
},
'#code-tab-3:focus-visible ~ * &': {
boxShadow: '0 0 0 2px $vespertidePrimary',
},
}}
transition="color .15s, background .15s"
typography="eyebrow"
>
{d.label}
</Box>
</>
}
title={
<>
<Text
as="span"
display="none"
id="code-title-0"
selectors={{ '#code-tab-0:checked ~ * &': { display: 'block' } }}
>
{a.file}
</Text>
<Text
as="span"
display="none"
id="code-title-1"
selectors={{ '#code-tab-1:checked ~ * &': { display: 'block' } }}
>
{b.file}
</Text>
<Text
as="span"
display="none"
id="code-title-2"
selectors={{ '#code-tab-2:checked ~ * &': { display: 'block' } }}
>
{c.file}
</Text>
<Text
as="span"
display="none"
id="code-title-3"
selectors={{ '#code-tab-3:checked ~ * &': { display: 'block' } }}
>
{d.file}
</Text>
</>
}
>
<Box
display="none"
id="code-panel-0"
selectors={{ '#code-tab-0:checked ~ * &': { display: 'block' } }}
>
<HighlightedCode html={a.html} />
</Box>
<Box
display="none"
id="code-panel-1"
selectors={{ '#code-tab-1:checked ~ * &': { display: 'block' } }}
>
<HighlightedCode html={b.html} />
</Box>
<Box
display="none"
id="code-panel-2"
selectors={{ '#code-tab-2:checked ~ * &': { display: 'block' } }}
>
<HighlightedCode html={c.html} />
</Box>
<Box
display="none"
id="code-panel-3"
selectors={{ '#code-tab-3:checked ~ * &': { display: 'block' } }}
>
<HighlightedCode html={d.html} />
</Box>
</CodeWindow>
</Box>
)
}
108 changes: 108 additions & 0 deletions apps/landing/src/app/_components/code-window.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { Box, Flex, globalCss, Text } from '@devup-ui/react'
import type { ComponentProps, ReactNode } from 'react'

globalCss({
'.shiki, .shiki span': {
fontFamily: 'D2Coding',
fontSize: '13px',
lineHeight: '1.65',
},
'.shiki': {
background: 'transparent !important',
padding: '0',
margin: '0',
overflowX: 'auto',
},
'[data-theme="dark"] .shiki, [data-theme="dark"] .shiki span': {
color: 'var(--shiki-dark) !important',
backgroundColor: 'transparent !important',
},
})

export function CodeWindow({
title,
tabs,
children,
...props
}: {
title: ReactNode
tabs?: ReactNode
children: ReactNode
} & Omit<ComponentProps<typeof Box<'div'>>, 'title'>) {
return (
<Box
bg="$cardBase"
border="1px solid $border"
borderRadius="$borderRadiusRadius12"
boxShadow="0 30px 60px -30px rgba(0,0,0,.25)"
overflow="hidden"
{...props}
>
<Flex
alignItems="center"
bg="$vespertideBg"
borderBottom="1px solid $border"
gap="10px"
px="14px"
py="10px"
>
<Flex gap="6px">
{Array.from({ length: 3 }, (_, i) => (
<Box
key={i}
bg="$caption"
borderRadius="50%"
boxSize="10px"
opacity="0.5"
/>
))}
</Flex>
<Text
color="$caption"
fontFamily="D2Coding"
fontSize="12px"
ml="4px"
overflow="hidden"
textOverflow="ellipsis"
whiteSpace="nowrap"
>
{title}
</Text>
{tabs && (
<Flex gap="2px" ml="auto">
{tabs}
</Flex>
)}
</Flex>
<Box overflowX="auto" px="22px" py="20px">
{children}
</Box>
</Box>
)
}

export function HighlightedCode({ html }: { html: string }) {
return <div dangerouslySetInnerHTML={{ __html: html }} />
}

export function StaticCodeBlock({
title,
html,
}: {
title: string
html: string
}) {
return (
<CodeWindow title={title}>
<HighlightedCode html={html} />
</CodeWindow>
)
}

export function HeroCodeWrapper({ children }: { children: ReactNode }) {
return (
<Flex justifyContent={[null, null, null, 'flex-end']} w="100%">
{children}
</Flex>
)
}
Loading
Loading