B122 — simplify: private button classes, drop bleed shell prop

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-08-02 17:57:40 +00:00
parent 8a64e330e6
commit 74c9c3a6e5
No known key found for this signature in database
5 changed files with 19 additions and 50 deletions

View file

@ -25,20 +25,21 @@ export type CampaignHomeActionButtonProps = {
href?: string
onClick?: () => void
disabled?: boolean
layout?: 'strip' | 'grid' | 'responsive'
layout?: 'strip' | 'responsive'
}
export const actionStripControlClassName =
'group box-content flex min-h-11 w-[5.5rem] shrink-0 snap-start flex-col items-center gap-2 rounded-md text-center outline-none focus-visible:ring-2 focus-visible:ring-ring active:opacity-90 disabled:pointer-events-none disabled:opacity-50'
const actionControlBaseClassName =
'group box-content flex min-h-11 flex-col items-center gap-2 rounded-md text-center outline-none focus-visible:ring-2 focus-visible:ring-ring active:opacity-90 disabled:pointer-events-none disabled:opacity-50'
export const actionGridControlClassName =
'group box-content flex min-h-11 w-full flex-col items-center gap-2 rounded-md text-center outline-none focus-visible:ring-2 focus-visible:ring-ring active:opacity-90 disabled:pointer-events-none disabled:opacity-50'
const actionStripControlClassName = cn(
actionControlBaseClassName,
'w-[5.5rem] shrink-0 snap-start',
)
export const actionResponsiveControlClassName =
'group box-content flex min-h-11 w-full flex-col items-center gap-2 rounded-md text-center outline-none focus-visible:ring-2 focus-visible:ring-ring active:opacity-90 disabled:pointer-events-none disabled:opacity-50 md:w-[5.5rem] md:shrink-0 md:snap-start'
/** @deprecated Use actionStripControlClassName or actionGridControlClassName */
export const actionControlClassName = actionStripControlClassName
const actionResponsiveControlClassName = cn(
actionControlBaseClassName,
'w-full md:w-[5.5rem] md:shrink-0 md:snap-start',
)
const circleClassName =
'flex size-14 items-center justify-center rounded-full bg-muted text-foreground transition-[transform,colors] duration-150 ease-out motion-reduce:transition-none pointer-fine:group-hover:scale-[1.05] pointer-coarse:group-data-[pressing=true]:scale-[1.05] motion-reduce:scale-100 group-hover:bg-muted/80 group-focus-visible:bg-muted/80'
@ -86,11 +87,7 @@ export const CampaignHomeActionButton = ({
})
const className = cn(
layout === 'grid'
? actionGridControlClassName
: layout === 'responsive'
? actionResponsiveControlClassName
: actionStripControlClassName,
layout === 'responsive' ? actionResponsiveControlClassName : actionStripControlClassName,
isInert && 'cursor-default',
)
const aria = {

View file

@ -71,7 +71,6 @@ export const CampaignHomeLayout = ({
retracted={focused}
slot="home-actions-chrome"
className="order-1 md:order-2"
allowHorizontalBleed
>
<div
data-slot="home-actions"

View file

@ -104,7 +104,7 @@ test.describe('Início — busca global (B47)', () => {
test.describe('Início — catálogo de ações (B45)', () => {
test.use({ viewport: { width: 390, height: 844 } })
test('staff sees all six home actions in the mobile grid without horizontal scroll', async ({
test('staff sees six home actions and can open municipalities without coverage', async ({
campaign,
page,
}) => {
@ -118,33 +118,14 @@ test.describe('Início — catálogo de ações (B45)', () => {
await expect(actionsRegion).toBeVisible()
for (const label of staffActionLabels) {
await expect(page.getByRole('link', { name: label, exact: true }).or(
page.getByRole('button', { name: label, exact: true }),
)).toBeVisible()
const link = page.getByRole('link', { name: label, exact: true })
const button = page.getByRole('button', { name: label, exact: true })
await expect(link.or(button)).toBeVisible()
}
const overflowX = await actionsRegion.evaluate((el) => getComputedStyle(el).overflowX)
expect(overflowX).not.toBe('auto')
expect(overflowX).not.toBe('scroll')
})
test('staff sees six home actions and can open municipalities without coverage', async ({
campaign,
page,
}) => {
const { fixtures } = campaign
const coordinator = await fixtures.createCampaignUser('coordinator', {
name: fixtures.value('Coordenadora Geral'),
})
await campaign.login(page, coordinator.email!, coordinator.password)
await expect(page.getByLabel('Ações rápidas')).toBeVisible()
for (const label of staffActionLabels) {
const link = page.getByRole('link', { name: label, exact: true })
const button = page.getByRole('button', { name: label, exact: true })
await expect(link.or(button)).toBeVisible()
}
await page.getByRole('link', { name: 'Ajustar votos', exact: true }).click()
await page.waitForURL(/\/campanha\/acoes\/atualizar-votos/)

View file

@ -4,7 +4,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import {
CampaignHomeActionButton,
actionControlClassName,
type CampaignHomeActionButtonProps,
} from '@/components/campaign/dashboard/CampaignHomeActionButton'
import {
@ -95,7 +94,8 @@ describe('CampaignHomeActionButton', () => {
const onClick = vi.fn()
renderActionButton({ label: 'Registrar', icon: BarChart3, onClick })
const control = screen.getByRole('button', { name: 'Registrar' })
expect(control.className).toBe(actionControlClassName)
expect(control.className).toContain('min-h-11')
expect(control.className).toContain('w-[5.5rem]')
})
it('opens the description drawer on long-press when the pointer is coarse', () => {

View file

@ -19,7 +19,7 @@ describe('CampaignHomeLayout', () => {
expect(actions?.closest('[data-slot="home-dock"]')).not.toBeNull()
})
it('keeps home-actions within page gutter on mobile (B122 grid)', () => {
it('does not bleed home-actions on mobile (B122 grid uses page gutter)', () => {
const { container } = render(<CampaignHomeLayout actions={<p>Actions block</p>} />)
const actions = container.querySelector('[data-slot="home-actions"]')
@ -28,14 +28,6 @@ describe('CampaignHomeLayout', () => {
expect(actions?.className).not.toMatch(/calc\(100%\+2rem\)/)
})
it('does not clip horizontal bleed on the actions retraction shell', () => {
const { container } = render(<CampaignHomeLayout actions={<p>Actions block</p>} />)
const actionsChrome = container.querySelector('[data-slot="home-actions-chrome"]')
const bleedWrapper = actionsChrome?.querySelector('[data-allow-horizontal-bleed="true"]')
expect(bleedWrapper).not.toBeNull()
})
it('renders search slot inside home-dock when provided', () => {
render(
<CampaignHomeLayout