Skip to content
Merged
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
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ Test files: `ComponentName.test.tsx`
## Coding Conventions

- **Indentation**: 2 spaces (Prettier, `useTabs: false`)
- **Comments**: do not add code comments unless strictly necessary β€” only to state a non-obvious constraint the code itself can't show. Never add comments that narrate what the next line does or why a change is correct.
- **Comments**: do not add code comments unless strictly necessary β€” only to state a non-obvious constraint the code itself can't show. Never add comments that narrate what the next line does or why a change is correct. Rationale for a change (why a selector moved, why a class is prefixed, what regression it fixes) belongs in the commit message or PR description, never in the source. Default to zero new comments; if you catch yourself explaining a decision, delete the comment and put it in the commit body. This applies to CSS and stylesheet files too.
- **Quotes**: single quotes
- **Line width**: 80 characters (Prettier default)
- **TypeScript**: strict mode (`strict`, `noUnusedLocals`, `noUnusedParameters`)
Expand Down
45 changes: 0 additions & 45 deletions lib/components/Sidebar/Sidebar.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,51 +64,6 @@ aside.konstruct-sidebar[data-mode='collapsed'] {
padding: 0 0.5rem;
}

.konstruct-sidebar li[role='option'] {
flex-shrink: 0;
}

/*
* Padding lives on the inner anchor (not the `<li>`) so the full
* hover/click area routes through the link β€” both navigation clicks and
* the Radix Tooltip trigger (in collapsed + expandOnHover mode) cover the
* whole option, not just the icon.
*/
.konstruct-sidebar li[role='option'] > a {
padding: 0.625rem;
}
.konstruct-sidebar[data-mode='expanded'] li[role='option'] > a {
padding: 0.625rem 1rem;
}

/*
* Hover / active styling driven by CSS custom properties. The properties
* are inherited from `.konstruct-sidebar` (or a closer ancestor) so the
* consumer can theme with a single inline `style` on the wrapper, which
* outranks any un-layered Tailwind utility shipped by federated remote
* micro-frontends.
*/
.konstruct-sidebar li[role='option']:hover {
background-color: var(--konstruct-sidebar-hover-bg, #252a41);
color: var(--konstruct-sidebar-hover-color, #fff);
}
.konstruct-sidebar li[role='option'][data-active='true'] {
background-color: var(--konstruct-sidebar-active-bg, #252a41);
color: var(--konstruct-sidebar-active-color, #fff);
}

.konstruct-sidebar li[role='option'] > a {
align-items: center;
color: inherit;
display: flex;
gap: 1rem;
text-decoration: none;
width: 100%;
}

/* Center icon-only content (option icons and Logo) in collapsed mode. */
.konstruct-sidebar[data-mode='collapsed'] li[role='option'],
.konstruct-sidebar[data-mode='collapsed'] li[role='option'] > a,
.konstruct-sidebar[data-mode='collapsed'] [data-konstruct-sidebar-logo] > a {
justify-content: center;
}
Expand Down
37 changes: 37 additions & 0 deletions lib/components/Sidebar/Sidebar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,43 @@ describe('Sidebar', () => {
expect(mockOnClick).toHaveBeenCalledTimes(1);
});

it('should let a consumer className override the default active and hover colors', async () => {
const { getLink } = setup({
options: (
<NavigationOption
isActive
className="hover:bg-metal-800 data-[active=true]:bg-metal-800"
>
<a href="/option-1">Option 1</a>
</NavigationOption>
),
});

const option = (await getLink(/option 1/i)).closest('li');

expect(option).toHaveClass('data-[active=true]:bg-metal-800');
expect(option).toHaveClass('hover:bg-metal-800');
expect(option).not.toHaveClass(
'data-[active=true]:bg-kubefirst-dark-blue-800',
);
expect(option).not.toHaveClass('hover:bg-kubefirst-dark-blue-800');
});

it('should apply the default active color when no override is passed', async () => {
const { getLink } = setup({
options: (
<NavigationOption isActive>
<a href="/option-1">Option 1</a>
</NavigationOption>
),
});

const option = (await getLink(/option 1/i)).closest('li');

expect(option).toHaveClass('data-[active=true]:bg-kubefirst-dark-blue-800');
expect(option).toHaveClass('hover:bg-kubefirst-dark-blue-800');
});

it("shouldn't have accessibility violations", async () => {
const { component } = setup({
options: (
Expand Down
6 changes: 3 additions & 3 deletions lib/components/Sidebar/Sidebar.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ export interface Props
* Inline styles applied to the wrapper `<aside>` (or the drawer panel in
* drawer mode). Useful for setting CSS custom properties that drive
* theming via the protection stylesheet (e.g.
* `--konstruct-sidebar-hover-bg`, `--konstruct-sidebar-active-bg`),
* since inline styles outrank un-layered utilities shipped by federated
* remote micro-frontends.
* `--konstruct-sidebar-logo-padding-expanded`), since inline styles
* outrank un-layered utilities shipped by federated remote
* micro-frontends.
*/
style?: CSSProperties;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ export const navigationOptionVariants = cva(
'cursor-pointer',
'flex',
'font-normal',
'font-normal',
'gap-4',
'rounded',
'shrink-0',
'group-data-[mode=collapsed]/sidebar:justify-center',
'group-data-[mode=collapsed]/sidebar:[&>a]:justify-center',
'text-black',
'w-full',
'text-kubefirst-dark-blue-300',
'hover:text-white',
Expand All @@ -40,7 +39,10 @@ export const navigationOptionVariants = cva(
compoundVariants: [
{
isActive: true,
class: ['text-white', 'bg-kubefirst-dark-blue-800'],
class: [
'data-[active=true]:text-white',
'data-[active=true]:bg-kubefirst-dark-blue-800',
],
},
],
},
Expand Down
Loading