Skip to content

Commit

Permalink
[Darkside] Internalheader CSS update (#3352)
Browse files Browse the repository at this point in the history
* ✨ Added darkmode support in react for internalheader

* :refactor: Support darkmode theming for internalheader

* 💄 Added bottom border to header, divider now subtleA

* 🐛 Remove hover,active effect in static title

* :refactor: Remove redundant :is for button

* :refactor: use padding shorthand

* 💄 Improved hover-effect on forced-color buttons, added story

* 🐛 Revert back to is button syntax
  • Loading branch information
KenAJoh authored Nov 21, 2024
1 parent 0da07be commit c8fd958
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 59 deletions.
94 changes: 45 additions & 49 deletions @navikt/core/css/darkside/internalheader.darkside.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
.navds-internalheader {
display: flex;
align-self: stretch;
background: var(--ac-internalheader-bg, var(--a-surface-inverted));
background: var(--ax-bg-raised);
min-height: 3rem;

--navds-internalheader-focus: inset 0 0 0 2px var(--a-border-focus-on-inverted);
border-bottom: 1px solid var(--ax-border-subtleA);
}

@media (forced-colors: active) {
Expand All @@ -13,52 +12,49 @@
border: solid 1px ButtonText;
color: ButtonText;
}

.navds-internalheader a:focus-visible {
box-shadow: none;
outline: 2px solid highlight;
outline-offset: 2px;
}

.navds-internalheader .navds-internalheader__button:focus-visible {
box-shadow: none;
outline: 2px solid highlight;
outline-offset: 2px;
}
}

.navds-internalheader__title {
border: none;
overflow: visible;
background: transparent;
font: inherit;
font-weight: var(--a-font-weight-bold);
font-weight: var(--ax-font-weight-bold);
line-height: normal;
text-align: left;
padding: 0 var(--a-spacing-5) 0 var(--a-spacing-6);
border-right: 1px solid var(--ac-internalheader-divider, var(--a-gray-600));
padding-block: 0;
padding-inline: var(--ax-spacing-6) var(--ax-spacing-5);
border-right: 1px solid var(--ax-border-subtleA);
display: flex;
align-items: center;
text-decoration: none;
margin: 0;
color: var(--ac-internalheader-text, var(--a-text-on-inverted));
}
color: var(--ax-text-default);

button.navds-internalheader__title {
cursor: pointer;
&:is(button) {
cursor: pointer;
}

&:hover {
background: var(--ax-bg-neutral-moderate-hover);
}

&:is(:hover, :active):not(button, a) {
background: initial;
}
}

.navds-internalheader__user {
padding: 0 var(--a-spacing-5);
border-left: 1px solid var(--ac-internalheader-divider, var(--a-gray-600));
padding: 0 var(--ax-spacing-5);
border-left: 1px solid var(--ax-border-subtleA);
display: flex;
align-items: center;
}

.navds-internalheader__button {
border: none;
margin: 0;
padding: 0 var(--a-spacing-3);
padding: 0 var(--ax-spacing-3);
overflow: visible;
background: transparent;
font: inherit;
Expand All @@ -68,38 +64,38 @@ button.navds-internalheader__title {
display: flex;
align-items: center;
justify-self: center;
gap: var(--a-spacing-2);
border-left: 1px solid var(--ac-internalheader-divider, var(--a-gray-600));
color: var(--ac-internalheader-text, var(--a-text-on-inverted));
}
gap: var(--ax-spacing-2);
border-left: 1px solid var(--ax-border-subtleA);
color: var(--ax-text-default);

a.navds-internalheader__title:hover,
button.navds-internalheader__title:hover,
.navds-internalheader__button:hover {
background-color: var(--ac-internalheader-hover-bg, var(--a-surface-inverted-hover));
&:hover {
background: var(--ax-bg-neutral-moderate-hover);
}
}

.navds-internalheader__title:focus-visible,
.navds-internalheader__button:focus-visible {
box-shadow: var(--navds-internalheader-focus);
outline: none;
@media (forced-colors: active) {
.navds-internalheader__button:hover {
background-color: highlighttext;
border-color: highlight;
color: highlight;
outline: 1px solid highlight;
isolation: isolate;
}
}

@supports not selector(:focus-visible) {
.navds-internalheader__title:focus,
.navds-internalheader__button:focus {
box-shadow: var(--navds-internalheader-focus);
outline: none;
.navds-internalheader__title,
.navds-internalheader__button {
&:focus-visible {
outline: 3px solid var(--ax-border-focus);
outline-offset: -3px;
}
}

a.navds-internalheader__title:active,
button.navds-internalheader__title:active,
.navds-internalheader__button:active {
background-color: var(--ac-internalheader-active-bg, var(--a-surface-inverted-active));
&:active {
background: var(--ax-bg-neutral-moderate-pressed);
}
}

.navds-internalheader__user-button {
padding-left: var(--a-spacing-5);
gap: var(--a-spacing-4);
padding-left: var(--ax-spacing-5);
gap: var(--ax-spacing-4);
}
36 changes: 28 additions & 8 deletions @navikt/core/react/src/internal-header/InternalHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import cl from "clsx";
import React, { HTMLAttributes, forwardRef } from "react";
import { UNSAFE_AkselTheme, UNSAFE_useAkselTheme } from "../provider";
import { OverridableComponent } from "../util/types";
import InternalHeaderButton, {
InternalHeaderButtonProps,
Expand Down Expand Up @@ -76,14 +77,33 @@ interface InternalHeaderComponent
* </InternalHeader>
* ```
*/
export const InternalHeader = forwardRef(({ className, ...rest }, ref) => (
<header
data-theme="dark"
{...rest}
ref={ref}
className={cl("navds-internalheader", className)}
/>
)) as InternalHeaderComponent;
export const InternalHeader = forwardRef(({ className, ...rest }, ref) => {
const themeContext = UNSAFE_useAkselTheme(false);

/*
* Component is always in "dark" mode, so we manually override global theme.
*/
if (themeContext) {
return (
<UNSAFE_AkselTheme theme="dark" asChild>
<header
{...rest}
ref={ref}
className={cl("navds-internalheader", className)}
/>
</UNSAFE_AkselTheme>
);
}

return (
<header
data-theme="dark"
{...rest}
ref={ref}
className={cl("navds-internalheader", className)}
/>
);
}) as InternalHeaderComponent;

InternalHeader.Title = InternalHeaderTitle;
InternalHeader.User = InternalHeaderUser;
Expand Down
32 changes: 32 additions & 0 deletions @navikt/core/react/src/internal-header/header.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,34 @@ export const UserWithMenuGridIconMenu = () => (
</InternalHeader>
);

export const UserButton = () => (
<InternalHeader style={{ width: 600 }}>
<InternalHeader.Title as="h1">Sykepenger</InternalHeader.Title>
<Spacer />
<Dropdown>
<InternalHeader.UserButton
as={Dropdown.Toggle}
name="Ola N."
description="Enhet: Skien"
/>
<Dropdown.Menu>
<dl>
<BodyShort as="dt" size="small">
Ola Normann
</BodyShort>
<Detail as="dd">D123456</Detail>
</dl>
<Dropdown.Menu.Divider />
<Dropdown.Menu.List>
<Dropdown.Menu.List.Item>
Logg ut <Spacer /> <LeaveIcon aria-hidden fontSize="1.5rem" />
</Dropdown.Menu.List.Item>
</Dropdown.Menu.List>
</Dropdown.Menu>
</Dropdown>
</InternalHeader>
);

export const Chromatic: Story = {
render: () => (
<VStack gap="4">
Expand Down Expand Up @@ -259,6 +287,10 @@ export const Chromatic: Story = {
<h2>UserWithMenuGridIconMenu</h2>
<UserWithMenuGridIconMenu />
</div>
<div>
<h2>UserButton</h2>
<UserButton />
</div>
</VStack>
),
parameters: {
Expand Down
10 changes: 8 additions & 2 deletions @navikt/core/react/src/provider/theme/AkselTheme.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import cl from "clsx";
import React, { forwardRef } from "react";
import { Slot } from "../../slot/Slot";
import { createContext } from "../../util/create-context";

type AkselThemeContext = {
Expand All @@ -17,6 +18,8 @@ type AkselThemeProps = {
children: React.ReactNode;
className?: string;
hasBackground?: boolean;
/* TODO: Handle this correctly with types */
asChild?: boolean;
} & AkselThemeContext;

const AkselTheme = forwardRef<HTMLDivElement, AkselThemeProps>(
Expand All @@ -26,6 +29,7 @@ const AkselTheme = forwardRef<HTMLDivElement, AkselThemeProps>(
const {
children,
className,
asChild = false,
theme = context?.theme ?? "light",
hasBackground: hasBackgroundProp = true,
} = props;
Expand All @@ -35,15 +39,17 @@ const AkselTheme = forwardRef<HTMLDivElement, AkselThemeProps>(
const hasBackground =
hasBackgroundProp ?? (isRoot || props.theme !== undefined);

const SlotElement = asChild ? Slot : "div";

return (
<ThemeProvider theme={theme}>
<div
<SlotElement
ref={ref}
className={cl("navds-theme", className, theme)}
data-background={hasBackground}
>
{children}
</div>
</SlotElement>
</ThemeProvider>
);
},
Expand Down

0 comments on commit c8fd958

Please sign in to comment.