diff --git a/client/src/shared/ui/CartSnackbar.tsx b/client/src/shared/ui/CartSnackbar.tsx
new file mode 100644
index 0000000..f2eb5a4
--- /dev/null
+++ b/client/src/shared/ui/CartSnackbar.tsx
@@ -0,0 +1,46 @@
+import { useEffect } from 'react'
+import Alert from '@mui/material/Alert'
+import Button from '@mui/material/Button'
+import Snackbar from '@mui/material/Snackbar'
+import { useNavigate } from 'react-router-dom'
+import { useUnit } from 'effector-react'
+import { $cartSnackOpen, cartDismissed } from '@/shared/model/cart-notifications'
+
+export function CartSnackbar() {
+ const open = useUnit($cartSnackOpen)
+ const navigate = useNavigate()
+
+ useEffect(() => {
+ if (!open) return
+ const timer = setTimeout(() => cartDismissed(), 4000)
+ return () => clearTimeout(timer)
+ }, [open])
+
+ const handleClose = () => cartDismissed()
+
+ const handleGoToCart = () => {
+ cartDismissed()
+ navigate('/cart')
+ }
+
+ return (
+
+
+ Перейти в корзину
+
+ }
+ >
+ Товар добавлен в корзину
+
+
+ )
+}
diff --git a/client/src/shared/ui/__tests__/CartSnackbar.test.tsx b/client/src/shared/ui/__tests__/CartSnackbar.test.tsx
new file mode 100644
index 0000000..9b708d9
--- /dev/null
+++ b/client/src/shared/ui/__tests__/CartSnackbar.test.tsx
@@ -0,0 +1,55 @@
+import { render, screen, fireEvent, act } from '@testing-library/react'
+import { describe, it, expect, vi } from 'vitest'
+import { MemoryRouter } from 'react-router-dom'
+import { cartAdded, cartDismissed } from '@/shared/model/cart-notifications'
+import { CartSnackbar } from '@/shared/ui/CartSnackbar'
+
+function renderWithRouter() {
+ render(
+
+
+ ,
+ )
+}
+
+describe('CartSnackbar', () => {
+ it('is hidden when store is false', () => {
+ cartDismissed()
+ renderWithRouter()
+ expect(screen.queryByText(/товар добавлен/i)).not.toBeInTheDocument()
+ })
+
+ it('shows snackbar when cartAdded is fired', () => {
+ renderWithRouter()
+ cartAdded()
+ expect(screen.getByText(/товар добавлен/i)).toBeInTheDocument()
+ expect(screen.getByRole('button', { name: /перейти в корзину/i })).toBeInTheDocument()
+ })
+
+ it('closes on dismiss button click', () => {
+ renderWithRouter()
+ cartAdded()
+ const closeBtn = screen.getByLabelText(/закрыть/i)
+ fireEvent.click(closeBtn)
+ expect(screen.queryByText(/товар добавлен/i)).not.toBeInTheDocument()
+ })
+
+ it('auto-closes after 4 seconds', () => {
+ vi.useFakeTimers()
+ renderWithRouter()
+ cartAdded()
+ act(() => {
+ vi.advanceTimersByTime(4000)
+ })
+ expect(screen.queryByText(/товар добавлен/i)).not.toBeInTheDocument()
+ vi.useRealTimers()
+ })
+
+ it('navigates to /cart and closes on "Перейти в корзину" click', () => {
+ renderWithRouter()
+ cartAdded()
+ const goBtn = screen.getByRole('button', { name: /перейти в корзину/i })
+ fireEvent.click(goBtn)
+ expect(screen.queryByText(/товар добавлен/i)).not.toBeInTheDocument()
+ })
+})