Detect dramatic increase in proportion among multiple classes I would like to use some tool to detect spike in one class's proportion.
Assume I received roughly the same percentage of red, blue and yellow candies throughout time. That means the absolute number can go up and down for each type of candy but the percentage for each candy will stay roughly the same. For example, it could be

*

*80 red (28%), 90 blue (32%), 110 yellow (39%)

*1 red (33%), 1 blue (33%), 1 yellow (33%)

And these are totally fine.
I want a tool to statistically detect when a particular percentage is larger than usual. For example, let's say one day i received 5 red (71%), 1 yellow and 1 blue. That will trigger the warning that the percentage for red is abnormal.
My gut instinct told me i should use Chi-square test to test one class vs. the rest of the classes. Is that correct?

So here (below) is a customizable tool (in R) that you can explore your problem with, and it is how I would think about the problem using a bottom-up approach.  You can re-run it a few times with the same settings to get a feel for what run-to-run differences look like and what your uncertainty in the estimate of the means might look like.
This link is to a paper on abrupt change detection and is how I like to think about detecting abrupt changes.
Code:
library(tidyverse)
library(matrixStats)

#parameters 
num_boots <- 3000
num_draws <- 10

#make original population 
pop <- sample(x = c("a", "b", "c"), #put your values here
              size=1000,            #total population
              prob=c(1,1,1)/3,      #sum to 1, frequencies of values
              replace = T)

#convert to factor (makes compute convenient)
pop <- as.factor(pop)

#get stats on it
summary(pop)

#prep for loop
log_store <- matrix(NA, num_boots, length(levels(pop))) %>% as.data.frame()

#bootstrapping
for(i in 1:num_boots){
  y <- sample(pop,num_draws)
  
  for(j in 1:length(levels(pop))){
  log_store[i,j] <- length(which(y==levels(pop)[j] ) ) 

  }
}

#make summaries in a useful form
df <- data.frame(labels = levels(pop),
                 sample_mean    = colMeans(log_store),
                 sample_std_dev = colSds(log_store %>% as.matrix()),
                 sample_max = colMaxs(log_store %>% as.matrix()),
                 sample_min = colMins(log_store %>% as.matrix()) )

#print it
print(tibble(df))

My output looks like this:

So what do I get from this?

*

*mean number per draw should have about the same proportions as in population

*one standard deviation is about 1.5 units so, if I use rules of thumb, about 67% of the time my values should be within 1.5 units of the mean, and about 99% of the my values should be within about 4.5 units of the mean.

To get the 80/90/110 you would change the code to
pop <- sample(x = c("red", "blue", "yellow"), #put your values here
              size=280,            #total population
              prob=c(80,90,110)/280,      #sum to 1, frequencies of values
              replace = T)

If you only draw 7 per day then adjust 'num_draws' to be 7 instead of ten.
The result from that would be this:

From this we see that most of the time we get 2-3 of each.  We would find it rather unlikely to get more than about 6 red candies.
