diff --git a/internal/common/ui/events/commands.go b/internal/common/ui/events/commands.go
index 19857b4..ef82c2f 100644
--- a/internal/common/ui/events/commands.go
+++ b/internal/common/ui/events/commands.go
@@ -43,3 +43,8 @@ func Confirm(prompt string, onYes func() tea.Cmd) tea.Cmd {
 type MessageWithStatus interface {
 	StatusMessage() string
 }
+
+type MessageWithMode interface {
+	MessageWithStatus
+	ModeMessage() string
+}
diff --git a/internal/common/ui/events/errors.go b/internal/common/ui/events/errors.go
index 9688142..9aa3388 100644
--- a/internal/common/ui/events/errors.go
+++ b/internal/common/ui/events/errors.go
@@ -10,6 +10,9 @@ type ErrorMsg error
 // Message indicates that a message should be shown to the user
 type StatusMsg string
 
+// ModeMessage indicates that the mode should be changed to the following
+type ModeMessage string
+
 // PromptForInput indicates that the context is requesting a line of input
 type PromptForInputMsg struct {
 	Prompt string
diff --git a/internal/dynamo-browse/controllers/events.go b/internal/dynamo-browse/controllers/events.go
index a460f5d..c8a3713 100644
--- a/internal/dynamo-browse/controllers/events.go
+++ b/internal/dynamo-browse/controllers/events.go
@@ -1,18 +1,43 @@
 package controllers
 
 import (
+	"fmt"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/lmika/awstools/internal/dynamo-browse/models"
 )
 
 type NewResultSet struct {
 	ResultSet     *models.ResultSet
+	currentFilter string
+	filteredCount int
 	statusMessage string
 }
 
+func (rs NewResultSet) ModeMessage() string {
+	var modeLine string
+
+	if rs.ResultSet.Query != nil {
+		modeLine = rs.ResultSet.Query.String()
+	} else {
+		modeLine = "All results"
+	}
+
+	if rs.currentFilter != "" {
+		modeLine = fmt.Sprintf("%v - Filter: '%v'", modeLine, rs.currentFilter)
+	}
+	return modeLine
+}
+
 func (rs NewResultSet) StatusMessage() string {
-	//return fmt.Sprintf("%d items returned", len(rs.ResultSet.Items()))
-	return rs.statusMessage
+	if rs.statusMessage != "" {
+		return rs.statusMessage
+	}
+
+	if rs.currentFilter != "" {
+		return fmt.Sprintf("%d of %d items returned", rs.filteredCount, len(rs.ResultSet.Items()))
+	} else {
+		return fmt.Sprintf("%d items returned", len(rs.ResultSet.Items()))
+	}
 }
 
 type SetReadWrite struct {
diff --git a/internal/dynamo-browse/controllers/iface.go b/internal/dynamo-browse/controllers/iface.go
index fcd4af1..bf61064 100644
--- a/internal/dynamo-browse/controllers/iface.go
+++ b/internal/dynamo-browse/controllers/iface.go
@@ -10,5 +10,5 @@ type TableReadService interface {
 	Describe(ctx context.Context, table string) (*models.TableInfo, error)
 	Scan(ctx context.Context, tableInfo *models.TableInfo) (*models.ResultSet, error)
 	Filter(resultSet *models.ResultSet, filter string) *models.ResultSet
-	ScanOrQuery(ctx context.Context, tableInfo *models.TableInfo, queryExpr string) (*models.ResultSet, error)
+	ScanOrQuery(ctx context.Context, tableInfo *models.TableInfo, query models.Queryable) (*models.ResultSet, error)
 }
diff --git a/internal/dynamo-browse/controllers/state.go b/internal/dynamo-browse/controllers/state.go
index 3518e6b..f94893c 100644
--- a/internal/dynamo-browse/controllers/state.go
+++ b/internal/dynamo-browse/controllers/state.go
@@ -44,3 +44,19 @@ func (s *State) setResultSetAndFilter(resultSet *models.ResultSet, filter string
 	s.resultSet = resultSet
 	s.filter = filter
 }
+
+func (s *State) buildNewResultSetMessage(statusMessage string) NewResultSet {
+	s.mutex.Lock()
+	defer s.mutex.Unlock()
+
+	var filteredCount int = 0
+	if s.filter != "" {
+		for i := range s.resultSet.Items() {
+			if !s.resultSet.Hidden(i) {
+				filteredCount += 1
+			}
+		}
+	}
+
+	return NewResultSet{s.resultSet, s.filter, filteredCount, statusMessage}
+}
diff --git a/internal/dynamo-browse/controllers/tableread.go b/internal/dynamo-browse/controllers/tableread.go
index c07d208..92dbc33 100644
--- a/internal/dynamo-browse/controllers/tableread.go
+++ b/internal/dynamo-browse/controllers/tableread.go
@@ -3,10 +3,10 @@ package controllers
 import (
 	"context"
 	"encoding/csv"
-	"fmt"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/lmika/awstools/internal/common/ui/events"
 	"github.com/lmika/awstools/internal/dynamo-browse/models"
+	"github.com/lmika/awstools/internal/dynamo-browse/models/queryexpr"
 	"github.com/pkg/errors"
 	"os"
 	"sync"
@@ -81,12 +81,20 @@ func (c *TableReadController) PromptForQuery() tea.Cmd {
 			Prompt: "query: ",
 			OnDone: func(value string) tea.Cmd {
 				if value == "" {
-					return c.Rescan()
+					return func() tea.Msg {
+						resultSet := c.state.ResultSet()
+						return c.doScan(context.Background(), resultSet, nil)
+					}
+				}
+
+				expr, err := queryexpr.Parse(value)
+				if err != nil {
+					return events.SetError(err)
 				}
 
 				return func() tea.Msg {
 					resultSet := c.state.ResultSet()
-					newResultSet, err := c.tableService.ScanOrQuery(context.Background(), resultSet.TableInfo, value)
+					newResultSet, err := c.tableService.ScanOrQuery(context.Background(), resultSet.TableInfo, expr)
 					if err != nil {
 						return events.Error(err)
 					}
@@ -100,7 +108,8 @@ func (c *TableReadController) PromptForQuery() tea.Cmd {
 
 func (c *TableReadController) Rescan() tea.Cmd {
 	return func() tea.Msg {
-		return c.doScan(context.Background(), c.state.ResultSet())
+		resultSet := c.state.ResultSet()
+		return c.doScan(context.Background(), resultSet, resultSet.Query)
 	}
 }
 
@@ -139,8 +148,8 @@ func (c *TableReadController) ExportCSV(filename string) tea.Cmd {
 	}
 }
 
-func (c *TableReadController) doScan(ctx context.Context, resultSet *models.ResultSet) tea.Msg {
-	newResultSet, err := c.tableService.Scan(ctx, resultSet.TableInfo)
+func (c *TableReadController) doScan(ctx context.Context, resultSet *models.ResultSet, query models.Queryable) tea.Msg {
+	newResultSet, err := c.tableService.ScanOrQuery(ctx, resultSet.TableInfo, query)
 	if err != nil {
 		return events.Error(err)
 	}
@@ -152,21 +161,7 @@ func (c *TableReadController) doScan(ctx context.Context, resultSet *models.Resu
 
 func (c *TableReadController) setResultSetAndFilter(resultSet *models.ResultSet, filter string) tea.Msg {
 	c.state.setResultSetAndFilter(resultSet, filter)
-
-	var statusMessage string
-	if filter != "" {
-		var filteredCount int
-		for i := range resultSet.Items() {
-			if !resultSet.Hidden(i) {
-				filteredCount += 1
-			}
-		}
-		statusMessage = fmt.Sprintf("%d of %d items returned", filteredCount, len(resultSet.Items()))
-	} else {
-		statusMessage = fmt.Sprintf("%d items returned", len(resultSet.Items()))
-	}
-
-	return NewResultSet{resultSet, statusMessage}
+	return c.state.buildNewResultSetMessage("")
 }
 
 func (c *TableReadController) Unmark() tea.Cmd {
diff --git a/internal/dynamo-browse/controllers/tablewrite.go b/internal/dynamo-browse/controllers/tablewrite.go
index 60ea800..c155e80 100644
--- a/internal/dynamo-browse/controllers/tablewrite.go
+++ b/internal/dynamo-browse/controllers/tablewrite.go
@@ -61,7 +61,7 @@ func (twc *TableWriteController) NewItem() tea.Cmd {
 					Dirty: true,
 				})
 			})
-			return NewResultSet{twc.state.ResultSet(), "New item added"}
+			return twc.state.buildNewResultSetMessage("New item added")
 		}
 
 		return keyPrompts.next()
@@ -161,7 +161,7 @@ func (twc *TableWriteController) NoisyTouchItem(idx int) tea.Cmd {
 						return events.Error(err)
 					}
 
-					return twc.tableReadControllers.doScan(ctx, resultSet)
+					return twc.tableReadControllers.doScan(ctx, resultSet, resultSet.Query)
 				}
 			},
 		}
@@ -190,7 +190,7 @@ func (twc *TableWriteController) DeleteMarked() tea.Cmd {
 						return events.Error(err)
 					}
 
-					return twc.tableReadControllers.doScan(ctx, resultSet)
+					return twc.tableReadControllers.doScan(ctx, resultSet, resultSet.Query)
 				}
 			},
 		}
diff --git a/internal/dynamo-browse/models/models.go b/internal/dynamo-browse/models/models.go
index 40e4f31..0043691 100644
--- a/internal/dynamo-browse/models/models.go
+++ b/internal/dynamo-browse/models/models.go
@@ -2,11 +2,17 @@ package models
 
 type ResultSet struct {
 	TableInfo  *TableInfo
+	Query      Queryable
 	Columns    []string
 	items      []Item
 	attributes []ItemAttribute
 }
 
+type Queryable interface {
+	String() string
+	Plan(tableInfo *TableInfo) (*QueryExecutionPlan, error)
+}
+
 type ItemAttribute struct {
 	Marked bool
 	Hidden bool
diff --git a/internal/dynamo-browse/models/queryexpr/ast.go b/internal/dynamo-browse/models/queryexpr/ast.go
index 4750028..d8c9912 100644
--- a/internal/dynamo-browse/models/queryexpr/ast.go
+++ b/internal/dynamo-browse/models/queryexpr/ast.go
@@ -16,7 +16,7 @@ type astBinOp struct {
 }
 
 type astLiteralValue struct {
-	String string `parser:"@String"`
+	StringVal string `parser:"@String"`
 }
 
 var parser = participle.MustBuild(&astExpr{})
diff --git a/internal/dynamo-browse/models/queryexpr/astquery.go b/internal/dynamo-browse/models/queryexpr/calcquery.go
similarity index 100%
rename from internal/dynamo-browse/models/queryexpr/astquery.go
rename to internal/dynamo-browse/models/queryexpr/calcquery.go
diff --git a/internal/dynamo-browse/models/queryexpr/expr.go b/internal/dynamo-browse/models/queryexpr/expr.go
index 128e1df..2916c15 100644
--- a/internal/dynamo-browse/models/queryexpr/expr.go
+++ b/internal/dynamo-browse/models/queryexpr/expr.go
@@ -6,6 +6,10 @@ type QueryExpr struct {
 	ast *astExpr
 }
 
-func (md *QueryExpr) BuildQuery(tableInfo *models.TableInfo) (*models.QueryExecutionPlan, error) {
+func (md *QueryExpr) Plan(tableInfo *models.TableInfo) (*models.QueryExecutionPlan, error) {
 	return md.ast.calcQuery(tableInfo)
 }
+
+func (md *QueryExpr) String() string {
+	return md.ast.String()
+}
diff --git a/internal/dynamo-browse/models/queryexpr/tostr.go b/internal/dynamo-browse/models/queryexpr/tostr.go
new file mode 100644
index 0000000..9453954
--- /dev/null
+++ b/internal/dynamo-browse/models/queryexpr/tostr.go
@@ -0,0 +1,13 @@
+package queryexpr
+
+func (a *astExpr) String() string {
+	return a.Equality.String()
+}
+
+func (a *astBinOp) String() string {
+	return a.Name + a.Op + a.Value.String()
+}
+
+func (a *astLiteralValue) String() string {
+	return a.StringVal
+}
diff --git a/internal/dynamo-browse/models/queryexpr/values.go b/internal/dynamo-browse/models/queryexpr/values.go
index d6b3739..8bb0e81 100644
--- a/internal/dynamo-browse/models/queryexpr/values.go
+++ b/internal/dynamo-browse/models/queryexpr/values.go
@@ -8,7 +8,7 @@ import (
 )
 
 func (a *astLiteralValue) dynamoValue() (types.AttributeValue, error) {
-	s, err := strconv.Unquote(a.String)
+	s, err := strconv.Unquote(a.StringVal)
 	if err != nil {
 		return nil, errors.Wrap(err, "cannot unquote string")
 	}
@@ -16,7 +16,7 @@ func (a *astLiteralValue) dynamoValue() (types.AttributeValue, error) {
 }
 
 func (a *astLiteralValue) goValue() (any, error) {
-	s, err := strconv.Unquote(a.String)
+	s, err := strconv.Unquote(a.StringVal)
 	if err != nil {
 		return nil, errors.Wrap(err, "cannot unquote string")
 	}
diff --git a/internal/dynamo-browse/services/tables/service.go b/internal/dynamo-browse/services/tables/service.go
index d58aaad..50f02eb 100644
--- a/internal/dynamo-browse/services/tables/service.go
+++ b/internal/dynamo-browse/services/tables/service.go
@@ -3,7 +3,6 @@ package tables
 import (
 	"context"
 	"github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression"
-	"github.com/lmika/awstools/internal/dynamo-browse/models/queryexpr"
 	"sort"
 	"strings"
 
@@ -33,7 +32,23 @@ func (s *Service) Scan(ctx context.Context, tableInfo *models.TableInfo) (*model
 	return s.doScan(ctx, tableInfo, nil)
 }
 
-func (s *Service) doScan(ctx context.Context, tableInfo *models.TableInfo, filterExpr *expression.Expression) (*models.ResultSet, error) {
+func (s *Service) doScan(ctx context.Context, tableInfo *models.TableInfo, expr models.Queryable) (*models.ResultSet, error) {
+	var filterExpr *expression.Expression
+
+	if expr != nil {
+		plan, err := expr.Plan(tableInfo)
+		if err != nil {
+			return nil, err
+		}
+
+		// TEMP
+		if plan.CanQuery {
+			return nil, errors.Errorf("queries not yet supported")
+		}
+
+		filterExpr = &plan.Expression
+	}
+
 	results, err := s.provider.ScanItems(ctx, tableInfo.Name, filterExpr, 1000)
 	if err != nil {
 		return nil, errors.Wrapf(err, "unable to scan table %v", tableInfo.Name)
@@ -76,6 +91,7 @@ func (s *Service) doScan(ctx context.Context, tableInfo *models.TableInfo, filte
 
 	resultSet := &models.ResultSet{
 		TableInfo: tableInfo,
+		Query:     expr,
 		Columns:   columns,
 	}
 	resultSet.SetItems(results)
@@ -107,23 +123,8 @@ func (s *Service) Delete(ctx context.Context, tableInfo *models.TableInfo, items
 	return nil
 }
 
-func (s *Service) ScanOrQuery(ctx context.Context, tableInfo *models.TableInfo, queryExpr string) (*models.ResultSet, error) {
-	expr, err := queryexpr.Parse(queryExpr)
-	if err != nil {
-		return nil, err
-	}
-
-	plan, err := expr.BuildQuery(tableInfo)
-	if err != nil {
-		return nil, err
-	}
-
-	// TEMP
-	if plan.CanQuery {
-		return nil, errors.Errorf("queries not yet supported")
-	}
-
-	return s.doScan(ctx, tableInfo, &plan.Expression)
+func (s *Service) ScanOrQuery(ctx context.Context, tableInfo *models.TableInfo, expr models.Queryable) (*models.ResultSet, error) {
+	return s.doScan(ctx, tableInfo, expr)
 }
 
 // TODO: move into a new service
diff --git a/internal/dynamo-browse/ui/model.go b/internal/dynamo-browse/ui/model.go
index b04a327..e16ed4e 100644
--- a/internal/dynamo-browse/ui/model.go
+++ b/internal/dynamo-browse/ui/model.go
@@ -9,6 +9,7 @@ import (
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/dynamotableview"
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/layout"
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/statusandprompt"
+	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/styles"
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/tableselect"
 	"github.com/pkg/errors"
 )
@@ -25,10 +26,12 @@ type Model struct {
 }
 
 func NewModel(rc *controllers.TableReadController, wc *controllers.TableWriteController, cc *commandctrl.CommandController) Model {
-	dtv := dynamotableview.New()
-	div := dynamoitemview.New()
-	statusAndPrompt := statusandprompt.New(layout.NewVBox(layout.LastChildFixedAt(17), dtv, div), "")
-	tableSelect := tableselect.New(statusAndPrompt)
+	uiStyles := styles.DefaultStyles
+
+	dtv := dynamotableview.New(uiStyles)
+	div := dynamoitemview.New(uiStyles)
+	statusAndPrompt := statusandprompt.New(layout.NewVBox(layout.LastChildFixedAt(17), dtv, div), "", uiStyles.StatusAndPrompt)
+	tableSelect := tableselect.New(statusAndPrompt, uiStyles)
 
 	cc.AddCommands(&commandctrl.CommandContext{
 		Commands: map[string]commandctrl.Command{
diff --git a/internal/dynamo-browse/ui/teamodels/dynamoitemview/model.go b/internal/dynamo-browse/ui/teamodels/dynamoitemview/model.go
index bcc65cf..1ac4440 100644
--- a/internal/dynamo-browse/ui/teamodels/dynamoitemview/model.go
+++ b/internal/dynamo-browse/ui/teamodels/dynamoitemview/model.go
@@ -3,6 +3,7 @@ package dynamoitemview
 import (
 	"fmt"
 	"github.com/lmika/awstools/internal/dynamo-browse/models/itemrender"
+	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/styles"
 	"io"
 	"strings"
 	"text/tabwriter"
@@ -38,9 +39,9 @@ type Model struct {
 	selectedItem     models.Item
 }
 
-func New() *Model {
+func New(uiStyles styles.Styles) *Model {
 	return &Model{
-		frameTitle: frame.NewFrameTitle("Item", false, activeHeaderStyle),
+		frameTitle: frame.NewFrameTitle("Item", false, uiStyles.Frames),
 		viewport:   viewport.New(100, 100),
 	}
 }
diff --git a/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go b/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go
index fbdfdb4..1e9f187 100644
--- a/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go
+++ b/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go
@@ -9,6 +9,7 @@ import (
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/dynamoitemview"
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/frame"
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/layout"
+	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/styles"
 	table "github.com/lmika/go-bubble-table"
 )
 
@@ -54,12 +55,12 @@ func (cm columnModel) Header(index int) string {
 	return cm.m.resultSet.Columns[cm.m.colOffset+index]
 }
 
-func New() *Model {
+func New(uiStyles styles.Styles) *Model {
 	tbl := table.New(table.SimpleColumns([]string{"pk", "sk"}), 100, 100)
 	rows := make([]table.Row, 0)
 	tbl.SetRows(rows)
 
-	frameTitle := frame.NewFrameTitle("No table", true, activeHeaderStyle)
+	frameTitle := frame.NewFrameTitle("No table", true, uiStyles.Frames)
 
 	return &Model{
 		frameTitle: frameTitle,
diff --git a/internal/dynamo-browse/ui/teamodels/frame/frame.go b/internal/dynamo-browse/ui/teamodels/frame/frame.go
index 7ce9ba6..e2da798 100644
--- a/internal/dynamo-browse/ui/teamodels/frame/frame.go
+++ b/internal/dynamo-browse/ui/teamodels/frame/frame.go
@@ -15,14 +15,19 @@ var (
 
 // Frame is a frame that appears in the
 type FrameTitle struct {
-	header      string
-	active      bool
-	activeStyle lipgloss.Style
-	width       int
+	header string
+	active bool
+	style  Style
+	width  int
 }
 
-func NewFrameTitle(header string, active bool, activeStyle lipgloss.Style) FrameTitle {
-	return FrameTitle{header, active, activeStyle, 0}
+type Style struct {
+	ActiveTitle   lipgloss.Style
+	InactiveTitle lipgloss.Style
+}
+
+func NewFrameTitle(header string, active bool, style Style) FrameTitle {
+	return FrameTitle{header, active, style, 0}
 }
 
 func (f *FrameTitle) SetTitle(title string) {
@@ -42,9 +47,9 @@ func (f FrameTitle) HeaderHeight() int {
 }
 
 func (f FrameTitle) headerView() string {
-	style := inactiveHeaderStyle
+	style := f.style.InactiveTitle
 	if f.active {
-		style = f.activeStyle
+		style = f.style.ActiveTitle
 	}
 
 	titleText := f.header
diff --git a/internal/dynamo-browse/ui/teamodels/statusandprompt/model.go b/internal/dynamo-browse/ui/teamodels/statusandprompt/model.go
index 380896b..a290750 100644
--- a/internal/dynamo-browse/ui/teamodels/statusandprompt/model.go
+++ b/internal/dynamo-browse/ui/teamodels/statusandprompt/model.go
@@ -12,15 +12,21 @@ import (
 // event is received, focus will be torn away and the user will be given a prompt the enter text.
 type StatusAndPrompt struct {
 	model         layout.ResizingModel
+	style         Style
+	modeLine      string
 	statusMessage string
 	pendingInput  *events.PromptForInputMsg
 	textInput     textinput.Model
 	width         int
 }
 
-func New(model layout.ResizingModel, initialMsg string) *StatusAndPrompt {
+type Style struct {
+	ModeLine lipgloss.Style
+}
+
+func New(model layout.ResizingModel, initialMsg string, style Style) *StatusAndPrompt {
 	textInput := textinput.New()
-	return &StatusAndPrompt{model: model, statusMessage: initialMsg, textInput: textInput}
+	return &StatusAndPrompt{model: model, style: style, statusMessage: initialMsg, modeLine: "", textInput: textInput}
 }
 
 func (s *StatusAndPrompt) Init() tea.Cmd {
@@ -33,7 +39,12 @@ func (s *StatusAndPrompt) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		s.statusMessage = "Error: " + msg.Error()
 	case events.StatusMsg:
 		s.statusMessage = string(msg)
+	case events.ModeMessage:
+		s.modeLine = string(msg)
 	case events.MessageWithStatus:
+		if hasModeMessage, ok := msg.(events.MessageWithMode); ok {
+			s.modeLine = hasModeMessage.ModeMessage()
+		}
 		s.statusMessage = msg.StatusMessage()
 	case events.PromptForInputMsg:
 		if s.pendingInput != nil {
@@ -87,8 +98,14 @@ func (s *StatusAndPrompt) Resize(w, h int) layout.ResizingModel {
 }
 
 func (s *StatusAndPrompt) viewStatus() string {
+	modeLine := s.style.ModeLine.Render(lipgloss.PlaceHorizontal(s.width, lipgloss.Left, s.modeLine, lipgloss.WithWhitespaceChars(" ")))
+
+	var statusLine string
 	if s.pendingInput != nil {
-		return s.textInput.View()
+		statusLine = s.textInput.View()
+	} else {
+		statusLine = s.statusMessage
 	}
-	return s.statusMessage
+
+	return lipgloss.JoinVertical(lipgloss.Top, modeLine, statusLine)
 }
diff --git a/internal/dynamo-browse/ui/teamodels/styles/styles.go b/internal/dynamo-browse/ui/teamodels/styles/styles.go
new file mode 100644
index 0000000..10caf45
--- /dev/null
+++ b/internal/dynamo-browse/ui/teamodels/styles/styles.go
@@ -0,0 +1,29 @@
+package styles
+
+import (
+	"github.com/charmbracelet/lipgloss"
+	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/frame"
+	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/statusandprompt"
+)
+
+type Styles struct {
+	Frames          frame.Style
+	StatusAndPrompt statusandprompt.Style
+}
+
+var DefaultStyles = Styles{
+	Frames: frame.Style{
+		ActiveTitle: lipgloss.NewStyle().
+			Bold(true).
+			Foreground(lipgloss.Color("#ffffff")).
+			Background(lipgloss.Color("#4479ff")),
+		InactiveTitle: lipgloss.NewStyle().
+			Foreground(lipgloss.Color("#000000")).
+			Background(lipgloss.Color("#d1d1d1")),
+	},
+	StatusAndPrompt: statusandprompt.Style{
+		ModeLine: lipgloss.NewStyle().
+			Foreground(lipgloss.Color("#000000")).
+			Background(lipgloss.Color("#d1d1d1")),
+	},
+}
diff --git a/internal/dynamo-browse/ui/teamodels/tableselect/model.go b/internal/dynamo-browse/ui/teamodels/tableselect/model.go
index 1feebe7..8f06a97 100644
--- a/internal/dynamo-browse/ui/teamodels/tableselect/model.go
+++ b/internal/dynamo-browse/ui/teamodels/tableselect/model.go
@@ -7,6 +7,7 @@ import (
 	"github.com/lmika/awstools/internal/dynamo-browse/controllers"
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/frame"
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/layout"
+	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/styles"
 	"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/utils"
 )
 
@@ -26,8 +27,8 @@ type Model struct {
 	w, h             int
 }
 
-func New(submodel tea.Model) *Model {
-	frameTitle := frame.NewFrameTitle("Select table", false, activeHeaderStyle)
+func New(submodel tea.Model, uiStyles styles.Styles) *Model {
+	frameTitle := frame.NewFrameTitle("Select table", false, uiStyles.Frames)
 	return &Model{frameTitle: frameTitle, submodel: submodel}
 }