Repository: storybookjs/storybook
File: code/core/src/manager/components/preview/tools/zoom.tsx (TypeScript)

Code before:
  return (
    <PopoverProvider
      padding="none"
      onVisibleChange={(isVisible) => {
        if (isVisible) {
          requestAnimationFrame(() => inputRef.current?.select());
        }
      }}
      popover={
        <>
          <ActionList>
            <ActionList.Item>
              <ZoomInput
                aria-label="Zoom percentage"
                ref={inputRef}
                unit="%"
                before={
                  <ActionList.Button size="small" padding="small" readOnly aria-hidden>
                    <ZoomIcon />
                  </ActionList.Button>
                }
                after={
                  <ActionList.Button
                    size="small"
                    padding="small"
                    hidden={value === INITIAL_ZOOM_LEVEL}
                    onClick={() => zoomTo(INITIAL_ZOOM_LEVEL)}
                    ariaLabel="Reset zoom"
                  >
                    <UndoIcon />
                  </ActionList.Button>
                }
                value={`${Math.round(value * 100)}%`}
                minValue={1}
                maxValue={800}
                setValue={(value: string) => {
                  const zoomLevel = parseInt(value, 10) / 100;
                  if (!Number.isNaN(zoomLevel)) {
                    zoomTo(zoomLevel);
                  }
                }}
              />
            </ActionList.Item>
          </ActionList>
          <ActionList>
            <ActionList.Item>
              <ActionList.Action
                onClick={zoomIn}
                ariaLabel="Zoom in"
                disabled={value >= ZOOM_LEVELS.at(-1)!}
              >

Review comment (suggestion):
To change the CSS of a component in our codebase, please use Emotion styled. By convention, we prefix styling props with a dollar to distinguish them from attributes:

```ts
import { styled } from 'storybook/theming'

const ZoomResetButton = styled(ActionList.Button)<{ $isInitialValue }>(
  ({ $isInitialValue }) => ({
    visibility: $isInitialValue ? 'hidden' : undefined
  })
);
```

And you can then use that button on line 84, by passing it the relevant props:

```ts
<ZoomResetButton
  size="small"
  padding="small"
  hidden={value === INITIAL_ZOOM_LEVEL}
  $isInitialValue={value === INITIAL_ZOOM_LEVEL}
  onClick={() => zoomTo(INITIAL_ZOOM_LEVEL)}
  ariaLabel="Reset zoom"
>
```

In particular, CodeRabbit shouted at you because you used a prop name (`hidden`) that matches a HTML attribute. This can lead to situations where the attribute is applied in the DOM even if you didn't want it to, so we prefer to keep names distinct.

Code after:
  zoomIn: () => void;
  zoomOut: () => void;
  zoomTo: (value: number) => void;
}>(function Zoom({ value, zoomIn, zoomOut, zoomTo }) {
  const inputRef = useRef<HTMLInputElement>(null);

  return (
    <PopoverProvider
      padding="none"
      onVisibleChange={(isVisible) => {
        if (isVisible) {
          requestAnimationFrame(() => inputRef.current?.select());
        }
      }}
      popover={
        <>
          <ActionList>
            <ActionList.Item>
              <ZoomInput
                aria-label="Zoom percentage"
                ref={inputRef}
                unit="%"
                before={
                  <ActionList.Button size="small" padding="small" readOnly aria-hidden>
                    <ZoomIcon />
                  </ActionList.Button>
                }
                after={
                  <ZoomResetButton
                    size="small"
                    padding="small"
                    $isInitialValue={value === INITIAL_ZOOM_LEVEL}
                    onClick={() => zoomTo(INITIAL_ZOOM_LEVEL)}
                    ariaLabel="Reset zoom"
                    aria-hidden={value === INITIAL_ZOOM_LEVEL}
                  >
                    <UndoIcon />
                  </ZoomResetButton>
                }
                value={`${Math.round(value * 100)}%`}
                minValue={1}
                maxValue={800}
                setValue={(value: string) => {
                  const zoomLevel = parseInt(value, 10) / 100;
                  if (!Number.isNaN(zoomLevel)) {
                    zoomTo(zoomLevel);
                  }
                }}
              />
            </ActionList.Item>
          </ActionList>