-
Notifications
You must be signed in to change notification settings - Fork 101
Fill out WIP TopNav, make it possible to preview with ?newnav #3335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -333,6 +333,7 @@ netstandard | |
| newcert | ||
| newguid | ||
| NEWID | ||
| newnav | ||
| Newtonsoft | ||
| nfsadmin | ||
| nlog | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| --- | ||
| import type { HTMLAttributes } from 'astro/types'; | ||
| import type { AvatarShape, AvatarSize } from '../lib/avatar'; | ||
| type SharedProps = { | ||
| size: AvatarSize; | ||
| shape: AvatarShape; | ||
| src?: string; | ||
| srcSet?: string; | ||
| alt?: string; | ||
| isMuted?: boolean; | ||
| title?: string; | ||
| }; | ||
| type Props = | ||
| | (HTMLAttributes<'div'> & SharedProps & { href?: never }) | ||
| | (HTMLAttributes<'a'> & SharedProps & { href: string | URL }); | ||
| const { | ||
| size, | ||
| shape, | ||
| src, | ||
| srcSet, | ||
| alt = '', | ||
| isMuted = false, | ||
| title, | ||
| href, | ||
| class: className, | ||
| ...rest | ||
| } = Astro.props satisfies Props; | ||
| const classes = `avatar avatar--${size} avatar--${shape}${isMuted ? ' avatar--muted' : ''}${className ? ` ${className}` : ''}`; | ||
| const Tag = href ? 'a' : 'div'; | ||
| --- | ||
|
|
||
| <Tag | ||
| class={classes} | ||
| title={title} | ||
| {...href ? { href } : {}} | ||
| {...rest} | ||
| data-avatar | ||
| data-avatar-size={size} | ||
| > | ||
| <span class="avatar__fallback" data-avatar-fallback><slot /></span> | ||
| <img | ||
| class="avatar__image" | ||
| src={src} | ||
| srcset={srcSet} | ||
| alt={alt} | ||
| data-avatar-image | ||
| hidden | ||
| /> | ||
| </Tag> | ||
|
|
||
| <script> | ||
| import '../scripts/avatar'; | ||
| </script> | ||
|
|
||
| <style> | ||
| .avatar { | ||
| position: relative; | ||
| display: flex; | ||
| flex-shrink: 0; | ||
| align-items: center; | ||
| justify-content: center; | ||
| overflow: hidden; | ||
| container-type: inline-size; | ||
| background: var(--colorAvatarBackgroundUserDefault); | ||
| color: var(--colorAvatarText); | ||
| font-weight: 400; | ||
| text-decoration: none; | ||
| text-transform: uppercase; | ||
| user-select: none; | ||
| transition: background-color 150ms ease-in-out; | ||
| } | ||
|
|
||
| .avatar[hidden] { | ||
| display: none; | ||
| } | ||
|
|
||
| .avatar--small { | ||
| width: 20px; | ||
| height: 20px; | ||
| } | ||
|
|
||
| .avatar--medium { | ||
| width: 36px; | ||
| height: 36px; | ||
| } | ||
|
|
||
| .avatar--large { | ||
| width: 48px; | ||
| height: 48px; | ||
| } | ||
|
|
||
| .avatar--circle { | ||
| border-radius: var(--borderRadiusCircle); | ||
| } | ||
|
|
||
| .avatar--rounded { | ||
| border-radius: var(--borderRadiusSmall); | ||
| } | ||
|
|
||
| .avatar--muted { | ||
| opacity: 0.4; | ||
| } | ||
|
|
||
| .avatar__fallback { | ||
| display: block; | ||
| margin: 0; | ||
| color: var(--colorAvatarText); | ||
| font-size: 44cqi; | ||
| } | ||
|
|
||
| .avatar__fallback[hidden] { | ||
| display: none; | ||
| } | ||
|
|
||
| .avatar__image { | ||
| width: 100%; | ||
| height: 100%; | ||
| aspect-ratio: 1 / 1; | ||
| background: var(--colorAvatarBackgroundImageDefault); | ||
| object-fit: scale-down; | ||
| transition: background-color 150ms ease-in-out; | ||
| } | ||
|
|
||
| a.avatar:hover, | ||
| a.avatar:focus-visible { | ||
| background: var(--colorAvatarBackgroundUserHover); | ||
| color: var(--colorAvatarText); | ||
| } | ||
|
|
||
| a.avatar:focus-visible { | ||
| outline: var(--borderWidth2) solid var(--colorBorderSelected); | ||
| outline-offset: var(--borderWidth2); | ||
| } | ||
|
|
||
| a.avatar:hover .avatar__image { | ||
| background: var(--colorAvatarBackgroundImageHover); | ||
| } | ||
| </style> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,25 @@ | ||
| --- | ||
| import Logo from '../assets/octopus-logo-v2.svg'; | ||
| import Avatar from './Avatar.astro'; | ||
| import Button from './Button.astro'; | ||
|
|
||
| type Props = { | ||
| active?: string; | ||
| links?: { label: string; href: string }[]; | ||
| }; | ||
|
|
||
| // TODO: Make these real links | ||
| const { | ||
| active = 'Docs', | ||
| links = [ | ||
| { label: 'Docs', href: '#' }, | ||
| { label: 'Learn', href: '#' }, | ||
| { label: 'API', href: '#' }, | ||
| { label: 'CLI', href: '#' }, | ||
| { label: 'Docs', href: '/docs' }, | ||
| { label: 'Learn', href: '#' }, // TODO: Make this a real link | ||
| { label: 'API', href: '/docs/octopus-rest-api' }, | ||
| { label: 'CLI', href: '/docs/octopus-rest-api/cli' }, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've assumed CLI means the CLI that talks to an Octopus Server instance over HTTP, not the CLI of the Octopus Server binary itself, which is only applicable to self-hosted |
||
| ], | ||
| } = Astro.props; | ||
| } = Astro.props satisfies Props; | ||
|
|
||
| const pathname = Astro.url.pathname.replace(/\/+$/, '') || '/'; | ||
| const currentLabel = links | ||
| .filter(({ href }) => pathname === href || pathname.startsWith(`${href}/`)) | ||
| .sort((a, b) => b.href.length - a.href.length)[0]?.label; | ||
| --- | ||
|
|
||
| <header class="top-nav"> | ||
|
|
@@ -34,10 +37,10 @@ const { | |
| <a | ||
| class:list={[ | ||
| 'top-nav__link', | ||
| label === active && 'top-nav__link--active', | ||
| label === currentLabel && 'top-nav__link--active', | ||
| ]} | ||
| href={href} | ||
| aria-current={label === active ? 'page' : undefined} | ||
| aria-current={label === currentLabel ? 'page' : undefined} | ||
| > | ||
| {label} | ||
| </a> | ||
|
|
@@ -46,11 +49,118 @@ const { | |
| </nav> | ||
| </div> | ||
| <div class="top-nav__trailing"> | ||
| <!-- All of these are just non-functional and for visual/presentation only at this stage --> | ||
| <Button icon="fa-regular fa-moon" aria-label="Switch to dark theme" /> | ||
| <!-- TODO: Make these real links --> | ||
| <!-- TODO: Fix the theme switcher icons --> | ||
| <Button | ||
| icon="fa-regular fa-moon" | ||
| aria-label="Dark mode" | ||
| aria-pressed="false" | ||
| data-theme-toggle-button | ||
| /> | ||
| <!-- TODO: Make this a real link --> | ||
| <Button label="Changelog" href="#" /> | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what this is supposed to point to just yet, I couldn't actually find release notes for non-self-hosted releases available anywhere |
||
| <Button label="Sign in" href="#" /> | ||
| <Button label="Start for free" href="#" importance="loud" /> | ||
| <Button | ||
| label="Sign in" | ||
| href="https://octopus.com/signin" | ||
| data-signed-out-only | ||
| /> | ||
| <Button | ||
| label="Start for free" | ||
| href="https://octopus.com/free-signup" | ||
| importance="loud" | ||
| data-signed-out-only | ||
| /> | ||
| <Avatar | ||
| size="medium" | ||
| shape="circle" | ||
| alt="" | ||
| data-signed-in-only | ||
| data-user-avatar | ||
| hidden | ||
| > | ||
| <span data-user-initials></span> | ||
| </Avatar> | ||
| </div> | ||
| </header> | ||
|
|
||
| <script> | ||
| import '../scripts/signed-in-user'; | ||
| import '../scripts/theme-switcher'; | ||
| </script> | ||
|
|
||
| <style> | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Made these scoped styles just like I recently did with |
||
| .top-nav { | ||
| box-sizing: border-box; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| gap: var(--space24); | ||
| padding: var(--space16) var(--space24) | ||
| calc(var(--space16) - var(--borderWidth1)); | ||
| border-block-end: var(--borderWidth1) solid var(--colorBorderPrimary); | ||
| background: var(--colorBackgroundPrimaryDefault); | ||
| } | ||
|
|
||
| .top-nav__leading, | ||
| .top-nav__trailing { | ||
| flex-shrink: 0; /* Disallow shrinking so button labels don't wrap across 2 lines */ | ||
| } | ||
|
|
||
| .top-nav__leading { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: var(--space64); | ||
| } | ||
|
|
||
| .top-nav__logo { | ||
| display: flex; | ||
| } | ||
|
|
||
| .top-nav__logo-mark { | ||
| display: block; | ||
| height: 2rem; | ||
| width: auto; | ||
| color: var(--colorTextPrimary); | ||
| } | ||
|
|
||
| .top-nav__links { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: var(--space2); | ||
| } | ||
|
|
||
| .top-nav__trailing { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: var(--space12); | ||
| } | ||
|
|
||
| a.top-nav__link { | ||
| box-sizing: border-box; | ||
| display: inline-flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| padding: var(--space8) var(--space12); | ||
| border-radius: var(--borderRadiusSmall); | ||
| background: var(--colorNavBackgroundRest); | ||
| color: var(--colorTextPrimary); | ||
| font: var(--textBodyRegularMedium); | ||
| text-align: center; | ||
| text-decoration: none; | ||
| } | ||
|
|
||
| a.top-nav__link:hover:not(.top-nav__link--active), | ||
| a.top-nav__link:focus:not(.top-nav__link--active) { | ||
| background: var(--colorNavBackgroundHover); | ||
| } | ||
|
|
||
| a.top-nav__link:focus-visible { | ||
| outline: var(--borderWidth2) solid var(--colorBorderSelected); | ||
| outline-offset: var(--borderWidth1); | ||
| } | ||
|
|
||
| a.top-nav__link--active { | ||
| background: var(--colorNavBackgroundActive); | ||
| color: var(--colorTextSelected); | ||
| font: var(--textBodyBoldMedium); | ||
| } | ||
| </style> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure just yet what this is supposed to point to, I think the others are good though