feat(pages): add macports to pages homepage - #873
Conversation
|
✅ OpenCodeReview: Review complete: 0 finding(s) across 5 selected item(s). |
|
Thanks for putting this together — the icon and the tab layout look clean, and I appreciate you testing it locally. That said, I'd rather not surface MacPorts on the homepage for now, for two reasons:
The install story we want to lead with is npm first, Homebrew second, and I'd like to keep the homepage down to just those two so the choice stays obvious for newcomers. Sorry to turn this one down after the work you put in — it's not a knock on the patch itself. If MacPorts users find their way to a port, that's great, we just don't want to be the ones promising to keep it current. |
|
@lizhengfeng101 I maintain the macports port for this, and the newest now avaliable is v1.9.2, I submitted a portfile for v1.9.3 |
|
Let me walk back my earlier comment — knowing you're the one maintaining the port changes my read on it, and I'd rather find MacPorts a home on the homepage than turn it away. Thanks for the patience while I thought it through. Here's the constraint I was dancing around. We're about to add an install-script channel — Three primary tabs stay flat, everything else moves behind More ⌄ — one extra click for the long tail, and the row stops growing every time we add a channel. MacPorts goes in the dropdown, which I think is the honest placement: discoverable and copy-pasteable, without claiming a slot next to npm. Would you be up for implementing the dropdown as part of this PR? If so, a few notes so you're not guessing at my preferences:
Don't feel obliged if this is more than you signed up for — say the word and I'll pick it up, and land your icon and channel entry on top. Either way the MacPorts entry is going in. And genuinely: thank you for maintaining the port, and I hope you'll keep it up. You having v1.9.3 submitted within a couple of days of the tag is a better answer to my "will it go stale" worry than anything I could have argued. We'll link to it from the install docs as well. |
|
That is quite thoughtful of you. I will get this done today. |
|
@lizhengfeng101 How is this: Screen.Recording.2026-08-14.at.3.00.28.PM.mp4 |
nice work! |
|
Nice — you got there faster than I expected, and pulling the shape into an First: I am not asking you to build keyboard navigation. I'm asking for less than what's there. I told you to add The right pattern here is a plain disclosure, which only requires <button
type="button"
- aria-haspopup="menu"
aria-expanded={menuOpen}
+ aria-controls="install-more-panel"
onClick={() => setMenuOpen((open) => !open)}
- <div role="menu" style={{ ... }}>
+ <div id="install-more-panel" style={{ ... }}>
- <button type="button" role="menuitem" onClick={...}>
+ <button type="button" onClick={...}>Second: the thing I flagged is a state bug, not a missing keyboard feature. The primary-tab - onClick={() => setActiveChannelKey(ch.key)}
+ onClick={() => { setActiveChannelKey(ch.key); setMenuOpen(false); }}With a mouse this already appears to work — but only because your document-level Adding that one line fixes the keyboard case and makes the mouse case intentional instead of lucky. Two smaller ones while you're in there:
Could you add tests for this?
I wrote these while checking the bug above, so they're yours — drop them in as // SPDX-License-Identifier: Apache-2.0
// Copyright 2026 alibaba/open-code-review Contributors
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';
import { LanguageProvider } from '../i18n';
import HeroSection from './HeroSection';
function renderHero() {
render(
<MemoryRouter>
<LanguageProvider>
<HeroSection />
</LanguageProvider>
</MemoryRouter>,
);
}
// The panel is found through the id that `aria-controls` already points at, so
// the test leans on the accessibility wiring instead of a test-only hook.
const panel = () => document.getElementById('install-more-panel');
const trigger = () => screen.getByRole('button', { name: /More|MacPorts/i });
describe('HeroSection install channels', () => {
it('starts on the first channel with the panel closed', () => {
renderHero();
expect(screen.getByText('npm i -g @alibaba-group/open-code-review')).toBeTruthy();
expect(panel()).toBeNull();
});
it('picking an overflow channel swaps the command and closes the panel', async () => {
const user = userEvent.setup();
renderHero();
await user.click(trigger());
expect(panel()).not.toBeNull();
await user.click(screen.getByRole('button', { name: /MacPorts/i }));
expect(screen.getByText('sudo port install open-code-review')).toBeTruthy();
expect(panel()).toBeNull();
});
it('closes when a primary tab is clicked', async () => {
const user = userEvent.setup();
renderHero();
await user.click(trigger());
await user.click(screen.getByRole('button', { name: /Homebrew/i }));
expect(screen.getByText('brew install open-code-review')).toBeTruthy();
expect(panel()).toBeNull();
});
// Keyboard activation dispatches `click` with no preceding `mousedown`, so
// this does not go through the same path as the test above.
it('closes when a primary tab is activated by keyboard', async () => {
const user = userEvent.setup();
renderHero();
await user.click(trigger());
screen.getByRole('button', { name: /Homebrew/i }).focus();
await user.keyboard('{Enter}');
expect(screen.getByText('brew install open-code-review')).toBeTruthy();
expect(panel()).toBeNull();
});
it('closes on Escape and on an outside click', async () => {
const user = userEvent.setup();
renderHero();
await user.click(trigger());
await user.keyboard('{Escape}');
expect(panel()).toBeNull();
await user.click(trigger());
await user.click(document.body);
expect(panel()).toBeNull();
});
it('reflects the selected overflow channel on the trigger', async () => {
const user = userEvent.setup();
renderHero();
expect(screen.getByRole('button', { name: /^More$/i })).toBeTruthy();
await user.click(trigger());
await user.click(screen.getByRole('button', { name: /MacPorts/i }));
const collapsed = screen.getByRole('button', { name: /MacPorts/i });
expect(collapsed.getAttribute('aria-expanded')).toBe('false');
expect(screen.queryByRole('button', { name: /^More$/i })).toBeNull();
});
});I ran these against your HEAD with the four fixes applied: Two notes on the tests so nothing surprises you:
Smaller polish, take or leave
Once the four fixes and the test file are in, this is good to merge from my side. Thanks for taking on more than you originally signed up for here. |
8d1446e to
cc3a882
Compare
Description
Add a macports icon and put macports installation method right next to homebrew as a tab.
Type of Change
How Has This Been Tested?
make testpasses locallyTested through
npm install && npm run devHere is what it look likes:
Checklist
go fmt,go vet)Related Issues
none yet