diff --git a/apps/native/src/features/student/problem/components/floating-toolbar/PointingDrawingToolbar.tsx b/apps/native/src/features/student/problem/components/floating-toolbar/PointingDrawingToolbar.tsx
new file mode 100644
index 00000000..d23e8818
--- /dev/null
+++ b/apps/native/src/features/student/problem/components/floating-toolbar/PointingDrawingToolbar.tsx
@@ -0,0 +1,255 @@
+import { View } from 'react-native';
+import { GestureDetector } from 'react-native-gesture-handler';
+import Animated from 'react-native-reanimated';
+import { Undo2, Redo2 } from 'lucide-react-native';
+
+import { AnimatedPressable } from '@components/common';
+import { EraserFilledIcon, PencilFilledIcon } from '@components/system/icons';
+import { colors } from '@theme/tokens';
+
+import {
+ BUTTON_RADIUS,
+ BUTTON_SIZE,
+ COLLAPSED_RADIUS,
+ COLLAPSED_W,
+ COLOR_GRID_GAP,
+ COLOR_GRID_W,
+ ColorSwatch,
+ type Corner,
+ DIVIDER_WIDTH,
+ EXPANDED_RADIUS,
+ GAP,
+ ICON_SIZE,
+ PADDING,
+ SHADOW,
+ TOOLBAR_H,
+ ToolbarButton,
+ ToolbarDivider,
+} from './shared';
+import { useFloatingToolbarSnap } from './useFloatingToolbarSnap';
+
+export const POINTING_BRUSH_COLORS = ['#000000', '#FF0900', '#0004FF', '#1BB52A'] as const;
+
+const EXPANDED_W =
+ PADDING +
+ BUTTON_SIZE +
+ GAP +
+ BUTTON_SIZE +
+ GAP +
+ DIVIDER_WIDTH +
+ GAP +
+ BUTTON_SIZE +
+ GAP +
+ BUTTON_SIZE +
+ GAP +
+ DIVIDER_WIDTH +
+ GAP +
+ COLOR_GRID_W +
+ PADDING;
+
+interface PointingDrawingToolbarProps {
+ canUndo: boolean;
+ canRedo: boolean;
+ onUndo: () => void;
+ onRedo: () => void;
+ isEraserMode: boolean;
+ onPenModePress: () => void;
+ onEraserModePress: () => void;
+ collapsed: boolean;
+ onCollapsedChange: (collapsed: boolean) => void;
+ containerWidth: number;
+ containerHeight: number;
+ initialCorner?: Corner;
+ selectedBrushColor: string;
+ onSelectBrushColor: (color: string) => void;
+}
+
+export const PointingDrawingToolbar = ({
+ canUndo,
+ canRedo,
+ onUndo,
+ onRedo,
+ isEraserMode,
+ onPenModePress,
+ onEraserModePress,
+ collapsed,
+ onCollapsedChange,
+ containerWidth,
+ containerHeight,
+ initialCorner = 'bottom-right',
+ selectedBrushColor,
+ onSelectBrushColor,
+}: PointingDrawingToolbarProps) => {
+ const toolbarWidth = collapsed ? COLLAPSED_W : EXPANDED_W;
+ const { composedGesture, animatedStyle, ready } = useFloatingToolbarSnap({
+ containerWidth,
+ containerHeight,
+ toolbarWidth,
+ initialCorner,
+ });
+
+ return (
+
+
+ {collapsed ? (
+ onCollapsedChange(false)} />
+ ) : (
+
+ )}
+
+
+ );
+};
+
+const ExpandedToolbar = ({
+ canUndo,
+ canRedo,
+ onUndo,
+ onRedo,
+ isEraserMode,
+ onPenModePress,
+ onEraserModePress,
+ selectedBrushColor,
+ onSelectBrushColor,
+}: Pick<
+ PointingDrawingToolbarProps,
+ | 'canUndo'
+ | 'canRedo'
+ | 'onUndo'
+ | 'onRedo'
+ | 'isEraserMode'
+ | 'onPenModePress'
+ | 'onEraserModePress'
+ | 'selectedBrushColor'
+ | 'onSelectBrushColor'
+>) => (
+
+
+ }
+ isActive={canUndo}
+ />
+
+ }
+ isActive={canRedo}
+ />
+
+
+ }
+ isActive={!isEraserMode}
+ />
+
+ }
+ isActive={isEraserMode}
+ />
+
+
+ {POINTING_BRUSH_COLORS.map((c) => (
+ onSelectBrushColor(c)}
+ />
+ ))}
+
+
+);
+
+const CollapsedToolbar = ({
+ isEraserMode,
+ onPress,
+}: {
+ isEraserMode: boolean;
+ onPress: () => void;
+}) => (
+
+
+ {isEraserMode ? (
+
+ ) : (
+
+ )}
+
+
+);
diff --git a/apps/native/src/features/student/problem/components/floating-toolbar/index.ts b/apps/native/src/features/student/problem/components/floating-toolbar/index.ts
index fc4e8576..e0b6dabb 100644
--- a/apps/native/src/features/student/problem/components/floating-toolbar/index.ts
+++ b/apps/native/src/features/student/problem/components/floating-toolbar/index.ts
@@ -1 +1,2 @@
export { ProblemDrawingToolbar } from './ProblemDrawingToolbar';
+export { PointingDrawingToolbar, POINTING_BRUSH_COLORS } from './PointingDrawingToolbar';
diff --git a/apps/native/src/features/student/problem/screens/PointingScreen.tsx b/apps/native/src/features/student/problem/screens/PointingScreen.tsx
index c3e5b040..43d29217 100644
--- a/apps/native/src/features/student/problem/screens/PointingScreen.tsx
+++ b/apps/native/src/features/student/problem/screens/PointingScreen.tsx
@@ -1,7 +1,7 @@
-import { Alert, View } from 'react-native';
+import { Alert, type LayoutChangeEvent, StyleSheet, View } from 'react-native';
import { XIcon } from 'lucide-react-native';
import { type NativeStackScreenProps } from '@react-navigation/native-stack';
-import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { AnswerEventPayload } from '@repo/pointer-content-renderer';
import { useShallow } from 'zustand/react/shallow';
@@ -30,6 +30,11 @@ import {
toChatScenario,
toUserAnswers,
} from '../transforms/contentRendererTransforms';
+import { POINTING_BRUSH_COLORS, PointingDrawingToolbar } from '../components/floating-toolbar';
+import { DrawingCanvas, type DrawingCanvasRef } from '../../scrap/utils/skia';
+import { useDrawingState } from '../../scrap/hooks/useDrawingState';
+
+const CONTENT_MAX_WIDTH = 720;
const PointingScreen = ({
navigation,
@@ -158,6 +163,41 @@ const PointingScreen = ({
const { leftWidth, rightWidth } = useSplitPanelLayout();
+ const canvasRef = useRef(null);
+ const drawingState = useDrawingState();
+ const [toolbarCollapsed, setToolbarCollapsed] = useState(false);
+ const [toolbarArea, setToolbarArea] = useState({ width: 0, height: 0 });
+ const [brushColor, setBrushColor] = useState(POINTING_BRUSH_COLORS[0]);
+
+ const handleToolbarAreaLayout = useCallback(({ nativeEvent }: LayoutChangeEvent) => {
+ const { width, height } = nativeEvent.layout;
+ setToolbarArea((prev) =>
+ prev.width === width && prev.height === height ? prev : { width, height }
+ );
+ }, []);
+
+ const handlePenModePress = useCallback(() => {
+ drawingState.setPenMode();
+ }, [drawingState]);
+
+ const handleEraserModePress = useCallback(() => {
+ if (drawingState.isEraserMode) {
+ drawingState.setPenMode();
+ } else {
+ drawingState.setEraserMode();
+ }
+ }, [drawingState]);
+
+ const handleSelectBrushColor = useCallback(
+ (color: string) => {
+ setBrushColor(color);
+ if (drawingState.isEraserMode) {
+ drawingState.setPenMode();
+ }
+ },
+ [drawingState]
+ );
+
const redirectToHome = useCallback(() => {
resetSession();
navigation?.navigate('StudentTabs', { screen: 'Home' });
@@ -234,11 +274,47 @@ const PointingScreen = ({
badge={badgeStatus}
paddingHorizontal={0}
/>
-
+
+
+
+
+
+ setToolbarCollapsed(true)}
+ />
+
+
+
+
+ canvasRef.current?.undo()}
+ onRedo={() => canvasRef.current?.redo()}
+ isEraserMode={drawingState.isEraserMode}
+ onPenModePress={handlePenModePress}
+ onEraserModePress={handleEraserModePress}
+ collapsed={toolbarCollapsed}
+ onCollapsedChange={setToolbarCollapsed}
+ containerWidth={toolbarArea.width}
+ containerHeight={toolbarArea.height}
+ selectedBrushColor={brushColor}
+ onSelectBrushColor={handleSelectBrushColor}
+ />
+
+